*****************************************************************************
*                      -- THE AMIFLEX TOGGLE PROGRAM --                     *
*****************************************************************************

;First we assign some equates to make the program a bit easier to read.
;All of these equates are for library calls.

Execbase	equ	 4		;EXEC library base address
OpenLibrary	equ	-552		;Openlibray offset address
CloseLibrary	equ	-414		;Closelibrary offset address
Forbid		equ	-132		;Forbid offset address
Permit		equ	-138		;Permit offset address
Supervisor	equ	-30		;Supervisor offset address
Startlist	equ	 38		;Startlist offset address

;The custom chips can only pull data form chip ram.
;The data for this program is put in chip ram so that the custom chips
;can access it, otherwise you would see no graphics.

	section	rainbow_copper,code_c	;Code to chip ram

;The bitplanes must have pointers in the copper list so that they are
;displayed correctly, this next routine places the bitplane pointers
;into the copper list.

	move.l	#screen,d0		;Screen data into d0
	move.w	d0,pl1l			;Low word in copper list
	swap	d0			;Get other word
	move.w	d0,pl1h			;High word in copper list

	move.l	#screen+10240,d0	;Screen data+offset into d0
	move.w	d0,pl2l			;Low word in copper list
	swap	d0			;Get other word
	move.w	d0,pl2h			;High word in copper list

	move.l	#screen+20480,d0	;Screen data+offset into d0
	move.w	d0,pl3l			;Low word in copper list
	swap	d0			;Get other word
	move.w	d0,pl3h			;High word in copper list

	move.l	#screen+30720,d0	;Screen data+offset into d0
	move.w	d0,pl4l			;Low word in copper list
	swap	d0			;Get other word
	move.w	d0,pl4h			;High word in copper list

	move.l	#screen+40960,d0	;Screen data+offset into d0
	move.w	d0,pl5l			;Low word in copper list
	swap	d0			;Get other word
	move.w	d0,pl5h			;High word in copper list

;As the routines are low level it is best to shut out multitasking.
;The Forbid routine in the EXEC library can do this for us. Also if
;we want to quit after we have set up our own copper list we must
;replace the old one. The GRAPHICS library Startlist offset can get
;the address of the old copper list which we then store for later use.  

	move.l	Execbase,a6		;Execbase into a6
	jsr	Forbid(a6)		;No multitask
	lea	graphics_name,a1	;Graphics library name into a1
	moveq	#0,d0			;Any version of the library
	jsr	OpenLibrary(a6)		;Open the library
	move.l	d0,a1			;Base address into a1
	move.l	Startlist(a1),old_copper;Store old copper list address
	move.l	Execbase,a6		;Execbase into a6
	jsr	CloseLibrary(a6)	;Close the graphics library

;Our copperlist can now be poked in

	move.l	#copper_list,$dff080
	move.l	#$0000,$dff088

;This wait_vbl routine serves no use in the program but I included it
;as it is very useful. The routine waits for a vertical blank.

wait_vbl:
	move.l	$dff004,d2		;Vposr into d2
	and.l	#$0001ff00,d2		;Get what we want
	cmp.l	#$00001000,d2		;Is it what we want??
	bne.s	wait_vbl		;No, carry on waiting

;This wait_keys routine reads the function keys from F1 to F5

wait_keys:
	cmp.b	#$5e,$bfec01		;F1 pressed?
	beq	change_mode50		;Yes, jump to routine

	cmp.b	#$5c,$bfec01		;F2 pressed?
	beq	change_mode60		;Yes, jump to routine

	cmp.b	#$5a,$bfec01		;F3 pressed?
	beq	change_filter		;Yes, jump to routine

	cmp.b	#$58,$bfec01		;F4 pressed?
	beq	hard_reset		;Yes, jump to routine

	cmp.b	#$56,$bfec01		;F5 pressed?
	bne.s	wait_keys		;No jump back and check again

;Until the F5 key is pressed, the above routine keeps checking the
;function keys. After F5 is pressed the quit routine runs. It replaces
;the old copper list and turns multitasking back on.

quit:
	move.l	old_copper,$dff080	;Put old copper list back
	jsr	Permit(a6)		;Multitask on
	rts				;Quit

;These are the routines that execute after a function key is pressed...

change_mode50:
	move.w	#32,$dff1dc		;50Hz mode on
	bra	wait_keys		;Go back to check keys again

change_mode60:
	move.w	#0,$dff1dc		;60Hz mode on
	bra	wait_keys		;Go back to check keys again

change_filter:
	eori.b	#2,$bfe001		;Toggle low pass filter
	cmp.b	#$5a,$bfec01		;Key still pressed?
	beq	wait_release		;Yes, jump to routine
	bra	wait_keys		;Otherwise go back

;This routine waits for the F3 key to be released after being pressed.
;If this is not done, a proper toggle effect does not happen.

wait_release:
	cmp.b	#$5a,$bfec01		;Key released?
	bne	wait_keys		;No, loop until it is
	bra	wait_release		;When it is go back

;This routine resets the machine. A call to EXEC is made to get into
;Supervisor mode as the reset command is priveledged.

hard_reset:
	cnop	0,4			;Longword alignment

reset:
	move.l	Execbase,a6		;Execbase in a6
	lea.l	reset_code(pc),a5	;Reset code into a5
	jsr	Supervisor(a6)		;Jump into Supervisor mode

reset_code:
	lea.l	2,a0			;Start of ROM address after reset
	reset				;Reset the machine
	jmp	(a0)			;Jump to ROM address

;This is the all important copper list, every line will not be
;commented but each separate routine is noted.

copper_list:

;This first routine sets up the screen and bit plane pointers

	dc.w	$008e,$2c81,$0090,$2cc1
	dc.w	$0092,$0038,$0094,$00d0
	dc.w	$00e0
pl1h:	dc.w	0
	dc.w	$00e2
pl1l:	dc.w	0
	dc.w	$00e4
pl2h:	dc.w	0
	dc.w	$00e6
pl2l:	dc.w	0
	dc.w	$00e8
pl3h:	dc.w	0
	dc.w	$00ea
pl3l:	dc.w	0
	dc.w	$00ec
pl4h:	dc.w	0
	dc.w	$00ee
pl4l:	dc.w	0
	dc.w	$00f0
pl5h:	dc.w	0
	dc.w	$00f2
pl5l:	dc.w	0
	dc.w	$00f4,$0000,$00f6,$0000
	dc.w	$0100,$5000,$0102,$0000
	dc.w	$0104,$0000,$0108,$0000
	dc.w	$010a,$0000

;The palette is then set up

	dc.w	$0180,$0000,$0182,$0fff
	dc.w	$0184,$0ccc,$0186,$0aaa
	dc.w	$0188,$0888,$018a,$0777
	dc.w	$018c,$0777,$018e,$0555
	dc.w	$0190,$0333,$0192,$000f
	dc.w	$0194,$012f,$0196,$033f
	dc.w	$0198,$044f,$019a,$066f
	dc.w	$019c,$077f,$019e,$099f
	dc.w	$01a0,$0002,$01a2,$0000

;The copper background is drawn

	dc.w	$3401,$fffe,$0180,$0000
	dc.w	$3501,$fffe,$0180,$0300
	dc.w	$3601,$fffe,$0180,$0600
	dc.w	$3701,$fffe,$0180,$0900
	dc.w	$3801,$fffe,$0180,$0c00
	dc.w	$3901,$fffe,$0180,$0f00
	dc.w	$3a01,$fffe,$0180,$0f00
	dc.w	$3b01,$fffe,$0180,$0c00
	dc.w	$3c01,$fffe,$0180,$0900
	dc.w	$3d01,$fffe,$0180,$0600
	dc.w	$3e01,$fffe,$0180,$0300
	dc.w	$3f01,$fffe,$0180,$0200
	dc.w	$8101,$fffe,$0180,$0300
	dc.w	$8201,$fffe,$0180,$0600
	dc.w	$8301,$fffe,$0180,$0900
	dc.w	$8401,$fffe,$0180,$0c00
	dc.w	$8501,$fffe,$0180,$0f00
	dc.w	$8601,$fffe,$0180,$0f00
	dc.w	$8701,$fffe,$0180,$0c00
	dc.w	$8801,$fffe,$0180,$0900
	dc.w	$8901,$fffe,$0180,$0600
	dc.w	$8a01,$fffe,$0180,$0300
	dc.w	$8b01,$fffe,$0180,$0000

;The sprites are pointed to memory address zero to keep them clear

	dc.w	$0120,$0000,$0122,$0000
	dc.w	$0124,$0000,$0126,$0000
	dc.w	$0128,$0000,$012a,$0000
	dc.w	$012c,$0000,$012e,$0000
	dc.w	$0130,$0000,$0132,$0000
	dc.w	$0134,$0000,$0136,$0000
	dc.w	$0138,$0000,$013a,$0000
	dc.w	$013c,$0000,$013e,$0000

;The copper list is terminated

	dc.w	$ffff,$fffe

;The bitmap image is included

screen:
	incbin	"df1:AMIPIC.Bmap"

;Space for the old copper list address

old_copper:
	dc.l	0

;Name of the graphics library

graphics_name:
	dc.b	"graphics.library",0
	even
