agentsclimarketplace

Nes format

Skill Yuki001/nes-skills/skills/nes-format

iNES, NES 2.0, and UNIF ROM format reference. Use when reading, writing, parsing, or debugging .nes/.unf ROM files, or handling NES ROM headers.From its SKILL.md

Install
npx -y skills add Yuki001/nes-skills --skill nes-format

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

11.3 KB, ~3.6k tokens by cl100k_base, as published. Nobody here has run it

NES ROM Format Reference

Three ROM formats exist: iNES, NES 2.0, and UNIF. NES 2.0 is the current standard and recommended for new dumps. UNIF is deprecated.

Format Detection Quick Guide

Signature in fileFormat
NES + $1A + byte 7 bits 3-2 = 10NES 2.0
NES + $1A + byte 7 bits 3-2 ≠ 10iNES
UNIFUNIF

iNES Format (.nes)

Created by Marat Fayzullin for the iNES emulator. Uses an 8-bit mapper number (0–255). Bytes 8–15 are loosely defined and vary between iNES revisions. NES 2.0 repurposes them with a formal specification.

File Layout

[16-byte Header] [optional 512-byte Trainer] [PRG-ROM data] [CHR-ROM data]

Some ROM images also have a 128-byte title at the end of the file.

Header Byte Map

ByteField
0–3$4E $45 $53 $1A — "NES" + MS-DOS EOF
4PRG-ROM size in 16KB units
5CHR-ROM size in 8KB units (0 = CHR-RAM used)
6Flags 6: NNNN FTBM
7Flags 7: NNNN xxTT
8PRG-RAM size in 8KB units (0 infers 8KB for compatibility)
9TV system: bit 0 = 1 if PAL
10Unofficial extension: TV system, PRG-RAM presence, bus conflicts
11–15Padding (should be zero, but some tools wrote identifying strings here)

Byte 6 Flags (NNNN FTBM)

BitNameMeaning
0MNametable arrangement: 0 = vertical mirroring, 1 = horizontal mirroring
1BBattery-backed PRG-RAM at $6000–$7FFF (or other persistent memory)
2TTrainer present between header and PRG-ROM (512 bytes at $7000–$71FF)
3FAlternative nametable layout (mapper-dependent, often 4-screen)
7–4NMapper number low nibble (D3–D0)

Mirroring notes:

  • Mappers that control mirroring themselves (MMC1, MMC3, AxROM) ignore bit 0.
  • Bit 3 does not always mean 4-screen — some mappers use different combinations (e.g., UNROM 512: %....1..0 = 1-screen, %....1..1 = 4-screen).
  • Mappers with hard-wired 4-screen (Napoleon Senki, Vs. System, GTROM) may have bit 3 redundantly set.

Trainer: 512 bytes loaded at $7000–$71FF. Holds mapper translation / CHR-RAM caching code for early RAM cartridges and Nesticle. Not present on unmodified dumps of original cartridges.

Byte 7 Flags (NNNN xxTT)

BitNameMeaning
1–0TConsole type: 0 = NES/Famicom, 1 = Vs. System, 2 = PlayChoice-10
3–2xNES 2.0 identifier: must be 10 (2) for NES 2.0
7–4NMapper number high nibble (D7–D4)

Mapper number = (byte 7 bits 7–4) << 4 | (byte 6 bits 7–4) → 0–255 for iNES.

PlayChoice-10 games have 8KB of Hint Screen data stored after CHR data. Vs. games have a coin slot and different palettes.

See references/mappers.md for the full mapper reference with detailed specifications.

Byte 10 (Unofficial Extension)

Not part of the original spec; few emulators honor it.

BitsField
1–0TV system: 0 = NTSC, 2 = PAL, 1/3 = dual compatible
5–4PRG-RAM: 0 = present, 1 = absent
6Bus conflicts: 0 = none, 1 = has bus conflicts

Bytes 11–15

Should be zero. If the last 4 bytes are not all zero and this is not NES 2.0, an emulator should mask off the upper 4 bits of the mapper number or refuse to load. Some tools wrote identifying strings here (e.g., "DiskDude!").

iNES Revision Detection

  1. If byte 7 AND $0C = $08 → NES 2.0
  2. If byte 7 AND $0C = $04 → Archaic iNES (no mapper high nibble)
  3. If byte 7 AND $0C = $00, and bytes 12–15 are all zero → iNES
  4. Otherwise → iNES 0.7 or Archaic iNES (treat with caution)

NES 2.0 Format (.nes)

Identified by (byte 7 & $0C) == $08. Backward-compatible with iNES for bytes 0–7. Extends the mapper number to 12 bits (0–4095), adds a submapper for disambiguating board variants, and formally specifies RAM/NVRAM sizing.

File Layout

[16-byte Header] [optional Trainer] [PRG-ROM] [CHR-ROM] [optional Misc ROMs]

Byte 8 — Mapper MSB / Submapper

BitsField
3–0Mapper number D11–D8 (extends to 12 bits total, 0–4095)
7–4Submapper number (0–15, disambiguates board/chip variants without relying on checksums)

See references/mappers.md for the full mapper reference with detailed specifications.

Byte 9 — ROM Size MSB

BitsField
3–0PRG-ROM size MSB (together with byte 4 → 12-bit PRG size)
7–4CHR-ROM size MSB (together with byte 5 → 12-bit CHR size)

Simple mode (MSB nibble $0–$E): PRG = value × 16KB, CHR = value × 8KB. Max: ~63 MB PRG, ~31 MB CHR.

Exponent-multiplier mode (MSB nibble = $F): Used when simple notation cannot represent the exact size. Header bits are reinterpreted:

  • Exponent E = bits D9–D4 (0–63)
  • Multiplier MM = bits D1–D0, actual multiplier = MM×2+1 (1, 3, 5, or 7)
  • Size = 2^E × (MM×2+1) bytes

If actual ROM size is odd and unrepresentable, pad to a representable size.

For Vs. Dual System: first half of PRG belongs to unit 1, second half to unit 2. Known splits exist for Vs. Gumshoe and Vs. Raid on Bungeling Bay.

Byte 10 — PRG-RAM / NVRAM Size

BitsField
4–0PRG-RAM (volatile) shift count
7–5PRG-NVRAM/EEPROM (non-volatile) shift count

Size formula: 64 << shift_count bytes. Shift count 0 = absent (compatibility: 0 infers no RAM).

Battery bit rule: If the upper nibble (NVRAM) is non-zero, byte 6 bit 1 (B) must be set. The reverse also applies unless the only battery-backed memory is mapper-internal or PRG-ROM is self-flashable.

Excludes: mapper-internal memory not CPU-mapped, MMC5 EXRAM, self-flashable PRG-ROM, external storage (cassette, Turbo File).

Byte 11 — CHR-RAM / CHR-NVRAM Size

BitsField
4–0CHR-RAM (volatile) shift count
7–5CHR-NVRAM (non-volatile) shift count

Same encoding as byte 10. Critical: emulators must not assume 8KB CHR-RAM when CHR-ROM is absent — all CHR-RAM must be explicitly specified. Nametable memory (PPU $2000–$2FFF) is excluded from this count even if 4-screen bit is set.

Byte 12 — CPU/PPU Timing

Two low bits:

ValueNameMeaning
0RP2C02NTSC NES
1RP2C07Licensed PAL NES
2Multiple regionSelf-adjusting to both NTSC and PAL
3UA6538Dendy (PAL variant, 50.0063 Hz)

Convention for assigning the correct value:

  • Licensed games: 0 for JP/NA releases, 1 for EU/AU/OC/HK, 2 when the same PRG-ROM shipped in both regions, never 3.
  • Unlicensed/homebrew: author designation first; 2 for self-adjusting; 3 for Chinese releases (Waixing etc.); default to 0.
  • VTxx Famiclones only support RP2C02 or UA6538 → use 0, 2, or 3.

Byte 13 — Vs. System / Extended Console Type

Interpretation depends on byte 7 bits 1–0 (Console Type):

When Console Type = 1 (Vs. System):

BitsField
3–0Vs. PPU variant (RP2C03-xxxx, RP2C04-0001 through -0004, RC2C05-01 through -04)
7–4Vs. Hardware type: 0=Normal, 1=RBI Baseball, 2=TKO Boxing, 3=Super Xevious, 4=Ice Climber, 5=Dual System Normal, 6=Dual System Raid on Bungeling Bay

RP2C04/RC2C05 PPUs use different palettes for copy protection. RC2C05 swaps $2000/$2001 and returns a signature in $2002.

When Console Type = 3 (Extended Console):

ValueConsole
0Regular NES/Famicom/Dendy
1Nintendo Vs. System
2PlayChoice-10
3Famiclone with Decimal Mode CPU
4NES/Famicom with EPSM module
5VT01 (red/cyan STN palette)
6VT02
7VT03
8VT09
9VT32
AVT369
BUMC UM6578
CFamicom Network System

Byte 14 — Miscellaneous ROMs

Bits 1–0: count of extra ROMs after CHR-ROM (0–3). Defined uses:

  • PlayChoice-10: INST-ROM (8KB) + PROM data (16 bytes) + PROM counter out (16 bytes) = 3 misc ROMs
  • VT369: 4KB embedded ROM
  • Mapper 086 submapper 1: speech data ROM
  • Mapper 355: PIC16C54 microcontroller ROM for copy protection
  • Mappers 561/562: non-standard trainers (different size/location than $7000)

Byte 15 — Default Expansion Device

7-bit ID for the expected peripheral at $4016/$4017. $00 = unspecified, $01 = standard controllers. This typically denotes the device required to play the game; for optional devices it lists the device if having it connected doesn't preclude normal controllers. Does not cover cartridge-connected devices (those belong to the mapper definition).

See references/device-ids.md for the complete 80-entry device ID table.


UNIF Format (.unf / .unif)

UNIF uses chunked TLV (Type–Length–Value) blocks, allowing flexible ordering. Deprecated — its originator abandoned the format in December 2008. NES 2.0 is recommended for new work. A few game rips still only exist as UNIF.

File Layout

[32-byte Header] [Chunk] [Chunk] ...

Header:

OffsetSizeValue
04UNIF (literal ASCII)
44LE32 — minimum version needed to parse all chunks
824Null bytes

Each chunk:

OffsetSizeValue
04Type ID (4 ASCII characters)
44LE32 — content length
8NContent (encoding depends on type)

Required Chunk

TypeContentNotes
MAPRNull-terminated UTF-8PCB identifier (e.g., "NES-SNROM", "HVC-UNROM"). Not a mapper number, not a free-form description.

ROM Data Chunks

TypeContentMin Ver
PRGnRaw binary, n-th PRG-ROM chip (n in hex, 0-indexed)4
CHRnRaw binary, n-th CHR-ROM chip4
PCKnLE32 CRC-32 of n-th PRG-ROM5
CCKnLE32 CRC-32 of n-th CHR-ROM5

Optional Metadata Chunks

TypeContentNotes
NAMENull-terminated UTF-8Game name
READNull-terminated UTF-8Comments / license info
DINF204-byte structDumper name (100 bytes), date (day/month/year), tool name (100 bytes)
BATR1-byte booleanBattery-backed RAM present (doesn't disambiguate which RAM)
MIRR1 byteMirroring: 0=horiz, 1=vert, 2=1scrA, 3=1scrB, 4=4scr, 5=mapper-controlled
TVCI1 byteTV: 0=NTSC only, 1=PAL only, 2=compatible with both
CTRL1-byte bitmaskControllers: 1=standard, 2=Zapper, 4=R.O.B., 8=Arkanoid, 16=Power Pad, 32=Four Score
VROR1 byteTreat CHR-ROM as RAM (deprecated, ignored by most emulators)

Key UNIF Shortcomings

  • No PRG-RAM field — two VRC4 games on identical PCBs can differ in PRG-RAM
  • Unordered chunks make patching impossible without unpacking to an intermediate form
  • MAPR abuse — users pick already-supported PCB names rather than creating accurate new ones for emulator compatibility
  • BATR ambiguity — doesn't specify which RAM is battery-backed when multiple are present
  • CTRL limitations — no port assignment, no Famicom-specific peripherals, no SNES controller via adapter, no mouse
  • No support for fully describing Vs. System or PlayChoice-10 hardware
  • ENCODING — before 2013, only 7-bit ASCII was assumed; UTF-8 adopted Q1 2013

What ships with it: 2 files

19.0 KB alongside SKILL.md

references/

Keep looking

Skills are one crate of 326,852. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.