Repository navigation
espp 1.4.2: espp::Audio (playback only), no DPI DMA2D, frame_buffers(), aligned TPM state I/O, menu save/load soak - #14
Merged
Merged
Conversation
The Phantom Menace and Metal Gear Solid save to a memory card in port 1: saves/tpm_card1.mcd and saves/mgs_card1.mcd, raw 128 KB card images as PC emulators use, made the first time the game looks. Unlike save states, which hold raw memory and load only into the build that wrote them, these survive firmware updates. - tpm-decomp fea7648..d51af21: libmcrd natively on the card image (tested on the desktop and the board: a save from one build loaded into another); recomp.py treats a jr to the function's own return address as a return (the save screen's bit packer returns through $a3) - psyz 3245d54: mcd, the card image and the BIOS's buXX: device - mgs_reversing 6d58e9f: the port's bu00: device and memcard.c on it (the game finds the card at boot) - Cart::get_memory_card_path names the image after the game's directory Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
The BSP now exposes the DPI panel's frame buffers, so the PPA's target no longer comes from its protected panel handle. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
The header and the game's memory regions went to FATFS at any address and file offset, so the SD driver bounced every write through internal DMA memory. With espp 1.4.0 (deeper I2S DMA rings, DMA2D for the panel) about 16 KB less of it is free, and a save from the pause menu failed outright (allocate_dma_buf: not enough mem). Through one 128-byte-aligned PSRAM block at block-multiple file offsets, as the disc's read-ahead does, nothing is bounced: saves 707-969 ms (1295 ms before), loads 330 ms (489 ms). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
TAB5_EMU_AUTOQUIT_STATES: a third of the way into each auto-started game the pause menu opens over it and Save is clicked, two thirds in Load, the same way taps do (Menu::click). The soak's saves go to saves-soak/ so the player's own are left alone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
There was a problem hiding this comment.
🟡 Changes recommended
Automatic quitting can occur before Load is exercised when a short deadline or slow save causes Save to overrun it, so quitting must wait for both state actions to complete when AUTOQUIT_STATES is enabled.
1 open issue
What changed in this PR
Updates the Tab5 integration for espp 1.4.0, improves TPM save-state I/O under limited DMA memory, and adds automated menu save/load exercises.
Changes:
- Uses the public BSP frame-buffer accessor and raises the minimum dependency version.
- Routes TPM state reads and writes through an aligned 64 KB buffer.
- Adds save/load actions to the launch/quit soak, with saves isolated in
saves-soak/.
| File | Description |
|---|---|
| main/main.cpp | Schedules menu save/load actions during automated runs. |
| main/Kconfig.projbuild | Adds the save/load soak option. |
| main/cart.hpp | Drives automated menu actions and isolates soak saves. |
| components/tpm/src/tpm_engine.cpp | Adds aligned, buffered state-file I/O. |
| components/tab5-emu/src/tab5-emu.cpp | Replaces protected BSP access with public frame-buffer APIs. |
| components/tab5-emu/idf_component.yml | Requires espp m5stack-tab5 1.4.0 or later. |
| components/menu/src/menu.cpp | Implements programmatic menu-button clicks. |
| components/menu/include/menu.hpp | Declares the menu click API. |
Review effort: Balanced
| state_step++; | ||
| } | ||
| #endif | ||
| if (std::chrono::steady_clock::now() >= quit_at) { |
…I DMA2D initialize_audio() takes the BSP's AudioConfig (espp::Audio::AppConfig) with recording off: no RX DMA ring or microphone task in internal RAM. initialize_lcd() turns the panel's DMA2D copies off: every LVGL flush is rotated, so it goes through the PPA and DMA2D never ran (~3 KB of internal DMA-capable RAM). 1.4.2 also brings the logger without a mutex per tag. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
ESP-IDF Size Report for 'Tab5 Emu'
FLASH uses app .bin size or json2 flash sum. RAM sums DRAM+IRAM via idf_size. Percentages shown when totals are available. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What
m5stack-tab5 >= 1.4.2; every espp component resolves to 1.4.2).frame_buffers()accessor (since 1.4.0) instead of the BSP's protected panel handle.espp::Audio:initialize_audio()starts fromdefault_audio_config()at 48 kHz with recording off, so there's no microphone DMA ring or task in internal RAM.initialize_lcd({.dma2d_enabled = false}): every LVGL flush here is rotated, so it goes through the PPA and DMA2D never ran.sdmmc_cmd: allocate_dma_buf: not enough mem). FATFS got the header and memory regions at arbitrary addresses and offsets, so the SD driver bounced every write through internal DMA memory, and 1.4.0 left little of it free. Saves now take 0.7–1.0 s (was 1.3 s) and loads 0.33 s (was 0.49 s).TAB5_EMU_AUTOQUIT_STATES. During the launch/quit soak, it opens the pause menu over each game and clicks Save a third of the way in and Load two thirds in, the same way a tap does (Menu::click). The soak's saves go tosaves-soak/, so real saves aren't touched.Internal RAM on the board (boot log)
1.4.0 had cost about 16.5 KB of DMA-capable RAM: the I2S rings doubled, including the unused RX one, and DMA2D was turned on. With recording and DMA2D off, 1.4.2 more than wins that back.
Tested on the Tab5
🤖 Generated with Claude Code
https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY