Files
tactility/Documentation/gameboy-side-loaded-elf-support.md
T
2026-07-17 18:10:52 -04:00

2.5 KiB

GameBoy side-loaded ELF support notes

This branch records the firmware-side changes used to make the Tactility GameBoy emulator prototype load past the generic missing symbol failure on an ESP32-S3 ES3C28P board.

Problem

Side-loaded .app packages are relocated by the firmware ELF loader. The app can build successfully against the local SDK but still fail at runtime if the board firmware does not export every dynamic symbol used by the app.

For the GameBoy prototype, USB serial logs showed the emulator app was being found and started, but firmware without the needed LVGL exports showed missing-symbol failures for the canvas path.

Firmware changes in this branch

TactilityC/Source/tt_init.cpp now includes LVGL and exports the core LVGL canvas/display functions the GameBoy app needs:

  • lv_canvas_create
  • lv_canvas_set_buffer
  • lv_obj_invalidate
  • lv_display_get_horizontal_resolution
  • lv_display_get_vertical_resolution

These are exported through the existing main_symbols[] table with ESP_ELFSYM_EXPORT(...), making them visible to side-loaded ESP32-S3 app ELFs.

The branch also removes the AlwaysRun devicetree delete target from Firmware/CMakeLists.txt. During iterative firmware builds this target deleted Generated/devicetree.c while compile rules still depended on it, causing intermittent build failures. The devicetree generation rule now depends directly on the source YAML.

Verification performed

On the iMac build host:

cd ~/Projects/gitea/tactility
. ~/esp/esp-idf/export.sh
python3 device.py es3c28p
idf.py build
idf.py -p /dev/ttyACM0 flash

Build result:

Tactility.bin binary size 0x2b82b0 bytes
Smallest app partition is 0x400000 bytes
0x147d50 bytes (32%) free

Flash target:

ESP32-S3 ES3C28P
USB serial: /dev/ttyACM0
MAC: 14:c1:9f:d0:5c:5c

Runtime serial showed the GameBoy core loop running and reporting approximately 49-50 FPS:

GAMEBOY_FPS 50
GAMEBOY_FPS 49
GAMEBOY_FPS 49

Current caveat

The app loop/FPS is running, but the photographed device showed the GameBoy framebuffer was not visibly rendering yet. That remaining issue is in the app/UI canvas presentation path, not the firmware missing-symbol issue addressed by this branch.

The app-side prototype lives in the separate Gitea repo:

https://git.reynafamily.com/adolforeyna/tactility_apps.git

The app branch changes include restoring the LVGL canvas path, using /data/roms/gb/default.gb for the flashed data-image test, and printing GAMEBOY_FPS markers over USB serial.