From f1a2a64e837b359a1f9b8d1be69aeb2c8fb0e02b Mon Sep 17 00:00:00 2001 From: chrg6 Date: Fri, 13 Nov 2026 15:20:28 -0500 Subject: [PATCH] Refuse to package a shader translator that was not built from the checkout's own sources: make_launcher prepares the translator's sources in a temporary folder, hashes them as tools/build_xlate.py does, and stops when the --xlate folder's nx2navi_xlate.id differs. 0.10.0 and 0.10.1 shipped the 0.9.2 translator, whose translations still clamp texture pool handles to slot 32767, so the ground could go see-through (issues #569 and #824). Co-Authored-By: Claude Opus 5.5 --- tools/make_launcher.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tools/make_launcher.py b/tools/make_launcher.py index 77b5853b..2ed51a43 100644 --- a/tools/make_launcher.py +++ b/tools/make_launcher.py @@ -188,6 +188,35 @@ def build_python(py): # ---------------------------------------------------------------- app// +def xlate_source_identity(): + """The identity tools/build_xlate.py writes for a translator built from this checkout: the vendor tree copied and + patched in a folder of its own (build_xlate.prepare_sources) and hashed as the build hashes it (build_xlate.identity). + Nothing is compiled; it takes a few seconds.""" + import tempfile + import build_xlate + old = build_xlate.BUILD + with tempfile.TemporaryDirectory(prefix='xlate-id-') as d: + build_xlate.BUILD = Path(d) / 'xlate' + try: + build_xlate.prepare_sources() + return build_xlate.identity() + finally: + build_xlate.BUILD = old + + +def check_xlate(xlate): + """A release carries the translator of its own sources. 0.10.0 and 0.10.1 shipped the 0.9.2 translator (identity + 4d051299) after tools/xlate/Program.cs had raised the texture pool to 40960 slots, so their translations still + clamped every pool handle to slot 32767 and the ground went see-through after some area loads (issues #569 and + #824). A translator whose nx2navi_xlate.id differs from this checkout's sources stops the build.""" + have = (xlate / 'nx2navi_xlate.id').read_text(encoding='ascii').strip() + want = xlate_source_identity() + if have != want: + sys.exit(f'{xlate}: its translator was built from other sources (identity {have[:16]}) than this checkout\'s ' + f'({want[:16]}): build it again with tools/build_xlate.py --out {xlate}') + print(f'translator identity {have[:16]}: built from this checkout\'s sources') + + def build_app(app, ver, xlate, feed_repo, lock, ffx=None, dlss=None, art=None, dlssg=None, pipelines=None, ffx4=None, pgo_profile=None): # The runtime's own shaders are source in the repository and SPIR-V headers in a release: a player's PC compiles @@ -207,6 +236,8 @@ def build_app(app, ver, xlate, feed_repo, lock, ffx=None, dlss=None, art=None, d for n in ('nx2navi_xlate.exe', 'nx2navi_xlate.id'): if not (xlate / n).is_file(): sys.exit(f'{xlate / n} is missing: build the shader translator first (tools/build_xlate.py)') + check_xlate(xlate) + for n in ('nx2navi_xlate.exe', 'nx2navi_xlate.id'): shutil.copy2(xlate / n, app / 'bin' / n) if ffx: # FSR 3.1 loads it from beside the game (runtime/vk_ffx.cpp); make_game.py copies it there shutil.copy2(ffx, app / 'bin' / 'amd_fidelityfx_vk.dll')