- Pascal 75%
- PowerShell 10.1%
- Liquid 10.1%
- Python 2.4%
- Batchfile 1.1%
- Other 1.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
- VRAM / ROM browser: click selects a tile, Shift+click extends a contiguous run inside one zone / bank page (blue outline). - Right-click menu: Copy N tiles, Cut N tiles (move), Paste N tiles here (at the right-clicked slot), Clear N tiles. Edit menu mirrors it as Ctrl+Shift+C / X / V (plain Ctrl+C / V stay the canvas clipboard). - Paste writes raw 2bpp data, so BG <-> art bank <-> sprite <-> font all work; a run that would cross a zone / bank edge is refused without an undo step. One undo step per paste/clear. - Move (Cut + Paste) clears the source and re-points references that can follow: screen cells on a BG->BG move, sprite OAM tiles on OBJ->OBJ, art window cells when the target stays inside the window's bank span. References that cannot follow (e.g. art-window cells when tiles move to BG) are counted and confirmed before the move; Ctrl+Z restores all. Tests: +18 import_zones selftest assertions (BG->bank copy, bank-edge refusal + no undo, in-bank move with art ref follow, bank->BG move with dangling ref, undo, BG->BG move with screen cell follow). run_all ALL GREEN. |
||
| .gitea/workflows | ||
| assets/icons | ||
| docs | ||
| installer | ||
| scripts | ||
| shopify | ||
| tests | ||
| tools | ||
| .gitignore | ||
| about.jpg | ||
| about_form.lfm | ||
| about_form.pas | ||
| AGENTS.md | ||
| app_icons.pas | ||
| build.cmd | ||
| build.sh | ||
| build_output_form.lfm | ||
| build_output_form.pas | ||
| downloader.pas | ||
| engine_export.pas | ||
| EULA.md | ||
| font_editor_frame.lfm | ||
| font_editor_frame.pas | ||
| font_manager_frame.lfm | ||
| font_manager_frame.pas | ||
| main.ico | ||
| main.lpi | ||
| main.lpr | ||
| main.manifest | ||
| main_selftests.inc | ||
| main_window.lfm | ||
| main_window.pas | ||
| nag_form.lfm | ||
| nag_form.pas | ||
| p1xel_resources.rc | ||
| pen_input.pas | ||
| pixel_editor_frame.lfm | ||
| pixel_editor_frame.pas | ||
| project.p1x | ||
| project_io.pas | ||
| README.md | ||
| screen_designer_frame.lfm | ||
| screen_designer_frame.pas | ||
| screen_manager_frame.lfm | ||
| screen_manager_frame.pas | ||
| screen_proofer_form.lfm | ||
| screen_proofer_form.pas | ||
| sha256.pas | ||
| THIRD_PARTY_NOTICES.md | ||
| version.inc | ||
| wizard.pas | ||
P1Xel Editor
A portable pixel editor custom-built for Game Boy (Color) development — from the first tile to a running ROM in one tiny executable.
~2.4 MiB single EXE (free "floppy" edition: ~720 KiB UPX-packed) · no installer · no runtime dependencies · Windows 10+ · native Linux (GTK2) build from the same source
Written in Free Pascal with Lazarus LCL.
Screenshots
Features
Editors & modes
| Editor | What you get |
|---|---|
| Tile Editor | 8×8 indexed 2bpp painting — draw, fill, line, clear; grid toggle, zoom, right-click color-0 erase; Single ⇄ 2×2 meta-tile modes (picking a named asset switches the view automatically) |
| Painter mode | Paint an arbitrary block of tiles as one image, then stamp it anywhere on the map — whole-stamp flipping included |
| Sprite Editor | 128-tile sprite zone; up to 40 sprites per screen; multi-part meta-sprites with positioned parts; hardware-ready OAM export |
| Font Editor + Manager | 81-glyph font with its own manager — edit glyphs, browse the map, and bake text directly onto screens with the text tool |
| Screen Designer | Place tiles and meta-tile stamps, bake text, place sprites, and paint per-cell attributes (palette index + H/V flips) |
| Inspect tool | Click any cell — see the tile's name, whether it is single or meta, and which sprite covers it |
| Screen Manager | Add, rename, delete screens in 20×18 and 32×32 sizes, up to 255 levels |
| Art Windows | 20×18 fullscreen art editor — dedicated windows for title-screen art, each bound to its own ROM bank (up to 16 banks × 192 tiles), with a per-window bank selector and a 1× native proofer |
| Whole-ROM viewer | Every byte of your ROM shown as tiles — sprite zone, font, background, and the raw tail — zoomable |
| Screen Proofer | Engine-accurate preview of any screen: verify the map, attributes, and sprites before you build |
Color
- 8 BG + 8 OBJ CGB palette banks, 4 colors each — edited visually, exported as hardware RGB555
Naming & the data contract
- Name everything — tiles, meta-tiles, sprites, meta-sprites — with duplicate detection and tags (
solid,lethal, custom) - Names flow straight into
catalog.toml; exports use standard Game Boy layouts any engine can consume:
meta.dat level table, palette RAM dumps, level descriptors (v2: + art window table — only when banks exist)
tileset.chr 6144-byte 2bpp tileset (sprites · font · background zones)
bank<k>.chr art bank dumps — up to 16 × 192 tiles, VRAM bank 1 (only when banks exist)
levels.tlm tile maps + CGB attribute planes
art.tlm fullscreen art window records — bank-relative tiles, attribute bit 3 set (only when banks exist)
levels.oam hardware OAM entries per level
catalog.toml every named asset with map bytes and tags (+ [banks], [art_windows])
banks.rgbasm generated bank ROMX sections with size asserts — assembled into the ROM by Build ROM
Projects without art banks export the byte-identical v1 contract — old projects are unaffected. The engine-side bank contract (file layouts, ArtBank<K>Data labels, CGB load recipe) is documented in docs/CONTRACT-BANKS.md: the ROM carries the bank data, ready for engine consumption.
- PNG export at 100% and 400% — any tile, meta-tile, sprite, screen, or the whole ROM
Toolchain — zero to running ROM
- Setup wizard: downloads and installs the RGBDS assembler (pinned release, SHA-256-verified), the BGB emulator, and the nomad-core sample project — staged safely, nothing touched on failure
- One-click Build ROM (rgbasm → rgblink → rgbfix) with live output and the failing file/line in the build log
- Bank-aware ROM builds — art banks ship in the ROM as generated
banks.rgbasmROMX sections, byte-verified at link time - Run in emulator — or watch mode that rebuilds and reloads while you edit
- Tool URLs overridable via
tools/toolchain.ini
Projects that don't lose work
- Binary
.p1xproject format (version 3 — v1/v2 files still open) with atomic saves (write temp → flush → replace) - Autosave every 10 seconds with crash recovery prompt on next launch
- 20-level undo/redo, dirty-state guards on open/close, recent projects, command-line open
Shareware build
The same editor with a 5-second purchase reminder at startup — build mode Release-Shareware (-dSHAREWARE). Buy URL defaults to the product page and is overridable via [Shareware] BuyUrl in tools/toolchain.ini.
Build
Toolchain: Lazarus 4.x + FPC 3.2.2 (lazbuild).
# Windows (from the repo root)
build.cmd Debug # or: Release (sold build, unpacked + signed), Release-Shareware (floppy build, UPX)
powershell -File tests\run_all.ps1 # every automated gate in one go
# Linux (GTK2, x64) — build in a native FS, never on a mounted Windows drive
lazbuild --build-mode=Linux main.lpi
Output lands in builds/. The Linux mode expects LCLWidgetType=gtk2 (default in main.lpi).
Test
Pure-FPC console tests under tests/ — no GUI needed:
fpc -Mobjfpc -Sh tests/loader_compile_test.pas # project loader vectors (v1/v2/sample)
fpc -Mobjfpc -Sh tests/sha256_test.pas # FIPS vectors + pinned rgbds artifacts
cd tests && fpc -Mobjfpc -Sh -Fu.. export_harness.lpr # .p1x -> 5-file export harness
powershell -File tests/run_golden_gate.ps1 # byte-compare exports vs tests/fixtures/
python tests/zipslip/run_matrix.py # zip-slip guard regression matrix
Release packaging
powershell -ExecutionPolicy Bypass -File scripts/package_release.ps1
Runs tests/run_all.ps1 first (red gate = no release), then builds Release (unpacked, Authenticode-signed before zipping) + Release-Shareware (UPX, unsigned), produces dist/ with portable zips (EXE + EULA + notices), the Inno Setup installer (when Inno 6/7 is installed), a *-symbols-win32.zip with the .dbg for crash symbolization (keep, do not publish), and SHA256SUMS.txt. Signing: scripts/sign.cmd (cert thumbprint or Azure Trusted Signing; -RequireSigning refuses to produce unsigned artifacts).
Repository layout
main.lpr / main.lpi project entry + build modes (Debug/Release/Release-Shareware/Linux)
main_window.pas/.lfm the editor (tile/sprite/font hosts, screens, toolchain UI)
engine_export.pas the data-contract exporters (deterministic, golden-testable)
project_io.pas pure-FPC .p1x loader
downloader.pas WinInet (Windows) / fphttpclient (Linux) + zip/tar extraction + SHA-256
wizard.pas toolchain setup wizard (pins, staging, TOFU)
sha256.pas pure-Pascal FIPS 180-4
nag_form.* shareware reminder ({$IFDEF SHAREWARE})
installer/ scripts/ Inno Setup script, packaging + signing
tests/ console tests, golden gate, regression kits
docs/CONTRACT-BANKS.md engine-side art bank contract (bank<k>.chr · art.tlm · meta.dat v2 · banks.rgbasm)
shopify/ storefront templates
License & notices
The application is distributed under its end-user license — see EULA.md. It is built with Free Pascal / Lazarus LCL (modified LGPL — see THIRD_PARTY_NOTICES.md), the free "floppy" edition is packed with UPX (GPL + special exception), and it integrates RGBDS (MIT) and BGB (freeware) at runtime.
P1Xel Editor is not affiliated with, endorsed by, or sponsored by Nintendo. Game Boy is a trademark of Nintendo.
Made in Poland by Cyfrowy Nomada · Fits on a floppy.


