# Writing a new ROM

Every ROM needs a little code for it to function properly.

In this example we set up a template that includes the ideal minimum code required for an executable ROM. This typically includes setting up things such as the Stack, Interrupts, main program loop, and for demonstration, a zero-page value that increments over time.

Feel free to copy this code directly into your IDE or text editor.

```asm6502
include "64cube.inc"

;zero-page values
ENUM $0
  counter db 1
ENDE

;called once at start
  org $200
  sei
  ldx #$ff
  txs

  lda #$0
  sta VIDEO

  _setw IRQ, VBLANK_IRQ
  cli

;constant loop
Main:
  jmp Main

;called once per frame
IRQ:
  inc counter
  rti
```

Give your new program a name. This can be anything so long as it has a `.s` assembly file extension. Then run your new ROM as follows:

```bash
./minicube newrom.s
```

You should now see a collection of pixels, with the one at the top left flickering, changing colour. These pixels are a visual representation of your program code in memory.

![](https://1901532303-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MYlgFz1gOz3pvCbWdEb%2Fuploads%2Fhva74ZC28AF7LLsQ8PWL%2FScreenshot%202022-01-06%20at%2009.24.35.png?alt=media\&token=ff78d7a2-b83a-449d-a435-954d2d188b4e)

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:

```bash
./minicube newrom.bin
```

## Breakdown of the ROM Start Template

In this section we'll look at 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.

```bash
include "64cube.inc"
```

Next is typically the block that enumerates any values for the zero-page. You can think of these as variables. Here we define a byte value that will be used as a counter.

```bash
ENUM $0
  counter db 1
ENDE
```

We must now specify the origin of the ROM program and set the Interrupt. Any instructions here are called once when the program starts. Setting the Stack Pointer should also be done here:

```asm6502
  org $200
  sei
  ldx #$ff
  txs
```

{% hint style="warning" %}
`0x0200` must be the start address for all programs.
{% endhint %}

Now to set the `VIDEO` register. To do this we load the Accumulator `lda` with the high-byte of the intended frame-buffer memory page.

```asm6502
  lda #$0
  sta VIDEO
```

{% hint style="info" %}
The`VIDEO`register can be set to any 4k page within`0x0000—0xF000`&#x20;

It is good practice to set this to at least`0x1000`however in this example it is at the beginning of memory and the zero-page, so we can see something happening. If not set the `VIDEO` register will default to `0x0000`
{% endhint %}

Next we set the vector for the VBLANK Interrupt. We can optionally use the `_setw` macro here simply because it is easier to work with. See more about [Macros here](https://aeriform.gitbook.io/minicube64/aliases).&#x20;

```asm6502
  _setw IRQ, VBLANK_IRQ
  cli
```

Now we have the main program loop. At least one loop must exist so that the ROM does not simply end. Usually anything in it would be called constantly, but for now it does nothing.

```asm6502
Main:
  jmp Main
```

{% hint style="info" %}
We are giving this loop the `Main` label but it can have any unique name.&#x20;
{% endhint %}

Lastly is the `VBLANK` Interrupt loop. The IRQ fires once per frame. Here we are only doing something basic, incrementing a timer, the `counter` value we defined earlier.

```asm6502
IRQ:
  inc counter
  rti
```

And that's it!

For reference, this is the absolute minimum required for a working ROM.

```asm6502
  org $200
  sei

Main:
  jmp Main
```
