Writing a new ROM
Every ROM needs a little code for it to function properly. In this example we set up the Stack, Interrupts, main program loop, and a zero-page value that increments over time.
The following is a template that includes ideal minimum code required for an executable ROM. Feel free to copy this code directly into your IDE and run the ROM.
1
include "64cube.inc"
2
​
3
ENUM $0
4
counter rBYTE 1
5
ENDE
6
​
7
org $200
8
sei
9
ldx #$ff
10
txs
11
​
12
lda #$0
13
sta VIDEO
14
​
15
_setw IRQ, VBLANK_IRQ
16
cli
17
​
18
Infinite:
19
jmp Infinite
20
​
21
IRQ:
22
inc counter
23
rti
Copied!
Give your new ROM a name. This can be anything so long as it has a .s assembly file extension. Then run your new program as follows:
1
./minicube newrom.s
Copied!
Your program will now run. You should see a collection of pixels, with the one at the top left changing colour.
The ROM will automatically compile to a complete .bin without dependencies that can be loaded separately, and may be distributed as desired. Loading the compiled ROM is done as so:
1
./minicube newrom.bin
Copied!

Breakdown of the ROM Start Template

In this section we'll break down what the template does.
You can write this in any text editing program, but it is best to use an IDE that supports 6502 syntax highlighting and grammar, such as VIM or Atom.
The first thing we should do is include the header file, which contains useful aliases and macros.
1
include "64cube.inc"
Copied!
Next is typically the block that enumerates any values for the zero-page. Think of these as variables. Here we define a byte value that is used as a counter.
1
ENUM $0
2
counter rBYTE 1
3
ENDE
Copied!
We must now specify the origin of the ROM program and set the Interrupt. Setting the Stack Pointer should also be done here:
1
org $200
2
sei
3
ldx #$ff
4
txs
Copied!
0x0200 must be the start address for all ROMS.
Now to set the VIDEO register. To do this we load the Accumulator with the high-byte of the intended frame-buffer memory page.
1
lda #$0
2
sta VIDEO
Copied!
TheVIDEOregister can be set to any 4k page within0x0000β€”0xF000
It is good practice to set this to at least0x1000however in this example it is at the beginning of memory and the zero-page, so we can see something happening.
Next we set the vector for the VBLANK Interrupt. We can use the _setw macro here.
1
_setw IRQ, VBLANK_IRQ
2
cli
Copied!
Now we have the main program loop. It does nothing in this example but is important to exist and function otherwise the ROM simply ends.
1
Infinite:
2
jmp Infinite
Copied!
We are giving this loop the Infinite label but it can have any unique name.
Lastly is the VBLANK Interrupt loop. The IRQ fires once per frame. Here we are only doing something basic, incrementing a timer, the counter we defined earlier.
1
IRQ:
2
inc counter
3
rti
Copied!
Last modified 4mo ago