Skip to content

Share the Genesis and PICO-8 cores with esp-box-emu; add PICO-8 - #17

Merged
finger563 merged 2 commits into
mainfrom
feat/shared-cores
Nov 11, 2026
Merged

finger563 merged 2 commits into
mainfrom
feat/shared-cores

Conversation

@finger563

Copy link
Copy Markdown
Contributor

Summary

  • Genesis: now the esp-cpp/gwenesis submodule (branch esp32), shared with esp-box-emu. The P4's all-PSRAM buffer placement is the GENESIS_HOT_IN_PSRAM gate, so the Tab5 now picks up box-emu's newer glue:
    • frame-render skipping when the display can't take a frame, and (bounded) while behind real time;
    • Sonic 3's Z80 V-int handling;
    • the two line-interrupt fixes: Sonic 2 Chemical Plant drawn all underwater, and Sonic 3 water only on every other frame.
  • Tab5Emu additions that the shared glue needs:
    • frame_slot_free(), plus the frames_dropped() / frames_blitted() / blit_cycles() counters, for the Genesis skip rule and its perf line;
    • gamepad_state_latched() for PICO-8, so a press shorter than a frame isn't lost.
  • PICO-8 (new):
    • the esp-cpp/femto8 submodule (branch esp32) as the pico8 component;
    • a Pico8Cart, and .p8 / .p8.png detection in rom_info;
    • audio goes through Tab5Emu::play_audio (PICO8_AUDIO_VIA_EMU), so femto8's 44.1 kHz output is resampled to the 48 kHz DAC;
    • built with -msmall-data-limit=0, so the statics that the linker.lf reset covers stay in .bss/.data.
  • CI: checks out the two new submodules.

Test plan

  • Tab5: Genesis video and sound as good as before. Sonic 2 Chemical Plant and Sonic 3 water are correct.
  • Tab5: a PICO-8 cart. Needs a cart in /sdcard/pico8/ and a metadata.csv line; not tried yet.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY

The Genesis core and glue are now the esp-cpp/gwenesis submodule (branch
esp32), shared with esp-box-emu. The P4's all-PSRAM placement is the
GENESIS_HOT_IN_PSRAM gate, so the Tab5 also gets box-emu's newer glue:
- skip rendering frames the display cannot take, and (bounded) while behind
- Sonic 3's Z80 V-int handling
- two line-interrupt fixes (Sonic 2 Chemical Plant drawn all underwater;
  Sonic 3 water only on every other frame)

That needs three small Tab5Emu additions the glue uses: frame_slot_free()
and frames_dropped()/frames_blitted()/blit_cycles() for the skip rule and
perf line, and gamepad_state_latched() so a tap shorter than a skipped
frame is not lost.

PICO-8 is new: the esp-cpp/femto8 submodule (branch esp32) as the pico8
component, a Pico8Cart, and .p8 / .p8.png in rom_info. Audio goes through
Tab5Emu::play_audio (PICO8_AUDIO_VIA_EMU) so the 44.1 kHz output is
resampled to the 48 kHz DAC.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
Copilot AI balanced review requested due to automatic review settings November 11, 2026 00:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The input latch is not drained before the PICO-8 cart task starts, so its first poll can replay already-released touch or gamepad presses from the launcher or previous cores.

1 open issue
What changed in this PR

This PR shares the Genesis and PICO-8 cores with esp-box-emu and integrates PICO-8 into Tab5Emu’s cartridge system.

Changes:

  • Replace vendored Genesis sources and local glue with the shared gwenesis submodule.
  • Add PICO-8 cartridge lifecycle support, ROM detection, and build/linker configuration.
  • Extend Tab5Emu with latched input and video queue statistics, and update CI submodule checkout.
File Description
main/​pico8_cart.hpp Add PICO-8 lifecycle, menu, save, and video integration.
main/​carts.hpp Register PICO-8 cartridge creation.
components/​tab5-emu/​src/​tab5-emu.cpp Implement input latching, frame availability, and video counters.
components/​tab5-emu/​include/​tab5-emu.hpp Expose the new input and video APIs.
components/​rom_info/​src/​rom_info.cpp Recognize .p8 and .p8.png carts.
components/​rom_info/​include/​rom_info.hpp Add the PICO-8 platform identifier and documentation.
components/​pico8/​linker.lf Define static placement and reset boundaries.
components/​pico8/​CMakeLists.txt Build femto8 and its shared platform glue.
components/​genesis/​src/​z80_shared_memory.cpp Remove local Z80 allocation code in favor of shared glue.
components/​genesis/​src/​genesis_shared_memory.cpp Remove local Genesis allocation code in favor of shared glue.
components/​genesis/​include/​z80_shared_memory.hpp Remove the local Z80 memory interface.
components/​genesis/​include/​genesis.hpp Replace the local core interface with the submodule’s version.
components/​genesis/​include/​genesis_shared_memory.hpp Remove the local Genesis memory interface.
components/​genesis/​include/​genesis_dualcore.h Replace local dual-core declarations with the shared version.
components/​genesis/​gwenesis/​src/​vdp/​gwenesis_vdp.h Remove vendored VDP declarations for the submodule migration.
components/​genesis/​gwenesis/​src/​sound/​z80inst.h Remove vendored Z80 sound interface declarations.
components/​genesis/​gwenesis/​src/​sound/​z80inst.c Remove vendored Z80 sound integration.
components/​genesis/​gwenesis/​src/​sound/​ym2612.h Remove vendored FM sound declarations.
components/​genesis/​gwenesis/​src/​sound/​gwenesis_sn76489.h Remove vendored PSG declarations.
components/​genesis/​gwenesis/​src/​sound/​gwenesis_sn76489.c Remove vendored PSG implementation.
components/​genesis/​gwenesis/​src/​savestate/​gwenesis_savestate.h Remove vendored save-state declarations.
components/​genesis/​gwenesis/​src/​savestate/​gwenesis_savestate.c Remove vendored save-state coordination.
components/​genesis/​gwenesis/​src/​io/​gwenesis_io.h Remove vendored controller I/O declarations.
components/​genesis/​gwenesis/​src/​io/​gwenesis_io.c Remove vendored controller I/O implementation.
components/​genesis/​gwenesis/​src/​cpus/​Z80/​Z80.h Remove vendored Z80 CPU declarations.
components/​genesis/​gwenesis/​src/​cpus/​Z80/​ConDebug.c Remove the vendored Z80 console debugger.
components/​genesis/​gwenesis/​src/​cpus/​Z80/​CodesXX.h Remove vendored Z80 indexed instructions.
components/​genesis/​gwenesis/​src/​cpus/​Z80/​CodesXCB.h Remove vendored Z80 indexed bit instructions.
components/​genesis/​gwenesis/​src/​cpus/​Z80/​CodesED.h Remove vendored Z80 extended instructions.
components/​genesis/​gwenesis/​src/​cpus/​Z80/​CodesCB.h Remove vendored Z80 bit instructions.
components/​genesis/​gwenesis/​src/​cpus/​Z80/​Codes.h Remove vendored Z80 base instructions.
components/​genesis/​gwenesis/​src/​cpus/​M68K/​readme.txt Remove vendored Musashi documentation.
components/​genesis/​gwenesis/​src/​cpus/​M68K/​macros.h Remove vendored M68K utility macros.
components/​genesis/​gwenesis/​src/​cpus/​M68K/​m68kcpu.c Remove the vendored M68K CPU implementation.
components/​genesis/​gwenesis/​src/​cpus/​M68K/​m68kconf.h Remove vendored M68K configuration.
components/​genesis/​gwenesis/​src/​cpus/​M68K/​m68k.h Remove vendored M68K declarations.
components/​genesis/​gwenesis/​src/​bus/​gwenesis_bus.h Remove vendored Genesis bus declarations.
components/​genesis/​gwenesis/​src/​bus/​gwenesis_bus.c Remove vendored Genesis memory-bus implementation.
components/​genesis/​gwenesis/​README.md Remove the old vendored-snapshot README.
components/​genesis/​gwenesis/​CMakeLists.txt Remove the vendored core’s build configuration.
components/​genesis/​CMakeLists.txt Use the submodule’s port sources and headers.
CMakeLists.txt Enable and include the PICO-8 component.
.gitmodules Register the gwenesis and femto8 submodules.
.github/​workflows/​build.yml Initialize both new submodules before CI builds.

Review effort: Balanced

Comment thread main/pico8_cart.hpp

void init() {
#if defined(ENABLE_PICO8)
init_pico8(get_rom_filename(), romdata_, rom_size_bytes_);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in esp-cpp/femto8@3c5fc45 (pinned by 3c8ac29). The fix went into the shared init_pico8() rather than Pico8Cart, so esp-box-emu gets it too. It now drains gamepad_state_latched() and sets the input gate before starting the cart task, the same way resume already did.

@github-actions

Copy link
Copy Markdown

ESP-IDF Size Report for 'Tab5 Emu'

Metric Base PR Delta
FLASH 0 bytes (0.00%) 0 bytes (0.00%) 0 bytes (0.00%)
DRAM 267,410 bytes (60.60%) 268,638 bytes (60.87%) 🔺 +1,228 bytes (+0.27%)
IRAM 0 bytes 0 bytes 0 bytes
RAM (DRAM+IRAM) 267,410 bytes 268,638 bytes 🔺 +1,228 bytes (+0.27%)

FLASH uses app .bin size or json2 flash sum. RAM sums DRAM+IRAM via idf_size. Percentages shown when totals are available.
DRAM/IRAM usage does not include memory used by the heap allocator at runtime.
This report was generated by esp-idf-size-delta.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
@finger563
finger563 merged commit 669bc9e into main Nov 11, 2026
1 check passed
@finger563
finger563 deleted the feat/shared-cores branch November 11, 2026 02:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants