Add GameBoy emulator prototype

This commit is contained in:
Hermes Reyna Bot
2026-07-17 11:05:33 -04:00
parent e68909d64d
commit 07749d86a1
7 changed files with 4809 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
# 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: 160*144*2 = 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.