SNES Example 1

Finally, some real programming!

Let’s do the simplest possible thing, to make sure that ca65 is working and we can get something to assemble correctly. We are going to turn the screen red.



.include "regs.asm"
.include "variables.asm"
.include "macros.asm"
.include "init.asm"

.segment "CODE"

  ;enters here in forced blank
.a16 ;just a reminder of the setting from init code

  stz CGADD ; set color address to 0
  lda #$1f     ;palette low byte gggrrrrr
  sta CGDATA; 1f = all the red bits
  lda #$00     ;palette high byte -bbbbbgg
  sta CGDATA; store zero for high byte

  ;turn the screen on (end forced blank)
  lda #$0f
  sta INIDISP ;$2100

  jmp InfiniteLoop

.include "header.asm"

Notice that every asm file is included into the main file. That is to keep our compile.bat as simple and error proof as possible. I have put the SNES_01 folder inside my cc65 folder, and so the path to the bin folder is ..\bin\


Let’s go over every line.

.p816 – puts the assembler in 65816 mode

.smart – tell the assembler to automatically adjust register size depending on REP / SEP changes (handled through macros like A8, AXY16, etc)

.include – all of our constants, macros, init code, and header file.

.segment “CODE” – where will our main code end up, in the CODE segment

main: – our label, where the init code jumps to at startup

.a16 / .i16 – this is what the register size was when it left init. These are assembler directives to set A and XY assembly to 16 bit size.

phk / plb – not that important here, but sets the Data Bank Register to the same as the Program Bank (which is currently $80, a mirror of $00, and necessary for fastROM).

A8 – a macro to put the A register in 8 bit mode, I know it’s confusing since I just told the assembler to do A16 a second ago. If you like, you can delete the .a16 line since we change it right away, but I like to leave directives just to remind myself what the settings were just before we got here.

stz CGADD ;$2121 – set the palette address register to zero

lda #$1f – load A register with the value $1f – the low byte of the color $001f = red.

sta CGDATA ;$2122 – send the low byte to the palette (CGRAM)

lda #$00 – load A register with the value $00 – the upper byte of the color.

sta CGDATA ;$2122 – send the high byte to the palette

lda #$0f – full brightness, no forced blank
sta INIDISP ;$2100 – effectively turns the screen ON

$2100 hardware register bits… x- – -bbbb
x = forced blank if set (turns off screen rendering)… $80
b = screen brightness, from 0 = black to $0f = full brightness

jmp InfiniteLoop – will jump repeatedly to this line

Now, we did NOT activate anything on the “main screen”, such as layers 1,2,3, or 4, or sprites (objects). With nothing on main, only the background color will show, which is the 0th palette entry.


Each color is 15 bits, BGR (the upper bit should be 0). Try changing the color and re-assembling. If you run it in MESEN-S, remember to reload from file/open and not click on the picture of the file (which only reloads the savestate, rather than reloading from file).

-bbbbbgg gggrrrrr
black = $0000
red = $001f
green = $03e0
blue = $7c00
white = $7fff

Here’s what it looks like. It’s not much, but we need to start somewhere.


And, if you look at the palette viewer, you can see our color at index 0.



Before we go, I just want to briefly mention the other files here.

Init.asm is the RESET code (and a few other bits). It zeroes all the registers and RAM and gets us to square one, before jumping long to main. Don’t feel like you need to understand every line in this file. Focus on the main code for now.

macros.asm is a few assembler macro definitions, like A8, AXY16, etc.

regs.asm is a list of constants, the SNES hardware registers. Also there are some constants that I wrote that will help.

If you want to  read about the hardware registers, go here…

variables.asm is a list of variables, which are in the “zeropage” or “BSS” (LoRAM) segments. There is just a little bit here used by the init code. We will add to this later.

And, lastly, the compiled ROM is the SNES_01.sfc file. This is what you should open in an emulator. I recommend the MESEN-S emulator. The usual file extension for SNES files are .sfc or .smc. SFC for Super Famicom and SMC for Super Magicom (a cartridge dumper / copier from the old days).


By the way, I had written a library of code (EasySNES), but I did not use most of it here. I was discussing the matter with some friends, and I feel that SNESdev could be taught better with simpler examples, and the library will just obfuscate what is really going on.

(SNESdev SNES SFC Super Nintendo Super Famicom programming tutorial)


My apologies, since this first tutorial is essentially the same as this one…

I didn’t copy it. We just both coincidentally arrived at the same first step. Oh well. The next steps will be different.

SNES main page


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s