SDL 3.4.20 uses default Switch controller stick and IMU calibration when the
pad has none, which fixes the infinite gyro readings on the Beitong Asura 2 Pro+.
The pins in tools/make_release.py (version, zip and devel sha256, SDL3.dll sha256)
and the Windows rows of THIRD_PARTY_NOTICES.md follow. The sniper sysroot row stays.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The floating-point helpers in simd.h and simd_fp.h inline into every lifted function before llvm-profdata matches
the profile, so the fpcheap change left pgo-v143 with a fifth of its weight while recomp/ stayed the same and
make_release saw nothing. pgo.py merge now reads the instrumented build's Ninja deps log and stores the digests of
the runtime/ headers the generated objects include (cpu.h, simd.h, simd_fp.h); make_release warns when one differs
or a record has none. docs/building.md says to retrain after a change to those headers, and build_game.py names the
libiconv-2.dll that MSYS2's SDL3.dll needs in deps-mingw/bin.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
make_release.py copied a hand-written list of the sources build_game.py compiles at install time and missed
mouse_direct.c, so the 06005d4 installer failed to link with undefined input_direct_mouse_* symbols. It now copies
build_game.INSTALL_SIDE, and build_game.py --runtime-lib stops with the missing file names before the link.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build_game.py --pgo gen builds an instrumented totk.exe (llvm-mingw: MSYS2's clang has no profile runtime) that adds
its counts to <out>/pgo/*.profraw every minute and at exit; plat_exit ends the process with ExitProcess, which skips
compiler-rt's atexit write. tools/pgo.py merges them into build/pgo/pgo-<ver>.profdata with a record of the recomp/
tree it fits. build_game.py --pgo FILE compiles the generated code at -O2 and the runtime with that profile.
make_release.py ships build/pgo's profiles in data/ and builds the runtime libraries with them; the installer passes
the update's profile to build_game.py, and builds at -O1 without one. Profiles name lifted functions by address and
hold branch counts and control-flow hashes of the generated C, no bytes of the game.
1.4.3 on machine A, mean frame by world clock: the fight2 bench 11.49 -> 10.06 ms (-12.5%), a fight outside the
training 13.00 -> 12.24 ms (-5.8%); every window CPU-bound. The profile was trained on scripted runs and 24 minutes
of play.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The check step tells a compressed file by its content (an NSP or XCI holding NCZ files), whatever its name, and
unpacks it into the temp folder with tools/ncz.py before the extraction reads it. Every NCA comes back byte for byte
and is checked against the hash in its name. The file dialog has one filter for all game files, and the form says
that compressed files are unpacked automatically, in every setup language.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-march=x86-64-v2 does not reach inline assembly, target attributes or intrinsics, which is how kern_ap_stub's YMM
saves got into libtotkrt-v2.a (issue #454). tools/check_isa.py disassembles objects and lists every function with
VEX/EVEX, BMI1/2, LZCNT, MOVBE, ADX, SHA, AES, PCLMUL or RDRAND/RDSEED code or YMM/ZMM/mask registers, except
functions in its DISPATCHED list (sha256.c blocks_ni, behind __builtin_cpu_supports). build_game.py --cpu v2 runs it
over the runtime objects after compiling and before linking or archiving, so make_release.py's v2 library build fails
too. Objects unchanged since the last clean scan are skipped; a full scan of the runtime takes about a second. The
release ships the script, and the installer's runtime fingerprint includes it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
make_release.py copied build/xlate as it found it, so a translator change reached no Windows release until someone rebuilt it by hand, and nothing failed when they did not: 0.2.1 and 0.2.8 shipped a translator from before the gather bias while the runtime logged that the bias was on. The Linux release builds its own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
The menu side is dev's: it has Simplified Chinese since #243, glyphs included. Simplified Chinese
joins the setup window as a fourth language beside Brazilian Portuguese, in the language switch,
the Windows and locale pick and the launcher; zh-Hans.json gets the nineteen texts added since
(fonts step, CPU level, base game checks, Linux checks) and the {game_exe} placeholder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-march=x86-64-v3 kept the port and the installer to CPUs with AVX2 and FMA. --cpu v2 compiles the generated code and the runtime for SSE4.2 instead. Without FMA3 the FP lowering calls fma/fmaf, so runtime/fma.c provides correctly rounded ones (musl, MIT) that honour MXCSR's rounding mode, FTZ and DAZ; the UCRT's software fallback rounds incorrectly by up to half an ulp. simd.h's fast paths keep their assumptions.
The installer's host check asks for x86-64-v2 and selects libtotkrt.a or libtotkrt-v2.a; both release scripts build and ship the pair. The differential tests compile fma.c as well, so a --cflags=-march=x86-64-v2 run tests it.
Tested on an i7-3770K (no AVX2, FMA or BMI) with an RTX 3060 Ti, game 1.4.3: the installer ran end to end, --selftest passed and play holds 40-60 fps at 1080p. fma and fmaf matched 152,288 exact vectors over two seeds, including ties, subnormals and every rounding mode, FTZ and DAZ combination. The v3 build is unchanged: fma.c is an empty translation unit there.
Shader preparation reads MacNativeGames' whole shader list history,
release downloads resume from a .part file, appimagetool and the type-2
runtime come from release tags, and the preparation summary counts the
vertex and fragment variants it skips with the graphics pipeline library
off.
The gettid cache in runtime/platform/linux.c conflicted with the same fix
already on dev (8dd7e20, #236); dev's version is kept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The restart moves into gfx_present.c's gfx_window_closed, which the Win32 and SDL windows share, and linux.c gets
plat_restart and plat_restart_wait: posix_spawn of /proc/self/exe with no descriptor past stderr and the default
signals, and a wait on a pidfd. The prompts code takes plat_file_exists, plat_setenv, strcasecmp and strdup, and the
menu and the log say a game resolution of another shape than 16:9 (16:10 now as well as 21:9) keeps the Switch prompts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The setup runs make_romfs_patches.py --prompts xbox and --prompts xbox-label and warns once when either fails, the
release bundles tools/button_icons.py and fontTools, and build_game.py and package_build.py copy both folders.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The branch forked 79 commits before main and 98 before dev. Resolutions:
1. Aspect ratio: dev's implementation stays (camera patch at page +56 on 1.4.3, tools/ultrawide_layout.py layouts per
size in romfs-patches-<w>x<h>, the aspect = fit|stretch setting). The PR's second implementation is dropped: the
aspect sets of patches-v121.txt and patches-v143.txt (the 1.4.3 one patched the same viewport sites as dev's),
tools/aspect_layouts.py, the resolution.c shapes that limited game resolutions to 16:9, 16:10 and 21:9, and the
picture_fit setting. Its letterbox code (gfx_fit_rect) is kept and reads TOTK_ASPECT.
2. Code dev changed where the PR moved it: the stick dead zone, the test gamepad and the paddles go to input.c; the
DPI awareness, keep-awake and IME detach of gfx_window.c go to gfx_window_win.c; device fault reports and GPU
breadcrumbs to gfx_present.c. gfx_window_dpi gets an SDL version.
3. dev's Win32 calls in shared code go through platform.h: the shader cache pack reader (PlatFile), the romfs
overlay checks, the audio pacing waits, the motion, ASTC and device fault locks. plat_cpu_usable and
plat_commit_info get Linux versions; plat_cpu_count counts the machine's processors on both. dpi_probe.c becomes
dpi_probe_win.c.
4. assume_focus defaults to 1 as the PR has it (a load interrupted by a focus loss can stop for good) and stays live,
with dev's Game tab row.
5. The frame limits 40 and 45 join dev's list. The BC 3D storage fallback for Vega only runs with
TOTK_BLOCK_VIEWS_3D=1, since dev makes 3D BC images without block views by default.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The setup window gets installer/text/zh-Hans.json, a full copy of the English catalog, and a third entry in its
language switch. A Windows display language of zh-CN or zh-SG picks it; zh-TW, zh-HK and zh-MO write Traditional
Chinese and stay on English. A Chinese window still starts with English as the game language, because Chinese game
text needs the Switch shared fonts the installer does not extract. The launcher's message box and
make_release.py's launcher_text.h carry the Chinese strings too.
The menu and the performance overlay get a text_zh_hans table for every menu id, and TOTK_MENU_LANG takes zh-Hans.
Left unset, the menu follows the system UI language with the same Simplified Chinese regions. The font atlas merges
in every glyph of the menu language's text from the system font (Microsoft YaHei, else SimSun) and is built again
when the menu language changes. ov_probe checks that every menu id has Chinese text, that the printf formats keep
the English conversions, and how system language tags map to menu languages; installer_gui_test checks the new
catalog the same way as the Russian one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcYzeu7eb2tXZMU4bRVcGh
The installer had English and Russian. installer/text/pt-BR.json covers every id with the same placeholders; the window offers PT-BR beside EN and RU and picks it when the Windows display language is Portuguese (Brazil), LANGID 0x0416; Portugal's Portuguese stays English. make_release.py writes LAUNCHER_*_PT_BR into launcher_text.h and the launcher shows it on the same LANGID. The catalog tests check every window language against English.
An output_res such as 3440x1440 now widens the camera's view to that shape on 1.4.3: patches-v143.txt
sets the aspect ratio at the camera and viewport sites that hand it to the perspective projection.
The HUD and menus come from a romfs-patches-<w>x<h> overlay that make_romfs_patches.py --aspect
builds through tools/ultrawide_layout.py, and romfs.c overlay_init picks that overlay when the game
resolution is not 16:9. The installer prepares it for 2560x1080, 3440x1440, 3840x1600 and 5120x2160.
When the window's shape differs from the game resolution's, the new aspect setting keeps the
picture's shape with black bars (fit, the default) or stretches it over the window.
The game lays its interface out in a 1920x1080 space and draws it over the whole output, so at 1280x800 every menu and
the HUD were 11 % taller than drawn, and at 21:9 34 % wider. tools/aspect_layouts.py rewrites the layout archive for
each shape: every layout's root pane scaled back, full-screen backgrounds kept full, the HUD moved to the screen's
edges, and the minimap, place name and dragon's tears map icon animations adjusted. It follows the behaviour of
Fruithapje21's TOTK-Ultrawide (GPL-3.0, read for behaviour only) and checks every original value before it writes.
make_romfs_patches.py writes the results to romfs-patches/16x10 and 21x9 at install and build time, and romfs.c serves
the one of the output's shape. resolution.c accepts 16:9, 16:10 and 21:9; another shape draws 16:9 with bars. The
menu lists the game resolutions by shape. Checked on 1.2.1 and 1.4.3 at 1280x800 and 3440x1440: HUD, minimap,
inventory, map, system tab and loading screen.
make_release.py and make_release_linux.py built the runtime library and the --prove build from generated/v121 alone.
The library reads only what both versions' layout.h share (MOD_COUNT, MOD_MAIN_BASE), so both scripts now take
generated/v121, else generated/v143, pass its --version, and name extract.py and gen.py when neither exists.
gen.py started one emit worker per CPU, about 1.3 GiB each on 1.4.3, so many-core machines with modest RAM died with a MemoryError during "Translating code to C" (issues 17, 28, probably 66). The default is now min(CPU count, 80% of the free physical memory / 1.5 GiB), at least 1, capped by the memory limit of the enclosing job object if there is one. --jobs still overrides it, and the chosen count and its reason are logged. The memory helper is tools/hostmem.py, shipped with the release tools.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1.2.1 renders the scene size it reads, while 1.4.3 scales it by output width / 1920: on 1.2.1 the scene set is on
whenever the output grows (2560x1440 gave a 1600x900 scene before, 2133x1199 now). An output at or below the shipped
size needs no grown HeapDef. The release deps carry the static libzstd and its header, totk.ini.example the four new
keys, THIRD_PARTY_NOTICES.md the MacNativeGames sites, FSR 1 and zstd.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The release built libtotkrt.a against generated/v121, so patches.c baked in 1.2.1's patch page (0x700472b000, the page
after 1.2.1's main). A 1.4.3 install lifts its code with the 1.4.3 patch table, whose patched sites read the page after
1.4.3's main (0x7003adf000): the runtime never committed it and the game faulted there soon after mounting the save, while
frame_rate.c wrote its frame step into sdk memory at the 1.2.1 address. patches.c now joins romfs.c in INSTALL_SIDE and
the release ships its source, so it compiles against the player's patches.h.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MacNativeGames now translates each shader's default bind state when it builds and keeps only other variants in its
shared list, so the list at origin/HEAD has 134 rows of 1.4.3 shaders. prepare_shaders.py seeds the default variant of
every shader it finds and reads the list through tools/shader_list.py, which adds the V rows older revisions held. On
1.4.3 that prepares 29,587 variants in 7 min with 0 translation failures, and every one of the 1,095 variants the field
and intro runs met in play is among them. The installer's dev path and make_release.py read the list the same way.
Also record that 1.2.1 loads saves 1.4.3 wrote.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
clean_env compared the upper-cased os.environ keys with mixed-case names and dropped SystemRoot, which crashed Tk in the bundled python.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>