26 Commits
Author SHA1 Message Date
Valiantsin DzerakhandClaude Opus 5.5 bc578148ab Write RomFS layout folders only for the screen shapes and prompts this player uses
The setup wrote 64 patch folders: every prompts style for all 15 shaped game resolutions. The new shapes step
(installer/screens.py) writes romfs-patches-<w>x<h> only for the shapes of the connected displays, the output_res the
game defaults to on each and the totk.ini output_res, and the prompts' shaped folder only for the style totk.ini
selects. One folder per shape: the runtime maps the game resolution to its shape's size (cfg.c cfg_shape_size, the
closest ratio within 1%), and an exact-size folder from an older install still wins. The settings menu marks a game
resolution whose shape has no folder and can start the generator for it in the background, for the next start.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 19:02:31 +03:00
itaskaev2andClaude Opus 5.5 f854d67e6f Name the other program that holds totk.exe when the setup cannot link it
When ld.lld cannot write the totk.exe it links in the setup's temp build folder (Permission denied), the setup
showed only "Compiling totk.exe failed". In #1122 the holder was an antivirus that flagged the new exe, not a
running game. The compile step now recognises that failure in the build log and says what to do: close the game,
exclude the setup's and the install folder from the antivirus, restart Windows and run the setup again. Texts in
en, ru, pt-BR and zh-Hans; build_game.py's own line names the antivirus too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 11:17:51 +01:00
Louis JusticeandClaude Opus 5.5 c2716d2e7c The keyboard and mouse text prompts show Y as T, and the setup draws the PC prompts from totk.ini's bindings.
Y has two default keys: the left mouse button, which is a menu's A while the pointer is shown, and T, which presses Y
everywhere. The button font (menu guides, the dialogue log) now shows Y as its first bound key that is not a mouse
button; the button guide in play and the action prompt keep the left button. The PC prompts are a setup step of their
own, keyed by the bind_ lines of the install's totk.ini, so running the setup again after rebinding redraws them
without preparing the shaders again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 18:11:38 -05:00
Luxury 2907f4efc3 Stop the installer space check at an unavailable drive root 2026-11-08 23:09:58 -05:00
fa94e36549 Store the data writes of mods' ExeFS patch files into main before the game runs
An IPS, IPS32 or pchtxt file for main that writes main's .rodata, .data or .bss was refused as a whole. Such writes
need no lifting: tools/exefs_patches.py now puts them in build-cache/exefs.data, and runtime/mods.c stores them into
the loaded main before any game code runs, as emulators and Atmosphere apply a patch file to the module before its
dynamic linker runs. A DT_RELR word gets main's base added; bytes over words an explicit-addend relocation fills change
nothing and are dropped; a write into the dynamic linker's tables, a lazily bound function pointer or outside main's
image keeps the file unsupported. A mod whose data lines do not all fit the build keeps its code patches off too.

The mods are applied from the bottom one up (mods_exefs_apply), so where two mods write the same bytes the higher one
wins, as it does for files. --probe-mods checks it with two mods writing one byte.

The lifted code reads some of main's bytes at lift time (the jump tables). recomp/gen.py lists those ranges in
<gen>/main/folded.txt, and the setup checks the data writes against them after the lift: a file that writes them
becomes unsupported, since the change would not reach the generated code. Generated C without mods is unchanged.

This is the data part of #790 (ericdallo's ExeFS work), split out on its own; the plugin part follows separately.

Co-Authored-By: itaskaev2 <165683571+itaskaev2@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 15:51:42 +01:00
Valiantsin DzerakhandClaude Opus 5.5 e8b8860abe Warn on a cut DLSS download and stay quiet without an RTX GPU
A connection cut mid-file raises http.client.IncompleteRead, which is not an OSError, so it failed the whole setup at
the DLSS step instead of warning. The download box is ticked by default, so every player without an RTX GPU got a
warning for a download they never chose; that case is a log line now. The game file dialog keeps its "All files"
filter: the check tells an NSZ or XCZ by its content, not its name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 15:37:11 +03:00
itaskaev2andClaude Opus 5.5 444e6f5b51 Download NVIDIA DLSS in the setup for RTX GPUs
dlaa and the DLSS modes need nvngx_dlss.dll next to totk.exe, which the release does not ship, so most players
never had DLSS. A new setup step after prepare downloads NVIDIA's own copy from the DLSS SDK repository
(github.com/NVIDIA/DLSS, tag v310.9.1, NVIDIA RTX SDK license) and checks its size and SHA-256.

The window has a tick box for it, on by default and named with its source and licence; the CLI takes --dlss. The
step runs on Windows with an NVIDIA RTX GPU (the host check's Vulkan devices), keeps a DLSS library the player
already put there, and on a failed download warns and lets the game run without DLSS; the next setup run tries
again. Texts in English, Russian, Brazilian Portuguese and Simplified Chinese, docs/installer.md step 7, tests in
tests/installer_test.py (DlssTest, with a file: URL).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 15:36:07 +03:00
Valiantsin DzerakhandClaude Opus 5.5 14ed048dd3 Read an install recorded as update 1.1.1 as 1.1.0 when the setup updates it
Releases before 0.3.1 recorded the 0x20000 update as 1.1.1. After the rename (#371) nothing mapped the recorded
name, so an update of such an install asked make_romfs_patches.py for --version v111 and failed at the end (#332);
in a fresh setup folder it would not find expected-v1.1.1.json at all. migrate_state maps the old name before the
plan and gives the extract record the key of the renamed expected file; the full check of kept output still hashes
the extraction against it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 22:17:31 +03:00
Valiantsin DzerakhandClaude Opus 5.5 e0e1ecfdbb Merge pull request #384: Fix installer catalog test encoding on Windows (FaserDocs)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 08:31:28 +03:00
Valiantsin DzerakhandClaude Opus 5.5 8eb48493c0 Rebuild the code cheats and ExeFS patches of a renamed mod folder
The lift key hashed each cheat and ExeFS patch file by its name and content only, but tools/cheats.py and
tools/exefs_patches.py name every patch set after "<mod folder>/<cheat or file>". After a mod folder was renamed,
totk.exe saw none of its code cheats in the build and started the rebuild, the setup found the lift current and skipped
it, and the cheats stayed "after the rebuild" for good. The key now takes each file's path under mods/ as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 19:28:32 +03:00
FaserDocs 86a9ea6d53 Read installer sources once as UTF-8 in the catalog test 2026-11-01 15:54:57 +01:00
Valiantsin DzerakhandClaude Opus 5.5 3668271182 Start the rebuild window and its setup run with a Python that finds the installer
The rebuild command puts the release folder on sys.path itself: totk.exe starts it in the install folder, and only the
Windows release Python's ._pth names that folder. In a repository the window and its setup run use the Python that
runs the setup, since the tools' embeddable Python there has neither tkinter nor the repository on its path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 17:40:22 +03:00
Valiantsin DzerakhandClaude Opus 5.5 c3dae879cb Build the mods' ExeFS patches into the game and switch them with their mod
A mod that patched the game code (.ips, .pchtxt) stayed off as a whole.
tools/exefs_patches.py now reads IPS, IPS32 and IPSwitch files from each
mod's exefs folder and from atmosphere/exefs_patches/<name>/. It keeps the
ones whose build id is main's and turns their writes into main's code into
one patch set per file. The writes go through the same rules as the code
cheats (tools/cheats.py convert). A file that writes main's data, or that the
rules cannot express, is unsupported as a whole. The setup's lift runs it
after cheats.py and writes build-cache/exefs.status.

runtime/mods.c checks each patch file against that status:

- a built file's set is switched on with its mod;
- a file the build lacks keeps the mod off and starts the rebuild at the next
  start, like a code cheat does;
- an unsupported file keeps the mod off, and the Mods tab shows the reason;
- a file for another version is counted and left out.

A mod patch on a site of one of the port's own sets turns that set off while
the mod is on, and the Mods tab names it. The Mods tab also gets the "Rebuild
the game now" row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:29:40 +03:00
Valiantsin DzerakhandClaude Opus 5.5 1bebcfd9ef Rebuild the game at start when an enabled mod has unbuilt code cheats
Code cheats need the game lifted and compiled with them. Running the setup
again did that, but it lifted and compiled everything and prepared the
shaders again.

- The setup keeps the generated C and the objects in its temp folder (about
  1.3 GB). gen.py rewrites only the chunks whose C changed, so Ninja
  recompiles only those. One new code cheat on 1.4.3 took a 47 s lift and
  19 s of compile and link on 24 cores.
- Prepare's key no longer follows the compile key, only the runtime, the
  translator and the game version, so a rebuild keeps the prepared shaders.
- The cleanup writes build-cache/rebuild.txt, the command that opens the
  setup window in a new --rebuild mode on the install folder. That mode runs
  at once and starts the game again when it succeeds.
- At start, runtime/cheats.c runs that command and exits when an enabled
  mod has code cheats the build lacks (plat_spawn, new for Windows and
  Linux). build-cache/rebuild.skip keeps a failed or cancelled rebuild from
  starting again for the same cheats. "Rebuild the game now" on the Cheats
  tab tries again, and [mods] mods_rebuild = off turns the rebuild off.
  Scripted runs never start it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:16:53 +03:00
Valiantsin DzerakhandClaude Opus 5.5 ac69f39529 Read cheat files from the mods folder instead of shipping them
A cheat file is now part of a mod: mods/<mod>/cheats/<build id>.txt, or the
Atmosphere places inside the mod folder, the file name in any case. The port
ships no cheat files any more (the MyNXCheats files and their notice row are
gone).

- tools/cheats.py --mods builds the code cheats of every mod folder; a
  cheat's key hashes "<mod folder>/<name>", so two mods' cheats of one name
  keep their own switches.
- The setup reads the cheats from <install>/mods and writes the status to
  build-cache/cheats.status.
- runtime/cheats.c reads the files of the enabled mods the port can use, in
  the Mods tab order, and the status from build-cache.
- A mod with only cheats is usable. The Cheats tab groups the cheats by mod,
  and the Mods tab says how many cheats a mod brought.
- The cheat texts are in all four menu languages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:05:31 +03:00
Valiantsin DzerakhandClaude Opus 5.5 5e584ea966 Merge pull request #51: Load Atmosphere cheat files and switch their cheats from a Cheats tab in the menu (conongnang)
Merged onto the mods folder (task/mods1); the Cheats tab sits after Mods. The cheats' menu text and the cheat file's
place are reworked for the mods folder in the commits that follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 13:31:17 +03:00
Valiantsin DzerakhandClaude Opus 5.5 4cece2c848 Merge pull request #346: Let the installer extract the Switch shared fonts from a firmware folder (fch869)
Conflicts with dev resolved by keeping both sides: the fonts step sits between check and extract,
beside the x86-64-v2 check, the pt-BR window language and the xbox-label patches. pt-BR gets the
thirteen firmware and fonts texts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:03:29 +03:00
turquopool 873ebb7755 Let the installer extract the Switch shared fonts from a firmware folder
The setup takes an optional --firmware directory (an unpacked firmware or an emulator's Contents/registered) and, for Chinese, Korean and Traditional Chinese, runs the vendored font extractor into <install>/shared-fonts. Without the folder it warns as before and the install still completes. The fonts step is keyed by the language and a cheap firmware fingerprint; the window gets a folder picker and help text, and the command line takes --firmware.
2026-11-01 15:22:14 +08:00
conongnangandClaude Opus 5.5 183519190a Bundle the cheat files for 1.2.1 and 1.4.3 and install them when the player has none
The setup keeps a player's own file. A bundled file the tools refuse costs its cheats, not the install.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:42:10 +07:00
conongnangandClaude Opus 5.5 a81b00930e Key the lift step on the files in cheats, so extracting main does not rebuild the game
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:15:20 +07:00
Valiantsin DzerakhandClaude Opus 5.5 375acc3a71 Say that a base game file is an update or a combined package instead of claiming it is not Tears of the Kingdom
An update NSP chosen as the base game keeps the base title id on its Program NCA and carries the update id (0100F2C0115B6800) only in its Meta NCA, so program_nca rejected it with the generic base-game metadata message (#261). Check.open_input now names an update file or a file with several Meta NCAs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 02:04:47 +03:00
Valiantsin DzerakhandClaude Opus 5.5 a76224f8a6 Fail the install when romfs/ is gone or unreadable after cleanup
An install whose romfs/ went empty and unreadable after the extraction had verified it (a folder Windows was still
deleting) ended with result ok, and the game stopped at its first file read. Cleanup now checks that romfs.bin and
index.json are still there, match the verified size and hash record, and that romfs.bin opens; otherwise it fails with
cleanup.romfs_unreadable, which tells the player to restart Windows and run the installer on the same folder (resume
extracts the game data again). Reported in #107.

tests/installer_test.py CleanupTest: an emptied, removed or resized romfs passed cleanup before, fails now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:42:03 +03:00
Valiantsin DzerakhandClaude Opus 5.5 67116a387f Map the zh-CN and zh-TW game languages to zh-Hans and zh-Hant
Choosing Simplified Chinese in the installer wrote lang = zh-CN to totk.ini and the game showed Japanese: ov_language() handed the code to nn::oe::GetDesiredLanguage unchanged, and TotK only accepts zh-Hans and zh-Hant for Chinese. Reported in #72 and #68.

ov_language() now maps both old spellings, so existing totk.ini files keep working and cfg.c still accepts them. The F1 menu offers one row per language under the canonical codes. The installer lists only zh-Hans and zh-Hant, writes them, and reads zh-CN or zh-TW from the CLI or from a recorded totk-install.json as the canonical code, so a repair or update of an old install does not fail with check.lang_unknown and rewrites the ini. --probe-services prints the configured language and checks the four Chinese codes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 13:27:19 +03:00
Valiantsin DzerakhandClaude Opus 5.5 b245b07722 Let the installer build from the 1.2.1 or the 1.4.3 update
The check identifies the update by hash among layout.SUPPORTED and records it in totk-install.json; an install that
records none is 1.2.1. Extraction, lifting, compiling and preparing take the version from there: the patch table and
expected hashes per version, build_game.py --version (rt_game_version), make_romfs_patches.py and prepare_shaders.py
--version. Step keys of a 1.2.1 install stay as they were, so updating such an install does not extract again. Another
update file than the recorded one plans the extraction again (a copy of the same file is recognised by its hash), and
an identified version change re-plans every step after the check. The disk space estimate takes the larger RomFS.
Catalog strings name both versions and take the version as a parameter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 18:18:20 +03:00
Valiantsin DzerakhandClaude Opus 5.5 a56a0e6fda Extract the RomFS again when a kept image fails its full hash instead of trusting its index.json
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 08:50:46 +03:00
Valiantsin DzerakhandClaude Opus 5.5 0431b62683 Add the installer core: the six setup steps, JSON progress events, totk-install.json resume and update, and explicit paths in the extract, build and shader tools
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 08:25:14 +03:00