;...................................
;: (c) 1993 Rebellion Software Ltd :
;: Hand coded by R.C.Dibley - 1993 :
;:.................................:

.text

Obj_blank::				; to clear the off screen object - in a double buffered, z buffered space
	move.l	#obj_store,d0			; main address
	move.l	screen.w,d1			; screen decides which is off screen
;	asl.w	#3,d1
	add.l	d1,d0
	bsr	WaitBlit
	move.l	d0,A1_BASE			; base address

	tst.b	display_mode.w
	beq	clear

	move.l	#PIXEL16|PITCH2|WID320,A1_FLAGS
	moveq	#0,d0
	move.l	d0,A1_PIXEL
	move.l	d0,A1_CLIP
	move.w	#250-60,d0			; basic horizon height to ensure always enough exists
	add.w	Horizon_h.w,d0			; actual required height
	lsr.w	#1,d0				; make into real lines - otherwise in halfs
	cmp.w	#125,d0
	ble.b	.use
	move.w	#125,d0
.use:	move.w	d0,-(sp)		; stack for use in second half
	swap	d0
	move.w	#320,d0				; width
	move.l	d0,B_COUNT

	move.w	#60,d0
	sub.w	Horizon_h.w,d0
	bpl.b	.ok
	moveq	#0,d0
.ok:	lsr.w	#1,d0
	swap	d0
	move.w	Genstr+2,d0			; x position
	and.w	#$3ff,d0			; limit to valid zone
	move.l	d0,A2_PIXEL

	move.l	#PIXEL16|WID1024,A2_FLAGS
	move.l	#bit_store,A2_BASE

	and.w	#3,d0		; 0 1 2 3	; alignment offset in pixels
	ext.l	d0
	beq.b	.na
	subq.w	#4,d0		; - 3 2 1 
.na:	sub.w	#320,d0
	bset	#16,d0
	move.l	d0,A2_STEP

	and.l	#3,d0				; see if any offset
	beq.b	.nex
	move.l	#SRCENX,d0			; put in extra read if needed
.nex:	or.l	#SRCEN|UPDA2|LFUSRC,d0		; set up rest of command
	move.l	d0,B_CMD

	clr.l	blitsem.w
	bsr	WaitBlit



	move.w	(sp),d0				; read height that was blitted but keep on stack
	swap	d0
	clr.w	d0				; clear x co-ord
	move.l	d0,A1_PIXEL			; set pixel pointer to account for new sizes

	move.l	#PIXEL32|PITCH2|WID160,A1_FLAGS	; and set new flags

	move.l	#260,d0		; total to clear
	sub.w	(sp)+,d0			; deduct height blitted already
	bmi.b	.ex
	swap	d0
	move.w	#320/2,d0			; 320 pixels, 2 at a time
	move.l	d0,B_COUNT

	move.l	ground.w,d0
	move.l	d0,B_PATD
	move.l	d0,B_PATD+4
	move.l	#PATDSEL,B_CMD
.ex:	clr.l	blitsem.w
	rts


clear:	move.l	#$29,A1_FLAGS			; 32bit, pitch 2 (=1 gaps), phrase mode
	moveq.l	#0,d0				; clear to black
	move.l	d0,A1_PIXEL			; no offset
	move.l	d0,A1_CLIP			; possible bug fix
;	move.l	#(160*112+$10000),B_COUNT	; 320*200 pixels, but two at a time
;	move.w	Horizon_h.w,d0			; horizon height adjustment
;	add.w	#96*2,d0
;	mulu	#80,d0				; width quartered, because height adjust is in half lines, and we blit in longs
	move.l	#260,d0
	swap	d0
	move.w	#160,d0
	bset	#16,d0				; correct counter
	move.l	d0,B_COUNT

	move.l	background.w,d0
	move.l	d0,B_PATD			; put blank into pattern data
	move.l	d0,B_PATD+4			; and second half
	move.l	#$00010000,B_CMD		; Go

	clr.l	blitsem.w
.if 0
	bsr.b	WaitBlit

;	move.l	#(160*128+$10000),B_COUNT
	move.w	#480-(96*2),d0				; twice screen height because height is in half lines
	sub.w	Horizon_h.w,d0
	bmi.b	.ex
;	bpl.b	.ok
;	illegal
	mulu	#80,d0
	bset	#16,d0
	move.l	d0,B_COUNT

	move.l	ground.w,d0
	move.l	d0,B_PATD
	move.l	d0,B_PATD+4
	move.l	#$10000,B_CMD
.ex:	clr.l	blitsem.w
.endif
	rts


WaitBlit:: 
	move.l	d7,-(sp)

wmore:	move.l	B_CMD,d7		; get Blitter status
	btst	#0,d7		; check outer loop idle
	beq.b	wmore		; wait until outer loop IS idle

wms:	tst.l	blitsem.w
	bne.b	wms

	moveq.l	#1,d7		; note this is quicker than addq.l #1,blitsem.w
	move.l	d7,blitsem.w	; 4+20<12+16

	move.l	(sp)+,d7
	rts

WaitBlit2::			; version for use when 
	move.l	d7,-(sp)
.lp:	move.l	B_CMD,d7
	btst	#0,d7
	beq.b	.lp
	move.l	(sp)+,d7
	rts


Blank::			; subroutine to blank out d0 bytes from d1 onwards - whole phrases only
	bsr	WaitBlit
	move.l	d1,A1_BASE		; base address
	move.l	#PIXEL32,A1_FLAGS	; flags set for : 32 bit data, phrase data mode.

	lsr.l	#3,d0		; because bytes become phrases
	swap	d0
	move.w	#2,d0
	swap	d0
	move.l	d0,B_COUNT	; put into inner loop counter
	moveq.l	#0,d0
	move.l	d0,A1_PIXEL	; set offset pointer to zero
;	move.l	d0,B_PATD	; put blank into pattern data
;	move.l	d0,B_PATD+4	; and second half

;	move.l	#$00010000,d0	; command to write pattern data
	move.l	d0,B_CMD	; and GO !
	clr.l	blitsem.w

	rts


Blit_move::		; moving from d0 to d1, d2 bytes rounded up (may overshoot)
	movem.l	d0-d3,-(sp)

	bsr	WaitBlit
	move.l	d0,-(sp)	; retain address for getting offset
	and.l	#$FFFFFFF8,d0	; round to phrase
	move.l	d0,A2_BASE	; put in

	move.l	(sp)+,d0	; recover address
	and.l 	#$7,d0		; limit to possible offsets - 0-7
	move.l	d0,-(sp)
	move.l	d0,A2_PIXEL	; put in

	move.l	#$000018,d0	; set mode to 8 bits, phrase mode
	move.l	d0,A2_FLAGS	; write in
	move.l	d0,A1_FLAGS	; to both sides

	move.l	d1,d0		; retain address
	and.l	#$FFFFFFF8,d1	; round to phrase
	move.l	d1,A1_BASE	; put in

	move.l	d0,d1		; recover
	and.l	#$7,d1		; limit
	move.l	d1,A1_PIXEL	; put in

	add.l	#$10000,d2	; to set Y count loop to one time
	move.l	d2,B_COUNT
	move.l	#$01800005,d0

	move.l	(sp)+,d2	; get back source pixel offset
	cmp.l	d2,d1		; check against target one - only need extra read if source offset is >> target offset
	blt.b	.off
	bclr	#2,d0
.off:	move.l	d0,B_CMD
	clr.l	blitsem.w
	movem.l	(sp)+,d0-d3
	rts


Long_blit::		; move from d0 to d1, d2 bytes but move as longs to allow more to shift [max then = $40000 bytes]
	movem.l	d0-d2,-(sp)	; aligning addresses is assumed to be the callers responsibility

	bsr	WaitBlit
	move.l	d0,-(sp)	; retain address for getting offset
	and.w	#$FFF8,d0	; round to phrase
	move.l	d0,A2_BASE	; put in

	move.l	(sp)+,d0	; recover address
	and.l 	#$7,d0		; limit to possible offsets - 0-7
	asr.l	#2,d0		; scale down because longs used so 2 pixels = 1 phrase
	move.l	d0,-(sp)
	move.l	d0,A2_PIXEL	; put in

	move.l	#PIXEL32,d0	; set mode to 32 bits, phrase mode
	move.l	d0,A2_FLAGS	; write in
	move.l	d0,A1_FLAGS	; to both sides

	move.l	d1,d0		; retain address
	and.w	#$FFF8,d1	; round to phrase
	move.l	d1,A1_BASE	; put in

	move.l	d0,d1		; recover
	and.l	#$7,d1		; limit
	asr.l	#2,d1
	move.l	d1,A1_PIXEL	; put in

	addq.l	#3,d2		; make sure rounding is up not down !
	asr.l	#2,d2		; scale down for longs
	add.l	#$10000,d2	; to set Y count loop to one time
	move.l	d2,B_COUNT
	move.l	#(SRCEN|SRCENX|LFUSRC),d0

	move.l	(sp)+,d2
	cmp.l	d2,d1
	blt.b	.off
	bclr	#2,d0		; remove SRCENX
.off:	move.l	d0,B_CMD
	clr.l	blitsem.w
	movem.l	(sp)+,d0-d2
	rts


blit_cockpit::
	move.l	#obj_store,d0			; main address
	tst.l	screen.w			; screen decides which is off screen
	bne.b	.sk
	addq.l	#8,d0
.sk:	tst.l	viewmove.w
	beq.b	.ok
	bchg	#3,d0
.ok:	bsr	WaitBlit
	move.l	d0,A1_BASE			; base address

	move.l	#PIXEL16|PITCH2|WID320,A1_FLAGS	; will be a straight phrase mode blit, no clever stuff
	moveq	#0,d0
	move.l	d0,A2_PIXEL
	move.l	d0,A1_CLIP
	move.l	d0,B_PATD
	move.l	d0,B_PATD+4
	move.l	#98<<16|320,B_COUNT

	moveq	#0,d0
	move.w	#152,d0
	tst.b	ntsc_type.w
	bne.b	.nt
	move.w	#174,d0
.nt:	swap	d0
	move.l	d0,A1_PIXEL
	move.l	#PIXEL16,A2_FLAGS
	move.l	#cockpit,A2_BASE

	move.l	#SRCEN|LFUSRC|DCOMPEN|DSTEN,B_CMD
	clr.l	blitsem.w
	rts

;===================================================

.if	programmer

Sky_blank::		; to reset the sky to plain blue bands - very old, no longer used
move.l	#sky_store,d0	; main address
bsr	WaitBlit
move.l	d0,A1_BASE		; base address
move.l	#$28,A1_FLAGS		; 32bit, pitch 1 (=1 gaps), phrase mode
move.l	#0,A1_PIXEL		; no offset
move.l	#(320*62+$10000),B_COUNT	; 320*124 pixels, but two at a time
move.l	background.w,d0
and.l	horizon.w,d0
move.l	d0,B_PATD		; put colour into pattern data
move.l	d0,B_PATD+4		; and second half
move.l	#$00010000,B_CMD	; Go
clr.l	blitsem.w

move.l	#3,d1		; four lines
.loop1:
bsr	WaitBlit
move.l	#(160+$10000),B_COUNT	; 320 pixels, but two at a time
add.l	#$10001000,d0
move.l	d0,B_PATD		; put colour into pattern data
move.l	d0,B_PATD+4		; and second half
move.l	#$00010000,B_CMD	; Go
clr.l	blitsem.w

dbra	d1,.loop1

move.l	#$88808880,d0		; partial green
move.l	#1,d1		; two lines

.loop2:
bsr	WaitBlit
move.l	#(160+$10000),B_COUNT	; 320 pixels, but two at a time
add.l	#$03000300,d0
move.l	d0,B_PATD		; put colour into pattern data
move.l	d0,B_PATD+4		; and second half
move.l	#$00010000,B_CMD	; Go
clr.l	blitsem.w

dbra	d1,.loop2


bsr	WaitBlit
move.l	#(320*63+$10000),B_COUNT
move.l	ground.w,d0
and.l	horizon.w,d0
move.l	d0,B_PATD		; put colour into pattern data
move.l	d0,B_PATD+4		; and second half
move.l	#$00010000,B_CMD	; Go
clr.l	blitsem.w
rts


.endif

;===============================================

full_blank::
	movem.l	d0-d2,-(sp)
	move.l	#$3C000,d0
	move.l	#gpusem,d1
	bsr	Blank

	moveq.l	#6,d2		; counter
	moveq.l	#0,d1		; start at 0 - because first action is to move pointer on
.lp:	move.l	#$40000,d0	; length of block (maximum size) is 256k
	add.l	d0,d1		; add length to address being wiped
	bsr	Blank
	dbra	d2,.lp

	movem.l	(sp)+,d0-d2
	rts

;===============================================================

.if 0
pwid	set	128
phigh	set	40

a1stp	set	($10000|($FFFF&(-pwid)))
bcnt	set	((phigh<<$10)|pwid)

show_pause::				; blit a pause symbol onto screen at x,y
	movem.l	d0-d1/a0,-(sp)

	movea.w	#gpusem,a0
.wait:	tst.l	(a0)
	bne.b	.wait

	move.l	#obj_store+8,d0			; main address
	move.l	screen.w,d1			; screen decides which is off screen
;	asl.w	#3,d1
	sub.l	d1,d0
	bsr	WaitBlit
	move.l	d0,A1_BASE			; base address

	move.l	#WID320|PIXEL16|PITCH2,A1_FLAGS	; 32 bit, pitch 1 (=1 gaps), phrase mode

	move.l	#$500060,A1_PIXEL		; offset at (96,80)
	move.l	#a1stp,A1_STEP		; stepping back distance

	moveq.l	#0,d0				; 
	move.l	d0,A1_CLIP			; possible bug fix
	move.l	d0,A2_PIXEL
	move.l	d0,B_PATD
	move.l	d0,B_PATD+4

	move.l	#bcnt,B_COUNT		; size of image

	move.l	#Exdisp,A2_BASE		; current address of Pause display
	move.l	#WID128|PIXEL16,A2_FLAGS

	move.l	#DSTEN|SRCEN|UPDA1|LFUSRC|DCOMPEN,B_CMD	;

	clr.l	blitsem.w
	bsr	WaitBlit
	clr.l	blitsem.w

	movem.l	(sp)+,d0-d1/a0
	rts
.endif
;===============================================================

; input	d0 = character (1-30 : ABCDEFGHIJKLMNOPQRSTUVWXYZ:/. )
; 	d1 = x position of upper left pixel
;	d2 = y position of upper left pixel
;	d3 = 0 for transparent else solid blit
;	a1 = screen address - just to make it really flexible
; translation note : for ease of use the codes are just ascii-64, so the following translations need to be applied
; : = [
; / = \
; . = ]
; spc = ^

Blit_char::				; general one character blit
	movem.l	d0-d2,-(sp)

	bsr	WaitBlit

	move.l	a1,A1_BASE		; A1 is destination
	swap	d2
	move.w	d1,d2
	move.l	d2,A1_PIXEL

	move.l	#$d000a,B_COUNT		; 10 wide, 13 high

	move.l	#PIXEL16|WID16|XADDPIX,A2_FLAGS
	move.l	#PIXEL16|WID320|XADDPIX,A1_FLAGS

	moveq	#$1f,d1
	and.l	d1,d0			; makes absolutely sure about what we have in d0 !
	swap	d0
	asr.l	#7,d0			; total multiply by $200 - size of one letter
	add.l	#Mapdisp-$200,d0	; -$200 corrects for A being character 1, not 0
	move.l	d0,A2_BASE		; A2 is source

	move.l	#$1fff6,d0
	move.l	d0,A2_STEP
	move.l	d0,A1_STEP

	moveq	#0,d0
	move.l	d0,B_PATD
	move.l	d0,A2_PIXEL
	move.l	d0,A1_CLIP		; jic

	tst.l	d3
	beq.b	.ok
	move.l	#SRCEN|UPDA1|UPDA2|LFUSRC,B_CMD
	bra.b	.dn

.ok:	move.l	#SRCEN|UPDA1|UPDA2|LFUSRC|DCOMPEN,B_CMD
.dn:	clr.l	blitsem.w

	movem.l	(sp)+,d0-d2
	rts

Blit_digit::				; general one numeric digit blit
	movem.l	d0-d2,-(sp)

	bsr	WaitBlit

	move.l	a1,A1_BASE		; A1 is destination
	swap	d2
	move.w	d1,d2
	move.l	d2,A1_PIXEL

	move.l	#$d0008,B_COUNT		; 8 wide, 13 high

	move.l	#PIXEL16|WID8|XADDPIX,A2_FLAGS
	move.l	#PIXEL16|WID320|XADDPIX,A1_FLAGS

	moveq	#$f,d1
	and.l	d1,d0			; makes absolutely sure about what we have in d0 !

	asl.l	#8,d0			; multiply by $100 - size of one number (8*16*2bytes)
	add.l	#Mapdisp+$3c00,d0	; points to font in RAM where expanded numbers are held
	move.l	d0,A2_BASE		; A2 is source

	move.l	#$1fff8,d0
	move.l	d0,A2_STEP
	move.l	d0,A1_STEP

	moveq	#0,d0
	move.l	d0,B_PATD
	move.l	d0,A2_PIXEL
	move.l	d0,A1_CLIP		; jic

	move.l	#SRCEN|UPDA1|UPDA2|LFUSRC|DCOMPEN,B_CMD
	clr.l	blitsem.w

	movem.l	(sp)+,d0-d2
	rts

Blit_car::				; specific blit function - miniature car into main screen
	movem.l	d0-d2,-(sp)
	bsr	WaitBlit

	move.l	a1,A1_BASE
	swap	d2
	move.w	d1,d2
	move.l	d2,A1_PIXEL

	move.l	#$a0028,B_COUNT		; 10 wide, 13 high

	move.l	#PIXEL16|WID40|XADDPIX,A2_FLAGS
	move.l	#PIXEL16|WID320|XADDPIX,A1_FLAGS

	move.l	d0,A2_BASE		; A2 is source

	move.l	#$1ffd8,d0
	move.l	d0,A2_STEP
	move.l	d0,A1_STEP

	moveq	#0,d0
	move.l	d0,B_PATD
	move.l	d0,A2_PIXEL
	move.l	d0,A1_CLIP		; jic

	move.l	#SRCEN|UPDA1|UPDA2|LFUSRC|DCOMPEN,B_CMD
	clr.l	blitsem.w

	movem.l	(sp)+,d0-d2
	rts


