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.
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
Previous post: Amiga Machine Code Letter VI - Blitter
Next post: Amiga Machine Code Letter VI - Blitter 3.