;
;	Copperlist Example 1.
;
;	Written for OZAmiga by Chris Leathley.
;
;	The code is fully comented to help you understand what is going on
;	as a lot of new areas are covered in one program.
;



;
;	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


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

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

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

; any part of the program that the custom chips use (ie the copper, blitter)
; must be in CHIP type memory for it to work 

;
;	If you are using Devpac as your assembler then comment out the A68k
;	version of the SECTION command and insert the devpac one
;


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


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

						; it is best to clear this
						; location as it will stop
						; any bitplane or sprite
						; flicking if those registers
						; havn't been initalized

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

;
; the amiga contains many librarys so the user can easily code system
; friendly programs using allready existing code
;
; address $4 holds the address of the master library the 'exec.library'.
; This library contains a lot of routines to open other librarys and to
; control aspects of the operating system.
;
; there are quite a few library to help the Amiga operate, most of them are
; all ready in ram (kickstart), others can be found in the LIBS: directory.
; Librarys include the 'graphics.library' which has routines to control any
; type of graphics on the screen.  Unless you are writting in C or writing
; system code we don't need to use the 'graphics.library' execept to get
; the old copperlist pointer (expained later).  Other librarys include the
; 'dos.library' which handles all disk input and output.
;


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

;
;	as mentioned in the artical, the display has a count of where the
;	display beem is on the monitor.  As it moves down the screen this
;	address holds the line number it is currently on
;
;	the vertical blank is the best time to trigger the copperlist as
;	when the beem is in this area nothing is being sent to the monitor
;	display, so not glitches are noticed as the copperlist changes
;

		move.l	#FIRSTCOPPER,$00DFF080	; insert new copperlist
		move.w	#$8280,$00DFF096	; use new control bits

;
;	move the address of the copperlist program (FIRSTCOPPER) into the
;	address which runs the copper
;
;	address $00DFF096 can switch all the individual DMA channels
;	either on or off.
;
;	unlike normal address, some of the Amiga's hardware address work
;	very differently.  Instead of over-writing the entire word with the
;	new one it will individually set or clear single bits within that
;	address.  Bit 15 (msb) is set to 1 if you want to set bits, and 0
;	if you want to turn them off.  The remaining bits stand for special
;	DMA control.  The $x2xx above enables all dma set while the $xx80
;	enables Copper DMA.  All other DMA channels remain unchanged. 
;


;	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

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

;
;	bit 6 in address $00BFE001 can tell if the left mouse button is being
;	pressed.  It will be set to 0 when this happens.  Bit 7 is the
;	joystick button.  Try changing it to 7, you will then have to press
;	the joystick button to exit.
;
;	The btst instruction tests a bit within a byte and sets the flags
;	accordinly.  It compare's the bit with zero.
;


;	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

; open library returns the address of the opened library in d0

		move.l	d0,a1			; d0 has pointer to library

; move this to an address register to we can use the offset addressing mode

		move.l	$0026(a1),$00DFF080	; restore original copperlist

;
; the graphic library contain many varables and programs usefull to the
; programmer and operating system.  As hardware programmer we only need to
; get one varable (or address) from the library.  Offset $26 contains the
; address of the previous copperlist (in most cases it is the workbench
; copperlist program)
;
; we need to restore the copperlist pointer to the old one otherwise the
; amiga will display the wrong display.  ie. you'll have our very nice
; colour bars instead of the CLI screen.  Since the COP1LC ($00DFF180)
; register is WRITE-ONLY we cannot get the copperlist address at the start
; of the program, so we have to use the operating system.
;

		jsr	CloseLibrary(a6)	; close graphics library

		jsr	Permit(a6)		; turn back on multitasking

		moveq	#0,d0			; no errors
		rts				; return of amiga dos

;
;	It is general convention to return a zero in D0 so the Amiga knows
;	that the program worked correctly and there wasn't any errors.
;



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



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

;
;	the library name open library uses.  It must have a 0 byte at the
;	end of the string.
;	The EVEN makes sure that any data or code following is on a word
;	boundary (an even address) otherwise the 68000 gets very cross and
;	sulks.
;


;
;	our first copperlist program
;
;	It puts 7 coloured bars onto the screen
;
FIRSTCOPPER:	dc.w	$0180,$0000		; make sure screen starts
						; off being black
		dc.w	$0100,$0000		; turn off bitplane display

;
;	$0180 is the register for colour zero.  If the 68000 wanted to use
;	it, it would be $00DFF180.
;
		dc.w	$4009,$FFFE,$0180,$0200	; red bar
		dc.w	$4109,$FFFE,$0180,$0400
		dc.w	$4209,$FFFE,$0180,$0600
		dc.w	$4309,$FFFE,$0180,$0800
		dc.w	$4409,$FFFE,$0180,$0A00
		dc.w	$4509,$FFFE,$0180,$0C00
		dc.w	$4609,$FFFE,$0180,$0E00
		dc.w	$4709,$FFFE,$0180,$0F00 ; the brightest point
		dc.w	$4809,$FFFE,$0180,$0E00
		dc.w	$4909,$FFFE,$0180,$0C00
		dc.w	$4A09,$FFFE,$0180,$0A00
		dc.w	$4B09,$FFFE,$0180,$0800
		dc.w	$4C09,$FFFE,$0180,$0600
		dc.w	$4D09,$FFFE,$0180,$0400
		dc.w	$4E09,$FFFE,$0180,$0200
		dc.w	$4F09,$FFFE,$0180,$0000
;
; the last colour must be the screen colour, otherwise you would see a pale
; red section on the screen.  Try changing it to $0FFF to see what I mean.
;

		dc.w	$6009,$FFFE,$0180,$0210	; orange bar
		dc.w	$6109,$FFFE,$0180,$0420
		dc.w	$6209,$FFFE,$0180,$0630
		dc.w	$6309,$FFFE,$0180,$0840
		dc.w	$6409,$FFFE,$0180,$0A50
		dc.w	$6509,$FFFE,$0180,$0C60
		dc.w	$6609,$FFFE,$0180,$0E70
		dc.w	$6709,$FFFE,$0180,$0F80
		dc.w	$6809,$FFFE,$0180,$0E70
		dc.w	$6909,$FFFE,$0180,$0C60
		dc.w	$6A09,$FFFE,$0180,$0A50
		dc.w	$6B09,$FFFE,$0180,$0840
		dc.w	$6C09,$FFFE,$0180,$0630
		dc.w	$6D09,$FFFE,$0180,$0420
		dc.w	$6E09,$FFFE,$0180,$0210
		dc.w	$6F09,$FFFE,$0180,$0000

		dc.w	$8009,$FFFE,$0180,$0220	; yellow bar
		dc.w	$8109,$FFFE,$0180,$0440
		dc.w	$8209,$FFFE,$0180,$0660
		dc.w	$8309,$FFFE,$0180,$0880
		dc.w	$8409,$FFFE,$0180,$0AA0
		dc.w	$8509,$FFFE,$0180,$0CC0
		dc.w	$8609,$FFFE,$0180,$0EE0
		dc.w	$8709,$FFFE,$0180,$0FF0
		dc.w	$8809,$FFFE,$0180,$0EE0
		dc.w	$8909,$FFFE,$0180,$0CC0
		dc.w	$8A09,$FFFE,$0180,$0AA0
		dc.w	$8B09,$FFFE,$0180,$0880
		dc.w	$8C09,$FFFE,$0180,$0660
		dc.w	$8D09,$FFFE,$0180,$0440
		dc.w	$8E09,$FFFE,$0180,$0220
		dc.w	$8F09,$FFFE,$0180,$0000

		dc.w	$A009,$FFFE,$0180,$0020 ; green bar
		dc.w	$A109,$FFFE,$0180,$0040
		dc.w	$A209,$FFFE,$0180,$0060
		dc.w	$A309,$FFFE,$0180,$0080
		dc.w	$A409,$FFFE,$0180,$00A0
		dc.w	$A509,$FFFE,$0180,$00C0
		dc.w	$A609,$FFFE,$0180,$00E0
		dc.w	$A709,$FFFE,$0180,$00F0
		dc.w	$A809,$FFFE,$0180,$00E0
		dc.w	$A909,$FFFE,$0180,$00C0
		dc.w	$AA09,$FFFE,$0180,$00A0
		dc.w	$AB09,$FFFE,$0180,$0080
		dc.w	$AC09,$FFFE,$0180,$0060
		dc.w	$AD09,$FFFE,$0180,$0040
		dc.w	$AE09,$FFFE,$0180,$0020
		dc.w	$AF09,$FFFE,$0180,$0000

		dc.w	$C009,$FFFE,$0180,$0022 ; cyan
		dc.w	$C109,$FFFE,$0180,$0044
		dc.w	$C209,$FFFE,$0180,$0066
		dc.w	$C309,$FFFE,$0180,$0088
		dc.w	$C409,$FFFE,$0180,$00AA
		dc.w	$C509,$FFFE,$0180,$00CC
		dc.w	$C609,$FFFE,$0180,$00EE
		dc.w	$C709,$FFFE,$0180,$00FF
		dc.w	$C809,$FFFE,$0180,$00EE
		dc.w	$C909,$FFFE,$0180,$00CC
		dc.w	$CA09,$FFFE,$0180,$00AA
		dc.w	$CB09,$FFFE,$0180,$0088
		dc.w	$CC09,$FFFE,$0180,$0066
		dc.w	$CD09,$FFFE,$0180,$0044
		dc.w	$CE09,$FFFE,$0180,$0022
		dc.w	$CF09,$FFFE,$0180,$0000

		dc.w	$E009,$FFFE,$0180,$0002 ; blue
		dc.w	$E109,$FFFE,$0180,$0004
		dc.w	$E209,$FFFE,$0180,$0006
		dc.w	$E309,$FFFE,$0180,$0008
		dc.w	$E409,$FFFE,$0180,$000A
		dc.w	$E509,$FFFE,$0180,$000C
		dc.w	$E609,$FFFE,$0180,$000E
		dc.w	$E709,$FFFE,$0180,$000F
		dc.w	$E809,$FFFE,$0180,$000E
		dc.w	$E909,$FFFE,$0180,$000C
		dc.w	$EA09,$FFFE,$0180,$000A
		dc.w	$EB09,$FFFE,$0180,$0008
		dc.w	$EC09,$FFFE,$0180,$0006
		dc.w	$ED09,$FFFE,$0180,$0004
		dc.w	$EE09,$FFFE,$0180,$0002
		dc.w	$EF09,$FFFE,$0180,$0000

		dc.w	$FFDF,$FFFE

;
; unless the copperlist has this command, it will start the vertical blank
; at this point.  thats ok for NTSC machines but we lose the bottom 2 inches
; of the display.  The above command tricks the copper into missing the
; first vertical blank position.  It will how ever happen around $38 (the
; very bottom of the screen.
;

		dc.w	$0009,$FFFE,$0180,$0202 ; pink
		dc.w	$0109,$FFFE,$0180,$0404
		dc.w	$0209,$FFFE,$0180,$0606
		dc.w	$0309,$FFFE,$0180,$0808
		dc.w	$0409,$FFFE,$0180,$0A0A
		dc.w	$0509,$FFFE,$0180,$0C0C
		dc.w	$0609,$FFFE,$0180,$0E0E
		dc.w	$0709,$FFFE,$0180,$0F0F
		dc.w	$0809,$FFFE,$0180,$0E0E
		dc.w	$0909,$FFFE,$0180,$0C0C
		dc.w	$0A09,$FFFE,$0180,$0A0A
		dc.w	$0B09,$FFFE,$0180,$0808
		dc.w	$0C09,$FFFE,$0180,$0606
		dc.w	$0D09,$FFFE,$0180,$0404
		dc.w	$0E09,$FFFE,$0180,$0202
		dc.w	$0F09,$FFFE,$0180,$0000

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


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


	END					; end of program
