*	DECIGEL+ v3.0
*	an extended 68010/20/30 patch for the Amiga
*	(c) 1989/90 by Martin Berndt
*	Option '-r' makes DeciGel resident
*	       '-v' allows Refresh of DeciGel3 vectors if resident
*	       '-t' just tests for resident module; WARN 5 if not found
*	Only one option could be used!

SysBase		equ	4
AttnFlags		equ	$128
PrivVect		equ	$20
OpenLibrary	equ	-552
CloseLibrary	equ	-414
AllocMem		equ	-198
SuperVisor	equ	-30
UserState		equ	-156
Output		equ	-60
Write		equ	-48
SetFunction	equ	-420
Forbid		equ	-132
Permit		equ	-138
SumKickData	equ	-612
KickMemPtr	equ	546
KickTagPtr	equ	550
KickCheckSum	equ	554
MOVEC_VBR_A3	equ	$4e7ab801
MOVEC_CACR_D0	equ	$4e7a0002
MOVEC_D0_CACR	equ	$4e7b0002
MOVEC_A0_CAAR	equ	$4e7b8802

main	movem.l	d1-d7/a0-a6,-(sp)		; store registers
	subq.w	#3,d0
	movem.l	d0/a0,-(sp)		; store parameter pointer
	bne.s	mainpp
	sub.b	#"-",(a0)+
	ori.b	#32,(a0)
mainpp	moveq	#0,d6
	bsr	GetBase
	lea	DosName(pc),a1		; open DOS library
	moveq	#0,d0			; any version
	jsr	OpenLibrary(a6)
	tst.l	d0			; error?
	beq	quitsp
	move.l	a6,a5			; store EXEC base
	move.l	d0,a6			; now use DOS base
	jsr	Output(a6)		; get output handle
	move.l	d0,d5			; and store it
	lea	Text(pc),a1		; get text address
	move.b	d7,14(a1)			; patch processor type
	add.b	#$30,14(a1)		; make it ASCII
	moveq	#37,d3			; string length
	bsr.s	DoWrite			; finally print it

	move.l	a6,a4			; store DOS Base
	move.l	a5,a6			; get EXEC Base
	lea	Title(pc),a1		; Name of ResModule
	bsr	FindResident		; try to find it
	movem.l	(sp),d1/a0		; get parameters
	tst.w	d1			; check length
	bne.s	rescont
	tst.b	(a0)+			; start checking string
	bne.s	rescont
	cmpi.b	#"t",(a0)			; check character
	bne.s	rescont
	bset	#14,d7
	addq.l	#8,sp			; stack correction
	tst.l	d0
	bne.s	donotres
	moveq	#5,d6			; set WARN
	bra.s	donotres			; exit

DoWrite	move.l	d5,d1			; Output handle
	move.l	a1,d2			; TextBuffer
	jmp	Write(a6)			; write string

rescont	tst.l	d0			; gotcha?
	beq.s	cont			; no Sir
	moveq	#0,d3			; no string extension
	movem.l	(sp),d1/a0		; get parameters
	tst.w	d1			; check length
	bne.s	donotcall
	tst.b	(a0)+			; start checking string
	bne.s	donotcall
	cmpi.b	#"v",(a0)			; check character
	bne.s	donotcall
	move.l	d0,a1			; call resident code
	move.l	iStruct-Struct(a1),a1
	jsr	(a1)
	moveq	#19,d3
	lea	ResText0(pc),a1		; string correction
	move.b	#" ",(a1)
donotcall	bset	#14,d7			; nothing to patch
	lea	ResText(pc),a1		; get Text
	add.w	#45,d3			; add extension
	move.l	a4,a6			; get DOS Base
	bsr.s	DoWrite			; print it

cont	movem.l	(sp)+,d1/a0		; get parameters
	tst.w	d1			; check length
	bne.s	donotres
	tst.b	(a0)+			; start checking string
	bne.s	donotres
	cmpi.b	#"r",(a0)			; check character
	bne.s	donotres
	bset	#15,d7			; set flag
donotres	move.l	a4,a1			; prepare reg
	move.l	a5,a6			; restore EXEC base
	jsr	CloseLibrary(a6)		; close DOS library
	btst	#14,d7
	bne.s	quit
	moveq	#0,d0
	move.w	#DosName-MoveMe,d0		; required memory
	moveq	#3,d1			; PUBLIC CHIP
	jsr	AllocMem(a6)
	tst.l	d0			; error?
	beq.s	quit
	move.l	d0,a2			; store pointer
	lea	DoPatch(pc),a5		; routine addr
	btst	#1,d7			; 68020/30 ?
	beq.s	doSV
	movem.l	a2/a5,-(sp)
	lea	FlushTrap(pc),a5		; clear cache
	jsr	SuperVisor(a6)
	movem.l	(sp)+,a2/a5
doSV	move.l	a2,-(sp)			; store base address
	jsr	SuperVisor(a6)		; call as exception
	move.l	(sp)+,a2
	tst.w	d7
	bmi.s	MakeRes			; make code resident
quit	move.l	d6,d0
quitr	movem.l	(sp)+,d1-d7/a0-a6		; restore registers
	rts				; exit

quitsp	addq.l	#8,sp			; stack correction
	bra.s	quit

MakeRes	lea	Struct-MoveMe(a2),a3	; start of structure
	lea	MemList-MoveMe(a2),a4	; start of MemList
	move.l	a3,d1
	lea	2(a3),a2
	move.l	d1,(a2)+			; set MatchTag
	add.l	d1,(a2)			; set EndSkip
	addq.l	#8,a2
	add.l	d1,(a2)+			; set Name
	add.l	d1,(a2)+			; set IdString
	add.l	d1,(a2)			; set Init
	move.l	a4,d1
	add.l	d1,10(a4)			; set name
	add.l	d1,16(a4)			; set address
	jsr	Forbid(a6)		; disable multitasking
	lea	ResArray-Struct+4(a3),a1	; linkage area
	move.l	KickTagPtr(a6),(a1)		; get old link
	beq.s	NoOldTag
	bset	#7,(a1)			; set linkage flag
NoOldTag	move.l	a3,-(a1)			; insert new link
	move.l	a1,KickTagPtr(a6)		; set KickTagPtr
	move.l	KickMemPtr(a6),(a4)		; get old KickMemPtr
	move.l	a4,KickMemPtr(a6)		; insert new KickMemPtr
	jsr	SumKickData(a6)		; get checksum
	move.l	d0,KickCheckSum(a6)		; and insert it
	jsr	Permit(a6)		; enable multitasking
	bra.s	quit

FindResident
	movem.l	a0/a2-a3,-(sp)		; store registers
	jsr	Forbid(a6)		; disable multitasking
	move.l	KickTagPtr(a6),d0		; try to get KickTagPtr
	beq.s	NoResi
	move.l	d0,a0
FindLoop	move.l	(a0),d0			; try to get entry
	beq.s	NoResi
	move.l	d0,a2
	move.l	14(a2),a2			; get name
	move.l	a1,a3
	moveq	#11,d0			; counter
CompLoop	cmp.b	(a2)+,(a3)+		; compare a byte
	bne.s	FindNext
	dbf	d0,CompLoop
	move.l	(a0),d0			; valid entry
	bra.s	FindRex			; exit
FindNext	addq.l	#4,a0			; increment pointer
	tst.b	(a0)			; check for link
	bpl.s	FindLoop
	move.l	(a0),d0			; get chain link
	bclr	#31,d0			; clear flag
	move.l	d0,a0			; use new list
	bra.s	FindLoop
NoResi	moveq	#0,d0
FindRex	move.l	d0,-(sp)
	jsr	Permit(a6)		; enable multitasking
	move.l	(sp)+,d0
	movem.l	(sp)+,a0/a2-a3		; restore registers
	rts

DoPatch	move.l	a2,a0			; move to work reg
	lea	MoveMe(pc),a1		; address of source
	move.w	#DosName-MoveMe-1,d0	; length of code to copy
loop	move.b	(a1)+,(a0)+		; move a byte
	dbf	d0,loop
	bra.s	ResPatch

MoveMe	movem.l	d0/a0/a6,-(sp)		; store registers
	move.l	14(sp),a0			; pointer to opcode
	move.w	(a0),d0			; get opcode
	andi.w	#$FFC0,d0			; mask out EA field
	cmpi.w	#$40C0,d0			; is it MOVE SR,EA ?
	bne.s	OhNo			; no
	ori.b	#2,(a0)			; convert to MOVE CCR,EA
	move.l	(SysBase).w,a6
	btst	#1,AttnFlags+1(a6)		; 68020/30 ?
	beq.s	PatExit
	dc.l	MOVEC_A0_CAAR
	dc.l	MOVEC_CACR_D0
	bset	#2,d0			; clear entry in cache
	dc.l	MOVEC_D0_CACR
PatExit	movem.l	(sp)+,d0/a0/a6		; restore regs
	rte
OhNo	movem.l	(sp)+,d0/a0/a6		; restore regs
PatchAddr
	jmp	$FC0000			; use old vector

ChipPatch	cmpi.l	#$b7fc0004,$1e(a5)		; wrong version?
	bne.s	ChipJmp
	move.l	$3e(a6),a3		; chipmem size
	lea	$1e(a5),a5		; skip bad routine
ChipJmp	jmp	(a5)

NewUserState
	ori.w	#$2000,sr			; change status
	move.w	sr,d1
	move.l	a7,USP			; restore SP
	move.l	d0,a7
	bclr	#$D,d1
	move.w	d1,sr
	rts

ResPatch	tst.b	d7			; 68010/20/30 ?
	beq.s	ResCont
	dc.l	MOVEC_VBR_A3		; get VBR
	move.l	ID(pc),d0			; test for own ID
	move.l	PrivVect(a3),a1
	cmp.l	ID-MoveMe(a1),d0		; already patched
	beq.s	ResCont
	move.l	PrivVect(a3),ChipPatch-MoveMe-4(a2)
	move.l	a2,PrivVect(a3)		; patch vector
ResCont	add.w	#ChipPatch-MoveMe,a2	; get offset
	move.l	a2,$2a(a6)		; set ColdCapture
	lea	$22(a6),a0		; start of checksum area
	moveq	#$16,d2			; counter
	moveq	#0,d1
CCloop	add.w	(a0)+,d1			; add a word value
	dbf	d2,CCloop
	not.w	d1			; negate checksum
	move.w	d1,$52(a6)		; finally store it
	tst.b	d7
	beq.s	equit
	add.w	#NewUserState-ChipPatch,a2	; get new vector
	move.l	a2,d0			; and fill it in
	move.l	#UserState,a0		; at this offset
	move.l	a6,a1			; in EXEC library
	jsr	SetFunction(a6)
equit	rte				; return from Exception

DeciRes	movem.l	d1-d7/a0-a6,-(sp)		; store registers
	bsr.s	GetBase
	beq.s	quitx
	btst	#1,d7			; 68020/30 ?
	beq.s	DoResPat
	lea	FlushTrap(pc),a5		; clear cache
	jsr	SuperVisor(a6)
DoResPat	lea	MoveMe(pc),a2		; Patch address
	lea	ResPatch(pc),a5		; Routine address
	jsr	SuperVisor(a6)		; call as exception
quitx	moveq	#0,d0
	movem.l	(sp)+,d1-d7/a0-a6		; restore registers
	rts				; exit

FlushTrap	dc.l	MOVEC_CACR_D0
	bset	#3,d0			; clear instruction cache
	dc.l	MOVEC_D0_CACR
	rte

GetBase	move.l	(SysBase).w,a6		; check CPU type
	move.b	AttnFlags+1(a6),d7
	andi.w	#3,d7			; mask flags
	rts

ID	dc.b	"DR30"			; ID

Struct	dc.w	$4afc			; Magic Word
	dc.l	0			; MatchTag
	dc.l	Title-Struct		; EndSkip
	dc.b	1,0,0,-10			; Flags,Version,Type,Pri
	dc.l	Title-Struct		; Name
	dc.l	Title-Struct		; IdString
iStruct	dc.l	DeciRes-Struct		; Init
Title	dc.b	"DeciRes 3.0",0
	even
ResArray	dc.l	0,0
MemList	dc.l	0,0			; Succ,Pred
	dc.w	0			; Type,Pri
	dc.l	Title-ResArray		; Name
	dc.w	1			; one entry
	dc.l	MoveMe-MemList		; address
	dc.l	DosName-MoveMe		; length

DosName	dc.b	'dos.library',0
Text	dc.b	27,'[33m',27,'[3mMC68000 ',27,'[0m',27,'[31minstalled.',10,0
	even
ResText	dc.b	'Resident Module ',27,'[33mDeciRes 3.0',27,'[31m found!'
ResText0	dc.b	10,'Vectors refreshed.',10
	even
	dc.l	0

	end7cks