Programming NROM

From NESdev Wiki
Jump to navigationJump to search

NROM and the other boards that make up mapper 0 are the simplest of all NES cartridge boards. All address decoding and chip enable handling are handled by the NES hardware; the only integrated circuits on the board are the PRG-ROM, CHR-ROM, and (in 72-pin carts) the CIC. This simplicity lends itself well to small-scale, beginner-level tutorials and projects.

Configuration

NROM has two major board configurations:

  • NROM-256 with 32KiB PRG-ROM and 8KiB CHR-ROM
  • NROM-128 with 16KiB PRG-ROM and 8KiB CHR-ROM

Your program is mapped into $8000-$FFFF (NROM-256) or both $8000-$BFFF and $C000-$FFFF (NROM-128). Most NROM-128 games actually run in $C000-$FFFF rather than $8000-$BFFF because it makes the program easier to assemble and link. Some kinds of data used by the NES CPU, such as the interrupt vectors and DPCM samples, have to be in $C000-$FFFF, and it simplifies the linker script if everything is in the same memory region. There are probably a few games that rely on the mirroring, but experiments with a multicart engine show that most can run with garbage in $8000-$BFFF.

NES 2.0 header

Below is an example NES 2.0 header for NROM boards. It should be backward-compatible with emulators supporting only the older iNES header format, but they may emulate extra RAM at $6000-$7FFF, whereas official boards (except for Family BASIC) have open bus instead.

.segment "HEADER"
  .byte "NES", $1A
  .byte 2         ; PRG-ROM size: 1 or 2 x 16KiB for NROM-128 or NROM-256 respectively
  .byte 1         ; CHR-ROM size: 1 x 8KiB
  .byte $00       ; Mapper 0; No battery; Vertical arrangement ("Horizontal mirroring")
  .byte $08       ; Mapper 0; NES 2.0 identifier
  .byte $00       ; No submapper
  .byte $00       ; PRG-ROM not 4 MiB or larger
  .byte $00       ; No PRG-RAM
  .byte $00       ; No CHR-RAM
  .byte $00       ; CPU/PPU timing: NTSC
  .byte $00       ; Not a Vs. System or extended console type
  .byte $00       ; No misc. ROMs
  .byte $00       ; Default expansion device: Unspecified

To use horizontal arrangement ("vertical mirroring") instead of vertical arrangement ("horizontal mirroring"), change the first .byte $00 after the CHR-ROM size field to .byte $01.

Common problems

Here are some common problems encountered in NROM (or similar discrete logic mapper) projects and their associated workarounds:

  • No on-board IRQ source for scroll splits or other raster effects - Use Sprite-0 hit. DMC IRQ, Sprite overflow, and/or cycle-timed code can also work but are trickier to get right.
  • No CHR-ROM banking for tile animations - Use PPUCTRL bits 4-3 as a "poor man's CNROM" by swapping the pattern table access between PPU $0000 and $1000.
  • No game save capabilities (outside of Family BASIC) - Use a password system.

More advanced requirements, such as fine-grained PRG/CHR bankswitching, nametable arrangement switching at runtime, or IRQ generation, will necessitate a mapper change (sometimes to an ASIC mapper). The project scope and budget should be evaluated beforehand if this is the case, especially if publishers and boardmakers are involved.

Example programs

CA65: