;_ args :t/xx ram:x ram:z
; The Patcher
; (c) 1993 MJSoft System Software
; Martin Mares

;	opt	x+

_nostart	set	1
	include	"macros.h"

	code
	section	Vars,BSS
v
	code

	lea	v,a4
	push	a0
	dv.l	dosbase
	lea	dosname(pc),a1
	call	exec,OldOpenLibrary
	pop	a0
	move.l	d0,(a4)
	bne.s	dosok
	moveq	#100,d0
	rts

	dbuf	srcname,128
	dbuf	destname,128
	dbuf	patname,128

dosok	cmp.b	#'?',(a0)
	bne.s	nohelp
	lea	help(pc),a0
	bra	okmsg

nohelp	geta	srcname,a1
	bsr	parsename
	geta	destname,a1
	bsr	parsename
	geta	patname,a1
	bsr	parsename
	bsr	skipspaces
	lea	toomany(pc),a0
	bne	errr

	dv.l	srcfile	
	dv.l	srclen
	geta	srcname,a0
	geta	srcfile,a2
	lea	srcerr(pc),a3
	bsr	loadfile

	dv.l	patfile
	dv.l	patlen
	geta	patname,a0
	geta	patfile,a2
	lea	paterr(pc),a3
	bsr	loadfile

	dv.l	destfile
	dv.l	destlen

	get.l	patfile,a2	; A2=patchfile
	cmp.l	#'MJPa',(a2)+
	bne.s	badpat
	cmp.l	#'tch'*256+1,(a2)+
	beq.s	pat1
badpat	lea	badpatt(pc),a0
	bra	errr

pat1	get.l	srclen,d0
	cmp.l	(a2)+,d0
	beq.s	pat2
incfil	lea	incfilt(pc),a0
	bra	errr

pat2	get.l	srcfile,a0
	moveq	#0,d1
	moveq	#0,d2
chs1	move.b	(a0)+,d2
	add.l	d2,d1
	ror.l	#1,d1
	subq.l	#1,d0
	bne.s	chs1
	move.l	(a2)+,d0
	cmp.l	(a2)+,d1
	bne.s	incfil

	moveq	#1,d1
	call	exec,AllocMem
	move.l	(a4),a6
	lea	imsmem(pc),a0
	put.l	d0,destfile
	beq	errr
	put.l	-8(a2),destlen
	move.l	d0,a3		; A3=destination
	get.l	srcfile,a0
patit1	moveq	#0,d0
	move.b	(a2)+,d0
	move.l	d0,d1
	lsr.w	#5,d1
	and.w	#$001F,d0
	bne.s	10$
	move.b	(a2)+,d0
	lsl.w	#8,d0
	move.b	(a2)+,d0
	tst.w	d0
	bne.s	10$
	moveq	#3,d7
11$	lsl.l	#8,d0
	move.b	(a2)+,d0
	dbra	d7,11$
10$	cmp.w	#6,d1
	bcc	ilgl
	add.w	d1,d1
	move.w	table(pc,d1.w),d1
	jsr	table(pc,d1.w)
	bra.s	patit1

rel	macro	*label
	dc.w	\1-table
	endm
table	rel	patend
	rel	change
	rel	insert
	rel	delete
	rel	skip
	rel	xorins

ilgl	lea	errpatt(pc),a0
	bra	errr

change	add.l	d0,a0
insert	move.b	(a2)+,(a3)+
	subq.l	#1,d0
	bne.s	insert
	rts

delete	add.l	d0,a0
	rts

skip	move.b	(a0)+,(a3)+
	subq.l	#1,d0
	bne.s	skip
	rts

xorins	push	a0
	get.l	srcfile,a1
	move.l	a1,a0
	add.l	srclen-v(a4),a1
xorins1	cmp.l	a1,a0
	bcs.s	1$
	get.l	srcfile,a0
1$	move.b	(a0)+,d1
	move.b	(a2)+,d2
	eor.b	d1,d2
	move.b	d2,(a3)+
	subq.l	#1,d0
	bne.s	xorins1
	pop	a0
	rts

patend	addq.l	#4,sp
	move.l	a3,d0
	sub.l	destfile-v(a4),d0
	cmp.l	destlen-v(a4),d0
	bne.s	ilgl

	geta	destname,a0
	move.l	a0,d1
	move.l	#1006,d2
	call	Open
	lea	wrterr(pc),a0
	move.l	d0,d7
	beq	errr
	get.l	destfile,d2
	get.l	destlen,d3
	call	Write
	move.l	d0,d2
	move.l	d7,d1
	call	Close
	lea	wrterr(pc),a0
	cmp.l	d2,d3
	bne	errr

	lea	donet(pc),a0
	bra	okmsg

loadfile	move.l	(a4),a6
	move.l	a0,d1
	move.l	#1005,d2
	call	Open
	move.l	a3,a0
	move.l	d0,d7
	beq	sperr
	move.l	d0,d1
	moveq	#0,d2
	moveq	#1,d3
	call	Seek
	move.l	d7,d1
	moveq	#-1,d3
	call	Seek
	move.l	d0,d3
	moveq	#1,d1
	call	exec,AllocMem
	move.l	(a4),a6
	move.l	d0,(a2)+
	bne.s	mem1ok
	move.l	d7,d1
	call	Close
insmem	lea	imsmem(pc),a0
	bra	sperr
mem1ok	move.l	d0,d2
	move.l	d3,(a2)
	move.l	d7,d1
	call	Read
	move.l	d0,d2
	move.l	d7,d1
	call	Close
	move.l	a3,a0
	cmp.l	d2,d3
	bne.s	sperr
	rts

argerr	lea	toofew(pc),a0
sperr	addq.l	#4,a7
errr	bsr	puts
	moveq	#10,d7
	bra.s	cleanup

okmsg	bsr	puts
okay	moveq	#0,d7	; ReturnCode
cleanup	move.l	4.w,a6
	get.l	srclen,d0
	beq.s	1$
	get.l	srcfile,a1
	call	FreeMem
1$	get.l	patlen,d0
	beq.s	2$
	get.l	patfile,a1
	call	FreeMem
2$	get.l	destlen,d0
	beq.s	3$
	get.l	destfile,a1
	call	FreeMem
3$	move.l	(a4),a1
	call	CloseLibrary
	move.l	d7,d0
	rts

skipspaces	move.b	(a0)+,d0
	beq.s	skipspend
	cmp.b	#' ',d0
	beq.s	skipspaces
	cmp.b	#9,d0
	beq.s	skipspaces
	cmp.b	#10,d0
skipspend	rts

parsename	bsr.s	skipspaces
	beq	argerr
	move.b	d0,d1
	cmp.b	#'"',d0
	beq.s	1$
	subq.l	#1,a0
	moveq	#' ',d1
1$	move.b	(a0)+,d0
	beq.s	2$
	cmp.b	#10,d0
	beq.s	2$
	cmp.b	d1,d0
	beq.s	3$
	move.b	d0,(a1)+
	bra.s	1$
2$	subq.l	#1,a0
	cmp.b	#' ',d1
	beq.s	3$
	lea	badargs(pc),a0
	bra	sperr
3$	sf	(a1)+
	rts

puts	move.l	a0,d2
1$	tst.b	(a0)+
	bne.s	1$
	subq.l	#1,a0
	move.l	a0,d3
	sub.l	d2,d3
	move.l	(a4),a6
	call	Output
	jump	Write

dosname	dc.b	'dos.library',0
help	dc.b	'The Patcher 1.1'
	dc.b	'                  '
	dc.b	'(c) 1993 MJSoft System Software, Martin Mares',10,10
	dc.b	'Usage: Patcher <source> <destination> <patch table>',10
	dc.b	0
toomany	dc.b	'Too many arguments!',10,0
toofew	dc.b	'Required argument missing!',10,0
badargs	dc.b	'Invalid arguments!',10,0
srcerr	dc.b	'Unable to read source file!',10,0
paterr	dc.b	'Unable to read patch file!',10,0
imsmem	dc.b	'Insufficient memory!',10,0
badpatt	dc.b	'Not a patch file!',10,0
errpatt	dc.b	'Corrupted patch file!',10,0
incfilt	dc.b	'Invalid source file for this patch table!',10,0
donet	dc.b	'Done.',10,0
wrterr	dc.b	'Unable to open output file!',10,0
	even
