aboutsummaryrefslogtreecommitdiffstats
path: root/tools (unfollow)
Commit message (Collapse)AuthorFilesLines
13 hourswasm: run the emulator in a browsergbc dev1-0/+137
`make wasm` builds the core to WebAssembly (~44KB stripped) and web/ is a front-end for it: drag-drop a ROM, pixelated canvas at any zoom, keyboard mapped like the native build, battery saves in localStorage. Built with zig cc, which carries its own wasm backend, linker and wasi-libc - so no emscripten dependency, just zig on PATH. Only the portable core goes in; render/kitty/control/main are terminal- and POSIX-bound and stay out. src/wasm.c is the browser's whole host layer: no terminal, no sockets, no files, and no frame pacing (the page's requestAnimationFrame owns that). The machine is static, the RGB888 -> RGBA conversion for putImageData happens in wasm, and nothing allocates per frame. The entire host interface is four WASI fd_* imports, pulled in by the cart info banner's fprintf; the page shims them to console.log in ~20 lines. Cartridge RAM *is* the save file here, so it's exported for the page to persist per cart title (every 5s and on unload). Because both builds now advance on the same frame boundary, the port is checked byte-for-byte against the native binary rather than by eyeballing a canvas - tools/wasm_check.mjs runs N frames in node and diffs the framebuffer against a --shot PPM: cgb-acid2 @60, dmg-acid2 @60, cpu_instrs @600, mem_timing-2 @700, pky.gbc @400 with an imported .sav, cgb-acid2 @120 through the full CGB BIOS boot animation -> all pixel-identical Also smoke-tested in headless chromium over CDP: core instantiates, ROM loads through the file input, canvas animates (7 distinct frames over 5.6s), keyboard reaches the joypad, 60fps, and a 32KB save lands in localStorage. No audio: the APU is still stubbed.
14 hourskitty: truecolor graphics output with a layered HUDgbc dev1-0/+174
Sixel is a 1987 printer format wearing a terminal costume: 256 colors per image, no alpha, no compositing, one flat picture. --kitty [scale] takes the other road on kitty/ghostty/WezTerm/Konsole: - the framebuffer ships as raw RGB888, so no per-frame palette build and no coarser quantization when a CGB game blows past 256 colors - the HUD (title, render rate, frameskip, turbo, live button readout) is a *separate* alpha-blended image on z-index 1, composited over the game by the terminal instead of being burned into the picture; 'h' toggles it, --no-hud starts without it - consecutive identical images are dropped, so a pause menu or text box stops the traffic dead - pixels go over at 1x and the terminal scales them into a cell box, so --kitty 6 costs the same bytes as --kitty 1 (padded to whole cells first, so the zoom stays exact) Two transfers: shm hands over the name of a POSIX shared-memory object (~60 bytes/frame) when we can tell the terminal is local, b64 inlines the bytes for ssh and tmux (which might be attached from another machine). --kitty-shm / --kitty-b64 force either. tmux gets DCS passthrough wrapping. --chrome and --palette work here just like in sixel mode. Nothing about a graphics stream is human-readable, so tools/kitty_decode.py reassembles a capture back into images - chunked payloads, tmux wrapping and all - and can assert a frame is pixel-identical to a --shot: tools/kitty_decode.py cap.bin -o frames --check shot.ppm -> OK: image 1 matches shot.ppm exactly (160x144)
2026-07-18tools: mk_sl0pboy_bios.py - fork the CGB boot ROM's GAME BOY -> SL0PBOYgbc dev1-0/+85
The stock CGB boot ROM draws its GAME BOY wordmark from a 192-byte blob at $0607 (routine $03F0 copies it to VRAM tiles $08-$37: 48 tiles, 4 bytes each, every byte a row doubled vertically). This re-encodes that blob with a bold-italic SL0PBOY bitmap of the same size and patches it in place over a local bios/gbc_bios.bin -> bios/sl0pboy_bios.bin. No code moves; the cart's own Nintendo logo ($104) is untouched so the integrity check still passes and the boot hands off normally. bios/ stays gitignored (copyrighted boot ROM); run this to produce the fork locally. Verified end to end: logo drop + color + chime -> gbos.
2026-07-17rebrand: gbc -> sl0pboy (binary, README, tooling)gbc dev4-4/+4
2026-07-15serial: headless mode tying serial port to stdio for OS debugginggbc dev2-0/+0
- --headless: no rendering/TUI; serial TX -> stdout, RX <- stdin (nonblocking) - generalize serial: serial_out_fd/serial_in_fd on the GB; internal-clock transfer now shifts in a real RX byte (from stdin) instead of always 0xFF - paced to native speed by default, --uncapped for turbo; pipes/scripts cleanly - README: document headless serial console
2026-07-15control: video frame capture + deterministic input-movie replaygbc dev2-0/+187
Two socket features for building reproducible showcase clips: - record start <path> [everyN] / record stop: append the RGB888 framebuffer of each produced frame to a flat 'GBCV' capture file (downsample with everyN). tools/gbgif.py turns it into a GIF (or PNG frames). Capture is decoupled from wall-clock/turbo/frameskip, so timing is always correct. - input play <path> [reset] / input stop: drive the joypad from a synthesized TAS-style movie (text: '<frames> [buttons...]' per line), frame-locked so replay is deterministic. 'reset' does an exact power-on (preserve cart ROM+SRAM, zero all other state) so a movie replays byte-identically -- verified by hashing two runs. tools/gbmovie.py is a Python builder for movies.
2026-07-15tools: stitch_overworld.py - DFS EXPLORE's connection graph into one ↵gbc dev1-0/+111
overworld image
2026-07-15gbhud: live joypad display (cute Game Boy layout, buttons light up)gbc dev1-0/+20
New INPUT section reads hJoyHeld (0xFFB4) and draws a d-pad cross + A/B circles + SEL/START pills; held buttons glow bright green, idle ones dim grey.
2026-07-15fix(control): ignore SIGPIPE so a vanishing client can't kill the emulatorgbc dev2-14/+33
A client that connects and closes before reading (e.g. the HUD's liveness probe) made the greeting write() raise SIGPIPE, terminating the whole emulator - this was behind much of the 'it keeps dying' this session. Also: gbhud now re-resolves the live instance from the registry on every reconnect (skipping stale sockets by test-connecting), so the HUD follows respawns, and its box rendering is ANSI-width-correct.
2026-07-15tools: live debug HUD (gbhud.py) + 'gbctl hud'gbc dev1-0/+185
Reads WRAM over the control socket, resolves addresses from pokeyellow.sym, and pretty-prints game state (location, player pos/facing, movement+collision debug, player name/money/badges, party nicknames/levels/HP bars) refreshing ~5Hz. 'gbctl hud' spawns it in a tmux split bound to the live instance.
2026-07-15apu: register-level emulation of 0xFF10-0xFF3F (fixes music fades)gbc dev2-0/+104
The APU was a black hole: reads returned 0xFF, writes were dropped. That hangs any game that fades music out by decrementing the NR50/rAUDVOL volume register until it reads 0 (Pokemon's StopMusic spin-wait) - the write never stuck, the read never hit 0, infinite loop. Store the 48 sound registers and return them with the standard hardware read-back OR-masks (NR50 mask 0x00 = exact readback). No synthesis, just correct register behavior.