NES Development

Here we will be learning how to make games for the NES using 6502 Assembly. The NES uses a modified 6502, so not everything is the same. There also won’t be code simulators (yet).

Background

The first “game” we are going to create will show how to create a background and change the color. All of the source code is on GitHub.

Setting Up

The first thing you want to do is download NESASM3, which compiles Assembly code into .nes files. You might want to add it to your Path for later use.

After setting up NESASM, you’re going to want to grab an emulator. I recommend FCEUXD SP. It has a great Debugger and loads of options.

Next, create an Assembly file. For this tutorial, we’ll be using background.asm. To compile it, run NESASM3 background.asm in your shell. It should come up with pass 1 and pass 2. Stick the .nes file in your emulator and you’re ready to go!

iNes Header

The 16 byte iNES header gives the NES all the information about the game including mapper, graphics mirroring, and PRG/CHR sizes. This will be the start of your file.

.inesprg 1   ; 1x 16KB bank of PRG code
  .ineschr 1   ; 1x 8KB bank of CHR data
  .inesmap 0   ; mapper 0 = NROM, no bank swapping
  .inesmir 1   ; background mirroring (ignore for now)

Reseting the system

Next, we need to reset the system. This will clear the memory and reset various things. You can put this in your code right after the header.

.bank 0
  .org $C000 
RESET:
  sei          ; disable IRQs
  cld          ; disable decimal mode
  ldx #$40
  stx $4017    ; disable APU frame IRQ
  ldx #$FF
  txs          ; Set up stack
  inx          ; now X = 0
  stx $2000    ; disable NMI
  stx $2001    ; disable rendering
  stx $4010    ; disable DMC IRQs

vblankwait1:       ; First wait for vblank to make sure PPU is ready
  bit $2002
  bpl vblankwait1

clrmem:
  lda #$00
  sta $0000, x
  sta $0100, x
  sta $0200, x
  sta $0400, x
  sta $0500, x
  sta $0600, x
  sta $0700, x
  lda #$FE
  sta $0300, x
  inx
  bne clrmem
   
vblankwait2:      ; Second wait for vblank, PPU is ready after this
  bit $2002
  bpl vblankwait2

Rendering a background

For now, we’re only going to render a background color. To do this, we will be writing to a special byte of memory.

The byte $2001 renders the background. Inputting a binary number, we can add a variety of options.

76543210
||||||||
|||||||+- Grayscale (0: normal color; 1: AND all palette entries
|||||||   with 0x30, effectively producing a monochrome display;
|||||||   note that colour emphasis STILL works when this is on!)
||||||+-- Disable background clipping in leftmost 8 pixels of screen
|||||+--- Disable sprite clipping in leftmost 8 pixels of screen
||||+---- Enable background rendering
|||+----- Enable sprite rendering
||+------ Intensify reds (and darken other colors)
|+------- Intensify greens (and darken other colors)
+-------- Intensify blues (and darken other colors)
lda #%100000   ;intensify blue
sta $2001

Next, we want to do some looping.

Forever:
  jmp Forever     ;jump back to Forever, infinite loop
NMI:
  rti