; FILE: Source:BlizKick.ASM          REV: 481 --- BlizKick - the ultimate maprom tool
; History
;  1      Running OK!
;  15     Now BlizKick should work with all Blizzard turbos.
;  19     Now BlizKick should even support KS 1.0... (?)
;  25     Added LOCALFAST feature.
;  31     Added QUICKBOOT feature.
;  33     Added better Printf.
;  48     Added Better ROM identification code (checksum).
;  65     Added "real" cache clear routine.
;  69     Fixed _seek bug.
;  71     Fixed KS 1.3 SPEEDROM bug.
;  81     Replaced "execinit" patch with resident tag.
;  107    Fix for Blizzard 1260! 1230-IV too!!
;  111    Added original Kickstart restoration.
;  114    Implemented KS1.x KS restoration.
;  115    Improved error messages.
;  116    Improved MAPROM test and CacheClear routine.
;  125    Added HOGWAITBLIT feature.
;  129    Added SetPatch (680x0.library) check.
;  175    Added MODULE feature.
;  186    Added EXTRESBUF feature.
;  210    Added External patches and BKMF_ExtResBuf flag, fixed 1.x ROMTag support.
;  215    Fixed LOCALFAST feature not to force MEMF_LOCAL or MEMF_KICK!
;  220    Fixed KS 1.x ROMTag support.
;  225    Added special handling for 1230-IV and 1260. Fixed FORCE.
;  240    Removed need to be run before SetPatch on 1260 systems.
;  248    Can be used with Enforcer, CPU FASTROM, VMM etc.
;  257    Improved 040/060 cache flushing code. BlizKick release 1.6.
;  266    Fixed bug in 040/060 MMU test code.
;  276    Added XPK support.
;  277    Modified to work better with PowerPC... :)
;  279    Added better (Old)OpenLibrary code. Removed FindName() things.
;  289    Fixed XPK support.
;  293    Now will set memory node name if null.
;  300    Fixed EXTRESBUF.
;  302    Fixed negative return code bug.
;  307    Added ROM address validity test.
;  311    Fixed BLIZZARD 2060 code.
;  313    Fixed one terrible bug from B2060 code.
;  328    Fixing EXTRESBUF...
;  332    Finished! Now it should work with 1260, 2040 and 2060.
;  338    DOES work on 1260. Fixed one minor bug. SoftSCSI module doesn't work.
;  340    Added memheader move code to LOCALFAST. -> Speed AllocMem()
;  343    Fixed reset code!
;  344    Allowed BlizKick to kick same kickfile and rom chip version.
;  348    Fixed .testblizppcrunnommu. Added pseudofile (*) feature.
;  353    Added LastPatches (fix for MEMF_REVERSE svstack, etc.)
;  361    Fixed svstack trash, disabled SVSTACKTRASH.
;  377    Added QUIET switch, fixed LastPatches, KS 33.180 works now!
;  388    Got KS 33.180 finally work 100%.
;  389    Added handling for BKMODPATH env variable.
;  399    Improved HOGWAITBLIT.
;  400    Found out that 2040 and 2060 boards are almost identical.
;  403    Fixed reset code to *disable* caches.
;  404    1.11ß1: Trying to get EXTRESBUF into fastmem.
;  412    Did it. Seems to work 100%.
;  415    Fixed MAPROM test. Now should detect if MAPROM not set.
;  416    Disabled SUPERVISOR_NOREVERSE from LastPatches.
;  421    Added support for (A4000?) CPU Cards.
;  425    Now KS 1.x are only patched if they're original versions. This should
;         prevent problems with some patches 1.x ROM images.
;  426    Fixed bug in ROM image validation test.
;  427    9th Dec 1997: ARGH! Wrote nice CPUCard support but forgot to enable
;         it!!! ;-)
;  429    Added support for Cyberstorm PPC and MKIII. Now should work at least
;         with CBM CPU Cards, Cyberstorm MKI, MKIII and PPC.
;  439    Separated A1200 and other model's check routines. Hopefully fixed CS
;         MKIII/PPC support. Added CS MKII support. Now CPUCARD is only meant to
;         be used with CS MKI & compatible.
;  442    Fixed few typos etc.
;  443    Fixed stupid BUG from CS support... THANKS DUKEN!! =)
;  444    Had mixed 20x0 and CS MK II product IDs... doh! Thanks shido at #amiga!
;  445    Fixed some Lock bugs.
;  446    13th May 1998 Made the source public in hope someone would continue the
;         development.
;  450    6th July 1998 Added Blizzard PPC support.
;  458    8th July 1998 Fixed Blizzard PPC and CS MKII support (I hope).
;  459    17th July 1998 Fixed stupid bug from CS MKII support.
;  461    4th October 1998 Finally fixed the blizz ppc bug. hehe.
;  462    6th October 1998 Fixed support for old KS.
;  463    9th October 1998 Fixed MK2 bug. Ta ChaoZer.
;  464    13th October 1998 Another MK2 fix <sigh>. Ta ChaoZer.
;  467    3rd November 1998 Disabled rom checksum disable in SPEEDROM.
;  468    24th January 1999 Fixed stupid blizzppc (and probably CSPPC too)
;         bug, blizzppc/csppc kernel overwrote EXTRES buffer. Now allocates
;         1mb extra memory.
;  469    7th November 1999 Made BlizKick use fastmem hunks again. Finally
;         made it possible to `FORCE-after-maprom-is-already-active' and remove
;         maprom for Blizzard PPC.
;  470    Implemented new straightforward method to solve BKMODPATH variable
;         in DoPlanting routine.
;  471    Doesn't Delay(25) if QUIET is specified.
;  472    Added 040/060 move16 optimized copymem256.
;  473    Sped up FindResident and resident module reconnect. froze 1.19.
;  474    7th Jan 2000: Bumped revision strings to 1.20.
;  475    8th Jan 2000: Fixed major memory loss on extresbuf Deallocate on error
;         condition. Also that Deallocate() call wasn't called in Forbid state.
;  476    9th Jan 2000: New feature: you can give *any* loadsegable executable
;         as module. Resident modules inside will be initialized. Cool. Renders
;         SCSIDEV43 module obsolete, just give devs:scsi43.device as one module!
;         You can also give l:fastfilesystem etc! wooow, this is WAY too cool. :)
;         This required a change in the internal way of handling EXTRES buffer
;         + some new InternalLoadSeg code.
;  477    Now uses move.l an,an as nop when possible. FindResident bugged, it
;         scanned ROM first, then EXTRES buffer. Fixed to be opposite.
;  478    Added mmu.library support to getmmu and runnommu routine. This is a
;         "good thing"(TM).
;  479    14th Jan 2000: LOCALFAST and QUICKBOOT are now finally gone. Arguments
;         are there, but do nothing. Now the good news: Finally cleaned up the
;         code, and changed EXTRES buffer attaching to ROM such way it finally
;         works everytime on blizzppc. Yes! Added new argument SANITY/K/N to
;         specify sanity added to EXTRES buffer allocation in kbytes. PoolMem
;         could have fucked BlizKick in several ways, it changes MemHeaders on
;         the fly... Fixed.
;  480    17th Jan 2000: *MAJOR BUG*: move16 could have easily got source
;         aligned by only 8 causing copy source shifted by 8 bytes -> non
;         working rom image. *THIS* has caused all these weird crashed with
;         different EXTRESBUF sizes. Me & my ultrafast copyloop. Duh! :(
;         Now uses *only* movem copy.
;  481    Wrote separate LocalFast module so removed ARG_LOCALFAST completely.
;         exe module support didn't set error code properly when out of EXTRES
;         buffer memory. Accidently called dos.library/Open for _gettc when
;         exec.library/Supervisor should have been called. Fun thing is that
;         this had so side effects. :)
;


;DEBUGMODE	EQU	1		;don't clone code

;
; I seriously doubt if this source code is useful for anything else.
; Hairy code everywhere, this one is really a bitch to maintain...
;

; TODO (err, not never, maybe, huh)
; o MMU ROM mapping for 030 040 and 060. Apollo boards and such.
; o ROM checksum (restore orig rom if bad)
; o IDEFix97 module (replacing LoadIDE)
; o OxyPatcher module (maybe)
; o possibility to get commandline arguments from a file
;   (can be emulated with `BlizKick ? <cmd_file')
; o module memory requirements inside the module itself ('$LEN: 280' ?)
; o SoftSCSI for Blizzard 20x0. Only if I had the information needed...
;

USE_STD_INCLUDES	SET	1
	IFNE	USE_STD_INCLUDES
	MACHINE	MC68040
	include	"exec/types.i"
	include	"exec/nodes.i"
	include	"exec/libraries.i"
	include	"exec/memory.i"
	include	"exec/execbase.i"
	include	"exec/resident.i"
	include	"exec/alerts.i"
	include	"exec/semaphores.i"
	include	"dos/dos.i"
	include	"exec/exec_lib.i"
	include	"dos/dos_lib.i"
	include	"graphics/gfxbase.i"
	include	"graphics/graphics_lib.i"
call	MACRO
	jsr	(_LVO\1,a6)
	ENDM
	ELSE
	include	"Devpac:Gen.gs"
	ENDC
	include	"dos/dosextens.i"
	include	"libraries/configvars.i"
	include	"libraries/expansion_lib.i"
	include	"hardware/dmabits.i"
	include	"hardware/custom.i"

	include	"libraries/xpk.i"	; from xpk_dev

	include	"blizkickmodule.i"


; mmu.library LVOs
	IFND	_LVOGetMMUType
_LVOGetMMUType	EQU	-$36
_LVOWithoutMMU	EQU	-$10E
	ENDC

; PoolMem uses this to indicate small pool MemHeader.
; We don't want to get EXTRES buffer memory from such mem...
MEMF_POOLMEM	EQU	$10

ARG_KICKFILE	EQU	0
ARG_MODULE	EQU	4
ARG_EXTRESBUF	EQU	8
ARG_SANITY	EQU	12
ARG_FORCE	EQU	16
ARG_QUICKBOOT	EQU	20
ARG_SPEEDROM	EQU	24
ARG_HOGWAITBLIT	EQU	28
ARG_CPUCARD	EQU	32
ARG_QUIET	EQU	36

BLIZPROD	EQU	$2140
ROMSUMOFFS	EQU	-$18
ROMSIZEOFFS	EQU	-$14
IDOFFS	EQU	-$10
BLIZKICK_ID	EQU	'BlzK'
DEF_SANITY	EQU	32		;default allocation sanity buffer, 32k

KEEP_CHECKSUM	EQU	1		;don't disable rom checksum
NEW_ENV_METHOD	EQU	1		;use new BKMODPATH solve routine

CACHEFLUSH040	MACRO
	dc.w	$F478		; CPUSHA BC	flush the data into memory
	dc.w	$4E71		; nop
	ENDM

FULLFLUSH040	MACRO
	dc.w	$F478		; CPUSHA BC	flush the data into memory
	dc.w	$F518		; PFLUSHA	flush the address translation cache
	dc.w	$4E71		; nop
	ENDM

;;	dc.w	$F4F8		; CPUSHA DC	flush the data cache into memory


	SECTION	CODE,CODE

Main	move.l	a0,a2
	move.l	d0,d2
	moveq	#RETURN_FAIL,d7
	move.l	(4).w,a6

	lea	(mmuname,pc),a1
	moveq	#41,d0
	bsr	OpenLib
	lea	(_mmubase,pc),a0
	move.l	d0,(a0)

	lea	(_ExecBase,pc),a0
	move.l	a6,(a0)
	lea	(_AttnFlags,pc),a0
	move.w	(AttnFlags,a6),(a0)

	IFGT	0
	btst	#AFB_68040,(_AttnFlags+1,pc)
	bne.b	.has_040
	lea	(copymem256,pc),a0
	move.w	#$6000|(copymem256_000-copymem256-2),(a0)
.has_040
	ENDC

	IFD	DEBUGMODE
	bsr	CacheClearOS
	ELSE
	move.l	#CODE_SIZEOF,d0
	move.l	#MEMF_PUBLIC,d1
	call	AllocMem
	lea	(_Self,pc),a0
	move.l	d0,(a0)
	beq	.exit

	move.l	d0,a1
	pea	(.jmpdest-Main,a1)
	pea	(CacheClearOS,pc)
	lea	(Main,pc),a0
	move.l	#CODE_SIZEOF,d0
	jmp	(_LVOCopyMemQuick,a6)
.jmpdest
	ENDC

	lea	(DosName,pc),a1
	moveq	#33,d0
	bsr	OpenLib
	move.l	d0,d6
	beq	.exit
	move.l	d0,a6

	moveq	#0,d4			Set default!!

	cmp.w	#37,(LIB_VERSION,a6)
	shs	d5

	bsr	getmmu
	lea	(_mmuflag,pc),a0
	move.b	d0,(a0)
	beq.b	.nommu

	btst	#AFB_68040,(_AttnFlags+1,pc)
	beq.b	.nommu
	; oops, used to call dos.library/Open() instead ;)
	move.l	(_ExecBase,pc),a6
	lea	(_gettc,pc),a5
	call	Supervisor
	lea	(_tc,pc),a0
	move.l	d0,(a0)
	move.l	d6,a6
.nommu

	lea	(_Array,pc),a3
	tst.b	d5
	bne.b	.ks20
	clr.l	-1(a2,d2.l)
	subq.l	#1,d2
	beq.b	.do			RESTORE!
	move.l	a2,(a3)
	lea	(_13Help,pc),a0
	cmp.b	#'?',(a2)
	bne.b	.do
	subq.l	#1,d2
	beq	.printmsgexit
	bra.b	.do
.ks20	lea	(_Template,pc),a0
	move.l	a0,d1
	move.l	a3,d2
	moveq	#0,d3
	call	ReadArgs
	move.l	d0,d4
	beq	.badargs

.do
	lea	(_Quiet,pc),a0
	move.l	(ARG_QUIET,a3),(a0)

	tst.l	(ARG_CPUCARD,a3)
	beq.b	.no_cpucard
	bsr	CheckCPUCard
	lea	(_CPUCard,pc),a0
	move.b	d0,(a0)
	bne.b	.has_cpucard
	lea	(NoCPUCard,pc),a0
	bra.b	.printmsgexit
.no_cpucard
	bsr	TestBliz
	lea	(RequiresBliz,pc),a0
	lea	(_BlizROM,pc),a1
	move.l	d0,(a1)
	beq.b	.printmsgexit
.has_cpucard

	movem.l	d4-d6/a6,-(sp)
	moveq	#RETURN_ERROR,d7
	lea	(Messu,pc),a0
	bsr	_PrintHeaderf
	bsr	_HeadMain
	movem.l	(sp)+,d4-d6/a6

.freeargs	tst.b	d5
	beq.b	.closedos
	move.l	d4,d1
	call	FreeArgs
.closedos	move.l	d6,a1
	move.l	(_ExecBase,pc),a6
	call	CloseLibrary
.exit

	move.l	(_mmubase,pc),d0
	beq.b	.nommulib
	move.l	d0,a1
	call	CloseLibrary
.nommulib
	move.l	(_Self,pc),d0
	beq.b	.nocopy
	move.l	d0,a1
	move.l	#CODE_SIZEOF,d0
	call	Forbid			Make sure we have time to execute
	call	FreeMem			the rest...
.nocopy	move.l	d7,d0
	rts

.printmsgexit	bsr	_PrintHeaderf
	bra.b	.freeargs

.badargs	bsr.b	_PrintFault		IN: d5=kickflag, d6=dosbase
	bra.b	.closedos


;  IN: d5=kickflag, d6=dosbase
; OUT: Fault printed
_PrintFault	movem.l	d0-d2/a0-a1/a6,-(sp)
	move.l	(_Quiet,pc),d0
	bne.b	.exit
	move.l	d6,a6
	call	IoErr
	tst.b	d5
	beq.b	.oldie
	move.l	d0,d1
	moveq	#0,d2
	call	PrintFault
.exit	movem.l	(sp)+,d0-d2/a0-a1/a6
	rts

.oldie	move.l	d0,-(sp)
	beq.b	.noerr
	lea	(_ks13error,pc),a0
	move.l	sp,a1
	bsr	_Printf
.noerr	addq.l	#4,sp
	bra.b	.exit


;  IN: A0=FmtString, A1=Array, a2=Buffer
; OUT: Formatted text
_Sprintf	movem.l	d0-d1/a0-a3/a6,-(sp)
	move.l	a2,a3
	lea	(.putchar,pc),a2
	move.l	(_ExecBase,pc),a6
	call	RawDoFmt
	movem.l	(sp)+,d0-d1/a0-a3/a6
	rts
.putchar	move.b	d0,(a3)+
	rts


;  IN: A0=FmtString, A1=Array, d6=dosbase
; OUT: Printed text, including program info header
_PrintHeaderf	movem.l	d0-d1/a0-a2/a6,-(sp)
	move.l	(_ExecBase,pc),a6
	move.l	#$10000,d0		; Allocate 64k buffer
	moveq	#MEMF_ANY,d1
	call	AllocMem
	move.l	d0,-(sp)
	beq.b	.nomem
	movem.l	(3*4,sp),a0-a1
	move.l	(sp),a2
	bsr.b	_Sprintf
	pea	(_Copyright,pc)
	pea	(_Version,pc)
	lea	(.header,pc),a0
	move.l	sp,a1
	bsr.b	_Printf
	addq.l	#8,sp
.nomem	move.l	(sp)+,d0
	beq.b	.exit
	move.l	d0,a1
	move.l	#$10000,d0
	call	FreeMem
.exit	movem.l	(sp)+,d0-d1/a0-a2/a6
	rts
.header	dc.b	$9B,'1;32m%s',$9B,'31m %s.',$9B,'0m',10
	dc.b	'%s',0
	CNOP	0,2


	STRUCTURE pf_data,0
	APTR	pfd_DosBase
	APTR	pfd_Count
	STRUCT	pfd_Buffer,256
	LABEL	pf_data_SIZEOF

	CNOP	0,4
;;_OutputFH	dc.l	0
;  IN: A0=FmtString, A1=Array (may be 0), d6=dosbase
; OUT: Printed text
_Printf
Printf	movem.l	a0-a3/a6/d0-d3,-(sp)
	move.l	(_Quiet,pc),d0
	bne.b	.exit
	lea	(-pf_data_SIZEOF,sp),sp
	move.l	sp,a3
	move.l	d6,(a3)+
	clr.l	(a3)+
	lea	(.newchar,pc),a2
	move.l	(_ExecBase,pc),a6
	call	RawDoFmt
	move.l	d6,a6
	IFD	_OutputFH
	move.l	_OutputFH,d1
	ELSE
	call	Output
	move.l	d0,d1
	ENDC
	move.l	a3,d2
	move.l	(-4,a3),d3
	call	Write
	lea	(pf_data_SIZEOF,sp),sp
.exit	movem.l	(sp)+,a0-a3/a6/d0-d3
	rts
.newchar	movem.l	d0-d3/a0-a1/a3/a6,-(sp)
	move.l	a3,d2				for Write()
	move.l	-(a3),d1
	move.b	d0,4(a3,d1.l)
	addq.b	#1,d1
	move.l	d1,(a3)
	bne.b	.dont_print
	move.l	-(a3),a6
	IFD	_OutputFH
	move.l	_OutputFH,d1
	ELSE
	call	Output
	move.l	d0,d1
	ENDC
	move.l	#256,d3
	call	Write
.dont_print	movem.l	(sp)+,d0-d3/a0-a1/a3/a6
	rts


;  IN: d6=dosbase, should remain if you're going to call internal _xxx functions
;      a3=paramarray, is zero if null template, scratch
;      a6=dosbase, scratch
; OUT: d7=return code
_HeadMain	tst.l	(a3)			(ARG_KICKFILE,a3)
	bne.b	.norestore
	lea	(_restore,pc),a0
	bsr	runnommu
	movem.l	(_regtemp,pc),d3/a4	preserves condition codes!
	bne	KickSys

	lea	(NoRem,pc),a0
	bra	_Printf
.norestore
	moveq	#0,d1			!!
	bsr	SetIoErr

	tst.l	(ARG_FORCE,a3)
	bne.b	.force1

	moveq	#RETURN_WARN,d7
	cmp.l	#BLIZKICK_ID,$01000000+IDOFFS Test for kicked ROM.
	beq	.exit
	moveq	#RETURN_ERROR,d7

.force1	move.l	(a3),a0			(ARG_KICKFILE,a3),a0
	cmp.b	#'*',(a0)
	bne.b	.not_pseudofile
	tst.b	(1,a0)
	bne.b	.not_pseudofile

	; Handle "*" -file:
	lea	$01000000+IDOFFS,a0	Will fail if kicked previously!
	cmp.l	#BLIZKICK_ID,(a0)	Test for kicked ROM.
	beq	.exit
	move.l	a0,a4
	move.l	-(a4),d3		a4=$01000000+ROMSIZEOFFS
	move.l	d3,d0
	moveq	#MEMF_PUBLIC,d1
	move.l	(_ExecBase,pc),a6
	call	AllocMem
	tst.l	d0
	beq	.exit
	move.l	a4,a0
	sub.l	d3,a0
	add.w	#-ROMSIZEOFFS,a0
	move.l	d0,a4
	move.l	a4,a1
	move.l	d3,d0
	call	CopyMemQuick
	move.l	d3,d1
	move.l	d3,d4
	bra.b	.cont_pseudo

.not_pseudofile
	bsr	XPKLoad
	beq	.exit
	move.l	a1,a4
	move.l	d1,d3
	move.l	d0,d4

.cont_pseudo	and.l	#$FFF3FFFF,d1		256K or 512K ROM
	bne	.free
	cmp.l	#$00080000,d3
	bhi	.free
	lea	ROMSUMOFFS(a4,d3.l),a5
	cmp.l	(4,a5),d3		Compare to romsize
	bne	.free

	move.l	(a4),d2
	and.l	#$FFF8FFFF,d2
	cmp.l	#$11104EF9,d2
	bne	.free
	move.l	(4,a4),d2		Test for relocated ROM
	add.l	d3,d2
	swap	d2
	cmp.w	#$0100,d2
	bne	.free

	move.l	a4,a0			Get original ROM checksum
	move.l	d3,d0
	bsr	ROMReSum
	lea	(_OrigSum,pc),a0
	move.l	d0,(a0)

	movem.l	($C,a4),d0/d1		Fix for old KS
	addq.l	#1,d0
	bne.b	.nofix
	move.l	d1,($C,a4)
.nofix
	tst.l	(ARG_FORCE,a3)
	bne.b	.force2

	moveq	#RETURN_WARN,d7
	lea	$01000000,a1
	move.l	a1,a0
	sub.l	(ROMSIZEOFFS,a0),a0
	move.l	($C,a0),d0		Test for different version.
	cmp.l	($C,a4),d0
	bne.b	.kick

	cmp.l	#BLIZKICK_ID,(8,a5)	Test for kicked file.
	beq.b	.free

.kick	moveq	#RETURN_ERROR,d7
.force2
	move.l	(_Quiet,pc),d0
	bne.b	.no_output
	lea	(Messu2,pc),a0
	lea	($C,a4),a1
	bsr	_Printf
	move.l	d6,a6
	moveq	#25,d1
	call	Delay
.no_output
	bsr.b	GoForIt

.free	move.l	(_ExecBase,pc),a6
	move.l	a4,a1
	move.l	d4,d0
	call	FreeMem

.exit	tst.l	d7
	bmi.b	.nexitok
	beq.b	.exitok
	bsr	_PrintFault		IN: d5=kickflag, d6=dosbase
	lea	(Already,pc),a0
	cmp.w	#RETURN_WARN,d7
	beq.b	.thiserr
	lea	(CouldNotKick,pc),a0
.thiserr	move.l	a3,a1
	bra	_Printf
.nexitok	neg.l	d7			result IN d7!!
.exitok	rts


GoForIt	;illegal

	neg.l	d7
	move.l	(_ExecBase,pc),a6

	move.l	(ARG_EXTRESBUF,a3),d0
	beq.b	.no_extbuf
	move.l	d0,a0
	move.l	(a0),d1

	move.l	#DEF_SANITY,d2
	move.l	(ARG_SANITY,a3),d0
	beq.b	.nosanity
	move.l	d0,a0
	move.l	(a0),d2
.nosanity	lsl.l	#8,d2
	lsl.l	#2,d2			*1024

	move.l	a4,a0
	move.l	d3,d0
	bsr	ExtResBuf
	bne.b	.got_extbuf
	bsr	_PrintFault		IN: d5=kickflag, d6=dosbase
	bra.b	.fail
.got_extbuf
.no_extbuf
	tst.l	(ARG_HOGWAITBLIT,a3)
	beq.b	.no_agawblit
	move.l	a4,a0
	move.l	d3,d0
	bsr	PutHogWaitBlit
.no_agawblit
	move.l	a4,a0
	move.l	d3,d0
	bsr	DoPlanting
	beq.b	.fail

	tst.l	(ARG_SPEEDROM,a3)
	beq.b	.no_patch2
	move.l	a4,a0
	move.l	d3,d0
	bsr	SpeedROM
.no_patch2

	move.l	a4,a0
	move.l	d3,d0
	bsr	LastPatches


	move.l	#BLIZKICK_ID,IDOFFS(a4,d3.l)
	move.l	a4,a0
	move.l	d3,d0
	bsr.b	ROMReSum
	move.l	d0,ROMSUMOFFS(a4,d3.l)
	bsr	CacheClearOS

	bsr	KickSys
.fail

;;	bra	FreeExtResBuf

;  IN: a6=execbase
; OUT: d0/d1/a0/a1 trashed
FreeExtResBuf
	move.l	(_erh_freeaddr,pc),d0
	beq.b	.xit
	move.l	d0,a1
	move.b	(_MemHeaderFlag,pc),d1
	beq.b	.xit
	call	Forbid
	lea	(_memhead,pc),a0
	bsr	FindMemHeader
	beq.b	.cantfind
	move.l	(_erh_alloclen,pc),d0
	call	Deallocate
.cantfind	call	Permit
	lea	(_erh_freeaddr,pc),a0
	clr.l	(a0)
.xit	rts


ROMReSum	move.l	d0,d1
	lsr.l	#2,d1
	move.l	ROMSUMOFFS(a0,d0.l),d0
	not.l	d0
.loop	add.l	(a0)+,d0
	bcc.b	.skip
	addq.l	#1,d0
.skip	subq.l	#1,d1
	bne.b	.loop
	not.l	d0
	rts



_restore	cmp.l	#BLIZKICK_ID,$01000000+IDOFFS	Test for kicked ROM.
	bne.b	.exitrts
	lea	$0B80000,a4		Magic address!
	move.l	(ROMSIZEOFFS,a4),d3
	move.l	d3,d0
	and.l	#$FFF3FFFF,d0		256K or 512K ROM
	bne.b	.exitrts
	cmp.l	#$00080000,d3
	bhi.b	.exitrts
	sub.l	d3,a4

	move.l	(a4),d0
	and.l	#$FFF8FFFF,d0
	cmp.l	#$11104EF9,d0
	bne.b	.exitrts

	lea	(_regtemp,pc),a0
	movem.l	d3/a4,(a0)
	moveq	#1,d0
	rts
.exitrts	moveq	#0,d0
	rts


getmmu	movem.l	d1-a6,-(sp)
	moveq	#0,d7

	move.l	(_mmubase,pc),d0
	bne.b	.use_mmulib

	move.l	(_ExecBase,pc),a6
	move.w	(AttnFlags,a6),d0
	btst	#AFB_68020,d0
	beq.b	.exit
	cmp.w	#37,(LIB_VERSION,a6)
	blo.b	.oldtest

	moveq	#-1,d7
	lea	(.test040plus,pc),a5
	btst	#AFB_68040,d0
	bne.b	.test
.oldtest	moveq	#1,d7
	lea	(.test020plus,pc),a5

.test	call	Disable
	call	Supervisor
	call	Enable

.exit	move.l	d7,d0
	movem.l	(sp)+,d1-a6
	rts


.use_mmulib	move.l	d0,a6	
	call	GetMMUType
	move.b	d0,d7
	bra.b	.exit


.test040plus	or.w	#$700,sr		Disable interrupts.
	movec	vbr,a0			Get VBR
	move.l	($10,a0),-(sp)		Save Illegal Instruction vector
	move.l	a0,-(sp)		Save VBR
	lea	(.illegal040,pc),a1
	move.l	a1,($10,a0)

	bsr	_fullflush040
	movec	tc,d0			$4e7a0003	Test some "common" MMU regs:
	movec	urp,d1			$4e7a1806	Test 040/060 MMU only reg!!
	movec	srp,d1			$4e7a1807	Test 040/060 MMU only reg!!
	nop
	nop
.exit040
	move.l	(sp)+,a0
	move.l	(sp)+,($10,a0)		Restore Illegal Instruction vector
	bsr	_fullflush040
	nop
	rte


	CNOP	0,4
.illegal040	moveq	#0,d7
	lea	(.exit040,pc),a0
	move.l	a0,(2,sp)
	bsr	_fullflush040
	nop
	rte


.test020plus	or.w	#$700,sr		Disable interrupts.

	movec	vbr,a0			Get VBR
	move.l	($10,a0),-(sp)		Save Illegal Instruction vector
	move.l	($2C,a0),-(sp)		Save F-Line Emul vector
	move.l	($E0,a0),-(sp)		Save MMU Config Error vector
	move.l	($E4,a0),-(sp)		Save MMU Illegal Operation Error vector
	move.l	($E8,a0),-(sp)		Save MMU Access Level Violation Error vector
	move.l	a0,-(sp)		Save VBR

	lea	(.mmuinstfailure,pc),a1
	move.l	a1,($10,a0)
	move.l	a1,($2C,a0)
	move.l	a1,($E0,a0)
	move.l	a1,($E4,a0)
	move.l	a1,($E8,a0)

	bsr	_flush020

	subq.l	#4,sp			Try to get TC
	dc.w	$F017,$4200		pmove.l tc,(sp)
.exitsuper
	addq.l	#4,sp
	move.l	(sp)+,a0		Restore VBR
	move.l	(sp)+,($E8,a0)		Restore MMU Access Level Violation Error vector
	move.l	(sp)+,($E4,a0)		Restore MMU Illegal Operation vector
	move.l	(sp)+,($E0,a0)		Restore MMU Config Error vector
	move.l	(sp)+,($2C,a0)		Restore F-Line Emul vector
	move.l	(sp)+,($10,a0)		Restore Illegal...
.exitall	bsr.b	_flush020
	nop
	rte

.mmuinstfailure	moveq	#0,d7
	lea	(.exitsuper,pc),a0	Invalid mmu instruction!
	move.l	a0,(2,sp)
	bsr.b	_flush020
	nop
	rte

_flush020	move.l	d0,-(sp)
	movec	cacr,d0
	or.w	#CACRF_ClearI!CACRF_ClearD,d0
	movec	d0,cacr
	move.l	(sp)+,d0
	rts


; runnommu -- run routine with mmu disabled
;
;  IN: a0=code to run in supervisor, mmu off. *MUST* return with rts!!
; OUT: d0=whatever values routine leaves to d0. cc's set accordingly.
;NOTE: only register guaranteed to be valid on return is d0
runnommu	movem.l	a5/a6,-(sp)
	move.l	(_mmubase,pc),-(sp)
	bne	.use_mmulib
	addq.l	#4,sp

	move.l	(_ExecBase,pc),a6
	lea	(.discode,pc),a5
	call	Disable
	call	Supervisor
	call	Enable
.exit	movem.l	(sp)+,a5/a6
	tst.l	d0
	rts
.discode	move.l	d0,-(sp)
	subq.l	#4,sp
	move.b	(_mmuflag,pc),d0
	beq.b	.nommua
	bmi.b	.is040a
	dc.w	$F017,$4200		pmove.l tc,(sp)
	clr.l	-(sp)
	dc.w	$F017,$4000		pmove.l	(sp),tc
	addq.l	#4,sp
	bsr	_flush020
	bra.b	.was030a
.is040a	bsr.b	_fullflush040
	movec	tc,d0
	move.l	d0,(sp)
	and.w	#$7F27,d0		E=%0, DCO=%00 DCI=%00
	movec	d0,tc
	bsr.b	_fullflush040
.was030a	move.l	(4,sp),d0
.nommua	nop
	jsr	(a0)
	move.l	d0,(4,sp)
	move.b	(_mmuflag,pc),d0
	beq.b	.nommub
	bmi.b	.is040b
	dc.w	$F017,$4000		pmove.l	(sp),tc
	bsr	_flush020
	bra.b	.nommub
.is040b	bsr.b	_fullflush040
	move.l	(sp),d0
	movec	d0,tc
	bsr.b	_fullflush040
.nommub	addq.l	#4,sp
	move.l	(sp)+,d0
	nop
	rte

.use_mmulib	move.l	(sp)+,a6
	move.l	a0,a5
	call	WithoutMMU
	bra.b	.exit


_fullflush040	FULLFLUSH040
	rts


TestBliz	movem.l	d1-a6,-(sp)
	moveq	#0,d7			"No Blizzard board with maprom"
	move.l	(_ExecBase,pc),a6

	bsr	.testblizppc
	bne	.exit_np

	lea	(.ExpName,pc),a1
	moveq	#33,d0
	bsr	OpenLib
	beq	.exit_np
	move.l	d0,a6

	lea	(.boards,pc),a2
	moveq	#0,d2
	moveq	#0,d6			clear maprom address lower...
.bfloop	moveq	#0,d0
	moveq	#0,d1
	move.w	(a2)+,d0		manufacturer
	bmi.b	.bfnomatch
	move.w	(a2)+,d1		product
	move.w	(a2)+,d6		maprom address, upper word
	move.l	(a2)+,d3		upper & lower ram area or -1
	sub.l	a0,a0
	call	FindConfigDev
	move.l	d0,d2
	beq.b	.bfloop
.bfnomatch	move.l	a6,a1
	move.l	(_ExecBase,pc),a6
	call	CloseLibrary
	tst.l	d2
	beq.b	.exit_np
	swap	d6			maprom address in d6
	move.l	d2,a0
	moveq	#0,d0
	move.b	(cd_Rom+er_Product,a0),d0

	lea	(_MK2,pc),a0
	cmp.w	#$19,d0
	seq	(a0)
	lea	(_B20x0,pc),a0
	cmp.w	#$18,d0
	seq	(a0)
	lea	(_PPC_MK3,pc),a0
	cmp.w	#$64,d0
	seq	(a0)

	move.l	d3,d0			upper & lower ram area for .csfindmemscan
	lea	(.blizfindmem,pc),a0
	addq.l	#1,d0
	beq.b	.skip			-1 it's blizzard!
	lea	(.csfindmem,pc),a0
.skip	call	Forbid
	lea	(MemList,a6),a5
	lea	(LH_TAIL,a5),a4
	jmp	(a0)

.exitsp
	move.l	d7,d0
.exit_known	call	Permit
.exit_np	tst.l	d0
	bne.b	.foundvalid
	lea	(_MemHeaderFlag,pc),a0
	clr.b	(a0)
.foundvalid	movem.l	(sp)+,d1-a6
	rts



.testblizppc	btst	#AFB_68040,(_AttnFlags+1,pc)
	beq	.pexit2

	lea	(.pidtag,pc),a1
	call	FindResident
	tst.l	d0
	bne.b	.foundit

	lea	(.nastyfind,pc),a0
	bsr	runnommu
	beq	.pexit2

.foundit	call	Forbid

	lea	(MemList,a6),a5
	lea	(LH_TAIL,a5),a4
.pscanloop	move.l	(a5),a5
	cmp.l	a5,a4
	beq	.pexit
	move.w	(MH_ATTRIBUTES,a5),d0
	and.w	#MEMF_POOLMEM!MEMF_PUBLIC!MEMF_CHIP!MEMF_FAST!MEMF_LOCAL!MEMF_24BITDMA,d0
	cmp.w	#MEMF_FAST!MEMF_PUBLIC,d0
	bne.b	.pscanloop
	tst.l	(LN_NAME,a5)
	bne.b	.pscanloop
	cmp.l	#$40000000,(MH_LOWER,a5)
	blo.b	.pscanloop
	move.l	(MH_UPPER,a5),d0
	cmp.l	#$80000000,d0
	bhs.b	.pscanloop
	and.l	#$0007FFFF,d0
	beq.b	.pfoundit

.pexit	call	Permit
.pexit2	moveq	#0,d0
	rts

.pfoundit	bsr.b	.foundmem

	call	Permit

	lea	(_BlizPPC,pc),a0
	st	(a0)

	move.l	#$FFF00000,d0
	rts


.nastyfind	lea	$F00020,a0		BlizzPPC flash is located here...
	move.l	#4000,d0		Must use .l!
	movem.l	(.pidtag,pc),d1-d4

.nf_find	cmp.l	(a0),d1
	bne.b	.nf_more
	cmp.l	(4,a0),d2
	bne.b	.nf_more
	cmp.l	(8,a0),d3
	bne.b	.nf_more
	cmp.l	(12,a0),d4
	bne.b	.nf_more

	moveq	#1,d0
	rts

.nf_more	addq.l	#1,a0
	subq.l	#1,d0
	bne.b	.nf_find
	rts

.pidtag	dc.b	'BlizzardPPC.IDTag',0
	CNOP	0,2


.foundmem	move.l	a5,a0			for Allocate_REVERSE
	lea	(_memhead,pc),a1
	moveq	#MH_FIRST,d0
	call	CopyMem
	lea	(_MemHeaderFlag,pc),a0
	st	(a0)
	rts


.blizfindmem
.trymore	sub.l	a3,a3
.scanloop	move.l	(a5),a5
	cmp.l	a5,a4
	beq	.exitsp
	move.w	(MH_ATTRIBUTES,a5),d0
	and.w	#MEMF_POOLMEM!MEMF_CHIP!MEMF_FAST!MEMF_PUBLIC,d0	Public fast?
	cmp.w	#MEMF_FAST!MEMF_PUBLIC,d0
	bne.b	.scanloop
	cmp.l	#$01000000,(MH_LOWER,a5)	32bit?
	blo.b	.scanloop
	move.l	(LN_NAME,a5),d0
	beq.b	.found
	move.l	d0,a2
	move.l	(a2),d0
	or.l	#$20202020,d0		To lowercase
	cmp.l	#'bliz',d0
	beq.b	.found
	tst.b	(a2)			null name -> buggy AllocMem result test!
	bne.b	.scanloop
.found
	bsr.b	.foundmem

	move.l	(MH_UPPER,a5),a3

	move.l	a3,d0			Test for MapROM:
	beq.b	.exit
	and.l	#$0007FFFF,d0
	bne.b	.exit
	move.l	a3,d0
	and.l	#$00080000,d0
	beq.b	.exit

	move.l	d6,d0			"known"?
	bne	.exit_known

	move.l	a3,a2
	add.l	#$80000-4,a2
	lea	$00F80000+$80000-4,a1

	lea	(.testcode,pc),a0
	bsr	runnommu
	beq.b	.exit
	move.l	a3,d7
.exit	tst.l	d7
	beq	.trymore
	bra	.exitsp


.is_mk2	sub.l	a3,a3
	move.l	#$08000000,d1		these values were fooked
	move.l	#$10000000,d2
.mk2scanloop	move.l	(a5),a5
	cmp.l	a5,a4
	beq	.exitsp
	move.w	(MH_ATTRIBUTES,a5),d0
	and.w	#MEMF_POOLMEM!MEMF_CHIP!MEMF_FAST!MEMF_PUBLIC,d0	Public fast?
	cmp.w	#MEMF_FAST!MEMF_PUBLIC,d0
	bne.b	.mk2scanloop
	cmp.l	(MH_LOWER,a5),d1
	blo.b	.mk2scanloop
	cmp.l	(MH_UPPER,a5),d2
	blo.b	.mk2scanloop		this condition was fooked

	bsr	.foundmem

	move.l	(MH_UPPER,a5),d0
	move.l	#$80000,d1
	move.l	d0,d2
	and.l	d1,d2
	bne.b	.mk2skip
	sub.l	d1,d0
.mk2skip	move.l	d0,d7
	bra	.exitsp



.csfindmem	move.b	(_MK2,pc),d0
	bne.b	.is_mk2

.cstrymore	sub.l	a3,a3
.csscanloop	move.l	(a5),a5
	cmp.l	a5,a4
	beq	.exitsp
	move.w	(MH_ATTRIBUTES,a5),d0
	and.w	#MEMF_POOLMEM!MEMF_CHIP!MEMF_FAST!MEMF_PUBLIC,d0	Public fast?
	cmp.w	#MEMF_FAST!MEMF_PUBLIC,d0
	bne.b	.csscanloop
	swap	d3
	cmp.w	(MH_LOWER,a5),d3
	blo.b	.csscanloop
	swap	d3
	cmp.w	(MH_UPPER,a5),d3
	blo.b	.csscanloop

	bsr	.foundmem

	move.l	(MH_UPPER,a5),a3

	move.l	a3,d0			Test for MapROM:
	beq.b	.csexit
	and.l	#$0007FFFF,d0
	bne.b	.csexit

	move.l	d6,d0			"known"?
	bne	.exit_known

	move.b	(_B20x0,pc),d0
	beq.b	.no20x0a

	cmp.w	#$0800,(MH_LOWER,a5)	Test for $08000000 mem.
	bne.b	.csexit
	move.l	a3,a2
	lea	(.testcode20x0,pc),a0
	bsr	runnommu
	beq.b	.csexit
.no20x0a
	move.l	a3,d7

.csexit	tst.l	d7
	beq	.cstrymore
	bra	.exitsp


; a1=ROM, a2=RAM
.testcode	or.w	#$700,sr		Disable interrupts
	move.l	(a2),d1
	cmp.l	(a1),d1
	bne.b	.exite
	not.l	d1
	move.l	d1,(a2)
	bsr.b	.cacheclr
	cmp.l	(a1),d1
	bne.b	.exite
	not.l	d1
	move.l	d1,(a2)
	bsr.b	.cacheclr
	moveq	#1,d0
	rts
.exite	moveq	#0,d0
	rts

.cacheclr	btst	#AFB_68020,(_AttnFlags+1,pc)
	bne	CacheClrS
	rts

; a1=ROM, a2=RAM
.testcode20x0
	or.w	#$700,sr		Disable interrupts
	moveq	#0,d4

	movec	dfc,d0
	move.l	d0,-(sp)
	moveq	#3,d0			Entry FC for Control Registers (also num of areas-1)
	movec	d0,dfc
	bsr.b	.cacheclr
.tcloop	moveq	#0,d1
	bsr	SetMemShadow

	bsr.b	.cacheclr
	nop
	move.l	(a2),d2
	move.l	d2,-(sp)
	eor.l	#$BADC0DE5,d2
	move.l	d2,(a2)
	nop
	bsr.b	.cacheclr
	move.l	(a2),d3
	move.l	(sp)+,(a2)
	nop
	bsr.b	.cacheclr
	cmp.l	d2,d3
	beq.b	.tcfound
	moveq	#1,d1
	bsr	SetMemShadow
	subq.l	#1,d0
	bpl.b	.tcloop

.tcexit	move.l	(sp)+,d0
	movec	d0,dfc
	bsr.b	.cacheclr
	move.l	d4,d0
	rts

.tcfound	lea	(_B20x0Bank,pc),a0	Self Modifying Code! MUST
	move.b	d0,(a0)			clear caches (.cacheclr does it)
	moveq	#1,d1
	bsr.b	SetMemShadow		Uses d0!
	moveq	#1,d4
	bra.b	.tcexit



BITEM	MACRO
	dc.w	\2,\3,\1
	dc.l	\4
	ENDM

.boards	BITEM $0000,BLIZPROD,$18,$08001000	18 2040-ERC/2060
	BITEM $0000,BLIZPROD,$0C,0		0C Cyberstorm MKI
	BITEM $0000,BLIZPROD,$19,0		19 Cyberstorm MKII
	BITEM $FFF0,BLIZPROD,$64,$08002000	64 Cyberstorm MKIII / PPC
	BITEM $4FF8,BLIZPROD,$11,-1		11 1230-IV / 1260 / 1240-T/ERC
	BITEM $1EF8,BLIZPROD,$0D,-1		0D 1230-III
	BITEM $0FF8,BLIZPROD,$0B,-1		0B 1230-II
;;	BITEM $????,BLIZPROD,$??,-1		0? 1230-I
	dc.w	-1


.ExpName	dc.b	'expansion.library',0
	CNOP	0,2


;
; This one is from old CyberMap I think...
; Modified a bit.
;
;*********************************************************
;*       writes memshadowregister of the given rambank
;*       setmemshadow(D0=bank,D1=on/off (bool))
;*********************************************************
;*       $ 8    2    c
;*       %100x yy10 1100 ---- ---- ---- ---- ----Shadow Register Format
;*					x = Set/Clr Flag  0=on 1=off
;*					y = Bank Number
MEMSHWREG	EQU	$82C00000		Shadow Enable Control Register
SetMemShadowN	moveq	#0,d0			Self Modifying Code!! Must clear
_B20x0Bank	EQU	*-1			caches before calling SetMemShadowN!
; IN: d0=bank, d1=mode
SetMemShadow	movem.l	d0-d1/a0,-(sp)
	and.l	#3,d0			mask bank number
	ror.l	#6,d0			shift in place
	or.l	#MEMSHWREG,d0		mask in MEMSHWREG adr
	tst.l	d1
	bne.b	.sf_skip		=! 0 -> TRUE -> b28=0
	bset	#28,d0			== 0 -> FALSE -> b28=1
.sf_skip	move.l	d0,a0			Write Register
	moves.l	a0,(a0)
	movem.l	(sp)+,d0-d1/a0
;;	rts
	bra	_fullflush040



; FindMemHeader - find memheader even if it has moved by PoolMem
; MUST call this in Forbid()! Use returned memheader before Permit()!
;
;  IN: a0=clone of MH (up to MH_FIRST) to find
;      a6=execbase
; OUT: a0=memheader or NULL, Z flag set
;
FindMemHeader	movem.l	d0-d3/a1,-(sp)
	moveq	#0,d0

	move.w	(MH_ATTRIBUTES,a0),d1
	move.w	(LN_TYPE,a0),d2
	move.l	(LN_NAME,a0),d3

	lea	(MemList,a6),a0
	lea	(LH_TAIL,a0),a1
.find	move.l	(a0),a0
	cmp.l	a0,a1
	beq.b	.fail
	cmp.w	(MH_ATTRIBUTES,a0),d1
	bne.b	.find
	cmp.w	(LN_TYPE,a0),d2		type & pri
	bne.b	.find
	cmp.l	(LN_NAME,a0),d3
	bne.b	.find

.exit	move.l	a0,d0
	movem.l	(sp)+,d0-d3/a1
	rts

.fail	sub.l	a0,a0
	bra.b	.exit



;  IN: a0=rom, d0=rom len
; OUT: d0=success, fail if no AGA or WaitBlit func couln't be found
PutHogWaitBlit	movem.l	d1-a6,-(sp)
	moveq	#0,d7

	cmp.w	#39,($C,a0)		Requires rom 39+
	blo.b	.exit

	lea	-4(a0,d0.l),a1

	move.w	$DFF004,d0		Test AGA:
	and.w	#$7F00,d0
	lsr.w	#8,d0
	bclr	#4,d0
	cmp.b	#$22,d0
	beq.b	.aga
	cmp.b	#$23,d0
	bne.b	.exit
.aga
	move.l	#$08390006,d0
.find	addq.l	#2,a0
	cmp.l	a1,a0
	beq.b	.exit
	cmp.l	(a0),d0
	bne.b	.find
	cmp.l	#$00DFF002,(4,a0)
	bne.b	.find
	cmp.l	#$66024E75,(8,a0)
	bne.b	.find

	cmp.l	#$08390006,(-8,a0)	No KS 1.x!
	beq.b	.exit
	cmp.l	#$4A3900DF,(-6,a0)	KS 2.x/3.x:
	bne.b	.exit
	subq.l	#6,a0
	lea	(.waitblit,pc),a1
	moveq	#(.waitblitend-.waitblit)/2,d0
.copy	move.w	(a1)+,(a0)+
	subq.l	#1,d0
	bne.b	.copy
	moveq	#1,d7

.exit	move.l	d7,d0
	movem.l	(sp)+,d1-a6
	rts

	; 1.x  36 bytes
	; 2.05 40 bytes
	; 3.0  48 bytes
	; 3.1  48 bytes
.waitblit	btst	#DMAB_BLTDONE-8,$DFF000+dmaconr			8
	bne.b	.gowait						2
	rts							2
.gowait	move.l	a0,-(sp)					2
	lea	($DFF000+dmaconr),a0				6
	move.w	#DMAF_SETCLR!DMAF_BLITHOG,(dmacon-dmaconr,a0)	6
.wait	btst	#DMAB_BLTDONE-8,(a0)				4
	bne.b	.wait						2
	move.w	#DMAF_BLITHOG,(dmacon-dmaconr,a0)		6
	move.l	(sp)+,a0					2
	rts							2 =42
	IFGT	0
.gowait	move.w	#DMAF_SETCLR!DMAF_BLITHOG,$DFF000+dmacon	8
.wait	btst	#DMAB_BLTDONE-8,$DFF000+dmaconr	8
	bne.b	.wait				2
	move.w	#DMAF_BLITHOG,$DFF000+dmacon	8
	rts					2 =40
	ENDC
.waitblitend
	IFGT	(.waitblitend-.waitblit)-42
	FAIL	!! WAITBLIT routine too long !!
	ENDC



;  IN: a0=rom start (buf)
;      d0=rom len
;      a1=name
; OUT: d0=ptr to resident (buf) or NULL
FindResident	movem.l	d1-a6,-(sp)
	move.l	a1,a3

	move.l	d0,d4
	move.l	a0,a4

	moveq	#1,d6
	lea	(_erh_arealen,pc),a0
	move.l	(a0)+,d0
	beq.b	.try_rom

	move.l	(a0),a0
	sub.l	a5,a5			Difference=0

.findres	moveq	#RT_SIZE-2,d1
	sub.l	d1,d0
	move.w	#RTC_MATCHWORD,d1
.find	subq.l	#2,d0
	bls.b	.try_rom
	cmp.w	(a0)+,d1
	bne.b	.find
	moveq	#2,d2
	add.l	(a0),d2			(RT_MATCHTAG-2,a0),d2
	add.l	a5,d2
	cmp.l	a0,d2
	bne.b	.find
	move.l	(RT_NAME-2,a0),a1
	add.l	a5,a1
	move.l	a3,a2
.compare	cmpm.b	(a2)+,(a1)+
	bne.b	.find
	tst.b	(-1,a2)
	bne.b	.compare

	move.l	a0,d0
	subq.l	#2,d0

.exit	movem.l	(sp)+,d1-a6
	rts

.exit_nf	moveq	#0,d0
	bra.b	.exit

.try_rom	tst.l	d6
	beq.b	.exit_nf

	move.l	d4,d0
	move.l	a4,a0

	move.l	#$01000000,d1
	sub.l	d0,d1			d2=rom start (rom)
	move.l	a0,a5
	sub.l	d1,a5			a5=difference

	moveq	#0,d6
	bra.b	.findres


PATHBUF_SIZE	EQU	256

;  IN: a0=ptr to rom (buf), d0=rom len, a3=array  (d6=dosbase)
; OUT: d0=success, will print doserror if failed
DoPlanting	movem.l	d1-a6,-(sp)
	lea	(-PATHBUF_SIZE,sp),sp
	move.l	sp,a5
	move.l	d6,a6

	move.l	d0,d1
	move.l	(ARG_MODULE,a3),d0
	beq	.exit			OK! ;-)
	move.l	d0,a2

	IFND	NEW_ENV_METHOD
	moveq	#0,d3
	ENDC
	moveq	#0,d4			null!
	cmp.w	#37,(LIB_VERSION,a6)
	blo	.not20

	IFD	NEW_ENV_METHOD

	movem.l	d1-d3/a0,-(sp)
	sub.l	a1,a1
	move.l	(_ExecBase,pc),a6
	call	FindTask
	move.l	d6,a6
	move.l	d0,a0
	lea	(pr_WindowPtr,a0),a0
	move.l	(a0),-(sp)
	move.l	a0,-(sp)
	moveq	#-1,d0
	move.l	d0,(a0)

	lea	(_VarName,pc),a0
	move.l	a0,d1
	move.l	a5,d2
	move.l	#PATHBUF_SIZE,d3	d4=0
	call	GetVar
	addq.l	#1,d0
	bne.b	.gotvar
	lea	(_VarEnvArcName,pc),a0
	move.l	a0,d1
	call	GetVar
	addq.l	#1,d0
	bne.b	.gotvar

	lea	(_VarEnvArcName,pc),a0
	move.l	a0,d1
	move.l	#MODE_OLDFILE,d2
	call	Open
	move.l	d0,d4			d4=0 if failed, no dirlock
	beq.b	.novar
	move.l	d4,d1
	move.l	a5,d2
	subq.l	#1,d3			#PATHBUF_SIZE-1
	call	Read
	move.l	d0,d2
	move.l	d4,d1
	call	Close
	tst.l	d2
	bmi.b	.novar
	clr.b	0(a5,d2.l)		null terminate
	move.l	a5,a0			strip linefeeds
.filt_loop	move.b	(a0)+,d0
	beq.b	.filt_end
	cmp.b	#10,d0
	bne.b	.filt_loop
	clr.b	-(a0)
.filt_end
.gotvar
	move.l	a5,d1
	bsr	_lockread
	beq.b	.nolock
	move.l	d1,d4
	call	CurrentDir
	move.l	d0,d7			oldlock
.nolock
.novar
	move.l	(sp)+,a0
	move.l	(sp)+,(a0)

	movem.l	(sp)+,d1-d3/a0
.not20

	ELSE

	movem.l	d1-d2/a0,-(sp)
	sub.l	a1,a1
	move.l	(_ExecBase,pc),a6
	call	FindTask
	move.l	d6,a6
	move.l	d0,a0
	lea	(pr_WindowPtr,a0),a0
	move.l	(a0),-(sp)
	move.l	a0,-(sp)
	moveq	#-1,d0
	move.l	d0,(a0)

	lea	(_EnvName,pc),a0
	move.b	#':',(3,a0)
	move.l	a0,d1
	bsr	_lockread
	move.l	d0,d2
	call	UnLock
	move.l	(sp)+,a0
	move.l	(sp)+,(a0)
	tst.l	d2
	bne.b	.has_env

	lea	(_EnvArcName,pc),a0
	move.l	a0,d1
	bsr	_lockread
	beq.b	.no_envarclock
	move.l	d0,d2
	lea	(_EnvName,pc),a0
	clr.b	(3,a0)
	move.l	a0,d1
	call	AssignLock
	move.l	d0,d3			d3=assignstate
	bne.b	.got_assign
	move.l	d2,d1
	call	UnLock
.got_assign
.no_envarclock
.has_env
	lea	(_VarName,pc),a0
	move.l	a0,d1
	move.l	a5,d2
	move.l	d3,-(sp)
	move.l	#PATHBUF_SIZE,d3	d4=0
	call	GetVar
	move.l	(sp)+,d3
	addq.l	#1,d0
	beq.b	.novar
	move.l	a5,d1
	bsr	_lockread
	beq.b	.nolock
	move.l	d0,d4
	move.l	d4,d1
	call	CurrentDir
	move.l	d0,d7			oldlock
.nolock
.novar	movem.l	(sp)+,d1-d2/a0
.not20
	ENDC

.loop	move.l	(a2)+,d0
	beq.b	.exit2
	move.l	d0,a1
	move.l	d1,d0
	bsr.b	FilePlant
	bne.b	.loop
	bsr	_PrintFault		IN: d5=kickflag, d6=dosbase
	lea	(PlantError,pc),a0
	move.l	a2,a1
	subq.l	#4,a1
	bsr	_Printf
	moveq	#-1,d0

.exit2	tst.l	d4
	beq.b	.nodirlock
	move.l	d0,-(sp)
	move.l	d7,d1
	call	CurrentDir
	move.l	d4,d1
	call	UnLock
	move.l	(sp)+,d0
.nodirlock
	IFND	NEW_ENV_METHOD

	tst.l	d3
	beq.b	.noassign
	move.l	d0,d7
	lea	(_EnvName,pc),a0
	clr.b	(3,a0)
	move.l	a0,d1
	moveq	#0,d2
	call	AssignLock
	move.l	d7,d0
.noassign
	ENDC

.exit	not.l	d0
	lea	(PATHBUF_SIZE,sp),sp
	movem.l	(sp)+,d1-a6
	rts

_lockread	moveq	#ACCESS_READ,d2
	call	Lock
	move.l	d0,d1
	rts

;  IN: a1=ptr to filename, a0=ptr to rom (buf), d0=rom len  (d6=dosbase)
; OUT: d0=success
FilePlant	movem.l	d1-a6,-(sp)
	move.l	d6,a6
	moveq	#0,d7

	lea	(.data,pc),a4
	movem.l	d0/a0,(a4)

	move.l	a1,d1
	call	LoadSeg
	move.l	d0,d5
	beq.b	.exit

	move.l	d5,a1
	add.l	a1,a1
	addq.l	#2,a1			;-)
	add.l	a1,a1
	movem.l	(a4),d0/a0
	bsr	InstallModule
	move.l	d0,d7
	bne.b	.was_module

	; try direct executable planting

	cmp.l	#BKMODULE_ID,(a1)	was it a module that failed?
	beq.b	.was_module		yes, quit!

	; the test above is really needed or else horrors
	; would happen. namely installing non-functional
	; resident tag that would crash system.

	move.l	(8*4,sp),d1		filename from stack
	move.l	#MODE_OLDFILE,d2
	call	Open
	move.l	d0,d4
	beq.b	.exit

	lea	(.af_dosbase,pc),a0
	move.l	a6,(a0)

	pea	(.freefunc,pc)
	pea	(.allocfunc,pc)
	pea	(.readfunc,pc)
	move.l	sp,a1
	clr.l	-(sp)
	move.l	sp,a2
	sub.l	a0,a0
	; d0=filehandle
	call	InternalLoadSeg
	lea	(4*4,sp),sp
	move.l	d0,d7

	move.l	d4,d1
	call	Close
	
.was_module	move.l	d5,d1
	beq.b	.exit
	call	UnLoadSeg
.exit	move.l	d7,d0
	movem.l	(sp)+,d1-a6
	rts



.data	ds.l	2

;  IN: d0=size, d1=flags
; OUT: d0=memory
.allocfunc	tst.l	d0
	bne.b	.af_do

.af_fail	move.l	a6,-(sp)
	move.l	(.af_dosbase,pc),a6
	moveq	#ERROR_NO_FREE_STORE,d1
	call	SetIoErr
	move.l	(sp)+,a6
	moveq	#0,d0
	rts

.af_do	btst	#MEMB_CHIP,d1		don't allow chipmem
	bne.b	.af_fail

	movem.l	d0/d1,-(sp)
	move.l	(_erh_memheader,pc),d0
	beq.b	.af_exit
	move.l	d0,a0
	move.l	(sp),d0
	call	Allocate
	tst.l	d0
	beq.b	.af_nomem
	; d0=return val

	; should clear allocated area?
	btst	#MEMB_CLEAR-16,(1,sp)
	beq.b	.af_exit

	; get original alloc req and align it
	move.l	(sp),d1
	addq.l	#MEM_BLOCKMASK,d1
	and.w	#-MEM_BLOCKSIZE,d1

	move.l	d0,a0
.af_clear	clr.l	(a0)+
	clr.l	(a0)+
	subq.l	#8,d1
	bne.b	.af_clear

.af_exit	addq.l	#8,sp
	rts

.af_nomem	addq.l	#8,sp
	bra.b	.af_fail

.af_dosbase	ds.l	1


;  IN: a1=memory d0=size
; OUT: -
.freefunc	tst.l	d0
	bne.b	.ff_do
.ff_no	rts
.ff_do	move.l	a1,d1
	beq.b	.ff_no

	move.l	(_erh_memheader,pc),d1
	beq.b	.ff_no

	movem.l	d0/a1,-(sp)
	move.l	a1,d1
	and.w	#-MEM_BLOCKSIZE,d1
	exg	d1,a1
	addq.l	#MEM_BLOCKMASK,d0
	sub.l	a1,d1
	add.l	d1,d0
	moveq	#-1,d1
	and.l	#-MEM_BLOCKSIZE,d0	note: .l!!
	beq.b	.ff_nofill
.ff_fill	move.l	d1,(a1)+
	move.l	d1,(a1)+
	subq.l	#8,d0
	bne.b	.ff_fill
.ff_nofill	movem.l	(sp)+,d0/a1

	move.l	(_erh_memheader,pc),a0
	jmp	(_LVODeallocate,a6)

;  IN: d1=fh, d2=buffer, d3=len
; OUT: d0=actual
.readfunc	jmp	(_LVORead,a6)



;  IN: d1.l=error (d6=dosbase)
SetIoErr	movem.l	d0-d1/a0-a1/a6,-(sp)
	move.l	d6,a6
	cmp.w	#36,(LIB_VERSION,a6)
	blo.b	.old
	call	SetIoErr
	bra.b	.exit
.old	move.l	(_ExecBase,pc),a6
	sub.l	a1,a1
	call	FindTask
	move.l	d0,a0
	move.l	(4,sp),(pr_Result2,a0)
.exit	movem.l	(sp)+,d0-d1/a0-a1/a6
	rts


;  IN: a1=ptr to module, a0=ptr to rom (buf), d0=rom len  (d6=dosbase)
; OUT: d0=success, d1/a0/a1 preserved
InstallModule	movem.l	d1-a6,-(sp)
	moveq	#0,d7
	move.l	#ERROR_OBJECT_WRONG_TYPE,d1
	bsr.b	SetIoErr

	move.l	#$01000000,d2
	sub.l	d0,d2
	move.l	a0,a5
	sub.l	d2,a5			a5=difference

	cmp.l	#BKMODULE_ID,(a1)+	(bkm_ID)
	bne.b	.exit
	move.w	(a1)+,d4		d4=bkm_Flags, a1=bkm_ResTag
	move.w	d4,d1
	and.w	#~BKMF_ALL,d1		Test validity:
	bne.b	.exit
	cmp.w	#BKEP_ID,(a1)		Test for patch module:
	beq	.is_epatch
	cmp.l	#RTC_MATCHWORD<<16,(a1)
	bne.b	.exit

	move.l	#ERROR_OBJECT_TOO_LARGE,d1
	bsr.b	SetIoErr

	lea	(.replace_test,pc),a3
	lsr.w	#1,d4			btst	#BKMB_ReplaceMode,d4
	bcs.b	.replace
	lea	(.single_test,pc),a3
	lsr.w	#1,d4			btst	#BKMB_SingleMode,d4
	bcc.b	.no_findresident
.replace	movem.l	d0/a1,-(sp)
	add.l	(RT_NAME,a1),a1
	bsr	FindResident
	move.l	d0,a2
	movem.l	(sp)+,d0/a1
	jmp	(a3)
.no_findresident
.is_single
.is_erbf	move.l	(RT_ENDSKIP,a1),d1
	lsr.w	#1,d4			btst	#BKMB_ExtResBuf,d4
	bcc.b	.no_extresbuf1
	neg.l	d1
.no_extresbuf1	bsr	FindSpace
	beq.b	.exit

.go_replace	move.l	d0,a3			a3=ptr to func (buf)
	move.l	d1,a2			a2=ptr to func (ROM)

	move.w	($C,a0),d1		d1=rom version
	move.l	a1,a0
	lea	(RT_VERSION,a0),a4
	cmp.b	(a4),d1			Test version!
	blo.b	.nofail
	move.b	d1,(a4)			Force current version!
	cmp.w	#36,d1
	shs	d1
	move.l	a3,a1			a2=ptr to func (ROM)
	bsr	PutResident

.nofail	moveq	#1,d7
.exit	move.l	d7,d0
.exit2	bsr	CacheClearOS		Clear caches.
	movem.l	(sp)+,d1-a6
	rts


.replace_test	beq.b	.exit			If no match exit!
	move.b	(RT_PRI,a2),d1
	cmp.b	(RT_PRI,a1),d1
	bne.b	.exit			If no match exit!

	lsr.w	#1,d4
	btst	#0,d4			btst BKMB_ExtResBuf,d4
	bne.b	.is_erbf

	move.l	(RT_ENDSKIP,a2),d1	d1=ptr to ENDSKIP (ROM)
	add.l	a5,d1			d1=ptr to ENDSKIP (buf)
	sub.l	a2,d1
	cmp.l	(RT_ENDSKIP,a1),d1
	ble.b	.exit
	move.l	a2,d0
	move.l	d0,d1
	sub.l	a5,d1
	bra.b	.go_replace


.single_test	beq.b	.is_single		SINGLE: If no match continue!
	move.b	(RT_PRI,a2),d1
	cmp.b	(RT_PRI,a1),d1
	bne.b	.is_single		SINGLE: If no match continue!
	move.l	#ERROR_TOO_MANY_ARGS,d1
	bsr	SetIoErr
	move.l	d0,d7
	bra.b	.exit

; a0=ptr to rom start (buf), a1=ptr to epatch, d0=rom len, d2=ptr to rom start (ROM)
.is_epatch	lea	(2,a1),a5
	move.l	d2,a1
	lea	(FindResident,pc),a2
	lea	(InstallModule,pc),a3
	lea	(_Printf,pc),a4
	move.l	(_ExecBase,pc),a6
	jsr	(a5)
	bra.b	.exit2


;  IN: a0=rom (buf), d0=rom len, d1=required space (negate if ExtResBuf required)
; OUT: d0=ptr to area (buf) or NULL, d1=ptr to area (rom)
;NOTE: condition codes set on return!
FindSpace	movem.l	d2-d3/d6-d7/a0-a2,-(sp)
	moveq	#0,d7

	move.l	#$01000000,d2
	sub.l	d0,d2
	move.l	a0,d6
	sub.l	d2,d6			d6=difference (buf-rom)

	tst.l	d1
	bmi.b	.required_extres

	lea	ROMSUMOFFS(a0,d0.l),a1
	bsr.b	.find
	bhs.b	.found			Big enough 'empty' space.

	move.l	#$00040000,d2
	cmp.l	d2,d0			Test for >$40000 ROM
	bls.b	.try_extres

	lea	(a0,d0.l),a1
	sub.l	d2,a1			a1=$FC0000
	move.l	(a1),d2
	and.l	#$FFF8FFFF,d2
	cmp.l	#$11104EF9,d2
	bne.b	.try_extres
	bsr.b	.find
	blo.b	.try_extres

.found	move.l	a1,d7
	addq.l	#1+3,d7
	and.w	#-4,d7

.exit	move.l	d7,d1
	sub.l	d6,d1
	move.l	d7,d0
	movem.l	(sp)+,d2-d3/d6-d7/a0-a2
	rts

.find	moveq	#-1,d2
.null	move.b	-(a1),d3
	addq.l	#1,d2
	not.b	d3
	beq.b	.null
	cmp.l	d1,d2
	rts

.required_extres
	neg.l	d1
.try_extres	move.l	(_erh_memheader,pc),d0
	beq.b	.exit
	move.l	d0,a0
	move.l	d1,d0
	move.l	a6,-(sp)
	move.l	(_ExecBase,pc),a6
	call	Allocate
	move.l	(sp)+,a6
	move.l	d0,d7
	moveq	#0,d6			NULL difference!
	bra.b	.exit


;  IN: a0=resident
;      a1=adr to "free" buf
;      a2=adr to "free" buf (rom)
;      d1.b=zero if <V36 ROM
PutResident	;bsr	CacheClearOS		336r: Added coz bad move16 optimized copymem patches?
	movem.l	d0-a6,-(sp)
	move.l	(_ExecBase,pc),a6
	lea	(RT_MATCHTAG,a1),a3
	lea	(4,a1),a4
	move.l	(RT_ENDSKIP,a0),d0
	call	CopyMem
	;bsr	CacheClearOS		336r: Added coz bad move16 optimized copymem patches?
	move.l	a2,d0
	move.l	d0,(a3)+		RT_MATCHTAG
	add.l	d0,(a3)+		RT_ENDSKIP
	tst.b	(4+3,sp)		V36+ ?
	bne.b	.no_incomp
	move.b	(a3),d1
	and.b	#~(RTF_AUTOINIT!RTW_COLDSTART),d1
	beq.b	.no_incomp
	and.b	#RTF_AUTOINIT!RTW_COLDSTART,(a3) Mask out incompatible bits
	or.b	#RTW_COLDSTART,(a3)
.no_incomp	move.b	(a3),d1
	addq.l	#RT_NAME-RT_FLAGS,a3
	add.l	d0,(a3)+		RT_NAME
	add.l	d0,(a3)+		RT_IDSTRING
	and.b	#RTF_AUTOINIT,d1
	beq.b	.noauto
	add.l	(a3),a4
	add.l	d0,(a4)+
	add.l	d0,(a4)+
	add.l	d0,(a4)+
.noauto	add.l	d0,(a3)+		RT_INIT
	movem.l	(sp)+,d0-a6
	rts


;  IN: a0=rom (buf), d0=rom len, d1=required buffer len, d2=sanity size
;      a6=execbase, d6=dosbase
; OUT: d0=ptr to extres buffer or NULL
ExtResBuf	movem.l	d0-a6,-(sp)
	moveq	#0,d7

	move.l	d0,d5			d5=rom len
	move.l	a0,a5			a0=buf strt

	move.l	#ERROR_OBJECT_WRONG_TYPE,d1
	bsr	SetIoErr

	cmp.w	#37,($C,a5)		need 37+
	blo	.exit

	move.b	(_MemHeaderFlag,pc),d0
	beq	.exit

	; find exec.library resident tag

	move.l	a5,a0
	move.l	d5,d0
	lea	(.execname,pc),a1
	bsr	FindResident
	tst.l	d0
	beq	.exit

	move.l	d0,a3
	move.l	(RT_INIT,a3),d1

	;test if inside rom bounds?
	cmp.l	#$0f80000,d1
	blo	.exit
	cmp.l	#$1000000,d1
	bhs	.exit

	; generate ram buffer address
	sub.l	#$f80000,d1		-$f80000
	add.l	a5,d1			+buffer
	move.l	d1,a0

	moveq	#12,d4			skip 12 bytes
	cmp.l	#$41F900DF,(a0)		37.x
	beq.b	.use12
	moveq	#4,d4			skip 4 bytes
	cmp.w	#$41FA,(a0)		39.x/40.x
	bne	.exit
.use12	add.l	(RT_INIT,a3),d4

	move.l	#extreshandler_SIZEOF+ERHANDLER_SIZEOF+8+MH_SIZE+7,d0
	add.l	(1*4,sp),d0		d1 from stack
	and.w	#-8,d0			align by 8

	; use this to set up MH_UPPER, MH_FREE,
	; MC_BYTES, ScanEnd...
	move.l	d0,d2
	sub.l	#extreshandler_SIZEOF,d2

	; len for allocabs
	move.l	d0,d3

	; add sanity just in case (something in boot could alloc
	; MEMF_REVERSE overwriting us...)
	;
	; If user sees 80010000 alert he/she should increase
	; SANITY

	add.l	#$90000,d0		add 576k... (internal sanity)
	add.l	(2*4,sp),d0		d2 from stack

	lea	(_erh_alloclen,pc),a0
	move.l	d0,(a0)

	call	Forbid
	lea	(_memhead,pc),a0
	bsr	FindMemHeader
	beq	.cantfind
	bsr	Allocate_REVERSE
	;call	Allocate
	call	Permit
	lea	(_erh_freeaddr,pc),a0
	move.l	d0,(a0)
	beq	.exit

	move.l	d0,a2
	move.l	d0,a1
	addq.l	#8,a2			jump over two longs

	lea	(extreshandler,pc),a0
	moveq	#extreshandler_SIZEOF,d0
	call	CopyMem

	lea	(extreshandler_SIZEOF-8,a2),a0
	move.l	a0,d0

	lea	(_erh_memheader,pc),a1
	move.l	a0,(a1)
	lea	(MH_SIZE,a0),a1
	clr.l	(a0)+			LN_SUCC
	clr.l	(a0)+			LN_PRED
	move.w	#NT_MEMORY<<8,(a0)+	LN_TYPE, LN_PRI
	clr.l	(a0)+			LN_NAME
	clr.w	(a0)+			MH_ATTRIBUTES
	move.l	a1,(a0)+		MH_FIRST
	move.l	a1,(a0)+		MH_LOWER
	add.l	d2,d0			d0 = a1 - (MH_SIZE+8) + size
	move.l	d0,(a0)+		MH_UPPER
	moveq	#-(MH_SIZE+8),d0
	add.l	d2,d0
	move.l	d0,(a0)+		MH_FREE
	move.l	a0,d7
	clr.l	(a0)+			MC_NEXT
	move.l	d0,(a0)+		MC_BYTES

	subq.l	#8,d0
	moveq	#-1,d1
.fill	move.l	d1,(a0)+
	move.l	d1,(a0)+
	subq.l	#8,d0
	bne.b	.fill


	move.l	a2,d0
	lea	(allocpt+2,pc),a0
	subq.l	#8,d0
	move.l	d0,(a0)
	lea	(alloclen+2,pc),a0
	move.l	d3,(a0)

	move.l	d7,(scanstartoffs-8,a2)
	lea	(_erh_areastart,pc),a0
	move.l	d7,(a0)
	moveq	#-(MH_SIZE+8),d0
	add.l	d2,d0
	lea	(_erh_arealen,pc),a0
	move.l	d0,(a0)
	add.l	d7,d0
	move.l	d0,(scanendoffs-8,a2)
	move.l	d4,(jumpoffs+2-8,a2)
	move.l	a2,(RT_INIT,a3)


	move.l	a5,a0			a0=ptr to rom (buf)
	move.l	d5,d0			d0=rom len
	lea	(_erhandler_module,pc),a1
	bsr	InstallModule
	tst.l	d0
	bne.b	.exit

	bsr	FreeExtResBuf
	moveq	#0,d7


.exit	move.l	d7,d0
	addq.l	#4,sp
	movem.l	(sp)+,d1-a6
	rts

.cantfind	call	Permit
	bra.b	.exit


.execname	dc.b	'exec.library',0
	CNOP	0,2

	; IN: a6=execbase
extreshandler	dc.l	0,0			don't trust 8 bytes we AllocAbs

	lea	(.areas,pc),a0
jumpoffs	EQU	*-extreshandler
	jmp	$badc0de


.areas	dc.l	$0F80000
	dc.l	$1000000
	dc.l	$0F00000
	dc.l	$0F80000
scanstartoffs	EQU	*-extreshandler
	dc.l	$c0ded
scanendoffs	EQU	*-extreshandler
	dc.l	$badd1e
	dc.l	-1

extreshandler_SIZEOF	EQU	(*-extreshandler+7)&-8




;  IN: a0=memHeader, d0=byteSize, a6=execbase
; OUT: d0=memoryBlock or null
Allocate_REVERSE
	sub.l	a1,a1			; default
	jsr	(_LVOForbid,a6)
	move.l	(MH_FIRST,a0),d1
	beq.b	.fail

	; find last MH that matches out requirements
.findfree_r	move.l	d1,a0
	cmp.l	(MC_BYTES,a0),d0
	bhi.b	.findskip_r
	move.l	a0,a1
.findskip_r	move.l	(a0),d1			; MC_NEXT
	bne.b	.findfree_r

	; found any?
	move.l	a1,d1
	beq.b	.fail

	; allocate from it!
	move.l	(MC_BYTES,a1),d1
	sub.l	d0,d1
	and.w	#-8,d1
	add.l	d1,a1
	jsr	(_LVOAllocAbs,a6)
	jsr	(_LVOPermit,a6)
	tst.l	d0
	rts

.fail	jsr	(_LVOPermit,a6)
	moveq	#0,d0
	rts



	STRUCTURE BKERHSS,0
	STRUCT	BKERHSS_ss,SS_SIZE
	ULONG	BKERHSS_version
	UWORD	BKERHSS_unused0
	APTR	BKERHSS_memheader
	LABEL	BKERHSS_SIZEOF

_erhandler_module
 BK_MOD BKMF_SingleMode|BKMF_ExtResBuf,_erhandler_end,(RTF_COLDSTART)<<24!37<<16!NT_UNKNOWN<<8!104,_erh_name,_erh_name,_ERHandler
;
; IMPORTANT:
; priority is after `diag init' resident that adds memory to system
;

	; d0=0, a0=0, a6=execbase
_ERHandler	; reallocate EXTRESBUF
allocpt	lea	$deadc0de,a1
alloclen	move.l	#$cafecafe,d0
	call	AllocAbs
	tst.l	d0
	bne.b	.got

	; die horribe death
	move.l	#AT_DeadEnd!AG_NoMemory,d7
	call	Alert
.got

	; initialize EXTRES API...

	moveq	#BKERHSS_SIZEOF,d0
	moveq	#MEMF_ANY,d1
	call	AllocMem
	tst.l	d0
	beq.b	.nomem

	move.l	d0,-(sp)
	move.l	d0,a0
	call	InitSemaphore
	move.l	(sp)+,a1
	move.l	#ERH_API_V1,(BKERHSS_version,a1)
	clr.w	(BKERHSS_unused0,a1)

	; must not optimize this!
_erh_memheader	EQU	*+2
	move.l	#0,(BKERHSS_memheader,a1)

	lea	(_erh_name,pc),a0
	move.l	a0,(LN_NAME,a1)
	move.b	#-120,(LN_PRI,a1)

	call	AddSemaphore
.nomem
	; fall in!
	;bsr.b	MoveChipHeader
	;rts

; Routines taken from FastExec 2.5 public domain source code by
; Torbjörn A. Andersson. Modified by Harry Sintonen.
******************************************************************************

MoveChipHeader	movem.l	d2/a2-a3,-(sp)
	call	Forbid

.loop0	move.l	(MemList,a6),d2

.loop1	move.l	d2,a2
	move.l	(a2),d2
	beq.b	.quit

	cmp.l	#$1000000,a2		; address
	bhs.b	.loop1

	moveq	#MH_SIZE,d0
	moveq	#MEMF_PUBLIC!MEMF_FAST,d1
	call	AllocMem
	tst.l	d0
	beq.b	.quit
	move.l	d0,a3

	lea	(LN_TYPE,a2),a0		; source
	lea	(LN_TYPE,a3),a1		; dest
	moveq	#MH_SIZE-LN_TYPE,d0
	call	CopyMem

	lea	(MH_SIZE,a2),a0
	cmp.l	(MH_LOWER,a2),a0
	bne.b	.ok
	move.l	a2,(MH_LOWER,a3)
.ok
	move.l	a2,a1			; node
	call	Remove
	lea	(MemList,a6),a0		; list
	move.l	a3,a1			; node
	call	Enqueue

;	cmp.w	#36,(LIB_VERSION,a6)
;	blo.b	.loop0

	move.l	a2,a1			; memoryBlock
	moveq	#MH_SIZE,d0

	move.l	d0,d1
	add.l	a1,d1
	lea	(MemList,a6),a0
.floop	move.l	(a0),a0
	tst.l	(a0)
	beq.b	.fdone
	cmp.l	(MH_LOWER,a0),a1
	blo.b	.floop
	cmp.l	(MH_UPPER,a0),a1
	bhs.b	.floop
	cmp.l	(MH_UPPER,a0),d1
	bhi.b	.fdone
	call	FreeMem
.fdone	bra.b	.loop0

.quit	call	Permit
	movem.l	(sp)+,d2/a2-a3
	rts

_erh_name	dc.b	'EXTRES Handler',0
	CNOP	0,2
_erhandler_end
ERHANDLER_SIZEOF EQU	(*-_erhandler_module+7)&-8


CacheClearOS	movem.l	d0-d1/a0-a1/a6,-(sp)
	pea	(.cleanexit,pc)
	move.l	(_ExecBase,pc),a6
	cmp.w	#37,(LIB_VERSION,a6)
	blo.b	CacheClear
	jmp	(_LVOCacheClearU,a6)	OK! ;-)
.cleanexit	movem.l	(sp)+,d0-d1/a0-a1/a6
	rts
CacheClear	btst	#AFB_68020,(_AttnFlags+1,pc)
	beq.b	.no68020
	movem.l	a5/a6,-(sp)
	lea	(.cacheclrsv,pc),a5
	move.l	(_ExecBase,pc),a6
	call	Supervisor
	movem.l	(sp)+,a5/a6
.no68020	rts
.cacheclrsv	or.w	#$700,sr		Disable interrupts
	bsr.b	CacheClrS
	nop
	rte
CacheClrS	btst	#AFB_68040,(_AttnFlags+1,pc)
	beq.b	.not040
	CACHEFLUSH040
	rts
.not040	move.l	d0,-(sp)
	movec	cacr,d0
	or.w	#CACRF_ClearI!CACRF_ClearD,d0
	movec	d0,cacr
	move.l	(sp)+,d0
	rts

DisableCache	btst	#AFB_68020,(_AttnFlags+1,pc)
	beq.b	.no68020
	movem.l	a5/a6,-(sp)
	lea	(.discachesv,pc),a5
	move.l	(_ExecBase,pc),a6
	call	Supervisor
	movem.l	(sp)+,a5/a6
.no68020	rts
.discachesv	or.w	#$700,sr		Disable interrupts
	bsr.b	DisableCacheS
	nop
	rte
DisableCacheS	move.l	d0,-(sp)
	movec	cacr,d0

	btst	#AFB_68040,(_AttnFlags+1,pc)
	bne.b	.is040

	and.w	#~(CACRF_EnableI!CACRF_IBE!CACRF_EnableD!CACRF_DBE),d0
	or.w	#CACRF_ClearI!CACRF_ClearD,d0
	bra.b	.exit
.is040
	BITDEF	CACR,HalfICache,13		;060
	BITDEF	CACR,NoAllocateI,14		;040/060
	BITDEF	CACR,EnableICache,15		;040/060
	BITDEF	CACR,ClearUserBCache,21		;060
	BITDEF	CACR,ClearAllBCache,22		;060
	BITDEF	CACR,EnableBCache,23		;060
	BITDEF	CACR,HalfDCache,27		;060
	BITDEF	CACR,DisableCPUSHInv,28		;060?
	BITDEF	CACR,EnableStoreBuffer,29	;060
	BITDEF	CACR,NoAllocateD,30		;040/060
	BITDEF	CACR,EnableDCache,31		;040/060

CACRF_CachesOr040	EQU	CACRF_EnableDCache|CACRF_EnableICache
CACRF_CachesAnd040	EQU	CACRF_NoAllocateI|CACRF_NoAllocateD
CACRF_CachesOr060	EQU	CACRF_CachesOr040|CACRF_EnableStoreBuffer|CACRF_EnableBCache
CACRF_CachesAnd060	EQU	CACRF_CachesAnd040|CACRF_DisableCPUSHInv|CACRF_HalfICache|CACRF_HalfDCache

	BITDEF	PCR,EnableDebugFeatures,7	;060
	BITDEF	PCR,DisableFPU,1		;060
	BITDEF	PCR,EnableSuperScalar,0		;060

	and.l	#~CACRF_CachesOr060,d0
	or.l	#CACRF_ClearAllBCache,d0
	nop
	dc.w	$F4F8			CPUSHA	BC
	nop
.exit	movec	d0,cacr
	move.l	(sp)+,d0
	rts

; IN: a1=libname, d0=version, a6=execbase
FindLib	bsr.b	OpenLib
	beq.b	.exit
	move.l	d0,-(sp)
	move.l	d0,a1
	call	CloseLibrary
	move.l	(sp)+,d0
.exit	rts
; IN: a1=libname, d0=version, a6=execbase
OpenLib	move.w	#_LVOOldOpenLibrary,d1
	cmp.w	#33,(LIB_VERSION,a6)
	blo.b	.oldol
	move.w	#_LVOOpenLibrary,d1
.oldol	jsr	0(a6,d1.w)
	tst.l	d0
	rts


;  IN: a0=filename (d6=dosbase, _Printf)
; OUT: a1=buffer, d0=buffer len, d1=file len

XPKLoad	movem.l	d2-d7/a2-a6,-(sp)
	move.l	a0,a3
	sub.l	a5,a5
	moveq	#0,d6
	moveq	#0,d7

	move.l	(4*4,sp),a6
	move.l	a3,d1
;;	moveq	#ACCESS_READ,d2
;;	call	Lock
;;	move.l	d0,d1
	bsr	_lockread

	beq	.exit
	move.l	d1,-(sp)
	lea	(-(fib_SIZEOF+4),sp),sp
	move.l	sp,d2
	addq.l	#3,d2
	and.w	#-4,d2
	call	Examine
	move.l	d2,a0
	move.l	(fib_Size,a0),d3
	move.l	d0,d2
	lea	((fib_SIZEOF+4),sp),sp
	move.l	(sp)+,d1
	call	UnLock
	tst.l	d2
	beq.b	.exit

	move.l	a3,d1
	move.l	#MODE_OLDFILE,d2
	call	Open
	move.l	d0,d5
	beq.b	.exit

	move.l	d5,d1
	subq.l	#4,sp
	move.l	sp,d2
	move.l	d3,-(sp)
	moveq	#4,d3
	call	Read
	move.l	(sp)+,d3
	move.l	(sp)+,d4
	subq.l	#4,d0
	bne.b	.exit
	move.l	d5,d1
	moveq	#0,d2
	move.l	d3,-(sp)
	moveq	#OFFSET_BEGINNING,d3
	call	Seek
	move.l	(sp)+,d3
	subq.l	#4,d0
	bne.b	.exit
	cmp.l	#'XPKF',d4
	beq.b	.tryxpk

.noxpk	move.l	(_ExecBase,pc),a6
	move.l	d3,d0
	moveq	#MEMF_PUBLIC,d1
	call	AllocMem
	move.l	(4*4,sp),a6
	move.l	d0,d2
	beq.b	.close

	move.l	d5,d1
	call	Read
	cmp.l	d0,d3
	bne.b	.free

	move.l	d3,d7
	move.l	d3,d6
	move.l	d2,a5
	bra.b	.close

.free	move.l	(_ExecBase,pc),a6
	move.l	d2,a1
	move.l	d3,d0
	call	FreeMem
	move.l	(4*4,sp),a6

.close	move.l	d5,d1
	call	Close

.exit	move.l	a5,a1
	move.l	d6,d0
	move.l	d7,d1
	movem.l	(sp)+,d2-d7/a2-a6
	rts


.tryxpk	move.l	(_ExecBase,pc),a6
	lea	(.xpkname,pc),a1
	moveq	#0,d0
	bsr	OpenLib
	beq	.noxpk
	move.l	d0,d2

	move.l	(4*4,sp),a6
	move.l	d5,d1
	call	Close
	exg	d2,a6

XPKERRSIZE	EQU	((XPKERRMSGSIZE+1+3)&-4)

	lea	(-XPKERRSIZE,sp),sp
	move.l	sp,a4
	clr.l	-(sp)
	move.l	sp,d3
	clr.l	-(sp)
	move.l	sp,d4
	clr.l	-(sp)
	move.l	sp,d5
	clr.l	-(sp)
	moveq	#-1,d0
	move.l	d0,-(sp)
	pea	XPK_PassThru		Allow uncompressed file
	pea	MEMF_PUBLIC
	pea	XPK_OutMemType
	move.l	d5,-(sp)		buflen
	pea	XPK_GetOutBufLen
	move.l	d4,-(sp)		filelen
	pea	XPK_GetOutLen
	move.l	d3,-(sp)		outbuf
	pea	XPK_GetOutBuf
	move.l	a4,-(sp)		errbuf
	pea	XPK_GetError
	move.l	a3,-(sp)
	pea	XPK_InName
	move.l	sp,a0
	call	XpkUnpack
	move.l	d5,sp

	move.l	(sp)+,d6		d6=buflen
	move.l	(sp)+,d7		d7=filelen
	move.l	(sp)+,a5		a5=outbuf

	tst.l	d0
	beq.b	.allok
	; a4=errbuf
	move.l	a4,a0
.finde	tst.b	(a0)+
	bne.b	.finde
	move.b	#10,(-1,a0)
	clr.b	(a0)
	move.l	a4,a0
	exg	d2,d6
	bsr	_Printf
	exg	d2,d6

.allok	lea	(XPKERRSIZE,sp),sp

	move.l	a6,a1
	move.l	(_ExecBase,pc),a6
	call	CloseLibrary
	bra	.exit


.xpkname	dc.b	'xpkmaster.library',0
	CNOP	0,2





;  IN: a0=rom, d0=rom len
; OUT: d0=success (number of patches done, or zero)
LastPatches	movem.l	d1-a6,-(sp)
	moveq	#0,d7
	move.l	a0,a6
	move.l	d0,d6

SUPERVISOR_NOREVERSE	SET	0
	IFNE	SUPERVISOR_NOREVERSE
	move.w	#2048/2-1,d0		during first 2k
	move.l	#$2D40003A,d1
.scan	addq.l	#2,a0
	cmp.l	(a0),d1
	dbeq	d0,.scan
	tst.w	d0
	bmi.b	.not0
	cmp.l	#$6608223C,(4,a0)
	bne.b	.scan
	cmp.l	#MEMF_CLEAR!MEMF_REVERSE,(8,a0)
	bne.b	.scan
	cmp.w	#$60EC,(12,a0)
	bne.b	.scan

	move.w	#MEMF_CLEAR>>16,(8,a0)
	addq.l	#1,d7
.not0
	ENDC

	move.l	(_OrigSum,pc),d5
	cmp.l	ROMSUMOFFS(a6,d6.l),d5
	bne	.not_correct_chksum

	cmp.l	#33<<16!180,($C,a6)
	bne.b	.not_33180
	cmp.l	#$56F2E2A6,d5		Must be original to patch!
	bne.b	.not_33180

	move.w	#$0020,($19C,a6)	2MB chip ram
	move.l	#$FF000001,($3000,a6)	ExecBase address mask

	IFGT	0
	move.l	#$20482249,d0		move.l a0,a0 / move.l a1,a1
	move.l	d0,($4D9A,a6)		expansion.library bug
	move.l	#$4EAEFF3A,($4D9A+4,a6)
	move.l	#$4A80672E,($4D9A+8,a6)
	move.l	#$24002200,($4D9A+12,a6)
	move.l	#$20434280,($4D9A+16,a6)
	move.l	#$302F0002,($4D9A+20,a6)
	move.w	d0,($4D9A+24,a6)
	ENDC

	move.l	#$20482249,d0		move.l a0,a0 / move.l a1,a1
	move.w	d0,($4D9A,a6)		expansion.library bug
	move.l	d0,($4D9A+2,a6)
	move.l	#$4A80672C,($4DA4,a6)
	move.l	#$24002240,($4DA4+4,a6)
	move.l	#$20437000,($4DA4+8,a6)
	move.b	#$30,($4DA4+12,a6)

	; my:
	move.l	#$99CC4ED5,($1E6,a6)	no $C00000 mem, please !!
;;	clr.b	($56D,a6)		disable cache (instruction)

	addq.l	#1,d7
.not_33180

	cmp.l	#34<<16!5,($C,a6)
	bne.b	.not_3405
	cmp.l	#$15267DB3,d5		Must be original to patch!
	bne.b	.not_3405

	move.w	#$0020,($19C,a6)	2MB chip ram
	move.l	#$FF000001,($303C,a6)	ExecBase address mask

	addq.l	#1,d7
.not_3405

.not_correct_chksum

	move.l	d7,d0
	movem.l	(sp)+,d1-a6
	rts


;  IN: a0=rom, d0=rom len
; OUT: d0=success (number of patches done, or zero)
SpeedROM	movem.l	d1-a6,-(sp)

	moveq	#0,d7
	move.l	a0,a2
	move.l	d0,d4
	move.l	#$01000000,d2
	sub.l	d4,d2
	move.l	a2,a5
	sub.l	d2,a5			a5=difference

	move.l	(4,a2),a1
	add.l	a5,a1

	cmp.w	#$203C,(6,a1)		KS 1.x start: (34.5)
	bne.b	.nosp1
	cmp.l	#$53806EFC,(12,a1)
	bne.b	.nosp1
	move.w	#$6008,(6,a1)
	addq.l	#1,d7
.nosp1
	IFEQ	KEEP_CHECKSUM
	cmp.l	#$41F900F8,(4,a1)	KS 3.0 chksum:
	bne.b	.nosp2
	cmp.l	#$72FF7401,(10,a1)
	bne.b	.nosp2
	move.l	#$7AFF6010,(10,a1)
	addq.l	#1,d7
.nosp2
	cmp.l	#$41FAFF28,(4,a1)	KS 3.1 chksum:
	bne.b	.nosp3
	cmp.l	#$72FF7401,(8,a1)
	bne.b	.nosp3
	move.l	#$7AFF6010,(8,a1)
	addq.l	#1,d7
.nosp3
	ENDC

	; Reconnect resident modules:

	moveq	#-(RT_SIZE+2),d1
	move.l	a2,a0
	add.l	d4,d1
	sub.l	a1,a1
.find	subq.l	#2,d1
	bls.b	.done
	cmp.w	#RTC_MATCHWORD,(a0)+
	bne.b	.find
	moveq	#2,d0
	add.l	(a0),d0			(RT_MATCHTAG-2,a0),d0
	add.l	a5,d0
	cmp.l	a0,d0
	bne.b	.find
	subq.l	#2,a0
	move.l	a1,d0
	beq.b	.is_1st
	move.l	a0,d0
	sub.l	a5,d0
	move.l	d0,(RT_ENDSKIP,a1)
.is_1st	move.l	a0,a1
	lea	(RT_SIZE,a0),a0
	bra.b	.find
.done
	move.l	a1,d0
	beq.b	.none
	; make last RT_ENDSKIP point $FFFFFE
	move.l	#$FFFFFE,(RT_ENDSKIP,a1)
.none

	; can't really reconnect EXTRES buffer restags
	; ...

	addq.l	#1,d7

	move.l	d7,d0
	movem.l	(sp)+,d1-a6
	rts


	IFGT	0

; *** WARNING: REQUIRES SOURCE AND DESTINATION ADDRESSES ALIGNEG BY 16! ***

;  IN: a0=source ptr
;      a1=dest ptr
;      d0=copy len, aligned by 256
; OUT: a0=source ptr + copy len
;      a1=dest ptr + copy len
;      d0=copy len
copymem256_040	move.l	d0,-(sp)
	lsr.l	#8,d0			/256
.copy	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16

	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16

	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16

	subq.l	#1,d0
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	move16	(a0)+,(a1)+		16
	bne.b	.copy
	move.l	(sp)+,d0
	rts

	ENDC


;  IN: a0=source ptr
;      a1=dest ptr
;      d0=copy len, aligned by 256
; OUT: a0=source ptr + copy len
;      a1=dest ptr + copy len
;      d0=copy len
copymem256	movem.l	d0-d7/a2-a6,-(sp)
	lsr.l	#8,d0			/256
.copy	movem.l	(a0)+,d1-d7/a2-a6
	movem.l	d1-d7/a2-a6,(a1)	12*4=48
	movem.l	(a0)+,d1-d7/a2-a6
	movem.l	d1-d7/a2-a6,(1*48,a1)	12*4=48
	movem.l	(a0)+,d1-d7/a2-a6
	movem.l	d1-d7/a2-a6,(2*48,a1)	12*4=48
	movem.l	(a0)+,d1-d7/a2-a6
	movem.l	d1-d7/a2-a6,(3*48,a1)	12*4=48
	movem.l	(a0)+,d1-d7/a2-a6
	movem.l	d1-d7/a2-a6,(4*48,a1)	12*4=48
	movem.l	(a0)+,d1-d4
	movem.l	d1-d4,(5*48,a1)		4*4=16
	subq.l	#1,d0
	lea	(256,a1),a1
	bne.b	.copy
	movem.l	(sp)+,d0-d7/a2-a6
	rts

	;IFGT	(copymem256_000-copymem256)-$7E
	;FAIL	"copymem256 offset out of bra.b!"
	;ENDC


;  IN: a4=rom buffer
;      d3=rom size
KickSys	;illegal

	lea	(_regtemp,pc),a0
	movem.l	d3/a4,(a0)

	move.l	(_ExecBase,pc),a6
	lea	(GfxName,pc),a1
	moveq	#0,d0
	bsr	FindLib
	move.l	d0,a2
	exg	a2,a6
	sub.l	a1,a1
	call	LoadView
	call	WaitTOF
	cmp.w	#39,(LIB_VERSION,a6)
	blo.b	.noaga
	btst	#GFXB_AA_ALICE,(gb_ChipRevBits0,a6)
	beq.b	.noaga
	lea	$DFF106,a0
	move.w	#$0C00,(a0)		Reset AGA hardware.
	move.w	#$0000,($1FC-$106,a0)
.noaga	call	WaitTOF
	exg	a2,a6

	move.b	(_CPUCard,pc),d0
	bne	.mapcpucard

	lea	(.super,pc),a0
	bra	runnommu

.super	ori.w	#$700,sr		Disable all ints!
	bsr	CacheClrS		flush caches

	movem.l	(_regtemp,pc),d3/a4

	bset	#7,$DE0002		Set Gary Coldstart

	move.b	(_B20x0,pc),d0
	beq.b	.noB20x0a
	movec	dfc,d5
	moveq	#3,d0			Entry FC for Control Registers
	movec	d0,dfc
	moveq	#0,d1			Turn shadow off:
	bsr	SetMemShadowN
.noB20x0a
	move.b	(_PPC_MK3,pc),d0
	bne.b	.also_ppc_mk3
	move.b	(_BlizPPC,pc),d0
	beq.b	.no_blizppc1
	clr.b	$F60013			Turn off BlizPPC maprom
.also_ppc_mk3	nop
	nop
	move.b	#$10,$F60000		blizzppc/csppc/mkiii
	nop				majik
	nop
.no_blizppc1
	move.l	(_BlizROM,pc),a1

	move.l	#$80000,d0
	cmp.l	d0,d3
	bhs.b	.no1st

	move.l	d3,d0			Copy 256k:
	move.l	a4,a0
	bsr	copymem256
.no1st
	move.l	d3,d0			Copy ROM:
	move.l	a4,a0
	bsr	copymem256

	move.b	(_B20x0,pc),d0
	beq.b	.noB20x0b
	moveq	#1,d1			Turn shadow back on:
	bsr	SetMemShadowN
	movec	d5,dfc
	bsr	_fullflush040
.noB20x0b
	bsr	DisableCacheS		Disable all caches.

	move.b	(_MK2,pc),d0
	beq.b	.no_mk2
	move.b	#$2A,$880000E3		Trigger MKII maprom
	nop
	bra.b	.doreset
.no_mk2
	move.b	(_PPC_MK3,pc),d0
	beq.b	.no_ppc_mk3

	move.l	(_tc,pc),d0		restore mmu state for
	movec	d0,tc			a while...
	nop

	lea	$00F60020,a0		Trigger PPC/MKIII maprom
	move.b	#$60,(a0)
	nop
	move.b	#$50,(a0)
	nop
	move.b	#$30,(a0)
	nop
	move.b	#1,(-8,a0)
	nop
	clr.b	(a0)
	bra.b	.also_ppc_mk3b
.no_ppc_mk3
	move.b	(_BlizPPC,pc),d0
	beq.b	.no_blizppc2

	move.l	(_tc,pc),d0		restore mmu state for
	movec	d0,tc			a while
	nop

	clr.b	$F60012			Trigger BlizPPC maprom
.also_ppc_mk3b
	nop
	nop
	move.b	#$40,$F60018		blizzppc/csppc/mkiii
	move.b	#$0C,$F60000		majik
	nop
	nop

	movec	tc,d0			disable MMU again
	and.w	#$7FFF,d0
	movec	d0,tc
	nop
.no_blizppc2

.doreset	moveq	#-1,d0			Trash execbase:
	move.l	d0,(4).w
	bsr	CacheClrS		flush caches

	lea	$DFF09A,a0
	move.w	#$4000,(a0)+		All interrupts off
	move.w	#$3FFF,(a0)+		All DMA off

	nop

	lea	$01000000+4,a0		...and reboot...
	sub.l	(ROMSIZEOFFS-4,a0),a0
	move.l	(a0),a0
	subq.l	#2,a0
	IFGT	(Main-*)&2		Main must be longword aligned!
	move.l	a1,a1
	ENDC
.reset	reset
	jmp	(a0)


.mapcpucard	call	Forbid			Must be V37+ if got here
	bsr.b	cachecontroli

	lea	(.nommucpuc,pc),a0
	bra	runnommu

.nommucpuc	ori.w	#$700,sr		Lock All Irqs

	clr.b	$DE0000			Gary bootflags=ColdStart
	clr.b	$DE0001
	nop
	move.l	#1,$80F80000		Trigger maprom
	nop

	move.l	a4,a0			a0=ptr to ROM Image
	move.l	#$07F80000,a1		Copy ROM Image
	move.l	#$80000,d0
	bsr	copymem256

	move.b	#$80,$DE0000		Gary BootFlag=ColdBoot
	move.b	#$80,$DE0001

	bra	.doreset


cachecontroli	moveq	#CACRF_EnableI!CACRF_IBE,d0
cachecontrol	move.l	#~CACRF_WriteAllocate,d1
	jmp	(_LVOCacheControl,a6)

;  IN: -
; OUT: d0,cc=nonzero if CPU Card with MAPROM present, else zero
CheckCPUCard	movem.l	d7/a6,-(sp)
	moveq	#0,d7
	move.l	(_ExecBase,pc),a6
	cmp.w	#37,(LIB_VERSION,a6)
	blo.b	.exit
	call	Forbid

	bsr.b	cachecontroli
	move.l	d0,-(sp)

	lea	(.nommu,pc),a0
	bsr	runnommu
	move.l	d0,d7

	move.l	(sp)+,d0
	bsr.b	cachecontrol

	call	Permit
.exit	move.l	d7,d0
	movem.l	(sp)+,d7/a6
	rts

.nommu	ori.w	#$700,sr		Lock All Irqs
	moveq	#0,d2
	clr.b	$DE0000			Gary bootflags=ColdStart
	clr.b	$DE0001
	nop
	move.l	#1,$80F80000		Trigger maprom
	nop
	move.l	$07F80000,d0		Test MAPROM
	cmp.l	$00F80000,d0
	bne.b	.nomap
	move.l	d0,d1			2nd test
	not.l	d1
	move.l	d1,$07F80000
	cmp.l	$F80000,d1
	beq.b	.does_map
.xit	move.l	d0,$07F80000
.nomap	move.b	#$80,$DE0000		Gary bootflags=Warmstart
	move.l	d2,d0
	rts

.does_map	moveq	#1,d2
	bra.b	.xit


_gettc	movec	tc,d0			$4e7a0003
	rte



mmuname	dc.b	'mmu.library',0
DosName	dc.b	'dos.library',0
_mmuflag	EQU	*-1
GfxName	dc.b	'graphics.library',0
	dc.b	'$VER:'
_Version	dc.b	'BlizKick 1.21 (17.1.00)',0
	dc.b	'$COPYRIGHT:'
_Copyright	dc.b	'Copyright © 1996-2000 PitPlane Productions',0
_Template	dc.b	'KICKFILE,MODULE/M,EXTRESBUF/N,SANITY/K/N,FORCE/S,'
	dc.b	'QUICKBOOT/S,SPEEDROM/S,HOGWAITBLIT/S,'
	dc.b	'CPUCARD=CSMKI/S,QUIET/S',0
_13Help	dc.b	'Usage: BlizKick ',$9b,'1mKICKFILE',$9b,'0m',10
	dc.b	'KICKFILE is full path for the ROM image to kick.',10,0
_ks13error	dc.b	'DOS Error #%ld!',10,0
	IFD	NEW_ENV_METHOD
_VarEnvArcName	dc.b	'ENVARC:'
_VarName	dc.b	'BKMODPATH',0
	ELSE
_EnvName	dc.b	'ENVx',0
_EnvArcName	dc.b	'ENVARC:',0
_VarName	dc.b	'BKMODPATH',0
	ENDC

RequiresBliz	dc.b	'BlizKick requires turbo board/CPU-card with MAPROM feature.',10,0
NoCPUCard	dc.b	'Couldn''t find CPU Card!',10,0
PlantError	dc.b	'Couldn''t plant module ''%s''!',10,0
Messu	dc.b	'Phase5 turbo board MapROM tool written by Harry "Piru" Sintonen.',10,0
Messu2	dc.b	'Kicking AMIGA ROM Operating System %d.%d.',10,0
Already	dc.b	'Kickstart is already kicked!',10,0
CouldNotKick	dc.b	'Couldn''t kick file ''%s''!',10,0
NoRem	dc.b	'Kickstart wasn''t kicked using BlizKick!',10,0


	CNOP	0,4
_Self	ds.l	1
_ExecBase	ds.l	1
_mmubase	ds.l	1
_Array	ds.l	10
_BlizROM	ds.l	1
_Quiet	ds.l	1
_OrigSum	ds.l	1
_regtemp	ds.l	2
_erh_alloclen	ds.l	1
_erh_freeaddr	ds.l	1
_erh_arealen	ds.l	1
_erh_areastart	ds.l	1
_tc	ds.l	1
_memhead	ds.b	MH_FIRST
_AttnFlags	ds.w	1
_MemHeaderFlag	ds.b	1
_B20x0	ds.b	1
_CPUCard	ds.b	1
_PPC_MK3	ds.b	1
_MK2	ds.b	1
_BlizPPC	ds.b	1

CODE_SIZEOF	EQU	(*-Main+7)&-8

	END


; model     id       mem     start     end        notes  maprom
;turbo mem 2140/?    -        ?       - ?          A500
; 1220     2140/0C   4 meg   $00200000-$00600000  A1200
; 1230-I   2140/0?   ? meg   $????????-$????????  A1200  $????????
; 1230-II  2140/0B   4 meg   $0E000000-$0E400000  A1200  $0FF80000 ! ??
; 1230-II  2140/0B   8 meg   $????????-$????????  A1200  $1EF80000 ! ??
; 1230-III 2140/0D   8 meg   $1DC00000-$1E400000  A1200  $1EF80000
; 1230-III 2140/0D  32 meg   $1D000000-$1EF80000  A1200  $1EF80000
; 1230-IV  2140/11   8 meg   $78000000-$78800000  A1200  $4FF80000
; 1230-IV  2140/11   2 meg   $78000000-$78200000  A1200  $4FF80000?
; 1230-IV  2140/11  16 meg   $68000000-$68F80000  A1200  $4FF80000?
;?1260     2140/11   4 meg   $68000000-$68400000  A1200  $4FF80000 040&060 flag set!
;>1260     2140/11   8 meg   $78000000-$78800000  A1200  $4FF80000 040&060 flag set!
;?1260     2140/11  16 meg   $68000000-$69000000  A1200  $4FF80000 040&060 flag set!
; 1260     2140/11   4 meg   $68000000-$68380000  A1200  $4FF80000? 040&060 flag set!
; 1240-T   2140/11  16 meg   $68000000-$69000000  A1200  $4FF80000? 040 flag set!
; 2040-ERC 2140/18   8 meg   $08000000-$08800000  A2000  $???????? 040 flag set!  'blizzard fastram'
; 2060     2140/18  20 meg   $08000000-$09400000  A2000  $???????? 040&060 flag set!
; 4030     2140/?    -        ?       - ?         A4000

; CSMKI    2140/0C  32 meg   $08000000-$0A000000  A4000  csmagic  040 flag set
; CSMKII   2140/19  80 meg   $08000000-$0D000000  A4000  csmagic
; CS-PPC   2140/64   ? meg    ?       - ?         A4000 
; BLIZPPC  2140/6E  16 meg   $68000000-$68800000  A1200  $FFF00000 040 flag set

 Board (unidentified):   Prod=8512/25($2140/$19) (@$EA0000 128K)
 Board (unidentified):   Prod=2092/18($82C/$12) (@$E90000 64K)
 Board (unidentified):   Prod=2167/201($877/$C9) (@$EC0000 64K)
 Board (unidentified):   Prod=8512/34($2140/$22) (@$40000000, size 64meg, subsize same)

last one is CV 64

 VERS:   Kickstart version 40.70, Exec version 40.10, Disk version 40.42
 RAM:    Node type $A, Attributes $505 (FAST), at $8000000-$CFFFFFF (80.0 meg)


*** CS MK I:

PROCESSOR:	CPU 68040/68882fpu
CUSTOM CHIPS:	AA PAL Alice (id=$0023), AA Lisa (id=$00F8)
VERS:	Kickstart version 39.106, Exec version 39.47, Disk version 39.29
RAM:	Node type $A, Attributes $505 (FAST), at $8000000-$9FFFFFF (32.0 meg)
	Node type $A, Attributes $703 (CHIP), at $2000-$1FFFFF (~2.0 meg)
BOARDS:
=======================================================================
 Board (unidentified):   Prod=2195/10($893/$A)
     (@$40000000, size 4meg, subsize same)
 ConfigDev structure found at location $27F8
==== Board ID (ExpansionRom) information:
er_Manufacturer         =2195=$893=(~$F76C)
er_Product              =10=$A=(~$F5)
er_Type                 =$8F
  (type 2 (Zorro III), size 4meg, subsize same)
  (not for free list, no ROM diag vec, chained to next)
er_Flags                =$10
  (no space preference, can be shut up)
er_InitDiagVec          =$0
==== Configuration (ConfigDev) information:
cd_BoardAddr            =$40000000
cd_BoardSize            =$1000000 (16384K)
cd_Flags                =$0  (CONFIGME bit cleared)
=======================================================================
 Board + ROM (HD?) (unidentified):   Prod=8512/12($2140/$C) (@$E90000 64K)
 ConfigDev structure found at location $2840
==== Board ID (ExpansionRom) information:
er_Manufacturer         =8512=$2140=(~$DEBF)
er_Product              =12=$C=(~$F3)
er_Type                 =$D1
  (type 3, size 64K, not for free list, ROM diag vec valid, not chained)
er_Flags                =$0
  (no space preference, can be shut up)
er_InitDiagVec          =$80
DiagCopy at             =$8003320
==== Configuration (ConfigDev) information:
cd_BoardAddr            =$E90000
cd_BoardSize            =$10000 (64K)
cd_Flags                =$0  (CONFIGME bit cleared)
=======================================================================
 Board + ROM (HD?) (unidentified):   Prod=2195/11($893/$B) (@$EA0000 64K)
 ConfigDev structure found at location $2888
==== Board ID (ExpansionRom) information:
er_Manufacturer         =2195=$893=(~$F76C)
er_Product              =11=$B=(~$F4)
er_Type                 =$D1
  (type 3, size 64K, not for free list, ROM diag vec valid, not chained)
er_Flags                =$40
  (no space preference, can not be shut up)
er_InitDiagVec          =$0
==== Configuration (ConfigDev) information:
cd_BoardAddr            =$EA0000
cd_BoardSize            =$10000 (64K)
cd_Flags                =$2  (CONFIGME bit still set)
=======================================================================
 Board (unidentified):   Prod=5000/1($1388/$1) (@$EB0000 64K)
 ConfigDev structure found at location $28D0
==== Board ID (ExpansionRom) information:
er_Manufacturer         =5000=$1388=(~$EC77)
er_Product              =1=$1=(~$FE)
er_Type                 =$C1
  (type 3, size 64K, not for free list, no ROM diag vec, not chained)
er_Flags                =$40
  (no space preference, can not be shut up)
er_InitDiagVec          =$0
==== Configuration (ConfigDev) information:
cd_BoardAddr            =$EB0000
cd_BoardSize            =$10000 (64K)
cd_Flags                =$0  (CONFIGME bit cleared)
=======================================================================
 Board + ROM (HD?) (unidentified):   Prod=2017/11($7E1/$B) (@$EC0000 64K)
 ConfigDev structure found at location $2918
==== Board ID (ExpansionRom) information:
er_Manufacturer         =2017=$7E1=(~$F81E)
er_Product              =11=$B=(~$F4)
er_Type                 =$D1
  (type 3, size 64K, not for free list, ROM diag vec valid, not chained)
er_Flags                =$0
  (no space preference, can be shut up)
er_InitDiagVec          =$8000
==== Configuration (ConfigDev) information:
cd_BoardAddr            =$EC0000
cd_BoardSize            =$10000 (64K)
cd_Flags                =$0  (CONFIGME bit cleared)
=======================================================================


; Apollo:

; 1230/28  2222/23   4 meg   $01C00000-02000000  A1200  none      030 flag set 'Apollo 32Bit Power'
;                    8 meg   $03C00000-04400000 'Apollo 32Bit Power'
; 1230/50  2222/23   4 meg   $01C00000-02000000  A1200  none      030 flag set 'Apollo 32Bit Power'
; 1240/40  2222/23   4 meg   $01C00000-02000000  A1200  none      040 flag set '32Bit Power-Burstm'??
; 1240     2222/23   8 meg   $01C00000-02400000  A1200  none      040 flag set '32Bit Power-Burstm'??
; 1260     2222/23   4 meg   $01C00000-02000000  A1200  none      040&060 flag set '32Bit Power-Burstm'??
; 4060     2222/23  32 meg   $08000000-0A000000  A4000  none      040&060 flag set 'Apollo 32Bit Power'
