Fix crashes and improve asset handling in PC port - #15
Merged
Conversation
build.py now copies assets/sounds.json into dist/<version>/ so the m4a backend's exe-dir probe finds it in release tarballs (the audio fix in 9c6b036 expected the file to ship there but nothing was producing it). Forward-port viruappu-mosaic.patch onto current upstream ViruaPPU: drop the affine-BG hunk (renderer was rewritten upstream and no longer has that path) and add the missing <stdlib.h> include so getenv() compiles. Re-enable the patch in xmake.lua now that it applies cleanly again.
Two related issues. (1) sub_0804AFB0 / GetRoomProperty on PC only checked the room-callback function table for property indices 4..7, returning NULL when a room actually stores DATA there (e.g. Minish Forest lily pads index a rail array via type2 in 4..7 in some rooms). Fall back to a packed ROM read when no callback is registered. (2) build.py packed assets from build/pc/assets/, but asset_extractor writes to build/<version>/assets/, so dist/<version>/ tarballs were missing whole subtrees (including data_080D5360/ which holds the lily-pad rail data). Point build.py at the right source path. With both fixes Minish Forest lily pads move correctly when shrunk; this is a progression unblocker.
Real GBA's MPlayStart was effectively a no-op when the engine re-issued the same song on the same player; agbplay's m4aMPlayStart restarts playback unconditionally and that's audible as the BGM resetting on every room transition (Link's house was the regression report). Track the currently-playing song per player and skip the restart when the same BGM (songId 1..99) is requested. Keep SFX (>=100) on the unconditional path — they legitimately re-trigger the same id. StopPlayer clears the tracking so the next start always restarts.
The USA GBA original queues BGM_BEANSTALK ("Climbing the Beanstalk") in
sub_StateChange_CastleGarden_Main and sub_StateChange_HyruleField_OutsideCastle
during the prologue. EU was patched to queue BGM_FESTIVAL_APPROACH —
the toned-down Picori Festival theme — which is the canonical music
for that sequence. Follow EU on PC_PORT.
The PC port had stripped the GBA-original 'gMessage.state & MESSAGE_ACTIVE' check from EnterRoomTextboxManager_Main, so the location-name banner created on room enter would linger after a script raised a fresh dialog (e.g. Zelda calling Link from off-screen as you leave the house). The result was a stray boxed name centered on screen for ~2 seconds before the real dialog took over off to the side. Restore the original kill condition. Also drop the chatty per-frame [MANAGER] dispatch and [AREA] textbox prints — they were diagnostics left in from earlier debugging and dominated stderr.
GBA-original animates the "becoming big" cutscene as giant → normal (player affine sx=1152 → 0x100, sprite displays 4.5x → 1x). User expectation for the port is the conventional small → big direction — matches what's intuitive for emerging from minish form. PC_PORT path now starts unk_80/unk_84 at 0x80 (sprite displays 0.5x — small) and grows by 5/frame up to 0x100 (1x), with a clamp so we don't overshoot into giant. GBA build keeps the original direction. Code paths: src/player.c sub_08073F4C (init scale) and sub_08074018 (per-frame grow).
After Festari/Gentari shows the local map and the player dismisses it, the room behind the dialog was rendering as solid black on the port. Two issues in the Subtask_FadeOut → RestoreGameTask → sub_0801AE44 path: 1. sub_0807C4F8 (scroll_flags&1 alternate path) only iterated ROM-packed 12-byte MapDataDefinition entries, but on the asset-loader path (gArea.pCurrentRoomInfo)->map points to native 24-byte structs whose dest is a void* holding a GBA address. The matcher missed them and gMapDataBottomSpecial stayed zeroed, so UpdateScrollVram filled the BG buffer with zeros. 2. Even with the buffer correctly filled, no one raised bg.updated=1 after RestoreGameTask, so sub_08016CA8 never copied the buffer to VRAM and the screen base kept the stale map tilemap. Force the buffer→VRAM copy in RestoreGameTask.
After the Festari/Gentari fix taught the codebase to detect packed-ROM vs native-heap MapDataDefinition format, the same hazard exists in three other places that iterate room property data: each assumes GBA-packed layout and silently misreads native 24-byte (or 16-byte) structs that the asset loader provides. - houseDoorExterior: 12-byte packed → 16-byte native unk_DoorProperty (low half of 8-byte u8* unk8 holds the GBA script address) - lavaPlatform: 16-byte packed → 24-byte native LavaPlatformEntry (low half of 8-byte Entity* unk_78 holds the GBA rail address) - delayedEntityLoadManager: 16-byte packed → 24-byte native NPCStruct (low half of 8-byte u16* script holds the GBA script address) Each site now detects packed-ROM via gRomData range check and falls back to native-struct iteration on the asset-loader path. The script pointer in each native struct is treated as a real heap pointer when ≥ 0x10000000, and as a sign-extended GBA address otherwise.
This reverts commit 01948f1.
This reverts commit f1f92d7.
… iterators"" This reverts commit 3b438c6.
The GBA-original HouseDoorExterior spawner sets entity->context only
when it has a non-NULL script pointer that resolves successfully:
if (p_unk8) {
u16* script = (u16*)Port_ResolveRomData(p_unk8);
if (script) entity->context = StartCutscene(...);
}
On real hardware the script address always resolved, so Type3 (a
fully-scripted door) could safely call ExecuteScript on context. On
the port, Port_ResolveRomData can return NULL for door scripts whose
GBA address isn't backed by the loaded ROM image, leaving the spawned
Type3 entity with context=NULL. The next frame then segfaults inside
ExecuteScript dereferencing the NULL context.
Reproduced entering Hyrule Field room 5 (Lon Lon Ranch). Skip the
script invocation under PC_PORT instead of crashing.
Fresh checkouts crashed when running the asset processor in extract mode because directory_iterator threw on a missing assets/ folder. Create it first so the iteration yields zero entries on a clean tree.
…ssets Two gaps in the extract→runtime pipeline meant fresh release tarballs were missing whole asset subtrees (most user-visibly data_080D5360/), which manifests as silent feature breakage: lily pads stationary, town doors not spawning their cutscene entities, etc. 1. assets_extractor.hpp: extract_area_tables skipped property indices 4..7 entirely because they're usually room callback functions. But some rooms (lily pads, doorway data tables) put data pointers there. Now treat them as data when the ROM offset matches an indexed asset entry, and add a final sweep that extracts every entry the index knows about which the specialized passes didn't already produce. 2. port_asset_pipeline.cpp: CopyRuntimePassthroughAssets had a fixed directory whitelist that excluded all data_* subtrees. Add the 12 data_<addr>/ directories explicitly so BuildRuntimeAssets carries them from assets_src/ to assets/. Verified by extracting from a clean tree: data_080D5360/ now contains all 260 files byte-identical to the previously-curated dist/USA/assets/ tree.
Bumps version to 0.1.2 and documents the fixes that landed since 0.1.1: - Doorway crash in HyruleField/LonLonRanch (HouseDoorExterior_Type3 NULL-context segfault) - Post-map-hint black BG (sub_0807C4F8 native-struct iteration + RestoreGameTask buffer→VRAM force-flush) - BGM resets per room, prologue BGM mismatch, stray location textbox during Zelda call, magic-stump grow direction - Asset extraction now produces data_*/ subtrees that release tarballs were silently missing — caused lily pads / town doors / etc. to break Known issues section enumerates what's still deferred (rolling-barrel affine-DMA, festival facades, doorway glitches, Minish Woods fog).
Reported in issue #2 (Kwagsyre, Kubuntu 25.10): user launched tmc_pc via a custom dynamic loader so they could supply their own glibc 2.43 (\$HOME/glibc-2.43/lib/ld-linux-x86-64.so.2 ./tmc_pc). In that scenario /proc/self/exe resolves to the dynamic loader, not tmc_pc, so the asset-loader's exe-dir lookup hunts \$HOME/glibc-2.43/lib/assets/... finds nothing, and the first gfx-group load aborts. FindEditableAssetsRoot / FindRuntimeAssetsRoot now consult an ordered list (exe-dir first, then cwd) so a working assets/ next to where the user invoked tmc_pc still resolves. Filename-only ROM lookups already fell back to cwd in port_rom.c. Also: replace the cryptic "ROM fallback is disabled for gfx groups on PC" abort message with a clear "run ./asset_extractor first" hint so users who haven't extracted yet know what to do.
port_hdma_step_line conflated DEST_FIXED (don't increment, don't reload) with DEST_RELOAD (do increment within each transfer, reload between transfers). For 8×u16 affine-matrix HBlank-DMA used by the rolling-barrel scene, this meant all 8 values overwrote BG2PA on each scanline — only the last word stuck and BG2PB..Y_H stayed at whatever the immediate-DMA prologue left them. Result: flat affine matrix per scanline, brown-bands render in Deepwood Shrine rolling barrel. Split DEST_FIXED / DEST_INC / DEST_RELOAD into three explicit modes: - FIXED: no increment, no reload - INC: increment within transfer, keep advanced address after - RELOAD: increment within transfer, rewind to dest_orig after Verified on the rolling-barrel scene: cylindrical interior renders correctly. Applies to any scene that registers HBlank-DMA with DEST_RELOAD on a multi-register window (BG2PA..Y_H, BG3PA..Y_H, WIN0H..1V).
LoadGfxGroup entries that target GBA EWRAM addresses (e.g. gfx group 30 → 0x02002F00 for gMapDataTopSpecial, used by Minish Paths to populate the foreground vegetation BG3 tilemap) were going through MemCopy's port_resolve_addr, which translates GBA EWRAM addresses to gEwram[] slots. But the port keeps several large GBA-EWRAM globals as heap-allocated stand-in arrays *outside* gEwram (gMapDataTopSpecial, gMapDataBottomSpecial, gMapTop, gMapBottom). Result: bytes landed in gEwram[0x2F00] but the game read from the heap-allocated symbol, which stayed empty — so BG3 in Minish Village entrance had no tilemap data and the green leafy vegetation didn't render. Port_ResolveEwramPtr already knows about these special addresses (it's used by LoadMapData / sub_0807C4F8). Route EWRAM-destined gfx-group copies through it so they land in the actual symbols the game reads. Reported in issue #3 (Minish Village entrance — Faulty Textures).
Two stacked bugs caused "You got X items!" textboxes (and rupee counts, kinstone counts, minigame timers, every dialog with a number variable) to render either zero or garbage on the port: 1. DecToHex (src/common.c): the GBA-original abuses Div (SWI 0x06) which returns the quotient in r0 and the remainder in r1 as a side effect, then reads the global register `r1` between successive Div calls to extract subsequent digits. On the port, Div is just plain `num / denom` with no register side effect, so `r1` stayed uninitialized — every digit past the most-significant was garbage. Replaced with a clean BCD encoder under PC_PORT. 2. gUnk_08107BE0 buf-source array (src/message.c): on GBA, gTextRender lives at EWRAM 0x02022780, so the variable-substitution buffer pointers gUnk_020227E8 / F0 / F8 / 0x02022800 happen to alias the rupees / field_0x14 / field_0x18 / field_0x1c byte-buffer slots inside gTextRender's _66/_77 fields (which sub_08056FBC populates). On the port, gTextRender is heap-allocated, so those raw GBA addresses point at unrelated gEwram[] bytes that nothing writes. Variable substitution read uninitialized bytes → no number displayed. Initialize the array at runtime to point inside gTextRender. Reported in issue #7 (Deepwood Shrine — Game Reports 0 Mysterious Shells Obtained).
Issue #10. The GBA-original keeps a 4-pointer table at ROM 0x080B2BD8 mapping each shadow type to sprite-frame data. The pointers stored in that table are IWRAM addresses (0x0300xxxx) into the runtime-copied overlay region, populated by InitOverlays via MemCopy(sub_080B197C, ram_sub_080B197C, RAMFUNCS_END - sub_080B197C). The PC port deliberately skips that IWRAM overlay copy (see src/main.c InitOverlays under PC_PORT), so the IWRAM pointers in the table point at uninitialized gIwram[] — every deferred shadow draw bailed at `if (frameData == NULL) continue;` and characters had no shadow underneath them. Load the table from ROM on first use and translate each IWRAM pointer to its ROM source via the linker-derived delta (0x080B2248 ↔ 0x03005FBC → 0x050AC28C, USA region). Direct-ROM pointer fallback for safety. EU/JP may need a different delta — flagged with a TODO; testers should retry on those builds.
Three issues bundled because the boss test paths overlap. 1. Drop shadows (issue #10): ProcessDeferredList bailed because sShadowFrameTable was never loaded — the GBA-original populates it via the IWRAM overlay copy that the PC port deliberately skips. Load the table directly from ROM at first use, with an IWRAM↔ROM offset translation derived from the linker symbol ram_sub_080B2248 (0x03005FBC ↔ 0x080B2248, USA region). 2. Deepwood boss heart container + warp not spawning (issue #12): gUnk_additional_a_DeepwoodShrineBoss_Main was a 64-byte port_linked_stubs.c stub left zeroed. The C code calls LoadRoomEntityList(&...) on it after the boss dies, so without real data the rewards never appeared. Copy the 48 bytes from ROM 0xDF94C in Port_InitDataStubs. 3. Deepwood barrel cobweb fall-through (player blocker reported by tester): GBA-original gates the fall on barrel angle in a 13- step window (unk_20 in 0x118..0x124), which is too tight for PC controls — testers hold Down for several seconds and never land the angle past the 0xF0 rest stop. Drop the angle gate on PC; once the cobweb (LV1TARU_OPEN) is removed and the player stands in the hole position with z=0, fall.
- Add explicit linking for fmt 12 (header-only mode was breaking scaninc, asset_processor, etc.) - Copy baserom.gba into build/pc/ so runtime asset_extractor succeeds - Tested on Kubuntu 25.04 (glibc 2.41)
WarpPointEntity::flag and HeartContainerEntity::flag2 sat at GBA-style offset 0x86 from struct base, which on x86-64 lands at 0xAE — but RegisterRoomEntity writes the spritePtr high-half to GenericEntity's field_0x86 at 0xB2 (the void*-aligned union forces a 4-byte gap before 0x84). The flag fields therefore read junk, so warps never armed and heart containers never spawned. Insert 4-byte PC-only padding before the 0x84 fields so they line up with what RegisterRoomEntity writes. Drop the FourElements port workaround that double-spawned the rewards now that the original flow works. Fixes the boss-reward chain in 999sian#12 properly (cd99dd4 only populated the data table).
The previous commit added per-struct PC padding to WarpPointEntity and HeartContainerEntity to dodge a void*-alignment mismatch. Same bug hits any entity subclass whose `flag` (or other) field sits at GBA offset 0x84/0x86 — GentariCurtain (Minish Village elder, #14), button, bossDoor, lockedDoor, lightDoor, jailBars, mask, fireplace, ~25 more. Fix once at the source: in RegisterRoomEntity, after writing the spritePtr halves to GenericEntity::cutsceneBeh/field_0x86 (PC 0xB0/2), also mirror them to PC 0xAC/AE — the natural-aligned position used by subclass structs without the void* trick. Bytes 0xAC-0xAF live in GenericEntity's pre-union padding so cutscene entities are unaffected (StartCutscene's later 8-byte scriptContext write at 0xB0 still wins). Skip ENEMY because Enemy.child grew from 4→8 bytes on x86-64, which already shifts subclass fields up by +4 — they land at 0xB2 and match GE_FIELD natively. Reverts the per-struct padding from 293a211 since this catches it universally.
Previous workflow checked out a private assets repo to copy baserom.gba into the workspace and ran 'python build.py --usa' which extracts assets at build time. Forks without ASSETS_REPO/ASSETS_TOKEN secrets fail at the checkout step (which is why every release run from this fork shows red). Release tarballs only ship tmc_pc + asset_extractor + sounds.json — the user runs asset_extractor against their own baserom on their own machine. So the build doesn't actually need a ROM, just 'xmake build tmc_pc' and 'xmake build asset_extractor'. Switch to that and drop the private-assets steps. sounds.json is tracked in repo at assets/sounds.json so it's available to the runner without extraction.
The 'Build tmc_pc' step needed assets/map_offsets.h and assets/gfx_offsets.h which are generated by ROM extraction. CI checkout doesn't run extraction (no ROM), so the build always failed at compile time. The two headers are stable per-region per-game-version (they're just ROM offset constants for asset blobs), so commit them under a .gitignore exception. EU is dropped from the matrix because we don't ship an EU tarball or have an EU ROM in CI to regenerate its offsets.
fix: build on Ubuntu 25.04+ with system fmt 12.x
Rolls back the partial-widescreen attempt that exposed cols 240..255 of the engine's 32-tile BG buffer. Cols 30..31 are a scroll buffer that the engine updates only during camera motion — on title, file-select, and cutscene-transition screens they hold stale tile data, plus engine-parked off-screen sprites live at OAM x>=240, so the right-edge strip showed visible glitches (stale palettes, duplicate sprites). Now: ViruaPPU clips BG and OAM at col 240 unconditionally, and port_ppu.cpp uniformly stretches the 240-px frame across any widescreen_width. Default widescreen_width=240 (clean GBA-native). Real widescreen requires a 64-tile (sa2-style BGCNT_TXT512x256) BG buffer and engine-side tile-load extension — Phase 2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Once the m4a buffer-sizing fix (7d36792) stopped the audio init from crashing early at startup, the synth thread started running its full workload — and the previously-set SINC resampler (~10x cost of LINEAR per voice) became a measurable per-frame CPU hit on top of the DSP post-process chain (biquad LP + mid/side widen + tanh clip). Drop to LINEAR. Audible difference vs SINC on chiptune material at 48 kHz output is small; CPU saving is large. Easy to flip back if a high-end audio pass is wanted. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…SINC
Splits virtuappu_mode1_render_frame into two passes:
1. Sequential — for each of 160 scanlines, fire the HDMA pre-line
callback (BG_VOFS water FX, BLDY fades, etc. mutate the live
IO register file) and snapshot post-callback IO state into a
per-line array.
2. Parallel via OpenMP — each thread points its thread-local
`virtuappu_mode1_io_thread_override` at its line's snapshot,
then renders BG / OBJ / composite normally. The single-threaded
read16 path falls through when the override is NULL, so all
non-render IO reads behave as before.
OpenMP was already wired into the build (`-fopenmp`, USE_OPENMP),
so this just lights up the cores. On a 4-core CPU the per-frame
PPU cost drops to roughly the line render / NUM_THREADS plus the
sequential snapshot pass (~1 µs/line) — Amdahl-bounded by the
synth thread and the snapshot pass, but still a visible win.
Also restores the agbplay resampler to SINC: the LINEAR drop earlier
in the session was a stopgap before the parallel-render path
existed; with PPU off the main thread the synth's CPU share is
no longer the bottleneck.
Patch infrastructure: viruappu-widescreen.patch absorbs the
parallel-render hunks (same file, overlapping context) and the
xmake marker is bumped to `io_thread_override` so it reapplies
cleanly on a fresh submodule reset.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nd flag 0x400 All eight takeover helpers (King Daltus, Minister Potho, Vaati, Zelda Stone, and six guards) end their per-NPC scripts with the same two-instruction tail: WaitForSyncFlag 0x00000400 DoPostScriptAction 0x0006 ; delete entity / destroy script ctx so the cutscene's exit relies on someone broadcasting sync flag 0x400. Neither the parent orchestrator (script_CutsceneOrchestratorTakeover) nor the in-castle child orchestrator (script_CutsceneOrchestratorTakeoverCutscene) ever issues SetSyncFlag 0x400. On GBA this presumably came from an implicit broadcast tied to the subtask transition that ends the cutscene; the C decomp's post-action handler at HandlePostScriptActions case 1 << 0x06 (delete entity) doesn't include any flag broadcast, and grep across the codebase turned up no SetSyncFlag 0x400 in the takeover script set. Caught with a [sync] tripwire diag on JesterWizard's bug-report save: King(id=36)/Vaati(id=39 type=1)/Zelda(id=40) all spinning forever on WaitForSyncFlag flag=0x400 cur=0x20. Set it at the takeover subtask's end-of-cutscene gate (sub_08053BBC, when CheckRoomFlag(0) sees the orchestrator's SetRoomFlag 0). Every waiting helper falls through to DoPostScriptAction 0x06 and exits cleanly. Scoped under PC_PORT so the GBA build behaviour is untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merge 7c10b08 (-X theirs) left an unbalanced #ifdef PC_PORT block: both sides' PC_PORT branches got included with a stray #else between them, leaving the outer guard unterminated. Drop the duplicate inner PC_PORT block; keep the single-branch resolution that uses gUnk_08128190.dest for the EWRAM-resolved scan.
A migration block introduced via the matheo merge converted any config.json frame_time_ns == 16666667 (the canonical 60-FPS lock) back to 0 (uncapped) at every startup, with a SaveConfig() so the overwrite persisted. Users who picked 60 FPS via the in-game port- settings menu had it silently undone the next launch — visible as the window-title FPS counter sitting well above 60 even with the preset at "60 FPS lock", and as a perceived fast-forward feel. Drop the migration. If users want uncapped, they can pick that in the port-settings menu; the deadline-based pacer in port_bios.c already honours frame_time_ns=0 as "no cap". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eo merge The matheo "Sync PC port from 999sian release branch" (646762e) brought stale snapshots of port_debug_menu.cpp, port_ppu.cpp/.h, port_bios.c, port_linked_stubs.c, and data_stubs_autogen.c — the 3-way merge in 7c10b08 silently dropped fixes/integrations that were already on master. Audit found 7 things missing in the post-merge tree: * zeldaret#54 boomerang dizzy-stars FX never clears (b9ce2fb): GetNextFunction's alive-dispatch lost the `confusedTime != 0 -> 4` branch, so GenericConfused stopped running on stunned enemies, the FX_STARS parent stayed alive, and stars persisted forever. * 14 per-room entity-list stubs (1212584): Re-add the PerRoomEntityListInit entries for TempleOfDroplets BigOcto, PalaceOfWinds GyorgTornado, Romio's Purple House, Borlov entrance, Percy, HouseInteriors1 Library, HyruleCastle, CoF boss, etc. These are LoadRoomEntityList sources that crash when read from zeroed BSS (covers reported issues zeldaret#55, zeldaret#64, zeldaret#68, zeldaret#70). * F8 debug-menu pages (077fed9, 668a936): Restore "Extra equip slots" cycle page (X/Y/L2/R2 assignments) and the "CRT filter" cycle entry under Display settings. Rename the upscale-mode entry from "Filter" to "Upscale" to disambiguate. * port_ppu.cpp present-pipeline losses: - Port_Filter_Apply call in raw/linear branches + auto-bump internal scale to >=4x when filter is active (CRT pattern needs >=3 px per phosphor cell to read). - virtuappu_mode1_render_affine_obj_overlay call in BuildScaledFrame so affine OAM (Vaati tornado, world-shrink, every spinning enemy) keeps sub-pixel accuracy at internal-render-scale. - Port_SoftSlots_RenderOverlay call after Port_DebugMenu_Render so the `\` config overlay during pause actually draws. - MODE1_GBA_WIDTH/HEIGHT consistency in BuildScaledFrame and EnsureScaledTexture (preserves widescreen Phase 1). * port_ppu.h: re-export Port_PPU_CycleFilter / Port_PPU_FilterName. * port_bios.c: also drop GBA input + tick the soft-slot pause counter while the soft-slot config overlay is open, not just for the F8 menu. Verified all other named fixes (#5, #22, #24, #25, zeldaret#34-36, zeldaret#39, zeldaret#42/43, zeldaret#46, zeldaret#51-53, zeldaret#57, zeldaret#61, zeldaret#65, zeldaret#67, zeldaret#69, zeldaret#72, zeldaret#76, zeldaret#78, zeldaret#91, zeldaret#93, plus WarpPoint/HC alignment via the universal spritePtr mirror, talon wrong-address, gleerok packed pointers, LikeLike/rupee-like soft-locks, Vaati apparate, FastTravel, GetNextFunction h=0 dispatch) are still present and were not regressed by the merge. Skipped: stderr-ring buffer in bug-report bundles (354324f) and addr2line shell-out (8739b84) — pure diagnostic features, not bug fixes; can be restored in a follow-up if wanted. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diagnostic fprintf hooks in ScriptCommand_SetSyncFlag / ScriptCommand_ClearSyncFlag / ScriptCommand_WaitForSyncFlag / ScriptCommand_WaitForSyncFlagAndClear (PC_PORT only) emit the flag mask, current syncFlags, and the (kind, id, type) of the entity running the script. WAIT/WAIT&CLR de-dup consecutive identical log lines so a stuck cutscene doesn't spam stderr. Used to chase the zeldaret#93 Vaati takeover softlock (already fixed in e2427e6); leaving the tripwires in for the next time we hit a cutscene-end gate that never opens. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ment watchdog The earlier zeldaret#93 fix (e2427e6) just broadcast sync flag 0x400 from the takeover-overlay end gate (sub_08053BBC). That helped the helpers stuck on `WaitForSyncFlag 0x400` *if* the cutscene ever reached that gate, but on JesterWizard's bug-report save the cutscene never gets that far — it stalls almost immediately after the player triggers it. Diagnosis. script_CutsceneOrchestratorTakeoverCutscene runs as a CUTSCENE_ORCHESTRATOR object inside the takeover Aux-Cutscene subtask. Its job is to broadcast a sequenced wave of sync flags (0x010, 0x004, 0x010, ..., 0x040, 0x001, 0x004, 0x200, 0x004, then SetRoomFlag 0) waking King / Vaati / Zelda / Minister / Guards in order. On the PC port this entity disappears after running its first two Wait commands (heartbeat hooks confirm the entity is no longer called by ObjectUpdate; my UnlinkEntity hook never fires for it; the post-stall snapshot shows it absent from gEntityLists). Cause is still unclear — neither the priority-elevation done in the parent takeover script (`Call sub_0807FBC4` -> RequestPriorityOverPlayer) nor a DeleteEntity / DeleteAllEntities path explains the state we see. Investigation continues. Workaround. sub_08053BBC (the takeover overlay-2 dispatcher) now runs a small state machine that broadcasts the same flag sequence the orchestrator script would, paced ~30-60 frames per step so the helpers' inter-step animations have time to play. Once the sequence finishes, it sets RoomFlag 0 itself; the existing branch then broadcasts 0x400 (belt-and-suspenders for any helper that reached its final WaitForSyncFlag 0x400 before the watchdog got there) and exits the subtask. Verified on JesterWizard's save: cutscene completes, player ends up in Hyrule Field post-takeover with the correct local flag (SOUGEN_08_TORITSUKI) set. Side effect: the cutscene's between-step camera moves race a bit faster than they would on hardware (~12s total vs. ~20s). That's a visible cosmetic regression vs. the GBA, but it's miles better than hanging forever. If the orchestrator entity ever stops disappearing, the watchdog stays harmless — it only kicks in while CheckRoomFlag(0) is still false, which is the same gate the original cutscene gates on. Also adds a NULL-pointer guard in CleanUpObjPalettes (src/color.c:308) for the iteration that walks gEntityLists[i].first->next->next->...; multiple helpers self-deleting in the same frame can leave the list with a stale node whose `next` is NULL before ClearAllDeletedEntities runs, and dereferencing it segfaults at offset 0x10 (the kind field). The guard skips the corrupted node; cleanup for the rest of the list finishes normally on the next frame. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dio flag Two follow-ups to the orchestrator-replacement watchdog from c5dca19: * Halve the per-step delays (60 -> 30 frames, 30 -> 15) so the cutscene finishes in ~6s instead of ~12s. The user testing reports were cutting out before the 12s sequence completed; 6s is enough time for helpers to unwind through their WAIT&CLR / SET pairs at PC speed while not keeping the user staring at a half-frozen screen. Known cosmetic issue not addressed here: the cutscene's camera moves and fades are driven by the orchestrator entity itself, not by the helpers — and that entity is the one that disappears, so the visuals during the sequence are glitchy and at one of the orchestrator's internal `SetFade5` (fade-to-black) gates the screen stays black until the watchdog forces RoomFlag 0. The cutscene COMPLETES (subtask exits, player ends in Hyrule Field with the right local flag set) but it doesn't *play* properly. Restoring proper visuals needs the underlying orchestrator-disappearance bug fixed. * Restore `--no-audio` CLI flag handling that was already declared in port_main.c's argv loop but disconnected from the audio init call (probably lost in the matheo merge). Useful as a workaround for the pre-existing intermittent agbplay SequenceReader.cpp:49 SIGSEGV while testing other things. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Getting the sword from the Blacksmith plays the proper animation, shrink/grow is completely fixed, and the shield from Zelda being given from Hyrule no longer floats where Link once stood. Also, added debug scaffolding to try to fix a pre-existing cloud deform bug.
Hardcoded files, git + auth path, and other conflicts have been resolved so universal compilation is successful
- Removed the F9 key bug report capture functionality from the BIOS. - Deleted the port_bugreport.cpp and port_bugreport_state.c files as they are no longer needed. - Introduced Port_IsAreaTablePtrFromAssets function to validate area table pointers from assets. - Updated Port_IsAreaTablePtrReadable to utilize the new validation function. - Adjusted room property list retrieval to ensure valid area table pointers. - Cleaned up script execution context checks to remove redundant corruption checks. - Updated xmake.lua to remove references to the deleted bug report files and adjust build flags accordingly.
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # libs/tmc-Android-Experimental # port/port_m4a_backend.cpp # xmake.lua
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced touch control handling in `port_touch_controls.cpp` with support for joystick and D-pad schemes. - Added functions to manage touch events, rendering, and settings requests. - Implemented a bootstrap launcher in `port_launcher_bootstrap.cpp` to initialize the launcher UI. - Updated `port_runtime_config.h` to include new touch scheme configurations and related functions. - Modified `xmake.lua` to include the new `guilite` dependency and launcher source files. - Enhanced the touch control rendering logic to accommodate different input schemes and visual feedback.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.