Adds torch-migration/PHASE0.md with the full gate detail: what each gate's
variable is, the driver source, exact commands, cost, and exit criteria.
Two gates the plan was missing:
- Gate C (Release build) - the harness 14/14 is a Debug measurement; CI
and releases build -O3.
- Gate A2 (two extractions in one process) - free once the driver exists,
retires the re-entrancy risk offline instead of by hand in the game.
Also: gates run full-tree + check.sh rather than test_assets.py (which
hardcodes the torch path and copies a filtered yml subset), 19 ROM dumps
not 17, and libgfxd being USE_STANDALONE-only is called out as the real
hazard in Gate A.
- Name the actual repo (briaguya0/soh-asset-yml); it holds yml only, and is
edited directly rather than regenerated. zapd_to_torch.py is a one-shot
conversion, not an ongoing workflow, since nobody edits the ZAPD XMLs once
ZAPD is gone.
- Phase 5 is pure deletion. Generator inputs are already preserved by the
harness's shipwright@95d8f7e submodule pin and by git history, so nothing
needs snapshotting or moving out of Shipwright.
- Clarify soh/CMakeLists.txt:107-109 as a configure-soh-directly fallback with
nothing left to fall back to.
- Downgrade the extraction wall-clock risk; perf work landed in Torch#219.
Co-Authored-By: Claude <noreply@anthropic.com>
Rewrite Gfx_TexScrollEx / Gfx_TwoTexScrollEx / Gfx_TwoTexScrollEnvColorEx to
emit one command per tile instead of one baked tile size per interpolated frame,
so texture DL memory no longer scales with InterpolationFPS
RegisterBetterSave registered its VB_LOAD_SAVE_MENU and VB_DRAW_SAVE_MENU
hooks unconditionally, and hardcoded the save/continue text overrides to
`true`, so the feature applied regardless of the enable checkbox and
toggling it off did nothing. CVAR_BETTERSAVE_VALUE was defined but never
read.
Gate all five hooks on CVAR_BETTERSAVE_VALUE (COND_VB_SHOULD for the two
vanilla-behavior hooks, the condition arg for the three OnOpenText hooks).
RegisterShipInitFunc already re-runs RegisterBetterSave when CVAR_BETTERSAVE
changes, so the COND_* macros unregister the hooks when it is off and
re-register them when it is on.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Allow player to try opening doors while climbing. Player can't open anything if a door doesn't offer it, so it's ok to try. Handle doors don't change player y position (player walks in the air), so manually lower it.
Increase y height limit for doors to offer open from 15.0f/20.0f to 50.0f (normal door height). (For shutter doors height could be individualized depending on shutter door type in the future.)
Make climbing up animation play even for sloped ledges. The animation/action breaks because game thinks player is not on ground. So, at the end of Player_ProcessSceneCollision, if player is in climbing up action, manually set BGCHECKFLAG_GROUND.
Adds an option for a Better Save Menu that, after saving, allows you to effectively soft-reset the current save (either return to spawn or reset to the dungeon entrance), and additionally lets you reset to spawn specifcally, even if you are in a dungeon. This allows for escaping from the rare entrance-rando related softlock that can happen.
Journal ranking of not-yet-obtainable major items.
The Journal ranks item hints by item category, but the rank lookup called
Context::GetFinalGIEntry with checkObtainability = true. For any hinted item
that isn't currently obtainable, that helper substitutes a blue rupee, so
genuine major items (e.g. Anju's Lens of Truth while adult) were categorized
as junk and sorted below Pieces of Heart and Gold Skulltula Tokens.
Pass checkObtainability = false so hints rank by the true placed item's value
regardless of current reachability. Ice-trap disguises still rank as their
cover item (handled by the separate overrides path in GetFinalGIEntry), and
Mysterious Shuffle still disables the ranking.
Follow-up fix to the in-game Hint Tracker feature.
Add found-item handling to the Hint Tracker Journal.
Once every location an item hint points at has been collected, the hint is
"found": it sinks to the bottom of its group, renders dimmed with a tick
prefix, and can be removed entirely via a new "Hide Found Items" toggle. A
"Found (collected)" colour picker sets the dim colour.
Only item and item-area hints in the Journal are affected; Way of the Hero,
Foolish and area hints are untouched, and the Locations view is unchanged.
Found state is derived from each location's collection status
(ItemLocation::HasObtained), so no new save data is introduced.
Make Hint Tracker settings searchable, matching the Check Tracker.
The Check Tracker registers its checkbox settings as searchable menu widgets
(WidgetInfo + AddSearchWidget); the Hint Tracker only did so for its colours
and window type, leaving every checkbox reachable only from the dedicated
settings window. Convert the checkboxes (Enable Dragging, Only Enable While
Paused, Expand/Collapse Buttons, Search Input, Hint Totals, Hide Found Items)
to the same searchable widget pattern. The Font Size slider stays inline, as
the Check Tracker leaves its own font slider inline too.
Items group out into the seven categories. The tier collapse functions are replaced
by a single label lookup in ItemCategoryRank order, and the type-priority
key scaling grows from 4 to 8 slots to fit the extra groups.
Category labels reuse the established translations from the hint text
tables. Mysterious Shuffle still keeps the single "Items" group.
If Ruto enters Bigocto's room after she has already been abducted, the room behaves weird due to actor functions. Randomizer respawns Ruto after abduction, so this can become a problem.
The easiest solution is probably to just not let player open doors to Bigocto room while carrying Ruto after abduction.
This fix makes shutter doors in randomizer when offering player to open the door - check scene, abduction flag, if door is transition actor index 21 or 3, held actor, and if held actor is Ruto.
Looks like this: https://www.youtube.com/watch?v=2Siq2Z41Pqo
The shutter door in decomp and thus this fix uses macros that are missing here, I copied all of them to the corresponding place in actor.h as they are very useful for actor params and will be added anyway when/if code is synced with decomp.
AudioLoad_IsFontLoadComplete had a stub `return true` that bypassed all
load-status checks, masking an out-of-bounds write: for large SAF packs
(many custom sequences) SetFontLoadStatus indexed fontLoadStatus[] with
fontId values larger than the fontMapSize-sized array, causing heap
corruption and semi-random crashes.
Remove the stub. Add a (size_t)fontId >= fontMapSize guard in both the
check and the setter: out-of-range IDs (custom SAF sequences that carry
no associated soundfont) are treated as "loaded" in the check and
silently skipped in the write, matching prior observable behavior while
eliminating the OOB access.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A new dockable tracker window (Randomizer menu, alongside the other
trackers) that records every hint the player has been shown and
presents them in two tabs:
- Locations: every hint location grouped by area, with hint text
masked as "???" until the stone or NPC has actually been read.
Auto-scrolls to the current area on scene transitions.
- Journal: only hints the player has already read, grouped by hint
type with the most valuable first. Way of the Hero and Foolish
entries render as compact area lines in configurable colors
defaulting to the in-game textbox palette; item hints are ordered
by the same adjusted item category that drives chest appearance,
so ice trap disguises rank as their cover item, and Mysterious
Shuffle disables the ranking.
The design is strictly spoiler-free: the tracker only ever shows what
the player has been told in-game. There is no reveal option, the
Journal hides unread hints entirely (its headers show read counts
only, never totals), and requirements like Mask of Truth are
respected because detection sits on the exact message-resolution
paths that decide whether a hint is shown.
Detection: a new OnRandoHintRevealed GameInteractor hook fires from
ReadHintMessage helpers in the gossip stone and static hint message
builders whenever a hint message is resolved for display; the tracker
subscribes to it. Read state persists per save file in a new
"hintTrackerData" SaveManager section as canonical hint names (robust
against enum reordering; unknown or malformed entries are skipped on
load), with the read set mutex-guarded against the threaded save path.
The window follows the sibling trackers' conventions: BeginFloatWindows
window/floating modes with combo-button and pause gating, a two-column
settings popout matching the Check Tracker's layout (behavior settings
left, colors right), header visibility toggles, font scaling, search
filtering, and per-save scoping with a placeholder on vanilla saves.
User-facing strings go through CustomMessage with EN/DE/FR text.
Co-authored-by: meldridge <meldridge@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>