Amiga Machine Code Letter VI - Blitter 2

Amiga Machine Code - Letter VI - Blitter 2

We have reached Letter VI of the Amiga Machine Code course. I’ll skip through the details in this post. Make sure to read the letter, to get a grasp of things.

In this post we will look at the code of the mc0601 program, found on Disk 1.

The program draws a blitter object that scrolls smoothly down the screen on a black background. It’s a very simple blitting, that provide some basic understanding, that will serve us well, when moving to more complex forms of blitting.

mc0601 screenshot

We need to load the object to blit from Disk 1 into memory at the correct label. In Seka use “V” to change to the folder BREV06, then run the program by writing:

SEKA>r
FILENAME>mc0601
SEKA>a
OPTIONS>
No errors
SEKA>ri
FILENAME>object
BEGIN>object
END>
SEKA>j

Be sure to lookup information about the custom chip registers as you read along.

start: ; program mc0601
move.w	#$4000,$dff09a     ; INTENA clear master interupt
                           ; turn off disk
or.b	#%10000000,$bfd100 ; CIABPRB Disk
and.b	#%10000111,$bfd100 ; CIABPRB Disk

move.w	#$01a0,$dff096 ; DMACON clear bitplane, copper, blitter

move.w	#$1200,$dff100 ; BPLCON0 1 bitplane and color burst
move.w	#$0000,$dff102 ; BPLCON1 scroll value
move.w	#$0000,$dff104 ; BPLCON2 video priority control
move.w	#0,$dff108     ; BPL1MOD
move.w	#0,$dff10a     ; BPL2MOD
move.w	#$2c81,$dff08e ; DIWSTRT
move.w	#$f4c1,$dff090 ; DIWSTOP enable PAL trick
move.w	#$38c1,$dff090 ; DIWSTOP
move.w	#$0038,$dff092 ; DDFSTRT 
move.w	#$00d0,$dff094 ; DDFSTOP

;----write screen pointer into bplcop
lea.l	screen,a1 ; put screen address into a1
lea.l	bplcop,a2 ; put bplcop address into a2
move.l	a1,d1     ; transfer screen to bitplane 1 pointer in bplcop
move.w	d1,6(a2)
swap	d1
move.w	d1,2(a2)

;-----transfer copper pointer to custom chip register
lea.l	copper,a1      ; put copper address into a1
move.l	a1,$dff080     ; COP1LCH (and COP1LCL)
move.w	#$8180,$dff096 ; DMACON set bitplane, copper

mainloop:
;-----busy wait for line 300
move.l	$dff004,d0 ; read VPOSR and VHPOSR into d0 as one long word
asr.l	#8,d0      ; shift right 8 positions
andi.l	#$1ff,d0   ; and for immediate data
cmp.w	#300,d0
bne	mainloop   ; if not at line 300 goto mainloop

;-----now at line 300---
bsr	clear      ; branch to subroutine clear

bsr	blitin     ; branch to subroutine blitin

btst	#6,$bfe001 ; test left mouse button
bne	mainloop   ; if not pressed goto mainloop

;-----exit program---
move.w	#$0080,$dff096 ; DMACON clear copper

move.l	$4,a6          ; reestablish DMA's and copper
move.l	156(a6),a6
move.l	38(a6),$dff080

move.w	#$80a0,$dff096

move.w	#$c000,$dff09a
rts ; exit program

clear:
lea.l	screen,a1     ; put screen address into a1

waitblit1:            ; wait for blitter to finish
btst	#6,$dff002    ; DMACONR test blitter
bne	waitblit1
;-----blitter finished---

;-----becuase no source only 0's are written to D---
move.l	a1,$dff054     ; BLTDPTH (and BLTDPTL) set to screen
move.w	#0,$dff066     ; BLTDMOD
move.w	#$0100,$dff040 ; BLTCON0 Use D channel - no source, no bool fun
move.w	#$0000,$dff042 ; BLTCON1
move.w	#$4014,$dff058 ; BLTSIZE %0100 0000 0001 0100 (256, 20)
rts
;-----end clear subroutine---

pos:
dc.l	0 ; allocate line position counter

blitin:         ; blit
lea.l	pos,a1  ; put pos address into a1
move.l	(a1),d1 ; move line position to d1
addq.l	#1,(a1) ; increment line position

cmp.w	#216,d1 ; blitting 40 lines. 216 + 40 = 256
bne	notbottom   ; if line pos is not 216 goto notbottom

clr.l	d1
clr.l	(a1)

notbottom:
lea.l	screen,a1 ; put screen address into a1
mulu	#40,d1    ; unsigned multiply - a line has 40 bytes (320/8)
add.l	d1,a1     ; add lines as number of bytes to start of screen (a1)
add.l	#12,a1    ; center blitting on screen (12 + 16 + 12 = 40)
                  ; the blit is 16 bytes wide
lea.l	object,a2 ; put object address into a2

waitblit2:         ; wait for blitter to finish
btst	#6,$dff002 ; DMACONR test blitter
bne	waitblit2
;-----blitter finished---

move.l	a1,$dff054          ; BLTDPTH (and BLTDPTL)
move.l	a2,$dff050          ; BLTAPTH (and BLTAPTL)
move.w	#24,$dff066         ; BLTDMOD (12 + width of blit + 12 = 40)
move.w	#0,$dff064          ; BLTAMOD
move.l	#$ffffffff,$dff044  ; BLTAFWM (and BLTALWM) blitter mask
move.w	#$09f0,$dff040      ; BLTCON0
move.w	#$0000,$dff042      ; BLTCON1
move.w	#$0a08,$dff058      ; BLTSIZE %0000 1010 0000 1000 
                            ; height = 40 lines, width = 8 words -> 128 pixel
rts                         ; return from blitin
;-----end blitin subroutine

copper:
dc.w	$2c01,$fffe ; wait($01,$2c)
dc.w	$0100,$1200 ; BPLCON0 enable 1 bitplane, color burst

bplcop:
dc.w	$00e0,$0000 ; BPL1PTH
dc.w	$00e2,$0000 ; BPL1PTL

dc.w	$0180,$0000 ; COLOR00 black
dc.w	$0182,$00ff ; COLOR01 cyan

dc.w	$ffdf,$fffe ; wait($df,$ff) enable wait > $ff horiz

dc.w	$2c01,$fffe ; wait($01,$12c)
dc.w	$0100,$0200 ; BPLCON0 disable bitplanes - older PAL chips
dc.w	$ffff,$fffe ; end of copper

screen:
blk.l	2560,0 ; allocate 10kb and set to zero

object:
blk.l	160,0 ; allocate 640 bytes and set to zero

The wait for blitter routine is also described here


Amiga Machine Code Course

Previous post: Amiga Machine Code Letter VI - Blitter

Next post: Amiga Machine Code Letter VI - Blitter 3.

Mark Wrobel
Mark Wrobel
Team Lead, developer and mortgage expert