mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
Docs: public copy, site presentation, release-gate review (D533, D534)
Public-copy language pass, homepage restructure and Documentation rename, 404 page, dead-anchor and permalink fixes, release-gate sign-off, and the pre-release review fixes of the 2026-10-05 batch (probe-doc drift, build-path hygiene, verify.sh and capture safety). Refs: D533 D534
This commit is contained in:
1 parent
452fa1025a
commit
d7b9371afb
33 files changed
+982
-468
No files matched your search
+1
-1
@@ -12,7 +12,7 @@ surface is:
|
||||
|
||||
A full walkthrough of what a release actually installs on your machine, and
|
||||
what a from-source build pulls in, is in
|
||||
[`docs/security-and-fidelity-status.md`](../docs/security-and-fidelity-status.md).
|
||||
[`docs/security.md`](../docs/security.md).
|
||||
|
||||
### Why the binaries are unsigned
|
||||
|
||||
|
||||
+34
-33
@@ -16,12 +16,12 @@ Region: **NTSC-U (US) only**. See [Known issues](#known-issues).
|
||||
build was played on (e.g. "Played on Windows and Steam Deck: campaign
|
||||
spot-checks, 2-4P split-screen, a controller-only session"). -->
|
||||
|
||||
The headline is **the settings interface, rebuilt**. Both options screens are
|
||||
merged into one, laid out like the Perfect Dark PC port's menu, with plain-English
|
||||
wording, real-unit sliders and a one-line description under whichever option you
|
||||
select. Alongside it: the game's own N64 control styles as a per-seat preset,
|
||||
emulator save files that load directly, a scalable HUD overlay, and a round of
|
||||
fidelity fixes checked frame-by-frame against the N64 game.
|
||||
The headline is **one real options system**: both options
|
||||
screens merged into a single menu, laid out like the Perfect Dark PC port's,
|
||||
with the game's own N64 control styles as a per-seat preset, emulator save
|
||||
files that load directly, and a scalable HUD overlay. A round of fidelity
|
||||
fixes, checked frame-by-frame against the N64 game, rounds out the feature
|
||||
list.
|
||||
|
||||
---
|
||||
|
||||
@@ -37,15 +37,6 @@ fidelity fixes checked frame-by-frame against the N64 game.
|
||||
- **Display mode** is a dropdown; **Backspace** goes back, matching the rest of
|
||||
the game's menus (D504 follow-up).
|
||||
|
||||
### Menu wording, units and help text (D505–D507)
|
||||
|
||||
- 27 maintainer-approved wording edits across both menus: option names say what
|
||||
they do, not what the internal variable is called (D505).
|
||||
- Sliders carry **real units** — percent, frames, seconds, pixels — and their
|
||||
values are standardised across the two menus (D506).
|
||||
- Selecting an option shows a **one-line description** of it in the same menu
|
||||
(D507).
|
||||
|
||||
### Control styles: the game's own N64 layouts (D513, D516, D518)
|
||||
|
||||
- **Control style** offers **Ext** (this port's scheme, unchanged) and
|
||||
@@ -79,18 +70,6 @@ fidelity fixes checked frame-by-frame against the N64 game.
|
||||
**crosshair colour by health** — the four settings the Perfect Dark port has
|
||||
that this port was missing.
|
||||
|
||||
### Overlay controls are antialiased (D520)
|
||||
|
||||
- Slider wedges, slider markers and dropdown arrows no longer step in whole
|
||||
canvas pixels (which grew visibly at large window sizes); they are drawn
|
||||
smooth at every size.
|
||||
|
||||
### Watch menu keeps its own settings (D349, corrected)
|
||||
|
||||
- Closing the in-level **Watch** menu now saves the watch's own screen size and
|
||||
ratio, and they no longer fight the front-end **Aspect ratio** setting. The
|
||||
earlier note in the findings log was corrected.
|
||||
|
||||
---
|
||||
|
||||
## Fidelity and stability fixes
|
||||
@@ -101,13 +80,19 @@ fidelity fixes checked frame-by-frame against the N64 game.
|
||||
- **Aspect ratio:** forced ratios now letterbox/pillarbox without re-cropping the
|
||||
play area (D508); the rare gun/hand model glitch after changing ratio
|
||||
mid-level is largely fixed, a rare remainder is logged (D509).
|
||||
- **Watch menu:** closing the in-level **Watch** menu now saves the watch's own
|
||||
screen size and ratio, and they no longer fight the front-end **Aspect ratio**
|
||||
setting; the earlier note in the findings log was corrected (D349).
|
||||
- **Overlay controls:** slider wedges, slider markers and dropdown arrows no
|
||||
longer step in whole canvas pixels (which grew visibly at large window sizes);
|
||||
they are drawn smooth at every size (D520).
|
||||
- **FPS counter:** holding left/right on a Bond settings row no longer drops the
|
||||
FPS counter (D517).
|
||||
- **Build:** a fresh build directory no longer produces an untagged executable
|
||||
name (D515).
|
||||
- **Tooling:** the asset converter's argument quoting and sidecar size check are
|
||||
tightened; the CI cache actions no longer carry stale ROM paths. The golden-frame
|
||||
tooling is now non-destructive and drift-free: a verification sweep used to
|
||||
tightened; the CI cache actions no longer carry stale ROM paths. The
|
||||
reference-frame tooling is now non-destructive and drift-free: a verification sweep used to
|
||||
overwrite your own `data/ge007.ini` and leave the previous level's save file
|
||||
behind, and now pins both idempotently (your ini and save are restored whatever
|
||||
the run does); the capture helper reads its frame windows out of the gate instead
|
||||
@@ -124,6 +109,16 @@ fidelity fixes checked frame-by-frame against the N64 game.
|
||||
|
||||
---
|
||||
|
||||
## The small stuff
|
||||
|
||||
27 menu-wording edits across both menus (option names say what they do, not
|
||||
what the internal variable is called, D505); sliders carrying **real units** —
|
||||
percent, frames, seconds, pixels — standardised across the two menus (D506);
|
||||
a **one-line description** of the selected option in the same menu (D507);
|
||||
and menu spelling standardised to one convention across both menus.
|
||||
|
||||
---
|
||||
|
||||
## Known issues
|
||||
|
||||
| Issue | Impact | Workaround |
|
||||
@@ -148,10 +143,16 @@ follow-ups.
|
||||
sentence "these were merged and review-verified but not playtested live"
|
||||
in the body; never imply a full playtest. -->
|
||||
|
||||
**Golden-gate state for this release:** both platforms carry the full 21-level
|
||||
reference-frame set (63 frames each) at the same stems, and each platform's gate
|
||||
is green against its own goldens. The cross-platform spread (0.348-3.983% of
|
||||
pixels over tol 2 on the 20 non-Cuba levels, structural tier 21/21 clean) is
|
||||
**Reference-frame gate for this release:** both platforms carry the full 21-level
|
||||
reference-frame set (63 frames each) at the same stems. The Windows gate is green
|
||||
against its own goldens (21/21, three consecutive clean sweeps); on Linux the
|
||||
crash gate is green and the pixel verdict is still owed (see below). The recipe pins the run for you: the save file's
|
||||
CONTENT is pinned (the gate installs its own canonical save per level, the same
|
||||
way it pins the display ini — D529) and the PRNG seed is hard-pinned (a stray
|
||||
`GE_RSEED` in your environment warns and is ignored rather than re-seeding the
|
||||
gate — D532), so a gate run and a capture run see the same starting state. The
|
||||
cross-platform spread measured on the shipped pairs (0.380-5.120% of pixels over
|
||||
tol 2 on the 20 non-Cuba levels, structural tier 21/21 clean) is
|
||||
informational only — it is not a cross-platform pixel-parity claim, and the
|
||||
linux *pixel* gate did not run on the capture box (its GL probe fails closed
|
||||
there; the linux crash gate did). The Dam ending cutscene has not been checked
|
||||
|
||||
@@ -9,6 +9,33 @@
|
||||
- **Current status:** the README "Status" section (`docs/dev/LEVEL-STATUS.md` is a historical per-level sweep record). Current task + environment: `docs/HANDOFF.md` (a rolling local working file — may be absent in a fresh clone; fall back to the README "Status" section).
|
||||
- **Dispatching subagents?** `docs/dev-process.md` — task budgets/deadlines, file partitioning, pre-flight, the standard brief template. Every investigation subagent reads `docs/porting-notes.md` first and appends to it.
|
||||
|
||||
## Public site pages (`docs/`) — presentation layer, not a source of truth
|
||||
|
||||
The repo's homepage and sub-pages are published by GitHub Pages; the local
|
||||
preview is `node scratch/build_preview.mjs site` → `scratch/_site/` (served
|
||||
with `node scratch/serve_preview.mjs 8777`). The site is a **presentation
|
||||
layer over the reference docs, kept in a separate area, and allowed to go
|
||||
stale** — never let it poison a work item:
|
||||
|
||||
- **Pure site pages** — `docs/index.md`, `documentation.md`,
|
||||
`the-software-rsp.md`, `the-asset-pipeline.md`, `framerate-and-pacing.md`,
|
||||
`input-and-aim.md`, `saves.md`, `security.md`, `fidelity.md` —
|
||||
summarise the ROADMAP / README / finding log / release notes. **Do not
|
||||
consult them as work information, cross-check against them, or treat a
|
||||
mismatch with `docs/ROADMAP.md` or the finding log as a bug** (that is
|
||||
the expected, independent-staleness case). Update them only when the task
|
||||
says so, and source every fact from the ROADMAP / README / finding log —
|
||||
never the other way round. The footer "last updated" date in
|
||||
`docs/_layouts/default.html` is the same class of site-only detail.
|
||||
- **Shared files** — `docs/internals.md`, `porting-notes.md`,
|
||||
`building.md`, `dev-process.md`, `dev/agentic-development.md` are
|
||||
authoritative working docs that the site publishes verbatim; edit them
|
||||
normally as part of dev work and the site picks up the change for free.
|
||||
|
||||
Keep the split intact: no working notes migrate into pure site pages, and
|
||||
never edit a shared doc merely to make the site read better — if the site is
|
||||
stale, fix the site page (or the fact upstream, as its own task).
|
||||
|
||||
## Non-negotiables
|
||||
|
||||
1. **N64 build untouched.** `Makefile`, `tools/`, `rsp/`, `ld/` belong to the N64 build. Never modify them for the PC port.
|
||||
@@ -45,8 +72,10 @@ mostly agent-authored.
|
||||
documentary and small (bug shots, previews — downscaled), and never commit
|
||||
bulk ROM-derived captures: capture output dirs are gitignored
|
||||
(`tools_pc/sweep-captures/cap-*/`, `tools_pc/sweep-captures/**/*.ppm`); the
|
||||
only bulk imagery in the tree is `tools_pc/golden/*.png`, which exists
|
||||
because `verify.sh` consumes it. Downloads ship no game content at all.
|
||||
only bulk imagery in the tree is `tools_pc/golden/**/*.png`
|
||||
(63 frames × 2 platforms, 126 total, nested per level at
|
||||
`tools_pc/golden/<level>/{win,linux}/`), which exists because `verify.sh`
|
||||
consumes it. Downloads ship no game content at all.
|
||||
5. **Batch, don't spam.** Accumulate approved doc/tree fixes across a session
|
||||
into ONE commit; no per-item branches.
|
||||
6. **Release gate.** Before pushing a release: the PII scrub and legal/copyright
|
||||
@@ -83,8 +112,9 @@ Needs CMake + SDL2 + zlib + OpenGL, and must run from the MSYS2 MINGW64 shell
|
||||
1. **`Cannot create temporary file in C:\Windows\: Permission denied`** at the
|
||||
link step. The PE toolchain (ninja → cmd → gcc/ld) needs a writable
|
||||
TMP/TEMP; the msys→native env conversion drops it in non-login shells
|
||||
(agent harnesses; the `C:/msys64` tree here was built for `D:/M/msys64`,
|
||||
so its conversion is unreliable). `build-pc.sh` now **self-heals**: it
|
||||
(agent harnesses; the `C:/msys64` tree here was built for a relocated MSYS2
|
||||
root — `<msys>` in the placeholder legend — so its path conversion is
|
||||
unreliable). `build-pc.sh` now **self-heals**: it
|
||||
probes a native child's TMP (via a file — piped `cmd.exe` stdout is
|
||||
unreliable under msys console emulation) and, if broken, re-runs
|
||||
cmake+build under PowerShell with `TMP`/`TEMP` set natively (the
|
||||
|
||||
@@ -48,14 +48,17 @@ project is as much a study of that process as it is a port. See
|
||||
|
||||
## News
|
||||
|
||||
- **2026-10-05** — **v0.5.0**: one options menu laid out like the Perfect Dark
|
||||
port's, with plain-English wording, real-unit sliders and a one-line description
|
||||
per option; the game's own N64 control styles as a per-seat preset; emulator save
|
||||
files that load directly; a scalable HUD overlay; fullscreen mode, window centring
|
||||
and crosshair settings; antialiased overlay controls; and a fidelity round checked
|
||||
frame-by-frame against the N64 game (fog, aspect-ratio letterboxing, the Watch
|
||||
menu's own settings). The reference-frame gate was re-based on both platforms
|
||||
(21 levels, 63 frames each). [Release notes](https://github.com/jkdansereau/goldeneye-pc-port/releases/tag/v0.5.0).
|
||||
- **2026-10-05** — **v0.5.0**: one real options system: a
|
||||
single menu (laid out like the Perfect Dark port's) covering every setting,
|
||||
the game's own N64 control styles as a per-seat preset, and your emulator
|
||||
saves loading directly; a scalable HUD overlay; fullscreen, window-centring
|
||||
and crosshair settings; and a fidelity round checked frame-by-frame against
|
||||
the N64 game (fog, aspect-ratio letterboxing, the Watch menu's own
|
||||
settings). The reference-frame gate was re-based on both platforms (21
|
||||
levels, 63 frames each). Plus the small stuff: a menu wording, units and
|
||||
help-text pass, standardised menu spelling, and antialiased overlay
|
||||
controls.
|
||||
[Release notes](https://github.com/jkdansereau/goldeneye-pc-port/releases/tag/v0.5.0).
|
||||
- **v0.4.1**: 2–4 player split-screen multiplayer, controller presets and
|
||||
rebinding, PlayStation/Nintendo button names, master volume and audio
|
||||
device selection, a steady 60 fps on low-end GPUs, and fidelity fixes
|
||||
@@ -239,7 +242,7 @@ only in the release packages, and no macOS/ARM builds yet.
|
||||
|
||||
What a release installs (no networking, no telemetry, no ROM or game assets)
|
||||
and how faithfully the port tracks the original game's logic:
|
||||
[Security & fidelity status](docs/security-and-fidelity-status.md).
|
||||
[Security](docs/security.md) and [fidelity](docs/fidelity.md) status.
|
||||
The binaries are not code-signed; from v0.5.0 on each release artifact also
|
||||
carries a GitHub build-provenance attestation you can check with
|
||||
`gh attestation verify <file> --repo jkdansereau/goldeneye-pc-port`
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ BUILD_DIR="${BUILD_DIR:-build-pc}"
|
||||
# MSYS2 install). Whatever `cmake`/`gcc` happen to be first on PATH is not
|
||||
# trustworthy: Git Bash's /mingw64 has no toolchain, and a pip-installed
|
||||
# cmake in a Python Scripts dir can shadow the MSYS2 one. GE_MSYS2_ROOT
|
||||
# (e.g. D:\M\msys64) overrides the search.
|
||||
# (e.g. C:\msys64) overrides the search.
|
||||
_ge_find_mingw_bin() {
|
||||
local c root
|
||||
root="${GE_MSYS2_ROOT:-}"
|
||||
@@ -67,7 +67,7 @@ _ge_find_mingw_bin() {
|
||||
if [ -n "${MSYSTEM:-}" ] && [ -z "${GE_PC_BUILD_VIA_NATIVE:-}" ]; then
|
||||
_mingw_bin="$(_ge_find_mingw_bin)" || {
|
||||
echo "ERROR: could not find the MSYS2 MinGW64 toolchain (mingw64/bin with cmake.exe + gcc.exe)." >&2
|
||||
echo "Install it (see docs/building.md) or point GE_MSYS2_ROOT at the MSYS2 root, e.g. GE_MSYS2_ROOT='D:\M\msys64'." >&2
|
||||
echo "Install it (see docs/building.md) or point GE_MSYS2_ROOT at the MSYS2 root, e.g. GE_MSYS2_ROOT='C:\msys64'." >&2
|
||||
exit 1
|
||||
}
|
||||
# Failure mode 3 (AGENTS.md): the toolchain's DLL dir must be on PATH,
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: 404
|
||||
description: Page not found.
|
||||
layout: default
|
||||
permalink: /404.html
|
||||
---
|
||||
|
||||
## 404
|
||||
|
||||
This page doesn't exist. The site's real pages are linked from the
|
||||
nav: [home]({{ '/' | relative_url }}) ·
|
||||
[documentation]({{ '/documentation' | relative_url }}) ·
|
||||
[building]({{ '/building' | relative_url }}).
|
||||
|
||||
*Note for anyone following a moved link: the old "under the hood" page now
|
||||
lives at [documentation]({{ '/documentation' | relative_url }}).*
|
||||
|
||||
<!-- Links use the | relative_url filter on purpose: a 404 page is served for
|
||||
ANY unknown path, so plain relative links would resolve against the
|
||||
requested (dead) URL instead of the site root. -->
|
||||
+13
-20
@@ -140,15 +140,13 @@ below).
|
||||
| Item | Status | Refs | Notes |
|
||||
|---|---|---|---|
|
||||
| Third-person Bond offset residual | partial; intro puppet explained (2026-10-02) | D173, D292 | Mostly fixed. On the level-start puppet the variance is tick/PRNG-dependent idle timing (D13 class, faithful, no sign-off requested); one 1-frame first-tick Y transient is untraced. If the residual is seen elsewhere (cutscene body model), the maintainer should note where. |
|
||||
| Dam ending cutscene: Bond placement; railing transparency | partial (railing/grate transparency confirmed faithful 2026-10-07; Bond-placement re-check pending) | D173, D292, D526; maintainer 2026-10-02 | **Railing/grate transparency CLOSED as faithful (D526):** the 2D edge-railing (grate) texture in the Dam ending shows "odd" transparency between its two anchors, confirmed identical on 1964/GEPD (port == N64) → the original 2D texture, not a port bug (D306/D291 class). **Remaining: re-check Bond placement at the end of Dam** (the D173 level-start probe found no defect; the last place a Bond offset was seen). |
|
||||
| Dam ending cutscene: Bond placement; railing transparency | partial (railing/grate transparency confirmed faithful 2026-10-05; Bond-placement re-check pending) | D173, D292, D526; maintainer 2026-10-02 | **Railing/grate transparency CLOSED as faithful (D526):** the 2D edge-railing (grate) texture in the Dam ending shows "odd" transparency between its two anchors, confirmed identical on 1964/GEPD (port == N64) → the original 2D texture, not a port bug (D306/D291 class). **Remaining: re-check Bond placement at the end of Dam** (the D173 level-start probe found no defect; the last place a Bond offset was seen). |
|
||||
| Title-screen attract demo runs too fast; F10 box rescales while it plays | backlogged (after v0.5.0, maintainer 2026-10-04) | D87 (ramrom file struct); timing: D13, D248, D427, D451, D486 | **Reported 2026-10-04 (maintainer live pass):** the attract segment plays visibly too fast; not investigated. Lead: it is a ramrom demo replay whose recordings carry a per-frame tick count, which the port's 60 fps / 1-tick pacing may override. Rule out PC causes, then compare with 1964. Same pass: the F10 box briefly rescaled during the demo (not reproduced; candidate fix = overlay reads fast3d's native viewport, parked locally). |
|
||||
| Dam: first-tower guard walks a small circle (glass collision polygon) | done | D490 | **Fixed 2026-10-02, merged into `release/v0.4.1` 2026-10-03:** a stack overflow in `sub_GAME_7F03ECC0` (flat-bbox objects, i.e. glass) corrupted the collision polygon; `rem[8]` under `AVOID_UB`. Headless probe: the guard now walks his whole patrol loop. Maintainer by-eye check in Dam passed 2026-10-02. The porting-notes D24 audit ran 2026-10-03 and found D491 (below); no other overflow of this kind. |
|
||||
| Struct reads across adjacent globals: portal bbox seeds put props in extra rooms; casing spin seeded from trigger state | done | D491 | **Fixed 2026-10-03, merged into `release/v0.4.1`:** `bg.c` / `gunfire.c` read three separate scalar globals as one coord3d; mingw reverses their order. `#ifdef PORT` reads the named globals. Builds clean, 900-frame `-level_09` smoke clean. Nothing by eye is expected. Delete this row once released. |
|
||||
| Sniper rifle: zoom level and speed vs 1964 | verify | #136, D484, D485, D494 | Crouch: **D494** (2026-10-03) makes the PC crouch key crouch/stand freely with the sniper, as GEPD does (superseding D483's freeze); maintainer-verified. Zoom level (D484, 20 -> 7 degrees) and speed (D485, tick-scaled, Rule-2) fixed 2026-10-02. **Owed:** 1964 A/B of zoom level and speed; close #136 after it. |
|
||||
| Crash on save slots 1/3/4, plus a host BSOD (fltmgr.sys) | decided | #94 | Needs a repro. Two maintainer retest requests (v0.3.0, v0.4.0) got no reply. Likely D299/D301 (save-slot crash, fixed) and D344 (BSOD on exit, fixed). **Decided 2026-10-01: close as stale when the release ships**, pointing at D299/D301/D344; no GitHub activity before then. |
|
||||
| Authored mip chains not sampled for explicit-LOD textures | post-1.0 | D323 | Distant textures use driver mips instead of Rare's hand-authored chain (heaviest on Statue/Aztec). Parked as a fidelity enhancement. **Decided 2026-10-01:** after 1.0, together with the LOD-fraction approximation as one "real RDP LOD" project. |
|
||||
| Approximations in the software RSP | post-1.0 | `gfx_pc.cpp` `G_CCMUX_LOD_FRACTION`; D323 | The LOD-fraction CC input is an eyeballed approximation, bundled with D323 as one "real RDP LOD" project after 1.0 (2026-09-30 triage). **WrapFix settled 2026-10-02:** the maintainer checked the Depot building ceilings against 1964 with the default `Video.WrapFix = 0` and they look right, so the default stays off (the opt-in knob remains; RC3/D167). |
|
||||
| Latent 64-bit ABI hazards | partial | D441, #107, #108; AUDIT-M6 `struct player`/`struct hand` raw offsets (porting-notes §A1) | **State (2026-10-03, D441):** complete census (local `scratch/d441/`; many compiler hits are intentional `(s32)&ANIM_DATA_*` offsets, D34); 17 files widened to `uintptr_t` under `#ifdef PORT`; 35 sign-extension sites fixed; CI ratchet `tools_pc/abi_ratchet.py` (baseline 389); arena windows centralised (`port/include/portaddr.h`); tier-1 high-arena build (`GE_HIGHARENA_BASE=0x90000000`) runs the menu and `-level_09` pixel-identical to default. D478: nothing live on the current layout; the rest is harmless today but would bite on macOS/ARM/ASLR. **Sweep (2026-10-05):** tier-1 all-level sweep done — 21/21 PASS, 0 crashes, worst over-tol 2.38 % Jungle / 1.38 % Surface 2 (both under their 3 % limit), all 1 %-limit levels <= 0.24 %; no fix batches, ratchet unchanged (389); recipe + caveats in the D441 findings entry. **Owed:** tier 2 (above 4 GiB; u32 slots widened); store-to-u32 vs arithmetic-only tag per site (`portHostToN64` under macOS port_addr); `mema.c` widening (D453); `initanitable.c` heap slots; GE_DETERM wall-clock timers (D117 follow-up, blocks using determinism mode for frame gates). **#108:** widening the `sndPlaySfx` bound disables the guard everywhere; prefer a range check. Detail: findings D441, D457, D478. |
|
||||
| Latent 64-bit ABI hazards | partial | D441, #107, #108; AUDIT-M6 `struct player`/`struct hand` raw offsets (porting-notes §A1) | **State (2026-10-03, D441):** complete census (local `scratch/d441/`; many compiler hits are intentional `(s32)&ANIM_DATA_*` offsets, D34); 17 files widened to `uintptr_t` under `#ifdef PORT`; 35 sign-extension sites fixed; CI ratchet `tools_pc/abi_ratchet.py` (baseline 389); arena windows centralised (`port/include/portaddr.h`); tier-1 high-arena build (`GE_HIGHARENA_BASE=0x90000000`) runs the menu and `-level_09` pixel-identical to default. D478: nothing live on the current layout; the rest is harmless today but would bite on macOS/ARM/ASLR. **Sweep (2026-10-05):** tier-1 all-level sweep done, 21/21 PASS, no fix batches, ratchet unchanged (389) — recipe + caveats in the D441 entry. **Owed:** tier 2 (above 4 GiB; u32 slots widened); store-to-u32 vs arithmetic-only tag per site (`portHostToN64` under macOS port_addr); `mema.c` widening (D453); `initanitable.c` heap slots; GE_DETERM wall-clock timers (D117 follow-up, blocks using determinism mode for frame gates). **#108:** widening the `sndPlaySfx` bound disables the guard everywhere; prefer a range check. Detail: findings D441, D457, D478. |
|
||||
|
||||
## 3. Verification debt (fixed; a live check is owed)
|
||||
|
||||
@@ -179,11 +177,9 @@ A single campaign pass with these on the checklist would clear most of them.
|
||||
| macOS (Intel + Apple Silicon) / ARM64 Linux | open (target 0.9.0/1.0, maintainer 2026-10-02) | PRs #88, #95; #101 | Outside drafts, parked for `main` until after 1.0. **Address model decided (2026-09-30): port_addr (#95)**, a `portN64ToHost`/`PORT_N64PTR` chokepoint with a `PORT_ADDR_STRICT` validator. The `macos` integration branch is on origin with #88 (merged), #132 and #95 (retargeted, open); nothing merges to `main` before the post-1.0 pass. **Open against `macos`:** #131 (self-hosted sweep scaffold, never run on a Mac; needs #95 first). **On the next rebase onto `main`:** take #131's `selfhosted.yml`; drop #95's `crouched_rifle` hunk (our #120/D445 is correct); relabel #95's D29x/D405-D421 labels. Needs the §2 ABI-hazard sweep; the maintainer tests firsthand before merging. |
|
||||
| Platform parity gate (Linux co-equal with Windows) | open | — | **Decided 2026-09-30:** yes. Every released platform carries the same gate: a 21-level sweep plus a campaign pass. Needs the golden baselines on both platforms first (§7). The last known Linux crash (D190) was closed as not-a-bug. |
|
||||
| Low-end GPUs (~30 fps on Celeron/HD 400) | fixed, verify on N3060 class | D339, D481, D482, #92 | **D481 (2026-10-02):** fast3d ran inline on the scheduler thread, delaying retrace delivery so the tick gate skipped frames; with the render worker a Lenovo X220 (HD 3000) went 44-46 → 60.0 fps. **D482:** Atom/Celeron-class GPUs (HD 400-605, UHD 600/605, software renderers) get DrawDistance/LodDistance 100 and MSAA 1 once, where still at defaults. **D473:** uncached per-batch getenv fixed. Direction: real optimizations, not a preset. **Next only if N3060-class hardware still drops:** one `GE_PERFSTAT=1` run there (`gpu=` vs `run=`), then a lighter renderer-keyed default (GPU) or fast3d per-batch cuts (CPU; local `PERF-HOTSPOTS.md`). |
|
||||
| Statue/Cradle hitching (maintainer, 2026-09-30) | parked (not player-visible, 2026-10-02) | `GE_PERFSTAT` spike counters (2026-10-01) | **Diagnosed (D475, D477, D480):** no sustained load. The ~33 ms frames are the game's frame limiter skipping a retrace after a slightly late gfx task (`boss.c`; D13-class timing). CPU bursts were CI-palette re-imports (ruled out, D477; CI4 D476) and in-play shader compiles (fixed by D480). **Parked 2026-10-02:** a maintainer play session with the timeline probe (`probe/hitch-timeline`, never merge) felt no hitching. Reopen only if a visible hitch is reported (lever: pre-warm at level load). |
|
||||
| Statue/Cradle hitching (maintainer, 2026-09-30) | parked (not player-visible, 2026-10-02) | `GE_PERFSTAT` spike counters | **Diagnosed (D475, D477, D480):** no sustained load — the ~33 ms frames are the frame limiter skipping a retrace after a late gfx task (`boss.c`, D13-class timing); CPU bursts were CI-palette re-imports (ruled out, D477) and in-play shader compiles (fixed, D480). **Parked 2026-10-02:** a play session with the timeline probe felt no hitching. Reopen only if a visible hitch is reported (lever: pre-warm at level load). |
|
||||
| Steam Deck preset skipped when first launched from Desktop Mode | verify | D283 | Fixed on `release/v0.4.1`: the Deck is detected by DMI hardware id (Valve Jupiter/Galileo; `STEAMOS` as a second signal) and the preset applies once per ini, only while Fullscreen/Maximized are untouched. Only a Windows build and a Linux `-fsyntax-only` check ran. **Owed: one run on a real Deck** (Desktop-Mode-created ini, then Game Mode; expect fullscreen 1280x800 and the log line `video: Steam Deck (DMI Valve ...)`). The Known-issues row goes when this ships. |
|
||||
| Windows 7 | open | #98 | **Re-checked 2026-10-02: likely feasible around 1.0.** The exe imports no Windows 8+ functions and the bundled SDL2 2.32.10 still supports Windows 7. The real blocker is the first-run converter `ge007-convert.exe` (PyInstaller, Python 3.9+): the native C converter (#6 Part B) removes it, or a separate Python 3.8 build. Work: one Windows 7 VM test, then manual per-release checks (CI cannot test it). Supersedes the earlier 'won't-fix' call. || Linux golden baselines (P7) + two residual render bands | closed (2026-10-05 re-round) | D521/D525 | 21-level `<level>/linux/` set captured 2026-10-04 on a real-GL box (Mesa / Intel HD 3000), then **re-rounded 2026-10-05 (P7b, D525)**: all 21 levels, 63 frames, at the D522 windows with the save pinned present (the 2026-10-04 set had `data/ge007.eep` cleared, and D523 measures that save-file presence moves ~every level). Cross-platform framediff vs `win/` at the same stems: structural **21/21 clean** (worst cell mean 4.43, phash <= 6 except cradle at 40), exact **0.348-3.983%** over tol 2 on the 20 non-Cuba levels. **Both residual bands closed:** Archives 19.956-24.554% (cell means to 50.8) is now 3.590-3.859% (worst cell 2.31, phash 1) and Streets 1200's 16.0-148.4 cell-mean band is now 3.616-3.983% (worst cell 4.43, phash 0) — save state, not a renderer. Dam's 900 flyby offset is out of the set (Dam sits at 1500-1700, cross-platform 2.964-3.443%). Caveat: the box's own sweep is crash-detect only (`glxinfo -B` fails there, rc 255, so `verify.sh`'s probe fails closed); the cross-platform numbers are computed on Windows. |
|
||||
|
||||
|
||||
| Windows 7 | open | #98 | **Re-checked 2026-10-02: likely feasible around 1.0.** The exe imports no Windows 8+ functions and the bundled SDL2 2.32.10 still supports Windows 7. The real blocker is the first-run converter `ge007-convert.exe` (PyInstaller, Python 3.9+): the native C converter (#6 Part B) removes it, or a separate Python 3.8 build. Work: one Windows 7 VM test, then manual per-release checks (CI cannot test it). Supersedes the earlier 'won't-fix' call. |
|
||||
|
||||
## 5. Modern-remaster layer (port features beyond the N64)
|
||||
|
||||
@@ -208,9 +204,6 @@ Background research lives in the maintainer's local notes (gitignored):
|
||||
|
||||
| Item | Status | Refs | Notes |
|
||||
|---|---|---|---|
|
||||
| `All unlocked` rework: RAM override instead of save patching | done | D442, D387, D259 | **Landed 2026-09-30 (D442):** query-time hooks in `file2.c`, RULE-2-SIGNOFF recorded; the EEPROM patch and D387 merge are removed. **Verified 2026-10-03 (headless):** ON = all 20 levels and cheats unlocked; OFF = only real progress; `ge007.eep` byte-identical. Delete this row once released. |
|
||||
| Settings units and values cleanup | done | D357, D443 | **Landed 2026-09-30 (D443):** mouse ×, whole-% deadzone/volume/vibration, FOV in horizontal degrees, MSAA 16×; verified 2026-10-03 (both UIs show the same values). FPS presets above 60 wait for the frame-rate-above-60 work. Delete this row once released. |
|
||||
| Restart button in the settings menus | done | D443 | **Landed 2026-09-30 (D443):** a "Restart game" row (orderly D344 quit, then relaunch). **Owed:** click it once on Windows (no BSOD); the Linux relaunch path has never been compiled. |
|
||||
| F10 / PC Options menu: PD-style dialog refactor + watch-consolidation review | verify | D504-D512, `MENU-PD-ALIGNMENT-PLAN.md` (maintainer's local notes) | **Built 2026-10-04 (D504); follow-ups merged into `release/v0.4.1`:** D505/D506/D507 (wording, real-unit sliders, descriptions); D508 forced aspect ratios (16:9 / 21:9); D509 2-frame hold after an aspect change (rare gun glitch = known issue); D510 overlay + FPS counter same size front end vs level; D512 `Game.HudScale` scales the F10 overlay. **Owed (live pass, `docs/dev/notes/MENU-LIVE-CHECKLIST.md`, launches A/B/C):** look-and-feel vs PD; mouse, keyboard and pad in a level and on the front end; HudScale 75/100/150; 21:9; display-mode round trip across a restart; split-screen 2P with the overlay open. **Gaps:** background blur (post-1.0, §5c); per-seat control scheme is #139 / D513. Watch consolidation: not cheaply feasible (parked as T5). |
|
||||
| Defaults/presets consolidation: one `Display mode` switch | verify | D504, D440, `MENU-PD-ALIGNMENT-PLAN.md` §5 (local notes) | **Landed 2026-10-04 (D504):** the derived `__DisplayMode` row shows Modern / Original N64 / Custom (no ini key); F10 dropdown + left/right stepping, front end steps too; one reset row per dialog covering exactly its keys; editing a non-bundled key does not flip Display mode. **Decided 2026-10-03: tri-state**, flipping to Custom when the user edits a bundled key. **Owed (live):** display-mode round trip across a restart; read of the regrouped pages and wording (MENU-LIVE-CHECKLIST.md A1/A2/A4). |
|
||||
| Control style Original shows the game's own N64 styles | verify | #139 follow-up, D516, D517 | **Landed 2026-10-04 (D516, merged @ 91595597):** "Controller style" row (Original only; the game's own 1.1-2.4 per seat, saved to the Bond file; front end reads "(in a mission)"); D498 presets hidden in Original. **D517:** hold-repeat on any Bond row dropped fps (EEPROM rewrite per detent); now staged like sliders. Live passes 2026-10-04 (maintainer): single player + split-screen 2P with different styles per seat. **Owed:** the 2.x second-pad pass (real second controller). |
|
||||
@@ -220,9 +213,7 @@ Background research lives in the maintainer's local notes (gitignored):
|
||||
| Gamepad presets: duplicate-binding warning, Xbox stick behaviours | open (after v0.5.0; documented in the README) | D469, D498, D518, D394 | D469 (pad action table, Jinx 1.1 default, Custom per-seat bindings), **D498** (Xbox 1.2 Christmas / 1.3 Frost / 1.4 Elektra) and the per-seat preset (**D518**) are done and maintainer-verified with pads. Not done (maintainer 2026-10-04: skip in game for v0.5.0, document only): a warning when two actions share a button; the Xbox "left stick aims the crosshair" and "D-pad copies the left stick" behaviours (D394). |
|
||||
| Pad button names on a Nintendo pad | verify | D471; local note `PAD-MENU-AUDIT.md` | Audit done 2026-10-01 (no controller-only trap; D472 fixed G1-G3). D471 family button names + player LEDs: **PS5 DualSense verified 2026-10-03.** **Owed:** a Nintendo (Switch) pad check; the maintainer has no such pad, so this waits for one or for a user report. |
|
||||
| Mute and auto-pause on focus loss; PNG screenshots to `screenshots/` | parked | D231, PR #56 (closed unmerged), `docs/dev/notes/parked/0001-QoL-*.patch` (local) | Deprioritised by the maintainer on 2026-09-25. F12 today is the dev PPM dump. |
|
||||
| FPS tanks while adjusting F10 music volume with a controller | done | D489 | Maintainer, 2026-10-02 (seen on PAL; general, also on v0.4.0). Cause: every pad/arrow slider step saved to the EEPROM (3 joy-poll handshakes + file rewrite on the game thread). Fixed: steps stage, save once on release; merged into `release/v0.4.1` 2026-10-03. Maintainer pad check passed 2026-10-03. Delete this row once released. |
|
||||
| Frame rate above 60 (120/144/uncapped with interpolation) | decision | [`dev/UNLOCKED-FPS-PLAN.md`](dev/UNLOCKED-FPS-PLAN.md) | The menu cap is {30, 60} (the ini accepts 0 = uncapped, but the sim ticks at the VI rate). The plan's Phase 0 is resolved by D248 (the default was a port bug; it is a real 60 fps) and its Phase 1 audit and Phase 2 slice scope are written (landed 2026-09-30), but the header still reads parked. Next step is a standing sim/render-rate measurement, not the old 30 fps investigation. Must stay compatible with netplay determinism. |
|
||||
| Swapping saves with emulators | done (D492) | D492; `tools_pc/eep_convert.py`; README "Using an emulator save" | **Implemented 2026-10-04:** `tools_pc/eep_convert.py` (`n64-to-pc`, `pc-to-n64`, `verify [--as n64|pc]`, auto-detect), bundled as `tools/eep_convert.py` in both release packages; README section added. **Why (D492):** the port stores checksum words and `options` little-endian, so an unconverted 1964 save fails validation and all five slots are wiped; converting (swap `options`, recompute the checksum pair) was proven in a headless A/B. On-disk format unchanged. Verified byte-identical and round-trip. |
|
||||
| PD Extended Options parity: settings that need new dev work | done (reviewed 2026-10-04; two rows deferred) | `MENU-PARITY-SONNET-PLAN.md` §3 (local notes); pd_port `port/src/optionsmenu.c` @ 32a1cb9 | **Reviewed 2026-10-04 (maintainer decisions; local notes `PD-PARITY-DESIGN-REVIEW.md`, `WATCH-SCREEN-RATIO-DESIGN.md`).** **Done:** D511 fullscreen mode, Center window, crosshair opacity and color by health (live check owed, MENU-LIVE-CHECKLIST.md A4/A5/B3). **Watch Screen size/Ratio:** stay on the watch, no PC rows; the game saves watch settings on watch close (D349 correction) and they don't fight Aspect ratio (README). **Deferred past v0.5.0:** mouse lock mode (Auto/Always/Off; aim lock itself = `Input.AimMode`, D337); per-seat controller device select (needs a stable pad id; MP input layer). **Closed:** edge deadzone = `Input.AimRange` (D338); crosshair sway N/A (GE has none; gun sway is D428); use key reloads, no toggle (Ext keeps D378's GEPD split, Control style Original gives the N64 behaviour); per-seat options/binds (pad binds already per seat, D469/D518; keyboard/mouse is one device); no Detail textures toggle (`Video.DetailBaseTile` is the D236 fix); N/A confirmed: HUD centering (automatic, D335b), glare, overexposure, GE64 muzzle flashes, MP death music, radial menu speed, language filter, crosshair speed. **Other rows:** analog movement/stick scale/crouch → #139, T7; tickrate/framerate limit → frame rate above 60. |
|
||||
| One PC options UI: front-end "PC Options" opens the F10 overlay over the folder graphic | verify | D519, D343, D504, D510, D512 | **Landed 2026-10-04 (D519, branch `feat/one-options-ui`):** the file-select "PC Options" entry opens the F10 overlay over file select; the `MENU_PC_OPTIONS` screen and four old probes are gone; Bond-file rows and the watch chooser are keyed to file select. Headless checks pass (D519). **Owed:** by-eye mouse, keyboard and pad pass on file select; profile chooser + Controller style with a real profile; footer text overlaps the Copy/Erase bar. |
|
||||
| Emulator saves load directly in the game (no tool for import) | verify | D514, D492; `port/src/eepimport.c` called from `geEepromLoad`; D297 `legacycrc.c` same pattern | **Landed 2026-10-04 (D514, merged into `release/v0.4.1`).** Copying a 1964/Project64 `.eep` in as `data/ge007.eep` works: on first launch each region that validates in emulator format and not port format is converted in place (same rules as `eep_convert.py`); regions invalid in both are left to the game's wipe; port saves untouched; the original is backed up to `ge007.eep.emulator.bak`. Export stays with `eep_convert.py`. Headless verify 6/6 byte-identical to the in-game-proven reference. **Owed:** by-eye mission select after importing a real 1964 save. |
|
||||
@@ -277,20 +268,22 @@ and a stage loader.
|
||||
|
||||
| Item | Status | Refs | Notes |
|
||||
|---|---|---|---|
|
||||
| Security review follow-ups | done | maintainer's local security review | All items done on `release/v0.4.1`: the Low hardening items, the Medium item (self-hosted workflow input handling), actions pinned by SHA, `pyinstaller` pinned to 6.22.3, and the ROM no longer stored in `actions/cache` by `selfhosted.yml` (staged from the runner's `_rom-seed` dir only). Dependabot bumps (#134, #135) landed as SHA pins. |
|
||||
| 1964-vs-port comparison harness | partial | `tools_pc/abpad/` | **2026-10-02/03:** one millisecond timeline drives 1964 (virtual XInput pad) and the port (`GE_INPUTSCRIPT_MS`), both windows captured on one clock with side-by-side sheets; verified through intro skip, file select and folder open. Not frame-identical (1964 has no seed pin or frame dump). Menu scripting dropped for `live_ab.ps1` (position-only, one real pad, `GE_PAD_BACKGROUND=1`). **Left:** in-level timelines (e.g. the D486 turret check); the two sides use different save files. |
|
||||
| Bond seems to move faster on the port than on 1964 (live A/B) | closed (2026-10-04, maintainer) | — | Seen 2026-10-03 in a live one-pad A/B. Closed as an input-mapping difference, not game speed: the GEPD 1964 bundle is set up for mouse and keyboard and the port then forced 1.2 SOLITARE (D513/D516 now offer the game's own styles). A valid future A/B is the port on a pad against a standard emulator with plain pad input. |
|
||||
| Scripted-playthrough harness | post-1.0 (maintainer 2026-10-04: not a good use of current LLMs; revisit with newer models) | `GE_INPUTSCRIPT`, D117 | Input script + `GE_PCDUMP` + crash-log check for unattended regression runs. **Maintainer concern (2026-10-03):** aiming, PRNG guards and timed events may block open-loop scripts, and runs aren't deterministic (D117). Levers: Invincibility + Invisibility cheats, closed-loop waypoint steering, pinned seed (`GE_RSEED`), coverage routes. Spike: one Dam route x5, measure end-position spread, then go/no-go. |
|
||||
| 1964-vs-port comparison harness | partial | `tools_pc/abpad/` | One millisecond timeline drives 1964 (virtual XInput pad) and the port (`GE_INPUTSCRIPT_MS`); both windows captured on one clock with side-by-side sheets, verified through intro skip, file select and folder open. Not frame-identical (1964 has no seed pin or frame dump). **Left:** in-level timelines (e.g. the D486 turret check); the two sides use different save files. |
|
||||
| Scripted-playthrough harness | post-1.0 (maintainer 2026-10-04: not a good use of current LLMs, revisit with newer models) | `GE_INPUTSCRIPT`, D117 | Input script + `GE_PCDUMP` + crash-log check for unattended regression runs. Levers: Invincibility + Invisibility cheats, closed-loop waypoint steering, pinned seed. Spike: one Dam route x5, measure end-position spread, then go/no-go. |
|
||||
| Cheap worker for mechanical, build-checked tasks | open | `delegate-local` MCP; memory of past Qwen issues | Birdman64's fast worker model wrote 44% of its commits while the lead planned and reviewed. Ours: pattern-applied edits (D441 fix batches, scaffolding strips, small tools), each gated by a clean build + a specific check + the lead's diff review, in the worker's own worktree. Local Qwen for edit-only tasks (it fabricates on reading tasks), or a hosted fast model via `delegate_to_provider` (the maintainer's cost call). |
|
||||
| Golden baselines | partial | `tools_pc/verify.sh`, `tools_pc/golden/README.md`, D117/D522/D529/D531 | **Windows gate GREEN (2026-10-05 re-base):** 21/21 PASS honest sequential. The recipe pins the save CONTENT (D529: `verify.sh` installs the canonical in-tree save `tools_pc/golden/ge007.eep` per level, the same way it pins the ini — D523's "presence" claim was refuted by the D529 A/B) and per-level windows — `900-1500:300` on 14 levels, `1000-1400:200` on Surface 2/Streets/Depot/Cradle/Frigate, `1500-1700:100` on Dam — because the 900 stem sits inside the wall-clock-paced intro flyby (D117; dam measured 1.6–7.2 % run to run). No tol limit raised. **Linux set (D525 → D530 → D531):** the 2026-10-04 round cleared the save, the box re-rounded 2026-10-05 (D530 — but under the box-LOCAL save: `capture_p7.sh`'s per-level re-pin silently overwrote D529's canonical install, the D531 blocker), and D531 (2026-10-07) fixed the tool and re-captured all 21 levels under the canonical eep (47/63 frames moved). **Owed:** the pixel-gated linux verify — the box's WSLg GPU display is session-state-dependent (its 10-05 capture was GPU-backed; 10-07's session reads back black even with `DISPLAY=:0`, so `verify.sh`'s probe fails closed to crash-detect); run `verify.sh sweep` on the box when its GPU display is up and check the four D117 flaky levels' first stems (never-do 6: exclude/widen, don't re-capture). |
|
||||
| Golden baselines | partial | `tools_pc/verify.sh`, `tools_pc/golden/README.md`, D117/D522/D529/D531 | **Windows gate GREEN (2026-10-05 re-base):** 21/21 PASS honest sequential. The recipe pins the save CONTENT (D529: `verify.sh` installs the canonical in-tree save `tools_pc/golden/ge007.eep` per level, the same way it pins the ini — D523's "presence" claim was refuted by the D529 A/B) and per-level windows — `900-1500:300` on 14 levels, `1000-1400:200` on Surface 2/Streets/Depot/Cradle/Frigate, `1500-1700:100` on Dam — because the 900 stem sits inside the wall-clock-paced intro flyby (D117; dam measured 1.6–7.2 % run to run). No tol limit raised. **Linux set (D525 → D530 → D531):** the 2026-10-04 round cleared the save, the box re-rounded 2026-10-05 (D530 — but under the box-LOCAL save: `capture_p7.sh`'s per-level re-pin silently overwrote D529's canonical install, the D531 blocker), and D531 (2026-10-05) fixed the tool and re-captured all 21 levels under the canonical eep (47/63 frames moved). **Cross-platform spread recomputed 2026-10-05** from the committed pairs (`framediff.py` win-vs-linux at the stems, tol 2): exact **0.380–5.120 %** on the 20 non-Cuba levels (silo's 900 stem is the outlier: cell mean 34.3, phash 10; streets 3.223–4.566), structural **21/21 clean**, max phash 40 (cradle, at threshold); Cuba 1.357–12.663 % is the structural-tier-only level. The D525 figures above predate the D531 linux re-capture. **Owed:** the pixel-gated linux verify — the box's WSLg GPU display is session-state-dependent (its 10-05 capture was GPU-backed; 10-07's session reads back black even with `DISPLAY=:0`, so `verify.sh`'s probe fails closed to crash-detect); run `verify.sh sweep` on the box when its GPU display is up and check the four D117 flaky levels' first stems (never-do 6: exclude/widen, don't re-capture). |
|
||||
| Flicker scan (A/B/A frame alternation) | parked (2026-10-03: tooling, nothing blocked on it; spec in the local investigation report `scratch/birdman64-rows-investigation.md` §4) | `GE_PCDUMP`, `GE_INPUTSCRIPT` | Dump **every** frame of a scripted run at low resolution and flag frame n when it differs from n-1 but matches n-2. For any old-vs-new pixel diff outside the golden gate, run a same-commit control first. Reference: Birdman64 `tools/flicker_scan.py`. |
|
||||
| Release build-provenance attestation | verify | `.github/workflows/ci.yml` release job; `.github/SECURITY.md`; README Status section | **Implemented 2026-10-04:** SHA-pinned `actions/attest-build-provenance` attests `dist/*.zip[.sha256]` + `dist/*.tar.gz[.sha256]` in the tag-only release job (`id-token: write` + `attestations: write` on that job only). Backs SECURITY.md's "unsigned, but reproducible" stance with `gh attestation verify <file> --repo jkdansereau/goldeneye-pc-port`; documented in SECURITY.md and the README. **Owed:** the v0.5.0 tag build is the first real run; confirm the step passes and verification succeeds on a downloaded asset, then delete this row. |
|
||||
| Self-hosted CI runner link failure | open | D244 | Needs a `pacman -Syu` on the runner (maintainer-only access). Release tag builds use GitHub runners, so it doesn't block a release. |
|
||||
| Remove temporary scaffolding before a release | partial | [`dev/GE-ENV-PROBES.md`](dev/GE-ENV-PROBES.md), D302 | Passes 2026-09-30 to 2026-10-03 removed the closed-finding probe suites (registry in `GE-ENV-PROBES.md`, `gen_env_probes.py --check` passing); TEMP probes `GE_TESTSTYLE` / `GE_D516` removed 2026-10-04. **Left:** D104 (kept while D294 is in verify); the M-183/M-185 clamps, **in scope 2026-10-03 (maintainer)**: re-verify all scripted-camera cutscenes with the clamps compiled out (intro flyover, per-level endings incl. the Dam abseil), then delete both blocks in `model.c`. |
|
||||
| P12 U5 review of `tools_pc/**` (release-diff, B10) | partial | `docs/dev/notes/RELEASE-BLOCKERS-v050.md` §F, D531 | **2026-10-07 (local session):** U5 reviewed (the unit that owed the P7 merge). **Blocker found + fixed in-tree:** `capture_p7.sh`'s per-level re-pin restored the local save, so the D530 box re-round ran under the box-local save — D531 (fixed + re-captured). **Applied 2026-10-07 as D532 (tooling-only):** (1) `verify.sh`'s `pin_ini_640x480` now fails closed like `pin_eep` (the old `2>/dev/null || true` call sites ran the gate under an unpinned ini on write failure — a spurious-verdict source); (2) `GOLDEN_SEED` hard-pinned with a warning for a differing stray `GE_RSEED` (the old `:-` form let the env var re-seed the gate; capture's `eval grep` still picks up the same line, so capture and gate stay consistent); (3) `audiodebug.ps1`'s dead `-AB`/`-Old` switches removed with a one-line note. **Still open on this row:** the pixel-gated box verify in a WSLg GPU-display window (D531) — crash-detect only until then. Clean: `p7_report.py`, `eep_convert.py`, `abi_ratchet.py`, `docs_budget.py`, `abpad/`, the D258/D416/PII#7 tool diffs, probe/capture deletions (`scan_op12/13.py`, the 433k-line `sweep-captures/` PPM set). |
|
||||
| Findings log and doc size | partial | `tools_pc/docs_budget.py` | The budget checker exists (per-file and tier-1 token budgets; `--toc FILE`). ROADMAP.md was trimmed under budget 2026-10-04. `findings.md` is still about 2 MB (~500k tokens), so agents must keep using the index. Nothing blocks; trim only if the budget check starts failing. |
|
||||
| P12 U5 review of `tools_pc/**` (release-diff, B10) | partial | D531/D532/D533 | Reviewed 2026-10-05 (the unit that owed the P7 merge). **Blocker found + fixed (D531):** `capture_p7.sh`'s per-level re-pin restored the local save, so the D530 box re-round ran under the box-local save — fixed + re-captured under the canonical eep (47/63 frames moved). **Should-fixes applied as D532 (tooling-only):** `verify.sh`'s `pin_ini_640x480` fails closed like `pin_eep`; `GOLDEN_SEED` hard-pinned with a warning for a stray `GE_RSEED`; `audiodebug.ps1`'s dead `-AB`/`-Old` switches removed. **Still open:** the pixel-gated box verify in a WSLg GPU-display window (D531) — crash-detect only until then. |
|
||||
| Findings log and doc size | partial | `tools_pc/docs_budget.py` | Budget checker (per-file and tier-1 token budgets; `--toc FILE`). `findings.md` is still about 2 MB (~500k tokens), so agents must keep using the index. Nothing blocks; trim only when a budget check fails. |
|
||||
| Branch and PR housekeeping | open | — | 30 landed local branches pruned 2026-09-30 (tips in `prune-branches-2026-09-30.txt`, notes archive). **On hold by the maintainer (do not prune yet):** probe-only `d243-verify-local`, `investigate/d243-cutscene-race`, `park/d236-probes-m139`. Local `main` and `release/v0.4.1` are deliberately not pushed. PR #62 (mouse dt-decouple) stays held until mouse feel is fundamentally better. |
|
||||
| Docs site: Web 1.0 phase 2 | decision | — | Phase 1 shipped. Phase 2 (centred serif page) is plan-only. |
|
||||
| Docs site: press/SEO pass (2026-10-05) | partial | `docs/` site pages | Landed on the pure site pages + presentation layer: real `<h1>` masthead on every page, `color-scheme`/`theme-color`/`max-image-preview`/`rel=me` in the layout, ink-mute >=4.5:1, focus-visible + selection, 15px body, mobile padding; `date`/`modified_time` front matter on the pure pages. Home-page additions (elevator-pitch pull-quote, Overview fact table, press/coverage section) were **removed on review 2026-10-05** — each restated the tagline/intro or duplicated a section below. The five short topic notes (the-software-rsp, the-asset-pipeline, framerate-and-pacing, input-and-aim, saves) were dropped from the published set (the PD port documents the same subjects; files stay in the repo as working material). **Open:** the same front matter on the *shared* docs (`internals.md`, `porting-notes.md`, `building.md`, `dev-process.md`, `dev/agentic-development.md`) is deliberately untouched — authoritative working docs, not edited for site polish. |
|
||||
| Agentic-development deep dive (doc) | queued — not yet (2026-10-05) | `docs/dev/agentic-development.md` | Write-up owed for the public case study: per-agent commit estimates / work estimates (the manual attribution pass over the session log, incl. the D350-style commit-date divergences), a code-quality audit of the trial models (GPT-6 (Sol) et al.), and the process feedback / findings. Deferred by the maintainer; pick it up when scheduled — nothing here blocks. |
|
||||
| Docs site: split Security & fidelity -> two pages + v0.5.0 update pass (2026-10-05) | done (local, unpushed) | `docs/security.md`, `docs/fidelity.md` (was `security-and-fidelity-status.md`) | Split on review (the homepage pointer sat near Known issues and read as if there were security *issues*); both pages cross-linked and linked from the hub and index.md's Download section. Update pass 2026-10-05 against the `release/v0.4.1` tree: no network includes/symbols/HTTP literals in compiled `src/`+`port/`; no registry or library-loading calls; converter imports no network module; bundle manifests re-checked (allowlist + ROM/oversized-blob hard-fail); region macros re-compared vs the Makefile (all three regions); library classification re-checked (CMake globs libultra+libultrare audio, gu, `io/vitbl.c` only). Full game-logic audit not re-run; recent `src/game` edits are finding-gated. |
|
||||
| Docs site: final sanity sweep + anchor fixes (2026-10-05) | done (local, unpushed) | `docs/porting-notes.md` (3 TOC hrefs), `docs/404.html` (permalink) | Audit of the 10-page published set: one h1 per page, no heading-level skips, all 42 in-page anchors resolve, titles/descriptions unique and <=160 chars, og:image/canonical present, JSON-LD parses, no local paths/usernames, served == built. Three `porting-notes.md` TOC hrefs carried a double hyphen where kramdown emits one (headings whose punctuation leaves a single separator: `(32->64):`, `D114/D116):`, `"off":`) — dead on the live GitHub Pages site, corrected at source against the live ids. `docs/404.html` needed `permalink: /404.html` (else canonical/og:url read `/404.html.html`). Preview-builder slug rule fixed to kramdown: strip punctuation, map **each** whitespace char to `-` (so ` / ` -> `--`), no run-collapsing; headings with inline markup now get ids too. |
|
||||
|
||||
## Community forks (not ours; reference only)
|
||||
|
||||
|
||||
+19
-9
@@ -36,19 +36,29 @@ plugins:
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The site publishes a small curated set:
|
||||
# index.md, under-the-hood.md (the "under the hood" hub), building.md, plus
|
||||
# index.md, documentation.md (the documentation hub), building.md, plus
|
||||
# 404.html (themed not-found page),
|
||||
# the four docs grouped behind that hub: internals.md, porting-notes.md,
|
||||
# dev-process.md, dev/agentic-development.md, the five short topic notes
|
||||
# grouped under it (the-software-rsp.md, the-asset-pipeline.md,
|
||||
# framerate-and-pacing.md, input-and-aim.md, saves.md), and
|
||||
# security-and-fidelity-status.md (linked from index.md's Known issues).
|
||||
# Everything else under docs/ is working material - the finding log, level
|
||||
# status, backlogs, plans, session notes, inherited decomp guides. It stays in
|
||||
# the repo (and on GitHub) but is excluded from the site build so it never
|
||||
# shows up as a published page or in sitemap.xml.
|
||||
# dev-process.md, dev/agentic-development.md, and
|
||||
# security-and-fidelity-status.md (split on review 2026-10-05 into
|
||||
# security.md + fidelity.md, linked from index.md's Download section and
|
||||
# the hub).
|
||||
# The five short topic notes (the-software-rsp.md, the-asset-pipeline.md,
|
||||
# framerate-and-pacing.md, input-and-aim.md, saves.md) were dropped from the
|
||||
# site on review 2026-10-05: the Perfect Dark port documents the same
|
||||
# subjects and nothing here was significantly new; they stay in the repo as
|
||||
# working material. Everything else under docs/ is working material - the
|
||||
# finding log, level status, backlogs, plans, session notes, inherited
|
||||
# decomp guides. It stays in the repo (and on GitHub) but is excluded from
|
||||
# the site build so it never shows up as a published page or in sitemap.xml.
|
||||
# NOTE: keep this list in sync as dev/ working docs are added; a new unlisted
|
||||
# .md under docs/ is silently published to the site + sitemap.xml.
|
||||
exclude:
|
||||
- the-software-rsp.md
|
||||
- the-asset-pipeline.md
|
||||
- framerate-and-pacing.md
|
||||
- input-and-aim.md
|
||||
- saves.md
|
||||
- HANDOFF.md
|
||||
- ROADMAP.md
|
||||
- SetupGuide.md
|
||||
|
||||
+117
-16
@@ -21,7 +21,9 @@
|
||||
--bg-panel: #121316; /* code / cards / tables */
|
||||
--ink: #e6e4df; /* warm off-white */
|
||||
--ink-soft: #a9a7a0; /* secondary text */
|
||||
--ink-mute: #70706a; /* captions, footer */
|
||||
--ink-mute: #8a8a83; /* captions, footer (>=4.5:1 on --bg-frame:
|
||||
the old #70706a measured 3.9:1 and failed
|
||||
WCAG AA on the tagline + legal line) */
|
||||
--line: #26282c; /* 1px borders */
|
||||
--line-2: #3a3d44; /* stronger borders */
|
||||
--accent: #e8a13a; /* GoldenEye gold (amber) */
|
||||
@@ -40,8 +42,9 @@
|
||||
margin: 0;
|
||||
color: var(--ink);
|
||||
font-family: var(--sans);
|
||||
font-size: 14px;
|
||||
line-height: 1.62;
|
||||
font-size: 15px; /* 14px read as console chrome, but the
|
||||
body is prose people actually read */
|
||||
line-height: 1.6;
|
||||
/* faint starfield (the old-school "space" tile, softened) */
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
@@ -63,6 +66,14 @@
|
||||
}
|
||||
a:hover { color: var(--accent-hi); text-decoration-color: currentColor; }
|
||||
|
||||
/* keyboard focus + selection: the amber thread again, so a focused
|
||||
control is visible on the near-black ground (a11y / keyboard users) */
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--accent-hi);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
::selection { background: var(--accent); color: #0b0b0d; }
|
||||
|
||||
/* ---- the centred "page" frame -------------------------------------- */
|
||||
.frame {
|
||||
max-width: 50rem;
|
||||
@@ -75,11 +86,13 @@
|
||||
/* ---- banner -------------------------------------------------------- */
|
||||
.banner { text-align: center; padding: 2.4rem 1rem 1.4rem; }
|
||||
.banner .t {
|
||||
margin: 0; /* it is an <h1> now (see the layout) */
|
||||
font-family: var(--mono);
|
||||
font-weight: 700;
|
||||
font-size: 1.7rem;
|
||||
letter-spacing: .05em;
|
||||
color: var(--ink);
|
||||
color: var(--accent); /* brand name in goldeneye gold -- the amber
|
||||
thread (masthead -> nav -> rule -> page title) */
|
||||
}
|
||||
.banner .tag { color: var(--ink-mute); font-size: .82rem; margin-top: .55rem; }
|
||||
|
||||
@@ -131,6 +144,23 @@
|
||||
border-bottom: 1px solid var(--line-2);
|
||||
}
|
||||
.doc-content h2::before { content: "\25aa "; color: var(--accent); }
|
||||
/* Page-title look: the 2026-09 SEO pass demoted page headings to h2
|
||||
(the masthead owns h1; no duplicate page titles) -- see the SEO
|
||||
conventions note in scratch/pr-seo-revise-prompt.md. The first
|
||||
content h2 of each page gets the h1 look; presentation only, the
|
||||
heading levels stay per-convention. (On the home page the masthead
|
||||
itself is the title, so its first h2 -- Status -- leads as a section.) */
|
||||
/* .flat-title (front matter on the home page): the masthead IS the
|
||||
page title there, so the first h2 must read as a plain section --
|
||||
otherwise masthead-h1 + amber first-h2 stack as a double header. */
|
||||
.doc-content:not(.flat-title) > h2:first-of-type {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
margin: .2rem 0 1rem;
|
||||
padding-bottom: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.doc-content h3 {
|
||||
font-family: var(--mono);
|
||||
font-size: .92rem;
|
||||
@@ -189,21 +219,88 @@
|
||||
}
|
||||
.doc-content tr:nth-child(2n) td { background: var(--zebra); }
|
||||
|
||||
/* ---- console blocks ------------------------------------------------ */
|
||||
/* Status / News / Download / Known issues panels (home page). Same
|
||||
amber-terminal language as the code blocks above, but the content
|
||||
keeps its semantic list/table markup (SEO + screen readers).
|
||||
|
||||
Site formatting rules (2026-10-05 PR pass + 2026-09 SEO conventions)
|
||||
— keep these:
|
||||
- Heading LEVELS follow the SEO pass: the page heading is h2 (the
|
||||
masthead owns h1; no duplicate page titles), sections are h2,
|
||||
h3 labels a real sub-topic only (e.g. the current-release line
|
||||
under Status). The first content h2 gets the amber "page-title"
|
||||
look via CSS only (.doc-content > h2:first-of-type) -- never by
|
||||
promoting the markup to h1.
|
||||
- h2 = the section, outside the panel.
|
||||
- Directives ("always use the latest release") are .callouts inside
|
||||
panels, or a .warn line (amber rule, ink text) where no panel
|
||||
exists; never headings — headings label topics,
|
||||
never emphasis.
|
||||
- List intros ("what a player will notice…") stay plain paragraphs.
|
||||
- Dated list-item leads ("2026-10-05 — v0.5.0") stay <strong> leads
|
||||
inside the <li>, not headings.
|
||||
- Headings must be single source lines: marked ends an ATX heading at
|
||||
the line break, so a wrapped "### …" silently becomes a heading plus
|
||||
a stray paragraph (Jekyll/other renderers differ — don't rely on
|
||||
multi-line headings at all). */
|
||||
.doc-content .cblock {
|
||||
background: var(--bg-panel);
|
||||
border: 1px solid var(--line);
|
||||
padding: 1.1rem 1.3rem .9rem;
|
||||
margin: 1.6rem 0;
|
||||
}
|
||||
|
||||
/* Expandable panels (<details>, e.g. the release history folded under
|
||||
Status): same panel language as .cblock; the summary line is the
|
||||
amber handle. The content is in the DOM either way -- collapsing is
|
||||
presentation, not hiding from search. */
|
||||
.doc-content details {
|
||||
background: var(--bg-panel);
|
||||
border: 1px solid var(--line);
|
||||
padding: .3rem 1.3rem .8rem;
|
||||
margin: 1.6rem 0;
|
||||
}
|
||||
.doc-content summary {
|
||||
font-family: var(--mono);
|
||||
font-size: .9rem;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
letter-spacing: .03em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.cblock h3 { margin-top: 0; color: var(--ink); }
|
||||
.cblock p, .cblock ul, details p, details ul {
|
||||
font-family: var(--mono);
|
||||
font-size: .88rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.cblock li, details li { margin: .5rem 0; }
|
||||
.cblock li::marker, details li::marker { color: var(--accent); }
|
||||
.cblock strong, details strong { color: var(--accent); font-weight: 600; }
|
||||
.cblock code, details code { background: transparent; border: 0; padding: 0; }
|
||||
.doc-content .callout {
|
||||
border-left: 3px solid var(--accent);
|
||||
padding: .15rem 0 .15rem .8rem;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
.doc-content .callout p { color: var(--ink-soft); }
|
||||
|
||||
/* Inline directive marker -- "Warning:" leading a sentence, amber like
|
||||
the rest of the accent thread, no panel around it. */
|
||||
.doc-content details .warn {
|
||||
border-left: 3px solid var(--accent);
|
||||
padding: .1rem 0 .1rem .7rem;
|
||||
margin: .2rem 0 .9rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.cblock table { background: transparent; margin: 1rem 0 .4rem; }
|
||||
.cblock > p:last-child { margin-bottom: 0; }
|
||||
|
||||
/* ---- images -------------------------------------------------------- */
|
||||
.doc-content img {
|
||||
border: 1px solid var(--line); border-radius: 0; max-width: 100%;
|
||||
}
|
||||
|
||||
/* ---- details / summary (the "full gallery" collapse) --------------- */
|
||||
.doc-content details {
|
||||
max-width: var(--measure);
|
||||
border: 1px solid var(--line);
|
||||
background: var(--bg-panel);
|
||||
padding: .6rem .9rem; margin: 1.5rem 0;
|
||||
}
|
||||
.doc-content summary {
|
||||
cursor: pointer; color: var(--accent);
|
||||
font-family: var(--mono); font-size: .85rem; letter-spacing: .03em;
|
||||
height: auto; /* no squashed stills when a width= is set */
|
||||
}
|
||||
|
||||
/* ---- console-viewer carousel (home page media) --------------------- */
|
||||
@@ -261,7 +358,11 @@
|
||||
|
||||
@media (max-width: 40rem) {
|
||||
.frame { margin: 8px; }
|
||||
.banner { padding: 1.4rem .8rem 1rem; }
|
||||
.banner .t { font-size: 1.35rem; }
|
||||
.doc-content { padding: 1.1rem 1rem .5rem; }
|
||||
.doc-content table { font-size: .82rem; }
|
||||
.doc-content pre { padding: .7rem .8rem; }
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -3,26 +3,44 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- Paint the browser chrome (scrollbars, form controls, new-tab cards)
|
||||
dark before CSS loads, so the page never flashes white on mobile. -->
|
||||
<meta name="color-scheme" content="dark">
|
||||
<meta name="theme-color" content="#050607">
|
||||
<!-- Indexing is NOT restricted: this only asks Google/Bing to show the
|
||||
large image preview in search cards, which is what makes the
|
||||
in-engine stills legible in a coverage roundup. -->
|
||||
<meta name="robots" content="max-image-preview:large">
|
||||
<link rel="icon" type="image/jpeg" href="{{ '/img/shots/shot-28.jpg' | relative_url }}">
|
||||
<!-- Entity disambiguation: the maintainer behind every page. -->
|
||||
<link rel="me" href="https://github.com/jkdansereau">
|
||||
{%- seo -%}
|
||||
{%- include head-custom.html -%}
|
||||
</head>
|
||||
<body>
|
||||
<div class="frame">
|
||||
|
||||
<!-- The masthead IS the page's h1: every page gets exactly one h1
|
||||
(the brand), and the page's own heading starts at h2. A <div>
|
||||
here left the document with no h1 at all, which is what search
|
||||
and screen readers key on. Presentation only -- the CSS class
|
||||
carries the look. -->
|
||||
<header class="banner">
|
||||
<div class="t">{{ site.title }}</div>
|
||||
<div class="tag">{{ site.description }}</div>
|
||||
<h1 class="t">{{ site.title }}</h1>
|
||||
<p class="tag">{{ site.description }}</p>
|
||||
</header>
|
||||
|
||||
<nav class="sitenav">
|
||||
<nav class="sitenav" aria-label="Site navigation">
|
||||
<a href="{{ '/' | relative_url }}">home</a><span class="sep">/</span>
|
||||
<a href="{{ '/under-the-hood' | relative_url }}">under the hood</a><span class="sep">/</span>
|
||||
<a href="{{ '/documentation' | relative_url }}">documentation</a><span class="sep">/</span>
|
||||
<a href="{{ '/building' | relative_url }}">building</a>
|
||||
</nav>
|
||||
<div class="rule g"></div>
|
||||
|
||||
<main class="doc-content">
|
||||
<!-- flat_title: this page's masthead IS its title, so the layout opts
|
||||
out of the amber first-h2 "page-title" look (no double header).
|
||||
Jekyll + the preview builder both honour this conditional. -->
|
||||
<main class="doc-content{% if page.flat_title %} flat-title{% endif %}">
|
||||
{{ content }}
|
||||
</main>
|
||||
|
||||
@@ -30,7 +48,8 @@
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="footer-stamp">
|
||||
last updated: 2026-10-07 · v0.5.0
|
||||
<a href="https://github.com/jkdansereau">maintained by jkdansereau</a>
|
||||
· last updated: 2026-10-05 · v0.5.0
|
||||
· <a href="https://github.com/jkdansereau/goldeneye-pc-port">GitHub</a>
|
||||
· <a href="https://github.com/jkdansereau/goldeneye-pc-port/releases">releases</a>
|
||||
</div>
|
||||
|
||||
+3
-2
@@ -51,7 +51,7 @@ toolchain is involved in extraction or in the PC build.** (The IDO toolchain is
|
||||
only needed to build the N64 ROM itself, and its proprietary SGI binaries are
|
||||
not distributed here; see [`SetupGuide.md`](https://github.com/jkdansereau/goldeneye-pc-port/blob/main/docs/SetupGuide.md) "Recompile IDO".)
|
||||
On Windows this is easiest under WSL or a Linux VM. Full details and
|
||||
alternatives (Docker) are in [`SetupGuide.md`](https://github.com/jkdansereau/goldeneye-pc-port/blob/main/docs/SetupGuide.md).
|
||||
alternatives (Docker) are in `SetupGuide.md`.
|
||||
|
||||
---
|
||||
|
||||
@@ -98,7 +98,8 @@ On Windows, `build-pc.sh` also locates the MSYS2 MinGW64 toolchain itself
|
||||
`cmake` earlier on PATH) and, if native child processes would get an
|
||||
unwritable `TMP`, re-runs the configure+build under PowerShell with a
|
||||
writable one. If MSYS2 is not installed at `C:\msys64`, set
|
||||
`GE_MSYS2_ROOT` (e.g. `GE_MSYS2_ROOT='D:\M\msys64'`). Re-exec logs:
|
||||
`GE_MSYS2_ROOT` (e.g. `GE_MSYS2_ROOT='C:\tools\msys64'` for a custom
|
||||
install location). Re-exec logs:
|
||||
`build-pc/ge007-native-reexec-*.log`.
|
||||
|
||||
For PAL/JP you must first generate that region's ROM-asset symbol file
|
||||
|
||||
@@ -120,6 +120,7 @@ Two classes:
|
||||
| `GE_FILESELECT_OVERLAY` | `port/src/frontoptions.c:96` | One-PC-options-UI (D519) test hook: opens the F10 overlay over file select without a click; value `n` > 1 also closes it `n` label-frames later. Replaces the retired front-screen probes (the FRONTOPTIONS_SECTION, FRONTNAVLOG, FRONTOPTS_WIDTHS and FRONTOPTIONS_AUTO probes). | **live** (harness) |
|
||||
| `GE_WSPROBE` (+ `GE_WSPROBE_FRONT`, `GE_WSPROBE_RESET`, `GE_WSPROBE_F10FRONT`) | `port/src/watchsettings.c:616,568,512`, `port/src/optionsoverlay.c:1566` | D354 watch-settings probe family: `WSPROBE[=tick]` logs before/after the queued settings commit one tick apart; `_FRONT[=tick]` drives a headless front-end change scenario; `_RESET` prepares an options-reset after 120 front ticks and verifies persistence once the stage drains; `_F10FRONT` fires a one-shot F10→front poll after the file-select save becomes available (avoids the joyDisablePoll deadlock). | **live** (diagnostic) |
|
||||
| `GE_ZF` (+ `GE_ZFTOL`, `GE_ZFBOX`) | `port/fast3d/gfx_pc.cpp:1653-1657` | Z-fight grid probe: per tri emit, buckets the centroid cell and flags cells that fight ≥5 times (cap 600 hits); `ZFTOL`=tolerance, `ZFBOX="x0 y0 x1 y1"`=world-box filter. | **live** (diagnostic) |
|
||||
| `GE_D526` (+ `GE_D526BOX`, `GE_D526MAX`) | `port/fast3d/gfx_pc.cpp:1895,2024,2032,2034` | D526 per-triangle draw-state census probe (text-only): `GE_D526="lo-hi"` = sim-frame range (same dash syntax as `GE_D75D`); `GE_D526BOX="x0 y0 x1 y1"` = NDC region filter (same syntax as `GE_ZFBOX`, default on-screen); `GE_D526MAX` caps per-triangle lines (default 400). Per emitted in-region tri: frame, NDC bbox, z/w, geometry_mode, other_mode_l/h, combine word, sampled tile tmem/fmt/siz, first_tile_index, prim alpha, vertex alpha min/max, use_alpha/modulate/invisible — plus one per-frame line aggregating in-region tris by (comb, oml, omh, alpha) signature. Retained as a generic transparency/texture triage tool (D195/D266/D268/D273 class); the D526 grate case itself was confirmed faithful N64 behaviour, so no fix shipped. Zero cost unless `GE_D75D`/`GE_ZF`/`GE_D303`/`GE_D526` is set (folded into the D474 `tri_dbg` gate). | **live** (diagnostic) |
|
||||
|
||||
## Dxx diagnostic probes — finding closed unless noted
|
||||
|
||||
|
||||
+216
-1
@@ -3,7 +3,8 @@
|
||||
> **Local machine paths are genericised** in this archive: `<repo>` = this repo's
|
||||
> working directory, `<repos>` = the local source-repos root, `<games>` / `<videos>`
|
||||
> = the local games / video roots, `<python>` = the local CPython install, `<temp>`
|
||||
> = a writable native temp dir. Session facts are unchanged.
|
||||
> = a writable native temp dir, `<msys>` = the local MSYS2 install root.
|
||||
> Session facts are unchanged.
|
||||
|
||||
> **Reference only.** Current state lives in the [README](../../README.md)
|
||||
> "Status" section and `docs/dev/LEVEL-STATUS.md`; per-finding detail is in
|
||||
@@ -6168,3 +6169,217 @@ Run from the **repo root**, not `build-pc/`.
|
||||
rating, don't hack it in.
|
||||
3. Prefer an **offline sidecar converter** (`tools_pc/d*_emit.py`,
|
||||
D43/D69/D88 pattern) over a runtime fixup for a whole ROM-asset format.
|
||||
---
|
||||
|
||||
# Appended 2026-10-05 (session 07j) — moved verbatim from `docs/HANDOFF.md` (briefs 2026-10-05 (session 07d) → 2026-10-05 (session 07g))
|
||||
|
||||
# HANDOFF — 2026-10-05 (session 07d)
|
||||
|
||||
## Branch
|
||||
`release/v0.4.1` @ `e9cf2ddf` (D530 addendum), tree clean.
|
||||
Local-only commits on top of `442eb2ff`: `aa19b354` (site SEO/redundancy),
|
||||
`2c378e7e`+`24b084d0` (Known issues), `ada7bbb1` (D530 goldens), `e9cf2ddf`
|
||||
(D530 addendum). **Nothing pushed.**
|
||||
|
||||
## This session (2026-10-05 (session 07d), user stepped away ~10:45, returns ~14:00 EDT)
|
||||
|
||||
1. **HANDOFF 07c item 1 (critical path) — DONE, committed (`ada7bbb1`):**
|
||||
- The X220 P7 re-round had completed on the box 2026-10-05 (tree `442eb2ff`,
|
||||
worktree `~/gh-fullhist-wt-p7`, `~/p7-reround.log` hit `P7 re-round DONE`
|
||||
12:53 EDT, **21/21 levels rc=0** under the canonical `ge007.eep`).
|
||||
- Pulled the 63 PNGs (15 MB tarball → `scratch/p7-pull/`, log →
|
||||
`scratch/p7-reround-pull.log`) and committed them into
|
||||
`tools_pc/golden/<level>/linux/`, replacing the D525 cleared-eep set:
|
||||
**51/63 differ; 12/63 byte-identical** (save-independent scenes,
|
||||
including frigate's first stem 001000 — a D117 stability signal).
|
||||
- **D117 flaky-four first-stem check (D529 never-do 6, first cross-machine
|
||||
test):** dam@1500 worst_cell 1.70 (phash 0), frigate@1000 byte-identical,
|
||||
streets@1000 1.78 (phash 0), jungle@900 5.12 (phash 3) — all in
|
||||
stable-level range, **none red → NO first-stem exclusion/widening**.
|
||||
- Structural tier all `ok` (cradle@40 documented exception; Cuba 26.4%
|
||||
within the documented 23.7–36.3% structural-only range). The `fail` rows
|
||||
in the box report are the expected cross-eep diffs vs the old set.
|
||||
- **Closes D529 never-do 3:** the index/README v0.5.0 "re-based on both
|
||||
platforms (21 levels, 63 frames each)" line now stands on a
|
||||
canonical-eep linux set → linux numbers unblocked (B7 satisfied).
|
||||
- Wrote **D530** (findings.md detail + §F table: D523 now SUPERSEDED-by-
|
||||
D529, D529 row was missing from the table — the 07c CSV had been
|
||||
hand-patched, which is why `gen_findings_index.py --check` drifted;
|
||||
regenerated) + `tools_pc/golden/README.md` linux-set text + History.
|
||||
|
||||
2. **DONE: fresh `verify.sh sweep` on the box against the NEW goldens**
|
||||
(shipped the 51 PNGs to `~/gh-fullhist-wt-p7`, box diff = 51 = the
|
||||
tree delta; fired 10:5x EDT, finished ~11:10 EDT): **21/21 PASS, 0
|
||||
FAIL** — but the run was **crash-detect only** (GE_PCDUMP reads black
|
||||
on the box's llvmpipe/WSLg, the D244 note; no pixel gate). So it is a
|
||||
stability re-check; the D117 cross-machine *pixel* evidence remains the
|
||||
re-round capture itself (the D530 first-stem check). Recorded as the
|
||||
D530 addendum (`e9cf2ddf`) with the residual: a pixel-gated box verify
|
||||
needs a working WSLg GPU session (the 10-05 re-round's pixel comparisons
|
||||
ran fine, so one exists).
|
||||
- Log pulled: `scratch/p7-verify-new-pull.log` (tail: `21` PASS, `0`
|
||||
FAIL, `SWEEP DONE`).
|
||||
|
||||
3. **DONE (partial, at push time still owed): PII scrub addendum for the 51
|
||||
new golden PNGs** — EXIF/text metadata sweep over all 63 linux PNGs:
|
||||
**0 metadata tags** (PIL); new doc text (D530, golden README) uses
|
||||
"X220" + `~/` paths only — no absolute paths/usernames/private IPs in
|
||||
tracked files (the box LAN address lives only in the gitignored
|
||||
HANDOFF + scratch logs). Addendum appended to
|
||||
`docs/dev/notes/PII-SCRUB-REPORT.md` (gitignored). The full
|
||||
LEGAL-review pass (game-content rule for screenshots) is still owed at
|
||||
push time.
|
||||
|
||||
## User to review at ~14:00 EDT
|
||||
- Local batch of 5 doc/golden commits (`aa19b354` SEO/redundancy;
|
||||
`2c378e7e`+`24b084d0` Known issues; `ada7bbb1` D530 goldens; `e9cf2ddf`
|
||||
D530 addendum — box sweep 21/21 crash-detect PASS).
|
||||
- Then the standing HANDOFF 07c items: 2. maintainer review of the 12-file
|
||||
batch; 3. P12 U2/U5/U6/U7 (deferred light-unit mechanical review);
|
||||
4. re-cut squash → B7/B8/B9 (README linux numbers now unblocked);
|
||||
5. push `release/v0.5.0` + tag.
|
||||
|
||||
## Environment
|
||||
- Preview: `:8777` (PID may be stale after a reboot — `node
|
||||
scratch/build_preview.mjs site && node scratch/serve_preview.mjs 8777`).
|
||||
- Box ssh: `ssh the test box` (Windows→box works; box has no sshd —
|
||||
everything rides the same session's stdin/stdout; pushes via
|
||||
`cat f | ssh ... 'cat > dest'` or tar pipes).
|
||||
- 3 parked worktrees (ci/d441/modpatch) untouched.
|
||||
|
||||
---
|
||||
|
||||
# HANDOFF — 2026-10-05 (session 07e) (D531 + P12 U5)
|
||||
|
||||
## Branch
|
||||
`release/v0.4.1` @ `164920c6`, tree clean. Three more local-only commits on
|
||||
top of `e9cf2ddf`: `4829fd94` (D531 blocker fix + canonical re-capture),
|
||||
`d2d75e11` (ROADMAP rows), `164920c6` (D531 addendum). **Nothing pushed.**
|
||||
|
||||
## This session (2026-10-05 (session 07e))
|
||||
|
||||
**D531 — `capture_p7.sh` canonical-re-pin blocker (P12 U5 review finding),
|
||||
fixed + re-captured. AMENDS D530.**
|
||||
|
||||
- U5 reviewed `tools_pc/**` (the release-diff unit that owed the P7 merge):
|
||||
small diffs all mechanical/clean; `p7_report.py`, `eep_convert.py`,
|
||||
`abi_ratchet.py`, `docs_budget.py`, `abpad/` clean (list-arg subprocess,
|
||||
raw_decode JSON, no shell, no destructive ops); deletions clean (probe
|
||||
tools + the 433k-line sweep-capture PPM set). **But** `capture_p7.sh`'s
|
||||
D529 adaptation was incomplete: the D524-era per-level re-pin
|
||||
(`cp "$EEP_ORIG" "$EEP"`, restoring the pre-capture LOCAL save) silently
|
||||
overwrote D529's pre-loop canonical install from level 1 — so **the
|
||||
10-05 box re-round (D530) ran under the box-local save, not the
|
||||
canonical eep**. D530's "canonical eep" provenance claim and first-stem
|
||||
table are void as canonical-save evidence (D530 entry + README amended in
|
||||
place; the table's numbers do check out against the 10-05 report).
|
||||
**The win set is unaffected** — `verify.sh`'s `pin_eep` was correct.
|
||||
- Fix: the loop now re-pins `cp "$CANON_EEP" "$EEP"` per level (EEP_ORIG
|
||||
kept for the exit-restore only); `cd "$ROOT"` added (the loop's
|
||||
dump/golden paths are root-relative, contradicting the header's
|
||||
"invoked from anywhere" claim).
|
||||
- **Re-captured:** shipped the fixed script to the box (sha matched), fresh
|
||||
21-level round with `DISPLAY=:0` → 21/21 rc=0, 63 frames. **47/63 differ
|
||||
from the D530 box-local-save set** (save content demonstrably moves
|
||||
frames), 16 byte-identical. Committed into the linux goldens.
|
||||
- **Renderer finding (corrects the 07d item-2 note):** even with
|
||||
`DISPLAY=:0` the box today reports no usable glxinfo renderer (software
|
||||
fallback → black read-backs) — the WSLg GPU display is
|
||||
**session-state-dependent** (the 10-05 re-round's p7_report pixel table
|
||||
proves it was GPU-backed then). Today's `verify.sh sweep` against the new
|
||||
goldens: **21/21 PASS, 0 FAIL, crash-detect only** (log
|
||||
`scratch/p7-verify-pixel-pull.log`). The pixel-gated verdict (incl. the
|
||||
four D117 flaky first stems) is owed for a GPU-display window.
|
||||
- Docs: D531 entry + §F row (regenerated CSV, 394 lines, `--check` OK),
|
||||
D530 amended in place, golden README intro + History, ROADMAP Golden
|
||||
baselines row (was still on D523 framing) + new P12 U5 row. PII addendum
|
||||
#2 (63 PNGs, 0 metadata tags).
|
||||
|
||||
**U5 should-fixes (rows on the ROADMAP, not yet applied):**
|
||||
1. `verify.sh` `pin_ini_640x480 2>/dev/null || true` fails OPEN (pin_eep
|
||||
fails closed) — a failed ini write runs the gate under the user's
|
||||
personal ini → spurious verdicts. Make it abort.
|
||||
2. `GOLDEN_SEED="${GE_RSEED:-…}"` lets a stray env var re-seed the gate —
|
||||
warn or hard-pin (capture inherits the same override via its eval out
|
||||
of verify.sh, so gate/capture stay consistent either way).
|
||||
3. `audiodebug.ps1` `-AB`/`-Old` are documented dead no-ops (nit).
|
||||
|
||||
## User to review at ~14:00 EDT (supersedes the 07d list)
|
||||
- 8 local commits: `aa19b354` (site SEO/redundancy), `2c378e7e` +
|
||||
`24b084d0` (Known issues), `ada7bbb1` (D530 goldens — now AMENDED BY
|
||||
D531), `e9cf2ddf` (D530 addendum), `4829fd94` (D531), `d2d75e11`
|
||||
(ROADMAP), `164920c6` (D531 addendum).
|
||||
- Preview: `node scratch/build_preview.mjs site` → `scratch/_site/` on :8777.
|
||||
|
||||
## Still owed (unchanged, plus)
|
||||
- Pixel-gated box verify in a WSLg GPU-display window (never-do 6 applies
|
||||
if the flaky four go red: exclude/widen, do NOT recapture).
|
||||
- The three U5 should-fixes above; P12 U2/U6/U7; HANDOFF 07c item 2
|
||||
(maintainer review of the 12-file docs batch); squash → B7/B8/B9; push
|
||||
`release/v0.5.0` + tag.
|
||||
- LEGAL review pass at push time (screenshots rule — 47 new linux PNGs are
|
||||
the same class: box-captured, no metadata).
|
||||
|
||||
---
|
||||
|
||||
# HANDOFF — 2026-10-05 (session 07f) (D532 + squash re-cut + PUSH)
|
||||
|
||||
## Pushed (2026-10-05 (session 07e)/f, maintainer approved)
|
||||
- **GitHub** `origin`: new branch `release/v0.5.0` (the re-cut squashed
|
||||
chain, 33 commits, tip `f077435a`) + annotated tag `v0.5.0`.
|
||||
**`origin/main` untouched** (`0e8c2ce2`) — main merge + public release
|
||||
wait for the maintainer's playtest.
|
||||
- **Forgejo mirror**: `release/v0.5.0-squashed` + tag `v0.5.0`.
|
||||
- Squash re-cut: `scratch/p11b-squash.py` (p11 + new tip `4dd1d56d`,
|
||||
assert 488, new group 33 covering D529-D532 + the site/amber pass).
|
||||
Tip tree byte-identical (B7), LAN scrub of intermediate trees
|
||||
re-applied, `pre-squash-v050` -> `4dd1d56d` (B6), tag message in
|
||||
`scratch/tag-msg-v050.txt` (B8), PII/legal addenda on the final tree
|
||||
(B9: clean; 4 pre-existing toolchain-path sites only).
|
||||
- **D532** (`4dd1d56d`) landed before the cut: verify.sh fail-closed
|
||||
ini pin + hard-pinned seed (warn on stray `GE_RSEED`), audiodebug
|
||||
dead switches removed. Docs: D532 entry/row, ROADMAP U5 row applied.
|
||||
|
||||
## Now owed (in order)
|
||||
1. **Maintainer playtest** (C6 list: D511-D514/D519 items) on the
|
||||
`release/v0.5.0` build → then remove the "not yet playtested live"
|
||||
block and cut the `gh release` (C1-C9; bundles built FROM the pushed
|
||||
tree).
|
||||
2. **Pixel-gated box verify** in a WSLg GPU-display window (D531; the
|
||||
box worktree `~/gh-fullhist-wt-p7` is still at `442eb2ff` — needs a
|
||||
bundle transfer of the new tip; no LAN route, options per the P7
|
||||
handback §8).
|
||||
3. **P12 U2/U6/U7** quick passes (U1/U3/U4/U5 PASS; U6 = build+CI
|
||||
diff, U7 = docs diff — read-only, ROADMAP rows for should-fixes).
|
||||
4. CI on the new GitHub branch: first real run of the SLSA
|
||||
build-provenance attestation (ROADMAP "Release build-provenance
|
||||
attestation" row: confirm, then delete).
|
||||
5. Box-side parallel: self-gate on the release branch (crash-detect
|
||||
until the GPU window).
|
||||
|
||||
## Local state
|
||||
`release/v0.4.1` @ `4dd1d56d` (== the pushed squashed tip tree), tree
|
||||
clean. `release/v0.5.0` / `release/v0.5.0-squashed` @ `f077435a`.
|
||||
`pre-squash-v050` @ `4dd1d56d`. Nothing else pending locally.
|
||||
|
||||
---
|
||||
|
||||
# HANDOFF — 2026-10-05 (session 07g) (push reverted; held local)
|
||||
|
||||
- **GitHub push REVERTED** (branch `release/v0.5.0` + tag `v0.5.0` deleted,
|
||||
verified via `git ls-remote`); backup lives on the private Forgejo mirror
|
||||
(`release/v0.5.0-squashed` + tag `v0.5.0` @ `f077435a`). Local refs:
|
||||
`release/v0.5.0` / `release/v0.5.0-squashed` @ `f077435a`,
|
||||
`pre-squash-v050` @ `4dd1d56d`.
|
||||
- **Standing rule (maintainer):** backups → Forgejo, never GitHub; GitHub
|
||||
pushes only after the maintainer approves everything.
|
||||
- **Docs finalization owed:** the batch review (`scratch/docs-batch-review.txt`,
|
||||
commit `ba29c558` — 16 text files) and the **PR/SEO language pass**
|
||||
(brief written: `scratch/pr-seo-revise-prompt.md` — tiers T1/T2/T3, voice,
|
||||
SEO parity checklist, hard rules; example fix = the v0.5.0 News tagline
|
||||
leading with "plain-English wording" + the UK/US spelling item demoted to
|
||||
"small stuff").
|
||||
- Then: playtest (C6) → `gh release` (C1–C9) → the ONE approved GitHub push
|
||||
(release branch + tag + release) → main.
|
||||
|
||||
---
|
||||
@@ -12,8 +12,8 @@ part-time direction. The goal, the setup, the timeline, and an honest read on
|
||||
what did and didn't work.*
|
||||
|
||||
> *Snapshot as of the v0.3.0 milestone (20 Sep 2026; findings through D321).
|
||||
> v0.4.0 (28 Sep) extended the timeline with the options/input work -- the
|
||||
> README's Background section carries the final project numbers.*
|
||||
> v0.4.0 (28 Sep) extended the timeline with the options/input work — the
|
||||
> README's "How it was made" section carries the final project numbers.*
|
||||
|
||||
## Contents
|
||||
|
||||
@@ -300,25 +300,8 @@ last few weeks), which has driven the most recent work. The local menu:
|
||||
**mostly deprecated now**: hand-offs between agents are done by hand for now,
|
||||
pending a better parallel-agent handoff system that drops the MCP overhead.
|
||||
- **GPT-6 (Sol)** via [OpenRouter](https://openrouter.ai) — a frontier hosted
|
||||
model, **trialed** to see how it held up (not the hardest-work tool). Its
|
||||
code output is still owed a code-quality audit in this doc.
|
||||
model, **trialed** to see how it held up (not the hardest-work tool).
|
||||
|
||||
The practical effect: the project stopped depending on any one model or its
|
||||
usage limits. The local GPU is now the default path for high-volume work, with
|
||||
hosted frontier models reserved for the problems the local models can't close.
|
||||
|
||||
**Measurement owed.** Which of these was best on a given task — and each
|
||||
model's rough cost-to-performance ratio — has not yet been measured properly;
|
||||
attributing individual commits to the model that produced them is still a
|
||||
manual pass. That includes a **code-quality audit of the GPT-6 (Sol) trial**.
|
||||
All of it is pending and will be added here when it lands.
|
||||
|
||||
A concrete reason the commit-date route is unreliable: the `D350` commit
|
||||
(`1303c0eb`, "expose watch-backed Bond settings in PC options and F10")
|
||||
carries a **27 Sep** timestamp on both its author and committer dates, but
|
||||
the session notes place that work on **4 Oct**. Because the two git dates
|
||||
agree, this is **not** a rebase artifact (a rebase would have moved the
|
||||
committer date while preserving the author date); it is a genuine divergence
|
||||
between the recorded commit time and the working session, and resolving it
|
||||
takes the session log, not the commit date. This is the class of edge case
|
||||
the attribution pass has to walk by hand.
|
||||
@@ -382,14 +382,16 @@ D519,FIXED,"One PC options UI: the file-select ""PC Options"" entry opens the F1
|
||||
D520,FIXED,"F10 overlay slider wedge, slider marker and dropdown arrow antialiased (they stepped in whole canvas pixels that grow with the window) —",FIXED (headless before/after capture; by-eye owed)
|
||||
D521,PARTIAL,A fixed-frame golden window that overlaps the intro flyby is platform-nondeterministic (cross-platform goldens); verify.sh's linux pixel-gate skip is driver-co…,PARTIAL (rule recorded 2026-10-04; the two residual bands CLOSED 2026-10-05 by D525's box re-round —
|
||||
D522,FIXED,The golden window's frame-900 stem is not settled gameplay on several levels —,FIXED 2026-10-05 (recipe-side re-base:
|
||||
D523,CLOSED,The golden recipe does not pin save state:,SUPERSEDED by D529 (2026-10-07) —
|
||||
D523,CLOSED,The golden recipe does not pin save state:,SUPERSEDED by D529 (2026-10-05) —
|
||||
D524,FIXED,The golden tooling was destructive and drift-prone:,FIXED 2026-10-05 (both pins idempotent —
|
||||
D525,FIXED,"The whole <level>/linux/ golden set was stale, not just on the six re-based levels —","FIXED 2026-10-05 (21-level box re-round, 63 frames, save pinned present; structural parity 21/21, Archives/Streets bands attributed to save state, not a renderer)"
|
||||
D526,CLOSED,P13 Dam-ending grate / edge-railing transparency is faithful N64 behaviour (port == 1964/GEPD); the per-triangle census probe is retained as a generic draw-sta…,"CLOSED — faithful, confirmed on 1964/GEPD (2026-10-07):"
|
||||
D526,CLOSED,P13 Dam-ending grate / edge-railing transparency is faithful N64 behaviour (port == 1964/GEPD); the per-triangle census probe is retained as a generic draw-sta…,"CLOSED — faithful, confirmed on 1964/GEPD (2026-10-05):"
|
||||
D527,OPEN,GE_PCDUMP written first:last (a colon where the dash belongs) silently dumps EVERY frame —,OPEN (harness documentation; a log-or-fail-closed fix is owed in the port layer)
|
||||
D528,OPEN,"GE_STARTMENU skips the EEPROM read, so front-end-only sessions never import the emulator save —",OPEN (harness documentation; the D514 imported-save test must run from a normal boot; a log-or-import fix is owed in the port layer)
|
||||
D529,FIXED,The golden gate depends on the save file's CONTENT —,FIXED 2026-10-07 (canonical save in-tree at tools_pc/golden/ge007.eep; verify.sh installs it like the ini pin; all 21 win sets re-captured under it —
|
||||
D530,?,The box (X220) linux golden re-round landed —,AMENDED BY D531 (2026-10-07) —
|
||||
D531,FIXED,capture_p7.sh's D529 adaptation was incomplete —,"FIXED 2026-10-07 (loop re-pins the canonical save per level + cd ""$ROOT""; fresh 21/21 box re-capture committed —"
|
||||
D532,FIXED,The three P12 U5 should-fixes applied —,FIXED 2026-10-07 (tooling-only:
|
||||
D529,FIXED,The golden gate depends on the save file's CONTENT —,FIXED 2026-10-05 (canonical save in-tree at tools_pc/golden/ge007.eep; verify.sh installs it like the ini pin; all 21 win sets re-captured under it —
|
||||
D530,?,The box (X220) linux golden re-round landed —,AMENDED BY D531 (2026-10-05) —
|
||||
D531,FIXED,capture_p7.sh's D529 adaptation was incomplete —,"FIXED 2026-10-05 (loop re-pins the canonical save per level + cd ""$ROOT""; fresh 21/21 box re-capture committed —"
|
||||
D532,FIXED,The three P12 U5 should-fixes applied —,FIXED 2026-10-05 (tooling-only:
|
||||
D533,FIXED,"The probe-doc drift that would have failed CI, plus three tracked-file accuracy/hygiene fixes (release-sweep spot-check) —",FIXED 2026-10-05 (GE-ENV-PROBES.md missing the GE_D526 family → gen_env_probes.py --check rc 1 = a CI-failing step; build-pc.sh local MSYS2 root in two messages; docs/fidelity.md og line; release-not…
|
||||
D534,FIXED,Pre-release review of the 2026-10-05 local batch —,FIXED 2026-10-05 (verify.sh/capture_p7.sh INT/TERM trap; release-notes linux-gate wording; dead security-and-fidelity-status.md links; future-dated 2026-10-07 labels normalised; D526 probe dangling-e…
|
||||
D450,FIXED,"Unplugging and replugging a controller was not picked up (user, GameSir-G7 Pro; 2026-09-29).","FIXED — port-only: the render thread's gfx_sdl_handle_events drains the same SDL queue as video.c's host pump but had no case for SDL_CONTROLLERDEVICEADDED/REMOVED, so it usually swallowed them and i…"
|
||||
|
+103
-18
@@ -790,16 +790,18 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
||||
| D520 | **F10 overlay slider wedge, slider marker and dropdown arrow antialiased (they stepped in whole canvas pixels that grow with the window)** — Port-only; D504 follow-up, P4k investigation; full `## D520` entry at file tail | FIXED (headless before/after capture; by-eye owed) |
|
||||
| D521 | **A fixed-frame golden window that overlaps the intro flyby is platform-nondeterministic (cross-platform goldens); verify.sh's linux pixel-gate skip is driver-conditional** — Port-only (docs + verify.sh probe); D117 class, P7; full `## D521` entry at the end of this file | PARTIAL (rule recorded 2026-10-04; the two residual bands CLOSED 2026-10-05 by D525's box re-round — save state, not a renderer; cross-platform parity stays informational, the gate is per platform) |
|
||||
| D522 | **The golden window's frame-900 stem is not settled gameplay on several levels — the win golden gate is not green (5/21 REGRESSION honest sequential, 7/21 concurrent)** — Golden gate; D117 follow-up; full `## D522` entry at file tail | FIXED 2026-10-05 (recipe-side re-base: per-level windows settled on every level; win gate 21/21 PASS honest sequential; no tol limit raised) |
|
||||
| D523 | **The golden recipe does not pin save state: `verify.sh` pins the ini but never touches `data/ge007.eep`, and the goldens were captured with a save present** — Golden gate; D514/D522 follow-up; full `## D523` entry at file tail | SUPERSEDED by D529 (2026-10-07) — the frame depends on the save's *content*, not its presence (the presence claim was only ever measured on Archives); the gate now installs the canonical in-tree save `tools_pc/golden/ge007.eep` |
|
||||
| D523 | **The golden recipe does not pin save state: `verify.sh` pins the ini but never touches `data/ge007.eep`, and the goldens were captured with a save present** — Golden gate; D514/D522 follow-up; full `## D523` entry at file tail | SUPERSEDED by D529 (2026-10-05) — the frame depends on the save's *content*, not its presence (the presence claim was only ever measured on Archives); the gate now installs the canonical in-tree save `tools_pc/golden/ge007.eep` |
|
||||
| D524 | **The golden tooling was destructive and drift-prone: `verify.sh`'s per-level ini/save pin snapshotted the previous level's game-written file (a sweep overwrites the user's own `data/ge007.ini`), and `capture_p7.sh` hardcoded the pre-D522 windows while deleting the save it captures with** — Golden tooling (U5 review of `tools_pc/**`); D522/D523 follow-up; full `## D524` entry at file tail | FIXED 2026-10-05 (both pins idempotent — first call snapshots the user's files, every level re-pins from that snapshot; `capture_p7.sh` reads the recipe out of `verify.sh` and requires the save present) |
|
||||
| D525 | **The whole `<level>/linux/` golden set was stale, not just on the six re-based levels — re-rounding it closes D521's two residual render bands** — Golden gate (P7b, box); D521/D522/D523 follow-up; full `## D525` entry at file tail | FIXED 2026-10-05 (21-level box re-round, 63 frames, save pinned present; structural parity 21/21, Archives/Streets bands attributed to save state, not a renderer) |
|
||||
| D526 | **P13 Dam-ending grate / edge-railing transparency is faithful N64 behaviour (port == 1964/GEPD); the per-triangle census probe is retained as a generic draw-state diagnostic** — P13 Dam ending (B1 lead); full `## D526` entry at file tail | CLOSED — faithful, confirmed on 1964/GEPD (2026-10-07): the show-through is in both (port == N64), so no port bug, no fix (D306/D291 class); the per-triangle census probe (GE_D526/GE_D526BOX/GE_D526MAX) is retained as a generic diagnostic |
|
||||
| D526 | **P13 Dam-ending grate / edge-railing transparency is faithful N64 behaviour (port == 1964/GEPD); the per-triangle census probe is retained as a generic draw-state diagnostic** — P13 Dam ending (B1 lead); full `## D526` entry at file tail | CLOSED — faithful, confirmed on 1964/GEPD (2026-10-05): the show-through is in both (port == N64), so no port bug, no fix (D306/D291 class); the per-triangle census probe (GE_D526/GE_D526BOX/GE_D526MAX) is retained as a generic diagnostic |
|
||||
| D527 | **`GE_PCDUMP` written `first:last` (a colon where the dash belongs) silently dumps EVERY frame** — harness trap (`port/src/video.c`); full `## D527` entry at file tail | OPEN (harness documentation; a log-or-fail-closed fix is owed in the port layer) |
|
||||
| D528 | **`GE_STARTMENU` skips the EEPROM read, so front-end-only sessions never import the emulator save** — harness trap; D514 follow-up; full `## D528` entry at file tail | OPEN (harness documentation; the D514 imported-save test must run from a normal boot; a log-or-import fix is owed in the port layer) |
|
||||
| D529 | **The golden gate depends on the save file's CONTENT — the D523 "presence, not which save" claim is refuted; the gate must pin a canonical save** — Golden gate; D523 follow-up (D525/D524); full `## D529` entry at file tail | FIXED 2026-10-07 (canonical save in-tree at `tools_pc/golden/ge007.eep`; `verify.sh` installs it like the ini pin; all 21 win sets re-captured under it — three consecutive clean 21/21 sweeps are the valid green record; the no-arg `verify.sh` path now exits 1; the box linux re-round under it landed as D530) |
|
||||
| D530 | **The box (X220) linux golden re-round landed — first cross-machine test of the four D117 flaky levels** — Golden gate (P7, box); D529 never-do 3/6 follow-up; full `## D530` entry at file tail | AMENDED BY D531 (2026-10-07) — the "canonical eep" provenance claim was wrong: the re-round ran under the box-LOCAL save (the `capture_p7.sh` per-level re-pin bug); the D531 re-capture under the true canonical eep supersedes this set |
|
||||
| D531 | **`capture_p7.sh`'s D529 adaptation was incomplete — the per-level re-pin restored the local save, so the 2026-10-05 box re-round ran under the box-local save; fixed + re-captured under the canonical eep** — Golden gate (P7, box); D529/D530 follow-up, P12 U5 review finding; full `## D531` entry at file tail | FIXED 2026-10-07 (loop re-pins the canonical save per level + `cd "$ROOT"`; fresh 21/21 box re-capture committed — 47/63 frames differ from the box-local-save set; pixel-gated box verify owed for a window with the box's WSLg GPU display active — today's session is on the software fallback, black read-backs) |
|
||||
| D532 | **The three P12 U5 should-fixes applied — the gate's ini pin now fails closed, the seed is hard-pinned (stray `GE_RSEED` warns), and `audiodebug.ps1`'s dead A/B switches are gone** — golden gate + tooling; D531/U5 follow-up; full `## D532` entry at file tail | FIXED 2026-10-07 (tooling-only: `pin_ini_640x480` fails closed like `pin_eep`; `GOLDEN_SEED` literal + warning, capture `eval` unaffected; `-AB`/`-Old`/`-OldMode` removed with a note) |
|
||||
| D529 | **The golden gate depends on the save file's CONTENT — the D523 "presence, not which save" claim is refuted; the gate must pin a canonical save** — Golden gate; D523 follow-up (D525/D524); full `## D529` entry at file tail | FIXED 2026-10-05 (canonical save in-tree at `tools_pc/golden/ge007.eep`; `verify.sh` installs it like the ini pin; all 21 win sets re-captured under it — three consecutive clean 21/21 sweeps are the valid green record; the no-arg `verify.sh` path now exits 1; the box linux re-round under it landed as D530) |
|
||||
| D530 | **The box (X220) linux golden re-round landed — first cross-machine test of the four D117 flaky levels** — Golden gate (P7, box); D529 never-do 3/6 follow-up; full `## D530` entry at file tail | AMENDED BY D531 (2026-10-05) — the "canonical eep" provenance claim was wrong: the re-round ran under the box-LOCAL save (the `capture_p7.sh` per-level re-pin bug); the D531 re-capture under the true canonical eep supersedes this set |
|
||||
| D531 | **`capture_p7.sh`'s D529 adaptation was incomplete — the per-level re-pin restored the local save, so the 2026-10-05 box re-round ran under the box-local save; fixed + re-captured under the canonical eep** — Golden gate (P7, box); D529/D530 follow-up, P12 U5 review finding; full `## D531` entry at file tail | FIXED 2026-10-05 (loop re-pins the canonical save per level + `cd "$ROOT"`; fresh 21/21 box re-capture committed — 47/63 frames differ from the box-local-save set; pixel-gated box verify owed for a window with the box's WSLg GPU display active — today's session is on the software fallback, black read-backs) |
|
||||
| D532 | **The three P12 U5 should-fixes applied — the gate's ini pin now fails closed, the seed is hard-pinned (stray `GE_RSEED` warns), and `audiodebug.ps1`'s dead A/B switches are gone** — golden gate + tooling; D531/U5 follow-up; full `## D532` entry at file tail | FIXED 2026-10-05 (tooling-only: `pin_ini_640x480` fails closed like `pin_eep`; `GOLDEN_SEED` literal + warning, capture `eval` unaffected; `-AB`/`-Old`/`-OldMode` removed with a note) |
|
||||
| D533 | **The probe-doc drift that would have failed CI, plus three tracked-file accuracy/hygiene fixes (release-sweep spot-check)** — release gate (P12 U2/U6/U7 spot-checks); full `## D533` entry at file tail | FIXED 2026-10-05 (`GE-ENV-PROBES.md` missing the `GE_D526` family → `gen_env_probes.py --check` rc 1 = a CI-failing step; `build-pc.sh` local MSYS2 root in two messages; `docs/fidelity.md` og line; release-notes gate paragraph quoted a pre-D531 spread) |
|
||||
| D534 | **Pre-release review of the 2026-10-05 local batch — Ctrl-C in the golden gate could leave the user's save replaced, plus doc accuracy fixes** — release gate; full `## D534` entry at file tail | FIXED 2026-10-05 (`verify.sh`/`capture_p7.sh` INT/TERM trap; release-notes linux-gate wording; dead `security-and-fidelity-status.md` links; future-dated `2026-10-07` labels normalised; D526 probe dangling-else; verify.sh usage range) |
|
||||
| D407 | **Tanks cannot be boarded/exited on PC — the v0.4.0 use/reload split (D378/D393) removed the B-button tap the engine's tank handlers in `bondview2.c` consume (user report 2026-09-28, Runway/Streets)** — full `## D407` entry at file tail | PARTIAL (fix landed in v0.4.0, port-only): present `GE_CONT_B` on the use (E / pad A) rising edge only while `g_PlayerIsInTank == 1` or `g_BondCanEnterTank != 0`; E keeps its D378 no-reload-fallback semantics elsewhere, N64 layout unaffected. D407(b) same cycle: front PC Options page-edge highlight clamp + mouse-wheel / W-S paging (wheel queue consumed on the menu, D223); its wheel mapping shipped inverted and was fixed to match W/S (wheel up = step up). D407(c): board-animation lockout, menu-accept B gate in tank states, in-tank aim routed through the legacy velocity stick + `Input.TankAimScale` knob. RESOLVED 2026-09-28: all port-only (src/game zero-diff), 10 TANKDBG probes stripped, release binary verified clean, user live tank drive signed off (board + exit OK, aim feel good). |
|
||||
| D408 | **`Game.SkipIntro` skips the post-mission failure dossier: with it on, entering a level then aborting (watch Z+A) or dying (KIA) returns straight to the menus — no REPORT / "Mission status: KILLED IN ACTION / ABORTED" screen** (user report 2026-09-28; save/AllUnlocked ruled out) — full `## D408` entry at file tail | OPEN (cosmetic, not root-caused past the handoff site). v0.4.0 decision: SkipIntro stays EXPERIMENTAL / not recommended for regular users — F10 row relabelled "Skip intro (EXPERIMENTAL)". |
|
||||
| D450 | **Unplugging and replugging a controller was not picked up (user, GameSir-G7 Pro; 2026-09-29).** — full `## D450` entry at file tail | FIXED — port-only: the render thread's `gfx_sdl_handle_events` drains the same SDL queue as video.c's host pump but had no case for `SDL_CONTROLLERDEVICEADDED/REMOVED`, so it usually swallowed them and `inputRescanPads` never ran. Both pumps now post a request; the rescan runs at the top of `inputUpdate`, on the thread that reads the pads. |
|
||||
@@ -17155,7 +17157,7 @@ keep: the next `./build-pc.sh` run reconfigures in place and picks up x86_64.
|
||||
|
||||
**Fix owed (recipe-side only; no game-code change):** either (a) move the capture window to stems settled on every level (1200–1800:300 is the measured candidate) and re-capture the 63 `win/` PNGs plus the box's linux set, or (b) keep the set and state the gate honestly (structural green + per-pixel marginal at 900) in `golden/README.md`, the ROADMAP row and the known-issues table. Driver: `scratch/sweep-par.sh` (gitignored; mirrors `verify.sh`'s ini pin, `GE_*` recipe, framediff flags and per-level limits, one cwd per level so runs can overlap — parallel verdicts are diagnosis only, the honest numbers come from the `JOBS=1` pass).
|
||||
|
||||
## D523: The golden recipe does not pin save state — `verify.sh` pins the ini but never touches `data/ge007.eep` (golden gate; D514/D522 follow-up) — **SUPERSEDED by D529 (2026-10-07): the frame depends on the save's CONTENT, not its presence; the gate now installs the canonical in-tree save**
|
||||
## D523: The golden recipe does not pin save state — `verify.sh` pins the ini but never touches `data/ge007.eep` (golden gate; D514/D522 follow-up) — **SUPERSEDED by D529 (2026-10-05): the frame depends on the save's CONTENT, not its presence; the gate now installs the canonical in-tree save**
|
||||
|
||||
**FIXED 2026-10-05 — `verify.sh` now pins the save file** (back up + require `data/ge007.eep`, mirroring the ini pin; it exits 2 with a message when a clone has none, rather than silently measuring a different scene), and `tools_pc/golden/README.md` states the pin. The measurements below are the record of why the gap mattered.
|
||||
|
||||
@@ -17193,7 +17195,7 @@ keep: the next `./build-pc.sh` run reconfigures in place and picks up x86_64.
|
||||
|
||||
## D526: P13 Dam-ending grate / edge-railing transparency is faithful N64 behaviour (port == 1964/GEPD); the per-triangle census probe is retained as a generic draw-state diagnostic
|
||||
|
||||
**CLOSED as faithful 2026-10-07 (no port bug; no fix).** The P13 "Dam-ending grate show-through" (2nd POSENDS camera: the area under the grate Bond stands on shows through — the 2D edge-railing/grate texture's between-anchors region) was triaged as a suspected B1 port bug (the grate quad's texture stage taking an alpha/blend path it shouldn't — D195/D268 class). To bucket it, a per-triangle draw-state census probe was built (this D526) and smoke-tested. The 1964/GEPD reference of the same 2nd-POSENDS shot then showed **the port and the N64 look the same** — the show-through is in *both*. So it is the original game's 2D grate/railing texture rendering, reproduced faithfully: a known issue that **closes in the D306/D291 class** (a "bug" that 1964 shows is intended behaviour). There is nothing to fix in `port/fast3d/`.
|
||||
**CLOSED as faithful 2026-10-05 (no port bug; no fix).** The P13 "Dam-ending grate show-through" (2nd POSENDS camera: the area under the grate Bond stands on shows through — the 2D edge-railing/grate texture's between-anchors region) was triaged as a suspected B1 port bug (the grate quad's texture stage taking an alpha/blend path it shouldn't — D195/D268 class). To bucket it, a per-triangle draw-state census probe was built (this D526) and smoke-tested. The 1964/GEPD reference of the same 2nd-POSENDS shot then showed **the port and the N64 look the same** — the show-through is in *both*. So it is the original game's 2D grate/railing texture rendering, reproduced faithfully: a known issue that **closes in the D306/D291 class** (a "bug" that 1964 shows is intended behaviour). There is nothing to fix in `port/fast3d/`.
|
||||
|
||||
**Probe (retained as a generic tool):** `d526_note_emit()` in `port/fast3d/gfx_pc.cpp`, folded into the D474 `tri_dbg()` gate (zero player cost when off). Env: `GE_D526="lo-hi"` (sim-frame window), `GE_D526BOX="x0 y0 x1 y1"` (NDC region, y-up; default whole screen), `GE_D526MAX=N` (cumulative per-triangle line cap, 400; the per-frame `D526F:` signature aggregate is uncapped). Emits to stderr: per-triangle NDC bbox, z/w, `gm`, `oml`, `omh`, combine mode, first-tile tmem/fmt/siz, prim + vertex alpha, use_alpha/modulate/invisible/2-cycle, plus a per-frame `D526F:` signature map. It is the only per-triangle *draw-state* census (D474/D75D/ZF/D303 are specialized) and is the right tool for the alpha/texture bug class (D195/D266/D268/D273).
|
||||
|
||||
@@ -17221,7 +17223,7 @@ Decision owed: document it (a NOTE log line when `GE_STARTMENU` is active: "EEPR
|
||||
|
||||
## D529: The golden gate depends on the save file's CONTENT — the D523 "presence, not which save" claim is refuted; the gate must pin a canonical save (golden gate; refines D523; follow-up to D525/D524)
|
||||
|
||||
**2026-10-07 (pre-push session).** The D523 pin installed *whichever* local save existed ("presence, not which save — Archives measures worst_cell 0.175625 on each of the four candidate saves and 21.557% with none"). That claim had only ever been measured **on Archives**. The 2026-10-07 sweep refutes it: the local `data/ge007.eep` had been rewritten by the live Dam-ending playtest sessions (md5 `a41d7ab…`, mtime 2026-10-05 07:27), and the honest sequential sweep under it produced **6/21 REGRESSION** on a *byte-identical binary* (the 2026-10-04 run had been 21/21).
|
||||
**2026-10-05 (pre-push session).** The D523 pin installed *whichever* local save existed ("presence, not which save — Archives measures worst_cell 0.175625 on each of the four candidate saves and 21.557% with none"). That claim had only ever been measured **on Archives**. The 2026-10-05 sweep refutes it: the local `data/ge007.eep` had been rewritten by the live Dam-ending playtest sessions (md5 `a41d7ab…`, mtime 2026-10-05 07:27), and the honest sequential sweep under it produced **6/21 REGRESSION** on a *byte-identical binary* (the 2026-10-04 run had been 21/21).
|
||||
|
||||
**The A/B (facility, window 900-1500:300):**
|
||||
|
||||
@@ -17238,7 +17240,7 @@ Two distinct classes in the 6-failure sweep, proven apart by the A/B:
|
||||
1. **Save-content dependent (facility, streets, jungle, cradle):** same failure signature (177.2–177.5 at the 1200/1500 stems — a *different scene* in-window, not a jitter class) only on the two saves with that content (the 2001 dexdrive save and the 10-05 local save share it; 2001-vintage saves apparently hold state that routes facility's intro differently). The other four candidates pass. **This is what D529 fixes: the gate installs ONE canonical save, so "which save" can never vary.**
|
||||
2. **D117 wall-clock flyby (dam@1500 4.9%, frigate@1000 3.2–8.3%, streets@1000 2.5–25.7%):** fails *identically on every save* — the window's first stem is inside the real-time-paced intro flyby, so the content at a given sim frame varies with machine load (D117, long-known, previously masked because the Oct-4 goldens happened to be captured the same way).
|
||||
|
||||
**Resolution (FIXED 2026-10-07, same session):**
|
||||
**Resolution (FIXED 2026-10-05, same session):**
|
||||
- **Canonical save in-tree: `tools_pc/golden/ge007.eep`** (2 KB, = `ge007 copy.eep`, the stable pre-live-sessions save the Oct-4 gate was green on). In-tree = a fresh clone or CI can run the gate with zero external state, and the D523 "fresh clone has no save → exit 2" failure branch is gone for good.
|
||||
- **`verify.sh` installs it like the ini pin** (snapshot the local `data/ge007.eep` if any → install the canonical → restore-or-remove on exit). The local playtest save is never the gate's input.
|
||||
- **All 21 win golden sets re-captured under the canonical save** (`scratch/golden-recapture-win-v050.sh`; 21/21 rc=0). The first four flaky levels (dam/frigate/streets/jungle — the D117 flyby stems) were re-captured again **clean** (no concurrent processes) after the first interleaved capture.
|
||||
@@ -17247,11 +17249,11 @@ Two distinct classes in the 6-failure sweep, proven apart by the A/B:
|
||||
|
||||
**Why this is not a renderer drift:** the binary is byte-identical to the 2026-10-04 21/21 run; the only variable that changed is `data/ge007.eep`, and the A/B is save-keyed (same binary, four passing saves, one failing save). No renderer code changed.
|
||||
|
||||
**Never do:** (1) run the golden gate against a local playtest save — it is exactly this class of drift; always the in-tree canonical eep. (2) claim "the frame depends on save *presence*" again — it depends on *content*; the D523 claim survives only as the (superseded) measurement on Archives. (3) treat the linux 63-frame set as valid under the canonical eep before the box re-round lands — it is the D525 cleared-eep round, and **no linux number may be cited (e.g. in the README pass) until that re-round lands**. (4) cite `verify.sh` with **no arguments** as a green run — a sweep is `verify.sh sweep` (the no-arg path now exits 1, closing the trap in code). (5) run a re-capture concurrently with a sweep (contention moves the D117 flyby stems). (6) treat **same-session** sweeps as proof the four D117 flaky levels (dam/frigate/streets/jungle) are stable across wall-clock: the first-stem content is time-dependent and the pin was fixed to "now" — the cross-machine test is the box re-round; **if those four go red there, the fix is to exclude or widen the first-stem cell for those levels, NOT to re-capture again** (an independent reviewer's 2026-10-07 verification flagged this; same-session worst_cell swings were streets 8.38→4.41, jungle 1.42→3.87). (7) trust a `capture_p7.sh` round's provenance claim without checking WHICH save state the loop actually installed — the D524-era per-level re-pin restored the local save and silently overwrote D529's pre-loop canonical install (D531); the linux set is only "canonical" if the loop line says `cp "$CANON_EEP"`.
|
||||
**Never do:** (1) run the golden gate against a local playtest save — it is exactly this class of drift; always the in-tree canonical eep. (2) claim "the frame depends on save *presence*" again — it depends on *content*; the D523 claim survives only as the (superseded) measurement on Archives. (3) treat the linux 63-frame set as valid under the canonical eep before the box re-round lands — it is the D525 cleared-eep round, and **no linux number may be cited (e.g. in the README pass) until that re-round lands**. (4) cite `verify.sh` with **no arguments** as a green run — a sweep is `verify.sh sweep` (the no-arg path now exits 1, closing the trap in code). (5) run a re-capture concurrently with a sweep (contention moves the D117 flyby stems). (6) treat **same-session** sweeps as proof the four D117 flaky levels (dam/frigate/streets/jungle) are stable across wall-clock: the first-stem content is time-dependent and the pin was fixed to "now" — the cross-machine test is the box re-round; **if those four go red there, the fix is to exclude or widen the first-stem cell for those levels, NOT to re-capture again** (an independent reviewer's 2026-10-05 verification flagged this; same-session worst_cell swings were streets 8.38→4.41, jungle 1.42→3.87). (7) trust a `capture_p7.sh` round's provenance claim without checking WHICH save state the loop actually installed — the D524-era per-level re-pin restored the local save and silently overwrote D529's pre-loop canonical install (D531); the linux set is only "canonical" if the loop line says `cp "$CANON_EEP"`.
|
||||
|
||||
## D531: `capture_p7.sh`'s D529 adaptation was incomplete — the per-level re-pin restored the local save, so the 2026-10-05 box re-round ran under the box-local save (not the canonical one); fixed + re-captured (golden gate; D529/D530 follow-up; P12 U5 review finding)
|
||||
|
||||
**Blocker found in the 2026-10-07 P12 U5 review (local session).** `tools_pc/capture_p7.sh`'s per-level loop had `cp "$EEP_ORIG" "$EEP"` (introduced by D524 to make the tool non-destructive): it restored the pre-capture **local** save — or a 0-byte eep when `data/ge007.eep` did not exist — before every level. D529's adaptation (`8fbf8aa0`) installed the canonical save (`cp "$CANON_EEP" "$EEP"`) **once, before the loop** and added the canonical-missing guard, but left the D524-era re-pin line in place — so from level 1 the canonical install was silently overwritten and every capture ran under the local save state. The header comment ("the pinned save, restored before every level") asserted what the code did not do.
|
||||
**Blocker found in the 2026-10-05 P12 U5 review (local session).** `tools_pc/capture_p7.sh`'s per-level loop had `cp "$EEP_ORIG" "$EEP"` (introduced by D524 to make the tool non-destructive): it restored the pre-capture **local** save — or a 0-byte eep when `data/ge007.eep` did not exist — before every level. D529's adaptation (`8fbf8aa0`) installed the canonical save (`cp "$CANON_EEP" "$EEP"`) **once, before the loop** and added the canonical-missing guard, but left the D524-era re-pin line in place — so from level 1 the canonical install was silently overwritten and every capture ran under the local save state. The header comment ("the pinned save, restored before every level") asserted what the code did not do.
|
||||
|
||||
**Impact — D530's provenance claim is wrong:** the 2026-10-05 box re-round (`~/p7-reround.log`, "P7 re-round DONE") ran under the box-local save (`sha256 d9f306…`, 2 KB — distinct from the in-tree canonical `65247b…`), not the canonical eep. D530's / the golden README's / the commit message's "63 PNGs under the canonical eep" did not hold, and D530's first-stem table (measured in that re-round's report against the old D525 goldens — its numbers do check out against the report) is not canonical-save evidence. **The win set is unaffected** — `verify.sh`'s `pin_eep` re-installs the canonical save on every call (that code was right); the bug was capture-side only.
|
||||
|
||||
@@ -17259,13 +17261,13 @@ Two distinct classes in the 6-failure sweep, proven apart by the A/B:
|
||||
|
||||
**Re-capture (this batch):** a fresh 21-level box re-round under the canonical eep (21/21 rc=0, 63 frames), committed into `tools_pc/golden/<level>/linux/` replacing the D530 box-local-save set: **47/63 frames differ** from it (save content demonstrably moves the frames — D529's drift class), 16 byte-identical (save-independent scenes). **Note on the box's pixel capability:** the 10-05 re-round's p7_report diff table (1–26% over on real content) proves its WSLg GPU display was active then; today the box reads back **black even with `DISPLAY=:0`** (`glxinfo -B` under `:0` reports no usable renderer — the WSLg GPU display is session-state-dependent, and today's session is on the software fallback), so today's `verify.sh` runs (D530's crash-detect sweep and this batch's `~/p7-verify-pixel.log`) are legitimately crash-detect-only. The pixel-gated cross-machine verify is owed for a window in which the box's GPU display is up again.
|
||||
|
||||
**Pixel-gated cross-machine gate (the real D117 datum):** `verify.sh sweep` on the box against the new canonical goldens — **2026-10-07 attempt (log `~/p7-verify-pixel.log`): 21/21 PASS, 0 FAIL, crash-detect only** (the run's renderer probe correctly failed closed on today's software-fallback session, so it adds stability, not, pixel data); the pixel verdict — including the four flaky levels' first stems — is owed for a window in which the box's WSLg GPU display is active. If the four flaky levels (dam/frigate/streets/jungle) go red there, the never-do 6 decision stands: exclude or widen the first-stem cell, do NOT re-capture.
|
||||
**Pixel-gated cross-machine gate (the real D117 datum):** `verify.sh sweep` on the box against the new canonical goldens — **2026-10-05 attempt (log `~/p7-verify-pixel.log`): 21/21 PASS, 0 FAIL, crash-detect only** (the run's renderer probe correctly failed closed on today's software-fallback session, so it adds stability, not, pixel data); the pixel verdict — including the four flaky levels' first stems — is owed for a window in which the box's WSLg GPU display is active. If the four flaky levels (dam/frigate/streets/jungle) go red there, the never-do 6 decision stands: exclude or widen the first-stem cell, do NOT re-capture.
|
||||
|
||||
**U5 review notes from the same pass (non-blockers):** the three should-fixes below were applied 2026-10-07 as D532 (gate hardening: fail-closed ini pin, hard-pinned seed, dead A/B switches removed).
|
||||
**U5 review notes from the same pass (non-blockers):** the three should-fixes below were applied 2026-10-05 as D532 (gate hardening: fail-closed ini pin, hard-pinned seed, dead A/B switches removed).
|
||||
|
||||
## D532: the three P12 U5 should-fixes applied — the golden gate's ini pin now fails closed, the seed is hard-pinned (a stray `GE_RSEED` warns instead of re-seeding), and `audiodebug.ps1`'s dead A/B switches are gone (golden gate + tooling; D531/U5 follow-up)
|
||||
|
||||
**2026-10-07 (local session).** Three tooling-only fixes, no game logic:
|
||||
**2026-10-05 (local session).** Three tooling-only fixes, no game logic:
|
||||
|
||||
1. **`verify.sh` `pin_ini_640x480` failed OPEN** — the three call sites (`single`/`sweep`/`parity`) were `pin_ini_640x480 2>/dev/null || true`, so a failed ini write (missing `data/`, read-only tree, failed snapshot) ran the gate under an **unpinned ini** — the frame depends on a defaults-only 640x480 ini exactly like the save pin (D529), so that was a spurious-verdict source, not a skipped nicety. The pin now fails closed (snapshot and write both `error + exit 2`, matching `pin_eep`'s style) and the call sites are plain.
|
||||
2. **`GOLDEN_SEED` hard-pinned** — it was `"${GE_RSEED:-0x0123456789abcdef}"`, so a stray `GE_RSEED` in the environment silently re-seeded the documented-as-pinned gate (frames shift → spurious verdicts). It is now the literal, with a warning when a differing env var is present (verified: `GE_RSEED=0xdead` warns, the pinned value is silent). `capture_p7.sh`'s `eval grep -m1 '^GOLDEN_SEED='` still picks up the same line, so capture and gate stay consistent.
|
||||
@@ -17273,9 +17275,9 @@ Two distinct classes in the 6-failure sweep, proven apart by the A/B:
|
||||
|
||||
PS parse: 0 errors; `bash -n` clean; the warning path verified. **Owed (unchanged):** the pixel-gated box verify in a WSLg GPU-display window (D531).
|
||||
|
||||
## D530: The box (X220) linux golden re-round landed — first cross-machine test of the four D117 flaky levels (golden gate; D529 never-do 3/6 follow-up) — **AMENDED BY D531 (2026-10-07): the 10-05 re-round ran under the box-LOCAL save, not the canonical one (the capture_p7.sh bug); the true canonical re-capture is D531**
|
||||
## D530: The box (X220) linux golden re-round landed — first cross-machine test of the four D117 flaky levels (golden gate; D529 never-do 3/6 follow-up) — **AMENDED BY D531 (2026-10-05): the 10-05 re-round ran under the box-LOCAL save, not the canonical one (the capture_p7.sh bug); the true canonical re-capture is D531**
|
||||
|
||||
**2026-10-07 (local session).** The box re-round D529 owed (never-do 3: the linux set was the D525 *cleared*-eep round and no linux number could be cited until it was re-rounded under `tools_pc/golden/ge007.eep`) ran on X220 on 2026-10-05 (tree `442eb2ff`, worktree `~/gh-fullhist-wt-p7`, log `~/p7-reround.log` hit `P7 re-round DONE` 12:53 EDT). **21/21 levels rc=0** (the box self-gate is crash-detect only — the pixel probe fails closed on the box, D244). This session pulled the 63 PNGs (21 levels × 3 frames) and committed them into `tools_pc/golden/<level>/linux/`, replacing the D525 set: 51/63 differ from the D525 round; the 12/63 that are byte-identical are save-independent scenes — including **frigate's first stem (001000)**, a direct D117 stability signal. **AMENDED BY D531: that re-round ran under the box-local save (the `capture_p7.sh` bug), so the "canonical eep" provenance claim — and the first-stem table below, as canonical-save evidence — does not hold; the D531 re-capture supersedes this set.**
|
||||
**2026-10-05 (local session).** The box re-round D529 owed (never-do 3: the linux set was the D525 *cleared*-eep round and no linux number could be cited until it was re-rounded under `tools_pc/golden/ge007.eep`) ran on X220 on 2026-10-05 (tree `442eb2ff`, worktree `~/gh-fullhist-wt-p7`, log `~/p7-reround.log` hit `P7 re-round DONE` 12:53 EDT). **21/21 levels rc=0** (the box self-gate is crash-detect only — the pixel probe fails closed on the box, D244). This session pulled the 63 PNGs (21 levels × 3 frames) and committed them into `tools_pc/golden/<level>/linux/`, replacing the D525 set: 51/63 differ from the D525 round; the 12/63 that are byte-identical are save-independent scenes — including **frigate's first stem (001000)**, a direct D117 stability signal. **AMENDED BY D531: that re-round ran under the box-local save (the `capture_p7.sh` bug), so the "canonical eep" provenance claim — and the first-stem table below, as canonical-save evidence — does not hold; the D531 re-capture supersedes this set.**
|
||||
|
||||
The `fail` rows in the box report are the expected cross-eep diffs against the *old* in-tree set, not regressions: structural tier is all `ok` (phash ≤ 3, cradle@40 the documented exception; Cuba 26.4% inside its documented 23.7–36.3% structural-only range).
|
||||
|
||||
@@ -17290,4 +17292,87 @@ The `fail` rows in the box report are the expected cross-eep diffs against the *
|
||||
|
||||
All four sit in the stable-levels' range (e.g. silo 0.41–0.84% over, worst_cell 0.41–0.42 is the quietest; archives 1.51–2.31 is noisier). **None went red → the never-do 6 decision closes with NO recipe change** (no first-stem cell excluded or widened on the linux side).
|
||||
|
||||
**Unblocked (D529 never-do 3):** the README/index v0.5.0 line "re-based on both platforms (21 levels, 63 frames each)" now stands on a canonical-eep linux set (D531's re-capture; the D530 set it first pointed at was the box-local-save round — see D531). **Fresh box sweep (crash-detect):** with the new goldens staged on the box, `verify.sh sweep` (2026-10-07) is **21/21 PASS** — but that run was crash-detect only (GE_PCDUMP reads black on the box's llvmpipe/WSLg, the D244 note), so it is a stability re-check, not a pixel datum. **AMENDED BY D531:** the "black frames" were **not** simply the no-DISPLAY llvmpipe path — the box's WSLg display is session-state-dependent: its 10-05 session was GPU-backed (the re-round's p7_report pixel table proves real frames), while today's reads back black even with `DISPLAY=:0` (software fallback; `glxinfo -B` reports no usable renderer). D531's pixel-gated attempt (21/21 crash-detect, `~/p7-verify-pixel.log`) is valid as a stability re-check; the pixel datum is owed for a GPU-display window.
|
||||
**Unblocked (D529 never-do 3):** the README/index v0.5.0 line "re-based on both platforms (21 levels, 63 frames each)" now stands on a canonical-eep linux set (D531's re-capture; the D530 set it first pointed at was the box-local-save round — see D531). **Fresh box sweep (crash-detect):** with the new goldens staged on the box, `verify.sh sweep` (2026-10-05) is **21/21 PASS** — but that run was crash-detect only (GE_PCDUMP reads black on the box's llvmpipe/WSLg, the D244 note), so it is a stability re-check, not a pixel datum. **AMENDED BY D531:** the "black frames" were **not** simply the no-DISPLAY llvmpipe path — the box's WSLg display is session-state-dependent: its 10-05 session was GPU-backed (the re-round's p7_report pixel table proves real frames), while today's reads back black even with `DISPLAY=:0` (software fallback; `glxinfo -B` reports no usable renderer). D531's pixel-gated attempt (21/21 crash-detect, `~/p7-verify-pixel.log`) is valid as a stability re-check; the pixel datum is owed for a GPU-display window.
|
||||
|
||||
## D533: release-sweep spot-check — the probe-doc drift that would have failed CI, plus three tracked-file accuracy/hygiene fixes (release gate; P12 U2/U6/U7 spot-checks)
|
||||
|
||||
**What was checked (P12 U2/U6/U7 spot-checks, read-only until a defect was found):**
|
||||
the EEP import path (`eepimport.c`: fixed-size `save_data[96]` + `smallSave[32]`
|
||||
copies, the 6-region backup rotation bounded at `.bak99`), the seat model
|
||||
(`MAX_PADS = 4` with `seat < 0 || seat >= MAX_PADS` guards, per-seat arrays
|
||||
`padPreset`/`padActPrev`/`padSelectPrev` all `[MAX_PADS]`), the ini/config
|
||||
buffers (`configRegisterString`'s `bufSize-1` `strncpy`, `padStr[MAX_PADS][PA_COUNT][32]`
|
||||
filled by `snprintf` with `sizeof`), the build's region-macro set against the
|
||||
N64 Makefile's `LCDEFS` (exact match for ntsc/pal/jpn-final), and the published
|
||||
docs' claims against the findings index.
|
||||
|
||||
**The CI-blocking one:** `tools_pc/gen_env_probes.py --check` returned **rc 1** —
|
||||
three probe vars in `port/fast3d/gfx_pc.cpp` (`GE_D526`, `GE_D526BOX`,
|
||||
`GE_D526MAX`, the D526 box-tolerance family) had no row in
|
||||
`docs/dev/GE-ENV-PROBES.md`. The self-hosted workflow runs that check as a hard
|
||||
step ("Check generated dev indexes are current"), so the pushed branch would
|
||||
have carried a red CI step. Fixed by documenting the family (it was already
|
||||
listed in the `docs/porting-notes.md` §F10 probe table — the drift is between
|
||||
the two generated-doc sources, not a missing record).
|
||||
|
||||
**`build-pc.sh` carried a local machine path.** Two messages named the
|
||||
maintainer's alternate MSYS2 root (`D:\<games>\msys64` form — the tree here was
|
||||
built for a different drive letter than the one it runs from). AGENTS rule 1
|
||||
forbids local absolute paths in tracked files; both sites now say `C:\msys64`,
|
||||
which is what the surrounding "add `C:\msys64\mingw64\bin` to your PATH" advice
|
||||
already says. No behaviour change (the strings are diagnostics only; the toolchain
|
||||
discovery itself is path-derived via `_ge_find_mingw_bin()`).
|
||||
|
||||
**`docs/fidelity.md` og description.** It read "…the one `#ifdef PORT` fix…" —
|
||||
misleading: `src/` carries 736 `#ifdef PORT` gates (the §A1 class), and the
|
||||
finding's claim is that exactly **one** of them is a game-logic-adjacent change.
|
||||
The description now reads "one game-logic-adjacent change", and the trim keeps it
|
||||
under the 160-char og limit (158). The body's precise claim is unchanged.
|
||||
|
||||
**The release notes quoted a stale measurement.** The Reference-frame-gate
|
||||
paragraph carried the D525 cross-platform spread (0.348–3.983 %, worst cell mean
|
||||
4.43, phash ≤6 except cradle 40) — measured before D531 re-captured all 21 linux
|
||||
sets under the canonical save (47/63 frames moved). Recomputed from the
|
||||
**committed** pairs (`framediff.py` win-vs-linux at the stems, tol 2): exact
|
||||
**0.380–5.120 %** on the 20 non-Cuba levels (silo's 900 stem is the outlier —
|
||||
cell mean 34.3, phash 10; streets 3.223–4.566), structural **21/21 clean**, max
|
||||
phash 40 (cradle, at the threshold); Cuba 1.357–12.663 % is the structural-tier-only
|
||||
level. The notes now carry the recomputed band and name the two gate pins a
|
||||
reader would otherwise have to look up (canonical save content — D529; hard-pinned
|
||||
seed — D532). The D525 figures stay in the ROADMAP row as the historical record
|
||||
for closing the two residual bands; the row now also carries the recomputed band.
|
||||
|
||||
**Not changed (judgement calls left alone):** the `eepimport.c` `.bak99`
|
||||
overwrite-on-rotation nit (cosmetic, 99-deep rotation is unreachable in practice),
|
||||
the `docs/ROADMAP.md` "Known issues" heading anchor (valid), and the site pages'
|
||||
own staleness (presentation layer, per AGENTS).
|
||||
|
||||
## D534: pre-release review of the 2026-10-05 local batch — Ctrl-C in the golden gate could leave the user's save replaced, plus doc accuracy fixes (release gate)
|
||||
|
||||
**Scope:** a read-only review of the 23 local commits of 2026-10-05
|
||||
(`8fbf8aa0^..0b0f610c`) before the v0.5.0 cut; defects fixed in one batch.
|
||||
|
||||
**The real one — an interrupted gate run could clobber `data/ge007.eep`.**
|
||||
`verify.sh` armed `trap 'restore_ini; restore_eep; kill_ours' EXIT INT TERM`
|
||||
(`capture_p7.sh` the same shape). Bash runs an INT/TERM trap and then
|
||||
*continues* the script: the restore put the user's save back and deleted the
|
||||
snapshot, but `EEP_PIN_BAK` stayed set, so the next level's `pin_eep` skipped
|
||||
the snapshot and installed the canonical save, and the final EXIT restore
|
||||
copied from a deleted file — the user's own save was left replaced on disk.
|
||||
Fix: restore on `EXIT` only, `INT`/`TERM` just `exit 130`/`143` (which fires
|
||||
EXIT once); `restore_eep`/`restore_ini` now clear their snapshot state, so
|
||||
they are idempotent. Tooling-only; the recipe is unchanged.
|
||||
|
||||
**Doc accuracy:** the release notes said "each platform's gate is green"
|
||||
while the same paragraph said the linux pixel gate did not run — now "Windows
|
||||
green; linux crash gate green, pixel verdict owed". `docs/security-and-fidelity-status.md`
|
||||
was split into `security.md` + `fidelity.md` but still linked from `README.md`,
|
||||
`.github/SECURITY.md` and the AGENTS.md site-page list (dead on publish) —
|
||||
repointed. Fifty-odd `2026-10-07` dates (session labels "07a…07k" that leaked
|
||||
in as calendar dates; every commit is dated 2026-10-05) normalised to
|
||||
2026-10-05; lettered labels became "2026-10-05 (session 07x)".
|
||||
|
||||
**Nits:** the D526 census probe had a dangling `else` (bound to the inner
|
||||
`if`, so with no `GE_D526BOX` the off-screen filter never ran) — braced;
|
||||
`verify.sh`'s usage print (`sed -n '2,32p'`) cut the `--json`/`--against`
|
||||
lines — now `2,34p`; an unbalanced bold in the ROADMAP Golden-baselines row.
|
||||
@@ -1,16 +1,17 @@
|
||||
---
|
||||
title: Under the Hood
|
||||
title: Documentation
|
||||
description: The technical documentation for the GoldenEye 007 PC port; the architecture, the N64-to-PC bug catalogue, and how the project is developed.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
---
|
||||
|
||||
## Under the hood
|
||||
## Documentation
|
||||
|
||||
The technical documentation for the port: how it works under the covers, the
|
||||
catalogue of N64→PC bugs it had to fix, and how the project is developed.
|
||||
(Building and running from source live on the separate
|
||||
[Building](building.md) page.)
|
||||
The technical documentation for the port: the **architecture** and how the
|
||||
project is **developed**. (Building and running from source live on the
|
||||
separate [Building](building.md) page.)
|
||||
|
||||
### How it works
|
||||
## Architecture
|
||||
|
||||
- **[Internals](internals.md)** — the architecture: the software RSP, the
|
||||
port layer, the asset pipeline, and the phased plan. The single reference
|
||||
@@ -18,7 +19,7 @@ catalogue of N64→PC bugs it had to fix, and how the project is developed.
|
||||
- **[Porting notes](porting-notes.md)** — the catalogue of N64→PC bugs: the
|
||||
recurring classes of defect and the ground-truth pattern each fix follows.
|
||||
|
||||
### How it's developed
|
||||
## Development
|
||||
|
||||
- **[Development process](dev-process.md)** — the investigation workflow:
|
||||
task budgets, file partitioning, the finding-log discipline, and the rules
|
||||
@@ -26,18 +27,7 @@ catalogue of N64→PC bugs it had to fix, and how the project is developed.
|
||||
- **[Agentic development](dev/agentic-development.md)** — the case study:
|
||||
how the two-AI-agent setup ran, its timeline and numbers, and an honest
|
||||
read on what did and didn't work.
|
||||
|
||||
### Topic notes
|
||||
|
||||
Short, single-topic notes — the quick-orientation version of the longer docs
|
||||
above:
|
||||
|
||||
- **[The software RSP](the-software-rsp.md)** — how the N64's graphics
|
||||
coprocessor is emulated in software.
|
||||
- **[The asset pipeline](the-asset-pipeline.md)** — how ROM assets become the
|
||||
files the port loads at runtime.
|
||||
- **[Framerate and pacing](framerate-and-pacing.md)** — the steady 60 fps,
|
||||
frame pacing and per-frame timing.
|
||||
- **[Input and aim](input-and-aim.md)** — controllers, keyboard, mouse aim
|
||||
and rebinding.
|
||||
- **[Saves](saves.md)** — the file-backed N64 save.
|
||||
- **[Security status](security.md)** — what the release packages install
|
||||
(and don't): no networking, no telemetry, no ROM, no system writes.
|
||||
- **[Fidelity status](fidelity.md)** — how faithfully the port reproduces
|
||||
the N64 game's logic, and what was audited to back that claim.
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
title: Fidelity status
|
||||
description: How faithfully the port reproduces the N64 game: unmodified decompiled logic, Makefile-mirrored region macros, one game-logic-adjacent change, and PRNG notes.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
---
|
||||
|
||||
## Fidelity status
|
||||
|
||||
This page answers one question plainly: *how faithfully does the port
|
||||
actually reproduce the original N64 game's logic*?
|
||||
The audit was run end-to-end on 2026-09-15 and re-verified for the v0.3.0
|
||||
release bundles on 2026-09-18.
|
||||
|
||||
**v0.5.0 update pass, 2026-10-05:** two of the checks were re-run
|
||||
directly against the current tree — the region build macros were
|
||||
compared line-by-line against the original N64 Makefile's macro sets
|
||||
(all three regions match exactly), and the library file classification
|
||||
(which original files compile versus get PC-shimmed) was re-checked
|
||||
against the project's own ground-truth manifest (the CMake build
|
||||
compiles the libultra and libultrare audio sets, the gu matrix helpers,
|
||||
and `io/vitbl.c` only — no silent gaps, no silent duplicates). The
|
||||
full game-logic audit was not re-run in this pass; recent `src/game`
|
||||
edits on the release branch are finding-gated (for example the D519
|
||||
front-end options work, and a model-c scripted-camera clamp removal
|
||||
that returned those files to pure decompilation). The full engineering
|
||||
record behind each item is in the project's finding log
|
||||
([`docs/dev/findings.md`](https://github.com/jkdansereau/goldeneye-pc-port/blob/main/docs/dev/findings.md)).
|
||||
|
||||
## The rule and what was checked
|
||||
|
||||
The port's non-negotiable rule is that decompiled game logic is never
|
||||
changed — only genuine N64-hardware dependencies get a PC-side
|
||||
replacement, in the `port/` layer. This was audited directly:
|
||||
|
||||
- **Region build macros** exactly mirror the original N64 Makefile's macro
|
||||
sets for all three regions — verified line-by-line (re-run 2026-10-05).
|
||||
- **The audio/library file classification** (which original files compile
|
||||
vs. get PC-shimmed) exactly matches the project's own ground-truth
|
||||
manifest — no silent gaps, no silent duplicates (re-run 2026-10-05).
|
||||
- **The one shipped game-logic-adjacent change** (a portal-culling
|
||||
float-precision fix, D271) is `#ifdef PORT`-gated, documented in the
|
||||
finding log, and moves *toward* matching N64 behavior, not away from it.
|
||||
Every other deviation from the decompiled source is one of the documented
|
||||
32→64-bit pointer-width ABI corrections described above.
|
||||
|
||||
## One issue, found and fixed before v0.3.0 shipped
|
||||
|
||||
The port's random-number generator (`port/src/random.c`) was documented
|
||||
as a bit-exact port of the N64's PRNG, but wasn't — a shift-operation
|
||||
helper didn't match the real MIPS64 instruction semantics it was meant to
|
||||
mirror. This was independently confirmed by hand-tracing the assembly
|
||||
against the C port, tracked as finding D284, and fixed before the release
|
||||
(verified clean across a full level sweep — all 20 missions plus the
|
||||
ending sequence — no crashes). It affected loot placement, AI behavior
|
||||
variance, and replay-state determinism from the very first random draw,
|
||||
in every release before v0.3.0. Because of the fix, RNG-derived output —
|
||||
including the save-file CRC — changed, which meant existing save files
|
||||
and any previously recorded replays no longer validate; v0.3.0's release
|
||||
notes describe the automatic save migration that handles this. We'd
|
||||
rather say this plainly than let a "verified bit-exact" claim stand
|
||||
uncorrected, both when it was wrong and now that it's fixed.
|
||||
|
||||
Everything else checked (the documented ABI/pointer-width exceptions used
|
||||
for the 32-to-64-bit transition, a sample of the finding log's own claimed
|
||||
fixes against the actual current code) matched what's documented.
|
||||
|
||||
---
|
||||
|
||||
*This page is kept current alongside future releases. Its source review is a
|
||||
manual, human-reviewed process today — see the project roadmap for plans to
|
||||
partially automate the mechanical parts of it.*
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
title: Framerate and pacing
|
||||
description: How the GoldenEye 007 PC port holds a steady 60 fps and keeps per-frame game timing correct on a fast CPU.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
---
|
||||
|
||||
## Framerate and pacing
|
||||
|
||||
+158
-164
@@ -5,6 +5,16 @@ description: >-
|
||||
A native PC port of GoldenEye 007 (Nintendo 64, 1997), built from
|
||||
decompiled source with a software RSP. v0.5.0 for Windows, Linux and
|
||||
Steam Deck.
|
||||
# Freshness signals for jekyll-seo-tag (article:published_time / modified_time
|
||||
# and the WebPage JSON-LD dates). Keep these equal to the last real content
|
||||
# change of THIS page, not to the last release.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
locale: en_US
|
||||
# The masthead is this page's title, so its first content h2 must NOT get the
|
||||
# amber page-title look (double header). See the .flat-title rule in
|
||||
# _includes/head-custom.html.
|
||||
flat_title: true
|
||||
---
|
||||
|
||||
A native PC port of _GoldenEye 007_ (Rare, 1997, Nintendo 64), compiled from
|
||||
@@ -16,60 +26,82 @@ 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.
|
||||
|
||||
[Download](#download) · [News](#news) · [See it running](#see-it-running) · [Known issues](#known-issues) · [Documentation](#documentation)
|
||||
[Status](#status) · [Download](#download) · [See it running](#see-it-running) · [Known issues](#known-issues) · [Documentation](#documentation)
|
||||
|
||||
**Status: v0.5.0 (2026-10-05) — fully playable, with a small set of known
|
||||
caveats.** The single-player campaign and the 2–4 player split-screen
|
||||
multiplayer both run at a steady 60 fps. The single-player campaign is
|
||||
completable end to end (all 20 missions plus the ending-credits sequence),
|
||||
and the 2–4 player split-screen campaign is supported on every multiplayer
|
||||
map; both were playtested on Windows, Linux and Steam Deck. This release
|
||||
adds **one
|
||||
options menu** (laid out like the Perfect Dark port's, with plain-English
|
||||
wording, real-unit sliders and a one-line description per option), the game's
|
||||
own **N64 control styles as a per-seat preset**, **direct loading of
|
||||
emulator save files**, a **scalable HUD overlay**, fullscreen and
|
||||
window-centring controls, and a **fidelity round checked frame-by-frame
|
||||
against the N64 game** (fog, aspect-ratio letterboxing, the Watch menu's own
|
||||
settings). What remains is a short list, under
|
||||
[Known issues](#known-issues).
|
||||
## Status
|
||||
|
||||
**This is a pre-1.0 release, not a finished product** — v1.0 is the target
|
||||
<div class="cblock">
|
||||
|
||||
### v0.5.0 (2026-10-05) — the campaign and split-screen both run end to end.
|
||||
|
||||
- **Single-player campaign complete.** All 20 missions plus the
|
||||
ending-credits sequence, completable end to end at a steady 60 fps.
|
||||
- **2–4 player split-screen multiplayer.** Supported on every multiplayer
|
||||
map; playtested on Windows, Linux and Steam Deck.
|
||||
- **One real options system.** A single menu, laid out like the Perfect
|
||||
Dark port's — plain-English wording, real-unit sliders, a one-line
|
||||
description per option — with the game's own **N64 control styles as a
|
||||
per-seat preset**.
|
||||
- **Emulator save files load directly.** Copy a 1964 / Project64 save into
|
||||
`data/` and it is converted on first launch.
|
||||
- **A scalable HUD overlay**, fullscreen and window-centring controls, and
|
||||
antialiased overlay controls.
|
||||
- **A fidelity round checked frame-by-frame against the N64 game** (fog,
|
||||
aspect-ratio letterboxing, the Watch menu's own settings), with the
|
||||
reference-frame gate re-based on both platforms (21 levels, 63 frames
|
||||
each).
|
||||
- The small stuff: a menu wording, units and help-text pass, and
|
||||
standardised menu spelling.
|
||||
|
||||
</div>
|
||||
|
||||
What remains is a short list, under [Known issues](#known-issues).
|
||||
|
||||
**This is a pre-1.0 release, not a finished product.** v1.0 is the target
|
||||
for a polished, feature-complete build; expect missing features and the
|
||||
occasional breaking change until then. See the
|
||||
[README's Roadmap section](https://github.com/jkdansereau/goldeneye-pc-port#roadmap)
|
||||
for direction (PAL/JP ROM support, macOS and ARM builds, the remaining small
|
||||
accuracy differences, and post-1.0 opt-in extras).
|
||||
occasional breaking change until then. The [README's Roadmap
|
||||
section](https://github.com/jkdansereau/goldeneye-pc-port#roadmap) is the
|
||||
single tracker for what comes next.
|
||||
|
||||
## News
|
||||
<details id="known-issues">
|
||||
<summary>Known issues</summary>
|
||||
|
||||
- **2026-10-05** — **v0.5.0**: one options menu with plain-English wording,
|
||||
real-unit sliders and a one-line description per option; the N64 control
|
||||
styles as a per-seat preset; direct emulator-save loading; a scalable HUD
|
||||
overlay; fullscreen and window-centring controls; and a fidelity round
|
||||
checked frame-by-frame against the N64 game. The reference-frame gate was
|
||||
re-based on both platforms (21 levels, 63 frames each).
|
||||
[Release notes](https://github.com/jkdansereau/goldeneye-pc-port/releases/tag/v0.5.0) ·
|
||||
[downloads](#download).
|
||||
- **2026-09-28** — **v0.4.0**: native widescreen, a complete aim system for
|
||||
mouse and controller, in-game key rebinding, crosshair customization,
|
||||
rumble-pak haptics, a rebuilt options overlay, and a broad fidelity-fix
|
||||
pass (water, particles, billboard trees, front-end logo, gunshot SFX, a
|
||||
true stable 60 fps). [Release notes](https://github.com/jkdansereau/goldeneye-pc-port/releases/tag/v0.4.0) ·
|
||||
[downloads](#download).
|
||||
- **2026-09-20** — **v0.3.0**: the first release with the complete campaign
|
||||
playable end to end at 60 fps on Windows, Linux, and Steam Deck.
|
||||
[Release notes](https://github.com/jkdansereau/goldeneye-pc-port/releases/tag/v0.3.0).
|
||||
- **2026-09-04 → 2026-09-16** — **v0.1.0 – v0.2.2**: the alpha and beta
|
||||
cycle — build chain, software RSP, first rendered frames, front end, and
|
||||
per-level stabilization across the campaign.
|
||||
<p>Full table in the <a href="https://github.com/jkdansereau/goldeneye-pc-port/blob/main/docs/ROADMAP.md#known-issues">roadmap's known-issues section</a>; root causes in the <a href="https://github.com/jkdansereau/goldeneye-pc-port/tree/main/docs/dev">finding log</a>.</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>NTSC-U ROMs only in the release packages.</strong> PAL and JP ROMs convert, build and run from source, but release packages ship the US (NTSC-U) ROM. On the roadmap.</li>
|
||||
<li><strong>Changing the aspect ratio in a level can briefly glitch the gun/hand model</strong> (cosmetic, one-off). Change the ratio from the front-end PC Options, or accept it (D509).</li>
|
||||
<li><strong>No macOS or ARM builds yet.</strong> Today the release ships Windows, Linux and Steam Deck (keyboard, mouse and controller-button rebinding are all supported, defaults in the <a href="https://github.com/jkdansereau/goldeneye-pc-port#controls">README's Controls section</a>); macOS and ARM are on the roadmap.</li>
|
||||
<li><strong><code>Skip intro</code> and <code>All unlocked</code> are experimental</strong> — leave them off for a normal playthrough. <code>All unlocked</code> has not written your save since v0.4.1, but saves made while it was on in builds before v0.4.1 can hold fake unlocks and are not repaired; back up <code>data/ge007.eep</code> if you used it on an older build (D442, D387).</li>
|
||||
<li><strong>The first frame of a level takes a little longer</strong> while its textures upload — a brief FPS-counter dip; nothing to fix (D475, D480).</li>
|
||||
<li><strong>In widescreen, far objects almost fully in fog can still show a faint distant building edge</strong> (4:3 matches the N64). Cosmetic (D503).</li>
|
||||
</ul>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Release history</summary>
|
||||
|
||||
<p class="warn"><strong>Warning:</strong> always use the latest release — earlier builds are kept in the release history for reference only; they lack the features and fixes of newer versions, so don't install an older release.</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>2026-10-05 — v0.5.0</strong>: what it adds is the Status list above. <a href="https://github.com/jkdansereau/goldeneye-pc-port/releases/tag/v0.5.0">Release notes</a>.</li>
|
||||
<li><strong>2026-09-28 — v0.4.0</strong>: native widescreen, a complete aim system for mouse and controller, in-game key rebinding, crosshair customization, rumble-pak haptics, a rebuilt options overlay, and a broad fidelity-fix pass. <a href="https://github.com/jkdansereau/goldeneye-pc-port/releases/tag/v0.4.0">Release notes</a>.</li>
|
||||
<li><strong>2026-09-20 — v0.3.0</strong>: the first release with the complete campaign playable end to end at 60 fps on Windows, Linux, and Steam Deck. <a href="https://github.com/jkdansereau/goldeneye-pc-port/releases/tag/v0.3.0">Release notes</a>.</li>
|
||||
<li><strong>2026-09-04 → 2026-09-16 — v0.1.0 – v0.2.2</strong>: the alpha and beta cycle — build chain, software RSP, first rendered frames, front end, and per-level stabilization across the campaign.</li>
|
||||
</ul>
|
||||
|
||||
</details>
|
||||
|
||||
## Download
|
||||
|
||||
<div class="cblock">
|
||||
|
||||
| Platform | Bundle | Notes |
|
||||
|---|---|---|
|
||||
| **Windows** (x86_64) | [win64.zip](https://github.com/jkdansereau/goldeneye-pc-port/releases) | Engine + runtime DLLs + the one-time asset tool. |
|
||||
| **Linux** (x86_64) / **Steam Deck** | [linux tarball](https://github.com/jkdansereau/goldeneye-pc-port/releases) | SDL2 is bundled, so it runs as-is on any distro, and sideloads onto a Deck with nothing installed. |
|
||||
| macOS / ARM Linux | — | Roadmap: not shipped yet. |
|
||||
|
||||
**Bring your own ROM.** Both bundles contain no ROM and no game assets: you
|
||||
supply your own GoldenEye 007 N64 ROM (the
|
||||
@@ -79,8 +111,16 @@ ROM; PAL and JP are on the roadmap. Then: unpack, drop the ROM in `data/`,
|
||||
and launch; the first run generates the derived assets automatically (no
|
||||
Python or other tooling needed). The full steps are in the
|
||||
[Quick start](https://github.com/jkdansereau/goldeneye-pc-port#quick-start);
|
||||
pre-built releases are legal to distribute precisely because they're useless
|
||||
without a ROM you already own.
|
||||
the packages carry no ROM or game assets, and run only with a ROM you
|
||||
already own. The binaries are not code-signed; each
|
||||
release artifact carries a GitHub build-provenance attestation you can
|
||||
verify with `gh attestation verify <file> --repo
|
||||
jkdansereau/goldeneye-pc-port`.
|
||||
|
||||
</div>
|
||||
|
||||
What the release actually installs is covered on [Security status](security.md);
|
||||
how faithfully it tracks the N64 game, on [Fidelity status](fidelity.md).
|
||||
|
||||
## See it running
|
||||
|
||||
@@ -91,74 +131,17 @@ without a ROM you already own.
|
||||
<span class="idx" id="vIdx">1 / 12</span>
|
||||
</div>
|
||||
<div class="vstage">
|
||||
<img id="vImg" src="img/shots/shot-01.jpg" alt="in-engine capture">
|
||||
<img id="vImg" src="img/shots/shot-01.jpg" alt="GoldenEye 007 PC port — Dam (v0.4.0 intro attract), in-engine capture">
|
||||
<button class="vbtn prev" id="vPrev" aria-label="previous capture">‹</button>
|
||||
<button class="vbtn next" id="vNext" aria-label="next capture">›</button>
|
||||
</div>
|
||||
<div class="vcap"><span id="vCap">Dam — v0.4.0 intro attract</span></div>
|
||||
</div>
|
||||
|
||||
<details>
|
||||
<summary><strong>Full gallery</strong>: 12 in-engine captures from a v0.4.0 intro-attract pass (3072×1728 widescreen, Sep 2026)</summary>
|
||||
|
||||
<p align="center">
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-01.jpg" width="100%" alt="In-engine: Dam (v0.4.0 intro attract)">
|
||||
<div><small>Dam</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-03.jpg" width="100%" alt="In-engine: Runway (v0.4.0 intro attract)">
|
||||
<div><small>Runway</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-04.jpg" width="100%" alt="In-engine: Surface (v0.4.0 intro attract)">
|
||||
<div><small>Surface</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-09.jpg" width="100%" alt="In-engine: Frigate (v0.4.0 intro attract)">
|
||||
<div><small>Frigate</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-11.jpg" width="100%" alt="In-engine: Surface 2 (v0.4.0 intro attract)">
|
||||
<div><small>Surface 2</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-16.jpg" width="100%" alt="In-engine: Statue (v0.4.0 intro attract)">
|
||||
<div><small>Statue</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-20.jpg" width="100%" alt="In-engine: Archives (v0.4.0 intro attract)">
|
||||
<div><small>Archives</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-21.jpg" width="100%" alt="In-engine: Cradle (v0.4.0 intro attract)">
|
||||
<div><small>Cradle</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-24.jpg" width="100%" alt="In-engine: Aztec (v0.4.0 intro attract)">
|
||||
<div><small>Aztec</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-27.jpg" width="100%" alt="In-engine: Control (v0.4.0 intro attract)">
|
||||
<div><small>Control</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-28.jpg" width="100%" alt="In-engine: Streets (v0.4.0 intro attract)">
|
||||
<div><small>Streets</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-29.jpg" width="100%" alt="In-engine: Jungle (v0.4.0 intro attract)">
|
||||
<div><small>Jungle</small></div>
|
||||
</div>
|
||||
</p>
|
||||
</details>
|
||||
|
||||
More captures may land here as playtesting continues.
|
||||
|
||||
## Play it, or take it apart
|
||||
|
||||
- **Try it yourself**: grab a bundle above, bring your own ROM, and play the
|
||||
campaign. It's an early cut for exactly this: if something breaks, an
|
||||
campaign. It's a pre-1.0 build for exactly this: if something breaks, an
|
||||
[issue](https://github.com/jkdansereau/goldeneye-pc-port/issues) with what
|
||||
you were doing is genuinely useful.
|
||||
- **Read the code**: the game logic in `src/` is unmodified decompilation;
|
||||
@@ -172,80 +155,51 @@ More captures may land here as playtesting continues.
|
||||
asset sidecar. [CONTRIBUTING](https://github.com/jkdansereau/goldeneye-pc-port/blob/main/CONTRIBUTING.md)
|
||||
has the ground rules that keep it faithful to the original game.
|
||||
- **AI disclosure**: development here used AI coding agents — Claude Code
|
||||
plus a local open-weight model on a single RTX 5090, directed by one person in their
|
||||
spare time. The project is as much a study of that process as it is a
|
||||
port, and the write-up is written to let you judge the result for yourself;
|
||||
it records what happened and takes no position for or against using LLMs
|
||||
on a project like this. See [the full
|
||||
plus a local open-weight model on a single RTX 5090, directed by one person
|
||||
in their spare time. The project is as much a study of that process as it
|
||||
is a port; the write-up records what happened and takes no position for or
|
||||
against using LLMs on a project like this. See [the full
|
||||
write-up](dev/agentic-development.md) — the setup, timeline, handoff
|
||||
workflow, and an honest account of what did and didn't work.
|
||||
|
||||
## How it works
|
||||
|
||||
The R4300 game code's logic and control flow are the decompilation's, and remain the
|
||||
reference we preserve. The port's changes inside `src/` are few in kind (mostly mechanical 32→64-bit pointer fixes, a couple of approved timing fixes, and the opt-in *All unlocked* hook), each gated behind `#ifdef PORT`. The N64's Reality Signal Processor, the graphics
|
||||
coprocessor that builds and executes each frame's display list, is emulated in
|
||||
software: the port interprets the graphics command stream (GBI) the game emits and translates it
|
||||
to OpenGL, bypassing the RDP entirely. Everything else that would touch N64
|
||||
hardware (video, audio, input, timers, save storage) is shimmed in a small
|
||||
dedicated layer, following the architecture of the Perfect Dark PC port from
|
||||
the same Rare engine family. Full detail: [Internals](internals.md); the bug
|
||||
The R4300 game code's logic and control flow are the decompilation's, and
|
||||
remain the reference we preserve. The port's changes inside `src/` are few in
|
||||
kind and each is gated behind `#ifdef PORT`: mechanical 32→64-bit
|
||||
pointer-width fixes, a couple of approved timing fixes, and the opt-in
|
||||
*All unlocked* and *Skip intro* hooks. The N64's Reality Signal Processor
|
||||
(RSP), the graphics coprocessor that builds and executes each frame's
|
||||
display list, is emulated in software: the port interprets the graphics
|
||||
command stream (GBI) the game emits and translates it to OpenGL, bypassing
|
||||
the RDP entirely. Everything else that would touch N64 hardware (video,
|
||||
audio, input, timers, save storage) is shimmed in a small dedicated layer,
|
||||
following the architecture of the Perfect Dark PC port from the same Rare
|
||||
engine family. Full detail: [Internals](internals.md); the bug
|
||||
catalogue: [Porting notes](porting-notes.md).
|
||||
|
||||
## Known issues
|
||||
|
||||
Known defects and limitations as of v0.5.0, each with its finding-log
|
||||
reference. The full list, with root causes and fix status: the
|
||||
[release notes](https://github.com/jkdansereau/goldeneye-pc-port/releases)
|
||||
and the [finding log](https://github.com/jkdansereau/goldeneye-pc-port/tree/main/docs/dev).
|
||||
|
||||
- **Facility — gas leak during Ourumov's monologue (D318).** If gas leaks,
|
||||
he can pause for up to ~10 s before the scripted shootout resumes. The
|
||||
race exists in the N64 original too (where it softlocks permanently);
|
||||
the port detects it and auto-recovers.
|
||||
- **F10 options overlay under native widescreen (D335b).** The overlay
|
||||
stretches with the window instead of pillarboxing like the front-end
|
||||
menus. Legible, cosmetic only; the F10 *Native widescreen* toggle
|
||||
restores the old stretched frame throughout. The world/HUD widescreen
|
||||
rendering itself is correct.
|
||||
- **Front-end Rareware logo (D75).** A subtle texture-filtering artifact;
|
||||
the Nintendo logo and legal page are clean. Cosmetic only.
|
||||
- **`All unlocked` is experimental (D387).** The fresh-install corruption
|
||||
case is fixed, but saves made while it is on are not guaranteed
|
||||
recoverable by switching it off — complete a level normally first, and
|
||||
back up `data/ge007.eep` before enabling it.
|
||||
- **No macOS or ARM builds yet** (both are on the
|
||||
[roadmap](https://github.com/jkdansereau/goldeneye-pc-port#roadmap));
|
||||
today the release ships Windows, Linux and Steam Deck. Keyboard, mouse
|
||||
and controller-button rebinding are all supported (defaults in the
|
||||
[README's Controls section](https://github.com/jkdansereau/goldeneye-pc-port#controls)).
|
||||
|
||||
What the release actually installs, and how faithfully it tracks the N64
|
||||
game: [Security & fidelity status](security-and-fidelity-status.md).
|
||||
|
||||
## Documentation
|
||||
|
||||
The technical docs live under [under the
|
||||
hood](under-the-hood.md) — the architecture, the N64→PC bug catalogue, and
|
||||
how the project is developed. [Building](building.md) covers building and
|
||||
running from source.
|
||||
The technical docs live on the [Documentation](documentation.md) page — the
|
||||
architecture, the N64→PC bug catalogue, and how the project is developed.
|
||||
[Building](building.md) covers building and running from source.
|
||||
|
||||
<script>
|
||||
// console-viewer carousel: one media slot, cycle the captures. Vanilla JS.
|
||||
(function () {
|
||||
var slides = [
|
||||
{ src:"img/shots/shot-01.jpg", cap:"Dam — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-03.jpg", cap:"Runway — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-04.jpg", cap:"Surface — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-09.jpg", cap:"Frigate — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-11.jpg", cap:"Surface 2 — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-16.jpg", cap:"Statue — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-20.jpg", cap:"Archives — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-21.jpg", cap:"Cradle — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-24.jpg", cap:"Aztec — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-27.jpg", cap:"Control — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-28.jpg", cap:"Streets — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-29.jpg", cap:"Jungle — v0.4.0 intro attract" }
|
||||
{ src:"img/shots/shot-01.jpg", cap:"Dam — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-03.jpg", cap:"Runway — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-04.jpg", cap:"Surface — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-09.jpg", cap:"Frigate — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-11.jpg", cap:"Surface 2 — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-16.jpg", cap:"Statue — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-20.jpg", cap:"Archives — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-21.jpg", cap:"Cradle — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-24.jpg", cap:"Aztec — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-27.jpg", cap:"Control — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-28.jpg", cap:"Streets — v0.4.0 intro attract" },
|
||||
{ src:"img/shots/shot-29.jpg", cap:"Jungle — v0.4.0 intro attract" }
|
||||
];
|
||||
var img = document.getElementById("vImg"),
|
||||
cap = document.getElementById("vCap"),
|
||||
@@ -254,7 +208,9 @@ running from source.
|
||||
function show(n) {
|
||||
i = (n + slides.length) % slides.length;
|
||||
img.src = slides[i].src;
|
||||
cap.innerHTML = slides[i].cap;
|
||||
img.alt = "GoldenEye 007 PC port — " + slides[i].cap +
|
||||
", in-engine capture, 3072×1728";
|
||||
cap.textContent = slides[i].cap;
|
||||
idx.textContent = (i + 1) + " / " + slides.length;
|
||||
}
|
||||
document.getElementById("vPrev").addEventListener("click", function () { show(i - 1); });
|
||||
@@ -266,3 +222,41 @@ running from source.
|
||||
show(0);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Software",
|
||||
"name": "GoldenEye 007 PC Port",
|
||||
"genericName": "Native PC port of a Nintendo 64 game",
|
||||
"softwareName": "GoldenEye 007 PC Port",
|
||||
"category": "GameCategory",
|
||||
"description": "A native PC build of GoldenEye 007 (Rare, 1997, Nintendo 64), compiled from the n64decomp/007 decompilation with the N64's RSP emulated in software. Ships no ROM and no game assets; you supply your own.",
|
||||
"softwareVersion": "0.5.0",
|
||||
"datePublished": "2026-10-05",
|
||||
"dateModified": "2026-10-05",
|
||||
"operatingSystem": ["Windows", "Linux", "Steam Deck"],
|
||||
"downloadUrl": "https://github.com/jkdansereau/goldeneye-pc-port/releases",
|
||||
"distributionType": "Software-Offline",
|
||||
"officialDistribution": {
|
||||
"@type": "SoftwareDistribution",
|
||||
"downloadUrl": "https://github.com/jkdansereau/goldeneye-pc-port/releases",
|
||||
"distributionLicense": "MIT"
|
||||
},
|
||||
"license": "https://opensource.org/licenses/MIT",
|
||||
"isFreeApplication": true,
|
||||
"url": "https://jkdansereau.github.io/goldeneye-pc-port/",
|
||||
"sameAs": "https://github.com/jkdansereau/goldeneye-pc-port",
|
||||
"publisher": {
|
||||
"@type": "Person",
|
||||
"name": "jkdansereau",
|
||||
"url": "https://github.com/jkdansereau"
|
||||
},
|
||||
"gallery": [
|
||||
"https://jkdansereau.github.io/goldeneye-pc-port/img/shots/shot-28.jpg",
|
||||
"https://jkdansereau.github.io/goldeneye-pc-port/img/shots/shot-01.jpg",
|
||||
"https://jkdansereau.github.io/goldeneye-pc-port/img/shots/shot-24.jpg"
|
||||
],
|
||||
"alternateName": "GoldenEye 007 (Nintendo 64, 1997) on the PC"
|
||||
}
|
||||
</script>
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
title: Input and aim
|
||||
description: How the GoldenEye 007 PC port maps keyboard, mouse and modern controllers onto the N64's controller, including mouse aim.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
---
|
||||
|
||||
## Input and aim
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ title: Internals
|
||||
description: Architecture behind the PC port; the software RSP-emulation approach, GoldenEye-vs-Perfect-Dark engine differences, and the phased development plan.
|
||||
---
|
||||
|
||||
## GoldenEye 007 PC Port: architecture & plan
|
||||
## Architecture & plan
|
||||
|
||||
> This began as the pre-implementation research note and is kept as the
|
||||
> architecture reference. Sections 1–9 describe the design; section 10 lists
|
||||
|
||||
@@ -19,14 +19,14 @@ good that you are looking at one of these.
|
||||
|
||||
## Contents
|
||||
|
||||
- [A. Pointer-width struct growth (32→64); the dominant class](#a-pointer-width-struct-growth-3264--the-dominant-class)
|
||||
- [A. Pointer-width struct growth (32→64); the dominant class](#a-pointer-width-struct-growth-3264-the-dominant-class)
|
||||
- [B. 16-byte PC `Gfx` / `Vtx` vs 8-byte N64](#b-16-byte-pc-gfx--vtx-vs-8-byte-n64)
|
||||
- [C. Big-endian rodata / ROM data read on little-endian PC](#c-big-endian-rodata--rom-data-read-on-little-endian-pc)
|
||||
- [C2. Port-layer / SDL shims](#c2-port-layer--sdl-shims)
|
||||
- [D. N64 hardware idioms fast3d does not emulate](#d-n64-hardware-idioms-fast3d-does-not-emulate)
|
||||
- [D2. The HUD/model "X-mirror"; RESOLVED](#d2-the-hudmodel-x-mirror-d114d116--resolved-it-was-an-upside-down-capture)
|
||||
- [D2. The HUD/model "X-mirror"; RESOLVED](#d2-the-hudmodel-x-mirror-d114d116-resolved-it-was-an-upside-down-capture)
|
||||
- [D3. GCC/mingw makes an all-non-negative `enum` UNSIGNED](#d3-gccmingw-makes-an-all-non-negative-enum-unsigned)
|
||||
- [D4. N64 "interrupts off" must be a real lock on PC](#d4-n64-interrupts-off-is-not-free-on-pc--it-must-be-a-real-lock)
|
||||
- [D4. N64 "interrupts off" must be a real lock on PC](#d4-n64-interrupts-off-is-not-free-on-pc-it-must-be-a-real-lock)
|
||||
- [D5. Loop bounds that assume linker adjacency of two globals](#d5-loop-bounds-that-assume-linker-adjacency-of-two-file-scope-globals)
|
||||
- [D12. Collapsing an LOD binding to tile 0 breaks a DETAIL binding](#d12-collapse-an-lod-binding-to-tile-0-is-wrong-for-a-two-texture-detail-binding-d236)
|
||||
- [D13. Per-render accumulation is not associative (1 vs 2–3 ticks/frame)](#d13-per-render-accumulation-is-not-associative-the-ports-1-tickframe-can-reach-states-the-n64s-23-ticksframe-never-did-d329)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
title: Saves
|
||||
description: How the GoldenEye 007 PC port backs the N64's EEPROM save with a plain file you can back up.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
---
|
||||
|
||||
## Saves
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
---
|
||||
title: Security & fidelity status
|
||||
description: What a release actually installs (no networking, no telemetry, no ROM or assets)
|
||||
and how faithfully the port tracks the original N64 game's logic.
|
||||
---
|
||||
|
||||
## Security & fidelity status
|
||||
|
||||
This page answers two questions plainly: *what does installing this put on
|
||||
your machine*, and *how faithfully does the port actually reproduce the
|
||||
original N64 game's logic*. Both were reviewed end-to-end on 2026-09-15 and
|
||||
re-verified for the v0.3.0 release bundles on 2026-09-18 (bundle contents,
|
||||
no-networking source check, and the asset converter). The no-networking source
|
||||
check was repeated against the `release/v0.4.1` tree on 2026-09-30 (no socket,
|
||||
HTTP or name-resolution calls in `src/` or `port/`; neither the engine nor the
|
||||
bundled `SDL2.dll` imports a networking DLL; no registry calls in the port's
|
||||
own code); the bundle contents were not re-checked then. The full engineering
|
||||
record behind each item is in the project's finding log
|
||||
([`docs/dev/findings.md`](dev/findings.md)).
|
||||
|
||||
## What a release actually installs
|
||||
|
||||
Each release (`goldeneye-pc-port-*-win64.zip` / `-linux-x86_64.tar.gz`)
|
||||
contains, and only contains: the game engine executable, a fixed set of
|
||||
standard runtime libraries (SDL2, zlib, and the MinGW/Linux runtime — no
|
||||
third-party downloads), the one-time ROM-to-PC asset converter, a README,
|
||||
and license texts. The build scripts hard-fail if a ROM image or an
|
||||
oversized blob ends up in the bundle. **No ROM, no game assets (textures,
|
||||
audio, models, levels, text) are ever shipped** — you supply your own
|
||||
legally-owned copy.
|
||||
|
||||
At runtime, the engine:
|
||||
|
||||
- has **no networking of any kind** (no sockets, no HTTP, checked directly
|
||||
against the source),
|
||||
- has **no telemetry, crash reporting, or analytics** of any kind,
|
||||
- **never touches the Windows registry** and **never requests elevated
|
||||
permissions**,
|
||||
- writes save data, config, and derived ROM assets only inside its own
|
||||
folder — never to `%APPDATA%`, `Program Files`, or any system location.
|
||||
|
||||
The one-time asset converter (`ge007-convert` / `prepare-assets.py`) — the
|
||||
part of the bundle most likely to draw suspicion, since it's the thing that
|
||||
reads your ROM and writes new files — has no network access at all,
|
||||
verifies your ROM against a fixed table of known retail GoldenEye 007
|
||||
hashes before touching it (an unrecognized file is rejected outright), and
|
||||
writes only inside the bundle folder. Its full source ships right next to
|
||||
the compiled version in every release if you'd like to read it yourself. The
|
||||
engine starts it automatically on the first run, when the two derived asset
|
||||
folders (`data/pcmodels-*`, `data/pccg-*`) are missing, passing it the ROM it
|
||||
found and the output folder; after that first run it is not launched again.
|
||||
|
||||
See [`SECURITY.md`](../.github/SECURITY.md) for why the binaries are
|
||||
unsigned and what that means in practice (a SmartScreen prompt on first
|
||||
run, and why some antivirus engines flag the converter specifically).
|
||||
|
||||
## Building from source
|
||||
|
||||
Cloning and building pulls in only standard, well-known packages: MSYS2
|
||||
`pacman` packages on Windows, `apt` packages on Linux — no `npm`, no
|
||||
`cargo`, nothing downloaded at CMake configure time, no git submodules, and
|
||||
no prebuilt binaries checked into the repository. The CI build freezes the release's asset-converter tool with `pyinstaller`,
|
||||
which is pinned to an exact version, and every third-party GitHub Action the
|
||||
workflows use is pinned to a full commit SHA (both from the release after
|
||||
v0.4.0; earlier releases installed an unpinned `pyinstaller`). What
|
||||
PyInstaller packages is entirely in-repo, stdlib-only Python, so a release is
|
||||
reproducible from a diff of this repository.
|
||||
|
||||
One development-only backdoor exists in source builds: the `GE_DEBUG_UNLOCKALL`
|
||||
environment variable (`src/game/file2.c`) pre-unlocks all cheat options at boot.
|
||||
It is off unless explicitly set, changes no shipped behavior, and is documented
|
||||
here so the env-var surface stays fully accounted for.
|
||||
|
||||
## Fidelity to the original N64 game
|
||||
|
||||
The port's non-negotiable rule is that decompiled game logic is never
|
||||
changed — only genuine N64-hardware dependencies get a PC-side
|
||||
replacement, in the `port/` layer. This was audited directly:
|
||||
|
||||
- **Region build macros** exactly mirror the original N64 Makefile's macro
|
||||
sets for all three regions — verified line-by-line.
|
||||
- **The audio/library file classification** (which original files compile
|
||||
vs. get PC-shimmed) exactly matches the project's own ground-truth
|
||||
manifest — no silent gaps, no silent duplicates.
|
||||
- **The one shipped game-logic-adjacent change** (a portal-culling
|
||||
float-precision fix, D271) is `#ifdef PORT`-gated, documented in the
|
||||
finding log, and moves *toward* matching N64 behavior, not away from it.
|
||||
Every other deviation from the decompiled source is one of the documented
|
||||
32→64-bit pointer-width ABI corrections described above.
|
||||
|
||||
**One issue, found and fixed before v0.3.0 shipped**: the port's
|
||||
random-number generator (`port/src/random.c`) was documented as a bit-exact
|
||||
port of the N64's PRNG, but wasn't — a shift-operation helper didn't match
|
||||
the real MIPS64 instruction semantics it was meant to mirror. This was
|
||||
independently confirmed by hand-tracing the assembly against the C port,
|
||||
tracked as finding D284, and fixed before the release (verified clean
|
||||
across a full level sweep — all 20 missions plus the ending sequence —
|
||||
no crashes). It affected loot placement, AI
|
||||
behavior variance, and replay-state determinism from the very first random
|
||||
draw, in every release before v0.3.0. Because of the fix, RNG-derived
|
||||
output — including the save-file CRC — changed, which meant existing save
|
||||
files and any previously recorded replays no longer validate; v0.3.0's
|
||||
release notes describe the automatic save migration that handles this. We'd
|
||||
rather say this plainly than let a "verified bit-exact" claim stand
|
||||
uncorrected, both when it was wrong and now that it's fixed.
|
||||
|
||||
Everything else checked (the documented ABI/pointer-width exceptions used
|
||||
for the 32-to-64-bit transition, a sample of the finding log's own claimed
|
||||
fixes against the actual current code) matched what's documented.
|
||||
|
||||
---
|
||||
|
||||
*This page is kept current alongside future releases. Its source review is a
|
||||
manual, human-reviewed process today — see the project roadmap for plans to
|
||||
partially automate the mechanical parts of it.*
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
title: Security status
|
||||
description: What a GoldenEye PC port release installs and doesn't: no networking, no telemetry, no ROM, no system writes — re-verified against the v0.5.0 source.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
---
|
||||
|
||||
## Security status
|
||||
|
||||
This page answers one question plainly: *what does installing this put on
|
||||
your machine*? The review was done
|
||||
end-to-end on 2026-09-15 and re-verified for the v0.3.0 release bundles on
|
||||
2026-09-18 (bundle contents, no-networking source check, and the asset
|
||||
converter). The no-networking source check was repeated against the
|
||||
`release/v0.4.1` tree on 2026-09-30 (no socket, HTTP or name-resolution
|
||||
calls in `src/` or `port/`; neither the engine nor the bundled `SDL2.dll`
|
||||
imports a networking DLL; no registry calls in the port's own code); the
|
||||
bundle contents were not re-checked then.
|
||||
|
||||
**v0.5.0 update pass, 2026-10-05:** the source checks were re-run against
|
||||
the current tree — no socket/network includes, no network symbols and no
|
||||
HTTP string literals in the compiled `src/` and `port/` sets; no registry
|
||||
or library-loading calls in either; the converter's Python sources
|
||||
(`prepare-assets.py` and its emit-script imports) import no network
|
||||
module. The bundle contents were re-checked against the packaging
|
||||
manifests (`tools_pc/bundle-win.sh` / `bundle-linux.sh` — the scripts CI
|
||||
runs): an explicit allowlist of engine, runtime DLLs, SDL2, licenses and
|
||||
converter tools, with a hard-fail guard against a ROM image or oversized
|
||||
blob sneaking in. The v0.5.0 artifacts themselves were not re-unpacked
|
||||
locally; they are built by the same scripts. The full engineering record
|
||||
behind each item is in the project's finding log
|
||||
([`docs/dev/findings.md`](https://github.com/jkdansereau/goldeneye-pc-port/blob/main/docs/dev/findings.md)).
|
||||
|
||||
## What a release actually installs
|
||||
|
||||
Each release (`goldeneye-pc-port-*-win64.zip` / `-linux-x86_64.tar.gz`)
|
||||
contains, and only contains: the game engine executable, a fixed set of
|
||||
standard runtime libraries (SDL2, zlib, and the MinGW/Linux runtime — no
|
||||
third-party downloads), the one-time ROM-to-PC asset converter, a README,
|
||||
and license texts. The build scripts hard-fail if a ROM image or an
|
||||
oversized blob ends up in the bundle. **No ROM, no game assets (textures,
|
||||
audio, models, levels, text) are ever shipped** — you supply your own
|
||||
legally-owned copy.
|
||||
|
||||
At runtime, the engine:
|
||||
|
||||
- has **no networking of any kind** (no sockets, no HTTP, checked directly
|
||||
against the source),
|
||||
- has **no telemetry, crash reporting, or analytics** of any kind,
|
||||
- **never touches the Windows registry** and **never requests elevated
|
||||
permissions**,
|
||||
- writes save data, config, and derived ROM assets only inside its own
|
||||
folder — never to `%APPDATA%`, `Program Files`, or any system location.
|
||||
|
||||
The one-time asset converter (`ge007-convert` / `prepare-assets.py`) — the
|
||||
part of the bundle most likely to draw suspicion, since it's the thing that
|
||||
reads your ROM and writes new files — has no network access at all,
|
||||
verifies your ROM against a fixed table of known retail GoldenEye 007
|
||||
hashes before touching it (an unrecognized file is rejected outright), and
|
||||
writes only inside the bundle folder. Its full source ships right next to
|
||||
the compiled version in every release if you'd like to read it yourself.
|
||||
The engine starts it automatically on the first run, when the two derived
|
||||
asset folders (`data/pcmodels-*`, `data/pccg-*`) are missing, passing it
|
||||
the ROM it found and the output folder; after that first run it is not
|
||||
launched again.
|
||||
|
||||
See [`SECURITY.md`](https://github.com/jkdansereau/goldeneye-pc-port/blob/main/.github/SECURITY.md) for why the binaries are
|
||||
unsigned and what that means in practice (a SmartScreen prompt on first
|
||||
run, and why some antivirus engines flag the converter specifically).
|
||||
|
||||
## Building from source
|
||||
|
||||
Cloning and building pulls in only standard, well-known packages: MSYS2
|
||||
`pacman` packages on Windows, `apt` packages on Linux — no `npm`, no
|
||||
`cargo`, nothing downloaded at CMake configure time, no git submodules, and
|
||||
no prebuilt binaries checked into the repository. The CI build freezes the
|
||||
release's asset-converter tool with `pyinstaller`, which is pinned to an
|
||||
exact version, and every third-party GitHub Action the workflows use is
|
||||
pinned to a full commit SHA (both from the release after v0.4.0; earlier
|
||||
releases installed an unpinned `pyinstaller`). What PyInstaller packages
|
||||
is in-repo, stdlib-only Python — a release is reproducible from this
|
||||
repository alone.
|
||||
|
||||
One development-only backdoor exists in source builds: the `GE_DEBUG_UNLOCKALL`
|
||||
environment variable (`src/game/file2.c`) pre-unlocks all cheat options at boot.
|
||||
It is off unless explicitly set, changes no shipped behavior, and is documented
|
||||
here so the env-var surface stays fully accounted for.
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
title: The asset pipeline
|
||||
description: How the GoldenEye 007 PC port turns N64 ROM assets into the model and graphics files it loads at runtime.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
---
|
||||
|
||||
## The asset pipeline
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
title: The software RSP
|
||||
description: How the GoldenEye 007 PC port emulates the N64's Reality Signal Processor (the graphics coprocessor) in software and bypasses the RDP.
|
||||
date: '2026-10-05'
|
||||
modified_time: '2026-10-05'
|
||||
---
|
||||
|
||||
## The software RSP
|
||||
|
||||
@@ -2057,9 +2057,9 @@ static void d526_note_emit(uint32_t f, struct LoadedVertex* const* v_arr, int us
|
||||
ok = 1;
|
||||
}
|
||||
if (!ok) return;
|
||||
if (d526_box_on)
|
||||
if (d526_box_on) {
|
||||
if (mxx < d526_box[0] || mnx > d526_box[2] || mxy < d526_box[1] || mny > d526_box[3]) return;
|
||||
else if (mxx < -1.05f || mnx > 1.05f || mxy < -1.05f || mny > 1.05f) return; // off-screen
|
||||
} else if (mxx < -1.05f || mnx > 1.05f || mxy < -1.05f || mny > 1.05f) return; // off-screen
|
||||
d526_sig_total++;
|
||||
int found = 0;
|
||||
for (int i = 0; i < d526_nsigs; i++) {
|
||||
|
||||
@@ -48,7 +48,7 @@ param(
|
||||
[switch]$Dump, # GE_AUDIODUMP=1 -> audiodump.raw
|
||||
[switch]$VoiceDump, # GE_VOICEDUMP=1 -> voicedump.raw (per-voice, D202/M-67)
|
||||
[switch]$MixerTrace, # GE_MIXERTRACE=1 -- SLOW, see warning below
|
||||
# (the -AB/-Old A/B switches were removed 2026-10-07, D532: GE_D204_OLD no
|
||||
# (the -AB/-Old A/B switches were removed 2026-10-05, D532: GE_D204_OLD no
|
||||
# longer exists in the game, so they were documented no-ops)
|
||||
|
||||
# Plumbing
|
||||
|
||||
@@ -54,7 +54,11 @@ cleanup() {
|
||||
if [ "$EEP_HAD" = 1 ]; then cp "$EEP_ORIG" "$EEP" 2>/dev/null; else rm -f "$EEP" 2>/dev/null; fi
|
||||
rm -f "$INI_ORIG" "$EEP_ORIG" 2>/dev/null
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
# D534: restore on EXIT only; INT/TERM just exit (which fires EXIT), so an
|
||||
# interrupted capture cannot continue past the restore with the snapshot gone.
|
||||
trap cleanup EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
|
||||
# recipe comes from the tracked gate tool, not from this file
|
||||
eval "$(grep -m1 '^GOLDEN_DUMP=' "$VSH")"
|
||||
|
||||
@@ -24,13 +24,13 @@ and per platform (`win`, and `linux` — 21 levels x 3 frames on each, captured
|
||||
D523, **superseded by D529**): the frame depends on the save's **content**, not
|
||||
its presence — D523's "presence, not which save" claim (worst_cell 0.175625 on
|
||||
each of the four candidate saves, 21.557% with none) was only ever measured on
|
||||
Archives, and the 2026-10-07 A/B refutes it (facility 177.47 scene-level on the
|
||||
Archives, and the 2026-10-05 A/B refutes it (facility 177.47 scene-level on the
|
||||
2026-10-05 playtest save, 0.0-0.25 on every other candidate on disk). `verify.sh`
|
||||
and `capture_p7.sh` install the canonical eep the same way they pin the ini
|
||||
(snapshot the local file if any, install the canonical one, restore-or-remove on
|
||||
exit), so the gate is reproducible on a fresh clone and in CI. A local playtest
|
||||
save is **never** the gate's input. The linux 63-frame set was re-captured
|
||||
on the box under the canonical eep 2026-10-07 (D531; the 2026-10-05
|
||||
on the box under the canonical eep 2026-10-05 (D531; the 2026-10-05
|
||||
re-round, D530, turned out to have run under the box-LOCAL save — the
|
||||
`capture_p7.sh` per-level re-pin bug, fixed in D531) and is valid.
|
||||
- Every run ends via `GE_QUITFRAME` (orderly quit; never a hard kill, D344).
|
||||
@@ -66,7 +66,7 @@ capture with the recipe above and replace `<level>/<platform>/*.png`.
|
||||
|
||||
## History
|
||||
|
||||
- **D531 (2026-10-07):** `capture_p7.sh`'s D529 adaptation was incomplete —
|
||||
- **D531 (2026-10-05):** `capture_p7.sh`'s D529 adaptation was incomplete —
|
||||
the per-level re-pin restored the pre-capture LOCAL save (D524-era line),
|
||||
silently overwriting D529's pre-loop canonical install, so the 2026-10-05
|
||||
box re-round (D530) ran under the box-local save, not the canonical one.
|
||||
@@ -74,7 +74,7 @@ capture with the recipe above and replace `<level>/<platform>/*.png`.
|
||||
and re-captured: fresh 21/21 box round, 63 frames committed, replacing the
|
||||
D530 set (47/63 frames differ — save content demonstrably moves the frames;
|
||||
16 byte-identical save-independent scenes).
|
||||
- **D530 (2026-10-07, AMENDED BY D531):** the linux set was re-rounded on the
|
||||
- **D530 (2026-10-05, AMENDED BY D531):** the linux set was re-rounded on the
|
||||
box (X220, tree `442eb2ff`; `~/p7-reround.log` hit `P7 re-round DONE`
|
||||
2026-10-05 12:53 EDT, 21/21 rc=0) and committed, replacing the D525
|
||||
cleared-eep set (51/63 frames differ; 12 save-independent scenes byte-
|
||||
|
||||
+15
-7
@@ -112,7 +112,7 @@ while [ $# -gt 0 ]; do
|
||||
--script) SCRIPT="$2"; USER_SCRIPT=1; shift 2 ;;
|
||||
--against) AGAINST="$2"; shift 2 ;;
|
||||
--json) JSON=1; shift ;;
|
||||
-h|--help) sed -n '2,32p' "$0"; exit 0 ;;
|
||||
-h|--help) sed -n '2,34p' "$0"; exit 0 ;;
|
||||
*) POSARGS+=("$1"); shift ;;
|
||||
esac
|
||||
done
|
||||
@@ -121,12 +121,12 @@ set -- "${POSARGS[@]:-}"
|
||||
case "${1:-}" in
|
||||
sweep) MODE=sweep; shift; SWEEP_SUBSET="${*:-}" ;;
|
||||
parity) MODE=parity; LEVEL_ARG="${2:-}"; shift 2 2>/dev/null || true ;;
|
||||
-h) sed -n '2,32p' "$0"; exit 0 ;;
|
||||
-h) sed -n '2,34p' "$0"; exit 0 ;;
|
||||
"")
|
||||
# D529 never-do 4: a no-arg run must NEVER look like a green verdict. It
|
||||
# prints the usage and exits NON-zero (2026-10-07: a no-arg pair was
|
||||
# prints the usage and exits NON-zero (2026-10-05: a no-arg pair was
|
||||
# cited as a "double-green" 21/21 because it exited 0).
|
||||
sed -n '2,32p' "$0"
|
||||
sed -n '2,34p' "$0"
|
||||
echo "error: no mode given -- a sweep is 'verify.sh sweep', one level is 'verify.sh <level>' (never cite a no-arg run as a gate result; D529)" >&2
|
||||
exit 1 ;;
|
||||
*) MODE=single; LEVEL_ARG="$1" ;;
|
||||
@@ -257,14 +257,21 @@ pin_ini_640x480() {
|
||||
restore_ini() {
|
||||
if [ -n "$INI_BAK" ]; then cp "$INI_BAK" "$INI" && rm -f "$INI_BAK"
|
||||
elif [ "$INI_CREATED" = 1 ]; then rm -f "$INI"; fi
|
||||
INI_BAK=""; INI_CREATED=0
|
||||
}
|
||||
trap 'restore_ini; restore_eep; kill_ours' EXIT INT TERM
|
||||
# D534: restore on EXIT only; INT/TERM just exit (which fires EXIT). A combined
|
||||
# `EXIT INT TERM` trap restored on Ctrl-C and then let the sweep CONTINUE --
|
||||
# the next level's pin re-installed the canonical save with the snapshot
|
||||
# already deleted, so the user's own ge007.eep was left replaced on disk.
|
||||
trap 'restore_ini; restore_eep; kill_ours' EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
|
||||
# --- save pin (D523, SUPERSEDED by D529): the goldens were captured with a
|
||||
# save file PRESENT. D529 (2026-10-07 A/B) proved the frame depends on the
|
||||
# save file PRESENT. D529 (2026-10-05 A/B) proved the frame depends on the
|
||||
# save's CONTENT, not just its presence -- D523's "presence, not which
|
||||
# save" claim had only been measured on Archives (worst_cell 0.175625 on
|
||||
# each of the four candidate saves, 21.557% with none), and the 2026-10-07
|
||||
# each of the four candidate saves, 21.557% with none), and the 2026-10-05
|
||||
# sweep (facility 177.47 scene-level on the local playtest save vs 0.0-0.25
|
||||
# on every other candidate on disk) refutes it. The gate now INSTALLS THE
|
||||
# CANONICAL SAVE (tools_pc/golden/ge007.eep, 2 KB, in-tree so a fresh
|
||||
@@ -291,6 +298,7 @@ restore_eep() {
|
||||
[ -n "$EEP_PIN_BAK" ] || return 0
|
||||
if [ "$EEP_PIN_HAD" = 1 ]; then cp "$EEP_PIN_BAK" "$EEP_PIN"; else rm -f "$EEP_PIN"; fi
|
||||
rm -f "$EEP_PIN_BAK"
|
||||
EEP_PIN_BAK=""; EEP_PIN_HAD=0
|
||||
}
|
||||
|
||||
# --- run one level -> sets globals: R_STATUS R_FRAMES R_SYM R_BRIEF -------
|
||||
|
||||
Reference in new issue
Block a user