11 September 2026
Converting NES CHR ROM Files (.CHR) to Lossless PNG Sprite Sheets
In the golden era of 8-bit gaming, the Nintendo Entertainment System (NES) and Family Computer (Famicom) captivated millions with iconic characters like Mario, Link, Samus, and Mega Man. Beneath the hood, these visuals were rendered by the Ricoh 2C02 Picture Processing Unit (PPU) reading graphical pattern tables stored in CHR ROM (.chr).
Whether you are extracting sprites from an iNES ROM, writing homebrew games with modern toolchains (like CC65 or NESLib), or studying 8-bit pixel art techniques, .chr files are everywhere. However, modern graphics programs cannot open raw 2bpp planar binary files.
This technical guide explores how NES PPU tile memory works, how 2-bit planar pixels are reconstructed, and how to convert .chr tile banks into modern 32-bit PNG sprite sheets with convrtr's NES CHR to PNG converter.
Anatomy of the 2-Bit-per-Pixel (2bpp) Planar Format
Each graphical tile on the NES is an 8 × 8 pixel grid and can display up to 4 simultaneous colors chosen from the PPU color palette.
To maximize memory efficiency, the NES PPU stores tiles in a planar format rather than an interleaved or chunky raster format:
- A single 8 × 8 tile occupies exactly 16 bytes.
- Bytes 0 to 7 represent Bitplane 0 (one byte per scanline row from top to bottom).
- Bytes 8 to 15 represent Bitplane 1 (one byte per scanline row from top to bottom).
To determine the color of a pixel at row y and column x (0 <= x, y < 8):
- Extract bit
7 - xfrom Bitplane 0 row byte:bit0 = (plane0[y] >> (7 - x)) & 1 - Extract bit
7 - xfrom Bitplane 1 row byte:bit1 = (plane1[y] >> (7 - x)) & 1 - Combine both bits into a 2-bit color index (0, 1, 2, or 3):
colorIndex = (bit1 << 1) | bit0
Pattern Table Layout and Sizing
Standard NES game cartridges allocate an 8KB CHR bank (8,192 bytes):
8,192 bytes / 16 bytes per tile = 512 tiles.- The PPU divides this into two 4KB pattern tables:
- Pattern Table 0: Background tiles (256 tiles, 128x128 px).
- Pattern Table 1: Sprite tiles (256 tiles, 128x128 px).
- Arranged in standard 16-tile rows, an 8KB file formats cleanly into a 128 × 256 pixel sprite sheet.
Converting CHR to Modern PNG
Because raw .chr files contain no color palette headers, convrtr's in-browser CHR decoder lets you choose from multiple display palettes:
- NES PPU Grayscale: Renders the 4 shades directly as white, light gray, dark gray, and black for sprite editing.
- Game Boy Green Phosphor: Classic DMG-01 four-shade monochrome LCD tint.
- Retro Platformer Color: Pre-mapped character colors with transparent background.
- Integer Scaling: 1x, 2x, or 4x nearest-neighbor scaling for crisp pixel-art preview on retina screens.
The entire conversion runs client-side in your browser using pure TypeScript and WebAssembly, ensuring your homebrew ROM assets never leave your device.