;************************************************************************
;* TITLE	: CDG.S							*
;* Function	: Initialize CD-G playerand other routines		*
;*									*
;* Project #	: JAGUAR CD+G						*
;* Modified	: Pradip K Fatehpuria	06/29/94			*
;*									*
;* COPYRIGHT(c) 1992,1993 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.							*
;************************************************************************

	.title	"CDG.S - CD+G related routines"

;*======================================================================*
;* HEADER FILES								*
;*======================================================================*

	.include 'jaguar.inc'
	.include 'blitter.inc'
	.include 'objlist.inc'
	.include "defs.inc"

;*======================================================================*
;* LOCAL EQUATES							*
;*======================================================================*

FNT08PIX	equ	0

;*======================================================================*
;* EXTERNAL DATA							*
;*======================================================================*

	.extern	initproc

;*======================================================================*
;* EXTERNAL DATA							*
;*======================================================================*

	.extern	objData
	.extern	screnmem

	.extern	bldobflg

	.extern	CDGType

	.extern	XORFlag

	.extern	tvPH
	.extern	tvPV
	.extern	tvCOPH
	.extern	tvCOPV

	.extern	lnPH
	.extern	lnPV
	.extern	lnCOPH
	.extern	lnCOPV

	.extern	ScrlType
	.extern	ScrlColr

;*======================================================================*
;* PUBLIC ROUTINES							*
;*======================================================================*

	.globl	initapp

	.globl	initCDG

	.globl	setscren
	.globl	settvgrf
	.globl	setlngrf

	.globl	blitidle
	.globl	clrscren

	.globl	clrtvdsp
	.globl	clrtvgrf
	.globl	clrlndsp
	.globl	clrlngrf

	.globl	bltfnt08
	.globl	cp2tvdsp
	.globl	updtvgrf

	.globl	bltfnt16
	.globl	cp2lndsp
	.globl	updlngrf

;*======================================================================*
;* PUBLIC DATA								*
;*======================================================================*

	.globl	tvdspmem
	.globl	lndspmem

	.globl	fontdata

;************************************************************************
;* SUBROUTINE AREA							*
;************************************************************************

	.text

;*======================================================================*
;* INITAPP	: initialise application parameters			*
;*======================================================================*

initapp:
	move.w	#$07C0,BG		; set the background color (BLUE)
	move.l	#$000000FF,BORD1	; set the border color (BLUE)

	move.w	#$07C0,-(sp)		; set the color to BLUE
	bsr	clrscren		; use blitter to clear screen
	add.l	#2,sp

	move.w	#$0000,CDGType		; CD-G type variable (none/line/tv)

	move.w	#0,d0			; channel number zero to be displayed
	bsr	initCDG			; initialise the CDG player
.ret:	rts

;*======================================================================*
;* INITCDG	: initialise a CDG track player				*
;* INPUT	: d0.w = TV Channel number to be viewed			*
;*======================================================================*

initCDG:
	bsr	initproc		; initialise CD+G processing parameters
	bsr	initcol			; initialise color table

	move.l	#tvgrfmm1,d0		; initialise pointer to TV graphics memory
	move.l	d0,tvgrfmem

	move.l	#tvgrfmm2,d0		; initialise pointer to alternate TV graphics memory
	move.l	d0,tvotherm

	move.l	#lngrfmm1,d0		; initialise pointer to LINE graphics memory
	move.l	d0,lngrfmem

	move.l	#lngrfmm2,d0		; initialise pointer to alternate LINE graphics memory
	move.l	d0,lnotherm

	move.w	#$0101,-(sp)		; set the color to BLUE
	bsr	clrtvdsp		; clear TV-Graphics Display memory
	bsr	clrtvgrf		; clear TV-Graphics memory
	add.l	#2,sp

	move.w	#$07C0,-(sp)		; set the color to BLUE
	bsr	clrlndsp		; clear LINE-Graphics Display memory
	bsr	clrlngrf		; clear LINE-Graphics memory
	add.l	#2,sp

	move.w	#FALSE,-(sp)		; set the line graphics object
	bsr	setlngrf		;   to be deleted from
	bsr	settvgrf		;   the main object list
	add.l	#2,sp
	move.w	#TRUE,bldobflg		; re-build the object list
.ret:	rts

;*======================================================================*
;* INITCOL	: initialise color table				*
;*======================================================================*

initcol:
	movem.l	d0-d1/a0,-(sp)

	move.l	#CLUT,a0
	move.l	#255,d0
	move.w	#$07C0,d1		; make them all BLUE
.cpyloop:
	move.w	d1,(a0)+
	dbra	d0,.cpyloop

.ret:	movem.l	(sp)+,d0-d1/a0
	rts

;*======================================================================*
;* DEFCOLOR	: initialise color table				*
;*======================================================================*

defcolor:
	movem.l	d0/a0-a1,-(sp)

	move.l	#CLUT,a1
	move.l	#31,d0			; copy rom color table 32 times
.cpyloop:
	lea.l	romcolor,a0
	move.w	(a0)+,(a1)+
	move.w	(a0)+,(a1)+
	move.w	(a0)+,(a1)+
	move.w	(a0)+,(a1)+
	move.w	(a0)+,(a1)+
	move.w	(a0)+,(a1)+
	move.w	(a0)+,(a1)+
	move.w	(a0)+,(a1)+
	dbra	d0,.cpyloop

.ret:	movem.l	(sp)+,d0/a0-a1
	rts

;************************************************************************
;* ROUTNES TO MANIPULATE OBJECT LISTS					*
;************************************************************************

;*======================================================================*
;* SETSCREN	: enable/disable SCREEN object				*
;* SETTVGRF	: enable/disable TV-graphics				*
;* SETLNGRF	: enable/disable line graphics				*
;*======================================================================*

setscren:
	movem.l	d0/a0,-(sp)

	lea.l	objData+OBJSIZE*0,a0	; pointer to SCREEN Object
	move.w	$C(sp),d0		; load flag in d0
	beq.s	noobj
	bra.s	stobj

settvgrf:
	movem.l	d0/a0,-(sp)

	lea.l	objData+OBJSIZE*1,a0	; pointer to SCREEN Object
	move.w	$C(sp),d0		; load flag in d0
	beq.s	noobj
	bra.s	stobj

setlngrf:
	movem.l	d0/a0,-(sp)

	lea.l	objData+OBJSIZE*2,a0	; pointer to SCREEN Object
	move.w	$C(sp),d0		; load flag in d0
	beq.s	noobj

stobj:	andi.b	#(~DELETE_OBJ),O_TYPE(a0)
	movem.l	(sp)+,d0/a0
	rts

noobj:	ori.b	#DELETE_OBJ,O_TYPE(a0)
	movem.l	(sp)+,d0/a0
	rts

;************************************************************************
;* DIFFERENT OBJECT SCREEN CLEARING ROUTINES				*
;************************************************************************

;*======================================================================*
;* BLITIDLE	: waits for the BLITTER IDLE				*
;*======================================================================*

blitidle:
	move.l	d0,-(sp)
.wait:	move.l	B_CMD,d0
	lsr.w	#1,d0
	bcc	.wait
.ret:	move.l	(sp)+,d0
	rts

;*======================================================================*
;* CLRSCREN	: clears jaguar video screen using the blitter		*
;*======================================================================*

clrscren:
	move.l	d0,-(sp)		; save registers
	bsr	blitidle		; wait for blitter idle

	move.w	$8(sp),d0		; get the color in d0
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4
	move.w	d0,B_PATD+6

	move.l	#screnmem,A1_BASE	; point to the buffer
	move.l	#0,A1_PIXEL		; pointer to (0,0)
	move.l	#$0001FE80,A1_STEP	; step y = 1, x = -384
	move.l	#((200<<16)|(384)),B_COUNT ; do (h = 200, w = 384)
	move.l	#(PITCH1|PIXEL16|WID384|XADDPHR),A1_FLAGS ; flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; start the BLTTER
.ret:	move.l	(sp)+,d0		; restore registers
	rts

;*======================================================================*
;* CLRTVDSP	: clear the display memory for TV Graphics		*
;*======================================================================*

clrtvdsp:
	move.l	d0,-(sp)		; save registers
	bsr	blitidle		; wait for blitter idle

	move.w	$8(sp),d0		; get the color in d0
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4
	move.w	d0,B_PATD+6

	move.l	#tvdspmem,A1_BASE	; point to the buffer
	move.l	#0,A1_PIXEL		; pointer to (0,0)
	move.l	#$0001FEC0,A1_STEP	; step y = 1, x = -320
	move.l	#((192<<16)|(320)),B_COUNT ; do h = 192, w = 320
	move.l	#(PITCH1|PIXEL8|WID320|XADDPHR),A1_FLAGS ; flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; start the BLTTER
.ret:	move.l	(sp)+,d0		; restore registers
	rts

;*======================================================================*
;* CLRTVGRF	: clear the graphic memory for TV-Graphics		*
;*======================================================================*

clrtvgrf:
	move.l	d0,-(sp)		; save registers
	bsr	blitidle		; wait for blitter idle

	move.w	$8(sp),d0		; get the color in d0
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4
	move.w	d0,B_PATD+6

	move.l	tvgrfmem,A1_BASE	; point to the buffer
	move.l	#0,A1_PIXEL		; pointer to (0,0)
	move.l	#$0001FEC0,A1_STEP	; step y = 1, x = -320
	move.l	#((240<<16)|(320)),B_COUNT ; do h = 240, w = 320
	move.l	#(PITCH1|PIXEL8|XADDPHR|WID320),A1_FLAGS ; flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; start the BLTTER
.ret:	move.l	(sp)+,d0		; restore registers
	rts

;*======================================================================*
;* CLRLNDSP	: clear the display memory for LINE-Graphics		*
;*======================================================================*

clrlndsp:
	move.l	d0,-(sp)		; save registers
	bsr	blitidle		; wait for blitter idle

	move.w	$8(sp),d0		; get the color in d0
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4
	move.w	d0,B_PATD+6

	move.l	#lndspmem,A1_BASE	; point to the buffer
	move.l	#0,A1_PIXEL		; pointer to (0,0)
	move.l	#$0001FEC0,A1_STEP	; step y = 1, x = -320
	move.l	#((24<<16)|(320)),B_COUNT ; do h = 240, w = 320
	move.l	#(PITCH1|PIXEL16|XADDPHR|WID320),A1_FLAGS ; flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; start the BLTTER
.ret:	move.l	(sp)+,d0		; restore registers
	rts

;*======================================================================*
;* CLRLNGRF	: clear the graphic memory for LINE-Graphics		*
;*======================================================================*

clrlngrf:
	move.l	d0,-(sp)		; save registers
	bsr	blitidle		; wait for blitter idle

	move.w	$8(sp),d0		; get the color in d0
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4
	move.w	d0,B_PATD+6

	move.l	lngrfmem,A1_BASE	; point to the buffer
	move.l	#0,A1_PIXEL		; pointer to (0,0)
	move.l	#$0001FEC0,A1_STEP	; step y = 1, x = -320
	move.l	#((72<<16)|(320)),B_COUNT ; do h = 240, w = 320
	move.l	#(PITCH1|PIXEL16|XADDPHR|WID320),A1_FLAGS ; flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; start the BLTTER
.ret:	move.l	(sp)+,d0		; restore registers
	rts

;************************************************************************
;* ROUTINES FOR BLITTING TV-GRAPHICS					*
;************************************************************************

;*======================================================================*
;* bltfnt08(x, y)							*
;* INPUT :	d3.w = x position					*
;*		d4.w = y position					*
;*									*
;* Blit a font with 8 bits per pixel to TV-Graf Memory at (x,y)		*
;*======================================================================*

;************************
.if FNT08PIX
;************************

bltfnt08:
	bsr	blitidle		; wait for blitter idle

	mulu	#$6,d3			; calculate x position in pixel
	addi.w	#$6,d3			; add extra 6 bit offset on left to keep scope for scrolling with copy

	mulu	#$C,d4			; calculate y position in pixel
	addi.w	#$C,d4			; add extra 12 bit offset on top to keep scope for scrolling with copy

	move.w	d4,d0			; y position
	swap	d0			; set the destination pixel pointer 
	move.w	d3,d0			; must be y|x (save x position in d3)
	move.l	d0,A1_PIXEL		; offset into draw buffer
	move.l	#$0001FFFA,A1_STEP	; step increment y = 1, x = -6

	move.l	#0,A2_PIXEL		; source is always from 0,0
	move.l	#$0001FFFA,A2_STEP	; step increment y = 1, x = -6

	move.l	#((12<<16)|(6)),B_COUNT	; outer/inner loop counters, h = 12, w = 6

	move.l	#(PITCH1|PIXEL8|WID320|XADDPIX),A1_FLAGS ; setup the source and
	move.l	#(PITCH1|PIXEL8|WID8|XADDPIX),A2_FLAGS	 ; destination flags

	move.l	tvgrfmem,A1_BASE	; pointer to destination buffer
	move.l	#fontdata,A2_BASE	; pointer to character data

.bcmd:	move.w	XORFlag,d0		; set up the blitter commands
	beq.s	.rplc
.xor:	move.l	#(SRCEN|UPDA1|UPDA2|DSTEN|LFU_AN|LFU_NA|BUSHI),B_CMD
	rts
.rplc:	move.l	#(SRCEN|UPDA1|UPDA2|LFU_AN|LFU_A|BUSHI),B_CMD
	rts

;************************
.else
;************************

bltfnt08:
	bsr	blitidle		; wait for blitter idle

	mulu	#$6,d3			; calculate x position in pixel
	addi.w	#$6,d3			; add extra 6 bit offset on left to keep scope for scrolling with copy

	mulu	#$C,d4			; calculate y position in pixel
	addi.w	#$C,d4			; add extra 12 bit offset on top to keep scope for scrolling with copy

.a1pix:
	move.w	d4,d0			; y position
	swap	d0			; set the destination pixel pointer 
	move.w	d3,d0			; must be y|x (save x position in d3)
	move.l	d0,A1_PIXEL		; offset into draw buffer

	move.l	#((1<<16)|(6)),d1	; step increment y = 1, x = (-6 + delta)
	add.w	d1,d0			; d0 = end pixel in blit
	andi.w	#$7,d0			; check if end pixel on phrase boundary
	beq.s	.a1step			; yes, set step increment
	addi.w	#8,d1			; now add an offset of (8-d0) to the end pixel,
	sub.w	d0,d1			;   so that it reaches the phrase boundary
.a1step:
	neg.w	d1
	move.l	d1,A1_STEP		; step increment y = 1, x = -6+delta

.a2pix:
	move.l	#0,A2_PIXEL		; source is always from 0,0
	cmp.w	#2,d0
	beq.s	.a2step2
	cmp.w	#4,d0
	beq.s	.a2step2
.a2step1:
	move.l	#$0001FFF8,A2_STEP	; step increment y = 1, x = -6+delta(-2) = -8
	bra.s	.bcount
.a2step2:
	move.l	#$0001FFF0,A2_STEP	; step increment y = 1, x = -6+delta(-10) = -16

.bcount:
	move.l	#((12<<16)|(6)),B_COUNT	; inner/outer loop counters

.aflags:
	move.l	#(PITCH1|PIXEL8|WID320|XADDPHR),A1_FLAGS ; source flags
	move.l	#(PITCH1|PIXEL8|WID8|XADDPHR),A2_FLAGS	 ; destination flags

.abases:
	move.l	tvgrfmem,A1_BASE	; pointer to destination buffer
	move.l	#fontdata,A2_BASE	; pointer to character data

.bcmd:	move.w	XORFlag,d0		; set up the blitter commands
	beq.s	.rplc
.xor:	move.l	#(SRCEN|UPDA1|UPDA2|DSTEN|LFU_AN|LFU_NA|BUSHI),B_CMD
	rts
.rplc:	move.l	#(SRCEN|UPDA1|UPDA2|DSTEN|LFU_AN|LFU_A|BUSHI),B_CMD
	rts

;************************
.endif
;************************

;*======================================================================*
;* cp2tvdsp	: Copies the graphics memory to display memory when a	*
;*		  update of graphics memory occurs			*
;*======================================================================*

cp2tvdsp:

;****************************************
;* UPDATE DISPLAY FROM GRAPHICS MEMORY -
;*
;* copy the graphic memory to the display
;* memory depending upon (tvPH, tvPV) and
;* (tvCOPH, TVCOPV) starting from FONT
;* at position (1,1)
;*
;* Also, there is an extra one-font 
;* border around TV-graphics memory, 
;* which is used for Scrolling with COPY
;*
;****************************************

	bsr	blitidle		; wait for blitter idle

	move.l	#(SRCEN|UPDA1|UPDA2|LFU_A|LFU_AN),d2
.a1pix:
	move.l	#0,A1_PIXEL		; initialise the destination pixel pointer
.a1step:
	move.l	#$0001FEE0,A1_STEP	; step increment : y = 1, x = -288

.a2pix:
	move.w	#24,d0			; initialise the source pixel pointer
	add.w	tvPV,d0
	sub.w	tvCOPV,d0
	swap	d0
	move.w	#12,d0
	add.w	tvPH,d0
	sub.w	tvCOPH,d0
	move.l	d0,A2_PIXEL
	move.w	d0,d3			; d3 = save source starting x

	move.l	#((1<<16)|(288)),d1	; y = 1, x = -(288 + delta)
	add.w	d1,d0			; d0 = end pixel in blit
	andi.w	#$7,d0			; check if end pixel on phrase boundary
	beq.s	.a2flag			; yes, set step increment
	addi.w	#8,d1			; now add an offset of (8-d0) to the end pixel,
	sub.w	d0,d1			;   so that it reaches the phrase boundary
.a2flag:
	and.w	#$7,d3			; check if starts from a phrase boundary
	beq.s	.a2step			; yes, then no need for two source reads
	or.l	#SRCENX,d2		; the command flags for phrase boundary
.a2step:
	neg.w	d1			; x step value
	move.l	d1,A2_STEP		; step for A2 1 = +1 y|-288 x

.bcount:
	move.l	#((192<<16)|(288)),B_COUNT ; height|width of playfield

.aflags:
	move.l	#(PITCH1|PIXEL8|WID320|XADDPHR),A1_FLAGS ; source flags
	move.l	#(PITCH1|PIXEL8|WID320|XADDPHR),A2_FLAGS ; destination flags

.abases:
	move.l	#tvdspmem,A1_BASE	; base address of destination buffer
	move.l	tvgrfmem,A2_BASE	; base address of character data

.bcmd:	move.l	d2,B_CMD		; set up the blitter commands

.ret:	rts

;*======================================================================*
;* updtvgrf	: updates the graphics memory for commands like, screen	*
;*		  update with preset/copy				*
;*======================================================================*

updtvgrf:

;****************************************
;* SCROLL GRAPHICS MEMORY, IF NECESSARY
;*
;* in this case copy the bit-blit from
;* TV-graphics memory left/right and
;* up/down according to scroll with
;* preset or copy instruction
;*
;* arrange source/destination pixel
;* pointers as well as the blitter
;* flags so that the overlapping
;* memory area problem is taken
;* care of
;****************************************

	move.w	tvCOPH,d0		; check if either of COPH or COPV is set
	or.w	tvCOPV,d0
	beq	.ret			; quit

	bsr	blitidle		; wait for blitter idle

	move.l	#(SRCEN|UPDA1|UPDA2|LFU_A|LFU_AN),d2
.a1pix:
	move.w	#12,d0
	add.w	tvCOPV,d0		; destination y
	swap	d0
	move.w	#6,d0
	add.w	tvCOPH,d0		; destination x
	move.l	d0,A1_PIXEL		; prepare the destination pixel pointer
	move.w	d0,d3			; d3 = save x position

	move.l	#((1<<16)|(300)),d1	; step y = 1, x = -(300 + delta)
	add.w	d1,d0			; end pixel in blit
	andi.w	#$7,d0			; check if end pixel on phrase boundary
	beq.s	.a1step			; yes, set step increment
	addi.w	#8,d1			; now add an offset of (8-d0) to the end pixel,
	sub.w	d0,d1			;   so that it reaches the phrase boundary
.a1step:
	neg.w	d1
	move.l	d1,A1_STEP		; setup the destination step increment

.a2pix:
	move.l	#((12<<16)|(6)),A2_PIXEL ; source y = 12, x = 6
	cmp.w	#$6,d3			; are the starting x position same
	beq.s	.a2step			; no, then no need to make two source reads
	or.l	#SRCENX,d2		; the command flags for phrase boundary
.a2step:
	move.l	#$0001FECE,A2_STEP	; step increment : y = 1, x = -306

.bcount:
	move.l	#((216<<16)|(300)),B_COUNT ; inner/outer loop counters

.aflags:
	move.l	#(PITCH1|PIXEL8|WID320|XADDPHR),A1_FLAGS ; setup the source flags
	move.l	#(PITCH1|PIXEL8|WID320|XADDPHR),A2_FLAGS ; setup the destination flags

.abases:
	move.l	tvotherm,A1_BASE	; base adress of destination buffer
	move.l	tvgrfmem,A2_BASE	; base of address of source buffer

.bcmd:	move.l	d2,B_CMD		; let blitter go

;****************************************
;* SWAP TV graphics memory with it's
;* alternater memory buffer
;****************************************

.swaptvg:
	move.l	tvgrfmem,d0
	move.l	tvotherm,d1

	move.l	d0,tvotherm
	move.l	d1,tvgrfmem

;****************************************
;* PRESET/COPY the border according to
;* scroll instruction
;****************************************

.hz:	move.w	tvCOPH,d0
	beq.s	.vt
	bmi.s	.hzneg
.hzpos:	move.l	#((0<<16)|(6)),d1	; destination (y|x)
	move.l	#((0<<16)|(306)),d2	; source (y|x)
	bra.s	.chblt
.hzneg:	move.l	#((0<<16)|(300)),d1	; destination (y|x)
	move.l	#((0<<16)|(0)),d2	; source (y|x)
.chblt:	move.l	#((240<<16)|(6)),d3	; (height|width)
	bsr	blttvgrf

.vt:	move.w	tvCOPV,d0
	beq.s	.ret
	bmi.s	.vtneg
.vtpos:	move.l	#((12<<16)|(0)),d1	; destination (y|x)
	move.l	#((228<<16)|(0)),d2	; source y
	bra.s	.cvblt
.vtneg:	move.l	#((216<<16)|(0)),d1	; destination y
	move.l	#((0<<16)|(0)),d2	; source y
.cvblt:	move.l	#((12<<16)|(312)),d3	; height
	bsr	blttvgrf

.ret:	rts

;*======================================================================*
;* BLTTVGRF	: blit one portion of tv graphics memory to another	*
;*									*
;* INPUT :								*
;*	D1.l : Destination Y|X						*
;*	D2.l : Source Y|X						*
;*	D3.l : Height|Width						*
;*======================================================================*

blttvgrf:
	bsr	blitidle		; wait for blitter idle

	move.w	ScrlType,d0		; check if copy with preset or copy
	beq.s	scrlset
scrlcpy:				; SCROLL WITH COPY

; COPY SOURCE BLOCK TO DESTINATION BLOCK

	move.l	d1,A1_PIXEL		; destination pixel pointer (y|x)
	move.l	d2,A2_PIXEL		; source pixel pointer (y|x)

	move.l	#$00010000,d0
	move.w	d3,d0
	neg.w	d0
	move.l	d0,A1_STEP		; source step increment
	move.l	d0,A2_STEP		; destination step increment

	move.l	d3,B_COUNT		; set the inner\outer loop counters

	move.l	tvgrfmem,A1_BASE	; pointer to destination buffer
	move.l	tvgrfmem,A2_BASE	; pointer to source buffer

	move.l	#(PITCH1|PIXEL8|WID320|XADDPIX),A1_FLAGS ; source flags
	move.l	#(PITCH1|PIXEL8|WID320|XADDPIX),A2_FLAGS ; destination flags

	move.l	#(SRCEN|UPDA1|UPDA2|LFU_A|LFU_AN),B_CMD ; let it go
.ret:	rts

scrlset:				; SCROLL WITH PRESET

;************************
.if 0
;************************

; CLEAR THE SOURCE BLOCK

	bsr	blitidle		; wait for blitter idle

	move.w	ScrlColr,d0		; set the fill pattern and color
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4
	move.w	d0,B_PATD+6

	move.l	d2,A1_PIXEL		; source pixel pointer (y|x)

	move.l	#$00010000,d0
	move.w	d3,d0
	neg.w	d0
	move.l	d0,A1_STEP		; step -width x, +1 y each line

	move.l	d3,B_COUNT		; set the inner/outer loop counters

	move.l	#tvgrfmem,A1_BASE	; point to the buffer

	move.l	#(PITCH1|PIXEL8|WID320|XADDPIX),A1_FLAGS ; set the flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; start the BLTTER

;************************
.endif
;************************

; CLEAR THE DESTINATION BLOCK

	bsr	blitidle		; wait for blitter idle

	move.w	ScrlColr,d0		; set the fill pattern and color
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4
	move.w	d0,B_PATD+6

	move.l	d1,A1_PIXEL		; source pixel pointer (y|x)

	move.l	#$00010000,d0
	move.w	d3,d0
	neg.w	d0
	move.l	d0,A1_STEP		; step -width x, +1 y each line

	move.l	d3,B_COUNT		; set the inner/outer loop counters

	move.l	tvgrfmem,A1_BASE	; point to the buffer

	move.l	#(PITCH1|PIXEL8|WID320|XADDPIX),A1_FLAGS ; set the flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; start the BLTTER
.ret:	rts

;************************************************************************
;* ROUTINES FOR BLITTING LINE-GRAPHICS					*
;************************************************************************

;*======================================================================*
;* bltfnt16(x, y)							*
;* INPUT :	d3.w = x position					*
;*		d4.w = y position					*
;*									*
;* Blit a font with 16 bits per pixel to TV-Graf Memory at (x,y)	*
;*======================================================================*

bltfnt16:
	bsr	blitidle		; wait for blitter idle

	mulu	#$6,d3			; calculate x position in pixel
	addi.w	#$6,d3			; add extra 6 bit offset on left to keep scope for scrolling with copy

	mulu	#$C,d4			; calculate y position in pixel
	addi.w	#$C,d4			; add extra 12 bit offset on top to keep scope for scrolling with copy

	move.w	d4,d0			; y position
	swap	d0			; set the destination pixel pointer 
	move.w	d3,d0			; must be y|x
	move.l	d0,A1_PIXEL		; offset into draw buffer
	move.l	#$0001FFFA,A1_STEP	; step increment y = 1, x = -6

	move.l	#0,A2_PIXEL		; source is always from 0,0
	move.l	#$0001FFFA,A2_STEP	; step increment y = 1, x = -6

	move.l	#((12<<16)|(6)),B_COUNT	; outer/inner loop counters, h = 12, w = 6

	move.l	#(PITCH1|PIXEL16|WID320|XADDPIX),A1_FLAGS ; set the source and
	move.l	#(PITCH1|PIXEL16|WID6|XADDPIX),A2_FLAGS   ; destination flags

	move.l	lngrfmem,A1_BASE	; base address of destination buffer
	move.l	#fontdata,A2_BASE	; base address of character data

	move.l	#(SRCEN|UPDA1|UPDA2|LFU_A|LFU_AN),B_CMD ; let it go
.ret:	rts

;*======================================================================*
;* cp2lndsp	: Copies the graphics memory to display memory when a	*
;*		  update of graphics memory occurs			*
;*======================================================================*

cp2lndsp:

;****************************************
;* copy the LINE-graphic memory to the
;* LINE-display memory depending upon
;* (lnPH,lnPV) and (lnCOPH,lnCOPV)
;* starting from FONT (1,1)
;****************************************

	bsr	blitidle		; wait for blitter idle

	move.l	#0,A1_PIXEL		; initialise the destination pixel pointer
	move.l	#$0001FEE0,A1_STEP	; step increment = +1 y|-288 x

	move.w	#24,d0			; initialise the source pixel pointer
	add.w	lnPV,d0
	sub.w	lnCOPV,d0
	swap	d0
	move.w	#12,d0
	add.w	lnPH,d0
	sub.w	lnCOPH,d0
	move.l	d0,A2_PIXEL
	move.l	#$0001FEE0,A2_STEP	; step increment = +1 y|-288 x

	move.l	#((24<<16)|(288)),B_COUNT ; set the inner/outer loop counters

	move.l	#(PITCH1|PIXEL16|WID320|XADDPIX),A1_FLAGS ; source flags
	move.l	#(PITCH1|PIXEL16|WID320|XADDPIX),A2_FLAGS ; destination flags

	move.l	#lndspmem,A1_BASE	; base address of destination buffer
	move.l	lngrfmem,A2_BASE	; base address of source buffer

	move.l	#(SRCEN|UPDA1|UPDA2|LFU_A|LFU_AN),B_CMD ; let it go
.ret:	rts

;*======================================================================*
;* updlngrf	: updates the graphics memory for screen copy commands	*
;*======================================================================*

updlngrf:

;****************************************
;* SCROLL GRAPHICS MEMORY, IF NECESSARY
;*
;* in that case copy the blit in
;* graphics memory left/right and
;* up/down according to scroll with
;* preset or scroll with copy
;****************************************

	move.w	lnCOPH,d0		; check if either of COPH
	or.w	lnCOPV,d0		; or COPV is set
	beq	.ret			; quit

	bsr	blitidle		; wait for blitter idle

	move.w	#12,d0
	add.w	lnCOPV,d0		; destination y
	swap	d0
	move.w	#6,d0
	add.w	lnCOPH,d0		; destination x
	move.l	d0,A1_PIXEL		; set the destination pixel pointer
	move.l	#$0001FED4,A1_STEP	; destination step (y = 1, x = -300)

	move.l	#((12<<16)|(6)),A2_PIXEL ; source starting position
	move.l	#$0001FED4,A2_STEP	; source step (y = 1, x = -300)

	move.l	#((48<<16)|(300)),B_COUNT ; inner/outer loop counters

	move.l	#(PITCH1|PIXEL16|WID320|XADDPIX),A1_FLAGS ; source flags
	move.l	#(PITCH1|PIXEL16|WID320|XADDPIX),A2_FLAGS ; destination flags

	move.l	lnotherm,A1_BASE	; base of destination buffer
	move.l	lngrfmem,A2_BASE	; base of source buffer

	move.l	#(SRCEN|UPDA1|UPDA2|LFU_A|LFU_AN),B_CMD ; let it go

;****************************************
;* SWAP LINE graphics memory with it's
;* alternater memory buffer
;****************************************

.swaplng:
	move.l	lngrfmem,d0
	move.l	lnotherm,d1

	move.l	d0,lnotherm
	move.l	d1,lngrfmem

;****************************************
;* PRESET the border according to the
;* scroll instruction
;****************************************

.hz:	move.w	lnCOPH,d0
	beq.s	.vt
	bmi.s	.hzneg
.hzpos:	move.l	#((0<<16)|(6)),d1	; destination (y|x)
	move.l	#((0<<16)|(306)),d2	; source (y|x)
	bra.s	.chblt
.hzneg:	move.l	#((0<<16)|(300)),d1	; destination (y|x)
	move.l	#((0<<16)|(0)),d2	; source (y|x)
.chblt:	move.l	#((72<<16)|(6)),d3	; (height|width)
	bsr	bltlngrf

.vt:	move.w	lnCOPV,d0
	beq.s	.ret
	bmi.s	.vtneg
.vtpos:	move.l	#((12<<16)|(0)),d1	; destination (y|x)
	move.l	#((60<<16)|(0)),d2	; source (y|x)
	bra.s	.cvblt
.vtneg:	move.l	#((48<<16)|(0)),d1	; destination (y|x)
	move.l	#((0<<16)|(0)),d2	; source (y|x)
.cvblt:	move.l	#((12<<16)|(312)),d3	; (height|width)
	bsr	bltlngrf

.ret:	rts

;*======================================================================*
;* BLTLNGRF	: blit one portion of line graphics memory to another	*
;*									*
;* INPUT :								*
;*	D1.l : Destination Y|X						*
;*	D2.l : Source Y|X						*
;*	D3.l : Height|Width						*
;*======================================================================*

bltlngrf:

;************************
.if 0
;************************

; CLEAR THE SOURCE BLOCK

	bsr	blitidle		; wait for blitter idle

	move.w	ScrlColr,d0		; set the fill pattern and color
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4
	move.w	d0,B_PATD+6

	move.l	d2,A1_PIXEL		; set the source pixel pointer (y|x)

	move.l	#$00010000,d0		; set the source step value
	move.w	d3,d0
	neg.w	d0
	move.l	d0,A1_STEP

	move.l	d3,B_COUNT		; set the inner/outer loop counters

	move.l	lngrfmem,A1_BASE	; point to the buffer

	move.l	#(PITCH1|PIXEL16|WID320|XADDPIX),A1_FLAGS ; set flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; let it go

;************************
.endif
;************************

; CLEAR THE DESTINATION BLOCK

	bsr	blitidle		; wait for blitter idle

	move.w	ScrlColr,d0		; set the fill pattern and color
	move.w	d0,B_PATD		; select the color
	move.w	d0,B_PATD+2
	move.w	d0,B_PATD+4		; select Fill Pattern
	move.w	d0,B_PATD+6

	move.l	d1,A1_PIXEL		; set the source pixel pointer (y|x)

	move.l	#$00010000,d0		; set the source step value
	move.w	d3,d0
	neg.w	d0
	move.l	d0,A1_STEP

	move.l	d3,B_COUNT		; set the inner/outer loop counters

	move.l	lngrfmem,A1_BASE	; point to the buffer

	move.l	#(PITCH1|PIXEL16|WID320|XADDPIX),A1_FLAGS ; set flags

	move.l	#(PATDSEL|UPDA1),B_CMD	; let it go
.ret:	rts

;************************************************************************
;* CONSTANT DATA AREA							*
;************************************************************************

	.data

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

		.phrase

romcolor:	.dc.w	$0000		; Black
		.dc.w	$07C0		; Blue
		.dc.w	$003F		; Green
		.dc.w	$07FF		; Cyan
		.dc.w	$F800		; Red
		.dc.w	$FFC0		; Magenta
		.dc.w	$F83F		; Yellow
		.dc.w	$FFFF		; White

		.phrase

;************************************************************************
;* VARIABLE DATA AREA							*
;************************************************************************

	.bss

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

		.phrase

tvdspmem:	.ds.w	(320*192)/2	; graphics memory for TV-Graphics
tvgrfmm1:	.ds.w	(320*240)/2	; graphics memory for TV-Graphics
tvgrfmm2:	.ds.w	(320*240)/2	; graphics memory for TV-Graphics

lndspmem:	.ds.w	(320*24)	; graphics memory for LINE-Graphics
lngrfmm1:	.ds.w	(320*72)	; graphics memory for LINE-Graphics
lngrfmm2:	.ds.w	(320*72)	; graphics memory for LINE-Graphics

dummy:		.ds.w	256		; just some dummy memory area

		.phrase

fontdata:	.ds.w	72		; memory for font data

dummy1:		.ds.w	256		; just some dummy memory area

		.phrase

tvgrfmem:	.ds.l	1		; pointer to TV graphics memory
tvotherm:	.ds.l	1		; pointer to alternate TV graphics memory

lngrfmem:	.ds.l	1		; pointer to LINE graphics memory
lnotherm:	.ds.l	1		; pointer to alternate LINE graphics memory

		.phrase

;************************************************************************
;* END OF FILE								*
;************************************************************************

	.end
