summaryrefslogtreecommitdiff
path: root/soh/src/code
AgeCommit message (Collapse)Author
11 daysJabu fish cutscene skip: immediately transition (#7159)Philip Dubé
This avoids awkward pause, also prevents recapturing fish Also cleanup RSK_JABU_OPEN
13 daysReopen the OPUS decoder when a note moves to another sample (#7137)David Racine
The decoder cached on a note was keyed on nothing, so a note reused for a different streamed sample carried on decoding the previous track. Audible as the wrong custom music: the sequence and soundfont the audio editor reports are correct, only the samples reaching the mixer are not. Reproduced on the game-start cutscene chain with a streamed music pack in 4 of 6 runs; 0 of 6 after. Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: serprex <159546+serprex@users.noreply.github.com>
2026-08-30Honour the loop end when reading streamed music (#7129)David Racine
Streamed samples were read a whole block at a time regardless of where the loop ended, so playback ran past it and only then jumped back. The seam therefore landed at a random offset up to a block late instead of where the sample asked for it, which is why a loop that is clean in an editor pops in game. Fixes #5780. Claude-Session: https://claude.ai/code/session_011Ex3z29fQzPEZgwH4EA641 Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-23Restore the realId assignment in AudioLoad_AsyncLoadInner (#7105)David Racine
The function declares realId and then indexes with it thirteen times - the load-status tables, AudioLoad_SearchCaches, the table entry it reads size and address from, every cache allocation, and the status write at the end - but nothing assigns it. It has read an uninitialised local since "Custom Sequences" (#2066) dropped the assignment in 2022. Restoring the line puts back the value the rest of the function expects. For SEQUENCE_TABLE and FONT_TABLE, AudioLoad_GetRealTableIndex returns the id unchanged, so this is only a correctness fix in practice: the paths that reach this function today go through the sequence script's async load command, which is rare enough that the garbage index has not been tied to any report.
2026-08-22Drop the seqLoadStatus bounds checks made redundant by #6932 (#7100)David Racine
#6917 guarded the three seqLoadStatus accessors against sequenceMapSize because the array was allocated at exactly that size, so a custom sequence id past it read and wrote off the end. #6932 sized the array to sequenceMapSize + 0xF to match sequenceMap, which covers the whole id space rather than rejecting the ids outside it, and also protects the writers those guards never saw: AudioHeap_AllocCached and AudioHeap_PopCache index seqLoadStatus directly. The guards are now not just redundant but bounded wrong - they treat the ids in [sequenceMapSize, sequenceMapSize + 0xF) as absent from a table that now has room for them. Nothing breaks today because every entry starts at 5, so AudioLoad_IsSeqLoadComplete answers true regardless and AudioLoad_SetSeqLoadStatus already declines to overwrite a 5 - but once the heap cache path moves such an entry off 5, the guard blocks an update that should happen. Reverting them restores the three functions to their decompiled form. The sizing from #6932 and the id check in AudioLoad_SyncInitSeqPlayerInternal remain the actual protection.
2026-08-17Hookify masks / timeless equipment (#7088)Philip Dubé
2026-08-17Add a Skip Warp Cutscenes enhancement (#7059)David Racine
Warp song cutscenes were skipped for randomizer players whether they wanted it or not: Demo_Kankyo cut the departure animation short from a hardcoded IS_RANDO branch, and entrance rando cleared respawnFlag so the arrival never played. There was no way to get the vanilla warp back, and no way for a vanilla playthrough to skip it. Drop both and put the behavior behind a Skip Warp Cutscenes toggle, defaulting on in randomizer so existing rando warps are unchanged. It kills the departure actor as it spawns and puts the arrival spawn mode back to IDLE, which covers both halves of the warp. Entrance rando's destination override moves off Demo_Kankyo's update onto a new OnWarpSongLeave hook fired from Environment_WarpSongLeave. That is where every warp path -- the cutscene, the skip toggle, and the spawn failure fallback -- commits its destination, so the override no longer depends on the departure actor being alive to see it, and a warp song shuffled onto a grotto return keeps its grotto respawn. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17Enemy rando, let enemies air walk over voidout floor in clear rooms (#7005)djevangelia
Behind a setting Add timed rooms + Fire Temple modifications
2026-08-14Decomp, three audio functions (#7069)djevangelia
2026-08-09fix(audio): bound audio-heap cache tables (SIGSEGV with large custom music ↵Pedro Nascimento
packs) (#6932) Root cause of three identical field crashes (audio thread, opcode fetch through a pointer with its low 32 bits overwritten, seconds after scene transitions): AudioHeap_AllocPermanent writes permanentCache[index] with index = permanentPool.count and no bound against the 32-entry array. In SoH every soundfont sync-load is forced permanent, and custom sequences whose SEQ.xml says CachePolicy="Temporary" ALSO allocate permanently (the factory stores the LUS enum where CACHE_TEMPORARY == 0, while AudioLoad_SyncLoad's switch reads 0 with the ROM convention 'permanent'). A pack with ~60 streamed customs plus vanilla fonts pushes count past 32 within a session, after which each allocation sprays a {ptr, size, tableType/id} triplet at 24-byte stride through gAudioContext - entry[135]'s ptr field lands exactly on seqPlayers[0].scriptState.pc and entry[156] on seqPlayers[1]'s (both verified against the crash-dump registers). - permanentCache raised 32 -> 512 (12 KB) and AllocPermanent refuses allocations past the array instead of corrupting memory. - Same unbounded-index disease fixed in the three sibling writers: AllocCached's persistent path (16-entry array; CACHE_EITHER degrades to temporary, hard persistent requests fail cleanly), AllocPersistentSampleCacheEntry, AllocTemporarySampleCacheEntry. - seqLoadStatus malloc sized for the full id space (sequenceMapSize + 0xF) matching sequenceMap; custom ids above sequenceMapSize previously overflowed the allocation by up to 15 bytes. Upstream SoH bugs, not branch-introduced - this branch's many-track packs merely made the overflow reachable in normal play. Standalone upstreamable fix.
2026-08-09FixFlexDrops (#7047)Philip Dubé
2026-08-09Fix heap corruption due to skybox code using GameState as PlayState (#7045)Philip Dubé
Also corrects clearing skybox context before Skybox_Setup
2026-08-08Hookify Skeleton Unregisters (#6988)Jameriquiah
Co-authored-by: serprex <159546+serprex@users.noreply.github.com>
2026-08-08Decomp, some camera names (#7043)djevangelia
2026-08-08Savestates, add `sEffectContext` (#7042)djevangelia
2026-08-05Fix Gold Skulltula tokens overwriting the Bow inventory slot (#7021)David Racine
gItemSlots and sExtraItemBases only cover the item IDs that live in the inventory, but Item_Give and Item_CheckObtainability index them with any item ID. Reading past gItemSlots lands on gUpgradeShifts, so INV_CONTENT(ITEM_SKULL_TOKEN) resolved to the Bow slot and stored the token there, permanently corrupting the save. Route both through a bounds-checked Item_GetSlot that reports SLOT_NONE for items that have no slot, and skip the inventory store in that case. That read is also undefined behaviour, which link-time optimization is free to exploit: with it present clang dropped the ITEM_SKULL_TOKEN branch and the ITEM_MEDALLION_WATER horse fixup from Item_Give entirely, so tokens were never counted either. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-03fix: seqLoadStatus OOB reads/writes for custom SAF sequences (#6917)David Racine
Custom SAF sequence IDs can exceed sequenceMapSize, causing out-of-bounds reads/writes on the seqLoadStatus byte array (sized exactly sequenceMapSize). This is the direct cause of intermittent battle music failure with BGM packs (issue #5706): on the second encounter, AudioLoad_SyncLoadSeq reads a garbage value from heap memory past seqLoadStatus[] and may find 1 (loading in progress), causing it to return NULL early — the sequence player is never initialized and no battle music plays. Symmetric fix to the fontLoadStatus guards in PR #6916: - AudioLoad_IsSeqLoadComplete: return true for OOB seqIds (custom SAF sequences are resource-manager-backed, not in the async-load status table) - AudioLoad_SetSeqLoadStatus: skip update for seqId >= sequenceMapSize - AudioLoad_SyncLoadSeq: skip the in-progress check for OOB seqIds Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-31Decomp, naming (OnePointCS, itemAction, blure, wall/floor types) (#7007)djevangelia
2026-07-24Constant-size texture scroll display lists via G_SETTILESIZE_LERP (#6902)Philip Dubé
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
2026-07-24Hookify Lost Woods Ocarina game (#6976)Jordan Longstaff
2026-07-22Savestates, more AudioOcarina serialization (#6954)djevangelia
2026-07-22Fix problems with Zelda's Letter & Weird Egg hatching (#6962)Philip Dubé
2026-07-19Shuffle Zelda's Letter (#6938)Philip Dubé
Removes RSK_SKIP_CHILD_ZELDA & RSK_KAK_GATE, these are managed by RSK_SHUFFLE_ZELDAS_LETTER & RSK_STARTING_ZELDAS_LETTER & RSK_SHUFFLE_WEIRD_EGG
2026-07-19Bugfix, make CC invisible Link equips invisible (#6926)djevangelia
2026-07-19Decomp, update AudioOcarina (code_800EC960.c) (#6941)djevangelia
2026-07-13fix(audio): bounds-check fontId to stop OOB crash with large SAF packs (#6916)David Racine
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>
2026-07-13Don't point free cam at sky coming out of crawlspace (#6920)Philip Dubé
2026-07-12Add save state wiring for Barinade, Bongo Bongo, & Morpha (#6914)Philip Dubé
Rename various variables across codebase to match decomp, many had been renamed when exposed for previous save state mechanism
2026-07-12wire decomp static savestates with macros (#6904)Philip Dubé
2026-07-12GIM Restoration (#6865)Amber Burton
All edge cases for bottle combinations and replacement/filling mirrors the real game, as well we produce the compass text, and does not render the item exactly as the original game does. (I would have preferred rendering the item since its only cosmetic but I couldn't find a way to do it). This also swaps the table redirect stuff for using the direct item id's which is a lot more clear and does not substitute anything for 'good enough' and covers all the edge case ids that have been documented. This is purely a cosmetic change to present the visual of the item without affecting the cutscene making any tricks for GIM still work and just looks more polished. This supplies effects of ALL game versions (including MZX build) as well as providing text table. To note: we still can crash with GIM even when returning item None EVEN at least with returning Kokiri Tunic (I can't really figure out why) and there are a few items in the table that use extra data that I don't know how to implement here just yet but the info is in the docs under "Variable". In the case of disabling the gim restoration, the game would still crash. This change adds a text id protection to prevent crashing, as well prevents invalid items from crashing directly, and also makes it so the game will no longer crash when having GIM disabled in the menu. Co-authored-by: serprex <159546+serprex@users.noreply.github.com>
2026-07-12Decomp pull, some `z_player` and global changes (#6908)djevangelia
2026-07-11Hookify text speed options (#6881)Jordan Longstaff
2026-07-11Maintenance, edits and addition to Lake Hylia water control (#6884)djevangelia
2026-07-09Decomp, update `z_en_holl.c` (#6890)djevangelia
2026-07-08Bugfix, child Hookshot first person in Hylia lab (#6847)djevangelia
2026-07-08Bugfix, rando Domain to Lake entry air swim (#6873)djevangelia
2026-07-07pull decomp changes: actor functions, z_en_horse.c (#6877)Philip Dubé
2026-07-04Decouple GBK from LACS (#5838)Philip Dubé
Triforce Pieces can now be tokens for bridge or ganon's soul. & can be tokens for multiple rewards Wincon can now be arbitrary conditions Ganon's Soul (removed from existing boss soul options) can now be arbitrary conditions Co-authored-by: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com>
2026-07-04Ivan: Move ActorDB registration into IvanCoop.cpp (#6815)Shishu the Dragon
2026-06-30Hookifying Various Cheats and FixVineFall (#6827)Chris
2026-06-29Sync's Ganons Trials and Fixes Softlock (#6828)Amber Burton
Previous co op softlock fix introduced a possible trial softlock making barrier never dissappear. This not only ensures that softlock cant happen, it syncs the trial flags in real time and allows all cutscenes to finish playing to properly remove the barrier even if the beams are physically visible in your game.
2026-06-27Better Octave Drop logic (#6796)jdperos
2026-06-27Cleanup unused includes & remove remaining LUS umbrella includes (#6813)Tim Schneeberger
2026-06-24No FMA (#6811)Philip Dubé
2026-06-24fix: free look continues from forced view when leaving a fixed camera ↵David Racine
(#4953) (#6808) When a scene-forced/fixed camera (e.g. the Spirit Temple boulder-room alcoves, CAM_SET_PREREND_FIXED / Camera_Fixed3) drives the view, the Free Look angles in play->camX/camY are left untouched while manualCamera stays set. On exit, Camera_Free resumed from those stale pre-alcove angles, so the camera snapped/reversed instead of following the player out. This does NOT change the forced-camera behavior: the alcove still clamps exactly as the game intends. It only fixes the hand-off back to Free Look: when Camera_Free resumes after another camera function drove the previous frame (detected via a frame-number gap), the free-look yaw/pitch are re-seeded from the camera's current orientation so the view continues from where it was left. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22Custom Bottle Contents (#6780)OtherBlue
2026-06-19fix: free look releases the door peek camera (#6756)David Racine
* fix(camera): let free look release the door peek camera After walking through a door, the door camera (CAM_SET_DOORC) held the view and only handed control back once the player moved or pressed a button, so the right stick did nothing until then. With free look the camera appeared frozen after every door. Treat right-stick movement as a release condition too, using the same stick threshold as free-look activation. * refactor(camera): move door-cam free-look release to a VB_SHOULD hook Reimplements the door peek camera free-look release as a vanilla-behavior hook instead of inline logic in z_camera.c, keeping the decomp file close to upstream. - Add VB_RELEASE_DOORC_CAMERA wrapping the existing Camera_Special9 release condition; the vanilla button/xzSpeed expression is left untouched. - Move the right-stick / free-look threshold logic into a new enhancement, FreeLookDoorCamRelease.cpp, registered with COND_VB_SHOULD and gated on FreeLook.Enabled so the hook only exists while Free Look is on. Behavior is unchanged from the previous fix; this only relocates the logic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18feat(camera): option for free look to follow the default camera distance (#6757)David Racine
Free Look pinned the camera to the fixed "Camera Distance" setting, so it never pulled in or out the way the vanilla camera does for the current situation. Add an opt-in "Follow Default Camera Distance" setting (FreeLook.UseGameDistance) that uses the game's per-mode default distance instead. The fixed distance slider is hidden while it is enabled. Closes #4050 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18Redo Fishing Pole Gi Model (#6759)nickel246
Replaces the gi model for the randomizer Fishing Pole to be more consistent with the rest of the game's gi models
2026-06-18fix(audio): replace stray custom-sequence printf with a debug log (#6752)David Racine
The custom-sequence registration loop printed each assigned seqNum to stdout via a bare printf, spamming the console with context-free numbers on every launch. Convert it to LUSLOG_DEBUG and include the sequence name so it is hidden by default yet useful for diagnosing music-pack loading.