A Game Boy Color emulator for the TUI
- TypeScript 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
MBC2 now decodes A8 across 0000-3FFF for RAM enable vs ROM bank, with 512 x 4-bit RAM. ROM+RAM carts (0x08/0x09) expose RAM from boot. DMG locks wave RAM while NR30 is on; CGB still allows access. Co-authored-by: Cursor <[email protected]> |
||
| .commandcode | ||
| bin | ||
| config | ||
| src | ||
| test | ||
| .env.example | ||
| .gitignore | ||
| mudah.json | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
tameuoyiolor
A Game Boy / Game Boy Color emulator that draws in the terminal. The name is a joke on TUI.
Built with @mudah-cli/mudah. Upscale shaders run through @mudah-cli/vgpu.
Run
npm install
node bin/tameuoyiolor.js info path/to/rom.gb
node bin/tameuoyiolor.js run path/to/rom.gb
node bin/tameuoyiolor.js test path/to/blargg-rom.gb
No ROM is bundled. Point the commands at any .gb or .gbc file.
--graphics=half is the default. It draws unicode half-blocks, which every truecolor terminal can show. Pass --graphics=kitty on Ghostty, Kitty, or WezTerm for pixel images.
node bin/tameuoyiolor.js run rom.gb --shader=lcd
node bin/tameuoyiolor.js run rom.gb --no-gpu # CPU filters only
node bin/tameuoyiolor.js run rom.gb --no-graphics --max-frames=60
Shaders: nearest (default), lcd, crt, scale2x. Cycle them with 1–4 or [ ]. LCD and CRT need a 2x or larger scale, so they look right on Kitty or a tall terminal.
Keys
| Key | Action |
|---|---|
| Arrows / WASD | D-pad |
| Z / X | A / B |
| Enter / Tab | Start / Select |
| Space | Pause |
. |
Step one frame while paused |
r |
Reset PC to 0x0100 |
1–4 / [ ] |
Shader |
| F5 | Capture a save state (F6 to load) |
| q / Esc | Quit |
How pixels reach the terminal
- The PPU writes a 160x144 pixel-record framebuffer.
resolveFrame(CPU) or the WGSL effect (GPU) maps records to RGBA.- The selected upscale shader (nearest / LCD grid / CRT / Scale2x) fills a larger buffer.
@mudah-cli/vgpuFramePresenterblits with Kitty graphics, or half-blocks when the terminal cannot place images.
Layout
src/
core/ emulator (no Mudah imports)
system.ts cpu/ mmu/ ppu/ cart/
render/ palette resolve, pack uniforms, GPU session, presenter
shaders/ WGSL source as strings
tui/ alt-screen play loop
commands/ run, test, info
providers/ boot wiring
System does not import @mudah-cli/mudah. The CLI is one consumer of the core.
What is still approximate
- PPU timing is per-line, not per-pixel. Mid-scanline raster tricks will not match hardware.
- APU: all four channels (pulse x2 with sweep, wave, noise), envelope decay, length counters (including the trigger
next-stepextra clock), the 512 Hz frame sequencer, and a coupling-capacitor high-pass, streamed through@mudah-cli/audio. - Audio backends: native (
audify) → spawn (pw-play/paplay/aplay) → silent.--no-audiodisables it. - Serial is a stub that returns
0xFFafter 4096 cycles (enough for Blargg signatures). - MBC3 RTC ticks at wall-clock 1 Hz, with latch
0x00 → 0x01on0x6000, halt and day-carry.
Test
npm test
npm run typecheck