1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 08:55:38 +00:00
nescript/examples/auto_chr_background.ne

49 lines
1.8 KiB
Text
Raw Normal View History

assets: auto-generate CHR data from @nametable() PNG sources `background Foo @nametable("file.png")` previously decoded the PNG into a tile-index table and an attribute table but left CHR generation to the user — they had to supply matching tiles via a separate `sprite Tileset @chr(...)` declaration in the same deduplication order, which was both error-prone and the main thing keeping the shortcut form from being a one-liner. The CHR pipeline now closes the gap. `png_to_nametable_with_chr` returns a `PngNametable` carrying the tile-index table, the attribute table, *and* a per-tile CHR blob encoded with the same brightness-bucketing `png_to_chr` already uses for sprites. The resolver passes `next_sprite_tile` (computed from the resolved sprite list) so each background's CHR allocation slots in immediately after the sprite range, and rewrites the nametable indices to point at the actual physical tile numbers. The linker copies each background's `chr_bytes` into CHR ROM at `chr_base_tile * 16`, so the final image renders without any user-supplied CHR. `BackgroundData` carries `chr_bytes` and `chr_base_tile` so the linker has everything it needs at a glance. Inline `tiles:` / `attributes:` declarations leave them empty and behave exactly like before — that path doesn't auto-generate CHR because the user is implicitly opting into "I'll provide tiles myself" by typing the indices out by hand. The new `examples/auto_chr_background.ne` is a 256×240 grayscale gradient committed alongside its `auto_chr_bg.png` source; the emulator harness verifies the rendered output against a committed golden so a regression in the dedupe/encode/linker plumbing fails CI loudly. Existing example ROMs are byte- identical because their backgrounds either have no PNG source or already provided their own CHR. https://claude.ai/code/session_01KEczoNUX3WmcFLfq6iAQxB
2026-04-15 03:29:58 +00:00
// Auto-CHR background — first NEScript example to use the
// `@nametable("file.png")` shortcut without supplying any matching
// CHR data. Previously the resolver decoded the PNG into a tile
// index table but left CHR generation to the user; the new
// `png_to_nametable_with_chr` helper also generates the per-tile
// CHR bytes from the same brightness-bucketing code that
// `png_to_chr` uses for sprite imports, then the asset resolver
// allocates contiguous CHR-ROM tile indices starting after the
// last sprite tile and rewrites the nametable to point at them.
//
// `auto_chr_bg.png` is a 256×240 grayscale gradient rendered to
// roughly fifty distinct tiles — enough variety to exercise the
// dedupe + CHR generation path but well within the 256-tile cap.
//
// Build: cargo run -- build examples/auto_chr_background.ne
game "Auto CHR Background" {
mapper: NROM
}
// Grayscale palette with every background sub-palette set to the
// same three shades. The PNG-to-attribute helper buckets each
// 16×16 quadrant by average brightness and assigns sub-palette
// 0..3, so we need *every* bg sub-palette to carry the same
// dk_gray / lt_gray / white triple — otherwise quadrants that
// pick a non-zero palette would render as the universal colour.
palette Main {
universal: black
bg0: [dk_gray, lt_gray, white]
bg1: [dk_gray, lt_gray, white]
bg2: [dk_gray, lt_gray, white]
bg3: [dk_gray, lt_gray, white]
sp0: [black, black, black]
sp1: [black, black, black]
sp2: [black, black, black]
sp3: [black, black, black]
}
// `@nametable` is the shortcut form: no `tiles:` / `attributes:`
// body, and the resolver fills both — and now CHR data too — from
// the PNG itself.
background Stage @nametable("auto_chr_bg.png")
on frame {
wait_frame
}
start Main