mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 23:10:33 +02:00
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>
96 lines
3.3 KiB
Python
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())
|