;----------------------------------------------------------------------------
;File name:	LOADER.S			Revision date:	2000.02.05
;Revised by:	Ulf Ronald Andersson		Revision start:	1999.09.03
;----------------------------------------------------------------------------
*	Created by TT-Digger vv6
*	Fri Sep 03 16:24:20 1999
*	TTD_5.5
*	TEXT	$000CB6 bytes, segment starts at L0000+$0
*	DATA	$0052D0 bytes, segment starts at T0CB6
*	BSS	$000000 bytes
*	SYMBOLS	$000000 bytes
*	FLAG	$0000
;----------------------------------------------------------------------------
	output	.TOS
	include	RA_XB.I
	include	RA_JAR.I
;----------------------------------------------------------------------------
Loader_id_1	=	'FAL_'
Loader_id_2	=	'GAME'
Loader_id_3	=	'.BIN'
;----------------------------------------------------------------------------
	TEXT
;----------------------------------------------------------------------------
start:
	movea.l	$0004(a7),a5			; a5 -> basepage
	sub.l	#$100,loc_sp			;reserve space on a local stack
	move.l	loc_sp(pc),sp			;activate new SSP
	lea	resident_end(pc),a0		; a0 -> resident_end
	suba.l	a5,a0				; a0 = (resident_end-basepage)
	gemdos	Mshrink,!,(a5),a0		; shrink program
;-------
	xbios	Getrez
	tst	d0
	beq.s	.have_ST_L_rez
	xbios	Setscreen,?,?,!
.have_ST_L_rez:
;-------
	gemdos	Super,!				;enter super mode
	move.l	d0,-(sp)			;push old SSP
;-------
	tst	(_longframe).w
	beq.s	.have_frame_size
	move	#8,frame_size
.have_frame_size:
	clr.l	d7				;clear special case flags
	eval_cookie	#'_CPU'
	bmi.s	.done_uncache
	cmp.l	#20,d0
	beq.s	.do_uncache
	cmp.l	#30,d0
	bne.s	.done_uncache
	bset	#7,d7				;set 68030 flag
.do_uncache:
	move.l	#$00000A0A,d0			;CACR value to disable caching
	movec.l	d0,CACR				;store d0 as cache control bits
.done_uncache:
	eval_cookie	#'_MCH'
	bmi.s	.done_compat_fix
	swap	d0
	cmp	#$0003,d0			;Falcon ?
	bne.s	.done_compat_fix
	move.b	(hw_F_comp_div).w,d0
	bclr	#F_comp_bus_b,d0		;set ST-type Bus
	move.b	d0,(hw_F_comp_div).w
	eval_cookie	#'_CT2'
	bmi.s	.done_compat_fix
	bset	#15,d7				;set CT2 caution flag
.done_compat_fix:
;-------
	moveq	#$01,d3			;d3 = $00000001 \/ shorter code for
	ror.l	#8,d3			;d3 = $01000000 /\ move.l #$1000000,d3
	cmpi.l	#$1357BD13,(ramvalid).w	;test TT RAM validity
	bne.s	.done_TT_RAM		;done if TT RAM invalid
	cmp.l	(ramtop).w,d3		;test (TT_RAM_base - ramtop)
	bge.s	.done_TT_RAM		;done OK if size undefined
	tst.w	d7			;CT2 caution flag set ?
	bpl.s	.make_reset
	gemdos	Cconws,CT2_warning_s(pc)
	gemdos	Crawcin
.make_reset:
	move.l	d3,(ramtop).w		;lower TT_RAM ramtop to base
	move.l	(_sysbase).w,a0		;a0 -> OS header (may be a copy)
	move.l	os_selfbeg_p(a0),a0	;a0 -> Original OS header
	move.l	os_reset_p(a0),a0	;a0 -> reset routine
	jmp	(a0)			;perform reset
;-------
.done_TT_RAM:
;-------
;;;patch physical disabling of TT_RAM here
;-------
	move.l	ev_gemdos.w,xb_next+game_gd_XB
	move.l	#xb_code+game_gd_XB,ev_gemdos.w
;-------
	gemdos	Super,()			; exit super mode
;-------
	gemdos	Pexec,!,MILENIUM_FOF_s(pc),NUL_s(pc),NUL_s(pc)
	gemdos	Super,!				;enter super mode
	move.l	d0,-(sp)			;push old SSP
	move.l	xb_next+game_gd_XB(pc),ev_gemdos.w
	gemdos	Super,()			; exit super mode
	gemdos	Pterm0
;----------------------------------------------------------------------------
	make	JAR_links
;----------------------------------------------------------------------------
;Start of:	XBRA linked GEMDOS routines	(JEK! unpacker)
;----------------------------------------------------------------------------
	XB_define	game_gd_XB,'Mill'
	btst	#$05,(a7)			; user mode call ?
	bne.s	super_gd_call
	move	usp,a0				;a0 -> user gemdos arguments
	bra.s	have_gd_args
;-------
super_gd_call:
	lea	6(sp),a0			;a0 -> super gemdos arguments
frame_size	= super_gd_call+2
have_gd_args:
	move	(a0),d0				;d0 = gemdos opcode
	move.b	game_gd_t1(pc,d0),d0		;d0 = local opcode, or negative
	bpl	maybe_game_gd
exit_to_orig_gd_1:
	XB_gonext_a0	game_gd_XB(pc)
;----------------------------------------------------------------------------
game_gd_t1:	;one byte per gemdos opcode defines local opcodes
	dc.b	-1,-1,-1,-1,-1,-1,-1,-1		;$00-$07 have no local code
	dc.b	-1,-1,-1,-1,-1,-1,-1,-1		;$08-$0F have no local code
	dc.b	-1,-1,-1,-1,-1,-1,-1,-1		;$10-$17 have no local code
	dc.b	-1,-1,00,-1,-1,-1,-1,-1		;$1A => 0 for Fsetdta
	dc.b	-1,-1,-1,-1,-1,-1,-1,-1		;$20-$27 have no local code
	dc.b	-1,-1,-1,-1,-1,-1,-1,01		;$2F => 1 for Fgetdta
	dc.b	-1,-1,-1,-1,-1,-1,-1,-1		;$30-$37 have no local code
	dc.b	-1,-1,-1,-1,-1,-1,-1,02		;$3F => 2 for Fread
	dc.b	-1,-1,03,-1,-1,-1,-1,-1		;$42 => 3 for Fseek
	dc.b	-1,-1,-1,-1,-1,-1,04,-1		;$4E => 4 for Fsfirst
	dcb.b	$B0,-1				;$50-$FF have no local code
;----------------------------------------------------------------------------
game_gd_t2:
	dc.l	Fsetdta_fun,Fgetdta_fun,Fread_fun,Fseek_fun
	dc.l	Fsfirst_fun
;----------------------------------------------------------------------------
maybe_game_gd:
	cmp	#$100,d0		;check high byte of gemdos opcode
	bhs	exit_to_orig_gd_1	;not for us if high byte nonzero
	asl	#2,d0			;d0 = index for longs
	move.l	game_gd_t2(pc,d0),d0	;d0 -> xxx_fun
	move.l	a0,-(sp)		;push -> args on old stack
	move.l	sp,a0			;a0 = old SSP  (-> arg_ptr, RTE_frame)
	cmp.l	#loc_stack,sp
	blo.s	.need_SSP
	cmp.l	#loc_stack_top,sp
	bls.s	.keep_SSP
.need_SSP:
	sub.l	#$100,loc_sp		;reserve space on a local stack
	move.l	loc_sp(pc),sp		;activate new SSP
	move.l	(a0),-(sp)		;sp -> arg_ptr
.keep_SSP:
	move.l	a0,-(sp)		;sp -> old_SSP, arg_ptr
	move.l	4(sp),a0		;a0 = arg_ptr
	lea	12(a0),a0		;\
	move.l	-(a0),-(sp)		; \/ 12 arg bytes are copied
	move.l	-(a0),-(sp)		; /\ to current SSP stack
	move.l	-(a0),-(sp)		;/
	exg	d0,a0			;d0 = arg_ptr,  a0 -> xxx_fun
	push_ex	_ind,(a0)+		;push a new stack frame leading to xxx_fun post_amble code
	move.l	a0,-(sp)		;push -> to xxx_fun pre_amble code
	move.l	d0,a0			;a0 = arg_ptr
	rts				;'return' to pre_amble code of xxx_fun
;----------------------------------------------------------------------------
Fsetdta_fun:
	dc.l	post_Fsetdta
pre_Fsetdta:
	bra.w	exit_to_orig_gd_2
;-------------------------------------
Fgetdta_fun:
	dc.l	post_Fgetdta
pre_Fgetdta:
	bra.w	exit_to_orig_gd_2
;-------------------------------------
Fsfirst_fun:
	dc.l	post_Fsfirst
pre_Fsfirst:
	bra.w	exit_to_orig_gd_2
;-------------------------------------
Fseek_fun:
	dc.l	post_Fseek
pre_Fseek:
	bra.w	exit_to_orig_gd_2
;-------------------------------------
Fread_fun:
	dc.l	post_Fread
pre_Fread:
	move.l	$0008(a0),Fread_buf_p.l
exit_to_orig_gd_2:
	XB_gonext_a0	game_gd_XB(pc)
;----------------------------------------------------------------------------
post_Fsetdta:
	move.l	2(sp),current_DTA_p.l
post_amble_exit:
	lea	12(sp),sp		;pop extra argument copy off stack
	move.l	(sp)+,a0		;pull old SSP to a0
	cmp.l	a0,sp			;is it different ?
	beq.s	.keep_sps		;if not, loc_sp is not involved
	add.l	#$100,loc_sp		;release reserved local stack space
	move.l	a0,sp			;reactivate old SSP
.keep_sps:
	move.l	(sp)+,a0		;a0 = original arg_ptr, popped
	rte				;exit to original caller
;-------------------------------------
post_Fgetdta:
	move.l	d0,current_DTA_p.l
	bra	post_amble_exit
;-------------------------------------
post_Fsfirst:
	tst.l	d0				; orig_gemdos result OK ?
	bne.w	L01EE
	move.l	d0,X0486.l
	move.l	a0,X048A.l
	move.l	$0002(a7),Fsfirst_pathname_p.l
	move 	#$0002,-(a7)
	move.l	Fsfirst_pathname_p.l,-(a7)
	move 	#$003D,-(a7)	; Fopen
	trap	#1		; Gemdos	; open file as rw
	addq.l	#8,a7
	move 	d0,Fsfirst_file_handle.l
	move 	#$0002,-(a7)
	move 	d0,-(a7)
	move.l	#$00000000,-(a7)
	move 	#$0042,-(a7)	; Fseek
	trap	#1		; Gemdos	; seek end of file
	lea 	$000A(a7),a7
	movea.l	current_DTA_p.l,a0
	lea 	$001A(a0),a0			; a0 -> dta_fsize of DTA
	move.l	d0,(a0)				; patch dta_fsize in DTA
	move 	Fsfirst_file_handle.l,-(a7)
	move 	#$003E,-(a7)	; Fclose
	trap	#1		; Gemdos
	addq.l	#4,a7
	move.l	X0486.l,d0
	movea.l	X048A.l,a0
L01EE:
	bra	post_amble_exit
;-------------------------------------

post_Fseek:
	cmpi 	#$0002,$0008(a7)		; seeking relative to EOF ?
	bne.w	L02A6
	cmpi.l	#$00000000,$0002(a7)
	bne.w	L02A6
	move 	$0006(a7),Fseek_file_handle.l
	move.l	d0,Fseek_saved_d0.l
	cmp.l	#$0000000A,d0			; file_pos >= 10 ?
	blt.w	L029A
	move 	#$0002,-(a7)
	move 	Fseek_file_handle.l,-(a7)
	move.l	#$FFFFFFF8,-(a7)
	move 	#$0042,-(a7)	; Fseek
	trap	#1		; Gemdos
	lea 	$000A(a7),a7
	addq.l	#8,d0
	move.l	d0,X0496.l
	move 	#$0001,X0472.l
	move.l	#pack_id_buf,-(a7)
	move.l	#$00000008,-(a7)
	move 	Fseek_file_handle.l,-(a7)
	move 	#$003F,-(a7)	; Fread
	trap	#1		; Gemdos	; read 8 bytes to pack_id_buf
	lea 	$000C(a7),a7
	cmpi.l	#'JEK!',pack_id.l		; pack_id == 'JEK!' ?
	bne.w	L029A
	move.l	pack_id_buf.l,d0
	bra.w	L02A6
;-------
L029A:	move.l	Fseek_saved_d0.l,d0
L02A6:	move 	#$0000,X0472.l
	bra	post_amble_exit
;-------------------------------------
post_Fread:
	tst 	$0002(a7)			; positive read handle ?
	bmi.w	L0424
	movem.l	d0-d7/a0-a6,-(a7)
	move.l	d0,X046A.l
	move.l	d0,X045C.l
	btst	#$00,d0
	bne.w	L0412
	cmpi 	#$0001,X0472.l
	beq.w	L0412
	movea.l	Fread_buf_p.l,a0
	move.l	a0,d7
	btst	#$00,d7
	bne.w	L0412
	adda.l	d0,a0
	move.l	-(a0),d0
	cmp.l	#'JEK!',d0
	beq.w	L0302
	bra.w	L0412
;-------
L0302:	move.l	-(a0),X045C.l
	move	sr,d1
	btst	#$0D,d1
	bne.w	L032C
	clr.l	-(a7)
	move 	#$0020,-(a7)	; Super
	trap	#1		; Gemdos
	addq.l	#6,a7
	lea 	X0466.l,a6
	move.l	d0,(a6)
	move 	#$0001,X0464.l
L032C:
	move 	hw_pal_00.l,X046E.l
	subq.l	#4,X046A.l
	movea.l	Fread_buf_p.l,a0
	adda.l	X046A.l,a0
	movea.l	Fread_buf_p.l,a1
	movea.l	-(a0),a2
	adda.l	a1,a2
	move.l	-(a0),d5
	move.l	-(a0),d0
	eor.l	d0,d5
L0358:	lsr.l	#1,d0
	bne.s	L0360
	bsr.w	L042A
L0360:	bcs.s	L03AE
	moveq	#$08,d1
	moveq	#$01,d3
	lsr.l	#1,d0
	bne.s	L036E
	bsr.w	L042A
L036E:	bcs.s	L03DA
	moveq	#$03,d1
	clr 	d4
L0374:	bsr.w	L0436
	move 	d2,d3
	add 	d4,d3
L037C:	moveq	#$07,d1
L037E:	lsr.l	#1,d0
	bne.s	L0386
	bsr.w	L042A
L0386:	roxl.l	#1,d2
	dbf	d1,L037E
	move.b	d2,-(a2)
	eori 	#$0707,X0470.l
	move 	X0470.l,hw_pal_00.l
	dbf	d3,L037C
	bra.w	L03E8
;-------
L03A8:	moveq	#$08,d1
	moveq	#$08,d4
	bra.s	L0374
;-------
L03AE:	moveq	#$02,d1
	bsr.w	L0436
	cmp.b	#$02,d2
	blt.s	L03D0
	cmp.b	#$03,d2
	beq.s	L03A8
	moveq	#$08,d1
	bsr.w	L0436
	move 	d2,d3
	move 	#$000C,d1
	bra.w	L03DA
;-------
L03D0:	move 	#$0009,d1
	add 	d2,d1
	addq 	#2,d2
	move 	d2,d3
L03DA:	bsr.w	L0436
L03DE:	subq 	#1,a2
	move.b	$00(a2,d2),(a2)
	dbf	d3,L03DE
L03E8:	cmpa.l	a2,a1
	blt.w	L0358
	move 	X046E.l,hw_pal_00.l
	cmpi 	#$0001,X0464.l
	bne.w	L0412
	move.l	X0466.l,-(a7)
	move 	#$0020,-(a7)	; Super
	trap	#1		; Gemdos
	addq.l	#6,a7
L0412:	move 	#$0000,X0464.l
	movem.l	(a7)+,d0-d7/a0-a6
	move.l	X045C.l,d0
L0424:
	bra	post_amble_exit
;----------------------------------------------------------------------------
L042A:	move.l	-(a0),d0
	eor.l	d0,d5
	move	#$0010,ccr
	roxr.l	#1,d0
	rts
;----------------------------------------------------------------------------
L0436:	subq 	#1,d1
	clr 	d2
L043A:	lsr.l	#1,d0
	bne.s	L0448
	move.l	-(a0),d0
	eor.l	d0,d5
	move	#$0010,ccr
	roxr.l	#1,d0
L0448:	roxl.l	#1,d2
	dbf	d1,L043A
	rts
;----------------------------------------------------------------------------
;Start of:	XBRA linked GEMDOS routines	(JEK! unpacker)
;----------------------------------------------------------------------------
pack_id_buf:
	dc.w	$0000,$0000
pack_id:dc.w	$0000,$0000
X045C:	dc.w	$0000,$0000
Fread_buf_p:
	dc.w	$0000,$0000
X0464:	dc.w	$0000
X0466:	dc.w	$0000,$0000
X046A:	dc.w	$0000,$0000
X046E:	dc.w	$0000
X0470:	dc.w	$0777
X0472:	dc.w	$0000
Fseek_file_handle:
	dc.w	$0000
Fseek_saved_d0:
	dc.w	$0000,$0000
Fsfirst_file_handle:
	dc.w	$0000,$0000
X0486:	dc.w	$0000,$0000
X048A:	dc.w	$0000,$0000
current_DTA_p:
	dc.w	$0000,$0000
Fsfirst_pathname_p:
	dc.w	$0000,$0000
X0496:	dc.w	$0000,$0000
NUL_s:	dc.w	$0000
PACKED_BY_s:
	dc.w	$368A,$A082,$8696,$8A88
	dc.w	$4084,$B240,$8C98,$829A
	dc.w	$8A58,$40A8,$908A,$409A
	dc.w	$8A9A,$848A,$A4A6,$409E
	dc.w	$8C40,$8C5C,$9E5C,$8C5C
	dc.w	$A85C,$0000
MILENIUM_FOF_s:	dc.b	'MILENIUM.FOF',NUL
	EVEN
;----------------------------------------------------------------------------
CT2_warning_s:
	dc.b	CR,LF
	dc.b	"I need to make a warm reset now, to get",CR,LF
	dc.b	"rid of FastRAM, which Millenium can not",CR,LF
	dc.b	"tolerate.  But this probably won't work",CR,LF
	dc.b	"since I have detected a CT2 cookie. But",CR,LF
	dc.b	"I'll try anyway, as soon as you press a",CR,LF
	dc.b	"key to continue.",CR,LF
	dc.b	NUL
;----------------------------------------------------------------------------
loc_stack:		ds.b	$800
loc_stack_top:		ds.b	$10
loc_sp:			dc.l	loc_stack_top
;----------------------------------------------------------------------------
resident_end:
;----------------------------------------------------------------------------
	end	
;----------------------------------------------------------------------------
;End of file:	LOADER.S
;----------------------------------------------------------------------------
