;========================================================================
;
; Project...: Evolution Memory Patch (short: EMP)
; Version...: 1.1
; Date......: 19-Oct-1991
; Author....: P. de Boer (VECTOR/Vision)
; Assembler.: AsmOne V1.01/DevPac 2.14
;
;========================================================================

		RSRESET
LN		RS.B	0
LN_SUCC		RS.L	1
LN_PRED		RS.L	1
LN_TYPE		RS.B	1
LN_PRI		RS.B	1
LN_NAME		RS.L	1
LN_SIZE		RS.W	0

NT_MSGPORT	EQU	4

		RSRESET
ML		RS.B	LN_SIZE
ML_NUMENTRIES	RS.W	1
ML_ME		RS.W	0
ML_SIZE		RS.W	0

		RSRESET
ME		RS.B	0
ME_REQS		RS.W	0
ME_ADDR		RS.L	1
ME_LENGTH	RS.L	1
ME_SIZE		RS.W	0

MEMF_CHIP	EQU	1<<1

		RSRESET
RT		RS.B	0
RT_MATCHWORD	RS.W	1
RT_MATCHTAG	RS.L	1
RT_ENDSKIP	RS.L	1
RT_FLAGS	RS.B	1
RT_VERSION	RS.B	1
RT_TYPE		RS.B	1
RT_PRI		RS.B	1
RT_NAME		RS.L	1
RT_IDSTRING	RS.L	1
RT_INIT		RS.L	1
RT_SIZE		RS.W	0

RTC_MATCHWORD	EQU	$4AFC
RTB_COLDSTART	EQU	0
RTF_COLDSTART	EQU	1<<0
RTB_AUTOINIT	EQU	7
RTF_AUTOINIT	EQU	1<<7
RTM_WHEN	EQU	1
RTW_NEVER	EQU	0
RTW_COLDSTART	EQU	1

KickMemPtr	EQU	546
KickTagPtr	EQU	550
KickCheckSum	EQU	554

NULL		EQU	0

_LVOWrite		EQU	-48
_LVOOutput		EQU	-60

_LVOFindResident	EQU	-96
_LVODisable		EQU	-120
_LVOEnable		EQU	-126
_LVOForbid		EQU	-132
_LVOPermit		EQU	-138
_LVOAllocMem		EQU	-198
_LVOAddPort		EQU	-354
_LVOFindPort		EQU	-390
_LVOCloseLibrary	EQU	-414
_LVOOpenLibrary		EQU	-552
_LVOSumKickData		EQU	-612
_LVOAddMemList		EQU	-618
_LVOCopyMem		EQU	-624

ExecBase	EQU	$4

CALL		MACRO
		IFC	'EXEC','\1'
		MOVEA.L	(ExecBase).W,A6
		ENDC
		IFNC	'EXEC','\1'
		MOVEA.L	\1Base,A6
		ENDC
		JSR	_LVO\2(A6)
		ENDM

OPENLIB		MACRO
		LEA	\1Name(PC),A1
		CLR.L	D0
		CALL	EXEC,OpenLibrary
		MOVE.L	D0,\1Base
		BEQ	\2
		ENDM

CLOSELIB	MACRO
		MOVEA.L	\1Base,A1
		CALL	EXEC,CloseLibrary
		ENDM

;========================================================================
		opt	o+

SkipSpaces	move.b	(a0)+,d0
		cmp.b	#" ",d0
		beq.s	SkipSpaces

		cmp.b	#$0A,d0
		beq.s	Nothing

		andi.b	#$5F,d0
		cmp.b	#"K",d0
		seq	Flag_Kill

Nothing		OPENLIB	DOS,NoDOS

		CALL	DOS,Output
		move.l	d0,OutHandle

PrintHello	lea	Hello.TXT(pc),a0
		move.l	#Hello.LEN,d3
		BSR	PrintText

InstallRomTag	lea	MyPortName(PC),a1
		CALL	EXEC,FindPort
		tst.l	d0
		bne	Err_Already

		lea	MultiName(pc),a1
		CALL	EXEC,FindResident
		move.l	d0,ResModule
		beq	Err_NoEvolution

		lea	BootName(pc),a1
		CALL	EXEC,FindResident
		move.l	d0,ResModule+4
		beq	Err_NoEvolution

AllocateMem	move.l	#TagCodeLen,d0
		moveq	#MEMF_CHIP,d1
		CALL	EXEC,AllocMem
		tst.l	d0
		beq	Err_NoMem

CopyTagCode	movea.l	d0,a5
		lea	TagCode(PC),a0
		movea.l	d0,a1
		move.l	#TagCodeLen,d0
		CALL	EXEC,CopyMem

		CALL	EXEC,Forbid
		CALL	EXEC,Disable

		lea	RomTagPtrs-TagCode(a5),a0
		move.l	KickTagPtr(a6),4(a0)
		beq.s	NoTagYet
		bset	#7,4(a0)

NoTagYet	move.l	a0,KickTagPtr(a6)
		lea	MyRomTag-TagCode(a5),a1
		move.l	a1,(a0)

InitMemList	lea	MyMemList-TagCode(a5),a1
		move.l	a5,ML_SIZE+ME_ADDR(a1)
		move.l	KickMemPtr(a6),d0
		move.l	d0,LN_SUCC(a1)
		move.l	a1,KickMemPtr(a6)

InitRomTag	lea	MyRomTag-TagCode(a5),a1
		move.l	a1,RT_MATCHTAG(a1)
		lea	RT_SIZE(a1),a2
		move.l	a2,RT_ENDSKIP(a1)
		lea	MyTagName-TagCode(a5),a2
		move.l	a2,RT_NAME(a1)
		move.l	a5,RT_INIT(a1)
		CALL	EXEC,SumKickData
		move.l	d0,KickCheckSum(a6)

InitPort	lea	MyPortName-TagCode(a5),a0
		lea	MyPort-TagCode(a5),a1
		clr.l	LN_SUCC(a1)
		clr.l	LN_PRED(a1)
		move.l	a0,LN_NAME(a1)
		CALL	EXEC,AddPort

		CALL	EXEC,Enable
		CALL	EXEC,Permit

		lea	Installed.TXT(pc),a0
		move.l	#Installed.LEN,d3
		bra.s	Exit

Err_NoEvolution	lea	NoEvolution.TXT(pc),a0
		move.l	#NoEvolution.LEN,d3
		bra.s	Exit

Err_Already	lea	AlreadyInst.TXT(pc),a0
		move.l	#AlreadyInst.LEN,d3
		bra.s	Exit

Err_NoMem	lea	NoMemory.TXT(pc),a0
		move.l	#NoMemory.LEN,d3

Exit		BSR.S	PrintText

CloseDOS	CLOSELIB	DOS

NoDOS		clr.l	d0
		rts

;========================================================================
PrintText	move.l	OutHandle(pc),d1
		beq.s	.Exit
		move.l	a0,d2
		CALL	DOS,Write

.Exit		rts

;========================================================================

OutHandle	DC.L	0
DOSBase		DC.L	0
DOSName		DC.B	"dos.library",$0

MultiName	DC.B	"MultiRAM",$0
BootName	DC.B	"Boot 1.2!",$0

Hello.TXT	DC.B	$9B,"1;33mEvolution Memory Patch",$9B,"0m V1.1 by P. de Boer"
		DC.B	" (VECTOR/Vision)",$0A
Hello.LEN	EQU	*-Hello.TXT
Installed.TXT	DC.B	"Patch installed !",$0A
Installed.LEN	EQU	*-Installed.TXT
AlseadyInst.TXT	DC.B	"Patch already installed !",$0A
AlreadyInst.LEN	EQU	*-AlreadyInst.TXT
NoMemory.TXT	DC.B	"Not enough memory for Patch !?!?",$0A
NoMemory.LEN	EQU	*-NoMemory.TXT
NoEvolution.TXT	DC.B	"Can't find evolution controller ?!?!",$0A
NoEvolution.LEN	EQU	*-NoEvolution.TXT
		EVEN

;========================================================================
		opt	p+

TagCode		movem.l	d0-d7/a0-a6,-(SP)

		lea	MyPort(pc),a1
		lea	MyPortName(PC),a0
		clr.l	LN_SUCC(a1)
		clr.l	LN_PRED(a1)
		move.l	a0,LN_NAME(a1)
		CALL	EXEC,AddPort

		lea	Flag_Kill(pc),a0
		tst.b	(a0)
		beq.s	.NoKill
		move.l	ResModule+4(pc),d0
		BSR.S	SeekAndDestroy

.NoKill		move.l	ResModule(pc),d0
		BSR.S	SeekAndDestroy

EvolutionCode	btst	#$07,$BFE001
		beq.s	.NoAddMem

		lea	$200000,a0
		move.l	#$800000,d0
		BSR.S	TestMem
		bne.s	.FoundMem

		lea	$800000,a0
		move.l	#$200000,d0
		BSR.S	TestMem			;d0=length, a0=start
		beq.s	.NoAddMem

.FoundMem	LEA	$00F01378,A1		;name
		MOVEQ	#$05,D1			;type is fast!public
		MOVEQ	#10,D2			;priority +10

		cmp.l	#$11144EF9,(a0)
		bne.s	.NoKick2.0
		sub.l	#$80000,d0
		add.l	#$80000,a0

.NoKick2.0	CALL	EXEC,AddMemList

.NoAddMem

EndTagCode	movem.l	(SP)+,d0-d7/a0-a6
EndCode		rts

;========================================================================
SeekAndDestroy	move.l	(ExecBase).w,a6
		move.l	300(a6),a0		;resident list

.Test		cmp.l	(a0)+,d0
		bne.s	.Test

.Go		move.l	(a0)+,-8(a0)		;easy way out...
		tst.l	-8(a0)
		beq.s	.Exit
		bmi.s	.Exit
		bra.s	.Go

.Exit		rts

;========================================================================
TestMem		movem.l	d2-d3/a2,-(SP)

		clr.l	d1

		move.l	a0,a1
		move.l	a0,a2
		add.l	d0,a2

		move.l	(a0),d2

		move.l	#"ASM0",(a0)
		cmp.l	#"ASM0",(a0)
		bne.s	.NoWay

		move.l	a0,a1
.Loop		add.l	#$40000,a1
		cmp.l	a2,a1
		bge.s	.EndOfMem

.MemoryThere	move.l	(a1),d3

		clr.l	(a1)
		tst.l	(a1)
		bne.s	.EndOfMem

		move.l	#"ASM0",(a0)
		cmp.l	#"ASM0",(a1)
		beq.s	.EndOfMem

		move.l	d3,(a1)
		bra.s	.Loop

.EndOfMem	move.l	a1,d1
		sub.l	a0,d1
;		cmp.l	d0,d1
;		beq.s	.SkipTest

;		clr.l	(a0)
;		tst.l	(a1)
;		beq.s	.SkipTest

;		nop			;enu?

.SkipTest	move.l	d2,(a0)

.NoWay		movem.l	(SP)+,d2-d3/a2

		move.l	d1,d0
		rts


;========================================================================

ResModule	DCB.L	2,0
RomTagPtrs	DCB.L	2,0

MyMemList	DS.B	LN_SIZE
		DC.W	1
		DC.L	NULL
		DC.L	TagCodeLen

MyRomTag	DC.W	RTC_MATCHWORD
		DC.L	NULL
		DC.L	NULL
		DC.B	RTF_COLDSTART
		DC.B	1
		DC.B	0
		DC.B	116		;just before evolution
		DC.L	NULL
		DC.L	NULL
		DC.L	0

MyPort		DC.L	NULL
		DC.L	NULL
		DC.B	NT_MSGPORT
		DC.B	0
		DC.L	NULL
		DC.B	0
		DC.B	0
		DC.L	NULL
		DS.B	14

MyPortName	DC.B	"EMP.port",$0
MyTagName	DC.B	"EMP patch",$0
Flag_Kill	DC.B	0
		EVEN

TagCodeLen	EQU	*-TagCode

;========================================================================

