mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
7dc8fdde9a
savestate save/load with slot >= SAVESTATE_SLOTS (12) was refused with the generic message that blames LLE runs, which sent a test chasing the wrong cause. It now replies "slot N out of range (0..11)". Guarded in test_savestate_status_protocol.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
56 lines
3.4 KiB
Python
56 lines
3.4 KiB
Python
"""Guard the deterministic savestate completion receipt used by load gates."""
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
HEADER = (ROOT / "include/savestate.h").read_text(encoding="utf-8")
|
|
STATE = (ROOT / "src/savestate.c").read_text(encoding="utf-8")
|
|
SERVER = (ROOT / "src/debug_server.c").read_text(encoding="utf-8")
|
|
INTERRUPTS_H = (ROOT / "include/interrupts.h").read_text(encoding="utf-8")
|
|
INTERRUPTS = (ROOT / "src/interrupts.c").read_text(encoding="utf-8")
|
|
REWIND = (ROOT / "src/psx_rewind.c").read_text(encoding="utf-8")
|
|
DIRTY = (ROOT / "src/dirty_ram_interp.c").read_text(encoding="utf-8")
|
|
BOOT_STATE_H = (ROOT / "include/boot_state.h").read_text(encoding="utf-8")
|
|
DMA = (ROOT / "src/dma.c").read_text(encoding="utf-8")
|
|
BOOT_STATE = (ROOT / "src/boot_state.c").read_text(encoding="utf-8")
|
|
|
|
# The per-word DMA2 cursor and XA DATA_END pending bit grow the snapshot wire.
|
|
# Keep the v7 read minimum: v8 adds enhancement memory, and all current v9
|
|
# writers preserve the BIOS-to-game handoff latch. Older incompatible files
|
|
# must be rejected before any live state is applied.
|
|
assert "#define DMA_GPU_LL_WIRE (4u + (10u * 4u))" in DMA
|
|
assert "#define BOOT_STATE_VERSION 9u" in BOOT_STATE_H
|
|
assert "h.version = BOOT_STATE_VERSION;" in BOOT_STATE
|
|
assert "h.version >= 9u && !(seen & (1u << BS_SEC_GAME_START))" in BOOT_STATE
|
|
assert "#define BOOT_STATE_VERSION_MIN_READ 7u" in BOOT_STATE_H
|
|
assert "Reject\n * them at the header before any section changes the live machine." in BOOT_STATE_H
|
|
|
|
assert "void savestate_status_json(char* buf, size_t cap);" in HEADER
|
|
assert '\\"generation\\"' in STATE and '\\"pending\\"' in STATE
|
|
assert "s_status_generation++" in STATE
|
|
assert '"savestate_status"' in SERVER
|
|
assert "savestate_status_json(status, sizeof status)" in SERVER
|
|
assert "int psx_irq_resume_context_snapshot_safe(void);" in INTERRUPTS_H
|
|
assert "int psx_irq_resume_context_snapshot_safe_at(uint32_t resume_pc);" in INTERRUPTS_H
|
|
assert "uint32_t psx_irq_resume_context_snapshot_pc(void);" in INTERRUPTS_H
|
|
assert "psx_irq_resume_context_snapshot_safe(void)" in INTERRUPTS
|
|
assert "psx_irq_resume_context_snapshot_safe_at(uint32_t resume_pc)" in INTERRUPTS
|
|
assert "psx_irq_resume_context_snapshot_pc(void)" in INTERRUPTS
|
|
assert "g_cosim_dirty_pump_site == 0" in INTERRUPTS
|
|
assert INTERRUPTS.index('if (psx_mod_function_entry_active()) return 0;') < INTERRUPTS.index('if (g_cosim_dirty_pump_site == 0)')
|
|
assert 'if (psx_mod_function_entry_active()) return;' in STATE
|
|
assert "case 1: /* transfer surface: target PC is materialized in CPUState */" in INTERRUPTS
|
|
assert "cands[n++] = psx_irq_resume_context_snapshot_pc();" in STATE
|
|
assert "cands[n++] = psx_irq_resume_context_snapshot_pc();" in REWIND
|
|
assert "int pc_ok = savestate_resume_pc_ok(pc);" in STATE
|
|
assert "(resume_pc == 0u && !pc_matches_cpu) || !snapshot_safe || !pc_ok" in STATE
|
|
assert "!psx_irq_resume_context_snapshot_safe_at(pc) || !resume_pc_ok(pc)" in REWIND
|
|
assert "psx_check_interrupts_at(cpu, pc)" in DIRTY
|
|
print("savestate status protocol guard passed")
|
|
|
|
# The debug server names an out-of-range slot instead of the generic refusal.
|
|
_handler = SERVER[SERVER.index("static void handle_savestate(int id"):]
|
|
_handler = _handler[:_handler.index("\n}\n")]
|
|
assert "slot >= SAVESTATE_SLOTS" in _handler
|
|
assert _handler.index("slot >= SAVESTATE_SLOTS") < _handler.index("savestate_request_save(slot)")
|
|
assert "out of range (0..%d)" in _handler
|