Commit Graph
865 Commits
Author SHA1 Message Date
itaskaev2andClaude Opus 5.5 5cd48ea696 Describe probe_movie_bench in docs/settings.md
tests/settings_doc_check.py failed on dev since 3cd2410 added TOTK_PROBE_MOVIE_BENCH to known[] without a row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 19:07:38 +01:00
Valiantsin DzerakhandClaude Opus 5.5 da86c39121 Merge #858: serve the HeapDef of the highest content mod below an HD texture pack, grown by the pack's texture heap, so the pack above The Second Quest no longer crashes at start
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 20:45:25 +03:00
Valiantsin Dzerakh 4f113847f5 Merge task/perfdraw: bind only the vertex buffers a draw's vertex input reads 2026-11-06 20:43:39 +03:00
Valiantsin DzerakhandClaude Opus 5.5 da24dd4cba Bind only the vertex buffers a draw's vertex input reads
The game keeps about ten vertex streams bound while a draw reads a few of them, and bind_vertex_buffers resolved and
compared all 17 slots on every draw. vk_pipeline_set_dynamic now returns the bindings of the state's vertex input,
from the same vertex_input that builds the dynamic input or the pipeline's, and the other slots get the zero buffer.
A stream is taken from the previous bind only when it was resolved there. In the fort, bind_vertex_buffers drops from
9.0% to 7.2% of the replay thread's work (two profiles, recorder on). TOTK_VB_USED=0 binds every stream as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 20:43:33 +03:00
Valiantsin Dzerakh 5eaac2ee86 Merge branch 'pr858' into task/heapgrow 2026-11-06 20:39:15 +03:00
Valiantsin DzerakhandClaude Opus 5.5 03c703a712 Merge #809 and #814: draw a 16:9 picture with bars when the HUD layout for a wider or narrower game resolution is missing, and fix the installer DPI test at 125% scaling
#809: on 1.4.3 at 2560x1080 without romfs-patches-2560x1080 the game drew 1920x1080 with the 16:9 HUD, aspect patch
off, 0 validation errors; the four probes pass. #814 changes the test only; DpiTest passes at 96 DPI, the 125% case
was checked by hand against Tk's rounding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 20:27:18 +03:00
Valiantsin Dzerakh 545a97d7ff Merge branch 'pr814' into task/hudshape 2026-11-06 20:24:04 +03:00
Valiantsin Dzerakh 0d4c3555d5 Merge branch 'pr809' into task/hudshape 2026-11-06 20:24:03 +03:00
Valiantsin DzerakhandClaude Opus 5.5 6cb41a5d17 Merge #835: store the data writes of mods' ExeFS patch files into main before the game runs
Checked on 1.4.3: tests/exefs_patches_test.py (14) and tests/installer_test.py (53) pass, --selftest, --probe-mods,
--probe-cfg and the four probes pass, the lifted main is byte-identical to generated/v143 apart from the new
folded.txt, and a field run without mods reaches gameplay with 0 validation errors. Not covered: folded.txt leaves out
the exception tables the lifter reads directly (recomp/jumptables.py landing pads), which no known mod patches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 20:12:53 +03:00
itaskaev2andClaude Opus 5.5 e69ee44a3a Grow a content mod's HeapDef when an HD texture pack above it grows the texture heap
df9ba65 keeps a content mod's heap sizes when its table is the one served, that
is when the mod is above the texture pack. With the pack on top (HDPacks.com's
4kTextures sorts first), the pack's table was still swapped for the game's own,
and The Second Quest's larger RSDB and UI heaps were lost: the game crashed at
start writing to address 0 in main+0x1d4200. heapdef_overlay now grows the
table of the highest switched-on mod that changes other heaps only, and falls
back to the game's own table when no mod has one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:04:18 +01:00
Valiantsin Dzerakh 257f6201a3 Merge branch 'pr835' into task/exefsdata 2026-11-06 19:56:29 +03:00
Valiantsin DzerakhandClaude Opus 5.5 a83b3b8b62 Merge #743: keep uniform updates inside a pass as scratch overlays and copy them at the pass end
Measured on machine A (RX 9070, 1.4.3, 3840x2160), in-run A/B of TOTK_UB_OVERLAY on standing scenes:
fight2 hills with Link standing after 55 s (about 104 updates inside a pass per submission): frame
11.99 -> 11.56 ms (-3.6%), GPU 7.41 -> 6.78 ms, replay unchanged. Field and sky island edge (6-19
updates inside a pass): -1.0% and -1.2%. No validation errors, no visible differences in fight2 shots.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 19:34:52 +03:00
Valiantsin Dzerakh f594062a43 Merge branch 'dev' into task/uboverlay 2026-11-06 19:15:36 +03: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 2327db91c3 Merge task/recline: keep the recorder queue's head, tail and producer state on separate cache lines and publish head in batches
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 16:49:38 +03:00
Valiantsin DzerakhandClaude Opus 5.5 0f4e0af554 Declare the recorder queue's put_h field by its own name, which the move into Q had rewritten as Q.put_h.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 16:24:56 +03:00
Valiantsin DzerakhandClaude Opus 5.5 b578d26628 Keep the recorder queue's head, tail and producer state on separate cache lines and publish head in batches
The recorder spins on head while it waits, and tail, put_h, head and the producer's statistics shared one cache line,
so every packet moved that line between the two cores: put took 6% of the replay thread in the fort with the recorder
on. head, tail and sleeping now have a line each, the producer keeps its own state and the last tail it read, and pub
publishes head once 64 words wait (TOTK_REC_PUB; 0 publishes every packet). Every wait publishes everything first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 16:18:56 +03:00
Valiantsin DzerakhandClaude Opus 5.5 df9ba65a91 Swap a mod's HeapDef for the game's own only when that table grows TextureHeap
heapdef_overlay replaced the served mod table whenever any switched-on mod grew the texture heap. With an HD pack and
another mod that ships a HeapDef for other heaps on top of it, the other mod's sizes were lost. It now checks the
served table itself (resolution.c res_heapdef_tex_grown): only a table with TextureHeap over the shipped size is
swapped, any other stays the base and gets the growth on top.

A mod HeapDef the port cannot read no longer logs "TextureHeap 0 KiB": the failure is logged with the mod's name.
read_original sat between read_served and its comment; each function has its own comment again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 15:23:15 +03:00
Valiantsin DzerakhandClaude Opus 5.5 caf53eb764 Merge #713: grow the texture heap a mod's HeapDef asks for, so HD texture packs load (#673)
Brings in #576 (kurerb, tex_heap_extra_mb) and itaskaev2's mod HeapDef reading on top of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 15:08:00 +03:00
Valiantsin DzerakhandClaude Opus 5.5 76c55e3374 Merge task/copystat: keep NVN recording copies off the game threads' critical path
fight2 on the same dev base, A B B A whole runs, 10-75 s: 13.31 -> 12.82 ms per frame (-0.49 ms); a 4-core
affinity run showed the same -0.68 ms share on an older base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:17:45 +03:00
Valiantsin Dzerakh c0ec4e3a4f Merge branch 'dev' into task/copystat 2026-11-06 14:05:50 +03:00
Valiantsin DzerakhandClaude Opus 5.5 3dd16691f1 Count host calls per thread instead of with a locked add on the slot's cache line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:05:44 +03:00
Valiantsin DzerakhandClaude Opus 5.5 5c8f3ee5c6 Keep NVN recording copies off the game threads' critical path.
Three game threads flatten recordings, inline them and add control memory at once, and every large copy came
from a fresh VirtualAlloc, so each one paid zero-page faults, and release_copies freed them under the exclusive
copy lock. Copies are now freed after the lock through a per-thread dead list, blocks of 256 KiB to 16 MiB come
from a small best-fit cache, and each copy keeps its pin list so a free or clone no longer walks the records again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:05:44 +03:00
itaskaev2andClaude Opus 5.5 2ad82557fd Reserve the larger stack and heap block only for a texture heap extra
The block below the module window stays 6 GiB, as on dev, and grows by the texture heap extra (tex_heap_extra_mb or
a mod's HeapDef) rounded up to a GiB. A player without an HD pack reserves nothing more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:43:42 +01:00
itaskaev2andClaude Opus 5.5 8ac207f353 Grow the texture heap a mod's HeapDef asks for instead of serving that table
HD texture packs made for the emulators ship their own HeapDef with TextureHeap and its parent grown for the
emulators' 8 GB memory option (HDPacks.com's 4K pack: by 3,419,000 KiB). Served as it is, the game asked for room the
application pool does not have and crashed at start (#673); without the file it looped the panic Blood Moon.

Before mem_init sizes the pool, resolution.c reads the HeapDef of every switched-on mod (mods.c mods_peek_romfs, which
lists the mods' RomFS roots without the rest of the scan: mods_scan needs paths main sets later) and counts the largest
TextureHeap growth over the shipped 506,880 KiB like TOTK_TEX_HEAP_EXTRA_MB (the larger of the two, at most 4 GiB). The
pool and the heap cap grow by it, and romfs.c heapdef_overlay serves the game's own table grown by that amount in the
mod's place, so the other heaps keep the sizes of the game version that runs.

Tested with the HDPacks.com 4K Texture Pack v1.0 as players install it, on 1.4.3 and 1.2.1 (RTX 4080 SUPER): the game
loads a save and runs at 60 fps with 0 validation errors, and holds 4.5 GB of game memory pools against 1.2 GB without
the pack. docs/mods.md, README.md and totk.ini.example say so; other packs come with no guarantee.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:43:41 +01:00
Herbert CostaandClaude Opus 5.5 2a70683007 Grow the HeapDef for tex_heap_extra_mb at the game's own resolution too
heapdef_overlay returned at once when res_heap_extra_kib() was 0, which it is at 1920x1080 with the game's scene size
and shadow map, so tex_heap_extra_mb did nothing there and a 1080p player with an HD pack still hit the Blood Moon
loop. It now also builds the table when res_tex_heap_extra_bytes() is set. Found by itaskaev2 in review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:43:41 +01:00
Herbert CostaandClaude Opus 5.5 a57ea119fa Grow the world texture heap for HD texture packs with tex_heap_extra_mb
HD texture packs made for emulators with 8 GB of DRAM, such as the HDPacks 4K pack, grow "TextureHeap" in their own
HeapDef table. Served as a mod, that table replaces the one the port grows for the resolution and the shadow map, and
the game crashes at boot; without it the pack's textures do not fit, and the game loads and then starts its panic
Blood Moon over and over.

tex_heap_extra_mb ([mods], 0 to 4096 MiB, read at start) grows TextureHeap and its parent ゲームグラフィックス in the
port's HeapDef, and the application pool and the heap cap by the same amount. LOW_SIZE goes from 6 to 10 GiB so the
stack and heap block holds the largest heap. At 0 the pool, the heap cap and the HeapDef are what they were.

The selftest's "beyond the pool" MapPhysicalMemory asked for 4 GiB, which a grown pool holds; it now asks for just
past the pool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:43:41 +01:00
Valiantsin Dzerakh 959033e1fb Merge the latest head of pull request #743 2026-11-06 11:25:30 +03:00
Valiantsin Dzerakh 4402b030fe Merge branch 'dev' into task/uboverlay
# Conflicts:
#	runtime/cfg.c
2026-11-06 11:25:30 +03:00
Valiantsin DzerakhandClaude Opus 5.5 e0f8121a6a Merge task/playtime: play time across runs on the Game tab (#729, #720)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:56:21 +03:00
Valiantsin DzerakhandClaude Opus 5.5 4645b8a0d0 Leave scripted runs out of the play time, keep a damaged file whole, and test the file with --probe-playtime.
A --seconds run (benches, menu shots, input scripts) reads the total so the Game tab shows it, but starts no counting
thread. The file is now read once at start instead of on the thread. A playtime.txt with a UTF-8 byte order mark reads
as valid, and a damaged one is kept whole as playtime.txt.bad instead of its first 63 bytes. --probe-playtime checks the
parser, a missing, valid and damaged file, the 30 s save and the 2 s cap of one tick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:55:42 +03:00
itaskaev2andClaude Opus 5.5 d850c2116d Count play time across runs and show it on the Game tab
A host thread adds each second in which the window has the focus and the game presents frames, keeps the total in
<profile>/playtime.txt (every 30 s and at exit) and the Game tab of the settings menu shows it with this run's share.
Texts in English, Russian, Brazilian Portuguese and Simplified Chinese. Closes #720.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:52:28 +03:00
Valiantsin DzerakhandClaude Opus 5.5 a959eab275 Merge task/vrampress: drop released textures the game has overwritten under VRAM pressure (#754)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:08:32 +03:00
Valiantsin DzerakhandClaude Opus 5.5 30456bc0a2 Merge task/recown: the recorder thread owns the parts it records from begin to submit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:07:53 +03:00
Valiantsin DzerakhandClaude Opus 5.5 218d251950 Merge task/gpuwrite: regions the GPU writes are never frozen read-only (#788, #802)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:07:53 +03:00
Valiantsin DzerakhandClaude Opus 5.5 895d202cce Let the recorder thread begin, end and submit the parts it records.
The part command buffers and their pool were used by two threads. The submitting thread still waits for the
submission, so the queue order is unchanged. TOTK_REC_END=0 brings the old split back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:07:45 +03:00
Valiantsin DzerakhandClaude Opus 5.5 9a81e3e2f1 Keep regions the GPU writes from being frozen read-only, and thaw a frozen one before a GPU write.
Storage-buffer stores, copies and fills land in imported guest memory without a fault or a write-watch bit, so a
region only the GPU wrote looked idle and was frozen while the GPU kept writing it. LAS Recomp never changes the
protection of imported memory because of NVIDIA. A possible cause of the NVIDIA "write invalid" device faults
(#788, #802), not proven.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:07:38 +03:00
Luxury 057a2d751c Account for Tk screen size rounding in the DPI test 2026-11-05 18:37:07 -05:00
Claude 0be3472fe0 Describe ub_overlay in docs/settings.md, which tests/settings_doc_check.py now asks of every name in known[]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BspNcezsiV8zT8wcnXrrME
2026-11-05 22:21:07 +00:00
Claude 53c916730a Merge remote-tracking branch 'origin/main' into pr/ub-overlay 2026-11-05 22:20:18 +00:00
ProSepandClaude Sonnet 5.5 0db730e800 Draw a 16:9 picture with bars when the HUD layout for the game resolution's shape is missing, and copy every shaped overlay into the build
A game resolution that is not 16:9 widened the camera while the HUD stayed at 16:9 stretched across the picture whenever romfs-patches-<w>x<h> was not next to romfs-index.bin, which is always so for a build from source. resolution.c now falls back to the largest 16:9 size inside the asked one and keeps the camera aspect patch off, logging the command that makes the layout. build_game.py copies every romfs-patches* folder with a manifest.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 22:44:39 +01:00
Valiantsin Dzerakh 0ae47a5782 Up version 0.3.11 v0.3.11 2026-11-05 19:59:52 +03:00
Valiantsin DzerakhandClaude Opus 5.5 4cd6b83716 Merge task/prwave10: PR #767 (game resolution follows the display's shape) and PR #625 (frame queue, off by default)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 19:56:56 +03:00
Valiantsin DzerakhandClaude Opus 5.5 7f04a104a3 Merge PR #625: a frame queue that frees a window image at its display time, off by default (ipavlin98)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 19:54:21 +03:00
Valiantsin DzerakhandClaude Opus 5.5 71831771cd Merge PR #767: default the game resolution to the display's shape (Wintego)
Keep 1920x1080 as the default with prompts = xbox or pc: the setup builds those prompts' folders for 16:9 only, so the
shaped default would have swapped the chosen prompts for the Switch ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 19:53:57 +03:00
Valiantsin Dzerakh 48c014843b Merge task/prwave9: PR #776 (size table entries of mods' pack members) and PR #650 (movie shape on outputs that are not 16:9) 2026-11-05 19:34:44 +03:00
Valiantsin Dzerakh 0d5719858e Merge PR #650: keep the shape of the pre-rendered movies on outputs that are not 16:9 (ProSep)
# Conflicts:
#	runtime/cfg.c
2026-11-05 19:32:18 +03:00
Valiantsin Dzerakh e4538aebc8 Merge PR #776: raise the size table entries of files inside mods' packs (ericdallo) 2026-11-05 19:32:07 +03:00
Valiantsin DzerakhandClaude Opus 5.5 a27e85b673 Merge task/mouse (1.2.1): the direct mouse camera on game 1.2.1 (issue #751)
All 72 1.4.3 sites mapped to 1.2.1 main (82 patch lines), the values that differ in a per-version MouseLayout. The
player state (ability, bow in hand) is not known on 1.2.1 yet, so mouse_aim_scale has no effect there, and the menu
pointer and map cursor stay 1.4.3 only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:48:19 +03:00
Valiantsin DzerakhandClaude Opus 5.5 61d0075039 Give game 1.2.1 the direct mouse camera of 1.4.3 (issue #751)
The 72 mouse_direct sites of patches-v143.txt mapped to the 1.2.1 main by enclosing function, each original word
checked: the camera input update, free orbit, Ultrahand and the 16 player camera modes. 1.2.1 keeps some values in
other registers and stack slots (camera input x in s11, orbit angles at sp+0x3c/0x40, Ultrahand x in s9), so the
hooks read a per-version MouseLayout; the 1.4.3 values and behaviour are unchanged.

Where 1.2.1 adds a turn in a shared helper, the degrees go to the store of the helper's result (Aiming's pitch
target, new ROLE_BASE_STORE) or to the turn it is given (Horse yaw). Wakeboard, ShieldSurfing and Tail read the stick
twice (REPEAT on the first read), the dialogue cameras' angle loads are pre-indexed (mov -> add, as ClimbObj).
The player state (ability, bow in hand) is not known on 1.2.1 and reads as not found.

tests/mouse_direct_check.py runs the hooks with both layouts and checks each load-site table against its patch file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:47:26 +03:00