nes-format — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited nes-format (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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.
| Signature in file | Format |
|---|---|
NES + $1A + byte 7 bits 3-2 = 10 | NES 2.0 |
NES + $1A + byte 7 bits 3-2 ≠ 10 | iNES |
UNIF | UNIF |
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.
[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.
| Byte | Field |
|---|---|
| 0–3 | $4E $45 $53 $1A — "NES" + MS-DOS EOF |
| 4 | PRG-ROM size in 16KB units |
| 5 | CHR-ROM size in 8KB units (0 = CHR-RAM used) |
| 6 | Flags 6: NNNN FTBM |
| 7 | Flags 7: NNNN xxTT |
| 8 | PRG-RAM size in 8KB units (0 infers 8KB for compatibility) |
| 9 | TV system: bit 0 = 1 if PAL |
| 10 | Unofficial extension: TV system, PRG-RAM presence, bus conflicts |
| 11–15 | Padding (should be zero, but some tools wrote identifying strings here) |
NNNN FTBM)| Bit | Name | Meaning |
|---|---|---|
| 0 | M | Nametable arrangement: 0 = vertical mirroring, 1 = horizontal mirroring |
| 1 | B | Battery-backed PRG-RAM at $6000–$7FFF (or other persistent memory) |
| 2 | T | Trainer present between header and PRG-ROM (512 bytes at $7000–$71FF) |
| 3 | F | Alternative nametable layout (mapper-dependent, often 4-screen) |
| 7–4 | N | Mapper number low nibble (D3–D0) |
Mirroring notes:
%....1..0 = 1-screen, %....1..1 = 4-screen).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.
NNNN xxTT)| Bit | Name | Meaning |
|---|---|---|
| 1–0 | T | Console type: 0 = NES/Famicom, 1 = Vs. System, 2 = PlayChoice-10 |
| 3–2 | x | NES 2.0 identifier: must be 10 (2) for NES 2.0 |
| 7–4 | N | Mapper 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.
Not part of the original spec; few emulators honor it.
| Bits | Field |
|---|---|
| 1–0 | TV system: 0 = NTSC, 2 = PAL, 1/3 = dual compatible |
| 5–4 | PRG-RAM: 0 = present, 1 = absent |
| 6 | Bus conflicts: 0 = none, 1 = has bus conflicts |
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!").
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.
[16-byte Header] [optional Trainer] [PRG-ROM] [CHR-ROM] [optional Misc ROMs]| Bits | Field |
|---|---|
| 3–0 | Mapper number D11–D8 (extends to 12 bits total, 0–4095) |
| 7–4 | Submapper number (0–15, disambiguates board/chip variants without relying on checksums) |
See references/mappers.md for the full mapper reference with detailed specifications.
| Bits | Field |
|---|---|
| 3–0 | PRG-ROM size MSB (together with byte 4 → 12-bit PRG size) |
| 7–4 | CHR-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:
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.
| Bits | Field |
|---|---|
| 4–0 | PRG-RAM (volatile) shift count |
| 7–5 | PRG-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).
| Bits | Field |
|---|---|
| 4–0 | CHR-RAM (volatile) shift count |
| 7–5 | CHR-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.
Two low bits:
| Value | Name | Meaning |
|---|---|---|
| 0 | RP2C02 | NTSC NES |
| 1 | RP2C07 | Licensed PAL NES |
| 2 | Multiple region | Self-adjusting to both NTSC and PAL |
| 3 | UA6538 | Dendy (PAL variant, 50.0063 Hz) |
Convention for assigning the correct value:
Interpretation depends on byte 7 bits 1–0 (Console Type):
When Console Type = 1 (Vs. System):
| Bits | Field |
|---|---|
| 3–0 | Vs. PPU variant (RP2C03-xxxx, RP2C04-0001 through -0004, RC2C05-01 through -04) |
| 7–4 | Vs. 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):
| Value | Console |
|---|---|
| 0 | Regular NES/Famicom/Dendy |
| 1 | Nintendo Vs. System |
| 2 | PlayChoice-10 |
| 3 | Famiclone with Decimal Mode CPU |
| 4 | NES/Famicom with EPSM module |
| 5 | VT01 (red/cyan STN palette) |
| 6 | VT02 |
| 7 | VT03 |
| 8 | VT09 |
| 9 | VT32 |
| A | VT369 |
| B | UMC UM6578 |
| C | Famicom Network System |
Bits 1–0: count of extra ROMs after CHR-ROM (0–3). Defined uses:
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 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.
[32-byte Header] [Chunk] [Chunk] ...Header:
| Offset | Size | Value |
|---|---|---|
| 0 | 4 | UNIF (literal ASCII) |
| 4 | 4 | LE32 — minimum version needed to parse all chunks |
| 8 | 24 | Null bytes |
Each chunk:
| Offset | Size | Value |
|---|---|---|
| 0 | 4 | Type ID (4 ASCII characters) |
| 4 | 4 | LE32 — content length |
| 8 | N | Content (encoding depends on type) |
| Type | Content | Notes |
|---|---|---|
MAPR | Null-terminated UTF-8 | PCB identifier (e.g., "NES-SNROM", "HVC-UNROM"). Not a mapper number, not a free-form description. |
| Type | Content | Min Ver |
|---|---|---|
PRG_n_ | Raw binary, n-th PRG-ROM chip (_n_ in hex, 0-indexed) | 4 |
CHR_n_ | Raw binary, n-th CHR-ROM chip | 4 |
PCK_n_ | LE32 CRC-32 of n-th PRG-ROM | 5 |
CCK_n_ | LE32 CRC-32 of n-th CHR-ROM | 5 |
| Type | Content | Notes |
|---|---|---|
NAME | Null-terminated UTF-8 | Game name |
READ | Null-terminated UTF-8 | Comments / license info |
DINF | 204-byte struct | Dumper name (100 bytes), date (day/month/year), tool name (100 bytes) |
BATR | 1-byte boolean | Battery-backed RAM present (doesn't disambiguate which RAM) |
MIRR | 1 byte | Mirroring: 0=horiz, 1=vert, 2=1scrA, 3=1scrB, 4=4scr, 5=mapper-controlled |
TVCI | 1 byte | TV: 0=NTSC only, 1=PAL only, 2=compatible with both |
CTRL | 1-byte bitmask | Controllers: 1=standard, 2=Zapper, 4=R.O.B., 8=Arkanoid, 16=Power Pad, 32=Four Score |
VROR | 1 byte | Treat CHR-ROM as RAM (deprecated, ignored by most emulators) |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.