Update 2.209
8/2/2026
v2.209.0.0BETAMINOR
SeymourAug 1, 2026
Aurora × noclip: 3D battle bridge (the editor now renders the REAL game field with the edited formation)
- Discovery: noclip's
parseEncounter(bin.ts:2494) uses EXACTLY ourBattle_Filelayout (script@0x4, monster ids i16@+0xC, float32 16B positions) —0e/<id>.binis byte-identical tobtl_*.bin(hash proof: 0e/0002 == bjyt02_00). EncounterIndexBridge(FfxLib/Battle): SHA-256 battleId↔encounterId index — 614/858 battles match (azit03_00→0e/00EF, klyt00_00→0e/001E, mihn00_00→0e/002F); 244 unmatched reported honestly.Aurora3DLauncher+ "🐉 View battle in 3D (noclip)" button in Aurora Chamber: overwrites0e/<encId>.binwith the CURRENT btl (.aurora3d.bakvanilla backup, "↩️ Restore 3D" button) and opensindex.html?battle=<encId>#ffx/b<mapIndex>(mapIndex from EncounterTable battlefield&0xFF) — the noclip native PS2 render shows the edited formation/positions.- Additive noclip patch (scenes.ts
selectEncounter, ~20 lines):?battle=param forces the exact encounter (skips weight selection); dist rebuilt + refreshed in the 8769 serve-dir (verified in the served bundle). - Gates:
--filter AuroraOverlayEnrichment9/9 PASS; full suite 357/357 PASS;Aurora3DLinkLab --override azit03_00copy=True/restore=True; HTTP E2E: 8769 serves the override byte-for-byte. Doc:docs/reverse/FFX_AURORA_NOCLIP_3D_BATTLE_BRIDGE_2026-08-01.md. - Phase 2 (next): drag/camera in noclip → POST to the editor (AuroraDragBridge pattern) → write to bin → reload. Per-field visual smoke pending. ### PATCH
v2.208.0.1
v2.209.1.0BETAPATCH
SeymourAug 1, 2026
Aurora: viewers INSIDE the editor (WebView2) + RealGame/EditViewer naming + battle-preview without the game menu
- Embedded: Aurora Chamber gained a
WebView2Hostcolumn — "Renderizar EditViewer" and "🐉 Ver no RealGame (ingame)" now open INSIDE the editor (no browser); ⟳ Reload viewer button;EmbeddedReloadRequestedauto-reloads after saves. - Actions on top: fixed ActionBar (Renderizar EditViewer · Ver no RealGame · Restaurar · Salvar posições · +/- monster · Exportar âncoras) — nothing hidden in scroll anymore.
- UI renaming:
noclip→ RealGame (ingame);MapViewer→ EditViewer (texts, status, banners). - No game menu: fixed
battle-previewscene desc in the noclip FFX catalog — URL?battle=<encId>&map=<mapIndex>#ffx/battle-previewalways resolves straight to FFX (mapIndex does not need to be among the 55 cataloged); dist rebuilt + verified in the served bundle (battle-preview+get("battle")present). - Auto-sync: SaveDraggedPositions/SaveCameraShots/SaveCameraFloats/AddMonster/RemoveMonster re-apply the RealGame override + reload the viewer (saved position shows in-game without re-clicking).
- Gates: full suite 359/359 PASS; Release build 0 errors; served bundle verified. ### MINOR
v2.209.0.0
v2.209.2.0BETAPATCH
SeymourAug 1, 2026
Aurora UI/UX: clean dashboard + dedicated pop-up viewers
- Dashboard: main screen is now map selection — list with badges ([ gLTF ] [ N tex ] [ N/N submeshes ] [ STUB ] [ map-only ], tone-colored), premium dark card for the place (#16121F bg + white text), Actions in ONE place (below the card: Renderizar EditViewer · 🐉 Ver no RealGame · 💾 Salvar posições · ➕/➖ Monster · Exportar âncoras · ↩️ Restaurar) — button duplication removed.
- Pop-ups (new architecture): dedicated
AuroraViewerWindow(WebView2) for EditViewer (raw editing) and RealGame (read-only) — they do NOT interact with each other; changing map/battle in the dashboard closes all windows automatically (prevents editing monsters on the wrong map / leaks). - Sidebar overlay: the floating viewer panel became a collapsible sidebar (❮ Hide → 58px strip) — no longer blocks the 3D view.
- Huge texts → [?] with tooltip (HonestyBanner moved into the "?" button tooltip).
- Gates: full suite 360/360 PASS · Release build 0 errors ·
node --checkOK. ### PATCH
v2.209.1.0
v2.209.3.0BETAPATCH
SeymourAug 2, 2026
Custom Mix / Arena+ unblocked: lab path fixed + ArenaMultiBossLab deployed to the game + vanilla-root configured
- Lab path fix (
ArenaPlusComposePick.cppResolveLabExe): added the candidate..\data\modules\tools\ArenaMultiBossLab\ArenaMultiBossLab.exe— the project's tools pattern (data\modules\tools, where SinScaleInject lives). Before, the hook only looked inmodules\tools\...— the lab was never found → CreateProcess failed → Custom Mix never composed anything in-game. - Lab deployed to the game:
ArenaMultiBossLabbuilt (Release, 0 errors/0 warnings) and copied (exe+dll+deps+recipes) todata\modules\tools\ArenaMultiBossLab\. - Vanilla-root configured:
modules\config\arena_plus_compose_vanilla_btl.txtcreated pointing toFFX Extracted\FFX\ffx_ps2\ffx\master\jppc\battle\btl(config txts were empty before →--vanilla-root ""→ lab failed). Mod-root default OK ({gameRoot}\data\mods\...\btlexists). - v6 rollback absorbed: HEAD's dllmain is already the v5 state (DrawString
0x9016B0crash in DIFF — the new navigation will be reintroduced with IDA available). Note on the 2.207.6.0 changelog entry. - RT2
Needs Testing(Custom Mix): F7 → Arena+ → Custom Mix → pick aeons → Launch → composed battle (e.g. Bikanel + 4 Dark Aeons, battle_id bika02_01). Relaunch uses the manifest created by the 1st Launch. ### PATCH
v2.209.2.0
v2.209.4.0BETAPATCH
SeymourAug 2, 2026
SIN unblocked: SinScaleInject path fixed (data\modules\tools) + roster dir fixed + Macalania/Thunder rosters restored from git + tool deployed
- Exe path fix (
SinCurseHook.cpp):{DLL_DIR}\tools\SinScaleInject\→..\data\modules\tools\SinScaleInject\SinScaleInject.exe(project tools pattern — before, CreateProcessA failed and SIN never ran in-game). - Roster dir fix (
SinScaleInject/Program.cs): default now{gameRoot}\data\modules\tools\SinScaleInject\data\rosters(wasmodules\tools\...— one level off). - Rosters restored from git (commit
eb2e93ed):spira-sin-area-rosters/withmacalania_all/bosses/field/woods.csv+thunder_plains.csv(monster_id,role,note,allowed_presetswith UNI-001..006 allowlist) + README. - Deployed to game:
SinScaleInjectbuilt (Release, 0 errors) and copied todata\modules\tools\SinScaleInject\+ rosters todata\modules\tools\SinScaleInject\data\rosters\. - RT2
Needs Testing(SIN): area transition withsin_curse.flag→ SinScaleInject runs (logSinCurseHook SinScaleInject SUCCESS) → area monsters with scaled HP/stats (T) +[UNI]kernel names + ATEL handler in AiFile → battle. - ffx-hooks with the SIN path fix: build ready, deploy pending (game was open at commit time — deploy when closed). ### PATCH
v2.209.3.0
v2.209.5.0BETAPATCH
SeymourAug 2, 2026
Custom Mix/Arena+ boss music unblocked: heartbeat gate no longer blocks MusicHook
- The problem: MusicHook (which applies the battle-music override) was blocked by the
WaitForProbeHeartbeatgate — the ffx-probe heartbeat never rises (probe without GetDeviceState hooked) →MusicHook install skipped: ffx-probe heartbeat gate failed→ Arena+ music never played. - The music:
ARENA_PLUS_MUSIC_TRACK_DEFAULT 145 = "Challenge"(boss-battle track — all Arena+ F7 rows: Dark Aeons + Penance; override viaarena_plus_music_<row>.txt/FFXHOOKS_ARENAPLUS_MUSIC_TRACK_<N>). - Fix: the gate is now non-blocking — waits 10s for the probe (if it answers, the extra SOUNDCMD also activates) and installs MusicHook even without heartbeat (override via FFXHooksBlock + battle-entry hooks Prep/PlayTrackWithPreload/SwitchCrossfade work without the probe; only the SOUNDCMD trigger degrades — WARN in log).
- RT2
Needs Testing: Custom Mix → Launch → the composed battle should play Challenge (145) instead of the common battle theme. - Noted pending: ffx-probe heartbeat never rises (dinput8 66.560 from 07-19) — investigate why GetDeviceState isn't hooked (affects SOUNDCMD/FORCEBATTLE via probe; music no longer depends on it). ### MINOR
v2.209.4.0
v2.209.6.0BETAPATCH
SeymourAug 2, 2026
Custom Mix music without silence/leak + composed-bin restore (never overwrites canonicals forever)
- Silence/leak fix (MusicHook.cpp
MusicPlayWithPreload_Shim): with SOUNDCMD degraded (no probe heartbeat), the shim suppressed the vanilla music and relied on soundcmd to play the override → battle in silence + override leaked to the next PlayTrack (the "desired" music played on exit). Now, without soundcmd: substitutes the track and plays the vanilla (no silence, no leak); with soundcmd: keeps the lab recipe (suppress + recipe). - Composed-bin restore on the normal Custom Mix path:
ArmDeferredFileRestorewas only armed on the 781D60 (cross-map) path — the normal path (e.g. composed bika02_01) left the bin in the mod-root forever (overwriting area canonical battles). Now the normal path also arms the restore (~30s). - Boot restore (
ArenaPlus_RestorePendingComposeOnBoot): if a previous session closed before the deferred restore (~30s), the boot restores the canonical from.spiraforge.bak(readsbattle_idfrom the gameRootcompose_last.json) — the compose never stays permanent. - Build PASS + LabDeploy to Steam.
- RT2
Needs Testing: Custom Mix → Launch → composed battle with the right music (no silence) → ~30s later the canonical bin is restored → area random encounters back to normal; closing the game before 30s → next boot restores. ### PATCH
v2.209.5.0
v2.209.7.0BETAPATCH
SeymourAug 2, 2026
Custom Mix music: soundcmd callback only set when the probe is alive (no soundcmd → shim substitutes the track and plays the vanilla)
- Why the 2.209.6.0 fix wasn't enough:
g_arenaSoundCmdFnwasn't null (the dllmain setArenaPlus_MusicHookProbeSoundCmdwhen the hook installed) — it only failed at runtime (no probe heartbeat) → the shim saw the callback → used the lab path (suppress + recipe) → soundcmd failed → silence + leak persisted. - Fix: the dllmain now keeps
probeAlive = FFXHOOKS_SKIP_PROBE_WAIT || WaitForProbeHeartbeat(10000)and only sets the soundcmd callback if the probe is alive (3 install points). Probe dead → callback null → thePlayTrackWithPreloadshim substitutes the track and plays the vanilla → Challenge (145) plays in the composed battle, no silence, no leak to exit. - Idle-crash verdict (investigated in IDA via MCP 13337): the fmodex AV is pre-existing —
AsyncTask_InvokeCallbackThunk(0x691480) calls(*(this+4))(*(this+8))with this+4/this+8 = freed heap (0x10CDCDCD); the thunk pointer lives in table0xB46FA0(audio region). None of our hooks touch this path (AsyncTask/0x691480/0xB46FA0) — the AVs predate the F7. The global VEH captures and logs it (diagnostics). Fixing it = finding who frees the audio AsyncTask (separate focus). - Build PASS + LabDeploy to Steam (20:09). ### MINOR
v2.209.6.0
v2.209.8.0BETAPATCH
SeymourAug 2, 2026
Boot restore fixed (real manifest at `modules\compose_last.json`) + test composed bin restored + Custom Mix supported scenarios confirmed
- Boot restore fixed: the real manifest is written by the lab at
modules\compose_last.json(module-relative) — the boot restore only looked in the gameRoot → an interrupted session's composed bin stayed on disk. Now looks in order:modules\compose_last.json→{gameRoot}\compose_last.json→{gameRoot}\mods\Spira Reforge\arena\compose_last.json. - Disk cleanup: the test's composed
bika02_01.bin(19:37) was restored to vanilla (.spiraforge.bakfrom 09/06/2024, 24,016 bytes) — confirmed by size/timestamp. - Custom Mix supported scenarios (verified via lab --compose dry-run): bikanel (bika02_01), macalania_forest/open/open2 (mcfr00_00/mcyt00_00/mcyt00_21), remiem (kino00_00), cavern/cavern_alt (nagi05_50/24/25). Mushroom Rock is NOT a supported scenario (compose falls back to cavern — that's why the x4 "didn't open" there). x3/x4 (3-4 actors) compose perfectly on supported scenarios (dry-run proven: 4 slots, chunk2/chunk3 ok).
- Build PASS + LabDeploy to Steam. ### PATCH
v2.209.7.0