fix(prompts): a failed rebuild of the button pictures keeps the last good file #486
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!486
Loading…
Reference in a new issue
No description provided.
Delete branch "jarynclouatre/Longshot:fix/prompt-cache-keep-good"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
When a start writes the button prompts' cache again (after the Button prompts face or a binding changed) and the write fails part way, for example on a full disk,
cache/prompts/Common.bntx.zs(orCommon.blarc.zs) is left cut short while its key file still holds the old setting's key. Back on the old setting the key matches, the file exists, and the cut file is given to the game at every start.write_patchedinhost/prompts.copensoutwithfopen(out, "wb"), which empties the old file before the new one is known good. On a failure the old key stays, and the reuse check is only "key equal and the file exists".What changed
host/prompts.c,write_patched): writes toout.tmpbeside the file, with every write and thefclosechecked. Then it removes the key file, moves the temporary file overout(MoveFileExAwithMOVEFILE_REPLACE_EXISTING) and writes the new key. On any failure the temporary file is deleted and the old file and its key stay as they were, which is still a valid pair. A stop between the steps leaves no key, so the next start writes again. Both callers (textures and layouts) go through this function, and each has its own key file.tests/test_prompt_cache_errors.pycompileswrite_patchedand its zstd helpers fromhost/prompts.c, with the three Windows file calls as stand-ins on POSIX calls. Setting A is written; setting B's write fails at a file size limit (RLIMIT_FSIZE, SIGXFSZ ignored); A's file bytes and key are unchanged and no.tmpis left; A again serves the same bytes; B with room replaces file and key, and the file holds the game's bytes with B's run. Skipped on Windows (no file size limit there).tests/test_mods_size_table.py's routing fixture buildsprompts.cover pieces ofhost/posix/win32_posix.cand now takes itsDeleteFileAandMoveFileExAtoo.Flags and settings
None.
Measurements
main:
9c9d69ed(2026-11-14)this PR: fix/prompt-cache-keep-good @
d690b06bHardware: none used (game-free checks on a Linux x86-64 PC, gcc 15.2, Python 3.14)
Scene: none, the game was not run
Method:
python3 -I -B tests/run_all.py --jobs 4, two runs each (main twice, then the branches of this batch in turn, twice). The new test also ran against main'shost/prompts.c.How to reproduce: the commands above in a checkout of each commit
9c9d69edd690b06btests/run_all.py(run 1, run 2)test_bake_portability.py,test_walk_key.pytests/test_prompt_cache_errors.pyFAIL: a failed write of setting B changed setting A's file (200000 bytes, was 300019)test_bake_portability.pyfails here for a missing Python module (zstandard).test_walk_key.py's fixture doesn't link on main (undefined reference to hos_oot_autoload_input).Testing
Tested: the game-free suite on a Linux PC, as in Measurements.
host/prompts.ccompiles (-fsyntax-only -Wall -Wextra) with llvm-mingw 20261104's x86_64-w64-mingw32-clang with no warnings, as main's, and whole with gcc intests/test_mods_size_table.py's fixture.Not tested: the game, and a full disk on Windows.
Needs other testers: None.
Screenshots
Nothing on screen.
Risk and rollback
A rewrite now needs room for a second copy of the file for a moment (a few MB). Reverting the commit puts the write in place back. #218 changes the
fopencalls in the same function tohos_fopen_*; whichever lands second needs a small rebase.Issues
None filed. Found reading
write_patched.Checklist
For everyone
type(scope): description).main.python -I -B tests/run_all.pyrun and passing (any failure that also fails onmainis named above).third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
mainand passing here.tests/that reads changed source updated in this PR, not weakened.WIP: fix(prompts): a failed rebuild of the button pictures keeps the last good fileto fix(prompts): a failed rebuild of the button pictures keeps the last good fileView command line instructions
Checkout
From your project repository, check out a new branch and test the changes.