;
;	Bitplane Example 12.
;
;	Written for OZAmiga by Chris Leathley.
;
;	uses the dual playfield mode on the amiga.  Puts the frame picture
;	in front of the scrolling warning picture in the background.
;
;	has the colour cycling routine in again and also changes playfield
;	priority for a slight slice of the screen.
;


;
;	Branch offsets into the Amiga's rom kernal librarys (exec)
;
Forbid		=	-132		; turn off Multitasking
Permit		=	-138		; turn it back on again
CloseLibrary	=	-414		; open a library (from ram or disk)
OpenLibrary	=	-552		; close an opened library

FRAME_SIZE	=	256*40		; size of frame picture bitplanes



; --------------------------------------------------------------------------

; a68k code
;	SECTION	code,CODE,CHIP			; make sure in chip memory

; devpac code
	SECTION	code,CODE_C			; make sure in chip memory

; --------------------------------------------------------------------------


;	program starts here
;
START:		clr.l	$0			; clear address 0

		move.l	$4,a6			; turn off multitasking
		jsr	Forbid(a6)


;
;	set up bitplane address into copper list program before copper is
;	turned on
;
		move.l	#FRAME,d0		; put warning picture address
		move.w	d0,BP1LO+2		; into copper (ODD planes)
		swap	d0			; (playfield 1)
		move.w	d0,BP1HI+2

		move.l	#FRAME+FRAME_SIZE,d0	; plane 2
		move.w	d0,BP3LO+2
		swap	d0
		move.w	d0,BP3HI+2

		move.l	#PICTURE,d0		; put warning picture address
		move.w	d0,BP2LO+2		; into copper (EVEN plane)
		swap	d0			; (playfield 2)
		move.w	d0,BP2HI+2


;	fire up the copper
;
.wait_vb	cmp.b	#$FF,$00DFF006		; wait for vb to change
		bne.s	.wait_vb

		move.l	#COPPERLIST,$00DFF080	; insert new copperlist
		move.w	#$8380,$00DFF096	; use new control bits
						; (turn on copper & bitplane dma)


;	wait for user to press the left mouse button and then exit program
;
MAIN_LOOP:	cmp.b	#$FF,$00DFF006		; wait for vertical blank
		bne.s	MAIN_LOOP

		bsr	SCROLL_WARNING

		bsr	CYCLE_WARNING


;	put in our little delay otherwise the above code will execute
;	many times while the raster line is still on postion $FF

		move.w	#256,d0			; count down from 256 to 0
.delay		sub.w	#1,d0
		bne	.delay

		btst	#$06,$00BFE001		; left mouse button ?
		bne.s	MAIN_LOOP		; no? do it all again


;	program finished, exit back to dos
;
EXIT:		move.l	$4,a6			; exec pointer
		lea	GFX_NAME,a1		; library name
		moveq	#0,d0			; library version
		jsr	OpenLibrary(a6)		; open graphics library

		move.l	d0,a1			; d0 has pointer to library
		move.l	$0026(a1),$00DFF080	; restore original copperlist

		jsr	CloseLibrary(a6)	; close graphics library

		jsr	Permit(a6)		; turn back on multitasking
		moveq	#0,d0			; no errors
		rts				; return of amiga dos



; --------------------------------------------------------------------------



;
;	scroll warning bitmap (640 pixels wide) left and right in lo-res
;	(displaying only 320 pixels at a time)
;
SCROLL_WARNING:	tst.w	SCROLL_DIRECTION	; test direction flag
		bne	.right			; 0 = left, 1 = right

.left		sub.w	#1,SCROLL_VALUE		; subtract 1 from x position
		tst.w	SCROLL_VALUE		; are we at 0 yet?
		bne	.set
		move.w	#1,SCROLL_DIRECTION	; yes so now go right
		bra	.set

.right		add.w	#1,SCROLL_VALUE
		cmp.w	#320+16,SCROLL_VALUE	; at max right position?
						; we go that little bit extra
						; to compensate for the frame
						; graphics in playfield 1
		bne	.set
		move.w	#0,SCROLL_DIRECTION	; now go left

.set		move.l	#0,d0
		move.w	SCROLL_VALUE,d0		; get x scroll value
		move.l	d0,d1			; move to a temporary regisiter
		divu	#16,d1			; calculate number of "words"
						; into bitplane pointers

		mulu	#2,d1			; convert result from bytes
						; to "words".  (bitplane pointers
						; must be a EVEN address)

		not.b	d0			; invert scroll offset
		and.w	#$000F,d0		; clip offset to range ($0 - $F)

		lsl.w	#4,d0			; shift to EVEN HSCROLL pos
		move.w	d0,HSCROLL_COP+2	; put result into copperlist

		move.l	#PICTURE,d0		; base address of picture
		add.l	d1,d0			; add number of "words" onto
						; picture start address.

		move.w	d0,BP2LO+2		; set bitplane pointers
		swap	d0
		move.w	d0,BP2HI+2
		rts



SCROLL_DIRECTION	dc.w	1		; (start going right)
SCROLL_VALUE		dc.w	0



; --------------------------------------------------------------------------



;
;	make the word "warning' on the bitmap cycle colours from
; 	bright yellow to black, to bright yellow again.
;
CYCLE_WARNING:	add.w	#1,CYCLE_DELAY		; change colour every 2
		cmp.w	#2,CYCLE_DELAY		; vertical blanks
		bne	.exit
		clr.w	CYCLE_DELAY		; reset counter

		move.w	CYCLE_OFFSET,d0		; get colour cycle table offset
		lea	WARNING_COLOURS,a0	; colour table
		add.w	d0,a0			; get to required colour

		move.w	(a0),WARNING_COP_COL+2	; set new colour in copperlist

		add.w	#2,CYCLE_OFFSET		; goto next colour entry in
						; table (since each entry is
						; one "word" we must add 2 bytes)

		cmp.w	#32*2,CYCLE_OFFSET	; at end of table?
		bne	.exit			; not this time
		clr.w	CYCLE_OFFSET		; reset offset (range is from
						; 0 to 31)
.exit		rts



CYCLE_DELAY	dc.w	0
CYCLE_OFFSET	dc.w	0


;	colour cycle table (32 entrys)
;
WARNING_COLOURS	dc.w	$FF0,$EE0,$DD0,$CC0,$BB0,$AA0,$990,$880	; fade from 
		dc.w	$770,$660,$550,$440,$330,$220,$110,$000 ; yellow to black
		dc.w	$000,$110,$220,$330,$440,$550,$660,$770	; and then upto
		dc.w	$880,$990,$AA0,$BB0,$CC0,$DD0,$EE0,$FF0	; yellow again

	

; --------------------------------------------------------------------------



;	graphics library name
;
GFX_NAME:	dc.b	'graphics.library',0
		EVEN



;
;	our copperlist program
;
COPPERLIST:	dc.w	$0180,$0000		; screen starts off black

		dc.w	$0120,0,$0122,0		; don't worry about this just
		dc.w	$0124,0,$0126,0		; yet as all it does is set
		dc.w	$0128,0,$012A,0		; all sprite positions to zero
		dc.w	$012C,0,$012E,0		; so no wondering sprites
		dc.w	$0130,0,$0132,0		; appear on the screen
		dc.w	$0134,0,$0136,0
		dc.w	$0138,0,$013A,0
		dc.w	$013C,0,$013E,0

BP1HI		dc.w	$00E0,0			; bitplane 1 address pointers
BP1LO		dc.w	$00E2,0
BP2HI		dc.w	$00E4,0			; bitplane 2 address pointers
BP2LO		dc.w	$00E6,0
BP3HI		dc.w	$00E8,0			; bitplane 3 address pointers
BP3LO		dc.w	$00EA,0

		dc.w	$100,$3600		; turn on 3 bitplanes
						; (2 ODD and 1 EVEN)
						; and duel playfield mode
						; (bit 10)

HSCROLL_COP	dc.w	$102,0			; hardware scroll to be zero
		dc.w	$104,0			; bitplane / sprite priority
		dc.w	$08E,$2C81		; window start (top left)
		dc.w	$090,$2CC1		; window stop (bottom right)
						; (STANDARD PAL DISPLAY VALUES)

		dc.w	$092,$38		; bitplane DMA start
		dc.w	$094,$d0		; bitplane DMA stop
		dc.w	$108,0			; odd modulo (frame picture)
		dc.w	$10A,40			; even modulo (warning picture)

		dc.w	$180,$000		; frame picture colours
		dc.w	$182,$D72		; colour 1
		dc.w	$184,$841		; colour 2
		dc.w	$186,$420		; colour 3

WARNING_COP_COL	dc.w	$192,$FF0		; warning text colour (yellow)
						; colour 9

		dc.w	$7009,$FFFE,$192,$DD0	; set text colour to dull yellow
						; after warning colour cycle.

		dc.w	$D409,$FFFE,$180,$005	; background colour to blue
		dc.w	$104,$0040		; put playfield 2 in front of
						; playfield 1 (swap prioritys)

		dc.w	$F409,$FFFE,$180,$000	; colour 0 to black again
		dc.w	$104,$0			; playfield priority back to norm

		dc.w	$FFFF,$FFFE		; end of copper list
						; start vertical blank


; --------------------------------------------------------------------------


;
;	include raw picture data into assembly code
;
FRAME:		INCBIN	oz.frame.raw

PICTURE:	INCBIN	oz.warning.raw


; --------------------------------------------------------------------------



	END					; end of program
