;****** Auto-Revision Header (do not edit) *******************************
;*
;* © Copyright by PetiWare
;*
;* Filename         : MakePatch.asm
;* Created on       : 16-Jan-93
;* Created by       : Peter Simons
;* Current revision : V0.017
;*
;*
;* Purpose: Erstellt aus einem Quell- und Zielfile einen Patch, mit dem
;*          man das Original zur Zielversion modifizieren kann.
;*
;*
;* V0.017 : Fehler in GeneratePatch() gefunden, der auftrat wenn das neue
;*          File kürzer war, als das Original!
;*
;* V0.016 : PatchHeader verbessert: CRCs und Filelängen werden mit ab-
;*          gespeichert!
;*
;* V0.015 : Speicherreservierungen von PUBLIC auf ANY umgestellt, sodaß
;*          sie auch mit Virtual Memory funktionieren.
;*
;* V0.014 : Wenn das Patchfile erstellt ist, wird der ProgressIndikator
;*          gelöscht.
;*
;* V0.013 : Wird kein Patchname angegeben, wird an den Namen des
;*          "NewVersion"-Files der String ".ptch" angehängt.
;*
;* V0.012 : MakePatch gibt jetzt eine (C)-Meldung und den Status aus,
;*          bevor der Patch erstellt wird.
;*
;* V0.011 : Reservierungen umgestellt auf AllocRemember()
;*
;* V0.010 : Die Erstellung des Patchfiles läßt sich über CTRL/C ab-
;*          brechen.
;*
;* V0.009 : Einfacher ProgressIndikator hinzugefügt
;*
;* V0.008 : Filelänge wird mit abgespeichert.
;*
;* V0.007 : GeneratePatchData() fast völlig umgeschrieben.
;*
;* V0.006 : Neuer Chunk: DT_INSERTED
;*
;* V0.005 : Chunknamen in die richtige Vergangenheitsform umbenannt:
;*          SKIP --> SKIPPED
;*
;* V0.004 : Die Patchdaten sind in Chunks aufgebaut: DT_ORIGINAL,
;*          DT_PATCHED, DT_SKIP, DT_NOMOREDATA
;*
;* V0.003 : GeneratePatchData() erkennt folgende Fälle sehr zuverlässig:
;*          Daten eingefügt, Daten herausgenommen und Daten einfach über-
;*          schrieben.
;*
;* V0.002 : Find(), FindFirstDifference() und Compare() hinzugefügt
;*
;* V0.001 : Die in der Kommandozeile angegebenen Files werden geladen
;*          und die benötigten Puffer reserviert.
;*
;* V0.000 : --- Initial release ---
;*
;*************************************************************************
;
;
;

;***************************************************************************
;*                                                                         *
;* SEKTION: Labels, Macros, Switches, Structures                           *
;*                                                                         *
;***************************************************************************

;-------------------------------------- Switches -----------
                MC68000
                NEWSYNTAX
                EXEOBJ
                OBJFILE "RAM:MakePatch"
                DEBUG on
                SYM
                MULTIPASS
;               VERBOSEOPTIM

;-------------------------------------- Structures --------
PatchChunk      CLRSO
pc_DataType     SO.w    1
pc_ChunkLen     SO.l    1
pc_ChunkData    SOVAL
pc_SIZEOF       SOVAL

gp_Struct       CLRFO
gp_Patch        fo.l    1
gp_Target       fo.l    1
gp_Original     fo.l    1
gp_PatchLen     fo.l    1
gp_TargetLen    fo.l    1
gp_OriginalLen  fo.l    1
gp_SIZEOF       FOVAL

;-------------------------------------- Labels ------------
                MACLIB  "DATAS:Includes.preass"
                MACLIB  "DATAS:Offsets.preass"
                INCLUDE "A:Sources/PetiToolLibrary/PToolLibrary.i"

KICKVERSION     equ     37
SEARCHLENGTH    equ     (2*pc_SIZEOF)+4

;-------------------------------------- Datatypes ---------
DT_NOMOREDATA   equ     0
DT_ORIGINAL     equ     1
DT_PATCHED      equ     2
DT_SKIPPED      equ     3
DT_INSERTED     equ     4

;-------------------------------------- Macros ------------
REVISION        MACRO
                dc.b "0.017"
                ENDM
REVDATE         MACRO
                dc.b "11-Feb-93"
                ENDM
PUSHM           MACRO
saveregs        setrl   \1
                movem.l saveregs,-(SP)
                ENDM
POPM            MACRO
                movem.l (SP)+,saveregs
                ENDM


;***************************************************************************
;*                                                                         *
;* SEKTION: Programm                                                       *
;*                                                                         *
;***************************************************************************

;---------------------- Systemumgebung initialisieren ---------------------
START:          lea     (DATA_Seg,PC),a5
                BASEREG a5,DATA_Seg

                lea     (ptoollibname,PC),a1
                moveq   #1,d0
                move.l  ($4).W,a6
                jsr     (_LVOOpenLibrary,a6)
                move.l  d0,(_PToolBase)
                bne.b   .PToolLibOkay
                bsr     _NoPToolLibrary
                bra     .Exit
.PToolLibOkay   move.l  d0,a6
                move.l  (ptl_DOSBase,a6),(_DOSBase)
                move.l  (ptl_IntuitionBase,a6),(_IntuitionBase)

                move.l  #CCF_OS_VERSION,d0
                move.w  #KICKVERSION,d1
                jsr     (_LVOCheckConfig,a6)
                tst.l   d0
                beq.b   .ConfigOkay
                lea     (PrgName,PC),a0
                moveq   #0,d2
                jsr     (_LVODisplayConfigErrorDos,a6)
                bra     .ClosePToolLib
.ConfigOkay
;------------------------------ Argument-Parsing --------------------------
                lea     (RDArgsTemplate,PC),a0
                move.l  a0,d1
                lea     (_Original,PC),a0
                move.l  a0,d2
                moveq   #0,d3
                move.l  (_DOSBase,PC),a6
                jsr     (_LVOReadArgs,a6)
                move.l  d0,(_RDArgsStruct)
                bne.b   .RDArgsOkay
                moveq   #0,d0
                moveq   #0,d1
                lea     (PrgName,PC),a0
                move.l  (_PToolBase,PC),a6
                jsr     (_LVOErrorHandleDos,a6)
                bra     .ClosePToolLib

.RDArgsOkay     tst.l   (_PatchFile)
                bne.b   .PatchNameOkay
                move.l  (_NewVersion,PC),a0
                bsr     _Len
                addq.l  #5,d0
                move.l  #MEMF_ANY,d1
                lea     (_RememberKey,PC),a0
                move.l  (_IntuitionBase,PC),a6
                jsr     (_LVOAllocRemember,a6)
                move.l  d0,(_PatchFile)
                move.l  (_NewVersion,PC),a0
                move.l  d0,a1
...             move.b  (a0)+,(a1)+
                bne.b   ...
                subq.w  #1,a1
                move.b  #'.',(a1)+
                move.b  #'p',(a1)+
                move.b  #'t',(a1)+
                move.b  #'c',(a1)+
                move.b  #'h',(a1)+
                clr.b   (a1)+
.PatchNameOkay
;------------------------------ Status ausgeben ---------------------------
                move.l  (_PatchFile,PC),-(SP)
                move.l  (_NewVersion,PC),-(SP)
                move.l  (_Original,PC),-(SP)
                pea     (PrgName,PC)
                lea     (Status,PC),a0
                move.l  SP,a1
                move.l  (_PToolBase,PC),a6
                jsr     (_LVOPrintFSimple,a6)
                add.w   #4*4,SP

;----------------------------- Puffer reservieren -------------------------
                move.l  (_Original,PC),a0
                jsr     (_LVOLoadFile,a6)
                move.l  d0,(_SourceBuffer)
                bne.b   .SourceOkay
                moveq   #1,d0
                move.l  (_Original,PC),-(SP)
                move.l  SP,a1
                bsr     _ErrorHandle
                addq.w  #4,SP
                bra     .FreeRDArgs

.SourceOkay     move.l  (_NewVersion,PC),a0
                jsr     (_LVOLoadFile,a6)
                move.l  d0,(_TargetBuffer)
                bne.b   .TargetOkay
                moveq   #1,d0
                move.l  (_NewVersion,PC),-(SP)
                move.l  SP,a1
                bsr     _ErrorHandle
                addq.w  #4,SP
                bra     .FreeSourceBuffer

.TargetOkay     move.l  (_TargetBuffer,PC),a0
                move.l  (a0),d2
                move.l  d2,d0
                move.l  #MEMF_ANY,d1
                lea     (_RememberKey,PC),a0
                move.l  (_IntuitionBase,PC),a6
                jsr     (_LVOAllocRemember,a6)
                move.l  d0,(_PatchBuffer)
                bne.b   .PatchOkay
                moveq   #2,d0
                pea     (AnyMemStr,PC)
                move.l  d2,-(SP)
                move.l  SP,a1
                bsr     _ErrorHandle
                addq.w  #8,SP
                bra     .FreeTargetBuffer
.PatchOkay
;------------------------------ Patch erstellen ---------------------------
                move.l  (_SourceBuffer,PC),a0
                move.l  (a0)+,d0
                move.l  (_TargetBuffer,PC),a1
                move.l  (a1)+,d1
                move.l  (_PatchBuffer,PC),a2
                move.l  d1,d2
                bsr     _GeneratePatchData
                bsr     _ClearLine
                cmp.l   #-1,d0
                bne.b   .NoBreak
                bsr     _BreakError
                bra     .FreeBuffers
.NoBreak        move.l  d0,d6
                bne.b   .SavePatchData
                moveq   #11,d0
                pea     (PatchTooLong,PC)
                move.l  SP,a1
                bsr     _ErrorHandle
                addq.w  #4,SP
                bra     .FreeBuffers

;----------------------------- ZielPuffer speichern -----------------------
.SavePatchData  move.l  (_PatchFile,PC),d1
                move.l  #MODE_NEWFILE,d2
                move.l  (_DOSBase,PC),a6
                jsr     (_LVOOpen,a6)
                ERRORHANDLE d5,0,(.FreeBuffers,PC)

                move.l  (_TargetBuffer,PC),a0
                move.l  (a0)+,d0
                move.l  (_PToolBase,PC),a6
                jsr     (_LVOCRC16Buffer,a6)
                move.w  d0,-(SP)                ; OriginalCRC
                move.l  (_SourceBuffer,PC),a0
                move.l  (a0)+,d0
                jsr     (_LVOCRC16Buffer,a6)
                move.w  d0,-(SP)                ; PatchedCRC
                move.l  (_TargetBuffer,PC),a0
                move.l  (a0),-(SP)              ; PatchedLength

                move.l  d5,d1
                move.l  SP,d2
                moveq   #8,d3
                move.l  (_DOSBase,PC),a6
                jsr     (_LVOWrite,a6)          ; Header speichern
                add.w   #8,SP
                cmp.l   #-1,d0
                beq.b   .SaveError

                move.l  d5,d1
                move.l  (_PatchBuffer,PC),d2
                move.l  d6,d3
                move.l  (_PToolBase,PC),a6
                jsr     (_LVOSaveBreak,a6)
                cmp.l   #-1,d0
                bne.b   .CloseDestFile
                move.l  (_DOSBase,PC),a6
                jsr     (_LVOIoErr,a6)
                tst.l   d0
                bne.b   .SaveError
                bsr     _BreakError
.SaveError      moveq   #11,d0
                pea     (SaveError,PC)
                move.l  SP,a1
                bsr     _ErrorHandle
                addq.w  #4,SP

.CloseDestFile  move.l  d5,d1
                move.l  (_DOSBase,PC),a6
                jsr     (_LVOClose,a6)

;-------------------------- Systemumgebung freigeben ----------------------
.FreeBuffers    lea     (_RememberKey,PC),a0
                moveq   #-1,d0
                move.l  (_IntuitionBase,PC),a6
                jsr     (_LVOFreeRemember,a6)

.FreeTargetBuffer:
                move.l  (_TargetBuffer,PC),a1
                move.l  ($4).w,a6
                jsr     (_LVOFreeVec,a6)

.FreeSourceBuffer:
                move.l  (_SourceBuffer,PC),a1
                move.l  ($4).w,a6
                jsr     (_LVOFreeVec,a6)

.FreeRDArgs     move.l  (_RDArgsStruct,PC),d1
                beq.b   .ClosePToolLib
                move.l  (_DOSBase,PC),a6
                jsr     (_LVOFreeArgs,a6)

.ClosePToolLib  move.l  (_PToolBase,PC),a1
                move.l  ($4).W,a6
                jsr     (_LVOCloseLibrary,a6)

.Exit           moveq   #0,d0
                rts

;***************************************************************************
;*                                                                         *
;* SEKTION: Unterroutinen                                                  *
;*                                                                         *
;***************************************************************************

;-------------------------------- Patchgeneration -------------------------
_GeneratePatchData:
                ; Erstellt das Patchfile, mit dem aus dem Originalfile
                ; das Zielfile erstellt werden kann.
                ;
                ; Parameter: A0=&Original A1=&Target A2=&PatchBuffer
                ;            D0=&OriginalLen D1=&Targetlen D2=&PatchBufsize
                ; Result   : D0=PatchLength
                ; Kommentar: Wenn als Patchlength eine Null zurückgegeben
                ;            wird, waere der Patch länger geworden, als das
                ;            komplett neue File!!
                ;            Bei einer -1L trat ein Break auf!

                PUSHM   d2-d7/a2-a3/a6
                moveq   #0,d6                   ; PatchLenCounter
                moveq   #0,d7
                subq.l  #1,d2                   ; Pufferlänge sicherheits-
                link.w  a4,#gp_SIZEOF           ; halber kleiner annehmen
                movem.l d0-d2/a0-a2,(gp_OriginalLen,a4)

.FindDiffLoop   move.l  (gp_Original,a4),a0
                move.l  (gp_OriginalLen,a4),d0
                move.l  (gp_Target,a4),a1
                move.l  (gp_TargetLen,a4),d1
                bsr     _FindFirstDifference
                cmp.l   #-1,d0
                beq     .NoMoreDiffs

                tst.l   d0
                beq.b   .NoOriginalData
                bsr     _WriteOriginalChunk
                cmp.l   #-1,d0
                beq     .exit

.NoOriginalData cmp.l   #SEARCHLENGTH,(gp_TargetLen,a4)
                bmi     .WriteRestInserted
                move.l  (gp_Original,a4),a2
                move.l  (gp_OriginalLen,a4),d2
                sub.l   #SEARCHLENGTH,d2
                moveq   #-1,d3

.ScanLoop       move.l  d2,d0
                bsr     _ShowProgress
                tst.l   d0
                beq.b   .NoBreak
                moveq   #-1,d7
                bra     .exit          ; CTRL/C???

.NoBreak        subq.l  #1,d2
                beq     .WriteRestInserted
                addq.l  #1,d3
                lea     (a2,d3.l),a1
                move.l  (gp_Target,a4),a0
                move.l  (gp_TargetLen,a4),d0
                moveq   #SEARCHLENGTH,d1
                bsr     _Find
                cmp.l   #-1,d0
                beq.b   .ScanLoop
                tst.l   d0
                beq.b   .WriteSkipChunk

                bsr     _WriteInsertedChunk
                cmp.l   #-1,d0
                beq     .exit

.WriteSkipChunk move.l  d3,d0
                beq     .FindDiffLoop
                bsr     _WriteSkippedChunk
                cmp.l   #-1,d0
                bne     .FindDiffLoop
                bra     .exit

.NoMoreDiffs    move.l  (gp_OriginalLen,a4),d0
                move.l  (gp_TargetLen,a4),d1
                cmp.l   d0,d1
                bpl.b   .SizeOkay
                move.l  d1,d0
.SizeOkay       bsr     _WriteOriginalChunk
                cmp.l   #-1,d0
                beq     .exit
.WriteRestInserted:
                move.l  (gp_TargetLen,a4),d0
                bsr     _WriteInsertedChunk
                cmp.l   #-1,d0
                beq     .exit

.finished       subq.l  #pc_SIZEOF,(gp_PatchLen,a4)
                bmi.b   .exit
                move.l  (gp_Patch,a4),a0
                move.w  #DT_NOMOREDATA,(a0)+
                clr.l   (a0)+
                addq.l  #pc_SIZEOF,d6

                move.l  d6,d7

.exit           move.l  d7,d0
                unlk    a4
                POPM
                rts



_WriteOriginalChunk:
                tst.l   d0
                beq.b   .exit
                subq.l  #pc_SIZEOF,(gp_PatchLen,a4)
                bmi.b   .ErrorExit
                move.l  (gp_Patch,a4),a0
                move.w  #DT_ORIGINAL,(a0)+
                move.l  d0,(a0)+
                move.l  a0,(gp_Patch,a4)
                add.l   d0,(gp_Original,a4)
                sub.l   d0,(gp_OriginalLen,a4)
                add.l   d0,(gp_Target,a4)
                sub.l   d0,(gp_TargetLen,a4)
                add.l   #pc_SIZEOF,d6
.exit           rts
.ErrorExit      moveq   #-1,d0
                bra.b   .exit


_WriteInsertedChunk:
                tst.l   d0
                beq.b   .exit
                subq.l  #pc_SIZEOF,(gp_PatchLen,a4)
                sub.l   d0,(gp_PatchLen,a4)
                bmi.b   .ErrorExit
                move.l  (gp_Target,a4),a0
                move.l  (gp_Patch,a4),a1
                move.w  #DT_INSERTED,(a1)+
                move.l  d0,(a1)+
                bsr     _CopyChunk
                move.l  a0,(gp_Target,a4)
                sub.l   d0,(gp_TargetLen,a4)
                btst.l  #0,d0
                beq.b   .NoOddLength
                subq.l  #1,(gp_PatchLen,a4)
                bmi     .exit
                clr.b   (a1)+
                addq.l  #1,d6
.NoOddLength    move.l  a1,(gp_Patch,a4)
                addq.l  #pc_SIZEOF,d6
                add.l   d0,d6
.exit           rts
.ErrorExit      moveq   #-1,d0
                bra.b   .exit

_WriteSkippedChunk:
                tst.l   d0
                beq.b   .exit
                subq.l  #pc_SIZEOF,(gp_PatchLen,a4)
                bmi.b   .ErrorExit
                move.l  (gp_Patch,a4),a0
                move.w  #DT_SKIPPED,(a0)+
                move.l  d0,(a0)+
                move.l  a0,(gp_Patch,a4)
                addq.l  #pc_SIZEOF,d6
                add.l   d0,(gp_Original,a4)
                sub.l   d0,(gp_OriginalLen,a4)
.exit           rts
.ErrorExit      moveq   #-1,d0
                bra.b   .exit

_WritePatchedChunk:
                tst.l   d0
                beq.b   .exit
                bsr     _WriteInsertedChunk
                cmp.l   #-1,d0
                beq.b   .exit
                bra     _WriteSkippedChunk
.exit           rts


_CopyChunk      move.l  d0,-(SP)
                beq.b   .exit
...             move.b  (a0)+,(a1)+
                subq.l  #1,d0
                bne.b   ...
.exit           move.l  (SP)+,d0
                rts


;---------------------------------- Diverses ------------------------------
_Len:
                ; Funktion : Bestimmt die Länge eines mit Null
                ;            abgeschlossenen Textes
                ;
                ; Parameter: A0=&Textpuffer
                ; Result   : D0=Länge *INKLUSIVE* des Nullbytes
                ; Kommentar: Verändert keine Register ausser D0!!!

                pea     (a0)            ; Register retten
.loop           tst.b   (a0)+
                bne.b   .loop           ; aktuelles Zeichen gleich Null?
                move.l  a0,d0
                move.l  (SP)+,a0
                sub.l   a0,d0           ; Länge zurückgeben
                rts

_ClearLine:
                ; Löscht die aktuelle Zeile (ProgressIndikator entfernen!)
                ;
                ;
                ; Parameter: keine
                ; Result   : keine

                PUSHM   d0-d1/a0-a1
                lea     (ClrLine,PC),a0
                move.l  (_PToolBase,PC),a6
                jsr     (_LVOPrintFSimple,a6)
                POPM
                rts

_ShowProgress:
                ; Gibt in die aktuelle Zeile den ProgressIndikator aus und
                ; testet auf CTRL+C.
                ;
                ; Parameter: D0=Bytes to go
                ; Result   : D0=SignalMask

                PUSHM   d1/a0-a1/a6

                and.l   #$FFFFFFF0,d0
                cmp.l   (.last,PC),d0
                beq.b   .DetectBreak

                lea     (Progress,PC),a0
                move.l  d0,-(SP)
                move.l  SP,a1
                move.l  (_PToolBase,PC),a6
                jsr     (_LVOPrintFSimple,a6)
                addq.w  #4,SP

.DetectBreak    move.l  #SIGBREAKF_CTRL_C,d1
                move.l  (_DOSBase,PC),a6
                jsr     (_LVOCheckSignal,a6)

                POPM
                rts

.last           ds.l    1

;----------------------------- Suchen und Vergleichen ---------------------
_FindFirstDifference:
                ; Findet das erste Byte, das im Zielpuffer anders ist, als
                ; im Quellpuffer.
                ;
                ; Parameter: A0=&Original A1=&Target
                ;            D0=&OriginalLen D1=&Targetlen
                ; Result   : D0=Offset im Quellpuffer
                ; Kommentar: Ein Rückgabewert von -1L bedeutet, das kein
                ;            Unterschied mehr gefunden werden konnte, bevor
                ;            ein Puffer zu Ende war.

                PUSHM   d1/a0-a1
                tst.l   d0
                beq.b   .ErrorExit
                tst.l   d1
                beq.b   .ErrorExit

...             cmp.b   (a0)+,(a1)+
                bne.b   .FoundDiff
                subq.l  #1,d0
                beq.b   .ErrorExit
                subq.l  #1,d1
                beq.b   .ErrorExit
                bra.b   ...

.FoundDiff      move.l  a0,d0
                movem.l (SP),saveregs
                sub.l   a0,d0
                subq.l  #1,d0

.exit           POPM
                rts

.ErrorExit      moveq   #-1,d0
                bra.b   .exit


_Find:
                ; Sucht eine Bytefolge in einem Puffer
                ;
                ; Parameter: A0=&Puffer A1=&String D0=Pufferlength
                ;            D1=StringLänge
                ; Result   : D0=Offset im Puffer oder -1L

                PUSHM   d1-d4/a0-a3
                move.l  a0,a3
                moveq   #0,d4                   ; ReturnCode
                move.l  d0,d2
                beq.b   .Exit
                move.l  d1,d3
                beq.b   .Exit
                sub.l   d1,d2
                bmi.b   .Exit
                beq.b   .SameLength
                addq.l  #1,d2

                moveq   #0,d0
                moveq   #0,d1
                move.b  (a1),d1

.FindFirstByte  move.b  (a0),d0
                cmp.b   d0,d1
                beq.b   .ByteFound
.NotTheSame     addq.w  #1,a0
                subq.l  #1,d2
                beq.b   .Exit
                bra.b   .FindFirstByte
.ByteFound      move.l  d3,d0
                bsr     _Compare
                tst.l   d0
                beq.b   .NotTheSame
                move.l  d0,d4

.Exit           moveq   #-1,d0
                tst.l   d4
                beq.b   .NotFound
                move.l  a0,d0
                sub.l   a3,d0
.NotFound       POPM
                rts

.SameLength     move.l  d1,d0
                bsr     _Compare
                move.l  d0,d4
                bra.b   .Exit



_Compare:
                ; Funktion : Vergleicht zwei Bytefolgen
                ;
                ; Parameter: A0=&String1 A1=&String2 D0=Länge des kürzeren
                ; Result   : D0=Gleich (-1) oder verschieden (0)

                PUSHM   d1-d2/a0-a1
                move.l  d0,d2
                subq.l  #1,d2
                moveq   #0,d0
                moveq   #0,d1
.loop           move.b  (a0)+,d0
                move.b  (a1)+,d1                ; compare them
                cmp.b   d0,d1
                dbne    d2,.loop
                move.w  d2,d0
                bmi.s   .same
                moveq   #0,d0
.same           ext.l   d0
.exit           POPM
                rts

;-------------------------------- Fehlerhandhabung ------------------------
_BreakError:
                ; Gibt den "Received CTRL/C"-String aus
                ;
                ; Parameter: keine
                ; Result   : keins

                PUSHM   d0-d1/a0-a1/a6
                lea     (PrgName,PC),a0
                moveq   #0,d1
                moveq   #5,d0
                move.l  (_PToolBase,PC),a6
                jsr     (_LVOErrorHandleDos,a6)
                POPM
                rts

_ErrorHandle:
                ; Erzeut über ErrorHandleIntuition() die Fehlermeldung.
                ;
                ; Parameter: A1=&DataFlow D0=Errornumber
                ; Result   : keins

                PUSHM   d0-d1/a0-a2/a6
                lea     (PrgName,PC),a0
                sub.l   a2,a2
                move.l  (_PToolBase,PC),a6
                jsr     (_LVOErrorHandleIntuition,a6)
                POPM
                rts


_NoPToolLibrary:
                ; Gibt einen Fehler aus, falls die PTool.Library nicht ge-
                ; öffnet werden konnte.
                ;
                ; Parameter: keine
                ; Result   : keins

                lea     (dosname,PC),a1
                move.l  ($4).W,a6
                jsr     (_LVOOldOpenLibrary,a6)
                tst.l   d0
                beq.b   .exit
                move.l  d0,a6
                jsr     (_LVOOutput,a6)
                move.l  d0,d1
                beq.b   .CloseDosLib
                lea     (PrgName,PC),a0
                move.l  a0,d2
                moveq   #NoPToolError_len,d3
                jsr     (_LVOWrite,a6)
.CloseDosLib    move.l  a6,a1
                move.l  ($4).W,a6
                jsr     (_LVOCloseLibrary,a6)
.exit           rts



;***************************************************************************
;*                                                                         *
;* SEKTION: Daten                                                          *
;*                                                                         *
;***************************************************************************
DATA_Seg:
                dc.b    "$VER: "
PrgName         dc.b    "MakePatch v"
                REVISION
                dc.b    " ("
                REVDATE
                dc.b    ")"
                dc.b    0
                dc.b    " requires the PTool.Library!!",$0A,$0A
NoPToolError_len equ (*-PrgName)

ptoollibname    CSTR    "ptool.library"
dosname         CSTR    "dos.library"
AnyMemStr       CSTR    "RAM"
RDArgsTemplate  CSTR    "Original/A,NewVersion/A,PatchFile"
PatchTooLong    CSTR    "Sorry, but the patch would have been longer, than the new-version!"
SaveError       CSTR    "File couldn't be saved succesfully!"
Progress        CSTR    $0D,"Progress: %8.lu byte to go..."
ClrLine         CSTR    $9B,$4D,$0D

Status          dc.b    $9B,"1;33",$6D,"%s",$9B,$6D," - coding by Peter Simons",$0A
                dc.b    "old version-file: %s",$0A
                dc.b    "new version-file: %s",$0A
                dc.b    "      patch-file: %s",$0A
                dc.b    0

                CNOP    0,4
_PToolBase      ds.l    1
_DOSBase        ds.l    1
_IntuitionBase  ds.l    1
_RememberKey    ds.l    1
_RDArgsStruct   ds.l    1
_SourceBuffer   ds.l    1
_TargetBuffer   ds.l    1
_PatchBuffer    ds.l    1

_Original       ds.l    1                       ; Array für ReadArgs()
_NewVersion     ds.l    1
_PatchFile      ds.l    1

                END
