What's Changed
Highlight - Massively Improved Stability
Bug A — never-freed scene arena. Every scene transition allocated a fresh 16 MB arena via libc malloc but never freed the previous one (syTaskmanStartTask, taskman.c:1322). Two consequences:
- ~16 MB/scene leak — hundreds of MB of mapped-but-dead memory in a long classic-mode session.
- Far worse: old arenas stayed mapped and readable for the whole process lifetime. A dangling pointer from a prior scene resolved to plausible-looking data — old GBI commands, old vertex blobs, old reloc-token contents — instead of segfaulting at the dangling site. Bugs that should have been one-line fixes were instead presenting as random GBI-walker SIGSEGVs ten frames downstream of the actual cause.
Bug B — 8-bit reloc-token generation byte. The PORT replaces N64 segmented pointers with a 32-bit "reloc token" decoded against a flat lookup table. The table is reset on every scene transition (portRelocResetPointerTable, RelocPointerTable.cpp:130) and the high byte of every token carries a generation that's bumped on each reset to invalidate stale tokens. With 8 bits + the reserved-NULL convention starting at 0x80, only 128 generations existed before wrap. A long classic-mode session (round → CSS → round → results → ...) hits 10–20 scene transitions per attempt; 128 generations was exhausted in well under an hour of play. After wrap, a stale token's generation byte coincidentally re-matched the current one, the decoder accepted it, and returned whatever pointer happened to live at that table index now — typically a different fighter's data of the same shape. Silent wrong-pointer resolution, indistinguishable from a successful lookup.
Bug C — long-lived BSS structures holding raw GObj pointers. Several static / BSS arrays held GObj* (and figatree heap pointers) across scene transitions and were never cleared:
- gSCManager{1PGame,VS,Transfer}BattleState.players[].fighter_gobj — read across scenes by ftshadow.c:107, sc1pgame.c:825, sc1pbonusstage.c:846-848, itmball.c:392, ftcomputer.c:5623, controller.c:208.
- sMNVSResultsFighterGObjs[] + sMNVSResultsFigatreeHeaps[] — VS results screen.
- sMN1PContinueFighterGObj + sMN1PContinueFigatreeHeap — 1P continue prompt.
- Seven primary GObj* fields the decomp's mnPlayersVSInitPlayer reset overlooked: cursor, puck, type_button, name_emblem_gobj, panel_doors, panel, type, plus figatree_heap. (The decomp clears the secondary GObj fields but missed these primary ones.)
Why this release should massively improve stability
Fixing Bug A turns an entire class of dangling host pointer reads from silent data corruption into a hard SIGSEGV at the read site, any further bugs should be easily to see and patch.
Fixing Bug B extends safety from under an hour of play before silent token aliasing on wrap to days of continuous play
Fixing Bug C cleans four enumerated long-lived structures, the crash that previously hid inside the GBI walker now lands cleanly at mnVSResultsSetPlayerTagPosition:1043 and we can fix it as soon as there's a trace.
In summary: any dangling-pointer related bug now produces a clean stack pointing directly at the offending file and line instead of a random-looking crash dozens of frames further downstream.
Additional Fixes
- Fix NRage analog accuracy: run formula at firmware int16 scale by @JRickey in #116
- Fix Windows launch crash since v0.5: noexcept LocateFile (issue #58) by @JRickey in #118
Full Changelog: v0.7.1-beta-hotfix...v0.7.2-beta-hotfix