Skip to content

[handoff] PathE savestate MCU current state - #1

Draft
zeppnyc wants to merge 2 commits into
mainfrom
handoff/pathe-current-mcu-20260506
Draft

[handoff] PathE savestate MCU current state#1
zeppnyc wants to merge 2 commits into
mainfrom
handoff/pathe-current-mcu-20260506

Conversation

@zeppnyc

@zeppnyc zeppnyc commented May 6, 2026

Copy link
Copy Markdown
Owner

Draft handoff PR for cloud-agent discovery. Do not merge as a product change without review.

This branch captures the current PathE savestate MCU source snapshot from memini, including previously untracked smoke/load files needed to analyze the FPGA PathE load issue from GitHub only.

Important file:

  • main/fusion_savestate_smoke48a.c

Related FPGA issue:

Related FPGA handoff PR:

t800 and others added 2 commits April 28, 2026 21:34
Adds the MCU-side state-port protocol skeleton, on-flash header layout,
and a host self-test against a mock transport. Wires the three new
firmware translation units into main/CMakeLists.txt; existing fpga_tx.c
and fpga_rx.c are untouched.

Protocol (per project-wiki/50_decisions/fusion-savestate-mcu-architecture.md):
  - V2 packet build/parse for STATE_CTL (0x20), STATE_DATA (0x21);
    STATE_EVENT (0x22) reserved as a placeholder.
  - STATE_CTL opcodes: BeginSave/Load, EndSession, Seek, ReadNext,
    ReadStreamBegin, WriteStreamBegin, WriteCommit; FPGA-side
    AckAccepted/Busy/Error/AckDone for tests.
  - STATE_DATA payload = seq_lo, seq_hi, data[0..8]; per-stream seq16
    starts at 0.

State machine (fpga_state_port):
  - Session begin/end, stream begin (read or write), push write data,
    abort, watchdog tick.
  - Wrong seq / wrong len / ERROR / unexpected packet aborts, sends
    ERROR to FPGA, bumps stream_generation, drops late ACK_DONE and
    late STATE_DATA from the failed generation.
  - Default watchdogs: 30s at 115200, 5s at 1,048,576 baud.

Storage (savestate_storage):
  - 56-byte FusionStateHeader with 'FUSS' magic, format_version, game
    id (CRC-32/ISO-HDLC), 8-byte git-short-hash version slots, payload
    crc32, commit_generation, commit_state.
  - Two-phase commit lifecycle on an in-RAM mock backend:
    Begin -> Append* -> Stage(Writing) -> Verify -> Valid.
    FindNewestValidSlot ignores Writing/Invalid slots so a power loss
    between Stage and Commit cannot promote a half-written slot.
  - FusionStorage_InitFromPartition is the seam for the deferred
    Phase 1.5/5 ESP-IDF custom-partition wiring; it currently reports
    NotImplemented so callers fall back to the mock without
    conditional compilation.

Game ID:
  - FusionSavestate_ComputeGameIdV1 = CRC-32/ISO-HDLC over ROM header
    bytes 0x0100-0x014F. Verified against the standard "123456789" ->
    0xCBF43926 test vector. game_id_algorithm = 1 stored in the header.

Host self-test (tests/host/):
  - make / make run -> 145 passed, 0 failed. Covers encode/decode
    roundtrip, seq mismatch abort, ERROR response abort, late-ACK
    ignore, watchdog abort, ACK_DONE stream completion, game_id_v1
    determinism, header layout (sizeof(FusionStateHeader_t) == 56,
    sizeof(FusionRegionDirectory_t) == 16), and two-phase commit
    lifecycle including a power-loss simulation.

ESP-IDF firmware build verified on memini via:
  rsync -av --delete --exclude=build/ --exclude=tests/host/build/
    fusion-savestate-mcu/ zepp@memini:/home/zepp/fusion-savestate-mcu/
  ssh zepp@memini 'cd /home/zepp/fusion-savestate-mcu &&
    . /home/zepp/esp-idf/export.sh && idf.py build'
Result: Project build complete (exit 0). mcu_fw.bin is 732240 bytes
(0xb2c50); app partition has 30% headroom.

No FPGA changes, no Gowin run, no archive worktree used as a source.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
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.

1 participant