Repository navigation
fix(mods): merge a mod's resource size table with the button prompts' instead of switching the icons off - #2270
Conversation
… instead of switching the icons off A RomFS mod that grows game files ships its own resource size table (every Clawshot randomizer seed does). The loader served it and host/prompts.c then switched the prompts' font off, since the faces' fonts are larger than the game's entry: with a seed loaded, texts showed the Switch's button icons instead of the controller's. Now the table that wins (the last-sorted mod's, as for any file) is served with the prompts' entries merged into it: each file gets the larger of the two entries, entries of one side are kept, sorted as the game's. The merged table is written as raw zstd blocks to prompts/rsizetable.mod.zs. A table it cannot merge (not a RESTBL, other name fields, out of order, a zstd frame without its size) is served as it is and the icons stay the game's, as before. host/prompts.c reads the tables with zstd's decoder (third_party/zstd), now compiled into the runtime too. tests/test_mods_size_table.py: the merge on made-up tables, and mods.c with prompts.c over folders (no mod, a mod with a table, a mod that grows a file without one, two mods, unmergeable tables, no prompts' table, a mod with its own font). Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hckrman101
left a comment
There was a problem hiding this comment.
Looks good to me. I read the merge and the precedence carefully.
Precedence: a mod's table still wins as a file (hos_mods_romfs keeps e->host), and the prompts' entries are only raised into it: max of the two sizes per file, entries only one side has are kept, sorted as the game's. The merge refuses anything that is not the game's format (header, name-field size, byte-length check, out-of-order parts, a name field that differs), and then the mod's table is served as it is with the game's icons, as before. The mod's version and name field are kept. Both parts are bounded (name field <= 1024, frame <= 64 MB, output buffer sized for the worst case). The ordering is right for both the CRC part and the name part. The non-table keys return 0 when a mod has the file, so a mod's own font/textures/layouts still win. Merged once per run, and the state machine with from guards the second-table case.
Nothing game-derived is added: the new test builds made-up tables, there is no binary in the diff, and the zstd change is the existing vendored decoder reused (PROVENANCE updated).
Two small nits, not blocking:
build()picks the mod table withhos_mods_find, which returns the first match in hash order, whilehos_mods_romfspasses the path actually opened. If a mod ever carried two files ending in.rsizetable.zs(another product number besides 111), the merge could be made from the one the game never opens, and the one it opens is then served unmerged next to the larger font, which the game drops. Unlikely, but picking the keyhos_mods_romfsgets for the real table name would remove it.- Only the Conventional Commit title check has run on this head so far; the rest of CI did not show up when I looked, so worth a glance that the full suite runs before merging. The author reports the Linux run and the in-game before/after screenshots, and says Windows was compiled for mingw but not run.
No prior comments or reviews on the PR to answer.
Conflicts resolved: - MKWVK_API_VERSION 18: upstream's version 17 is prompts_live (NotRexed#2366); the data folder's MkwVkHost.data_dir follows it as version 18. - host/hos_update.c: "Skip this version" stays in the data folder; upstream's call order (NotRexed#2283, the check after the saves' place is known) is kept, with hos_data_init having chosen that place first. tests/test_linux_update_skip.py builds the start with hos_data.c instead of the removed saves_dir. - host/prompts.c: upstream's live prompts and mod size tables (NotRexed#2366, NotRexed#2270), with the generated files (and the new rsizetable.mod.zs) in cache/prompts; made_dir makes cache/ too. - builder/linux/play-diagnostics.sh: upstream's socket stderr (NotRexed#2279), with hookshot_startup.log in logs/. - The program cache moved to vk_progcache.cpp (NotRexed#2323): its path is cache/. - hookshot_driver_faults.txt (NotRexed#1823) goes to cache/ and is moved there. - env_on/env_value_off (NotRexed#2042), env_override (vk_menu.cpp), the prepare watchdog (vk_main.cpp), audio and docs merged with the data folder paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cache.cpp (NotRexed#2323), zstd's jobs to zstd_jobs (NotRexed#2270) - vk_progcache.cpp: the cache read keeps each stage's code (stage_code) and a refused record leaves nothing to destroy; program_cache_borrow lets go of the layouts alone. vk_progcache.h no longer declares make_module. - vk_shader.cpp: seed_variant_of's destroys of a failed or already made variant's modules (NotRexed#2358) are gone with the modules. - nx2/build.py: zstd_jobs(encoder=True) builds the encoder for the Vulkan back end, without ZSTD_MULTITHREAD; zstd_headers() is the users' dependency (vk_stage_code.cpp). The runtime's decoder-only zstd is unchanged. - tests: test_seed_variant_cleanup (NotRexed#2358) checks what the cache keeps instead of module lifetimes; test_recorder_sync's BOUNDARY_OK has no vk_shader.cpp entry left and vk_progcache.cpp's names its layouts; test_shader_stamp_cache knows zstd_headers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@hckrman101 thanks for the review here. #2592 now selects the mod table by the game's own RomFS table name instead of hash order, and made-up two-version tables prove both font-first and table-first requests with GCC and Clang (both fail on main). Your other point was CI visibility: the follow-up records the local suite separately and still needs the full GitHub regression checks approved and green, not just the title check. |
Follow hckrman101's review of NotRexed#2270. A mod can ship several versions' size tables; do not seed the prompts' one-time merge from the first match in hash order. Use the game's RomFS table name, selected as the prompt-assets builder does, and look up the winning mod file exactly. Keep the merge and mod precedence unchanged. Made-up two-version tables cover both font-first and table-first opens. The branch passes with GCC and Clang; both orders fail on main. No game file is used by these fixtures. Assisted-by: GPT-6 Astra Co-Authored-By: GPT-6 Astra <noreply@openai.com>
While a mod that ships its own resource size table is loaded, the button icons in every text go back to the Switch's,
whatever controller and Button prompts setting the player has. Every randomizer seed made by
Clawshot ships one, and Clawshot lists this as a known issue ("While a seed is
loaded, button icons in text show Switch buttons instead of your controller's").
Fixes #2329.
Why it happens
The game reads one size table. The button prompts' fonts are larger than the game's, so Hookshot serves the game's table
with the font's entry raised (
prompts/rsizetable.zs). A mod that makes files bigger has to ship the table with itsown entries raised (#1325), and the mod's file wins, as any mod file does.
host/prompts.cthen saw a mod table andturned the prompts' font off (
prompts: a mod has the resource size table: the game's own icons in texts), because thelarger font would not fit the mod's entry. The textures and layouts stayed the controller's, so the pause menu showed
the controller's pictures and Switch letters side by side.
What changed
host/prompts.c,host/mods.c: when the size table the game opens is a mod's file, it is served with the prompts'entries merged into it: each file gets the larger of the two entries, entries only one side has are kept, sorted as
the game's (
merge_restbl). The result is written once per run as raw zstd blocks toprompts/rsizetable.mod.zs, asthe font already is, and the prompts' font is served as without a mod. Any other mod file is served as before.
entries are merged into it.
not give its size) is served as it is, with the game's icons, as before; the log says why.
mods: System/Resource/ResourceSizeTable.Product.111.Nin_Ounce_NVN2.rsizetable.zs <- <file> (with the button prompts' sizes merged in)andprompts: <file>: the button prompts' sizes merged into the mod's resource size table (1 entries raised or added).nx2/build.py: zstd's decoder (third_party/zstd, already compiled intohookshot_vk) is compiled into the runtimetoo, from one
zstd_jobs()both use. The readme's Mods section says what happens to a mod's table.How it was tested
tests/test_mods_size_table.py(new):merge_restblcut out ofprompts.con made-up tables against an independentmodel, and seven tables it must refuse; then, on Linux,
mods.candprompts.cas they are over real folders: nomod, a mod with a table, a mod without a table that grows a file, two mods with tables, a table that cannot be merged,
no prompts table, a mod with its own font, and with
zstandarda level-19 frame and one without its size. It failson
main.python -I -B tests/run_all.pyon Linux, before a rebase onto currentmain(the new test and the two tests this change edits were run again after it and pass): 361 passed, 10 skipped; the failures are the two that fail onmainonthis machine (
test_updater_asset_digest.py: no .NET 8 packs offline;test_wayland_libdecor_hint.py: a clang 23warning) and
test_bake_mimo.py, whose shader-recompiler compile failed with an empty error at load 134 and passesrun alone (103 s).
In the game (RTX 4090, NVIDIA 615.78.08, Arch Linux, headless; Button prompts set to PlayStation 5, as a run
without a controller needs; a Clawshot seed as a mod; a save in Kokiri Forest, the pause menu's Basic Controls page):
main): the DualSense picture next to Switch icons in the texts (ZL, minus, A, B, X, Y, "Select (A) Back(B)"), and
prompts: a mod has the resource size table: the game's own icons in textsin the log;same build without the mod; the log says
(with the button prompts' sizes merged in)after the table's line andprompts: ps5 icons, 16 buttons on this pad's controls. The seed's Kokiri Forest and Hyrule Field placement fileswere read from the mod and the forest loaded. The table the game wrote has all 19 entries the seed raised and the
font's entry raised, and equals the merge computed separately in Python.
Not tested
Windows:
host/prompts.candhost/mods.ccompile forx86_64-w64-mingw32with-Wall -Wextraand no warning, butwere not built into a Windows game or run there; the folder part of the test runs on Linux only (it uses host/posix's
file calls), the merge part on both. AMD and Intel: nothing here touches the GPU. Real controllers: the face was chosen
with the Button prompts setting, as a run without a controller needs.
Found while helping with Clawshot's known issue; I'll tell its maintainer about this pull request.
Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com