.text


	.org	0x0000

	dc.l	0x0,0x200
	dc.l	INT,INT,INT,INT,INT,INT,INT
	dc.l	INT,INT,INT,INT,INT,INT,INT,INT
	dc.l	INT,INT,INT,INT,INT,INT,INT,INT
	dc.l	INT,INT,INT,HBL,INT,VBL,INT,INT
	dc.l	INT,INT,INT,INT,INT,INT,INT,INT
	dc.l	INT,INT,INT,INT,INT,INT,INT,INT
	dc.l	INT,INT,INT,INT,INT,INT,INT,INT
	dc.l	INT,INT,INT,INT,INT,INT,INT

	.ascii	"SEGA MEGA DRIVE "				    /* Console Name (16) */
	.ascii	"KRIKzz 2009.JUL "				    /* Copyright Information (16) */
	.ascii	"KRIKzz gameloader                               "  /* Domestic Name (48) */
	.ascii	"KRIKzz gameloader                               "  /* Overseas Name (48) */
	.ascii	"GM 00000000-00"				    /* Serial Number (2, 14) */
	dc.w	0x0000						    /* Checksum (2) */
	.ascii	"JD              "				    /* I/O Support (16) */
	dc.l	0x00000000					    /* ROM Start Address (4) */
	dc.l	0x20000 					    /* ROM End Address (4) */
	dc.l	0x00FF0000					    /* Start of Backup RAM (4) */
	dc.l	0x00FFFFFF					    /* End of Backup RAM (4) */
	.ascii	"RA                      "			    /* Modem Support (12) */
	.ascii	"http://krikzz.com  biokrik@gmail.com    "	    /* Memo (40) */
	.ascii	"JUE             "				    /* Country Support (16) */
reset:
	tst.l	0xa10008
	bne	SkipJoyDetect
	tst.w	0xa1000c
SkipJoyDetect:
	bne	SkipSetup
	lea	Table,%a5
	movem.w (%a5)+,%d5-%d7
	movem.l (%a5)+,%a0-%a4
* Check Version Number
	move.b	-0x10ff(%a1),%d0
	andi.b	#0x0f,%d0
	beq	WrongVersion
* Sega Security Code (SEGA)
	move.l	#0x53454741,0x2f00(%a1)
WrongVersion:
	move.w	(%a4),%d0
	moveq	#0x00,%d0
	movea.l %d0,%a6
	move	%a6,%usp
* Set VDP registers
	moveq	#0x17,%d1
FillLoop:
	move.b	(%a5)+,%d5
	move.w	%d5,(%a4)
	add.w	%d7,%d5
	dbra	%d1,FillLoop
	move.l	(%a5)+,(%a4)
	move.w	%d0,(%a3)
	move.w	%d7,(%a1)
	move.w	%d7,(%a2)
L0250:
	btst	%d0,(%a1)
	bne	L0250
* Put initial values into a00000
	moveq	#0x25,%d2
Filla:
	move.b	(%a5)+,(%a0)+
	dbra	%d2,Filla
	move.w	%d0,(%a2)
	move.w	%d0,(%a1)
	move.w	%d7,(%a2)
L0262:
	move.l	%d0,-(%a6)
	dbra	%d6,L0262
	move.l	(%a5)+,(%a4)
	move.l	(%a5)+,(%a4)
* Put initial values into c00000
	moveq	#0x1f,%d3
Filc0:
	move.l	%d0,(%a3)
	dbra	%d3,Filc0
	move.l	(%a5)+,(%a4)
* Put initial values into c00000
	moveq	#0x13,%d4
Fillc1:
	move.l	%d0,(%a3)
	dbra	%d4,Fillc1
* Put initial values into c00011
	moveq	#0x03,%d5
Fillc2:
	move.b	(%a5)+,0x0011(%a3)
	dbra	%d5,Fillc2
	move.w	%d0,(%a2)
	movem.l (%a6),%d0-%d7/%a0-%a6
	move	#0x2700,%sr
SkipSetup:
	bra	Continue
Table:
	dc.w	0x8000, 0x3fff, 0x0100, 0x00a0, 0x0000, 0x00a1, 0x1100, 0x00a1
	dc.w	0x1200, 0x00c0, 0x0000, 0x00c0, 0x0004, 0x0414, 0x302c, 0x0754
	dc.w	0x0000, 0x0000, 0x0000, 0x812b, 0x0001, 0x0100, 0x00ff, 0xff00
	dc.w	0x0080, 0x4000, 0x0080, 0xaf01, 0xd91f, 0x1127, 0x0021, 0x2600
	dc.w	0xf977, 0xedb0, 0xdde1, 0xfde1, 0xed47, 0xed4f, 0xd1e1, 0xf108
	dc.w	0xd9c1, 0xd1e1, 0xf1f9, 0xf3ed, 0x5636, 0xe9e9, 0x8104, 0x8f01
	dc.w	0xc000, 0x0000, 0x4000, 0x0010, 0x9fbf, 0xdfff

Continue:
	tst.w	 0x00C00004

* set stack pointer
	move.w	 #0,%a7

* user mode
	move.w	#0x2300,%sr

* clear Genesis RAM
	lea	0xff0000,%a0
	moveq	#0,%d0
clrram: move.w	#0,(%a0)+
	subq.w	#2,%d0
	bne	clrram

	jmp	gameLoaderStart


*------------------------------------------------
*
*	interrupt functions
*
*------------------------------------------------

.bss

	.extern vtimer

.text

INT:
	jmp reset
	*rte

HBL:
	movem.l %d0-%d1/%a0-%a1,-(%sp)
	bsr    _hblankcallback
	movem.l (%sp)+,%d0-%d1/%a0-%a1
	rte

VBL:
	*addq.l	 #1,vtimer
	movem.l %d0-%d1/%a0-%a1,-(%sp)
	bsr    _vblankcallback
	movem.l (%sp)+,%d0-%d1/%a0-%a1
	rte


*------------------------------------------------
*
* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
*    of using this software, even if they result from defects in it.
*
*------------------------------------------------

ldiv:
	move.l	4(%a7),%d0
	bpl	ld1
	neg.l	%d0
ld1:
	move.l	8(%a7),%d1
	bpl	ld2
	neg.l	%d1
	eor.b	#0x80,4(%a7)
ld2:
	bsr	i_ldiv		/* d0 = d0/d1 */
	tst.b	4(%a7)
	bpl	ld3
	neg.l	%d0
ld3:
	rts

lmul:
	move.l	4(%a7),%d0
	bpl	lm1
	neg.l	%d0
lm1:
	move.l	8(%a7),%d1
	bpl	lm2
	neg.l	%d1
	eor.b	#0x80,4(%a7)
lm2:
	bsr	i_lmul		/* d0 = d0*d1 */
	tst.b	4(%a7)
	bpl	lm3
	neg.l	%d0
lm3:
	rts

lrem:
	move.l	4(%a7),%d0
	bpl	lr1
	neg.l	%d0
lr1:
	move.l	8(%a7),%d1
	bpl	lr2
	neg.l	%d1
lr2:
	bsr	i_ldiv		/* d1 = d0%d1 */
	move.l	%d1,%d0
	tst.b	4(%a7)
	bpl	lr3
	neg.l	%d0
lr3:
	rts

ldivu:
	move.l	4(%a7),%d0
	move.l	8(%a7),%d1
	bsr	i_ldiv
	rts

lmulu:
	move.l	4(%a7),%d0
	move.l	8(%a7),%d1
	bsr	i_lmul
	rts

lremu:
	move.l	4(%a7),%d0
	move.l	8(%a7),%d1
	bsr	i_ldiv
	move.l	%d1,%d0
	rts
*
* A in d0, B in d1, return A*B in d0
*
i_lmul:
	move.l	%d3,%a2 	  /* save d3 */
	move.w	%d1,%d2
	mulu	%d0,%d2 	  /* d2 = Al * Bl */

	move.l	%d1,%d3
	swap	%d3
	mulu	%d0,%d3 	  /* d3 = Al * Bh */

	swap	%d0
	mulu	%d1,%d0 	  /* d0 = Ah * Bl */

	add.l	%d3,%d0 	  /* d0 = (Ah*Bl + Al*Bh) */
	swap	%d0
	clr.w	%d0		 /* d0 = (Ah*Bl + Al*Bh) << 16 */

	add.l	%d2,%d0 	  /* d0 = A*B */
	move.l	%a2,%d3 	  /* restore d3 */
	rts
*
*A in d0, B in d1, return A/B in d0, A%B in d1
*
i_ldiv:
	tst.l	%d1
	bne	nz1

*	divide by zero
*	divu	#0,%d0		 /* cause trap */
	move.l	#0x80000000,%d0
	move.l	%d0,%d1
	rts
nz1:
	move.l	%d3,%a2 	  /* save d3 */
	cmp.l	%d1,%d0
	bhi	norm
	beq	is1
*	A<B, so ret 0, rem A
	move.l	%d0,%d1
	clr.l	%d0
	move.l	%a2,%d3 	  /* restore d3 */
	rts
*	A==B, so ret 1, rem 0
is1:
	moveq.l #1,%d0
	clr.l	%d1
	move.l	%a2,%d3 	  /* restore d3 */
	rts
*	A>B and B is not 0
norm:
	cmp.l	#1,%d1
	bne	not1
*	B==1, so ret A, rem 0
	clr.l	%d1
	move.l	%a2,%d3 	  /* restore d3 */
	rts
*  check for A short (implies B short also)
not1:
	cmp.l	#0xffff,%d0
	bhi	slow
*  A short and B short -- use 'divu'
	divu	%d1,%d0 	  /* d0 = REM:ANS */
	swap	%d0		 /* d0 = ANS:REM */
	clr.l	%d1
	move.w	%d0,%d1 	  /* d1 = REM */
	clr.w	%d0
	swap	%d0
	move.l	%a2,%d3 	  /* restore d3 */
	rts
* check for B short
slow:
	cmp.l	#0xffff,%d1
	bhi	slower
* A long and B short -- use special stuff from gnu
	move.l	%d0,%d2
	clr.w	%d2
	swap	%d2
	divu	%d1,%d2 	  /* d2 = REM:ANS of Ahi/B */
	clr.l	%d3
	move.w	%d2,%d3 	  /* d3 = Ahi/B */
	swap	%d3

	move.w	%d0,%d2 	  /* d2 = REM << 16 + Alo */
	divu	%d1,%d2 	  /* d2 = REM:ANS of stuff/B */

	move.l	%d2,%d1
	clr.w	%d1
	swap	%d1		 /* d1 = REM */

	clr.l	%d0
	move.w	%d2,%d0
	add.l	%d3,%d0 	  /* d0 = ANS */
	move.l	%a2,%d3 	  /* restore d3 */
	rts
*	A>B, B > 1
slower:
	move.l	#1,%d2
	clr.l	%d3
moreadj:
	cmp.l	%d0,%d1
	bhs	adj
	add.l	%d2,%d2
	add.l	%d1,%d1
	bpl	moreadj
* we shifted B until its >A or sign bit set
* we shifted #1 (d2) along with it
adj:
	cmp.l	%d0,%d1
	bhi	ltuns
	or.l	%d2,%d3
	sub.l	%d1,%d0
ltuns:
	lsr.l	#1,%d1
	lsr.l	#1,%d2
	bne	adj
* d3=answer, d0=rem
	move.l	%d0,%d1
	move.l	%d3,%d0
	move.l	%a2,%d3 	  /* restore d3 */
	rts


