; $VER: FixCrM.s 1.0 (23.10.97)
; Author: David Tritscher (dt14@uow.edu.au)
; Created: 23.10.97

;--------------------------------------------------------------------------

SYS_AllocMem		EQU	-$C6
SYS_FreeMem		EQU	-$D2
SYS_CloseLibrary	EQU	-$19E
SYS_OpenLibrary		EQU	-$228

DOS_Open		EQU	-$1E
DOS_Close		EQU	-$24
DOS_Read		EQU	-$2A
DOS_Write		EQU	-$30
DOS_IoErr		EQU	-$84
DOS_ExamineFH		EQU	-$186
DOS_SetIoErr		EQU	-$1CE
DOS_PrintFault		EQU	-$1DA
DOS_ReadArgs		EQU	-$31E
DOS_FreeArgs		EQU	-$35A
DOS_PutStr		EQU	-$3B4

;--------------------------------------------------------------------------

		RSRESET
ExecBase	RS.L	1
DosBase		RS.L	1
ReadArgs	RS.L	1
Args		RS.B	0
SrcName		RS.L	1
DstName		RS.L	1
Quiet		RS.L	1
SrcHandle	RS.L	1
DstHandle	RS.L	1
SrcLength	RS.L	1
DstLength	RS.L	1
Memory		RS.L	1
Length		RS.L	1
FIB		RS.B	260
Variables	RS.B	0

;--------------------------------------------------------------------------

Start:
	MOVE.W	#Variables/2-1,D0
1$	CLR.W	-(SP)
	DBF	D0,1$
	MOVE.L	SP,A5

	MOVEQ	#100,D7

	MOVE.L	4.W,A6
	MOVE.L	A6,ExecBase(A5)
	LEA	DosName(PC),A1
	MOVEQ	#36,D0
	JSR	SYS_OpenLibrary(A6)
	MOVE.L	D0,DosBase(A5)
	BEQ	Exit

	MOVEQ	#20,D7

	LEA	Template(PC),A0
	MOVE.L	A0,D1
	LEA	Args(A5),A0
	MOVE.L	A0,D2
	MOVEQ	#0,D3
	MOVE.L	DosBase(A5),A6
	JSR	DOS_ReadArgs(A6)
	LEA	Args.MSG(PC),A0
	MOVE.L	D0,ReadArgs(A5)
	BEQ	PrintFault

	MOVEQ	#10,D7

	MOVE.L	SrcName(A5),D1
	MOVE.L	#$3ED,D2		; MODE_OLDFILE
	JSR	DOS_Open(A6)
	LEA	OpenSrc.MSG(PC),A0
	MOVE.L	D0,SrcHandle(A5)
	BEQ	PrintFault

	MOVE.L	DstName(A5),D1
	MOVE.L	#$3EE,D2		; MODE_NEWFILE
	JSR	DOS_Open(A6)
	LEA	OpenDst.MSG(PC),A0
	MOVE.L	D0,DstHandle(A5)
	BEQ	PrintFault

	MOVE.L	SrcHandle(A5),D1
	LEA	FIB(A5),A0
	MOVE.L	A0,D2
	JSR	DOS_ExamineFH(A6)
	LEA	Examine.MSG(PC),A0
	TST.L	D0
	BEQ	PrintFault

	MOVE.L	FIB+124(A5),D0		; fib_Size
	MOVE.L	D0,SrcLength(A5)
	MOVE.L	D0,DstLength(A5)
	ADD.L	#12,D0
	MOVE.L	D0,Length(A5)
	MOVEQ	#0,D1			; MEMF_ANY
	MOVE.L	ExecBase(A5),A6
	JSR	SYS_AllocMem(A6)
	LEA	Memory.MSG(PC),A0
	MOVE.L	D0,Memory(A5)
	BEQ	PrintFault

	MOVE.L	SrcHandle(A5),D1
	MOVE.L	Memory(A5),D2
	MOVE.L	SrcLength(A5),D3
	MOVE.L	DosBase(A5),A6
	JSR	DOS_Read(A6)
	LEA	Read.MSG(PC),A0
	CMP.L	D0,D3
	BNE	PrintFault

; Make sure it's really a CrunchMania file.
Check:
	MOVE.L	Memory(A5),A4

	MOVE.L	SrcLength(A5),D4
	MOVEQ	#3,D0
	AND.L	D4,D0
	BNE	NotCrm
	CMP.L	#200,D4			; Gimme something to work with
	BLO	NotCrm

	CMP.L	#$3F3,(A4)		; Start with a hunk_header
	BNE	NotCrm
	CMP.L	#$3F2,-4(A4,D4.L)	; End with a hunk_end
	BNE	NotCrm

	MOVE.L	8(A4),D5
	ADDQ.L	#5,D5
	LSL.L	#2,D5

	MOVE.L	20(A4),D0		; Get the memory alloc for the first hunk
	CMP.L	4(A4,D5.L),D0		; Get the length of the first hunk
	BNE	NotCrm

	CMP.L	#$12,D0			; Could be a crunchmania file
	BNE.B	1$
	CMP.W	#$002A,18(A4,D5.L)
	BNE	NotCrm
	CMP.W	#$FFC4,64(A4,D5.L)
	BNE	NotCrm
	MOVEQ	#0,D0
	BRA.B	2$

1$	CMP.L	#$15,D0			; Could be a fixed crunchmania file
	BNE	NotCrm
	CMP.W	#$0036,18(A4,D5.L)
	BNE	NotCrm
	CMP.W	#$FFB8,76(A4,D5.L)
	BNE	NotCrm
	MOVEQ	#-1,D0

2$	LEA	8(A4,D5.L),A0
	CMP.W	#$48E7,(A0)+		; MOVEM.L D0-A7,-(A7)
	BNE	NotCrm
	CMP.W	#$FFFF,(A0)+
	BNE	NotCrm
	CMP.W	#$3C3C,(A0)+		; MOVE.W #x,D6
	BNE	NotCrm

	TST.L	D0			; Was it a fixed crunchmania file?
	BNE	NewCrm

	LEA	50(A4,D5.L),A0
	CMP.W	#$2F49,(A0)+		; MOVE.L A1,$3C(A7)
	BNE	NotCrm
	CMP.W	#$003C,(A0)+
	BNE	NotCrm
	CMP.W	#$4CDF,(A0)+		; MOVEM.L (A7)+,D0-A6
	BNE	NotCrm
	CMP.W	#$7FFF,(A0)+
	BNE	NotCrm
	CMP.W	#$4E75,(A0)+		; RTS
	BNE	NotCrm

	CMP.W	#$4E94,20(A4,D5.L)
	BNE	NotCrm
	CMP.W	#$4E94,24(A4,D5.L)
	BNE	NotCrm
	CMP.W	#$4E94,30(A4,D5.L)
	BNE	NotCrm
	CMP.W	#$4E94,48(A4,D5.L)
	BNE	NotCrm

	CMP.W	#$4E75,78(A4,D5.L)
	BNE	NotCrm

; It looks like a crunchmania file. Patch it.
Patch:
	ADD.W	#12,18(A4,D5.L)		; Fix up some offsets
	SUB.W	#12,64(A4,D5.L)

	ADDQ.L	#3,20(A4)		; We added 3 longs to the file
	ADDQ.L	#3,4(A4,D5.L)

	LEA	54(A4,D5.L),A0
	LEA	(A4,D4.L),A1
	LEA	12(A1),A2
1$	MOVE.W	-(A1),-(A2)		; Open up a gap for the new code
	CMP.L	A1,A0
	BLO.B	1$

	MOVE.W	#$0C6E,(A0)+	; CMP.W #$24,$14(A6)
	MOVE.W	#$0024,(A0)+
	MOVE.W	#$0014,(A0)+
	MOVE.W	#$6504,(A0)+	; BLO.B *+6
	MOVE.W	#$4EAE,(A0)+	; JSR -$27C(A6)
	MOVE.W	#$FD84,(A0)+

	ADD.L	#12,DstLength(A5)

	MOVEQ	#0,D7
	TST.L	Quiet(A5)
	BNE	Write
	LEA	Patch.MSG(PC),A0
	MOVE.L	A0,D1
	JSR	DOS_PutStr(A6)
	BRA	Write

NewCrm:
	MOVEQ	#5,D7
	TST.L	Quiet(A5)
	BNE	Write
	LEA	NewCrm.MSG(PC),A0
	MOVE.L	A0,D1
	JSR	DOS_PutStr(A6)
	BRA	Write

NotCrm:
	MOVEQ	#5,D7
	TST.L	Quiet(A5)
	BNE	Write
	LEA	NotCrm.MSG(PC),A0
	MOVE.L	A0,D1
	JSR	DOS_PutStr(A6)
	BRA	Write

Write:
	MOVE.L	DstHandle(A5),D1
	MOVE.L	Memory(A5),D2
	MOVE.L	DstLength(A5),D3
	JSR	DOS_Write(A6)
	CMP.L	D0,D3
	BEQ	Done

	MOVEQ	#10,D7
	LEA	Write.MSG(PC),A0

PrintFault:
	MOVE.L	A0,D2
	MOVE.L	DosBase(A5),A6
	JSR	DOS_IoErr(A6)
	MOVE.L	D0,D1
	JSR	DOS_PrintFault(A6)
Done:
	MOVE.L	ExecBase(A5),A6
	MOVE.L	Memory(A5),D0
	BEQ.B	1$
	MOVE.L	D0,A1
	MOVE.L	Length(A5),D0
	JSR	SYS_FreeMem(A6)
1$	MOVE.L	DosBase(A5),A6
	MOVE.L	SrcHandle(A5),D1
	BEQ.B	2$
	JSR	DOS_Close(A6)
2$	MOVE.L	DstHandle(A5),D1
	BEQ.B	3$
	JSR	DOS_Close(A6)
3$	MOVE.L	ReadArgs(A5),D1
	BEQ.B	4$
	JSR	DOS_FreeArgs(A6)
4$	MOVE.L	DosBase(A5),A1
	MOVE.L	ExecBase(A5),A6
	JSR	SYS_CloseLibrary(A6)

Exit:
	LEA	Variables(SP),SP
	MOVE.L	D7,D0
	RTS

;--------------------------------------------------------------------------

	DC.B	"$VER: FixCrM 1.0 (23.10.97)",13,10,0
DosName		DC.B	"dos.library",0
Template	DC.B	"FROM/A,TO/A,QUIET/S",0

Args.MSG	DC.B	"ReadArgs()",0
OpenSrc.MSG	DC.B	"Open(Src)",0
OpenDst.MSG	DC.B	"Open(Dst)",0
Examine.MSG	DC.B	"ExamineFH()",0
Memory.MSG	DC.B	"AllocMem()",0
Read.MSG	DC.B	"Read()",0
Write.MSG	DC.B	"Write()",0

Patch.MSG	DC.B	"Fixed! Saving",10,0
NewCrm.MSG	DC.B	"Already patched! Copying",10,0
NotCrm.MSG	DC.B	"Unknown! Copying",10,0
