Files
ppsspp/Tools/update-dispatcher.py
T
Henrik RydgårdandClaude Opus 5.5 e0f2060cd5 Tools: Find ARM64 builds in update-dispatcher.py, fix headless_bench.py options
update-dispatcher.py only knew x64 paths, so on Windows-on-ARM it regenerated from a stale x64
build. headless_bench.py handed the options after -- to argparse's REMAINDER, which newer
Pythons treat as more binaries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 10:33:30 +02:00

96 lines
3.3 KiB
Python

#!/usr/bin/env python
# Regenerates Core/MIPS/InterpreterDispatch.cpp (the ExecInstruction switch-tree
# interpreter dispatcher) from the tables in Core/MIPS/MIPSTables.cpp.
#
# Run this after changing anything that affects those tables - new instructions,
# retimed cycle counts, encoding changes, etc. The generated file is checked into
# git like any other source file, not built on the fly, so it needs to be
# regenerated and the diff committed whenever the tables change.
#
# This script only needs an already-built PPSSPPHeadless binary (see
# docs/pspautotests.md for how to build one); it doesn't build anything itself.
# After it finishes, just build normally - Core/MIPS/InterpreterDispatch.cpp is
# already wired into every build system, so no further steps are needed.
import os
import platform
import subprocess
import sys
# Same search list test.py uses to find a headless build. The machine's own architecture comes first:
# an x64 build runs on Windows-on-ARM too, and may be a stale one.
CANDIDATES = ([
"Windows/ARM64/Debug/PPSSPPHeadless.exe",
"Windows/ARM64/Release/PPSSPPHeadless.exe",
] if platform.machine().lower() in ("arm64", "aarch64") else []) + [
"Windows/x64/Debug/PPSSPPHeadless.exe",
"Windows/x64/Release/PPSSPPHeadless.exe",
"Windows/Debug/PPSSPPHeadless.exe",
"Windows/Release/PPSSPPHeadless.exe",
"build/Debug/PPSSPPHeadless",
"build/Release/PPSSPPHeadless",
"build/RelWithDebInfo/PPSSPPHeadless",
"build/MinSizeRel/PPSSPPHeadless",
"build/PPSSPPHeadless",
"./PPSSPPHeadless",
"./PPSSPPHeadless.exe",
]
OUT_PATH = os.path.join("Core", "MIPS", "InterpreterDispatch.cpp")
def find_headless():
for candidate in CANDIDATES:
if os.path.isfile(candidate):
return candidate
return None
def main():
repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
os.chdir(repo_root)
headless = find_headless()
if headless is None:
sys.stderr.write("error: couldn't find a built PPSSPPHeadless binary. Checked:\n")
for candidate in CANDIDATES:
sys.stderr.write(" %s\n" % candidate)
sys.stderr.write("Build PPSSPPHeadless first (see docs/pspautotests.md), then re-run this script.\n")
return 1
print("Using %s" % headless)
# subprocess/CreateProcess on Windows can fail to resolve a relative,
# forward-slash path as the executable itself - use an absolute, normalized path.
headless_abs = os.path.normpath(os.path.abspath(headless))
try:
result = subprocess.run([headless_abs, "--generate-interpreter-dispatch"], capture_output=True)
except OSError as e:
sys.stderr.write("error: couldn't run %s: %s\n" % (headless, e))
return 1
if result.returncode != 0:
sys.stderr.buffer.write(result.stderr)
sys.stderr.write("error: %s exited with code %d\n" % (headless, result.returncode))
return 1
generated = result.stdout
# Sanity check before clobbering the tracked file - a stale/broken binary should
# fail loudly here rather than silently truncating InterpreterDispatch.cpp.
if b"int ExecInstruction(MIPSState *mips, MIPSOpcode op)" not in generated:
sys.stderr.write("error: generated output doesn't look right (missing ExecInstruction) - not overwriting %s\n" % OUT_PATH)
return 1
with open(OUT_PATH, "wb") as f:
f.write(generated)
print("Regenerated %s" % OUT_PATH)
return 0
if __name__ == "__main__":
sys.exit(main())