;*======================================================================*
;*                TITLE:                  INIT.S                        *
;*                Function:               68000 Initialization routines *
;*                                                                      *
;*                Project #:              JAGUAR                        *
;*                                                                      *
;*                Programmer:             Robert J Zydbel               *
;*                                        Andrew J Burgess              *
;*                                                                      *
;*                Started:                10/30/92 .. RJZ               *
;*                                                                      *
;*              COPYRIGHT 1992 Atari Computer Corporation               *
;*          UNATHORIZED REPRODUCTION, ADAPTATION, DISTRIBUTION,         *
;*          PERFORMANCE OR DISPLAY OF THIS COMPUTER PROGRAM OR          *
;*        THE ASSOCIATED AUDIOVISUAL WORK IS STRICTLY PROHIBITED.       *
;*                            ALL RIGHTS RESERVED.                      *
;*                                                                      *
;*======================================================================*
;*	Initialize()	- intialize the 68000 and GPU
;*	ClrDispBuf()	- clear the display buffer, using the BLITTER
;*	ClrDuildBuf()	- clear the build buffer, using the BLITTER
;*	ClrDaramBuf()	- clear the parameter buffer
;*	ChangeDisplay()	- swap the display and build buffer pointers
;*	IntInit()	- initialize VBLANK
;*	CopyObjList()	- copy Obj List ram
;*	Random()	- Random number generator
;*======================================================================*

	.title	"INIT.S - initialization routines"

BASE		EQU	$00D00000		;* 68000 register base address	*
BAR_ON		EQU	1

TOTAL_OBJS	EQU	1
OBJSIZE		EQU	((8*TOTAL_OBJS)+2)


	.include	"jaguar.inc"
	.include	"blit.inc"
	.include	"defs.inc"

	.text

;*======================================================================*
;* Setup the high memory area:
;*
;*	+-------------------------------+ 00000000
;*	|	Program space		|
;*	|		|		|
;*	|		|		|
;*	|		\/		|
;*		      . . .
;*	|		^		|
;*	|		|		|
;*	|		|		|
;*	+-------------------------------+ DISPBUF1 - BUFFERSIZE
;*	|	    DISPBUF2		|
;*	|		|		|
;*	|		\/		|
;*	+-------------------------------+ ENDRAM - BUFFERSIZE
;*	|	    DISPBUF1		|
;*	|		|		|
;*	|	        \/		|
;*	+-------------------------------+ ENDRAM
;*
;* Define 2 buffers that are the screen size (320x200 pixels)
;* Remember that these buffers must take into account the pixel bit depth
;* In this example we are using 16 bit pixels ( CRY color scheme) Thus
;* we need 2 bytes per pixel.
;*
;* Next setup a parameter ram area to be shared between the 68K and the
;* GPU. This will be used to pass parameters between the 2 processors
;*
;* Finally, setup the 68k stack pointer
;*
;*======================================================================*
LONGDATA	EQU	4
PTRSIZE		EQU	LONGDATA
COUNTSIZE	EQU	LONGDATA
VERTSIZE	EQU	(2*LONGDATA)
MAXCOL		EQU	320
MAXROW		EQU	200
BUFFERSIZE	EQU	(MAXCOL*MAXROW*2)

DISPBUF1	EQU	ENDRAM-BUFFERSIZE
DISPBUF2	EQU	DISPBUF1-BUFFERSIZE
;*======================================================================*

;*======================================================================*
;*		EXTERNAL DECLARATION
;*======================================================================*
	.globl	olist_ptr	; Pointer to Active Object List
	.globl	olist_ram	; Storage for Active Object List
	.globl	olist_end	; End of Active Object List
	.globl	olist		; Storage for Master Object List
	.globl	olist_data	; Prepackeged Object List
	.globl	obj_display	; Display bitmap object

	.globl	param_ptr	; Pointer to shared parameter buffer
	.globl	disp_ptr	; screen buffer address
	.globl	draw_ptr	; build buffer address
	.globl	curDisplay	; current display buffer flag

	.globl	VideoIni	; video initialization
	.globl	VBlank		; VBLANK interrupt
	.globl	ClrGpuBuf	; GPU buffer clear
	.globl	ClrMatrices	; clear rotate data areas


;*======================================================================*
;* Initialize()	- intialize the 68000 and GPU
;*
;*	input:
;*		a0	- 68000 address of GPU program
;*		a1	- GPU RAM address to load into
;*
;*	preserved:
;*		d0-d2
;*		a0-a1
;*======================================================================*

	.globl	Initialize

Initialize:
	movem.l	d0-d2/a0-a1,-(sp)	; save registers

	jsr	VideoIni		; initialize video interrupt

	;* enable Fast DRAM
	move.w	MEMCON1,d0
	or	#$60,d0
	move.w	d0,MEMCON1	; set to fast DRAM

	;* run GPU in Intel I/O mode, Motorola Pixel Mode
	move.l	#$00020002,G_BIGEND

	;* set to build and display pointers
	clr.b	curDisplay
	move.l	#DISPBUF1,disp_ptr
	move.l	disp_ptr,a0
	jsr	ClrDispBuf
	move.l	#DISPBUF2,draw_ptr
	move.l	draw_ptr,a0
	jsr	ClrBuildBuf

; At this point I will set up an object list containing
; a Branch object, a Scaled Bit map object and a Stop object.
;	move	#(5*2)-1,d1
	move	#OBJSIZE-1,d1
	lea	olist_data,a1
	lea	olist,a0
.ocopy:	move.l	(a1)+,(a0)+	; Copy Raw Object list to Master Olist
	dbra	d1,.ocopy

	move.l	#olist_ram,d0
	add.l	#40,d0
	and.l	#$ffffffe0,d0
	subq.l	#8,d0		; Adjust ptr to 4*Phrase - Phrase Boundary
	move.l	d0,olist_ptr	; OLIST_PTR = Ptr to Displayable Object List
	add.l	#32,d0		; d0 = Ptr to Stop Object
	lsr.l	#3,d0
	move.l	d0,d1
	ror.l	#8,d0
	and.l	#$ff000000,d0
	lsr.l	#8,d1
	and.l	#$0fff,d1	; Split for Hardware Fucks
	lea	olist,a0	; point to olist once again
	move.l	4(a0),d2
	or.l	d0,d2
	move.l	d2,4(a0)
	move.l	d1,(a0)		; Patch-Up Branch Object
	or.l	d0,12(a0)
	move.l	#DISPBUF1,d0
	lsr.l	#3,d0
	lsl.l	#6,d0
	lsl.l	#6,d0
	or.l	d0,d1
 	move.l	d1,8(a0)	; Patch-Up Bitmap Object

;	move	#(5*2)-1,d1
	move	#OBJSIZE-1,d1
	move.l	olist_ptr,a0
	lea	olist,a1
.cpylp:	move.l	(a1)+,(a0)+	; Copy Object list to display space
	dbra	d1,.cpylp

	move.l	olist_ptr,d0
	swap	d0
	move.l	d0,OLP		; Point to finished Object List

 	jsr	IntInit

	;* clear various buffers
	jsr	ClrGpuBuf
	jsr	ClrMatrices

	move.w	#$C1,VMODE	; Turn on the display

	movem.l	(sp)+,a0-a1/d0-d2	; restore registers

	rts

;*======================================================================*
;* ClrDispBuf()		- clear the display buffer, using the BLITTER
;* ClrBuildBuf()	- clear the build buffer, using the BLITTER
;*
;*	preserved:
;*		d0
;*		a0
;*======================================================================*

	.globl	ClrDispBuf
	.globl	ClrBuildBuf

ClrDispBuf:
ClrBuildBuf:
	movem.l	d0/a0,-(sp)		; save registers

	TIMEBAR	RGB_WHITE

 	move.l	#(PITCH1|PIXEL16|WID320|XADDPHR),d0
	swap	d0
	move.l	d0,A1_FLAGS

	move.l	a0,d0
	swap	d0
	move.l	d0,A1_BASE

	move.w	#(-MAXCOL),d0
	swap	d0
	move.w	#1,d0
	move.l	d0,A1_STEP

	move.w	#MAXCOL,d0
	swap	d0
	move.w	#(MAXROW),d0
	move.l	d0,B_COUNT

	clr.l	d0
	move.l	d0,A1_PIXEL
	move.l	d0,B_PATD
	move.l	d0,B_PATD+4

	move.l	#(PATDSEL|UPDA1),d0
	swap	d0
	move.l	d0,B_CMD

	;* wait for the Blitter to complete before continuing
	;* remember that it is recommended that an extra read
	;* occur before releasing the Blitter for BUG 5
	;* BUT the 68000 is an external memory access and the
	;* blitter must release before the 68000 get the bus
	;* therefore, BUG 5 does not apply
.waitblit:
	move.l	#B_CMD,a0
	move.l	(a0),d0
	swap	d0
	btst	#11,d0
	beq	.waitblit

	TIMEBAR	RGB_BLACK

	movem.l	(sp)+,a0/d0		; restore registers

	rts

;*======================================================================*
;* ChangeDisplay()	- swap the display and build buffer pointers
;*
;*	preserved:
;*		a0
;*======================================================================*

	.globl	ChangeDisplay

ChangeDisplay:
	move.l	a0,-(sp)		;* save registers

	;* which is the current Display buffer
	tst.b	curDisplay
	bne	.disp2

	;* the current display buffer is DISPBUF1
.disp1:
	move.l	#DISPBUF1,draw_ptr
	move.l	#DISPBUF2,disp_ptr
	move.b	#1,curDisplay
 	bra	.chgdone

	;* the current display buffer is DISPBUF2
.disp2:
	move.l	#DISPBUF2,draw_ptr
	move.l	#DISPBUF1,disp_ptr
	clr.b	curDisplay

.chgdone:
	move.l	(sp)+,d0		; restore registers

	rts

;*======================================================================*
;* IntInit()	- initialize VBLANK
;*
;* This will set up the VI (Vertical line counter Interrupt)
;* Or it would if the low order bit of INT1 REALLY was the VI interrupt
;*
;*	preserved:
;*		d0
;*======================================================================*

 	.globl	IntInit

IntInit:
	movem.l	d0,-(sp)		; save registers

	move.l	#VBlank,LEVEL2

.if	BAR_ON != 0
	move.w	#51,VI			; (must be ODD)
.else
	move.w	#451,VI			; (must be ODD)
.endif

	move.w	#1,INT1
	move.w	sr,d0
	and.w	#$f8ff,d0
	move.w	d0,sr

	movem.l	(sp)+,d0		; restore registers

	rts

;*======================================================================*
;* CopyObjList()	- copy Obj List ram
;*
;*	preserved:
;*		d1-d3
;*		a0-a2
;*======================================================================*

	.globl	CopyObjList

BROBJ		EQU	(2*LONGDATA) 
BITOBJ		EQU	(BROBJ+(4*LONGDATA))
STPOBJ		EQU	(BROBJ+BITOBJ)

SCRNADDR	EQU	(BROBJ)

CopyObjList:
	movem.l	d1-d3/a0-a2,-(sp)

	move.l	olist_ptr,a0
	move.l	a0,a2

	move.l	#OBJSIZE-1,d1
	lea	olist,a1
.cpylp:	move.l	(a1)+,(a0)+	; Copy Object list to display space
	dbra	d1,.cpylp

	;* Tell the object list where the display buffer is
	move.l	disp_ptr,d2			;* D2 = Data Pointer
	lsr.l	#3,d2				;* long align
	lsl.l	#6,d2				;* move into upper 5 nibbles
	lsl.l	#6,d2
	move.l	SCRNADDR(a2),d3			;* D3 = old addr
	and.l	#$0000003F,d3			;* retain upper 3 nibbles of
						;*	Link Pointer
	or.l	d2,d3				;* recombine Data Pointer and Link Pointer
	move.l	d3,SCRNADDR(a2)			;* put back into display buffer

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

	rts

;*======================================================================*
;* Random()	- Random number generator
;*
;*	output:
;*		d0 = random number
;*
;*	preserved:
;*		d1
;*		a0
;*======================================================================*

Random:
	movem.l	d1/a0,-(sp)		; save registers

	lea	seed,a0
	move.l	#4,d1		; move 5 numbers
.loop:	move.l	4(a0),(a0)+	; move seed number one spot to the left
	dbra	d1,.loop
	move.l	seed,d1		; get first seed number
	add.l	seed+12,d1	; add fourth see number
	add.l	d1,seed+20	; add first + fourth to sixth seed number
	move.l	seed,d0		; return first seed number

	movem.l	(sp)+,d1/a0		; restore registers

	rts

;*======================================================================*

seed:
	dc.l	$00000123,$00ABCF01,$00000110,$0000FEA9,$0000013F,$00045001

;*======================================================================*

	.END

;*=====================================================================*
;*	    		EOF
;*=====================================================================*

