
;    ญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญ
;    ญญ                                                              ญญ
;    ญญ                Patch Maker  V1.0  (Jan. 1990)                ญญ
;    ญญ                                                              ญญ
;    ญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญ
;    ญญ                                                              ญญ
;    ญญ               Author: Roger Fischlin                         ญญ
;    ญญ                       Steigerwaldweg 6                       ญญ
;    ญญ                       D-6450 Hanau 7                         ญญ
;    ญญ                       West Germany                           ญญ
;    ญญ                                                              ญญ
;    ญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญ
;    ญญ                                                              ญญ
;    ญญ Patch Maker is public domain software - so feel free to copy ญญ
;    ญญ                         it.                                  ญญ
;    ญญ                                                              ญญ
;    ญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญ
;    ญญ                                                              ญญ
;    ญญ              Assembler : DevPac Assembler V2.1               ญญ
;    ญญ              Linker    : Blink                               ญญ
;    ญญ                                                              ญญ
;    ญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญ




	incdir   	":include/"

	include	libraries/dos_lib.i
	include	libraries/dos.i
	include	exec/exec.i
	include	exec/exec_lib.i

	include	misc/easystart.i

OpenThem	clr.l	Differences
	move.l	d0,d6
	lea	dosname(pc),a1		; open Dos.library
	moveq.l	#0,d0
	CALLEXEC 	OpenLibrary
	move.l	d0,_DOSBase
	beq	NoDos

	tst.l	returnMsg		; get output handle
	beq	CLI
	move.l	#ConWindow,d1
	move.l	#MODE_NEWFILE,d2	; started from Workbench
	CALLDOS	Open		; so we must open an own window
	tst.l	d0
	beq	CloseDos	
	move.l	d0,OutputHandle
	bra.s	MakePatch
CLI	CALLDOS	Output		; started from CLI
	move.l	d0,OutputHandle
	
	cmp.l	#1,d6		; "?" ?
	beq.s	MakePatch
	move.l	OutputHandle,d1	; write info text
	move.l	#InfoText,d2
	move.l	#Info_Length,d3
	CALLDOS	Write
	bra	CloseCon
		


MakePatch	move.l	OutputHandle,d1	; write headline
	move.l	#Headline,d2
	move.l	#HL_Length,d3
	CALLDOS	Write
	

	move.l	OutputHandle,d1	; ask user
	move.l	#Text1,d2
	move.l	#57-32,d3
	CALLDOS	Write
	move.l	OutputHandle,d1	; get first file name
	move.l	#Buffer1,d2
	move.l	#256,d3
	CALLDOS	Read
	cmp.l	#1,d0		; user just pressed return
	beq	CloseCon
	lea.l	Buffer1,a0
	clr.b	-1(a0,d0)

	move.l	OutputHandle,d1	; ask user
	move.l	#Text2,d2
	move.l	#57-32,d3
	CALLDOS	Write
	move.l	OutputHandle,d1	; get first file name
	move.l	#Buffer2,d2
	move.l	#256,d3
	CALLDOS	Read
	cmp.l	#1,d0		; user just pressed return
	beq	CloseCon
	lea.l	Buffer2,a0
	clr.b	-1(a0,d0)
	
	move.l	OutputHandle,d1	; ask user
	move.l	#Text3,d2
	move.l	#57-32,d3
	CALLDOS	Write
	move.l	OutputHandle,d1	; get first file name
	move.l	#PatchName,d2
	move.l	#256,d3
	CALLDOS	Read
	cmp.l	#1,d0		; user just pressed return
	beq	CloseCon
	lea.l	PatchName,a0
	clr.b	-1(a0,d0)


	move.l	#Buffer1,d1		; open files
	move.l	#MODE_OLDFILE,d2
	CALLDOS	Open
	tst.l	d0
	beq	Open1Error
	move.l	d0,FileHandle1
	move.l	#Buffer2,d1
	move.l	#MODE_OLDFILE,d2
	CALLDOS	Open
	tst.l	d0
	beq	Open2Error
	move.l	d0,FileHandle2
	move.l	#PatchName,d1
	move.l	#MODE_NEWFILE,d2
	CALLDOS	Open
	tst.l	d0
	beq	Open3Error
	move.l	d0,FileHandle3

	move.l	#Buffer1,d1		; get lock for file size
	moveq.l	#-2,d2
	CALLDOS	Lock
	move.l	d0,d5
	beq	ReadError
	move.l	d0,d1
	move.l	#FIB,d2	
	CALLDOS	Examine
	move.l	d0,d6
	move.l	d5,d1
	CALLDOS	UnLock
	tst.l	d6
	beq	ReadError
	move.l	FIB+fib_Size,d4	; file 1 size

	move.l	#Buffer2,d1		; get lock for file size
	moveq.l	#-2,d2
	CALLDOS	Lock
	move.l	d0,d5
	beq	ReadError
	move.l	d0,d1
	move.l	#FIB,d2	
	CALLDOS	Examine
	move.l	d0,d6
	move.l	d5,d1
	CALLDOS	UnLock
	tst.l	d6
	beq	ReadError
	cmp.l	FIB+fib_Size,d4	; comapre file sizes
	bne	DifferentSizes

	move.l	OutputHandle,d1	; write $a
	move.l	#ReturnText,d2
	moveq.l	#1,d3
	CALLDOS	Write
	move.l	#-4*1024,Offset	; clear offset

	
NextBlock	jsr	UserBreak
	add.l	#4*1024,Offset
	jsr	PrintCurrentPos
	move.l	FileHandle1,d1		; read block (4 KB)
	move.l	#Buffer1,d2
	move.l	#4*1024,d3
	CALLDOS	Read
	tst.l	d0
	bmi	ReadError		; error !	
	tst.l	d0
	beq	End		; reached end of file 
	move.l	d0,d5
	move.l	FileHandle2,d1		; read block (4 KB)
	move.l	#Buffer2,d2
	move.l	#4*1024,d3
	CALLDOS	Read
	cmp.l	d0,d5
	bne	ReadError		; same number of bytes ??
	add.l	#Buffer1,d5
	move.l	d5,BufferSize

	lea.l	Buffer1,a4		; make patch by comparing both buffers
	lea.l	Buffer2,a5
Compare1	cmpm.b	(a4)+,(a5)+		; same byte ?
	beq	NoDifference
	move.l	a4,d0
	subq.l	#1,d0
	sub.l	#Buffer1,d0
	add.l	Offset,d0		; get offset
	lea.l	OffsetText+1,a0
	jsr	MakeHex
	move.l	FileHandle3,d1
	move.l	#OffsetText,d2
	move.l	#42-32,d3
	CALLDOS	Write		; write offset to patch
	cmp.l	#42-32,d0
	bne	ReadError
	lea.l	-1(a4),a4
	lea.l	-1(a5),a5
	moveq.l	#0,d7		; up to 16 bytes per row

Compare2	cmpm.b	(a4)+,(a5)+		
	beq	NoMoreDiff
	addq.l	#1,d7
	add.l	#1,Differences
	move.b	-1(a5),d0
	jsr	MakeByte
	move.l	FileHandle3,d1
	move.l	#ByteText,d2
	moveq.l	#3,d3
	CALLDOS	Write		; write byte to patch
	cmp.l	#3,d0
	bne	ReadError
	move.l	a4,d0
	cmp.b	#16,d7		; already 16 bytes ?
	beq	NoMoreDiff		
	cmp.l	BufferSize,d0		; reached end of buffer ?
	bne	Compare2	
	bra	NextBlock
NoMoreDiff	move.l	FileHandle3,d1		; write $a to patch
	move.l	#ReturnText,d2
	moveq.l	#1,d3
	CALLDOS	Write
	cmp.l	#1,d0
	bne	ReadError

NoDifference	move.l	a4,d0
	cmp.l	BufferSize,d0		; reached end of buffer ?
	bne	Compare1	
	bra	NextBlock

End	lea.l	PatchText+54-38+2,a0	; write patch size
	move.l	Differences,d0
	bsr	MakeHex
	move.l	OutputHandle,d1	
	move.l	#PatchText,d2
	move.l	#67-38+3,d3
	CALLDOS	Write

CloseFile3	move.l	FileHandle3,d1		; close files
	CALLDOS	Close
CloseFile2	move.l	FileHandle2,d1
	CALLDOS	Close
CloseFile1	move.l	FileHandle1,d1
	CALLDOS	Close

	move.l	OutputHandle,d1	; print out some nice words
	move.l	#GoodByeText,d2
	move.l	#52-35+3,d3
	CALLDOS	Write
	
CloseCon	tst.l	returnMsg
	beq	CloseDos
	move.l	OutputHandle,d1	; wait  until user presses RETURN
	move.l	#ConText,d2
	move.l	#60-35+1,d3
	CALLDOS	Write
	move.l	OutputHandle,d1	
	move.l	#Buffer1,d2
	moveq.l	#1,d3
	CALLDOS	Read
	
	move.l	OutputHandle,d1	; close window if started from WB
	CALLDOS	Close

CloseDos	move.l	_DOSBase,a1		; close dos.library
	CALLEXEC	CloseLibrary

NoDos	moveq.l	#0,d0
	rts

*
* error routines - print error text
*

DifferentSizes	move.l	OutputHandle,d1	
	move.l	#DiffSizesText,d2
	move.l	#57-35+2,d3
	CALLDOS	Write
	bra	CloseFile3
Open1Error	move.l	OutputHandle,d1	
	move.l	#Open1ErrorText,d2
	move.l	#67-35+3,d3
	CALLDOS	Write
	bra	CloseDos
Open2Error	move.l	OutputHandle,d1	
	move.l	#Open2ErrorText,d2
	move.l	#67-35+3,d3
	CALLDOS	Write
	bra	CloseFile1
Open3Error	move.l	OutputHandle,d1	
	move.l	#Open3ErrorText,d2
	move.l	#67-35+3,d3
	CALLDOS	Write
	bra	CloseFile2
ReadError	move.l	OutputHandle,d1	
	move.l	#DiskErrorText,d2
	move.l	#67-35+4,d3
	CALLDOS	Write
	bra	CloseFile3


*
* subroutines	
*
MakeHex	lea.l	Hex(pc),a1		; convert d0-> ASCII
	lsl.l	#8,d0
	moveq.l	#5,d2
NextNibble	rol.l	#4,d0
	move.b	d0,d1
	and.l	#$f,d1
	move.b	(a1,d1),(a0)+
	dbra	d2,NextNibble
	rts

MakeByte	lea.l	Hex(pc),a0		; convert d0-> ASCII
	move.b	d0,d1
	and.l	#$f,d1
	lsr.b	#4,d0
	and.l	#$f,d0
	move.b	(a0,d0),ByteText
	move.b	(a0,d1),ByteText+1
	rts
	
PrintCurrentPos
	lea.l	CurrentPosText+47-32(pc),a0	; write current offset
	move.l	Offset,d0
	bsr	MakeHex
	move.l	OutputHandle,d1	
	move.l	#CurrentPosText,d2
	move.l	#53-32+1,d3
	CALLDOS	Write
	rts

UserBreak	sub.l	a1,a1		; check if user break
	CALLEXEC	FindTask
	move.l	d0,a0
	move.l	26(a0),d0
	and.l	#%1111<<12,d0
	tst.l	d0
	bne.s	Break
	rts
Break	lea.l	4(a7),a7		; exit jsr
	move.l	OutputHandle,d1	
	move.l	#UserBreakText,d2
	move.l	#50-38+4,d3
	CALLDOS	Write
	bra	CloseFile3
	

		

	even
Text1	dc.b	"Enter first  file name : "
	even
Text2	dc.b	"Enter second file name : "
	even
Text3	dc.b	"Enter patch name       : "
	even
DiffSizesText	dc.b	$a,"Different file sizes !",$a
	even
Open1ErrorText	dc.b	$a,"ERROR - can't open first file ! ",$a,$a
	even
Open2ErrorText	dc.b	$a,"ERROR - can't open second file !",$a,$a
	even
Open3ErrorText	dc.b	$a,"ERROR - can't open patch file ! ",$a,$a
	even
DiskErrorText	dc.b	$a,$a,"ERROR - can't read/write bytes !",$a,$a
	even
UserBreakText	dc.b	$a,$a,"USER BREAK !",$a,$a
	even
GoodByeText	dc.b	$a,"Have a nice day !",$a,$a
	even
PatchText	dc.b	$a,$a,"Patch contains $000000 bytes.",$a
	even
ConText	dc.b	$a,"Press RETURN key to exit."
	even
InfoText
Headline	dc.b	$a,$9b,"4;31;40m","            PATCH-MAKER   by Roger Fischlin 1/90            ",$9b,"0;31;40m",$a,$a
HL_Length equ *-Headline
	dc.b	"This small utility compares two files and  creates a  patch.",$a
	dc.b	"So if somebody has got  the first  file, the  patch and FILE",$a
	dc.b	"MASTER (Fish 298) he can create the second file. It's useful",$a 
	dc.b	"if the first file isn't public domain.",$a,$a
	dc.b	"                 Author : Roger Fischlin",$a
	dc.b	"                          Steigerwaldweg 6",$a
	dc.b	"                          D-6450 Hanau 7",$a
	dc.b	"                          West Germany",$a,$a
	dc.b	" PATCH MAKER is public domain / FILE MASTER is shareware !",$a,$a
Info_Length equ *-InfoText
	even
CurrentPosText	dc.b	"Please wait - $000000",$0d
OffsetText	dc.b	"$000000 : "
	even
ByteText	dc.b	"   "
	even
ReturnText	dc.b	$a
	even
Hex	dc.b	"0123456789abcdef"
dosname	DOSNAME
	even
ConWindow	dc.b	"CON:60/20/520/150/Patch Maker Window",0
	even

	Section	"",BSS

FileHandle1	ds.l	1
FileHandle2	ds.l	1
FileHandle3	ds.l	1
_DOSBase	ds.l	1
OutputHandle	ds.l	1
Offset	ds.l	1
Differences	ds.l	1
BufferSize	ds.l	1
Buffer1	ds.b	4*1024
Buffer2	ds.b	4*1024
PatchName	ds.b	256
	cnop	0,4
FIB	ds.b	fib_SIZEOF
