diff --git a/.github/release-notes.md b/.github/release-notes.md index 7d12d6ff..ee5b5d23 100644 --- a/.github/release-notes.md +++ b/.github/release-notes.md @@ -1,7 +1,7 @@ ## GoldenEye 007 PC Port

- ~32 s gameplay montage from live play sessions (no audio track)

@@ -15,6 +15,34 @@ > [README's Roadmap section](https://github.com/jkdansereau/goldeneye-pc-port#roadmap) > for where this is headed. +### What's new since v0.2.1 + +Hotfix batch from Steam Deck/Linux user playtest feedback on v0.2.1 — two +crash fixes plus two QoL asks: + +- **Fixed: intermittent SIGSEGV on Steam Deck/Linux when destroying objects** + (terminals, exploding grenades) (D255). Root cause: `vtxstore_fix_refs` + read a live object's model pointer through a mistyped 4-byte-enum field + instead of the real pointer field, truncating it to garbage on 64-bit + builds — harmless on the original 32-bit N64, fatal on PC. Verified live + on real Steam Deck hardware, held through Facility (repeated terminal + destruction) and Caverns' radio-objective terminals with zero crashes. +- **Fixed: a second, separate Steam Deck/Linux crash during explosion-heavy + combat** (D285) — the audio thread's pool-exhaustion scan read the active- + sound list without the lock its writer (`sndSetupSound`) already takes, + so a burst of near-simultaneous SFX (an explosion, plus debris/metal) + could race a concurrent list mutation. Locked to match the existing + write-side guard. Live-tested on real Steam Deck hardware with dense, + sustained overlapping-explosion combat (dual grenade launchers plus + rocket-launcher-cheat guards) — no crash. +- **Front-end menu navigation (main menu, file select, mission-select map) + now uses the LEFT analog stick**, matching the F10 options overlay and + modern controller conventions, instead of requiring the right stick + (D282). +- **Added a "Quit to desktop" row to the F10 options overlay** — previously + the only way to exit was Alt+F4 / closing the window, a real gap on + Steam Deck / controller-only / fullscreen setups (D293). + ### What's new since v0.2.0 Small hotfix batch from user playtest feedback on v0.2.0: @@ -150,12 +178,6 @@ Small hotfix batch from user playtest feedback on v0.2.0: terminal destruction) and through Caverns' radio-objective terminals with zero crashes. Please still report any other Deck/Linux-specific faults. -- **Steam Deck / gamepad: the right analog stick currently navigates the - main menu, file select, and mission-select map** — not the left stick. - This matches the N64 default but is unintuitive on a modern controller; - moving front-end menu navigation to the left stick is a planned QoL fix, - not done in this release. - ### Downloads | File | Platform | diff --git a/README.md b/README.md index 93926484..13d0201f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ in a dedicated `port/` layer, following the architecture of the [Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark), the same Rare "Indy" engine family, one hardware generation apart. -**v0.2.1** is out for Windows and Linux (including Steam Deck, where the +**v0.2.2** is out for Windows and Linux (including Steam Deck, where the Linux bundle sideloads as-is) and runs the full campaign at a steady 60 fps with known rough edges ([Status](#status)). Free to download, build on and modify (you bring the ROM). @@ -53,7 +53,7 @@ account of what worked and what didn't. Both bundles contain **no ROM and no game assets**: you supply your own (see [Requirements](#requirements)), which keeps the release legal to -distribute. Earlier builds: v0.2.0 and v0.1.0 alpha, same page. You can also build it +distribute. Earlier builds: v0.2.1, v0.2.0 and v0.1.0 alpha, same page. You can also build it yourself; see [Building](#building). ### Quick start @@ -67,24 +67,26 @@ included or distributed. Then: 2. Make a `data/` folder next to the executable and drop the ROM in as `ge007.ntsc-final.z64`. 3. Launch the executable from that folder. The first run takes a few extra seconds: it detects the ROM and generates the derived asset folders once (no Python or other tooling needed). -Read the [Status](#status) caveats first: v0.2.1 has known rough edges, +Read the [Status](#status) caveats first: v0.2.2 has known rough edges, listed plainly there. ## Status -**v0.2.1 - playable, with known rough edges.** The full single-player +**v0.2.2 - playable, with known rough edges.** The full single-player campaign is completable end to end (all 21 missions, Agent difficulty, playtested), at a steady 60 fps; all 21 solo missions load, render and run crash-free, verified on Windows, Linux and real Steam Deck hardware. Feedback is very welcome. **Working:** boot sequence and front end (menu → mission select → briefing → -start); all 21 solo missions load, render and are crash-free (full campaign +start), front-end menu navigation on the left stick to match the F10 overlay +(D282); all 21 solo missions load, render and are crash-free (full campaign playtested end to end at Agent difficulty); steady 60 fps (software RSP off the presentation critical path); full audio: in-level music and SFX; keyboard + mouse (click-to-lock, proportional aim mode) and a modern dual-stick controller layout; file-backed saves; faithful N64 progression by default (F10 → *All unlocked* opens every level, 007 mode and the full cheat menu); F10 in-game -options overlay (resolution, frame cap, MSAA, filtering, FOV, sensitivity); +options overlay (resolution, frame cap, MSAA, filtering, FOV, sensitivity, +quit to desktop); Windows and Linux. **Known issues:** @@ -117,16 +119,15 @@ Windows and Linux. at least one save written** (complete a level normally first, e.g. Dam on Agent). Enabling it on a brand-new install with no prior save can still cause silent audio and odd right-mouse-aim behavior (D257/D259/D281). -- **Linux / Steam Deck:** an intermittent SIGSEGV remains, with a reliable - repro found this release — Facility's computer terminals (the ones you - activate to open a door for level progression) consistently crash the - game on activation (D255; seen on Linux generally, not Deck-hardware - specific). Combat-related crashes reported earlier (Bunker, Frigate) may - be the same bug via a different trigger; current builds capture full - faulting registers in `ge007.crash.log`. -- Steam Deck / gamepad: front-end menu navigation (main menu, file select, - mission-select map) currently requires the right analog stick, not the - left (D282) — a planned QoL fix, not done in this release. +- ~~Linux / Steam Deck: intermittent SIGSEGV when destroying objects + (terminals, exploding grenades)~~ **FIXED (D255)** — a mistyped 4-byte-enum + field truncated a 64-bit pointer; verified live on real Steam Deck + hardware. A second, separate Steam Deck/Linux crash during + explosion-heavy combat is also fixed (D285, an unlocked audio-thread + list read racing a concurrent write) — live-tested on real Steam Deck + hardware with sustained, dense overlapping-explosion combat, no crash. + Please still report any remaining Deck/Linux crashes; current builds + capture full faulting registers in `ge007.crash.log`. - Assorted further cosmetic defects are tracked in [`docs/dev/GRAPHICS-BACKLOG.md`](docs/dev/GRAPHICS-BACKLOG.md). - No macOS or ARM support; no controller rebinding UI. @@ -230,7 +231,7 @@ code with this one. | **How** | Decompilation-based source port: human-reconstructed C, compiled for the host; game logic runs as written | Static binary recompilation: the shipped machine code is auto-translated to C; no source-level understanding | | **Lineage** | [GoldenEye 007 decompilation](https://github.com/n64decomp/007) + [Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark) engine family | Xbox 360 "…Recompiled" static-recompilation family | | **Renderer** | Software RSP → OpenGL | Hardware (Vulkan) | -| **Status** | v0.2.1 public release; full campaign playable at 60 fps (see [Status](#status)) | Playable full game with online multiplayer | +| **Status** | v0.2.2 public release; full campaign playable at 60 fps (see [Status](#status)) | Playable full game with online multiplayer | | **Why it exists** | To run the *original* N64 game from source, and as a [case study in AI-agent collaboration](#background) on a hard low-level codebase | To get a playable PC release of the remaster | They answer a different question: how to get the *remaster* onto PC by diff --git a/docs/dev/findings-index.csv b/docs/dev/findings-index.csv index a1244847..79d39dad 100644 --- a/docs/dev/findings-index.csv +++ b/docs/dev/findings-index.csv @@ -150,16 +150,16 @@ D251,FIXED,F10 options overlay QoL pass:,"FIXED (port-only, port/src/optionsover D252,?,"Particle effects cycle through a rainbow palette (M-124, user playtest of the v0.2.0-pre candidate).", D253,FIXED,Facility (and any level with a FORCECROUCH/LADDER linked special tile) SIGSEGV on Linux/Steam Deck —,FIXED — Deck-verified: D254,FIXED,Linux crash handler destroyed its own logs:,FIXED — field-verified. -D255,FIXED,"Facility firefight SIGSEGV on Steam Deck (v0.2.0-pre CI bundle, D253 fix confirmed working —",FIXED — 32-bit pointer truncation in vtxstore_fix_refs (ChrRecord.chrflags mistyped alias); verified live on real Steam Deck hardware. +D255,?,"Facility firefight SIGSEGV on Steam Deck (v0.2.0-pre CI bundle, D253 fix confirmed working —", D256,FIXED,Saves (and config) silently failed to persist on Linux whenever the game was not launched from the directory containing data/ —,FIXED (path half) — save-flow detail still owed from the user. D257,FIXED,New Game.AllUnlocked option (F10; default flipped OFF for v0.2.0 —,FIXED — verified by user playtest (PR #79 merged); default flipped OFF for v0.2.0 (D259). -D259,FIXED,Game.AllUnlocked (D257) breaks audio on a fresh save:,FIXED in v0.2.1 — the deferred fix was applied: +D259,FIXED,Game.AllUnlocked (D257) breaks audio on a fresh save:,FIXED in v0.2.1 —… D260,FIXED,v0.2.1 (user request):,"FIXED — build green; one-line branch swap, trivially reviewable." D261,FIXED,v0.2.1 (user request:,FIXED — feel-check received; W/S sensitivity follow-up logged above. D262,FIXED,v0.2.1 (user report):,"FIXED (primary cause, D264) —" D264,FIXED,"D262's root cause (ABI/layout class, cf.","FIXED — build green, probes removed; visual confirmation pending." -D263,RESOLVED,v0.2.1 (user report):,"RESOLVED (not a bug), but refined (v0.2.1 further user testing, 2026-09-15) —" +D263,RESOLVED,v0.2.1 (user report):,"RESOLVED (not a bug), but refined (v0.2.1 further user testing, 2026-09-15) —…" D265,?,"D236 investigation (port-layer, port/fast3d/gfx_pc.cpp):",PARKED — reverted to baseline; evidence + suspect list above. D258,OPEN,PAL/JP asset conversion is broken at the source-data level —,"OPEN — repair path verified, not applied (out of v0.2.0 scope)." -D285,FIXED,"A real Steam Deck SIGSEGV caught during D255 live-testing (v0.2.1 published binary, symbolized on-device via addr2line against its own debug symbols) is a SEPA…","FIXED (M-141, src/snd.c) —" +D285,FIXED,Steam Deck SIGSEGV during D255 live-testing = SEPARATE bug:,"FIXED (M-141, src/snd.c) —" D293,FIXED,"QoL ask: no discoverable way to quit the game from the UI (M-141, Steam Deck user playtest —","FIXED (M-141) — ""Quit to desktop"" row added to the F10 overlay; build-verified Win+Linux, not yet live-confirmed.…" diff --git a/docs/dev/findings.md b/docs/dev/findings.md index 705d7729..9f1f8e30 100644 --- a/docs/dev/findings.md +++ b/docs/dev/findings.md @@ -10137,6 +10137,9 @@ do { **Do NOT conflate with D255** — different fault address, different thread, different subsystem, different code path. Both may be independently real; testing one does not rule out the other, and a fix for one will not affect the other. **Next, concrete:** (1) settle question 1 above (N64 disassembly check or accept the D4-class port-layer exception); (2) if a lock is warranted, wrap `sndHandleEvent`'s preempt-scan (and audit the rest of the function for the same gap against every other `D_800243E4` touch point in the file) in `osSetIntMask(OS_IM_NONE)`/restore, matching `sndSetupSound`'s existing pattern; (3) live-verify via gdb on a real reproduced crash, not just the static read. **M-141: FIXED, per the accepted D4-class port-layer exception; not yet live-verified.** Question 1 is settled by precedent rather than a fresh N64 disassembly read: `sndSetupSound` (the paired writer) already takes `osSetIntMask(OS_IM_NONE)`/restore completely unconditionally — **no `#ifdef PORT` at all** — around the identical `D_800243E4` list mutation, in this same file, with no N64-behavior caveat noted anywhere near it. Since `osSetIntMask` is genuine N64 API (not a port shim call added out of nowhere) and the port's own `osSetIntMask` implementation (`port/src/libultra.c`, "Interrupt mask -> global recursive lock", D147/D152) is a **process-wide recursive** critical section — safe to nest inside `alEvtqPostEvent`/`alSynSetVol` calls without deadlock risk — adding the identical lock/unlock pair around `sndHandleEvent`'s preempt-scan follows the exact same already-accepted shape as its sibling writer, unconditionally, no `#ifdef PORT` needed (matches the surrounding code's own style). Audited the rest of `sndHandleEvent` (`snd.c:263-680`) for other `D_800243E4` touch points per the open item above: **the preempt-scan is the only one** — nothing else in the function reads or writes that list. Fix: `src/snd.c`, wraps `ALSoundState *iterState = ...` through the closing `} while (limitReached && iterState != NULL);` in `OSIntMask d285Mask = osSetIntMask(OS_IM_NONE);` / `osSetIntMask(d285Mask);`. **Verified:** build green; `-level_09`/`-level_20` boot 1400+ frames each with zero crashes and zero `D152: osSetIntMask lock stuck` warnings (which would fire if this new lock ever wedged). **Not verified:** a `GE_INPUTSCRIPT`-driven rapid-fire stress test (modelled on D219/M-90's scripted-Z-pulse approach) was attempted to force the 8-voice pool exhaustion this scan requires, but the script's own parse-confirmation log line never appeared in this run's output — the scripted-input harness did not visibly activate for a reason not root-caused this session (worth a quick look next time `GE_INPUTSCRIPT` is used: confirm it still fires on current `main`/`release/v0.3.0` before trusting a "no crash" result from it as a real stress test). No live Deck/gdb reproduction attempted this session (no Deck SSH session active). Given the D4/D152 precedent's exact-shape match, confidence in the fix is HIGH; confidence that it's been exercised under real load is LOW — the honest bar met here is "correct by precedent, build/sweep-clean," not "reproduced-then-fixed." Next: an interactive session (ideally the same live Steam Deck setup as D255/M-140, explosion-heavy combat, e.g. Facility/Frigate) should confirm the crash no longer reproduces. + +**Live-verified, 2026-09-16, real Steam Deck hardware, v0.2.2 hotfix build.** User ran Archives with dual grenade launchers plus guards spawned with the rocket-launcher cheat — sustained, dense overlapping-explosion combat, exactly the 8-voice-pool-exhaustion / SFX-burst scenario this fix targets — with no crash. This is user-reported (not gdb-attached or `D_800243E4`-state-captured at the moment of stress), so it does not pin the exact race window the way a live-fault capture would, but it is a real, on-hardware, high-load stress test of the fix's actual trigger condition, not just the build/sweep-clean bar noted above. Confidence upgraded from "correct by precedent, unexercised under real load" to "correct by precedent, exercised under real load with no failure." + ## D286 — M-140: user-confirmed, real (not system-side) ~8s frame freeze on Caverns, Steam Deck, same live session as D255/D285 — self-recovered, not a crash; case not yet root-caused **Context.** Caught live during the same Deck SSH session used to fix D255: the game's own hang watchdog (`portHeartbeatCheck`, `port/src/libultra.c`) fired once, logging `kernel heartbeat: no frame rendered for 8008866 us (frames=46404); state:` (unit bug in the log line, see below — the raw value is *microseconds*, printed with a `ms` suffix and no `/1000`; fixed this session, `port/src/libultra.c`) followed by a per-thread/per-queue state dump and a `crashDumpThreads` backtrace of the watchdog thread itself (`portTickThread` → `portHeartbeatCheck` → `crashDumpThreads`, `port/src/libultra.c:266/315`, `port/src/crash.c:458` — this is the watchdog reporting on *itself*, a diagnostic dump, not a fault). **User confirmed by direct observation: this was a real, visible freeze** (not a display/system hiccup — the Deck's own WiFi had one unrelated sleep/wake event earlier in the session, so system-side causes were a live alternative hypothesis, now ruled out by the user's own eyes on the screen), happening "pretty early" in a Caverns playthrough, not tied to an explosion or terminal (ruling out D255/D285 as the cause — this is a third, distinct issue). **Outcome: self-recovered.** VI-post/frame-render logging resumed normally within the same log stream immediately after the watchdog fired, and the session continued (the user later closed the game normally, no crash log, all 5 game threads still `started=1`/`exited=0` at the time of the dump — nothing was permanently deadlocked). This is a genuine ~8s *stall*, not a hang or a crash.