mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
docs: final v0.2.0 pre-tag pass
- 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.
This commit is contained in:
1 parent
b2d5551ece
commit
436484a926
9 files changed
+476
-469
No files matched your search
+28
-25
@@ -1,4 +1,4 @@
|
||||
## GoldenEye 007 PC Port — <version>
|
||||
## GoldenEye 007 PC Port <version>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/jkdansereau/goldeneye-pc-port/raw/v0.2.0/docs/media/goldeneye-gh-preview.gif" width="480"
|
||||
@@ -6,15 +6,17 @@
|
||||
</p>
|
||||
|
||||
> The full single-player campaign runs at a steady 60 fps with audio (music +
|
||||
> SFX) playing throughout, on Windows and Linux including Steam Deck — and it
|
||||
> SFX) playing throughout, on Windows and Linux including Steam Deck, and it
|
||||
> is completable end to end: the whole campaign has been playtested through
|
||||
> all 21 missions (Agent difficulty). To our knowledge this is also the first
|
||||
> open-source port of the original N64 game to ship as a public release. It's
|
||||
> an early public cut: all 21 solo missions load and run crash-free, but the
|
||||
> known issues below are real — feedback is very welcome.
|
||||
> all 21 missions (Agent difficulty). It's an early public cut: all 21 solo
|
||||
> missions load and run crash-free, but the known issues below are real;
|
||||
> feedback is very welcome.
|
||||
|
||||
### What's new since v0.1.0
|
||||
|
||||
- **Drop-in ROM, no tooling**: unpack the bundle, drop your NTSC-U (US) ROM
|
||||
in `data/`, launch; the first run generates the derived assets
|
||||
automatically. No Python, no installer, nothing to set up.
|
||||
- **Steady 60 fps** in normal play (the software RSP runs off the presentation
|
||||
critical path); `Video.DisplayFPS` in the F10 overlay shows it.
|
||||
- **Audio**: in-level music and sound effects throughout (the alpha was
|
||||
@@ -26,38 +28,39 @@
|
||||
- **Rendering**: outdoor skies render correctly; water no longer renders
|
||||
green/pulsing; reflective surfaces (glass, chrome weapon skins) work.
|
||||
- **Crash fixes**: the two v0.1.0-era crashing levels (Bunker ii, Statue) and
|
||||
the AI-pacing bug that broke Cradle are fixed and playtest-verified — all 21
|
||||
the AI-pacing bug that broke Cradle are fixed and playtest-verified: all 21
|
||||
solo missions load and run crash-free. Also fixed: the Steam Deck / Linux
|
||||
Facility crash triggered by walking into the crouch-forcing spot at the
|
||||
level's opening (D253) — this also revives the auto-crouch and ladder
|
||||
level's opening (D253); this also revives the auto-crouch and ladder
|
||||
signals, which were dead on PC before.
|
||||
- **QoL**: F10 in-game options overlay (fullscreen, resolution, frame cap,
|
||||
MSAA, texture filtering, FOV/draw distance, sensitivity), F12 screenshot.
|
||||
- **Everything unlocked by default** — all 21 solo levels are selectable at
|
||||
- **Everything unlocked by default**: all 21 solo levels are selectable at
|
||||
every difficulty from the first launch, 007 mode is available, and the cheat
|
||||
menu is fully populated. No *active* cheats are enabled (weapons remain
|
||||
per-mission pickups, as on N64); F10 → *All unlocked* switches back to
|
||||
faithful N64 progression.
|
||||
- **Steam Deck first-run preset** — on SteamOS the first launch seeds
|
||||
- **Steam Deck first-run preset**: on SteamOS the first launch seeds
|
||||
Deck-friendly defaults (native 1280×800 fullscreen, VSync, MSAA 4, 150%
|
||||
draw/LOD distance); an existing `ge007.ini` always wins. Two more F10 rows:
|
||||
*No hit flash* (suppresses the damage-flash overlay) and *Skip intro*.
|
||||
- **Modern dual-stick controller layout** (the scheme used by the console
|
||||
re-releases): left stick move/strafe, right stick look, right trigger fire,
|
||||
left trigger aim, A/X use, B/Y crouch/cancel, **RB/LB cycle weapons**.
|
||||
- **Linux / Steam Deck**: the Linux bundle now ships its own SDL2 — it runs
|
||||
- **Linux / Steam Deck**: the Linux bundle now ships its own SDL2, so it runs
|
||||
as-is on any distro, and sideloads onto a Steam Deck with nothing
|
||||
installed. Saves and F10 settings now persist no matter which directory you
|
||||
launch from (previously Linux wrote them relative to the launch directory
|
||||
only, so they silently failed elsewhere — D256); the options overlay is
|
||||
only, so they silently failed elsewhere; D256); the options overlay is
|
||||
fully gamepad-driven on the Deck.
|
||||
|
||||
### Known issues
|
||||
|
||||
- **Cutscenes frequently glitch** — skipped beats, wrong camera, misplaced or
|
||||
hovering actors, wrong timing; the Dam level-end cutscene is racy (D243).
|
||||
The most visible gap in this release.
|
||||
- **Particle colours cycle through a rainbow palette** — bullet-impact sparks
|
||||
- **Cutscenes still glitch, mostly with James Bond**: in scripted sequences
|
||||
Bond is the one who gets misplaced, hovers, or spins; the other actors are
|
||||
fine for the most part now. The Dam level-end cutscene is racy (D243).
|
||||
Still the most visible gap in this release.
|
||||
- **Particle colours cycle through a rainbow palette**: bullet-impact sparks
|
||||
and lingering smoke/explosion residue drift through the hues over time
|
||||
instead of holding their intended grey/orange palette (D252).
|
||||
- Water on `IsWater` levels shows a moving seam between two patterns (D245);
|
||||
@@ -69,14 +72,14 @@
|
||||
selected** (e.g. the MSAA value appears both on its own row and again at
|
||||
the panel bottom); earlier builds showed it as an intermittent 4K-
|
||||
fullscreen ghost of the top row.
|
||||
- **Steam Deck: one intermittent crash remains** — the v0.1.0-era Facility
|
||||
- **Steam Deck: one intermittent crash remains**: the v0.1.0-era Facility
|
||||
crash is confirmed fixed on Deck hardware, but a SIGSEGV can occasionally
|
||||
occur during heavy firefights (D255; seen on Bunker and Frigate). The
|
||||
faulting-register capture in `ge007.crash.log` has pinned it: an object
|
||||
record whose model reference is NULL while the record is still active —
|
||||
record whose model reference is NULL while the record is still active;
|
||||
i.e. something in a mid-firefight destruction leaves the record live one
|
||||
tick too long. We're tracking down the exact destruction path; more Deck
|
||||
playtime across levels is welcome — please report any Deck-specific faults.
|
||||
playtime across levels is welcome; please report any Deck-specific faults.
|
||||
|
||||
### Downloads
|
||||
|
||||
@@ -87,13 +90,13 @@
|
||||
|
||||
Each contains the engine executable, a README, license texts, and the
|
||||
`prepare-assets` tool. **No ROM, no game assets.** The Windows bundle carries
|
||||
its runtime DLLs; the Linux bundle carries SDL2 — on both platforms nothing
|
||||
its runtime DLLs; the Linux bundle carries SDL2, so on both platforms nothing
|
||||
needs to be installed first.
|
||||
|
||||
### Running it
|
||||
|
||||
You supply your own **GoldenEye 007 N64 ROM** (`.z64`, big-endian) that you
|
||||
legally own — the **NTSC-U (US)** release is what this build supports (PAL / JP
|
||||
legally own: the **NTSC-U (US)** release is what this build supports (PAL / JP
|
||||
are on the roadmap). No Python, no toolchain, nothing to install.
|
||||
|
||||
1. Unpack the archive.
|
||||
@@ -103,13 +106,13 @@ are on the roadmap). No Python, no toolchain, nothing to install.
|
||||
seconds: it detects your ROM, generates the two derived asset folders
|
||||
(`data/pcmodels-ntsc-final/`, `data/pccg-ntsc-final/`) once, and saves them
|
||||
for every future run. (The generator is `prepare-assets/ge007-convert`
|
||||
inside the bundle; you can also run it manually — it prints what it's doing.)
|
||||
inside the bundle; you can also run it manually; it prints what it's doing.)
|
||||
|
||||
**Steam Deck:** sideload the unpacked folder (USB or a file manager), do steps
|
||||
2–3, then add the executable to Games → *Add Game* as a non-Steam game.
|
||||
|
||||
**In-game settings on the Deck:** the options overlay is fully gamepad-driven
|
||||
— it opens with **Select**, the D-pad or left stick (up/down) moves between
|
||||
**In-game settings on the Deck:** the options overlay is fully gamepad-driven:
|
||||
it opens with **Select**, the D-pad or left stick (up/down) moves between
|
||||
options, **A** steps the selected option forward, **B** steps it back, and
|
||||
**Start** (or Select again) closes. No keyboard needed.
|
||||
|
||||
@@ -124,7 +127,7 @@ sha256sum -c goldeneye-pc-port-<version>-linux-x86_64.tar.gz.sha256
|
||||
|
||||
### Source & docs
|
||||
|
||||
<https://github.com/jkdansereau/goldeneye-pc-port> — built on the
|
||||
<https://github.com/jkdansereau/goldeneye-pc-port>, built on the
|
||||
[GoldenEye 007 decompilation](https://github.com/n64decomp/007), architecture
|
||||
after the [Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark).
|
||||
Non-commercial fan preservation/research project; not affiliated with any
|
||||
|
||||
@@ -12,11 +12,10 @@ in a dedicated `port/` layer, following the architecture of the
|
||||
[Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark), the same
|
||||
Rare "Indy" engine family, one hardware generation apart.
|
||||
|
||||
**v0.2.0** is out for Windows and Linux — including Steam Deck, where the
|
||||
Linux bundle sideloads as-is — and runs the full campaign at a steady 60 fps
|
||||
with known rough edges ([Status](#status)). To our knowledge it's also the
|
||||
first open-source port of the original N64 game to ship as a public release:
|
||||
free to download, build on and modify (you bring the ROM).
|
||||
**v0.2.0** is out for Windows and Linux (including Steam Deck, where the
|
||||
Linux bundle sideloads as-is) and runs the full campaign at a steady 60 fps
|
||||
with known rough edges ([Status](#status)). Free to download, build on and
|
||||
modify (you bring the ROM).
|
||||
|
||||
It's also a case study in AI-agent collaboration on a large, low-level
|
||||
codebase: two coding agents, driven by one person part-time, porting ~230
|
||||
@@ -26,47 +25,45 @@ See [Background](#background).
|
||||
> [!IMPORTANT]
|
||||
> **You must supply your own GoldenEye 007 ROM.** This repository contains no
|
||||
> Nintendo code or assets, and no ROM. Nothing here is distributable as a
|
||||
> playable game — see [Requirements](#requirements) and [Legal](#legal).
|
||||
> playable game: see [Requirements](#requirements) and [Legal](#legal).
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/img/shots/shot-06.jpg" width="32%" alt="Bunker 1, in-engine">
|
||||
<img src="docs/media/goldeneye-gh-preview.gif" width="32%"
|
||||
<img src="docs/media/goldeneye-gh-preview.gif" width="64%"
|
||||
alt="~32 s gameplay montage from live play sessions">
|
||||
<img src="docs/img/shots/shot-01.jpg" width="32%" alt="Dam, in-engine">
|
||||
<br><em>All in-engine, running in the port — Bunker 1 and Dam captures plus a
|
||||
~32 s gameplay montage loop from the v0.2.0 playtest.</em>
|
||||
<br><em>All in-engine, running in the port, a ~32 s gameplay montage loop
|
||||
from the v0.2.0 playtest.</em>
|
||||
</p>
|
||||
|
||||
## Download
|
||||
|
||||
| Platform | Bundle | Notes |
|
||||
|---|---|---|
|
||||
| **Windows** (x86_64) | [win64.zip](../../releases) | Engine + runtime DLLs + the one-time asset tool. |
|
||||
| **Linux** (x86_64) / **Steam Deck** | [linux tarball](../../releases) | SDL2 is bundled — runs as-is on any distro, and sideloads onto a Deck with nothing installed. |
|
||||
| **Windows** (x86_64) | [win64.zip](/jkdansereau/goldeneye-pc-port/releases) | Engine + runtime DLLs + the one-time asset tool. |
|
||||
| **Linux** (x86_64) / **Steam Deck** | [linux tarball](/jkdansereau/goldeneye-pc-port/releases) | SDL2 is bundled, so it runs as-is on any distro, and sideloads onto a Deck with nothing installed. |
|
||||
|
||||
Both bundles contain **no ROM and no game assets** — you supply your own
|
||||
Both bundles contain **no ROM and no game assets**: you supply your own
|
||||
(see [Requirements](#requirements)), which keeps the release legal to
|
||||
distribute. Earlier builds: v0.1.0 alpha, same page. You can also build it
|
||||
yourself; see [Building](#building).
|
||||
|
||||
### Quick start
|
||||
|
||||
You need a GoldenEye 007 N64 ROM (`.z64`, big-endian; NTSC-U recommended — all
|
||||
three regions are supported). No ROM or game asset is included or distributed.
|
||||
Then:
|
||||
You need a GoldenEye 007 N64 ROM (`.z64`, big-endian). This release supports
|
||||
the **NTSC-U (US)** version; PAL and JP are on the roadmap ([issue
|
||||
#85](/jkdansereau/goldeneye-pc-port/issues/85)). No ROM or game asset is
|
||||
included or distributed. Then:
|
||||
|
||||
1. Download the Windows or Linux bundle from [Releases](../../releases) and unpack it.
|
||||
1. Download the Windows or Linux bundle from [Releases](/jkdansereau/goldeneye-pc-port/releases) and unpack it.
|
||||
2. Make a `data/` folder next to the executable and drop the ROM in as `ge007.ntsc-final.z64`.
|
||||
3. Run the one-time asset step: `python3 prepare-assets/prepare-assets.py` (Python 3.8+, stdlib only).
|
||||
4. Launch the executable from that folder.
|
||||
3. Launch the executable from that folder. The first run takes a few extra seconds: it detects the ROM and generates the derived asset folders once (no Python or other tooling needed).
|
||||
|
||||
Read the [Status](#status) caveats first — v0.2.0 has known rough edges,
|
||||
Read the [Status](#status) caveats first: v0.2.0 has known rough edges,
|
||||
listed plainly there.
|
||||
|
||||
## Status
|
||||
|
||||
**v0.2.0 — playable, with known rough edges.** The full single-player
|
||||
campaign is completable end to end (all 21 missions, Agent difficulty —
|
||||
**v0.2.0 - playable, with known rough edges.** The full single-player
|
||||
campaign is completable end to end (all 21 missions, Agent difficulty,
|
||||
playtested), at a steady 60 fps; all 21 solo missions load, render and run
|
||||
crash-free, verified on Windows, Linux and real Steam Deck hardware. Feedback
|
||||
is very welcome.
|
||||
@@ -74,8 +71,7 @@ is very welcome.
|
||||
**Working:** boot sequence and front end (menu → mission select → briefing →
|
||||
start); all 21 solo missions load, render and are crash-free (full campaign
|
||||
playtested end to end at Agent difficulty); steady 60 fps
|
||||
(software RSP off the presentation critical path); full audio — in-level music
|
||||
and SFX; keyboard + mouse (click-to-lock, proportional aim mode) and a modern
|
||||
(software RSP off the presentation critical path); full audio: in-level music and SFX; keyboard + mouse (click-to-lock, proportional aim mode) and a modern
|
||||
dual-stick controller layout; file-backed saves; all levels, 007 mode and the full cheat menu unlocked by
|
||||
default (F10 → *All unlocked* restores faithful N64 progression); F10 in-game
|
||||
options overlay (resolution, frame cap, MSAA, filtering, FOV, sensitivity);
|
||||
@@ -83,17 +79,16 @@ Windows and Linux.
|
||||
|
||||
**Known issues:**
|
||||
|
||||
- **Cutscenes glitch frequently** — skipped beats, wrong camera, misplaced or
|
||||
hovering actors, wrong timing; the Dam level-end cutscene is racy (D243).
|
||||
The most visible gap in this release.
|
||||
- A few in-level music tracks sound wrong — a wrong-sounding bass instrument
|
||||
on some elevator/level tracks (D230).
|
||||
- **Cutscenes still glitch, mostly with James Bond**: in scripted sequences
|
||||
Bond is the one who gets misplaced, hovers, or spins; the other actors are
|
||||
fine for the most part now. The Dam level-end cutscene is racy (D243).
|
||||
Still the most visible gap in this release.
|
||||
- Particle colours drift through a rainbow palette instead of holding their
|
||||
grey/orange intent (bullet sparks, lingering smoke/explosion residue) (D252).
|
||||
- Water levels show a moving seam between two water patterns (D245); thin
|
||||
pixel strips at the left/right screen edges at non-integer window scales
|
||||
(D246).
|
||||
- Some front-end 3D models are off — the spinning Nintendo logo renders as two
|
||||
- Some front-end 3D models are off: the spinning Nintendo logo renders as two
|
||||
white blobs and the Rareware logo's texture filtering looks wrong (D75).
|
||||
- The F10 overlay's bottom row duplicates whatever item is currently selected
|
||||
(D251).
|
||||
@@ -103,23 +98,23 @@ Windows and Linux.
|
||||
[`docs/dev/GRAPHICS-BACKLOG.md`](docs/dev/GRAPHICS-BACKLOG.md).
|
||||
- No macOS or ARM support; no controller rebinding UI.
|
||||
|
||||
Root causes and fix status for every item: the [release notes](../../releases)
|
||||
Root causes and fix status for every item: the [release notes](/jkdansereau/goldeneye-pc-port/releases)
|
||||
and the finding log in [`docs/dev/findings.md`](docs/dev/findings.md).
|
||||
|
||||
### Steam Deck
|
||||
|
||||
The Linux bundle is the Deck build. SFTP it over from your PC, or download
|
||||
it straight from the [releases page](../../releases) on the Deck itself:
|
||||
unzip, drop your ROM in `data/`, run `prepare-assets` once, and add the
|
||||
executable as a non-Steam game. SDL2 is bundled, so no dependencies need
|
||||
it straight from the [releases page](/jkdansereau/goldeneye-pc-port/releases) on the Deck itself:
|
||||
unzip, drop your ROM in `data/`, launch it once (the first run generates the
|
||||
derived assets), and add the executable as a non-Steam game. SDL2 is bundled, so no dependencies need
|
||||
installing. On SteamOS the first launch seeds `ge007.ini` with Deck-friendly
|
||||
defaults — native 1280×800 fullscreen, VSync, MSAA 4, and 150% draw/LOD
|
||||
defaults: native 1280×800 fullscreen, VSync, MSAA 4, and 150% draw/LOD
|
||||
distance (the authored N64 fade distances read short on the close-up panel);
|
||||
everything is changeable in the options overlay and persists afterwards. The renderer is CPU-bound (software RSP); expect original N64-era
|
||||
performance at 60 fps rather than more. This release was playtested on real
|
||||
Deck hardware — the v0.1.0-era Facility crash was never reproduced there, and
|
||||
its prime suspect (D253) is fixed; one intermittent SIGSEGV in heavy
|
||||
firefights remains open (D255).
|
||||
Deck hardware; the v0.1.0-era Facility crash (D203) did not recur: its root
|
||||
cause was identified and fixed (D253), verified on the Deck; one intermittent
|
||||
SIGSEGV in heavy firefights remains open (D255).
|
||||
|
||||
**In-game settings on the Deck.** The options overlay is fully gamepad-driven:
|
||||
it opens with **Select**, the D-pad or left stick (up/down) moves between
|
||||
@@ -130,29 +125,29 @@ overlay is `F10` + arrows/Enter.
|
||||
|
||||
## Beyond playing
|
||||
|
||||
- **Tweak it** — `ge007.ini` and the F10 in-game overlay expose resolution,
|
||||
- **Tweak it**: `ge007.ini` and the F10 in-game overlay expose resolution,
|
||||
frame cap, MSAA, texture filtering, FOV/draw distance and mouse feel;
|
||||
launch with `-fresh` for a clean-slate run.
|
||||
- **Read it** — [`docs/internals.md`](docs/internals.md) maps the
|
||||
- **Read it**: [`docs/internals.md`](docs/internals.md) maps the
|
||||
architecture and the software RSP; [`docs/porting-notes.md`](docs/porting-notes.md)
|
||||
is the catalogue of N64→PC bug classes hit along the way. Game logic in
|
||||
`src/` is unmodified decompilation; every hardware surface lives in the
|
||||
MIT-licensed `port/` layer.
|
||||
- **Mod it** — the port layer, build system and `tools_pc/` are yours to
|
||||
- **Mod it**: the port layer, build system and `tools_pc/` are yours to
|
||||
extend (see [License](#license)); [`CONTRIBUTING.md`](CONTRIBUTING.md) has
|
||||
the ground rules for getting changes in, and [`docs/dev/`](docs/dev/) is
|
||||
the raw engineering record behind every fix.
|
||||
|
||||
## Background
|
||||
|
||||
The port was built by two coding agents — a local open-weight model
|
||||
The port was built by two coding agents, a local open-weight model
|
||||
(`unsloth/Qwen3.8-27B-GGUF` on one RTX 5090, via the [pi](https://pi.dev/)
|
||||
agent) doing the groundwork (build, boot chain, software-RSP integration,
|
||||
asset pipeline, first frames), and **Claude Code** (Sonnet 5, Opus 5 for the
|
||||
hardest bugs) joining for the collaborative phase (the 21-level sweep, the
|
||||
ABI finding catalog, SDL input, front end) — handing work back and forth
|
||||
ABI finding catalog, SDL input, front end), handing work back and forth
|
||||
through shared written notes, directed by one person part-time. In short:
|
||||
~3.5 weeks, ~430 commits, 200+ root-caused bugs logged.
|
||||
~3.5 weeks, ~430 commits, 200+ bugs logged and tracked to resolution.
|
||||
|
||||
The full write-up (timeline, handoff mechanism, effort breakdown, an honest
|
||||
"what worked / what didn't"): [`docs/dev/agentic-development.md`](docs/dev/agentic-development.md).
|
||||
@@ -169,18 +164,18 @@ different: they machine-translate the shipped binary of the *unreleased Xbox
|
||||
360 XBLA remaster*, a different game on a different codebase with no shared
|
||||
code with this one.
|
||||
|
||||
| | This project | [GoldenEye-Recomp](https://github.com/SunJaycy/GoldenEye-Recomp) / [Steam Deck build](https://github.com/couchk1ng/GoldenEye-Recomp-SteamDeck) |
|
||||
| | This project | The other well-known "GoldenEye on PC" recompilation projects (and their Steam Deck builds) |
|
||||
|---|---|---|
|
||||
| **What it ports** | The original **Nintendo 64** game (1997) | The **Xbox 360 XBLA** HD remaster (built ~2007, never released) |
|
||||
| **How** | Decompilation-based source port — human-reconstructed C, compiled for the host; game logic runs as written | Static binary recompilation — the shipped machine code is auto-translated to C; no source-level understanding |
|
||||
| **How** | Decompilation-based source port: human-reconstructed C, compiled for the host; game logic runs as written | Static binary recompilation: the shipped machine code is auto-translated to C; no source-level understanding |
|
||||
| **Lineage** | [GoldenEye 007 decompilation](https://github.com/n64decomp/007) + [Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark) engine family | Xbox 360 "…Recompiled" static-recompilation family |
|
||||
| **Renderer** | Software RSP → OpenGL | Hardware (Vulkan) |
|
||||
| **Status** | v0.2.0; see [Status](#status) | Playable full game, higher frame rates, online multiplayer |
|
||||
| **Why it exists** | A [case study in AI-agent collaboration](#background) on a hard low-level codebase | A polished, playable PC release of the remaster |
|
||||
| **Status** | v0.2.0 public release; full campaign playable at 60 fps (see [Status](#status)) | Playable full game with online multiplayer |
|
||||
| **Why it exists** | To run the *original* N64 game from source, and as a [case study in AI-agent collaboration](#background) on a hard low-level codebase | To get a playable PC release of the remaster |
|
||||
|
||||
If you just want to play GoldenEye on PC today, use one of the recompilation
|
||||
projects: they are finished and this is not. What's here is the other half,
|
||||
getting the *original* game running from source.
|
||||
They answer a different question: how to get the *remaster* onto PC by
|
||||
machine translation. This project answers how to get the *original 1997
|
||||
game* onto PC, running from its reconstructed source.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -193,7 +188,9 @@ big-endian (`.z64`) format, matching one of:
|
||||
| PAL (EU) | `pal-final` | `ge007.pal-final.z64` | `167c3c433dec1f1eb921736f7d53fac8cb45ee31` |
|
||||
| NTSC-J (JP) | `jpn-final` | `ge007.jpn-final.z64` | `2a5dade32f7fad6c73c659d2026994632c1b3174` |
|
||||
|
||||
US is the recommended and best-tested version.
|
||||
This release supports the US (NTSC-U) version; PAL and JP ROMs are
|
||||
recognised by region but not yet supported (on the roadmap, [issue
|
||||
#85](/jkdansereau/goldeneye-pc-port/issues/85)).
|
||||
|
||||
The port also relies on the decompilation's asset-extraction step, which pulls
|
||||
the level, model, texture and music data out of your ROM at build time. That
|
||||
@@ -219,7 +216,7 @@ git clone https://github.com/jkdansereau/goldeneye-pc-port.git
|
||||
cd goldeneye-pc-port
|
||||
# 1. extract assets from your ROM (see docs/building.md)
|
||||
# 2. build the port
|
||||
./build-pc.sh ntsc-final # or pal-final / jpn-final
|
||||
./build-pc.sh ntsc-final # NTSC-U; PAL/JP engine builds compile, but their asset sidecars are not yet producible (issue #85)
|
||||
```
|
||||
|
||||
### Linux
|
||||
@@ -314,8 +311,8 @@ Key docs are also published as a site:
|
||||
| [`docs/internals.md`](docs/internals.md) | Architecture, the RSP-emulation approach, GE-vs-PD engine differences, the phased plan. |
|
||||
| [`docs/porting-notes.md`](docs/porting-notes.md) | The recurring N64→PC bug classes hit during the port, with fixes. |
|
||||
| [`docs/dev/agentic-development.md`](docs/dev/agentic-development.md) | The research angle: the two-agent setup, timeline, handoff workflow, and an assessment of what did and didn't work. |
|
||||
| [`docs/dev-process.md`](docs/dev-process.md) | The investigation workflow in detail — budgets, file partitioning, the finding-log discipline. |
|
||||
| [`docs/dev/`](docs/dev/) | The raw engineering record: the full finding log, per-level status, graphics backlog, playtest matrices, and [`docs/dev/game-behavior-reference.md`](docs/dev/game-behavior-reference.md) (a secondary-sourced playtest reference for how the retail game is meant to behave — repo-only, code is ground truth). |
|
||||
| [`docs/dev-process.md`](docs/dev-process.md) | The investigation workflow in detail: budgets, file partitioning, the finding-log discipline. |
|
||||
| [`docs/dev/`](docs/dev/) | The raw engineering record: the full finding log, per-level status, graphics backlog, playtest matrices, and [`docs/dev/game-behavior-reference.md`](docs/dev/game-behavior-reference.md) (a secondary-sourced playtest reference for how the retail game is meant to behave; repo-only, code is ground truth). |
|
||||
| [`docs/SetupGuide.md`](docs/SetupGuide.md), [`docs/StyleGuide.md`](docs/StyleGuide.md) | Inherited from the decompilation this repo forks. |
|
||||
|
||||
## Credits
|
||||
@@ -324,30 +321,30 @@ This port is a thin layer on a large amount of other people's work.
|
||||
|
||||
**Prior work it is built on**
|
||||
|
||||
- The [GoldenEye 007 decompilation](https://github.com/n64decomp/007) — years of
|
||||
- The [GoldenEye 007 decompilation](https://github.com/n64decomp/007), years of
|
||||
effort by Larry Ficken ("kholdfuzion") and the project's contributors; plus
|
||||
zoinkity's GoldenEye documentation, which the decomp started from. This port
|
||||
is a fork of that repository.
|
||||
- The [Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark)
|
||||
(Ryan Dwyer and contributors) — the reference architecture for this port and
|
||||
(Ryan Dwyer and contributors), the reference architecture for this port and
|
||||
the source of the `fast3d` software RSP.
|
||||
- The [Perfect Dark decompilation](https://github.com/n64decomp/perfect_dark) —
|
||||
- The [Perfect Dark decompilation](https://github.com/n64decomp/perfect_dark),
|
||||
the sibling decomp the PD port is built on.
|
||||
- **Carnivorous** — author of the *Mouse Injector* input plugin for 1964 (the
|
||||
- **Carnivorous**: author of the *Mouse Injector* input plugin for 1964 (the
|
||||
"GEPD Edition" bundle). Its mouse-aim behaviour for GoldenEye/Perfect Dark is
|
||||
what our in-game GEPD-style aim mode is modelled on; the implementation here
|
||||
what the in-game GEPD-style aim mode is modelled on; the implementation here
|
||||
is an independent reimplementation of that behaviour, not derived code.
|
||||
Thanks also to **Rice** and **schibo** of the 1964 team for the emulator it
|
||||
shipped with.
|
||||
|
||||
**Vendored / adapted code**
|
||||
|
||||
- `port/fast3d/` — the software RSP, adapted from the PD port. It originates
|
||||
- `port/fast3d/`: the software RSP, adapted from the PD port. It originates
|
||||
with the [Ship of Harkinian](https://github.com/HarbourMasters) /
|
||||
libultraship fast3d (© Emill, MaikelChan; MIT — see `port/fast3d/LICENSE.txt`),
|
||||
libultraship fast3d (© Emill, MaikelChan; MIT, see `port/fast3d/LICENSE.txt`),
|
||||
which itself descends from
|
||||
[sm64-port](https://github.com/sm64-port/sm64-port)'s fast3d and audio mixer.
|
||||
- `port/fast3d/glad/` — OpenGL loader generated by
|
||||
- `port/fast3d/glad/`: OpenGL loader generated by
|
||||
[glad](https://github.com/Dav1dde/glad) (David Herberth, MIT).
|
||||
- The decompilation toolchain: [`ido-static-recomp`](https://github.com/decompals/ido-static-recomp)
|
||||
(Emill / decompals), [`qemu-irix`](https://github.com/n64decomp/qemu-irix) and
|
||||
@@ -357,7 +354,7 @@ This port is a thin layer on a large amount of other people's work.
|
||||
**Methodology**
|
||||
|
||||
- Chris Lewis, [*"Decompiling a Nintendo 64 Game in 84 Days"*](https://blog.chrislewis.au/decompiling-a-nintendo-64-game-in-84-days/) (the Snowboard
|
||||
Kids decompilation write-up) — the agent-workflow practices in
|
||||
Kids decompilation write-up), the agent-workflow practices in
|
||||
[`docs/dev-process.md`](docs/dev-process.md) are adapted from it.
|
||||
|
||||
**Tools and models used to develop the port**
|
||||
@@ -367,7 +364,7 @@ This port is a thin layer on a large amount of other people's work.
|
||||
`UD-Q4_K_XL` quant;
|
||||
[Unsloth](https://unsloth.ai) (the GGUF quantisation and Unsloth Desktop,
|
||||
used as the local model server).
|
||||
- [pi](https://pi.dev/) — the local coding-agent harness.
|
||||
- [pi](https://pi.dev/): the local coding-agent harness.
|
||||
- [Claude / Claude Code](https://claude.com/claude-code) (Anthropic).
|
||||
|
||||
## Legal
|
||||
@@ -376,7 +373,7 @@ This is a non-commercial fan preservation/research project, in the same
|
||||
category as the many other N64 decompilation and native-port repositories on
|
||||
GitHub. It follows the same conventions they do:
|
||||
|
||||
- **No ROM and no game assets are distributed** — not in this repository and
|
||||
- **No ROM and no game assets are distributed**: not in this repository and
|
||||
not in any release. Textures, audio, models, level data and in-game text are
|
||||
extracted from a ROM *you already own*, on *your* machine, at build time.
|
||||
- The repository is a fork of the public
|
||||
@@ -385,7 +382,7 @@ GitHub. It follows the same conventions they do:
|
||||
- No official logos, box art, or marketing assets are used. "GoldenEye 007",
|
||||
"007", "James Bond" and related marks belong to their respective owners
|
||||
(Nintendo, Microsoft/Rare, MGM, Danjaq, EON Productions).
|
||||
- Pre-built binaries published under [Releases](../../releases) contain
|
||||
- Pre-built binaries published under [Releases](/jkdansereau/goldeneye-pc-port/releases) contain
|
||||
only the engine (the `port/` layer plus the compiled decompilation, with no
|
||||
game data of any kind), bundled with permissively-licensed runtime libraries
|
||||
(SDL2, zlib, the MinGW runtime; their licenses travel in the download). Any
|
||||
|
||||
+19
-13
@@ -7,13 +7,13 @@ description: Full build and asset-extraction guide for the GoldenEye 007 PC port
|
||||
|
||||
Stages:
|
||||
|
||||
1. **Extract assets from your ROM** (§2) — a one-time step using the
|
||||
1. **Extract assets from your ROM** (§2): a one-time step using the
|
||||
decompilation's own toolchain to pull levels, models, textures, fonts and
|
||||
music into `assets/`. *(Only needed to regenerate the committed data files;
|
||||
a plain `git clone` already has what the PC build compiles.)*
|
||||
2. **Build the port** (§3) — a CMake build compiling the game sources plus the
|
||||
2. **Build the port** (§3): a CMake build compiling the game sources plus the
|
||||
`port/` layer into a native executable. Needs no ROM.
|
||||
3. **Generate the PC asset sidecars** (§4) — two pure-Python converters turn
|
||||
3. **Generate the PC asset sidecars** (§4): two pure-Python converters turn
|
||||
ROM model / stage data into the PC-layout `data/pcmodels-*` / `data/pccg-*`
|
||||
files the port loads at runtime. **Required to run.**
|
||||
|
||||
@@ -27,10 +27,11 @@ for accepted versions and hashes.
|
||||
|
||||
### Port build
|
||||
|
||||
> **Only the Windows (MSYS2 MINGW64) path is tested.** The Debian/Ubuntu and
|
||||
> macOS columns below are best-effort guidance — the port has never been built
|
||||
> or run on Linux or macOS. Expect to fix build breaks yourself on those
|
||||
> platforms.
|
||||
> **The Windows (MSYS2 MINGW64) path is the primary one.** The Linux build is
|
||||
> compiled by CI on every push and ships in the release bundle (also
|
||||
> playtested on Steam Deck hardware); the macOS column is best-effort
|
||||
> guidance and has never been built or run there. Expect to fix build breaks
|
||||
> yourself on untested platforms.
|
||||
|
||||
| Need | Windows (MSYS2 MINGW64) | Debian/Ubuntu | macOS (Homebrew) |
|
||||
|------|------------------------|---------------|------------------|
|
||||
@@ -45,10 +46,10 @@ for accepted versions and hashes.
|
||||
|
||||
The extraction scripts need `binutils-mips-linux-gnu` (or an equivalent MIPS
|
||||
binutils), `make`, `git`, and `python3`. They build a small host-compiled
|
||||
`tools/extractor` and slice blobs straight out of the ROM — **no IDO / IRIX
|
||||
`tools/extractor` and slice blobs straight out of the ROM; **no IDO / IRIX
|
||||
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".)
|
||||
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).
|
||||
|
||||
@@ -108,7 +109,7 @@ builds are named `ge007.pal-final.x86_64` / `ge007.jpn-final.x86_64`.
|
||||
## 4. Generate the PC asset sidecars (required to run)
|
||||
|
||||
The port does **not** read model geometry, stage bg/stan data, or per-level
|
||||
setup data from the raw ROM at runtime — it reads them from PC-layout *sidecar*
|
||||
setup data from the raw ROM at runtime; it reads them from PC-layout *sidecar*
|
||||
files under `data/`, produced offline by three converters. **Without them the
|
||||
game shows the intro logos and then crashes** in
|
||||
`modelPromoteNodeOffsetsToPointers` (finding D179) or on the first level load
|
||||
@@ -130,6 +131,9 @@ python3 tools_pc/d69_emit.py ntsc-final # -> data/pccg-ntsc-final/{pccg
|
||||
python3 tools_pc/d88_emit.py ntsc-final --regen # appends the 21 per-level Usetup*Z stage-setup files -> ~3.6 MB
|
||||
```
|
||||
|
||||
**PAL / JP note:** sidecar generation for these regions is currently broken at
|
||||
the source-data level (finding D258); use an NTSC-U ROM until issue #85 lands.
|
||||
|
||||
These are **pure-stdlib Python 3** (no MIPS toolchain, independent of the
|
||||
step-2 asset extraction) and read only the ROM plus files already committed to
|
||||
the repo (`scripts/filelist.u.csv`, `assets/obseg/file_resource_table.inc.c`,
|
||||
@@ -138,10 +142,12 @@ deterministic function of the ROM. Re-run after any change to `d43_emit.py` /
|
||||
`d69_emit.py` / `d88_emit.py` or the model/bg converters (`d43_*`, `d69_*`,
|
||||
`d88_propdefs.py`).
|
||||
|
||||
> The release bundle ships `prepare-assets/prepare-assets.py`, which runs all
|
||||
> three passes against your ROM automatically — see the bundled `README.md`.
|
||||
> The release bundle ships the same converter frozen as
|
||||
> `prepare-assets/ge007-convert`; the game spawns it on first launch when the
|
||||
> sidecars are missing, so end users never run it by hand. See the bundled
|
||||
> `README.md`.
|
||||
|
||||
> `data/pcmodels-*/` and `data/pccg-*/` are gitignored ROM-derived game data —
|
||||
> `data/pcmodels-*/` and `data/pccg-*/` are gitignored ROM-derived game data;
|
||||
> never commit or redistribute them.
|
||||
|
||||
---
|
||||
|
||||
+23
-23
@@ -1,37 +1,37 @@
|
||||
---
|
||||
title: Development Process
|
||||
description: The investigation workflow behind the port — task budgets, file partitioning, and the finding-log discipline used across sessions and agents.
|
||||
description: The investigation workflow behind the port; task budgets, file partitioning, and the finding-log discipline used across sessions and agents.
|
||||
---
|
||||
|
||||
# How this port is developed
|
||||
|
||||
Most of this port's work is not writing code — it is **diagnosis**: figuring
|
||||
Most of this port's work is not writing code; it is **diagnosis**: figuring
|
||||
out which N64 hardware or ABI behavior a piece of unmodified game code is
|
||||
silently relying on, and satisfying it in the `port/` layer without touching
|
||||
the game's logic. A lot of that diagnosis is done with LLM coding agents, and
|
||||
the workflow below is what makes that productive rather than chaotic.
|
||||
|
||||
For the project context — the two-model split, the timeline, and an honest
|
||||
assessment of what did and did not work — see
|
||||
For the project context (the two-model split, the timeline, and an honest
|
||||
assessment of what did and did not work), see
|
||||
[`dev/agentic-development.md`](dev/agentic-development.md).
|
||||
|
||||
It is adapted from Chris Lewis's write-up
|
||||
[*"Decompiling a Nintendo 64 Game in 84 Days"*](https://blog.chrislewis.au/decompiling-a-nintendo-64-game-in-84-days/)
|
||||
(Snowboard Kids, 2026), an AI-assisted decompilation that ran several times
|
||||
faster than its predecessor. That project bit-matches compiler output;
|
||||
this one matches runtime behavior, so the mechanics differ — but the
|
||||
this one matches runtime behavior, so the mechanics differ; but the
|
||||
project-structure lessons carry over directly.
|
||||
|
||||
## 1. Every investigation task gets a visible budget
|
||||
|
||||
An open-ended tool — for them the permuter, for us "rebuild and run the game
|
||||
and stare at a frame dump" — wrecks throughput when an agent will grind it
|
||||
An open-ended tool; for them the permuter, for us "rebuild and run the game
|
||||
and stare at a frame dump"; wrecks throughput when an agent will grind it
|
||||
indefinitely. Giving the agent a **deadline it can see** lets it trade
|
||||
tool-time against thinking and decide when to give up.
|
||||
|
||||
So every investigation brief states:
|
||||
|
||||
- a **budget** — "≤ N build → run → inspect cycles" or "~M minutes"; and
|
||||
- a **budget**; "≤ N build → run → inspect cycles" or "~M minutes"; and
|
||||
- the **fallback on expiry**: stop, revert any temporary probes, and write up
|
||||
what was found with an explicit confidence rating. A good write-up of a
|
||||
half-solved bug is a deliverable, not a failure.
|
||||
@@ -45,7 +45,7 @@ more room.
|
||||
|
||||
Lewis's agents recorded generalisable IDO quirks in a learnings file; later
|
||||
agents read it and did better. Our equivalent is
|
||||
[`porting-notes.md`](porting-notes.md) — the recurring N64→PC bug classes,
|
||||
[`porting-notes.md`](porting-notes.md); the recurring N64→PC bug classes,
|
||||
each entry a terse index into the full
|
||||
[`dev/findings.md`](https://github.com/jkdansereau/goldeneye-pc-port/blob/main/docs/dev/findings.md)
|
||||
log. Every investigation brief links it, and every investigation ends by
|
||||
@@ -54,8 +54,8 @@ appending any new generalisable quirk.
|
||||
The classes it currently tracks:
|
||||
|
||||
- pointer-width struct growth (32→64) in ROM-serialized or pun-allocated
|
||||
structs — the dominant class;
|
||||
- 16-byte host `Gfx`/`Vtx` vs 8-byte N64 — reservation and copy sizing;
|
||||
structs; the dominant class;
|
||||
- 16-byte host `Gfx`/`Vtx` vs 8-byte N64; reservation and copy sizing;
|
||||
- big-endian rodata read on a little-endian host: `f32` word-pairs, header
|
||||
offset tables, packed bitfields;
|
||||
- N64 hardware idioms the software RSP does not emulate (fill-rect Z clear,
|
||||
@@ -71,7 +71,7 @@ Lewis ran multiple git worktrees and found the real cost was
|
||||
- **Partition tracks by the files they will touch**, so patches never collide.
|
||||
A task that can't be cleanly file-partitioned shouldn't be parallelised.
|
||||
- Each agent reverts its own temporary probes before reporting, leaving only
|
||||
committed, env-gated, capped diagnostics — and never touches another track's
|
||||
committed, env-gated, capped diagnostics; and never touches another track's
|
||||
uncommitted edits.
|
||||
- One integrator merges each track with its write-up, then the next round
|
||||
starts from a clean tree. Investigation branches are not allowed to drift.
|
||||
@@ -85,7 +85,7 @@ Before dispatching an investigation agent:
|
||||
- capture a baseline frame dump;
|
||||
- grep the finding log for a prior instance of the same bug class;
|
||||
- check the [Perfect Dark port](https://github.com/fgsfdsfgs/perfect_dark) for
|
||||
the analogous code — same engine family.
|
||||
the analogous code; same engine family.
|
||||
|
||||
Then hand the agent the *findings*, not just the problem.
|
||||
|
||||
@@ -94,12 +94,12 @@ Then hand the agent the *findings*, not just the problem.
|
||||
- **The match-percentage loop.** This port doesn't bit-match. "Done" is: no
|
||||
fault, and visually correct against N64 reference footage.
|
||||
- **"Understanding the function is the easy part."** True when decompiling;
|
||||
inverted here — the hard part is identifying the implicit hardware/ABI
|
||||
inverted here; the hard part is identifying the implicit hardware/ABI
|
||||
contract the already-readable C depends on.
|
||||
|
||||
## 6. Keep PR/git-history noise low
|
||||
|
||||
A session produces a lot of small, independently-verifiable units of work —
|
||||
A session produces a lot of small, independently-verifiable units of work;
|
||||
one Dxx row, one docs pass, one mechanical fix. Left unmanaged that turns
|
||||
into a pile of small open PRs that's harder to review than the work
|
||||
justifies. Rules:
|
||||
@@ -107,31 +107,31 @@ justifies. Rules:
|
||||
- **Squash-merge single-purpose and docs-only PRs.** The repo has squash
|
||||
merge enabled; use it (`gh pr merge --squash --delete-branch`) for anything
|
||||
whose in-branch commit history (iteration, probe-add, probe-strip) isn't
|
||||
itself useful to keep — which is most PRs. Reserve a plain merge commit for
|
||||
itself useful to keep; which is most PRs. Reserve a plain merge commit for
|
||||
a PR whose individual commits are each a distinct, reviewable unit someone
|
||||
might want to `git revert` independently (e.g. this session's PR #50: a
|
||||
fix commit + a separate analysis-only commit).
|
||||
- **Batch same-session, same-flavor docs updates into one PR/branch**
|
||||
instead of opening a new PR per finding row. A runtime re-check that
|
||||
updates one `findings.md` row (like #48) doesn't need its own PR if
|
||||
another docs-only branch is already open in the same session — fold it in.
|
||||
another docs-only branch is already open in the same session; fold it in.
|
||||
Only split into separate PRs when the pieces have genuinely different
|
||||
review/merge timing (e.g. one needs a human playtest, the other doesn't).
|
||||
- **A branch takes only the change it's named for.** Don't let unrelated
|
||||
housekeeping (a stray gitignore fix, a config tweak) ride along on an
|
||||
active feature/fix branch just because it's the one checked out — cut a
|
||||
active feature/fix branch just because it's the one checked out; cut a
|
||||
separate branch, even for a one-line change.
|
||||
- **Stacked PRs declare the dependency in the title/body** ("step 2 of N,
|
||||
step 1 is #N") and get rebased/merged in order promptly — don't let a
|
||||
step 1 is #N") and get rebased/merged in order promptly; don't let a
|
||||
later step sit open so long the earlier step's content drifts under it.
|
||||
- **Triage the open-PR list at least once a session**, ordered by
|
||||
time-to-close (docs-only and non-draft first, human-playtest-gated last).
|
||||
A PR idle long enough that `main` has moved past the finding rows it
|
||||
touches is **stale, not just old** — check for real textual conflict
|
||||
touches is **stale, not just old**; check for real textual conflict
|
||||
(`git merge-tree`), not just calendar age. If `main` already has more
|
||||
current information than the PR (a bug the PR still lists `OPEN` that's
|
||||
since been fixed and verified), **close it rather than force a merge or
|
||||
spend a cycle rebasing it** — re-derive only whatever part of its content
|
||||
spend a cycle rebasing it**; re-derive only whatever part of its content
|
||||
is still true as a fresh, small PR against current `main`. Merging stale
|
||||
content back over newer information is a regression, not a save.
|
||||
|
||||
@@ -141,11 +141,11 @@ justifies. Rules:
|
||||
TASK: <one bug, one subsystem>.
|
||||
READ FIRST: docs/porting-notes.md; docs/dev/findings.md <specific Dxx entries>.
|
||||
FILES YOU MAY TOUCH: <disjoint from any other in-flight work>.
|
||||
KNOWN-GOOD / RULED OUT: <list — do not re-investigate>.
|
||||
KNOWN-GOOD / RULED OUT: <list; do not re-investigate>.
|
||||
PRE-FLIGHT ATTACHED: <probe output, baseline capture, PD-port pointer>.
|
||||
BUDGET: <N build->run cycles / ~M min>. On expiry: revert probes, write up with confidence.
|
||||
CONSTRAINTS: no game-logic changes; ABI/layout/format only; #ifdef PORT; documented in the finding log.
|
||||
VERIFY: <the exact tools_pc/verify.sh (or probe) invocation that proves this done — or, if runtime verification is impossible in this environment, say so and name what a human must run>.
|
||||
VERIFY: <the exact tools_pc/verify.sh (or probe) invocation that proves this done; or, if runtime verification is impossible in this environment, say so and name what a human must run>.
|
||||
REPORT: (a) root cause + file:line evidence (b) fix diff, or why not
|
||||
(c) probes left in tree (d) confidence.
|
||||
Append any generalisable quirk to docs/porting-notes.md.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Agentic Development
|
||||
description: A case study in two AI coding agents porting a Nintendo 64 game to PC — the setup, timeline, handoff workflow, and an honest assessment of what worked.
|
||||
description: A case study in two AI coding agents porting a Nintendo 64 game to PC; the setup, timeline, handoff workflow, and an honest assessment of what worked.
|
||||
---
|
||||
|
||||
# Agentic development: two AI coding agents porting GoldenEye 007
|
||||
@@ -16,7 +16,7 @@ what did and didn't work.*
|
||||
- [Why this project exists](#why-this-project-exists)
|
||||
- [The setup](#the-setup)
|
||||
- [Timeline](#timeline)
|
||||
- [By the numbers](#by-the-numbers) — [Commit velocity](#commit-velocity) · [Who did what](#who-did-what)
|
||||
- [By the numbers](#by-the-numbers); [Commit velocity](#commit-velocity) · [Who did what](#who-did-what)
|
||||
- [The handoff workflow](#the-handoff-workflow)
|
||||
- [Assessment](#assessment)
|
||||
|
||||
@@ -24,7 +24,7 @@ what did and didn't work.*
|
||||
|
||||
The playable port is real, but it is not the primary deliverable. The goal was
|
||||
to **test how well coding agents hold up on a large, unfamiliar, low-level
|
||||
codebase** — one with none of the properties that make web-app work easy for
|
||||
codebase**; one with none of the properties that make web-app work easy for
|
||||
an LLM:
|
||||
|
||||
- ~230 translation units of decompiled Nintendo 64 game C, compiled
|
||||
@@ -39,7 +39,7 @@ an LLM:
|
||||
Concretely it set out to validate a **two-agent arrangement**: a
|
||||
locally-hosted open-weight model doing the bulk of the work on a single
|
||||
consumer GPU, a hosted frontier model brought in for a collaborative phase,
|
||||
and — the part that turned out most interesting — the two **handing work back
|
||||
and, the part that turned out most interesting, the two **handing work back
|
||||
and forth** through shared written artifacts, directed by one human.
|
||||
|
||||
## The setup
|
||||
@@ -47,17 +47,17 @@ and forth** through shared written artifacts, directed by one human.
|
||||
| | |
|
||||
|---|---|
|
||||
| Local agent | `unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL` on a single **NVIDIA RTX 5090**, driven mainly through the **[pi](https://pi.dev/)** coding agent. Unsloth Desktop (Unsloth's local model runtime, which can drive agents such as Claude Code) was also trialed but not used significantly. |
|
||||
| Hosted agent | **Claude**, via **Claude Code**, on a Claude Pro subscription — mostly **Sonnet 5**, with **Opus 5** used as an escalation tier for the hardest problems and whenever there was subscription budget to spend on it |
|
||||
| Hosted agent | **Claude**, via **Claude Code**, on a Claude Pro subscription; mostly **Sonnet 5**, with **Opus 5** used as an escalation tier for the hardest problems and whenever there was subscription budget to spend on it |
|
||||
| Human | one person: direction, work partitioning, integration, and every build / playtest / frame-capture the agents could not run |
|
||||
| Base | fork of the [GoldenEye 007 decompilation](https://github.com/n64decomp/007) (years of prior work by Larry Ficken ("kholdfuzion") and contributors) |
|
||||
| Reused | the [Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark)'s `fast3d` software RSP — same Rare engine family |
|
||||
| Reused | the [Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark)'s `fast3d` software RSP; same Rare engine family |
|
||||
|
||||
The port is the GoldenEye-specific porting work **on top of** those two
|
||||
existing bodies of work; it is not a from-scratch reimplementation of either.
|
||||
|
||||
In practice the models formed a **three-tier escalation**: the local model
|
||||
handled well-scoped work, Sonnet 5 took what it stalled on, and Opus 5 was
|
||||
reserved for the bugs that needed the most reasoning held at once — the same
|
||||
reserved for the bugs that needed the most reasoning held at once; the same
|
||||
"escalate when stuck" move applied at every level.
|
||||
|
||||
## Timeline
|
||||
@@ -68,7 +68,7 @@ All dates from this repository's own commit history (August 2026).
|
||||
gantt
|
||||
dateFormat YYYY-MM-DD
|
||||
axisFormat %b %d
|
||||
title GoldenEye 007 PC port — from fork to playable front end
|
||||
title GoldenEye 007 PC port; from fork to playable front end
|
||||
section Local model - Qwen 3.8 via pi
|
||||
Fork + PC-port scaffolding :m1, 2026-08-16, 1d
|
||||
Full compile + link (~230 TUs) :m2, 2026-08-20, 1d
|
||||
@@ -90,7 +90,7 @@ gantt
|
||||
- **Day 4** (20 Aug): the entire ~230-TU game + libultra set compiles and
|
||||
links as a host binary.
|
||||
- **Day 6** (22 Aug): first real frames render.
|
||||
- **Day 8** (24 Aug): the whole intro sequence renders — logos, gun-barrel,
|
||||
- **Day 8** (24 Aug): the whole intro sequence renders; logos, gun-barrel,
|
||||
cast roll.
|
||||
- **Day 11** (27 Aug): second agent joins.
|
||||
- **Day 13** (29 Aug): **all 21 solo missions load, render, and survive an
|
||||
@@ -100,7 +100,7 @@ gantt
|
||||
|
||||
So roughly **two weeks**, one person part-time, to take a decompilation from
|
||||
"builds an N64 ROM" to "boots on desktop, renders every solo level, playable
|
||||
through the front end into the early game" — with audio and a set of cosmetic
|
||||
through the front end into the early game"; with audio and a set of cosmetic
|
||||
issues still outstanding.
|
||||
|
||||
## By the numbers
|
||||
@@ -139,7 +139,7 @@ pie showData title "Commits by agent (raw count)"
|
||||
"Local model (Qwen 3.8 / pi)" : 62
|
||||
```
|
||||
|
||||
(Phase A — the first 26 commits, to 24 Aug — was entirely the local model,
|
||||
(Phase A, the first 26 commits, to 24 Aug, was entirely the local model,
|
||||
solo; from 27 Aug on the two agents worked in parallel.)
|
||||
|
||||
| Milestone / workstream | Primary agent | Weight |
|
||||
@@ -150,20 +150,20 @@ solo; from 27 Aug on the two agents worked in parallel.)
|
||||
| Offline asset-conversion architecture + first converters (`tools_pc/`) | local model | large |
|
||||
| Intro rendering (logos → gun-barrel → cast) | local model | medium |
|
||||
| Stage load unblocked (`D69`–`D87`) | Claude | medium |
|
||||
| 21-level crash sweep — ~12 crash classes root-caused (`D88`–`D169`) | Claude | large |
|
||||
| 21-level crash sweep; ~12 crash classes root-caused (`D88`–`D169`) | Claude | large |
|
||||
| SDL input layer (keyboard / mouse / gamepad, mouse-look) | Claude | medium |
|
||||
| Front-end flow (menu → briefing → start), EEPROM saves | Claude | medium |
|
||||
| Parallel struct-layout / converter static audits | local model | medium |
|
||||
| Continuing tasks after Claude hit a usage limit | local model | small |
|
||||
| The hardest structural bugs (matrix handedness, format specs) | Claude | — |
|
||||
| Every build, playtest, frame capture, integration, and direction | human | — |
|
||||
| The hardest structural bugs (matrix handedness, format specs) | Claude | n/a |
|
||||
| Every build, playtest, frame capture, integration, and direction | human | n/a |
|
||||
|
||||
**Estimated effort split.** The raw commit count above (~28% local / ~72%
|
||||
Claude) undercounts the local model: Phase A landed the build system and boot
|
||||
chain in relatively few, large commits, and the local model kept contributing
|
||||
~15–20% of Phase B in parallel. Weighting by milestone difficulty rather than
|
||||
raw commits — the foundation is a heavier third of the project than its commit
|
||||
share suggests — the developer's estimate is roughly:
|
||||
raw commits; the foundation is a heavier third of the project than its commit
|
||||
share suggests; the developer's estimate is roughly:
|
||||
|
||||
```mermaid
|
||||
pie showData title "Agent effort, milestone-weighted"
|
||||
@@ -202,28 +202,28 @@ flowchart LR
|
||||
Both agents worked against the **same three written artifacts**, which is what
|
||||
let them substitute for each other:
|
||||
|
||||
1. **`HANDOFF.md`** — the current state, the immediate next task, and the
|
||||
1. **`HANDOFF.md`**; the current state, the immediate next task, and the
|
||||
environment gotchas. Originally a session-to-session note for one agent, it
|
||||
became the **interface between the two agents**: when Claude reached a
|
||||
usage limit mid-problem, the local model picked the task up from the
|
||||
HANDOFF state and continued; when the local model hit a bug that needed
|
||||
deeper structural reasoning, it wrote up where it was and Claude took over.
|
||||
2. **`findings.md`** — the chronological finding log. 162 numbered entries,
|
||||
2. **`findings.md`**; the chronological finding log. 162 numbered entries,
|
||||
each a root cause with `file:line` evidence and the fix. New agents (either
|
||||
model) are pointed at the relevant entries before they start.
|
||||
3. **`porting-notes.md`** — the append-only "recurring bug classes" file. The
|
||||
3. **`porting-notes.md`**; the append-only "recurring bug classes" file. The
|
||||
single highest-leverage artifact: it stopped both models from
|
||||
re-deriving the same class of N64→PC bug over and over.
|
||||
|
||||
Around these, the working rules (full detail in
|
||||
[`../dev-process.md`](../dev-process.md)):
|
||||
|
||||
- **file-partitioned tasks** — each agent's task scoped to a disjoint set of
|
||||
- **file-partitioned tasks**; each agent's task scoped to a disjoint set of
|
||||
files so patches never collided;
|
||||
- **visible budgets** — every investigation task carried an explicit
|
||||
- **visible budgets**; every investigation task carried an explicit
|
||||
"N build→run cycles" limit and a defined fallback (revert probes, write up
|
||||
with a confidence rating);
|
||||
- **the human owns verification** — building, running the game, capturing a
|
||||
- **the human owns verification**; building, running the game, capturing a
|
||||
frame, and judging it against N64 reference footage was never delegated.
|
||||
|
||||
## Assessment
|
||||
@@ -232,7 +232,7 @@ Honest notes, for anyone weighing whether this transfers.
|
||||
|
||||
**Worked well**
|
||||
|
||||
- The **local model carried the groundwork phase** — build system, boot
|
||||
- The **local model carried the groundwork phase**; build system, boot
|
||||
chain, OS shims, and the offline-converter architecture. None of it was
|
||||
rewritten later. A 27B open model on one consumer GPU was genuinely productive
|
||||
on this.
|
||||
@@ -241,14 +241,14 @@ Honest notes, for anyone weighing whether this transfers.
|
||||
because the accumulated notes were good. This is also what made the two
|
||||
models interchangeable on a given task.
|
||||
- **Handoff on limit** turned Claude's usage cap from a hard stop into a
|
||||
slowdown — the local model kept the problem moving.
|
||||
slowdown; the local model kept the problem moving.
|
||||
- Bounded behavioural bugs (a truncated pointer, a byte-swap off by one) are a
|
||||
good fit for an agent given a tight loop and a reference to diff against.
|
||||
|
||||
**Worked poorly / needed the human**
|
||||
|
||||
- **Anything requiring the running game.** Build, playtest, capture a frame,
|
||||
decide whether it looks right — that loop was the human's job throughout,
|
||||
decide whether it looks right; that loop was the human's job throughout,
|
||||
and it was the bottleneck.
|
||||
- **Non-deterministic bugs.** Frame-timing stalls and concurrent-build
|
||||
flakiness repeatedly fooled agents into "fixing" regressions that were not
|
||||
@@ -258,7 +258,7 @@ Honest notes, for anyone weighing whether this transfers.
|
||||
rather than a fix, even with the budget raised.
|
||||
- **The capability gap is a gradient, not a wall.** The local model was strong
|
||||
on well-scoped work and weaker when a bug needed several interacting facts
|
||||
held at once — those went to Sonnet 5, and the few that stalled Sonnet went
|
||||
held at once; those went to Sonnet 5, and the few that stalled Sonnet went
|
||||
to Opus 5. Each tier earned its place on the problems the tier below it
|
||||
couldn't close.
|
||||
|
||||
|
||||
+50
-47
@@ -3,7 +3,7 @@ title: GoldenEye 007 PC Port
|
||||
description: >-
|
||||
A native PC port of the original Nintendo 64 GoldenEye 007, built from its
|
||||
decompiled source with a software RSP. v0.2.0 is out for Windows
|
||||
and Linux (including Steam Deck) — download it, drop in your own ROM, and
|
||||
and Linux (including Steam Deck): download it, drop in your own ROM, and
|
||||
play; or dig into the code and the engineering record behind it.
|
||||
---
|
||||
|
||||
@@ -11,16 +11,16 @@ description: >-
|
||||
|
||||
A native PC port of the original 1997 Nintendo 64 _GoldenEye 007_, compiled
|
||||
from the game's [decompiled source](https://github.com/n64decomp/007) with the
|
||||
N64's graphics coprocessor (RSP) running in software — the same architecture
|
||||
N64's graphics coprocessor (RSP) running in software, the same architecture
|
||||
as the [Perfect Dark PC port](https://github.com/fgsfdsfgs/perfect_dark), the
|
||||
same Rare "Indy" engine family, one hardware generation apart.
|
||||
|
||||
**Status: v0.2.0** — to our knowledge, the first open-source port of the
|
||||
original N64 game to ship as a public release. The full single-player
|
||||
campaign runs at a steady 60 fps with no known crashes, and audio (music +
|
||||
SFX) plays throughout.
|
||||
Known rough edges — cutscenes still glitch, a few music tracks sound wrong, a
|
||||
handful of cosmetic rendering defects remain — are listed plainly under
|
||||
**Status: v0.2.0.** The full single-player campaign runs at a steady 60 fps
|
||||
and is completable end to end; all 21 missions load and run clean on Windows
|
||||
and Linux (one intermittent Steam Deck crash remains, listed below), and
|
||||
audio (music + SFX) plays throughout. The known
|
||||
rough edges (cutscenes that still glitch, a few music tracks that sound
|
||||
wrong, a handful of cosmetic rendering defects) are listed plainly under
|
||||
[Honest status](#honest-status).
|
||||
|
||||
<p align="center">
|
||||
@@ -34,13 +34,15 @@ handful of cosmetic rendering defects remain — are listed plainly under
|
||||
| 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 — it runs as-is on any distro, and sideloads onto a Deck with nothing installed. |
|
||||
| **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. |
|
||||
|
||||
**Bring your own ROM.** Both bundles contain no ROM and no game assets — you
|
||||
**Bring your own ROM.** Both bundles contain no ROM and no game assets: you
|
||||
supply your own GoldenEye 007 N64 ROM (the
|
||||
[Requirements table](https://github.com/jkdansereau/goldeneye-pc-port#requirements)
|
||||
has the three region filenames and SHA-1s). Then: unpack, drop the ROM in
|
||||
`data/`, run `prepare-assets` once, launch. The full four steps are in the
|
||||
has the region filenames and SHA-1s). This release supports the NTSC-U (US)
|
||||
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.
|
||||
@@ -53,83 +55,83 @@ without a ROM you already own.
|
||||
</p>
|
||||
|
||||
<details>
|
||||
<summary><strong>Full playtest gallery</strong> — 19 in-engine captures from the v0.2.0-pre Windows playtest, across the campaign</summary>
|
||||
<summary><strong>Full playtest gallery</strong>: 19 in-engine captures from the v0.2.0 Windows playtest, across the campaign</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.2.0-pre)">
|
||||
<img src="img/shots/shot-01.jpg" width="100%" alt="In-engine: Dam (v0.2.0)">
|
||||
<div><small>Dam</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-02.jpg" width="100%" alt="In-engine — Facility (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-02.jpg" width="100%" alt="In-engine: Facility (v0.2.0)">
|
||||
<div><small>Facility</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.2.0-pre)">
|
||||
<img src="img/shots/shot-03.jpg" width="100%" alt="In-engine: Runway (v0.2.0)">
|
||||
<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.2.0-pre)">
|
||||
<img src="img/shots/shot-04.jpg" width="100%" alt="In-engine: Surface (v0.2.0)">
|
||||
<div><small>Surface</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-05.jpg" width="100%" alt="In-engine — Surface (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-05.jpg" width="100%" alt="In-engine: Surface (v0.2.0)">
|
||||
<div><small>Surface</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-06.jpg" width="100%" alt="In-engine — Bunker 1 (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-06.jpg" width="100%" alt="In-engine: Bunker 1 (v0.2.0)">
|
||||
<div><small>Bunker 1</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-07.jpg" width="100%" alt="In-engine — Silo (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-07.jpg" width="100%" alt="In-engine: Silo (v0.2.0)">
|
||||
<div><small>Silo</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.2.0-pre)">
|
||||
<img src="img/shots/shot-09.jpg" width="100%" alt="In-engine: Frigate (v0.2.0)">
|
||||
<div><small>Frigate</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-10.jpg" width="100%" alt="In-engine — Frigate (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-10.jpg" width="100%" alt="In-engine: Frigate (v0.2.0)">
|
||||
<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.2.0-pre)">
|
||||
<img src="img/shots/shot-11.jpg" width="100%" alt="In-engine: Surface 2 (v0.2.0)">
|
||||
<div><small>Surface 2</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-13.jpg" width="100%" alt="In-engine — Bunker 2 (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-13.jpg" width="100%" alt="In-engine: Bunker 2 (v0.2.0)">
|
||||
<div><small>Bunker 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.2.0-pre)">
|
||||
<img src="img/shots/shot-16.jpg" width="100%" alt="In-engine: Statue (v0.2.0)">
|
||||
<div><small>Statue</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-19.jpg" width="100%" alt="In-engine — Statue (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-19.jpg" width="100%" alt="In-engine: Statue (v0.2.0)">
|
||||
<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.2.0-pre)">
|
||||
<img src="img/shots/shot-20.jpg" width="100%" alt="In-engine: Archives (v0.2.0)">
|
||||
<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.2.0-pre)">
|
||||
<img src="img/shots/shot-21.jpg" width="100%" alt="In-engine: Cradle (v0.2.0)">
|
||||
<div><small>Cradle</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-23.jpg" width="100%" alt="In-engine — Cradle (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-23.jpg" width="100%" alt="In-engine: Cradle (v0.2.0)">
|
||||
<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.2.0-pre)">
|
||||
<img src="img/shots/shot-24.jpg" width="100%" alt="In-engine: Aztec (v0.2.0)">
|
||||
<div><small>Aztec</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-25.jpg" width="100%" alt="In-engine — Aztec (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-25.jpg" width="100%" alt="In-engine: Aztec (v0.2.0)">
|
||||
<div><small>Aztec</small></div>
|
||||
</div>
|
||||
<div style="width:32%;text-align:center;margin:4px">
|
||||
<img src="img/shots/shot-26.jpg" width="100%" alt="In-engine — Frigate (v0.2.0-pre)">
|
||||
<img src="img/shots/shot-26.jpg" width="100%" alt="In-engine: Frigate (v0.2.0)">
|
||||
<div><small>Frigate</small></div>
|
||||
</div>
|
||||
</p>
|
||||
@@ -137,23 +139,23 @@ without a ROM you already own.
|
||||
|
||||
More captures may land here as playtesting continues.
|
||||
|
||||
## Play it — or take it apart
|
||||
## Play it, or take it apart
|
||||
|
||||
- **Try it yourself** — grab a bundle above, bring your own ROM, and play the
|
||||
- **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
|
||||
[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;
|
||||
- **Read the code**: the game logic in `src/` is unmodified decompilation;
|
||||
every hardware surface (video, audio, input, save storage, and the
|
||||
software-RSP renderer) is shimmed in the MIT-licensed `port/` layer.
|
||||
[Internals](internals.md) is the map; [Porting notes](porting-notes.md) is
|
||||
the catalogue of N64→PC bug classes hit along the way — a good read even if
|
||||
the catalogue of N64→PC bug classes hit along the way, a good read even if
|
||||
you never touch the code.
|
||||
- **Mod it** — the port layer, build system and `tools_pc/` helpers are MIT
|
||||
- **Mod it**: the port layer, build system and `tools_pc/` helpers are MIT
|
||||
licensed and yours to extend: new video options, input tweaks, your own
|
||||
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.
|
||||
- **The research angle** — this is also a case study in AI-agent collaboration
|
||||
- **The research angle**: this is also a case study in AI-agent collaboration
|
||||
on a large, low-level codebase: two coding agents (a local open-weight model
|
||||
on a single RTX 5090, and Claude / Claude Code), driven by one person
|
||||
part-time through ~230 translation units of unmodified big-endian MIPS game
|
||||
@@ -162,20 +164,21 @@ More captures may land here as playtesting continues.
|
||||
|
||||
## How it works
|
||||
|
||||
The R4300 game code is compiled completely unmodified — the decompilation's
|
||||
The R4300 game code is compiled completely unmodified; the decompilation's
|
||||
control flow is ground truth. 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 GBI stream 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
|
||||
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).
|
||||
|
||||
## Honest status
|
||||
|
||||
- **Cutscenes glitch frequently** — skipped beats, wrong camera, misplaced or
|
||||
hovering actors. The most visible gap in this release.
|
||||
- **Cutscenes still glitch, mostly with James Bond**: in scripted sequences
|
||||
Bond is the one who gets misplaced, hovers, or spins; the other actors are
|
||||
fine for the most part now. Still the most visible gap in this release.
|
||||
- A few in-level music tracks sound wrong (wrong instruments, occasional garbling).
|
||||
- Particle colours drift through a rainbow palette instead of holding grey/orange.
|
||||
- Water levels show a moving seam; pixel strips at screen edges at non-integer
|
||||
@@ -190,11 +193,11 @@ and the [finding log](https://github.com/jkdansereau/goldeneye-pc-port/tree/main
|
||||
|
||||
## Documentation
|
||||
|
||||
- [The two-agent development case study](dev/agentic-development.md) — goal, setup, timeline, the handoff workflow, and an honest assessment of what did and didn't work.
|
||||
- [Development process](dev-process.md) — how work was scoped, partitioned, and budgeted across agents; the finding-log discipline.
|
||||
- [Internals](internals.md) — architecture, the software RSP-emulation approach, GoldenEye-vs-Perfect-Dark engine differences, the phased plan.
|
||||
- [Porting notes](porting-notes.md) — the recurring Nintendo 64 → PC bug classes hit during the port, with fixes.
|
||||
- [Building](building.md) — full build and asset-extraction guide.
|
||||
- [The two-agent development case study](dev/agentic-development.md): goal, setup, timeline, the handoff workflow, and an honest assessment of what did and didn't work.
|
||||
- [Development process](dev-process.md): how work was scoped, partitioned, and budgeted across agents; the finding-log discipline.
|
||||
- [Internals](internals.md): architecture, the software RSP-emulation approach, GoldenEye-vs-Perfect-Dark engine differences, the phased plan.
|
||||
- [Porting notes](porting-notes.md): the recurring Nintendo 64 → PC bug classes hit during the port, with fixes.
|
||||
- [Building](building.md): full build and asset-extraction guide.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+57
-57
@@ -1,14 +1,14 @@
|
||||
---
|
||||
title: Internals
|
||||
description: Architecture behind the PC port — the software RSP-emulation approach, GoldenEye-vs-Perfect-Dark engine differences, and the phased development plan.
|
||||
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
|
||||
# GoldenEye 007 PC Port: 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
|
||||
> external references. The phased plan in section 8 is largely done through
|
||||
> Phase 2 — for current status see the
|
||||
> Phase 2; for current status see the
|
||||
> [README](https://github.com/jkdansereau/goldeneye-pc-port#status) and
|
||||
> [`dev/LEVEL-STATUS.md`](https://github.com/jkdansereau/goldeneye-pc-port/blob/main/docs/dev/LEVEL-STATUS.md);
|
||||
> for the blow-by-blow finding log see
|
||||
@@ -28,18 +28,18 @@ platforms.
|
||||
|
||||
1. [Executive summary](#1-executive-summary)
|
||||
2. [What the PD port actually does (the reference architecture)](#2-what-the-pd-port-actually-does-the-reference-architecture)
|
||||
— [2.1 Emulate the RSP, bypass the RDP](#21-the-key-architectural-insight-emulate-the-rsp-bypass-the-rdp)
|
||||
· [2.1 Emulate the RSP, bypass the RDP](#21-the-key-architectural-insight-emulate-the-rsp-bypass-the-rdp)
|
||||
· [2.2 How the RSP is invoked](#22-how-the-rsp-is-invoked)
|
||||
· [2.3 Build system](#23-build-system)
|
||||
· [2.4 PD-port copy-candidate audit](#24-pd-port-copy-candidate-audit-session-2026-08-22)
|
||||
3. [GoldenEye decomp: what we're porting](#3-goldeneye-decomp-what-were-porting)
|
||||
— [3.1 Entry / main loop](#31-entry--main-loop)
|
||||
· [3.1 Entry / main loop](#31-entry--main-loop)
|
||||
· [3.2 The two libultra trees](#32-the-two-libultra-trees-srclibultra-and-srclibultrare)
|
||||
4. [N64 hardware surfaces that must be shimmed](#4-n64-hardware-surfaces-that-must-be-shimmed)
|
||||
5. [GE-specific graphics differences vs PD (the RSP work)](#5-ge-specific-graphics-differences-vs-pd-the-rsp-work)
|
||||
6. [Audio](#6-audio)
|
||||
7. [Input & saves](#7-input--saves)
|
||||
8. [Recommended plan](#8-recommended-plan) — phases 0–4
|
||||
8. [Recommended plan](#8-recommended-plan); phases 0–4
|
||||
9. [Open questions / risks](#9-open-questions--risks)
|
||||
10. [References](#10-references)
|
||||
|
||||
@@ -70,7 +70,7 @@ platforms.
|
||||
* **Saves** are **EEPROM-based** (controller EEPROM via `osEeprom*`), not
|
||||
Memory Pak. The PFS/motor code in `joy.c` is only for accessory (Rumble Pak
|
||||
/ Memory Pak) detection and can be stubbed. Phase 4 is therefore a
|
||||
file-backed EEPROM plus no-op PFS/motor shims — simpler than a full Memory
|
||||
file-backed EEPROM plus no-op PFS/motor shims; simpler than a full Memory
|
||||
Pak emulation.
|
||||
|
||||
---
|
||||
@@ -127,7 +127,7 @@ R4300 builds a Gfx display list
|
||||
The PD port **emulates the RSP in software** (`fast3d/gfx_pc.cpp`) and
|
||||
**bypasses the RDP entirely**: the software RSP translates GBI commands
|
||||
directly into OpenGL calls. The R4300 game code is run natively and is
|
||||
unaware of the difference — it just builds display lists and "starts the
|
||||
unaware of the difference; it just builds display lists and "starts the
|
||||
RSP" as usual.
|
||||
|
||||
The frame flow (from `port/src/pdsched.c` + `port/src/video.c`):
|
||||
@@ -162,7 +162,7 @@ The PC build is **CMake** (the N64 build stays Make + IDO). Dependencies:
|
||||
* `src/game/*.c` (all of it)
|
||||
* a curated list of `src/lib/*.c` (the engine helpers that are
|
||||
platform-independent: mema, memp, model, music, snd, vi, rdp, etc.)
|
||||
* `src/lib/ultra/audio/*.c` (libaudio — runs fine on the CPU)
|
||||
* `src/lib/ultra/audio/*.c` (libaudio; runs fine on the CPU)
|
||||
* `src/lib/ultra/gu/*.c` (gu matrix helpers)
|
||||
* `port/src/*.c` + `port/src/*.cpp` + `port/fast3d/*.cpp`
|
||||
|
||||
@@ -176,38 +176,38 @@ for this project (see CONTRIBUTING.md): same Rare "Indy"/Bond engine family, and
|
||||
port layer solves the same problem classes we are currently hitting. Audited
|
||||
against our remaining work items:
|
||||
|
||||
**Direct copy candidates (Phase 3/4 — our stubs were scaffolded to be replaced
|
||||
**Direct copy candidates (Phase 3/4; our stubs were scaffolded to be replaced
|
||||
by these):**
|
||||
|
||||
| PD file | Lines | Replaces our | Notes |
|
||||
|---|---|---|---|
|
||||
| `port/src/mixer.c` | 722 | 31-line stub | libaudio→SDL final mixer; same RareAL family. Adapt to GE's `audi.c` wiring (sample rate/buffering) |
|
||||
| `port/src/input.c` | 1551 | 48-line stub | SDL_GameController backend: hotplug, rumble, keyboard fallback. Remap the button table to GE's scheme (C-buttons/Z-trig differ from PD) |
|
||||
| `port/src/fs.c` | 294 | 81 lines | File-backed save dir (`--savedir`, `$S` path expansion) — foundation for Phase 4 EEPROM/PFS file backing (ours are no-op stubs today) |
|
||||
| `port/src/fs.c` | 294 | 81 lines | File-backed save dir (`--savedir`, `$S` path expansion); foundation for Phase 4 EEPROM/PFS file backing (ours are no-op stubs today) |
|
||||
| `port/src/audio.c` | 75 | 70 lines | Near-identical; diff when Phase 3 starts |
|
||||
|
||||
**Reference implementations (Phase 2 — the D32/D37/D43 class).** PD's port
|
||||
**Reference implementations (Phase 2; the D32/D37/D43 class).** PD's port
|
||||
layer has a `port/src/preprocess/` module (~4,125 lines): a per-ROM-segment
|
||||
`preprocessfunc` table in their `romdata.c` that converts N64-layout asset data
|
||||
to PC-native layout *at load time* — a systematic solution to the problem class
|
||||
to PC-native layout *at load time*; a systematic solution to the problem class
|
||||
we have been fixing ad-hoc per asset type.
|
||||
- `filemodel.c` (1,114) — the direct **D43** analogue: same `PROMOTE` idiom,
|
||||
- `filemodel.c` (1,114); the direct **D43** analogue: same `PROMOTE` idiom,
|
||||
**same vma 0x5000000**. NOT a drop-in copy (GE's `ModelRoData` union + opcode
|
||||
set differ — PD has stargunfire/headspot/gundl node types), but the node-walk
|
||||
set differ; PD has stargunfire/headspot/gundl node types), but the node-walk
|
||||
order, placement/alignment choices, and record handling are Rare-validated
|
||||
against near-identical data: adapt rather than design from scratch.
|
||||
- `filebg.c` (524) — BG tables (an expected D43 follow-on fault).
|
||||
- `segaudio.c` (362) — audio bank-tree conversion; cross-check for our D37
|
||||
- `filebg.c` (524); BG tables (an expected D43 follow-on fault).
|
||||
- `segaudio.c` (362); audio bank-tree conversion; cross-check for our D37
|
||||
`romdataFixupAudioBank`.
|
||||
- `filelang.c`, `filetiles.c`, `filepads.c`, `filesetup.c`, `gbi.c`,
|
||||
`segfonts.c` — the remaining asset types we will hit.
|
||||
`segfonts.c`; the remaining asset types we will hit.
|
||||
|
||||
**Not copyable:** GE-specific `ModelRoData` record map; fast3d CC/RM
|
||||
correctness (GE's custom GBI modes vs `gmain.s` do not exist in PD); PD extras
|
||||
(`config.c`, `optionsmenu.c`, `mpsetups.c`, `mod.c`) — options menu, MP setup,
|
||||
(`config.c`, `optionsmenu.c`, `mpsetups.c`, `mod.c`); options menu, MP setup,
|
||||
MOD player; not part of 1:1 fidelity.
|
||||
|
||||
**Caveats:** copy **port-layer files only** — their decomp was modified for PC
|
||||
**Caveats:** copy **port-layer files only**; their decomp was modified for PC
|
||||
(e.g. `types.h` keeps N64 offset comments while using real pointers); our
|
||||
non-negotiables are unchanged. Same family ≠ identical format: validate every
|
||||
copied conversion per-field against GE headers + ROM ground truth (the standing
|
||||
@@ -221,19 +221,19 @@ D32 procedure).
|
||||
US/EU/JP ROMs. Game code lives in `src/game/` (~242 files) plus engine
|
||||
files in `src/`.
|
||||
* **Engine layout** (same family as PD):
|
||||
* `src/sched.c` — RCP scheduler (`osCreateScheduler`, `__scExec`,
|
||||
* `src/sched.c`; RCP scheduler (`osCreateScheduler`, `__scExec`,
|
||||
`__scYield`). Structurally near-identical to PD's `src/lib/sched.c`.
|
||||
* `src/game/rsp.c` — builds the Gfx display list, wraps it in an `OSScTask`,
|
||||
* `src/game/rsp.c`; builds the Gfx display list, wraps it in an `OSScTask`,
|
||||
and starts it via the scheduler (`rspGfxTaskStart`).
|
||||
* `src/fr.c` — frame/VI management, video modes (`osViSetMode`).
|
||||
* `src/audi.c`, `src/snd.c`, `src/music.c` — libaudio-based sound + music.
|
||||
* `src/joy.c` — controllers, **EEPROM** save handling (via `joyGamePak*`
|
||||
* `src/fr.c`; frame/VI management, video modes (`osViSetMode`).
|
||||
* `src/audi.c`, `src/snd.c`, `src/music.c`; libaudio-based sound + music.
|
||||
* `src/joy.c`; controllers, **EEPROM** save handling (via `joyGamePak*`
|
||||
-> `osEeprom*`), plus PFS/motor code for accessory (Rumble Pak / Memory
|
||||
Pak) detection only.
|
||||
* `src/init.c` — `init()` -> `mainproc()` -> `bossEntry()` (game entry).
|
||||
* `src/init.c`; `init()` -> `mainproc()` -> `bossEntry()` (game entry).
|
||||
**Compiled for the PC** (provides `mainproc()`); its N64-only `init()` is
|
||||
stubbed (see A3).
|
||||
* **Custom RSP microcode:** `rsp/graphics/gmain.s` (1545 lines) — a modified
|
||||
* **Custom RSP microcode:** `rsp/graphics/gmain.s` (1545 lines); a modified
|
||||
fast3d. This is the RSP-side code that consumes the display list. For the PC
|
||||
port we do **not** run this; we replace it with the software RSP. But it is
|
||||
the authoritative reference for which GBI commands GE actually emits.
|
||||
@@ -265,23 +265,23 @@ overlap.
|
||||
|
||||
What the PC build must do with each:
|
||||
|
||||
* **`src/libultra/audio/*.c`** — standard libaudio (AL). Runs on the CPU;
|
||||
* **`src/libultra/audio/*.c`**; standard libaudio (AL). Runs on the CPU;
|
||||
**compile** (the game's `audi.c`/`snd.c`/`music.c` depend on it).
|
||||
* **`src/libultrare/audio/*.c`** (`drvrNew.c`, `env.c`, `reverb.c`) — Rare's
|
||||
* **`src/libultrare/audio/*.c`** (`drvrNew.c`, `env.c`, `reverb.c`); Rare's
|
||||
audio "New" driver. `synthesizer.c` calls `alSaveNew`/`alAuxBusNew`/
|
||||
`alMainBusNew`/`alLoadNew`/`alResampleNew`/`alEnvmixerNew`/`alEnvmixerParam`/
|
||||
`alFxParam`, all defined here. Runs on the CPU; **compile**.
|
||||
* **`src/libultra/gu/*.c`** — matrix helpers (`guMtxF`, `guOrtho`, ...).
|
||||
* **`src/libultra/gu/*.c`**; matrix helpers (`guMtxF`, `guOrtho`, ...).
|
||||
**Compile**.
|
||||
* **`src/libultrare/io/vitbl.c`** — defines `osViModeTable` (a data table),
|
||||
* **`src/libultrare/io/vitbl.c`**; defines `osViModeTable` (a data table),
|
||||
referenced ~15× by `fr.c`. **Compile** (it's data, not a driver). This is the
|
||||
*only* `io/` file we compile.
|
||||
* **All other `src/libultra/io/*.c` and `src/libultrare/io/*.c`** — hardware
|
||||
* **All other `src/libultra/io/*.c` and `src/libultrare/io/*.c`**; hardware
|
||||
drivers (PI, SI, SP, DP, VI, controller, PFS, motor, EEPROM, ...). **Exclude
|
||||
and shim** in `port/src/libultra.c`. Notably `pfsinit.c`/`pfsisplug.c`
|
||||
(`osPfsInit`/`osPfsIsPlug`) and `motor.c` (`osMotor*`) are called by
|
||||
`joy.c` only for accessory detection, so they are shimmed as no-ops (see §7).
|
||||
* **`src/libultra/os/*.c` + `src/libultrare/os/*.c`** — OS core (threads,
|
||||
* **`src/libultra/os/*.c` + `src/libultrare/os/*.c`**; OS core (threads,
|
||||
message queues, timers, cache, TLB). **Exclude and shim** in
|
||||
`port/src/libultra.c` (+ `n64stubs.c` for the boot/TLB/FPU symbols).
|
||||
|
||||
@@ -296,7 +296,7 @@ What the PC build must do with each:
|
||||
|
||||
| Subsystem | GE API used | Port strategy (from PD) |
|
||||
|-----------|-------------|--------------------------|
|
||||
| RSP (coproc 0) | `osSpTaskLoad/StartGo/Yield`, display lists | Software RSP (`fast3d`) — **main work** |
|
||||
| RSP (coproc 0) | `osSpTaskLoad/StartGo/Yield`, display lists | Software RSP (`fast3d`); **main work** |
|
||||
| RDP (coproc 1) | `osDpSetStatus`, `osDpSetNextBuffer`, render modes | Bypassed; OpenGL backend |
|
||||
| VI (video) | `osViSetMode`, `osViVSyncCallback`, `osViWaitVSync` | SDL2 window + GL context + frame pacing |
|
||||
| AI (audio) | `osAiSetFrequency/SetNextBuffer/GetLength` | SDL audio device + queue |
|
||||
@@ -312,32 +312,32 @@ What the PC build must do with each:
|
||||
GE's `include/gbi_extension.h` defines the custom GBI surface. Compared to the
|
||||
PD port's `fast3d`, the deltas are:
|
||||
|
||||
1. **`G_TRI4`** — draws up to 4 triangles in one command using 4-bit vertex
|
||||
1. **`G_TRI4`**; draws up to 4 triangles in one command using 4-bit vertex
|
||||
indices (0–15). A memory-saving optimization (Rare packed 4 tris into the
|
||||
slot normally used for `G_TRI2`).
|
||||
* **Status: already supported** by the PD `fast3d` (`gfx_sp_tri4`, and the
|
||||
PD game itself uses it). ✅
|
||||
2. **`G_SETTEX`** (`0xc0`) — "use texture from bank": selects a texture by
|
||||
2. **`G_SETTEX`** (`0xc0`); "use texture from bank": selects a texture by
|
||||
bank/tile with detail/mipmap type, min-level, detail-id and texture-id.
|
||||
Emitted only by `gsSPUseTexture` (`include/gbi_extension.h:193`).
|
||||
* **Status: appears UNUSED.** `gsSPUseTexture` is defined but never called
|
||||
anywhere in the game code or the RSP ucode (`rsp/graphics/gmain.s`), and
|
||||
`G_SETTEX` appears nowhere outside its `#define`. The game uses the
|
||||
standard texture commands (`gSPTexture`, `gSPTextureL`,
|
||||
`gSPTextureRectangle`, `gSPTextureRectangleFlip`) — all already handled
|
||||
`gSPTextureRectangle`, `gSPTextureRectangleFlip`); all already handled
|
||||
by the PD `fast3d`. **If this holds (verify the decomp is complete),
|
||||
Phase 2 shrinks to verifying the custom CC/RM modes and the PD fast3d
|
||||
may work largely as-is.** Keep a `G_SETTEX` decode path as a safety net,
|
||||
but it is no longer the headline task.
|
||||
3. **Custom color-combiner modes** — `G_CC_MODULATEIFADE`, `G_CC_FADE`,
|
||||
3. **Custom color-combiner modes**; `G_CC_MODULATEIFADE`, `G_CC_FADE`,
|
||||
`G_CC_DECALFADE`, `G_CC_BLENDRGBFADEA`, etc. (fade/blend variants).
|
||||
* **Status: handled generically** by the fast3d color-combiner -> GLSL
|
||||
shader compiler (`gfx_cc.cpp`), which compiles arbitrary CC equations.
|
||||
Needs verification that each GE mode produces correct GLSL.
|
||||
4. **Custom render mode** — `G_RM_CUSTOM_AA_ZB_XLU_SURF` (AA_ZB_XLU with
|
||||
4. **Custom render mode**; `G_RM_CUSTOM_AA_ZB_XLU_SURF` (AA_ZB_XLU with
|
||||
`Z_UPD`).
|
||||
* **Status: handled** by the render-mode -> GL state mapping; verify.
|
||||
5. **`gDPLoadTLUT06/07`** — custom TLUT load variants.
|
||||
5. **`gDPLoadTLUT06/07`**; custom TLUT load variants.
|
||||
* **Status: minor**, map onto the existing `G_LOADTLUT` path.
|
||||
|
||||
**Conclusion:** the PD `fast3d` is a strong starting point. `G_SETTEX` appears
|
||||
@@ -347,7 +347,7 @@ safety net. Everything else (matrices, lights, fog, tri1/tri4, texture load,
|
||||
sync/flush) is shared.
|
||||
|
||||
> Note: GE's on-hardware RSP ucode is `rsp/graphics/gmain.s`. We do not run it
|
||||
> on PC, but it is the ground truth for the exact command encodings GE emits —
|
||||
> on PC, but it is the ground truth for the exact command encodings GE emits;
|
||||
> use it to validate the software RSP's command decoding.
|
||||
|
||||
---
|
||||
@@ -355,7 +355,7 @@ sync/flush) is shared.
|
||||
## 6. Audio
|
||||
|
||||
* GE uses **libaudio (AL)** on the R4300 (`src/audi.c`, `src/snd.c`,
|
||||
`src/music.c`) — identical architecture to PD. Sound synthesis (ADPCM
|
||||
`src/music.c`); identical architecture to PD. Sound synthesis (ADPCM
|
||||
decode, mixing, FX) runs on the CPU; the RSP audio ucode is a thin
|
||||
pass-through to the AI DMA.
|
||||
* The PD port runs libaudio natively and routes the mixed output through
|
||||
@@ -370,7 +370,7 @@ sync/flush) is shared.
|
||||
|
||||
* **Controllers:** `src/joy.c` uses `osContInit` / `osContStartReadData`.
|
||||
The port maps SDL2 keyboard/mouse/gamepad into the N64 `OSError`/controller
|
||||
structs. PD implements 1964GEPD-style and Xbox-style bindings — a good
|
||||
structs. PD implements 1964GEPD-style and Xbox-style bindings; a good
|
||||
default for GE too (fire=Z, aim=R, etc.).
|
||||
* **Saves:** GE saves are **EEPROM-based**, not Memory Pak. The actual save
|
||||
I/O (`src/game/file2.c`) uses `joyGamePakProbe/LongRead/LongWrite`, which
|
||||
@@ -386,35 +386,35 @@ sync/flush) is shared.
|
||||
|
||||
## 8. Recommended plan
|
||||
|
||||
### Phase 0 — Scaffolding (this change)
|
||||
### Phase 0: Scaffolding (this change)
|
||||
* Add `port/` directory structure + headers + stub sources.
|
||||
* Add a top-level `CMakeLists.txt` (+ `cmake/` modules) for the PC build,
|
||||
parallel to the N64 `Makefile`.
|
||||
* This document + `port/README.md`.
|
||||
|
||||
### Phase 1 — Boot to a window
|
||||
### Phase 1: Boot to a window
|
||||
* Port `system.c`, `fs.c`, `romdata.c`, `config.c`, `main.c`.
|
||||
* Port `video.c` + a minimal `fast3d` (clear color, present).
|
||||
* Goal: load `ge007.u.z64`, open a window, draw a clear color.
|
||||
|
||||
### Phase 1.5 — Boot to first frame (ABI reconciliation)
|
||||
### Phase 1.5: Boot to first frame (ABI reconciliation)
|
||||
* Get mainThread through all of `bossInitMainthreadData()` → `bossEntry()` →
|
||||
`bossMainloop()` and render frame 1. (Done — D34–D58; see §G.)
|
||||
* Recurring mechanism: **ROM-data struct ABI/layout fixes** (the D32 pattern) —
|
||||
`bossMainloop()` and render frame 1. (Done; D34–D58; see §G.)
|
||||
* Recurring mechanism: **ROM-data struct ABI/layout fixes** (the D32 pattern);
|
||||
a 32-bit-pointer struct read as a 64-bit-pointer struct misaligns; convert
|
||||
embedded pointer fields to `u32` + cast at use sites (PD ground truth), then
|
||||
verify the load-time rebase yields valid DRAM addresses. See §H for the
|
||||
step-by-step procedure and the standing "non-negotiable #2 ABI exception."
|
||||
* Goal: title screen / first level actually drawn on the GL surface.
|
||||
|
||||
### Phase 2 — RSP / rendering
|
||||
### Phase 2: RSP / rendering
|
||||
* Bring in the PD `fast3d` (gfx_pc / gfx_opengl / gfx_cc / gfx_sdl2).
|
||||
* Verify the custom CC/RM modes against `gmain.s`; add a `G_SETTEX` decode
|
||||
path only if it turns out to be used (see §5 — it appears unused).
|
||||
path only if it turns out to be used (see §5; it appears unused).
|
||||
* Port `pdsched.c` (GE variant) to drive the software RSP.
|
||||
* Goal: render the title screen / first level.
|
||||
|
||||
### Phase 3 — Audio + input
|
||||
### Phase 3: Audio + input
|
||||
* Port `audio.c`, `mixer.c`, `mod.c`; wire libaudio output to SDL.
|
||||
* **Decide the ASP strategy** (see §11 C2): if audio runs the `aspMain`
|
||||
microcode, wire `aspMainTextStart`/`aspMainDataStart` to the real microcode
|
||||
@@ -422,7 +422,7 @@ sync/flush) is shared.
|
||||
* Port `input.c` (keyboard/mouse/gamepad).
|
||||
* Goal: playable with sound.
|
||||
|
||||
### Phase 4 — Saves + polish
|
||||
### Phase 4: Saves + polish
|
||||
* File-backed EEPROM (saves); PFS/motor already stubbed as no-ops.
|
||||
* Widescreen, mouse-look, FPS options, config file, crash handler.
|
||||
* Goal: feature-parity with the original + QoL extras.
|
||||
@@ -431,21 +431,21 @@ sync/flush) is shared.
|
||||
|
||||
## 9. Open questions / risks
|
||||
|
||||
1. **`G_SETTEX` (low priority)** — appears unused (`gsSPUseTexture` is never
|
||||
1. **`G_SETTEX` (low priority)**; appears unused (`gsSPUseTexture` is never
|
||||
called). If a future decomp revision or a missed call site shows it is used,
|
||||
reverse the texture-bank selection (bank -> image, tile, detail/mipmap type)
|
||||
from `gmain.s` + `tex.c` / `initmttex.c`. Not currently the main unknown.
|
||||
2. **Custom CC correctness** — the GLSL compiler must handle every fade/blend
|
||||
2. **Custom CC correctness**; the GLSL compiler must handle every fade/blend
|
||||
mode GE uses; validate per-mode against the original. This is now the main
|
||||
rendering unknown.
|
||||
3. **Scheduler fidelity** — GE's `sched.c` has speed-graph / profiling hooks
|
||||
3. **Scheduler fidelity**; GE's `sched.c` has speed-graph / profiling hooks
|
||||
(`speedgraphMarkerHandler`) and a slightly different task model than PD;
|
||||
the port scheduler must reproduce the gfx/audio interleaving and VSync
|
||||
pacing.
|
||||
4. **Decomp completeness** — the decomp is WIP; some functions may still be
|
||||
4. **Decomp completeness**; the decomp is WIP; some functions may still be
|
||||
stubs/`unk_`. The PC port inherits whatever state the decomp is in. Track
|
||||
the upstream `n64decomp/007` and rebase.
|
||||
5. **Endianness / alignment** — GE, like PD, is big-endian N64 code with
|
||||
5. **Endianness / alignment**; GE, like PD, is big-endian N64 code with
|
||||
unaligned accesses; the PD port handles this with careful casts and
|
||||
`-fno-strict-aliasing`. Reuse those flags.
|
||||
|
||||
|
||||
+186
-186
File diff suppressed because it is too large.
Load diff
Vendored
+22
-24
@@ -1,16 +1,17 @@
|
||||
# GoldenEye 007 PC Port — @VERSION@ (pre-release)
|
||||
# GoldenEye 007 PC Port - @VERSION@
|
||||
|
||||
A native PC port of the original Nintendo 64 *GoldenEye 007*, compiled from the
|
||||
[GoldenEye 007 decompilation](https://github.com/n64decomp/007).
|
||||
|
||||
> **Pre-release — playable, with known rough edges.**
|
||||
> **Playable, with known rough edges.**
|
||||
> The full single-player campaign runs at a steady 60 fps with no known
|
||||
> crashes, and in-level music + sound effects play throughout. Known issues:
|
||||
> cutscenes glitch frequently (the Dam level-end in particular), a few music
|
||||
> tracks have wrong-sounding instruments, some front-end 3D models are broken
|
||||
> (the spinning Nintendo logo, the MISSION COMPLETE / mode-select models), and
|
||||
> assorted cosmetic rendering defects remain. This cut is for playtesting —
|
||||
> report what you find.
|
||||
> cutscenes still glitch, mostly with James Bond (the Dam level-end in
|
||||
> particular), a few music tracks have wrong-sounding instruments, some
|
||||
> front-end 3D models are broken (the spinning Nintendo logo, the MISSION
|
||||
> COMPLETE / mode-select models), and assorted cosmetic rendering defects
|
||||
> remain. It's an early public cut: report what you find, feedback is very
|
||||
> welcome.
|
||||
|
||||
Project & source: <https://github.com/jkdansereau/goldeneye-pc-port>
|
||||
|
||||
@@ -30,8 +31,8 @@ NTSC-U (US):
|
||||
| PAL (EU) | `ge007.pal-final.z64` | `167c3c433dec1f1eb921736f7d53fac8cb45ee31` |
|
||||
| NTSC-J (JP) | `ge007.jpn-final.z64` | `2a5dade32f7fad6c73c659d2026994632c1b3174` |
|
||||
|
||||
US is the best-tested. The asset step below detects the region from the ROM's
|
||||
SHA-1, so any of the three works as-is.
|
||||
This release supports the **NTSC-U (US)** ROM. PAL and JP ROMs are recognised
|
||||
by their SHA-1 but not yet supported; they are on the roadmap.
|
||||
|
||||
@DEPS@
|
||||
## 2. Set up (one time)
|
||||
@@ -39,26 +40,22 @@ SHA-1, so any of the three works as-is.
|
||||
1. Unzip this folder anywhere.
|
||||
2. Make a `data` folder next to `@EXE@`.
|
||||
3. Copy your ROM into it, named exactly: `data/ge007.ntsc-final.z64`
|
||||
4. Prepare the ROM-derived data (needs Python 3.8+ on your PATH):
|
||||
|
||||
```
|
||||
python3 prepare-assets/prepare-assets.py
|
||||
```
|
||||
|
||||
(On Windows, `python prepare-assets\prepare-assets.py`.)
|
||||
|
||||
This reads your ROM and writes `data/pcmodels-ntsc-final/` and
|
||||
`data/pccg-ntsc-final/` next to the executable. It uses only the Python
|
||||
standard library — no compiler or N64 toolchain — and takes a few seconds.
|
||||
Run it again only if you replace the ROM.
|
||||
4. That's all the setup. On first launch the game detects the ROM and
|
||||
generates the derived data (`data/pcmodels-ntsc-final/` and
|
||||
`data/pccg-ntsc-final/`) automatically; that first run takes a few extra
|
||||
seconds. No Python, no compiler, no N64 toolchain: nothing to install.
|
||||
If you replace the ROM later, delete those two folders and the game will
|
||||
regenerate them on the next launch.
|
||||
|
||||
## 3. Run
|
||||
|
||||
Run `@EXE@` **from this folder**. Configuration is written to `ge007.ini` on
|
||||
first run.
|
||||
|
||||
> If the game exits immediately reporting missing data, re-run step 2.4 above
|
||||
> and check it printed `ALL CHECKS PASSED` for both passes.
|
||||
> If the game exits immediately reporting missing data, run the generator
|
||||
> manually from this folder (`prepare-assets/ge007-convert`; on Windows,
|
||||
> `prepare-assets\ge007-convert.exe`). On success it prints one line per pass
|
||||
> and ends with `prepare-assets: done.`
|
||||
|
||||
## 4. Controls (defaults)
|
||||
|
||||
@@ -74,7 +71,8 @@ first run.
|
||||
| Start | `Enter` / `Tab` | Start |
|
||||
| Options overlay | `F10` | Select (D-pad/stick + A/B navigate, Start closes) |
|
||||
|
||||
Mouse sensitivity and Y-inversion are in the `[Input]` section of `ge007.ini`.
|
||||
Mouse sensitivity (master and aim-mode), Y-inversion and the other input
|
||||
settings are in the `[Input]` section of `ge007.ini`, or in the F10 overlay.
|
||||
|
||||
@DECK@
|
||||
## 5. Legal
|
||||
|
||||
Reference in new issue
Block a user