This is a CHR tile editor for the NES (Famicom) created using Rust and egui.
In addition to the basic features of YY-CHR, it includes 10 types of drawing tools, PNG import, and continuous scrolling display, all designed to enhance usability.
cargo run --releaseRequires Rust 1.80 or later.
Cargo will automatically fetch the required libraries.
You can open a file in Bank View by selecting it from File β Openβ¦ or by dragging and dropping it into the window.
Supported Formats:
.nesβ iNES format. Supports ROMs that include CHR-ROM.binβ Headerless raw CHR binary.zipβ Automatically extract and load the first.nesfile in the ZIP
File β New File creates an empty 16KB CHR data file (newfile).
| Action | Shortcut |
|---|---|
| Save | βS / Ctrl+S |
| Save As | ββ§S / Ctrl+Shift+S |
When there are unsaved changes, an asterisk (*) is shown in the title bar.
A confirmation dialog appears when you try to close the window.
- Bank View (left): Minimum width 410px. Integer-scale zoom to fit window width
- Dot Editor (center): Resizable. Minimum 180px
- Info Panel (right): Fixed width 245px
Displays all CHR data as a vertical texture with 16 tiles per row (128px). 1 row = 16 tiles Γ 16 bytes = 0x100 bytes. Use the scrollbar to navigate up and down.
Enter a hex address in the "Address:" field in the toolbar and press the Go button or Enter to jump to that position.
The selection block (= editing unit in the Dot Editor) can be switched between 5 sizes.
| Button | Size | Tiles |
|---|---|---|
8 |
8Γ8 px | 1Γ1 tiles |
16 |
16Γ16 px | 2Γ2 tiles |
32 |
32Γ32 px | 4Γ4 tiles |
64 |
64Γ64 px | 8Γ8 tiles |
128 |
128Γ128 px | 16Γ16 tiles |
Clicking a tile sets it as the selection origin, and the Dot Editor displays the tile block for the current focus size.
The selected tile block (based on focus size) is displayed enlarged for editing. Click the toolbar icons or use keyboard shortcuts to select tools.
| Action | Description |
|---|---|
| Right-click | Eyedropper β sets the clicked pixel's color as the drawing color |
Click and drag to draw one pixel at a time. Even when dragging across multiple tiles, all changes can be undone in a single Undo step.
Draws in a checkerboard pattern using (x+y) % 2 parity from the click origin, skipping every other pixel. The pattern remains seamless even across tile boundaries.
Click to set a start point and drag to draw a straight line. Uses Bresenham's algorithm for integer-precise lines. A real-time preview is shown while dragging. Confirmed on button release.
Drag to specify two corners and draw only the outer border. Confirmed on button release.
Fills the entire interior of the rectangle. Confirmed on button release.
Fills the rectangle area with a checkerboard pattern based on the origin parity. Confirmed on button release.
Defines an ellipse by its bounding box (two diagonal corners) and draws the outline only. Combines left/right row endpoints and top/bottom column endpoints for a gap-free outline. Confirmed on button release.
Fills the entire interior of the ellipse using a scanline method. Confirmed on button release.
Fills all connected pixels of the same color index at the clicked position using BFS (breadth-first search). 4-directional connectivity. Does nothing if the clicked color matches the drawing color.
A two-phase copy & paste tool.
| Phase | Action | Behavior |
|---|---|---|
| Select (Phase 1) | Drag | Preview the selection with a dashed border |
| Release | Confirm the area and copy it into the buffer | |
| Paste (Phase 2) | Drag | Dashed outline + pixel preview follows the cursor |
| Release | Write to CHR (buffer is retained) | |
| Right-click | Cancel and return to Phase 1 |
The buffer is retained so you can stamp the same content multiple times.
| Action | Shortcut |
|---|---|
| Copy | βC / Ctrl+C |
| Paste | βV / Ctrl+V |
Copies the current focus-size tile block to the clipboard and pastes it at the selected tile position. Paste can be undone.
| Key | Action |
|---|---|
β β β β |
Move selected tile by 1 tile |
Z / X / C / V |
Switch palette set 0β3 |
βN / Ctrl+N |
New file |
βZ / Ctrl+Z |
Undo |
βC / Ctrl+C |
Copy tiles |
βV / Ctrl+V |
Paste tiles |
βS / Ctrl+S |
Save |
ββ§S / Ctrl+Shift+S |
Save As |
When the selected tile moves off-screen with the arrow keys, the view auto-scrolls.
Displays the NES palette (DAT palette) as 4 sets Γ 4 colors. Select a cell and choose a color from the NES 64-color picker to change it.
Switch the set used for Bank View rendering with the Z / X / C / V keys.
The following operations are available from the Palette menu.
| Menu Item | Description |
|---|---|
| Open PAL file⦠| Load a .pal file (192 bytes = 64 colors à 3 RGB bytes) and overwrite the master palette |
| Open DAT file⦠| Load a .dat file (16+ bytes) and update the palette sets |
| Save DAT file⦠| Export the current palette sets as a .dat file |
| Reset Master Palette (NES Standard) | Restore the built-in NES standard 64-color palette |
On startup, assets/rchr.pal (master palette) and assets/rchr.dat (palette sets) are loaded automatically.
Compatible with YY-CHR format.
While YY-CHR's "Paste Image" only supports 8bpp indexed BMP / 8-bit indexed PNG, r-chr accepts all of the following:
- Indexed color PNG (1-bit / 2-bit / 4-bit / 8-bit)
- Full color PNG (RGB / RGBA)
- PNG with transparency (tRNS chunk / alpha channel)
- File β Import PNGβ¦ to open a file selection dialog
- Drag and drop a PNG file onto the window
A NES / BIN file must be opened first.
After selecting a PNG, a confirmation dialog appears.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PNG Import β
β β
β File: sprite.png (32Γ32 px = 4Γ4 tiles) β
β β
β Mapping Strategy: β
β β Palette Match (recommended) β Index Direct β RGB Approx β
β β
β β 3 colors could not be exactly matched and were approximated β
β β 1 transparent palette entry β mapped to index 0 β
β β
β Preview (after conversion): β
β [Preview rendered in converted CHR colors] β
β β
β Paste at: Tile 0 (0x000000) β
β β
β [Cancel] [Paste] β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Paste at: The currently selected tile in Bank View is used as the origin
- After pasting: Can be undone with Undo (
βZ/Ctrl+Z) - Mapping Strategy: Switching via radio button updates the preview in real time
3 methods are available for converting PNG pixels to CHR color indices (0β3). The strategy is auto-selected based on the file type, but can be changed manually in the dialog.
Auto-selected when: Indexed color PNG with a PLTE chunk
Ideal when working in Aseprite with the NES master palette.
Conversion flow:
PLTE[i] RGB
β Nearest-neighbor match among NES master palette 64 colors
β Select the closest of the 4 colors in the current DAT palette set
β Convert to CHR index 0β3
Aseprite workflow:
- Create a sprite in Indexed Color mode in Aseprite
- Set the palette from
rchr.palor the game's actual NES palette - File β Export as PNG (keeping indexed color mode)
- Open the file in r-chr and select the target tile
- File β Import PNGβ¦ or D&D to import β "Palette Match" is auto-selected
- Check the preview and press Paste
Auto-selected when: Indexed color PNG without a PLTE chunk
Pixel index value mod 4 β CHR index 0β3
Use case: When the first 4 palette entries (indices 0β3) are intentionally mapped to CHR 0β3.
Auto-selected when: Full color PNG (RGB / RGBA)
Each pixel's RGB
β Calculate RGB distance to the 4 colors in the current DAT palette set
β Map to the closest color index 0β3 β write to CHR
Use case: Full color PNGs, screenshots, images converted from BMP, or any arbitrary PNG. Color reproduction is approximate only. Accuracy improves when the DAT palette matches the game's actual palette.
When a PNG contains transparent pixels (tRNS chunk / alpha channel), they are automatically mapped to CHR index 0.
| Format | Transparency Condition |
|---|---|
| Indexed PNG (with tRNS) | Palette entries with alpha = 0 in tRNS |
| RGBA PNG | Pixels with alpha value < 128 |
In NES CHR, index 0 corresponds to the background color (transparent color for sprites), so mapping transparent pixels to 0 ensures the sprite appearance is set correctly. The count of transparent pixels is shown in the dialog's warning area.
All drawing operations and PNG imports support Undo.
| Operation | Undo Unit | Max Steps |
|---|---|---|
| Dot Editor editing (pencil, drag) | All tile changes in one drag stroke | 100 |
| Line / Rectangle / Ellipse / Flood Fill | All tile changes for one shape | 100 |
| Stamp | All tile changes in one stamp | 100 |
| Tile Paste | All tile changes in one paste | 100 |
| PNG Import | All affected tiles in one batch | 100 |
src/
main.rs β Entry point & window setup
native_menu.rs β macOS native menu (muda crate)
editor/
mod.rs
app.rs β App state & main loop (eframe::App)
bank_view.rs β Bank View (full CHR display & tile selection)
clipboard.rs β Tile copy & paste
dot_editor.rs β Dot Editor & 10 drawing tools
file_ops.rs β Open / Save / New file operations
info_panel.rs β Right panel (palette, draw color, info display)
keyboard.rs β Keyboard shortcut handling
png_import.rs β PNG import dialog
setup.rs β Font setup
theme.rs β Color, font & size constants
mac/
mod.rs
menu_bar.rs β egui menu bar (non-macOS)
menu_events.rs β macOS native menu event handling
io/
mod.rs
chr.rs β CHR decode / encode / rendering
nes.rs β iNES format parser / RomData type
png.rs β PNG / BMP import (mapping & CHR write)
model/
mod.rs
palette.rs β NES palette (MasterPalette / DatPalette)
assets/
rchr.pal β Default master palette (YY-CHR compatible .pal)
rchr.dat β Default palette sets (YY-CHR compatible .dat)
rchr.bin β Default CHR data displayed on startup (R-CHR logo)
nes.pal β NES standard 64-color palette (for reset)
icons/ β SVG icons for toolbar & drawing tools
This tool was developed with reference to YY-CHR. YY-CHR is a well-established NES / SNES CHR editor, and served as a major reference for the basic interface design and CHR format handling.
This project is licensed under the MIT License. See the LICENSE file for details.
Daisuke Takayama


