Basic ca65 Usage for SNES Programming
First Example
The first example is a minimal example of setting up the ROM header, vectors, etc.
Usage:
ca65 ca65.s
ld65 -C lorom128.cfg -o ca65.smc ca65.o
lorom128.cfg
# ca65 linker config for 128K SMC
# Physical areas of memory
# Names need not match, but it makes it easier to remember if they do.
MEMORY {
ZEROPAGE: start = 0, size = $100;
BSS: start = $200, size = $1800;
ROM: start = $8000, size = $8000, fill = yes;
BANK1: start = $18000, size = $8000, fill = yes;
BANK2: start = $28000, size = $8000, fill = yes;
BANK3: start = $38000, size = $8000, fill = yes;
}
# Logical areas code/data can be put into.
SEGMENTS {
ZEROPAGE: load = ZEROPAGE, type = zp;
BSS: load = BSS, type = bss, align = $100;
CODE: load = ROM, align = $8000;
RODATA: load = ROM;
HEADER: load = ROM, start = $FFC0;
ROMINFO: load = ROM, start = $FFD5, optional = yes;
VECTORS: load = ROM, start = $FFE0;
# The extra three banks
BANK1: load = BANK1, align = $8000, optional = yes;
BANK2: load = BANK2, align = $8000, optional = yes;
BANK3: load = BANK3, align = $8000, optional = yes;
}
ca65.s
; Minimal example of using ca65 to build SNES ROM.
;
; ca65 ca65.s
; ld65 -C lorom128.cfg -o ca65.smc ca65.o
.p816 ; 65816 processor
.i16 ; X/Y are 16 bits
.a8 ; A is 8 bits
.segment "HEADER" ; +$7FE0 in file
.byte "CA65 EXAMPLE" ; ROM name
.segment "ROMINFO" ; +$7FD5 in file
.byte $30 ; LoROM, fast-capable
.byte 0 ; no battery RAM
.byte $07 ; 128K ROM
.byte 0,0,0,0
.word $AAAA,$5555 ; dummy checksum and complement
.segment "VECTORS"
.word 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, reset, 0
.segment "CODE"
reset:
clc ; native mode
xce
rep #$10 ; X/Y 16-bit
sep #$20 ; A 8-bit
; Clear PPU registers
ldx #$33
@loop: stz $2100,x
stz $4200,x
dex
bpl @loop
; Set background color to $03E0
lda #$E0
sta $2122
lda #$03
sta $2122
; Maximum screen brightness
lda #$0F
sta $2100
forever:
jmp forever
Second Example
The second example hides the ROM boilerplate in another file and focuses on showing a green screen. It's useful as a fallback to see whether code is running at all in a given situation. It's about the simplest "hello world" style program that gives feedback (the absolute simplest is to enable interlace mode and stare closely at your CRT, an approach I used when first running code on the SNES).
Usage:
ca65 green.s
ld65 -C lorom128.cfg -o green.smc green.o
green.s
; Displays green screen
;
; ca65 green.s
; ld65 -C lorom128.cfg -o green.smc green.o
.define ROM_NAME "GREEN"
.include "lorom128.inc"
reset:
init_cpu
; Clear PPU registers
ldx #$33
@loop: stz $2100,x
stz $4200,x
dex
bpl @loop
; Set background color to $03E0
lda #$E0
sta $2122
lda #$03
sta $2122
; Maximum screen brightness
lda #$0F
sta $2100
forever:
jmp forever
lowrom128.inc
; Sets up processor basics and ROM headers/vectors
.p816 ; 65816 processor
.i16 ; X/Y are 16 bits
.a8 ; A is 8 bits
.segment "HEADER" ; +$7FE0 in file
.byte ROM_NAME
.segment "ROMINFO" ; +$7FD5 in file
.byte $30 ; LoROM, fast-capable
.byte 0 ; no battery RAM
.byte $07 ; 128K ROM
.byte 0,0,0,0
.word $AAAA,$5555 ; dummy checksum and complement
.segment "VECTORS"
.word 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, reset, 0
.code
.macro init_cpu
clc
xce
rep #$10 ; X/Y 16-bit
sep #$20 ; A 8-bit
.endmacro
Downloads
ca65_template.7z
green_screen.7z
Written by blargg on 2013-08-22.