Files
psxrecomp/runtime/tests/test_interp_mod_immediate_guards.py
T
Matt Stanley 13b7f81d29 Add guarded instruction variants fixed during offline mod activation
Keep selector zero stock and seal all choices until the next session restart. Refuse nonzero online activation, scope non-stock save states by frozen choices, and preserve original instruction guards when combined with effective-address adapters. Use overlay ABI34 on current master without the old menu dependency stack.
2026-10-19 16:37:32 -07:00

43 lines
2.2 KiB
Python

"""Pin the dirty-RAM interpreter's [[mod_immediate.sites]] call site: the word
substitution must follow the guarded instruction hook (which compares the
original word) and precede every use of `insn` for decode and execution."""
import pathlib
import re
SRC = pathlib.Path(__file__).resolve().parents[1] / "src" / "dirty_ram_interp.c"
def test_interp_substitutes_after_instruction_hook():
text = SRC.read_text(encoding="utf-8")
start = text.index("static int exec_one_fetched(CPUState *cpu, uint32_t pc, uint32_t insn,\n"
" uint32_t *next_pc_out) {")
body = text[start:text.index("static int exec_one_fetched_inner(CPUState *cpu, uint32_t pc, uint32_t insn,", start + 10)]
patch = "if (g_psx_mod_immediate_live) insn = psx_mod_immediate_patch(pc, insn);"
hook = "if (g_psx_mod_instruction_hooks) psx_mod_instruction(cpu, pc, insn);"
assert body.count(patch) == 1
assert body.index(hook) < body.index("const uint32_t original_instruction = insn;") < body.index(patch), "hook guards the original word"
# decode of the load/store fields happens after the substitution
assert body.index(patch) < body.index("const uint32_t ld_op = op_field(insn);")
def test_interp_includes_header():
text = SRC.read_text(encoding="utf-8")
assert re.search(r'#include "mod_immediate\.h"', text)
def test_session_seals_before_scope_and_guest():
text = (SRC.parent / "main.cpp").read_text(encoding="utf-8")
body = text[text.index("auto start_mod_session ="):]
assert body.index("psx_mod_immediate_begin_session(") < body.index("mod_runtime_activate_plugins();")
assert body.index("mod_runtime_activate_plugins();") < body.index("mod_runtime_savestate_scope(")
text = (SRC.parent / "mod_runtime.cpp").read_text(encoding="utf-8")
body = text[text.index('extern "C" void mod_runtime_activate_plugins(void)'):]
assert body.index("mod_reset_plugin_sessions();") < body.index("psx_mod_immediate_begin_activation();")
assert body.index("mod_invoke_activation_plugin(plugin.id);") < body.index("psx_mod_immediate_end_activation();")
if __name__ == "__main__":
test_interp_substitutes_after_instruction_hook()
test_interp_includes_header()
test_session_seals_before_scope_and_guest()