Files
Adolfo 4ff787ff1d fix(GameBoy): I2 2bpp 5.6KB internal canvas fixes black screen after reboot (L:144 FPS:40)
Root cause: RGB565 46KB PSRAM required flush_cache handler which is NULL on ESP32S3 LVGL port -> dirty cache never reached PSRAM -> black. Frame writes L:144 prove core OK, FPS:40 proves timer OK, but PSRAM stale.

Fix: I2 indexed 160*144/4=5760 bytes internal RAM, no cache coherency, no WiFi/SD starvation (previous 46KB internal -> 7KB free -> sdmmc_read_sectors fail + wifi m f null). Uses lv_canvas_set_buffer I2 + lv_canvas_set_palette white/light/dark/black. Preserves Roms/GB capitalized probe + .gb file browser tap via tt_app_get_parameters bundle file.

Installs to 192.168.68.132, survives reboot.
2026-07-20 14:06:08 -04:00
..
2026-07-17 11:05:33 -04:00
2026-07-17 11:05:33 -04:00

GameBoy Emulator (Tactility Prototype, No Audio)

DMG Game Boy emulator for Tactility side-loaded apps, using Peanut-GB (MIT) as CPU/LCD core.

Status

  • Prototype v0.1.0-dev compiling draft focused on architecture, not yet production-hardened.
  • No audio (ENABLE_SOUND 0). Audio path stubbed for future MiniGB APU or i2s-driven implementation.
  • Supports MBC1/MBC2/MBC3/MBC5 via Peanut-GB.
  • ROM loader from SD card.
  • Save RAM persistence via .sav file next to ROM.
  • LVGL framebuffer: native 160x144 RGB565, integer-scaled if display large enough, centered on black background.
  • Input: on-screen D-pad + A/B + Start/Select + hardware keyboard arrows + LVGL key events (z= A, x= B).
  • Timer-driven at ~16ms (~60Hz) calling gb_run_frame().

ROM Location

  • Scanned directory: /sdcard/roms/gb/ for *.gb, *.gbc, *.bin (up to 64 entries).
  • Default quick-load: /sdcard/roms/gb/default.gb if present on app show, autoloads and jumps directly to emulation.
  • Place your legally dumped ROMs there; no ROMs are bundled.

Save RAM Path Design (stubbed + implemented minimal)

  • Save file = ROM path with extension replaced by .sav (e.g. /sdcard/roms/gb/tetris.gb -> /sdcard/roms/gb/tetris.sav).
  • Loaded on ROM load, saved on:
    • switching back to menu
    • app hide
    • error recovery path
  • Size queried via gb_get_save_size_s() / gb_get_save_size().
  • Future improvement: also mirror to app user-data dir (tt_app_get_user_data_child_path) if SD is read-only.

Memory Considerations (ESP32-S3 / PSRAM)

  • Large buffers allocated via heap_caps_malloc(..., MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT) with fallback to internal.
  • ROM buffer: up to 2MB (MBC5 max-ish) PSRAM preferred.
  • Cart RAM: variable, often 8KB-32KB, PSRAM.
  • Framebuffer: 1601442 = 46,080 bytes (~45KB) native RGB565. PSRAM preferred. No double buffering needed (line callback writes directly).
  • No huge heap allocations.
  • Emulator context struct gb_s is static inside AppCtx (~few KB).

Controls / Input Mapping

GB On-screen Keyboard Remarks
D-pad 4 arrow buttons LV_KEY_ arrows press/release tracked
A A button (right cluster) z
B B button (right cluster) x
Start Sta Enter / Space
Select Sel Esc / Backspace
Touch Quadrants not yet separated buttons cover

Future: touch quadrants mapping via pointToQuadrant like GameKitInput.

LCD Rendering

  • Peanut-GB calls lcd_draw_line(gb, pixels[160], line) per scanline.
  • pixels low 2 bits = shade 0-3.
  • Mapped to olive/gray palette RGB565 (editable).
  • Canvas buffer is the framebuffer itself.
  • Scale: if display resolution >= 320x432 => 2x, >=480x576 => 3x via LVGL transform scale (keeps native buffer).

No-Audio Limitation

  • ENABLE_SOUND 0 audio callbacks not compiled.
  • To add audio:
    1. Vendor MiniGB APU (minigb_apu) or similar.
    2. Implement audio_read / audio_write forwarding to APU.
    3. Define ENABLE_SOUND 1, include APU, create audio task similar to BookPlayer (i2s_controller).
    4. Feed APU samples in timer / separate task.

Build

Same as other Tactility apps:

. $IDF_PATH/export.sh
export TACTILITY_SDK_PATH=...
python3 tactility.py Apps/GameBoy build esp32s3 --local-sdk

Licensing

  • App code: GPLv3 (same as Tactility Apps).
  • Peanut-GB vendored lib: MIT (Copyright (c) 2018-2023 Mahyar Koshkouei). License preserved in Libraries/PeanutGB/peanut_gb.h.

Next Steps

  • Improve input: add touch quadrant → D-pad, repeat timers for held buttons.
  • Add pause/resume UI, FPS display.
  • Add palette selector (auto_assign_palette logic from peanut_sdl).
  • Add file picker dialog (tt_app_selectiondialog_start) improvement + recursive folder browsing.
  • Audio: vendoring minigb_apu and creating I2S task.
  • Save state beyond cart RAM (full emu snapshot).
  • RTC persistence for MBC3 RTC games.
  • Error dialog via tt_app_alertdialog_start.
  • Validate with Cppcheck / clang-format and ESP-IDF build.