; Captain Planet HD loader
; v1.0: saves hiscores, copylocks removed, Captive disk cheat implemented
; by Kyzer/CSG

	include	whdload.i
	include	whdmacros.i

MEM=$80000

base	SLAVE_HEADER
	dc.w	10,WHDLF_NoError
	dc.l	MEM,0		; basemem, 0
	dc.w	start-base,0,0		; slave code, dir, dontcache
	dc.b	0,$59			; debugkey, quitkey
	dc.l	0			; expmem
	dc.w	name-base,copy-base,info-base
name	dc.b	'Captain Planet',0
copy	dc.b	'1991 Mindscape',0
info	dc.b	'HD-installed by Kyzer',0
resload	dc.l	0
tags	dc.l	WHDLTAG_CUSTOM1_GET
trainer	dc.l	0,TAG_DONE
start	lea	resload(pc),a1
	move.l	a0,(a1)+
	move.l	a0,a2

	lea	tags(pc),a0
	jsr	resload_Control(a2)

	lea	MEM,a4			; a4 = top of memory
	lea	-$4870(a4),a5		; a5 = decoded bootblock addr
	lea	.boot(pc),a0
	move.l	a5,a1
	jsr	resload_LoadFile(a2)	; load bootcode
	patch	$56(a5),.cont		; stop bootcode at loading ratt-dos
	jmp	(a5)			; run bootcode
.cont	move.w	#$8000!DMAF_MASTER!DMAF_RASTER!DMAF_COPPER,_custom+dmacon

	lea	$124.w,a6		; a6 = ratt-dos base
	lea	.ratt(pc),a0
	move.l	a6,a1
	jsr	resload_LoadFile(a2)	; load ratt-dos
	lea	.patch(pc),a0
	move.l	a6,a1
	jsr     resload_Patch(a2)	; patch ratt-dos
	move.l	a6,4.w			; save at 0
	move.l	a6,0.w			; save at 4
	lea	$2000(a6),a0		; initialise ratt-dos
	lea	.datas(pc),a1
	jsr	$68(a6)
	jmp	MEM-$4870+$fc		; back to bootcode

.datas	dc.l	0,$32320000,0,MEM,0,0
.boot	dc.b	'bootcode',0
.ratt	dc.b	'rattdos',0
	cnop	0,4

; ratt-dos functions			;$40 OK    'get existing drives'
;$00 OK(5) 'init drives with sync'	;$44 ALERT ??? writes directory
;$04 OK(5) 'init drives'		;$48 ALERT 'rename file'
;$08 PATCH 'set directory buffer'	;$4C ALERT ??? writes something
;$0C OK    'set data buffer'		;$50 OK    empty function
;$10 PATCH 'raw read'			;$54 OK    'get buffers'
;$14 PATCH 'save file'			;$58 OK(1) 'find dir entry'
;$18 ALERT ???				;$5C OK    'set sync'
;$1C PATCH 'load file'			;$60 OK(1) 'change disk'
;$20 OK(4) 'motor off'			;$64 OK(4) 'specific motor off'
;$24 OK    'restore ints'		;$68 OK    'initialise'
;$28 OK    'set/store ints'		;$6C OK    memory function
;$2C ALERT 'set directory size'		;$70 OK    'free memory'
;$30 ALERT 'clear directory'		;$74 OK    'allocate memory'
;$34 ALERT 'get empty track'		;$78 OK    'set drive parameters'
;$38 OK2&3 'get disk dir'		;$7C OK    'alloc mem with type'
;$3C OK    'reset drives'		;$80 OK    'get memory info'

.patch	PL_START
	; removal of internal disk-accessing ratt-dos functions
	PL_L	$7b0,$70004e75		; (1) 'find disk and load directory'
	PL_R	$3ec			; (2) 'select drive'
	PL_R	$4a0			; (3) 'read disk dir'
	PL_R	$67a			; (4) 'motor off'
	PL_R	$5ec			; (5) 'init drives'
	; patches of external functions
	PL_P	$1c2,setdir
	PL_P	$2ec,load
	PL_P	$82a,rawread
	PL_P	$86a,rawwrit

	; alerts
	PL_I	$18
	PL_I	$2c
	PL_I	$30
	PL_I	$34
	PL_I	$44
	PL_I	$48
	PL_I	$4c
	PL_END

;SETDIR: d0 = new buffer
setdir	movem.l	d0-d1/a0-a2,-(sp)
	move.l	d0,($124+$f6e).w	; save dir pointer
	move.l	d0,a1
	lea	.cpdir(pc),a0
	move.l	resload(pc),a2
	jsr	resload_LoadFile(a2)	; read in copy of dir
	movem.l	(sp)+,d0-d1/a0-a2
	rts
.cpdir	dc.b	'cp.dir',0
	cnop	0,4

;RAWREAD: d0 = sync, d2 = track, d3 = length
rawread	swap	d2
	move.w	d0,d2
	cmp.l	#$00034489,d2	; load hiscores
	beq.s	.hisc
	cmp.l	#$00024489,d2	; DO NOTHING - return OK (protection check)
	beq.s	.ok
	cmp.l	#$00024522,d2	; DO NOTHING - fail (Captive disk check)
	beq.s	.fail
	illegal			; fail on any other values
.hisc	move.l	(a4),a1
	addq.l	#4,a1
	lea	hisc(pc),a0
	move.l	resload(pc),a2
	jsr	resload_LoadFile(a2)
	move.l	(a4),a1
.ok	clr.l	$60.w
	rts
.fail	move.l	#-4,$60.w
	rts

;RAWWRITE:
rawwrit	cmp.w	#$0003,d2
	beq.s	.hisc		; save hiscores
	illegal			; fail anything else
.hisc	move.l	a0,a1
	lea	hisc(pc),a0
	moveq	#48,d0
	move.l	resload(pc),a2
	jmp	resload_SaveFile(a2)

hisc	dc.b	'HI-Score',0
	cnop	0,4

;LOAD:
; in:  a0 = load address, a1 = filename, d1 =  magic unpacking number?
; out: a0 = load address + length, $60.l = length
load	movem.l	d0-d2/a1-a2,-(sp)
	exg.l	a0,a1		; a0=fname, a1=loadaddr
	cmp.b	#':',2(a0)
	bne.s	1$		; name "CP:xyz" -> "xyz"
	addq.l	#3,a0
1$	move.l	a0,-(sp)
	moveq	#4-1,d0
	lea	.name(pc),a2
.cp	move.b	(a0)+,(a2)+	; copy 4 bytes of name
	dbra	d0,.cp
	move.l	(sp)+,a0

	move.l	a1,-(sp)	; save load address
	move.l	resload(pc),a2
	jsr	resload_LoadFile(a2)
	move.l	d0,d2

	move.l	(sp),a1		; a1 = load address
	lea	.name(pc),a0
	cmp.l	#'CP'<<16,(a0)	; compare filename loaded to "CP"
	bne.s	2$
	bsr.s	patchcp		; patch main CP executable
	bra.s	.done
2$	cmp.l	#'cpbo',(a0)	; compare filename loaded to "cpboot"
	bne.s	.done
	ret	$1be(a1)	; remove cpboot's debugger

.done	move.l	d2,$60.w	; $60.w = load length
	move.l	(sp)+,a0	; a0 = load address
	add.l	d2,a0		; a0 = load address + load length
	movem.l	(sp)+,d0-d2/a1-a2
	rts

.name	dc.l	0

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

patchcp	move.l	trainer(pc),d0
	bne.s	1$
	lea	.cheats(pc),a0		; if cheat-mode is disabled then
	move.w	#PLCMD_END,(a0)		; cut off the cheat patches
1$	lea	.patch(pc),a0
	adda.w	#$20,a1			; a1 = $5a9c
	move.l	resload(pc),a2
	jmp	resload_Patch(a2)
.patch	PL_START
	PL_B	$1a56,$60		; remove mem checksum (beq.s -> bra.s)
	PL_B	$32ee,$60		; remove mem checksum (beq.s -> bra.s)
	PL_R	$15a0			; remove some drive access
	PL_P	$a2d0,.lock1		; decoded copylock
	PL_P	$9c0a,.lock2		; decoded copylock
.cheats	PL_B	$3bbc,$60		; livescheat (bne.s -> bra.s)
	PL_B	$9fd8,$60		; levelcheat (bne.s -> bra.s)
	PL_B	$a036,$60		; levelcheat (bne.s -> bra.s)
	PL_END

.lock1	move.l	#$92385060,d3
	bra.s	.lock
.lock2	move.l	#$52613060,d3
.lock	movem.l	d0-d7/a0-a7,-(sp)
	move.l	#$43896371,d0
	moveq	#0,d1
	move.l	sp,a6

	move.l	d0,$60.w
	moveq	#3,d3
	move.l	d1,4(a6)

.outer	lsl.w	#2,d3
	move.l	(a6,d3.w),d2
	rol.w	#4,d2
	andi.b	#%00001111,d2
	beq.b	.done
	subi.w	#$1000,2(a6,d3.w)
	move.l	(a6,d3.w),d3
	rol.w	#8,d3
	move.w	d3,d1
	andi.w	#7,d1
	lsl.w	#2,d1
	movea.l	$20(a6,d1.w),a0
	rol.w	#4,d3
	move.w	d3,d1
	andi.w	#7,d1
	lsl.w	#2,d1
	move.l	(a6,d1.w),d1
.inner	movea.l	(a0)+,a1
	add.l	d0,(a1,d1.l)
	subq.b	#1,d2
	bne.b	.inner
	rol.w	#4,d3
	andi.w	#15,d3
	cmp.b	#8,d3
	blt.b	.outer
.done	cmp.l	$60.w,d0
	beq.s	.ok
	illegal
.ok	move.l	resload(pc),a6
	jsr	resload_FlushCache(a6)
	movem.l	(sp)+,d0-d7/a0-a7
	rts
