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.

Prev — Next