All six TCRF article bodies were extracted (backlog/cut-content/articles/,
gitignored) and cross-referenced against src/ + assets/obseg/. Full verified
findings with file:line refs land in backlog/cut-content/RESEARCH.md.
Verified 1:1: the 11 unused cheats (CHEAT_ID enum vs cheat.c grant table),
music track index (MUSIC_TRACKS enum vs Notes-page GS index), MP character
table (~40 entries, 1.0446 eye height), all unused text strings (LmiscE/LgunE/
LpropobjE/LtitleE), build dates (compiletime.c), Spectrum emulator plumbing
(front.c MENU_SPECTRUM_EMU — only the transition is missing).
Corrections to TCRF/first pass: bg_dest is shipped Frigate geometry (not an
early version); cryp/dish are shipped Egypt/Temple; Library/Stack share
Basement's bg_ame; 28 of 29 unused items exist in the object table.
Tracked doc updated to point at the research file; backlog/ gitignored.
Cross-reference the local TCRF 'cutting room floor' export
(scratchpad/backlog-scrape/restore-cut-content-mod, gitignored) against the
decomp source and extracted asset tables. Article bodies were lost to a
Cloudflare challenge at scrape time; findings rest on the ~170 intact article
images + all image filenames, each mapped to ROM object/level evidence:
- A: full debug menu (U+D C-hold) decompiled in debugmenu_handler.c — free cam,
level switch, ramrom record/replay, screenshot grabs; all compiled into PC build
- B: cut weapons (taser/rocket/grenade/P90/spectre/autoshot) have models + stats
+ SFX; rocket/grenade/P90 grantable via existing cheat codes (cheat.c)
- C: 'unused items' page maps 1:1 to file_resource_table entries with use-logic
- D: 8 commented-out MP map entries in front.c with dev notes (Citadel/Statue/
Cradle/Aztec/Runway/Dam/Depot/Frigate)
- E: per-level unused props + orphaned level geometry (Crypt has bg+briefing but
no LEVELID; len/dish/cat/oat/arec/ame/ark/ref dirs beyond shipped set)
- F/G/H: unused faces, prerelease comparison pairs, dev-build video embeds
Feasibility tiers 0-3 with the port-layer-only constraint called out.
- Drop-in ROM wording everywhere (README quick start, Pages landing,
release notes, bundled README): first launch auto-generates the
derived assets via the frozen converter; no Python/toolchain needed.
PAL/JP marked not-yet-supported with issue #85 pointers.
- building.md: Linux build is CI-compiled and ships in the bundle
(was 'never built or run on Linux'); bundle note now describes the
frozen ge007-convert auto-spawn; PAL/JP sidecar caveat (D258).
- Status rewording across README/Pages/release notes: drop the
'first open-source port to our knowledge' claim; cutscene glitch
description aligned to 'mostly with James Bond'; index.md status
no longer contradicts the open D255 Deck crash.
- Em-dash cleanup across all GitHub Pages docs (index, building,
internals, porting-notes, dev-process, agentic-development,
release notes); internal dev logs untouched.
* Drop-in ROM: first-run sidecar conversion, no Python (issue #6, Part A + interim)
The release bundle now turns a dropped-in NTSC-U ROM into a playable game
with zero tooling: when data/pcmodels-* / data/pccg-* are missing at boot,
the engine spawns the frozen prepare-assets converter shipped in the bundle
(prepare-assets/ge007-convert[.exe], PyInstaller --onefile), waits for it,
and re-checks before continuing (port/src/romconvert.c, called from
romdataInit after ROM validation). Failure aborts boot with a message
instead of the later D179-class crash.
- prepare-assets.py: runs in-process via runpy when frozen (no user Python
to exec); NTSC-U-only gate with a clear message for PAL/JP ROMs; d88's
sibling import needs an explicit sys.path entry (run_path does not set
one). Verified: frozen exe output byte-identical to the unfrozen path and
to the shipped sidecars.
- CI (linux + windows): PyInstaller freeze step before bundling
(ensurepip / --break-system-packages for MSYS2's pip-less python).
- bundle scripts: copy ge007-convert into prepare-assets/ (hard-fail if not
frozen), size guard 60 -> 120 MB.
- Release notes: US-only drop-in instructions, no Python required.
- D258: PAL/JP filelist naming defects documented; multi-region deferred to
the Part B follow-up.
* CI: install pip via pacman on Windows (MSYS2 ensurepip is disabled); regen findings index for D258
The one broken bass instrument on Control/Cavern/Runway is a plain
byte-order bug in a corner the earlier passes never looked at. The
instrument bank's only two AL_RAW16_WAVE wavetables (instruments 2 and
51, sharing base 0x2118 / len 790) decode as a clean ~110 Hz soft-attack
bass sample when read big-endian s16 -- which is how the N64 CPU reads
them. The PC mixer's resampler consumes host-native (little-endian) s16,
so every sample arrives byte-swapped: deterministic per-instrument
corruption, exactly the M-106 repro. ADPCM nibble data is byte-order
agnostic, which is why every other instrument sounds right.
romdataFinishCartMap() now walks both bank trees (same ALBankFile layout
as romdataFixupAudioBank) and bswap16s each RAW16 [tbl+base,+len) range
in place in the cart map -- where alBnkfNew() points the mixer at it
directly. Shared ranges are deduped (swapping twice undoes the swap);
all reads bounds-checked. D55 in-place-fixup idiom; port-only, no game
logic touched.
Startup log: 'romdataInit: D230 byte-swapped 1 RAW16 wavetable range(s)
in place'. Owes a by-ear pass on the three repro tracks.
findings.md D230 -> FIXED with full root cause; release-notes.md drops
the music known-issue bullet.
The old attract-bunker1/attract-dam PNGs predate the D227 sky, D229 water
and 60 fps fixes. Point both pages at the Sept-13 playtest gallery instead
(shot-06 Bunker 1, shot-01 Dam) — same files as the gallery below, honest
captions — and drop the stale PNGs.
- README and docs/index.md (Pages) now embed goldeneye-gh-preview.gif
where the mp4 <video> tag was; release notes already used the GIF
- git rm the 27 MB mp4 (GIF stays — it is the release-notes asset, pinned
to the v0.2.0 tag)
- remove three unreferenced docs/img/bugs screenshots left over from the
culling/D176 A-B captures
- versioninfo gains GE007_VERSION_CODENAME (larkspur) and GE007_ORIGIN_URL,
printed by --version (new 'origin' line) and the startup log. A build keeps
pointing at this repository no matter who compiles or renames it.
- CONTRIBUTING: new 'Forks and derivative works' section — rebranding,
localizing and extending are welcome without permission; attribution (with
a link) and preserving/linking the docs/dev engineering record are the ask;
stripping the attribution is what disqualifies a fork as a descendant.
* Release notes: finalize for v0.2.0 final (CI re-stamps the body on tag cut)
- Drop '(pre-release)' from the title; <version> stamps to 0.2.0, so the
Downloads/Verify tables already name the final assets correctly.
- Blockquote rewritten: no more 'cut is for playtesting'. Claims what is true
(21 missions load and run crash-free) without claiming an end-to-end
completable campaign; adds the first-public-release note, hedged with
'to our knowledge'.
- New What's-new bullets: Everything-unlocked-by-default (D257, ON by default,
F10 opt-out, no active cheats) and the Steam Deck first-run preset + the two
new F10 rows (No hit flash / Skip intro).
- Known issues unchanged — all eight walked with the user and confirmed still
open; wording already matches the latest reports.
- Preview montage GIF at the top of the body (release pages can't play mp4);
raw URL pinned to the v0.2.0 tag, so it resolves once PR #80 has merged and
the tag is cut.
* Release notes: campaign-completed claim + D255 register-capture diagnosis
- Blockquote: full campaign playtested end to end (all 21 missions, Agent
difficulty) per the v0.2.0-pre PC playtest
- D255 bullet: updated from 'narrowed to a stale model reference' to the
pinned diagnosis (NULL ObjectRecord.model on an active record during
mid-firefight destruction; repros on Bunker + Frigate)
* README: 32 s gameplay preview montage (mp4) + preview-video runbook
* Prune: drop superseded goldeneye-demo.gif (replaced by gh-preview montage)
* Docs: v0.2.0 finalization pass — final wording, aligned known issues, Deck-verified line, social preview card
- README + pages site: 'v0.2.0 (pre-release)' -> v0.2.0 throughout; the
stale 'not yet verified on real Deck hardware' line is replaced with the
playtest fact (D253 fixed, D255 still open).
- Known-issues lists in README + site now match the release notes one-for-one
(adds the F10 bottom-row duplicate D251 and the intermittent Deck SIGSEGV
D255; D243/D230/D252/D245/D246/D75 carry their finding labels).
- Working list mentions AllUnlocked default-ON (D257) with the F10 opt-out.
- First-public-release note added to the README hero and site status line,
hedged with 'to our knowledge'.
- social-preview.png (1280x640 GitHub link card) composed from a gameplay
frame of the preview montage; scratchpad/make-social-preview.py is the
local recipe (gitignored, like make-preview.py).
- Commit docs/img/shots/manifest.csv (gallery -> source recording map);
gitignore the regenerable CONTACT-SHEET.jpg; drop scratch-gdb-cmds.txt.
* Social preview: regenerate card from updated briefing HTML (v0.2.0 final wording)
The PNG committed earlier was a screenshot of the rendered site (stale
wording, video element unrendered). The canonical source is
.github/social-preview.html per .github/social-preview.md; update its
Status/Statistics lines to the v0.2.0 final state and re-render:
- Status: RELEASED v0.2.0 — WINDOWS · LINUX · STEAM DECK
- All 21 solo missions — full campaign completed in playtesting
- ~22k lines C/C++ · ~10k Python (port layer + tools)
- ~250 bugs root-caused · two coding agents, one human, part-time
Verified by pixel-diff against the previous render: only the four text
bands changed; title/fonts/layout identical. Drop the unreferenced
root-level social-preview.png.
* docs: refresh social preview + status for v0.2.0 playtest results
- Social card: 'RELEASED v0.2.0', 21/21 missions completed in playtesting,
~250 bugs fixed, two agents + one human; re-rendered the PNG from the
canonical .github/social-preview.html source (pixel-diff vs the old render
shows only the four edited text bands changed)
- README Status: campaign now claimed as completable end to end (user
playtest: full campaign, Agent difficulty, PC); Working list matches
- findings: D255 updated with the Deck register capture (Rdi=nil -> NULL
ObjectRecord.model, destroy-path ordering case confirmed; truncation ruled
out) and the rule-#2 sign-off question for a guard; D254 field-verified
* docs: regenerate findings index (D254/D255 status updates)
Port-layer only (no game-code edits):
- main.c seeds debug_enable_all_levels_flag + debug_007_unlock_flag
after configLoad() when Game.AllUnlocked is set (same class as the
existing GE_UNLOCK_ALL getenv hook).
- libultra.c eep shim patches the save block at read time (the exact
fileValidateSaves pattern: block 4, 5x96 bytes): sets all 20
progression-gated cheat-unlock bits per slot and fills every empty
stage/difficulty completion time with the max (0x3FF), preserving
existing player times, then recomputes each slot's CRC with the
game's own fileGenerateCRC so validation passes. The completion-time
half is required: with any SP cheat active, g_AppendCheatSinglePlayer
makes mission select accept only STAGESTATUS_COMPLETED levels, so an
unlock-only save locks every level once a cheat is turned on.
- optionsoverlay.c: 'All unlocked' toggle row (default ON for this cut).
Verified: fresh-eep GE_SAVELOG shows all 5 slots stored==calc; user
playtest confirms all levels at each difficulty, 007 mode, populated
cheat menu, cheats working, mission select intact with all cheats on.
The two user-facing config keys were registered but only reachable by
hand-editing ge007.ini. Add ROW_TOGGLE rows (below Screen shake):
- No hit flash (D232, community "no damage flash"; suppresses the
non-black fade paths in bondview2)
- Skip intro (D216; read at title-stage load, so it takes effect the
next time the title screen is reached)
Video.FixMipTextures / Video.WrapFix deliberately left out: opt-in
fidelity bug-fixes, not preferences.
Verified live (isolated CWD): both rows render in the F10 panel and
toggle; clean exit persists Game.NoHitFlash=1 + Game.SkipIntro=1 to
ini; relaunch with SkipIntro=1 logs "Game.SkipIntro: booting to
file-select" and skips straight to mission select. NoHitFlash's
in-game suppression rests on its prior D232 verification (needs
combat, not automatable).
STEAMOS detection in main() seeds video config defaults before configLoad;
first-launch-only by construction (an existing ge007.ini always wins). The
150% DrawDistance/LodDistance addresses authored N64 fade distances reading
short on the close-up Deck panel (e.g. the Dam lock fading in within sight)
while desktops keep the faithful 100% default.
The release job only set --notes-file when creating the draft; existing
drafts got 'upload --clobber' (assets only), so the body stayed frozen at
the first cut's notes. Compute the stamped notes unconditionally and add
'gh release edit --notes-file' to the update path.
D256 (Linux saves/config now persist from any launch dir) is in this cut
and Deck-verified; the D255 line reflects the narrowed diagnosis and the
register-capturing crash handler. Drop the 'no known crashes' claim from
the pre-release blurb since D255 is open.
romdataInit finds the ROM in CWD data/, exe-dir data/, or ./, but the
POSIX $S branch only ever produced a CWD-relative path, so any launch
from another directory ran fine while every EEPROM and ini write failed
silently (no ./data/ to fopen into) — saves never persisted and F10
settings reset on every launch. Mirror the Windows branch via
readlink(/proc/self/exe) and mkdir the target dir best-effort. Verified
on WSL with exe+data in /tmp and CWD=/: config, eeprom, and ROM all
land in <exedir>/data/.
The POSIX handler re-entered on SIGABRT (sysFatalError -> abort) and
truncated ge007.crash.log, so field crashes came back as bare abort
records with no faulting PC or registers. Guard against re-entry,
terminate directly with _exit(), and dump si_addr + the general register
set from the ucontext — a Deck crash now names the bad pointer on its
face.
Also documents D255 (new SIGSEGV in vtxstore's active-object walk during
a Facility firefight on the Deck; disassembly shows the fault is a
32-bit-zero-extended read of ObjectRecord.model, misnamed ChrRecord.
chrflags by the decompiler) and updates the release notes' Deck status.
- D197 (Silo face wrap): closed per user playtest, dropped
- D75: reworded — Nintendo logo still broken, Rareware logo filtering off;
mission-complete/mode-select screens have no 3D models (old framing wrong)
- F10 ghost row: now deterministic bottom-row duplicate of the selected item
(D251 addendum); earlier intermittent 4K framing superseded
stanCheckLinkedSpecialTile was decompiled with an all-s32 middle-arg
prototype while its callers pass it through the standTileLocusCallback_B_t
typedef (f32 f32 f32). On x86-64 SysV the int/float class split puts the
6th arg (outFlags/record) in %rdx per the typedef but %r9 per the
definition, so the FORCECROUCH/LADDER store hit a stale scratch register.
MIPS o32 passes both through GPRs a0-a5 identically, which is why the
mismatch was invisible on N64 and in the decompilation.
ABI-class edit (AGENTS.md #2 narrow exception): body never uses the three
middle params; N64 codegen unaffected. Verified under gdb on WSL:
pre-fix SIGSEGV at stan.c:2441 with r9=0x3 and a valid record in the
caller frame; post-fix the same walk route completes clean.
- README: manual Contents TOC dropped (GitHub auto-generates); Download
table moved to the top with Quick start under it; Status compressed to
a Working paragraph + tight known-issue list (D-numbers live in the
release notes / finding log now); How-it-works tightened.
- Pages (docs/index.md): demo gif is the hero; download table up top;
new How-it-works and Honest-status sections; legal footer; the 19-shot
playtest gallery unchanged.
- Options overlay is now gamepad-driven: README Steam Deck section, the
bundle README (new @DECK@ block on Linux, controller column added to
the controls table), and the release-notes template all document
Select / D-pad / A / B / Start instead of a Steam key-mapping workaround.
Controller-only machines (Steam Deck) had no way to open or navigate the
F10 options overlay -- it was keyboard+mouse only. Now:
- Select (BACK) rising edge toggles the overlay, tracked across both the
open and closed poll paths (padSelectPrev) so a held button cannot
re-toggle on the transition. BACK is read nowhere else in the port.
- While open, D-pad or left stick up/down moves the selection, A/X step
forward (the Enter equivalent), B/Y step back, Start closes. The gamepad
bits are OR-ed into the existing keyboard edge logic, so repeat/clamp/
scroll behaviour is identical; input.c already swallows pad 0 while the
overlay is open, so nothing reaches the game.
- inputPadButton/inputPadAxis accessors expose raw SDL pad state to the
overlay (unaffected by our logic-layer swallow).
Smoke-tested headless with GE_OPTIONSOVERLAY=1 and no pad attached.
Resized to 1600px width / q85, clean names (shot-NN.jpg), in a
collapsible section so the landing page stays light. Raw captures and
the curation work-products (contact sheet, manifest) stay local under
docs/img/screenshots/ (gitignored). Per-image captions/level names and
trimming pending owner review of the contact sheet.
Two defects found in the local review of the unpushed v0.2.0-pre work:
1. input.c: padShoulderPrev was only updated outside menu mode, so a
shoulder held across the menu->game transition fired a spurious
weapon cycle on the first gameplay poll. Edge state is now tracked
every poll; emission stays suppressed in menus where A means select.
2. ci.yml release job: the notes template substitutes <version> with the
raw tag (v0.2.0-pre), but bundle-{linux,win}.sh strip the leading v
when building asset names -- the published notes would have linked
goldeneye-pc-port-v0.2.0-pre-* assets that don't exist. Substitute
the stripped form (NOTES_VERSION) instead.
README:
- compress the Background section (two-agent detail now one tight
paragraph; full write-up stays in agentic-development.md)
- new 'Beyond playing' section: tweak it (ini/F10/-fresh), read it
(internals + porting notes as the entry points, src/ vs port/ split),
mod it (MIT port layer, CONTRIBUTING ground rules, docs/dev record)
- Quick start no longer implies NTSC-U only
Pages (docs/index.md, served from main:/docs):
- status was stale ('alpha, v0.1.0') -- now v0.2.0 pre-release with the
honest rough-edges summary linking to README #status
- new Downloads section up top: Windows + Linux/Steam Deck bundles with
the no-ROM note and the four-step path
- 'Play it - or take it apart' CTA mirroring the README sentiment
(try it / read the code / mod it / research angle)
- in-engine gallery (attract views + demo clip); more captures land
here as playtesting continues
Launch with -fresh (or --fresh) for a clean-slate run: removes
$S/ge007.eep (the file-backed EEPROM save, all five slots) and
$S/ge007.ini before configLoad / the eeprom's lazy load touch them.
The ini is re-written with defaults on exit as usual; the .eep only
reappears if a save is actually written. Verified in a scratch data
dir: both files removed at launch, ini regenerated as defaults.
Steam Deck target. LS move/strafe + RS look + RT fire + LT aim were
already in place (D194/D238 naturalPitchMode); this completes the
scheme with shoulder weapon cycling per the console re-releases:
RB rising edge = next weapon, LB rising edge = previous weapon.
Cycling rides the game's own A-line formulas (bondview2.c
weaponForwardOffset/weaponBackOffset): a fresh A edge cycles forward;
A+Z presented on the same tick cycles backward -- the identical trick
the mouse-wheel path uses (D223), which also guarantees no stray shot
(triggerOn is gated off while invButtons is held). Edges are emitted
for exactly one poll so holding a shoulder cannot latch A and block
firing; both are suppressed in menu mode where A means select.
A/X = action/use, B/Y = crouch/cancel (unchanged); LB no longer maps
to lean. README controls table + release notes updated.
The $ORIGIN verification compared ldd's absolute resolved path against the
relative $OUT, so it always failed even though the bundled libSDL2 was the
copy being resolved (CI 34778363397 showed exactly that). Match both forms;
the remaining-deps listing now filters by bundle dir name for the same
reason.
User playtest report: bullet-impact sparks and lingering smoke/explosion
residue drift through the full hue wheel over time instead of holding their
intended grey/orange palette. Logged in findings §F (D252) with this
session's mechanism work: particle colour comes entirely from the 15
distinct IMAGE_SMOKE_N x IMAGE_FIRE_N (RGBA16) pairs the particles age
through (assets/oddtextures.c records, white default vertex); the M-82/D172
tile-offset fix and the 5551 decode are both verified correct for this path;
prime suspect is import_texture_rgba16 deriving width/height from the tile
line size (32x7 instead of 16x14 for the 16px-wide fire tiles), which would
scramble each aging stage into a different wrong hue -- exactly the observed
slow rainbow sweep. Per user instruction: documented only, ships as a known
issue (README + release notes + GRAPHICS-BACKLOG); index csv regenerated.
The in-game GEPD-style aim mode (D194/M-122) is modelled on the Mouse
Injector plugin for 1964 -- credit its author Carnivorous and the 1964
developers Rice & schibo in the README Credits section. Note the port's
implementation is an independent reimplementation of the behaviour, not
derived code.
bundle-linux.sh now copies the exact libSDL2 the exe was linked against next
to it and sets the rpath to $ORIGIN via patchelf, with an ldd assertion that
the bundled copy is the one resolved. zlib/libGL remain system deps
(preinstalled on desktop distros and SteamOS). CI installs patchelf; the
generated in-bundle README gains a Steam Deck sideload note and the SDL2
zlib-license copyright file is carried when the distro ships one.
Also refreshes the release-facing docs that ship with / describe the cut:
- .github/release-notes.md: v0.1.0-alpha body -> <version> pre-release body
(what's new + known issues incl. D243/D230/D245/D246/D197/D75, the D251
4K ghost row, and 'not yet verified on real Deck hardware')
- tools_pc/dist/README.md.in: alpha claims (no audio / black sky / US-only)
-> pre-release status; ROM table now lists all three regions (the asset
step auto-detects by SHA-1)
- Status: 'alpha' -> 'v0.2.0 (pre-release)'; working list now reflects the
60 fps fix (D248), click-to-lock mouse + GEPD aim mode (D194 closed), sky
(D227) and water green-pulse (D229) fixes, F10 overlay, mute/screenshot QoL;
known issues updated (cutscenes D243/D160/D173, music D230, front-end models
D75, water seam D245, edge strips D246).
- Download: leads with the two v0.2.0-pre bundles (names match bundle-*.sh
output, which strips the leading v), notes SDL2 is bundled in the Linux
tarball so it runs as-is on any distro or a sideloaded Steam Deck.
- New 'Steam Deck' subsection: sideload steps, CPU-bound performance note,
D203 status (suspect fixed, unverified on real hardware).
- Quick start + comparison table + Linux build section updated to match.
Per the M-82/M-106 user decision: click-to-lock is now the only cursor
capture mode. Port-only deletion, no game-code touch:
port/src/input.c drop mouseCaptureMode + Input.MouseCaptureMode key;
simplify reconcileGrab/notifyClick/releaseCapture/
aimGepdCompute guards; delete the !haveAbs relative
P-controller menu path and its dead state (menuEst/Tgt,
menuCursorStep, MENU_P_GAIN/EST_DELTA/MOUSE_TO_PX);
drop the unused inputMouseCaptureActive() export
port/include/input.h update WI-1 comment, remove the dead declaration
port/src/optionsoverlay.c remove the 'Mouse capture' toggle row + labels
Existing ini files that set Input.MouseCaptureMode are ignored (config layer
skips unknown keys). Closes D192 (outer grid cells unreachable under mode 0)
and D239 (always-grab parity) by removing the bugged path rather than
patching it.
Known issue (logged in D251): intermittent ghost repeat of a top row at the
panel bottom in true 4K fullscreen; local repro clean, MSAA-off bisection
pending with the user.
RMB aim mode rewritten as a direct mirror of GEPD's mouse aiming:
crosshair-position writes with the game's own damping left running,
gun pose derived from crosshair position (no stick synthesis), camera
edge-scroll at screen edges. vv_theta [0,360) wrap dropped for GEPD
parity. User playtest: spazz accepted (95%), sensitivity calibrated
(hipfire matched to aim mode; MouseSensitivity master now scales both).
Defaults ~25% above the user-approved match point. Input.GepdSens
renamed Input.AimModeSens (old key kept as deprecated alias).