Intro to the bass (badass) 6502 assembler
Part 2
In the last part we saw how to create a simple C64 program to play some music.
We used the load()
function to load the music into the assembler, and then
the !fill
meta command to place it onto memory.
Now it’s time to add some graphics.
First we add a couple of macros to make it easier to work with the VIC:
; Set VIC base address
!macro VicAdr(adr) {
!assert (adr & $3fff) == 0
lda #((~adr)&$ffff)>>14
sta $dd00
}
; Set Bitmap and screen offsets
!macro BitmapAndScreen(bm_offs, scr_offs) {
!assert (bm_offs & $dfff) == 0
!assert (scr_offs & $c3ff) == 0
.bits0 = (bm_offs>>10)
.bits1 = (scr_offs>>6)
lda #.bits0 | .bits1
sta $d018
}
The first macro sets the VIC base address, which can only be located in one of
16KB offsets of main RAM. We use the !assert
to verify this, meaning our code
will not compile if we try to use an incompatible address.
The second macro is similar, but it takes offsets (from the VIC base address)
and also makes sure they are legal. We use local symbols (starting with a '.'
)
to avoid polluting the namespace (yes symbols defined in macros will affect the
global symbol table).
VicAdr($4000)
BitmapAndScreen($2000, $000)
Ok, so now this means that we need to locate our bitmap data at address
$6000
and our screen data at $4000
.
Let’s import a koala picture:
koala = load("image.koa")
bitmap = koala[2:$1f42]
screen_ram = koala[$1f42:$232a]
color_ram = koala[$232a:$2712]
bg_color = koala[$2712]
colors:
!fill color_ram
screen:
!fill screen_ram
!section "koala", $6000
!fill bitmap
Here we use array slicing again to extract all the parts.
Remember that loading data an manipulating arrays only happens at compile time, it doesn’t affect the program in any way. We need the !fill
command to place data in memory.
The bitmap is placed directly at $6000
using a !section
command, but
the screen and color data needs to be copied.
Here is the code to copy our colors to Color RAM, and our screen to $4000
,
where we set it up earlier:
scrTarget = $4000
lda #$18
sta $d016
lda #$3b
sta $d011
lda #bg_color
sta $d020
sta $d021
$ lda colors,x
sta $d800,x
lda colors+$100,x
sta $d900,x
lda colors+$200,x
sta $dA00,x
lda colors+$2e8,x
sta $dae8,x
!if screen != screenTarget {
lda screen,x
sta scrTarget,x
lda screen+$100,x
sta scrTarget+$100,x
lda screen+$200,x
sta scrTarget+$200,x
lda screen+$2e8,x
sta scrTarget+$2E8,x
}
inx
bne -
A few new things here: we use an !if
statement here to avoid the copy
just in case we do relocate the screen data to the correct position at load time.
We also use the anonymous $
label to avoid defining labels when we don’t
need to.