Commit Graph
100 Commits
Author SHA1 Message Date
James Dansereau e7f4540b15 release: v0.4.0 screenshot set — 12 intro-attract stills (3072x1728 widescreen) downscaled to 1600px JPG, replacing the v0.2.0 playtest shots per level; Control/Streets/Jungle added; 6 superseded duplicates dropped; manifest + contact sheet refreshed; README gains a press-kit hero row (Streets/Dam/Runway/Aztec); preview gif re-cut at 400px/15fps/128c (smoother, 15 MB vs 23.6) 2026-09-28 10:06:52 -04:00
James Dansereau efef63fd7f release: v0.4.0 preview media — 24 s montage from live v0.4.0 play sessions (Runway tank opener, Dam, Caverns, Aztec, Bunker 2, Surface 2); release-notes image ref re-pointed to the v0.4.0 tag; README/index captions refreshed 2026-09-28 09:52:52 -04:00
James Dansereau 4f66db12d6 v0.4.0 wrap-up: D407 RESOLVED — tank board-ordering fix, board-animation lockout, menu-accept B gate, in-tank aim routing + Input.TankAimScale; PC Options wheel direction fixed (D407(b)); all 10 TANKDBG probes stripped (src/game zero-diff); D408 logged (SkipIntro skips the failure dossier — Skip intro marked EXPERIMENTAL); release notes + readme stats 2026-09-28 09:28:28 -04:00
James Dansereau 76e9202dfd release: v0.4.0 notes — tank board/exit bullet + PC Options paging follow-up; readme final stats (995 commits, 285 findings D1-D407) 2026-09-28 08:26:09 -04:00
James Dansereau 2b75f3ed8e findings: D407 logged — tank board/exit dead on PC after the D378/D393 use/reload split (port-only fix; live tank drive owed for sign-off) 2026-09-28 08:26:09 -04:00
James Dansereau 460cfd77e0 port: D407 — tank board/exit via the B bit in tank states; PC Options page-edge highlight clamp + mouse-wheel/W-S paging (D407(b)) 2026-09-28 08:26:09 -04:00
James Dansereau a8a9f2932e readme: final project stats (992 commits, 284 findings D1-D406); mark the agentic-development case study as a v0.3.0-era snapshot (through 20 Sep / D321), with the README carrying the final numbers 2026-09-28 02:31:31 -04:00
James Dansereau 9e71e7990b release notes: page indicator wording matches the shipped UI (Page p/N marker + bottom hint) 2026-09-28 02:27:56 -04:00
James Dansereau 73dd0c4ca0 readme and docs site: v0.4.0 release status, release news section, masthead tagline, and accuracy pass
- v0.4.0 status framing (the most complete release to date; the common
  defect classes fixed; a short list of known caveats) and the pre-1.0
  note, on both the README and the Pages home page.
- Dated release news section with links to the GitHub release tags.
- Keyword-reinforced meta descriptions; site masthead tagline.
- Accuracy: options section list per the shipped overlay, Xbox 1.1 (Jinx)
  controller roles (D394), Select opens the overlay, Deck 2x MSAA / 250%
  preset, background stats, footer last-updated stamp.
2026-09-28 02:27:56 -04:00
James Dansereau ebf8e4c05d findings: D406 resolved -- front-options pagination validated on the Steam Deck 2026-09-28 02:26:56 -04:00
James Dansereau a5924517fc port: front-options page hint one row below the last entry (D406d) -- pitch-aligned, not floating at the paper edge 2026-09-28 02:25:51 -04:00
James Dansereau 0c4b60e440 findings: D406c -- page hint on every page (11 rows/page), chevron wording dropped 2026-09-28 02:25:00 -04:00
James Dansereau 4b66494813 port: front-options page hints on every page, clearer wording (D406c)
11 rows per page now (was 13) so the bottom line of the paper is always
free for the page hint -- page 1 of a multi-page section shows
'Down: next page' after all (a full 13-row page had no room and no
hint, reported from the Deck). Hint wording drops the confusing
chevrons: 'Down: next page' / 'Up: previous page'.
2026-09-28 02:24:36 -04:00
James Dansereau 58691e5c5e port: front-options slider bars clear long labels; explicit page indicators (D406b)
Per user reports on the v0.4.0 front screen: the X/Y axis look
sensitivity (controller) labels ran into the fixed 232px slider track.
Bars now start 10px past each row's measured label (rows too long for
any track show the value only); drag hit-test and A-hold mapping use
the same per-row origin. Page 2 of a multi-page section now carries an
explicit dim 'Page p/N' marker right of the title plus a bottom hint
('Down: more rows >' / 'Up: previous page <') wherever the page has
room below; the (p/N) title suffix is retired. GE_FRONTOPTS_WIDTHS
one-shot label-metrics log added (same env-gated diagnostic
convention).
2026-09-28 02:21:22 -04:00
James Dansereau 8e58376d46 port: front-end PC Options pagination for long sections (D406)
INPUT (17 visible rows) outgrew the fixed 440x330 paper: the 18px pitch
was sized before the D356 profile row, so a full page's last row landed
at y=335 (off the bottom of the screen) and rows past the silent 14-row
cap (Crouch mode, Reset to defaults, Bindings...) were unreachable from
the front screen. Sections now page at 13 rows (the largest that fits);
the vertical stepper crosses page boundaries in both directions and the
title carries a (p/N) marker. F10 overlay untouched (it scrolls its own
window). Headless verification (SkipIntro boot + scripted D-pad stepping
+ GE_FRONTNAVLOG): page 1 -> page 2 down and back up, all 17 rows
reachable. GE_FRONTOPTIONS_AUTO test hook added (diagnostic-only, same
convention as GE_FRONTOPTIONS_SECTION). Findings D406 + index; release
notes: options section list corrected to the shipped Input/Gameplay/HUD/
Graphics/Audio/Display and the D406 line added.
2026-09-28 02:09:03 -04:00
James Dansereau 82476f3dd2 readme: v0.4.0 voice pass over a web-1.0 structure
Plain declarative prose throughout the overview and section intros - no
product-page register, no first-person winks. Structure carries the period
feel: top anchor-nav line (middot separators), a dated news line for the
release, --- section rules, and a last-updated footer stamp.
2026-09-28 01:34:43 -04:00
James Dansereau 1b290b2012 findings: D405 table row 4-cell -> 3-cell (pointer merged into title cell) so the index generator buckets it; D405 now indexes as CLOSED 2026-09-28 01:32:13 -04:00
James Dansereau 64913054ce release: v0.4.0 site/README consistency + Web 1.0 re-skin
- Docs site: drop jekyll-theme-cayman for a hand-rolled _layouts/default.html
  (masthead band + middot text nav + footer with last-updated stamp and legal
  line; head re-plumbed with {% seo %}, viewport, favicon); head-custom.html
  fully rewritten to the chosen design tokens - charcoal/off-white/amber,
  Libre Baskerville headings over system sans, square corners, 1px borders,
  flat (no gradients/shadows), mermaid wrapper re-skinned.
- docs/index.md: v0.4.0 status (native widescreen, aim system, rebinding,
  crosshair, rumble, rebuilt overlay); Honest status replaced by the v0.4.0
  release-notes known issues; body anchor-nav line; legal footer moved to
  layout.
- security-and-fidelity-status.md: front matter so {% seo %} titles it.
- README.md: v0.4.0 truth pass (status, Working/Known issues, Deck preset
  2x MSAA / 250% per code, background stats 981 commits / 283 findings,
  comparison table, GEPD-default controls paragraph, earlier builds) plus
  markdown-native motifs matching the site: top anchor-nav line, --- section
  rules, last-updated footer stamp, license badge in the amber accent.
- release-notes: SFTP sideload mention (leftover from the Deck session).
2026-09-28 01:32:13 -04:00
James Dansereau ad20cf210a release: v0.4.0 notes as source of truth - feature-organized, every claim code-verified (labels, options, defaults, D248 root cause) 2026-09-28 01:17:59 -04:00
James Dansereau 889f2e5d5e release: notes logic pass - rainbow fix moved to Graphics; Known issues = actual residuals only (D335b F10 overlay stretch replaces the widescreen heads-up) 2026-09-28 01:15:27 -04:00
James Dansereau b1ee5a3655 release: notes completeness pass - 60fps fix (D248), D202 mixer, D393 pad defaults, D314/D290/D342 polish 2026-09-28 01:14:35 -04:00
James Dansereau 2dd2d9dd35 release: comprehensive v0.4.0 notes - full v0.3.0..v0.4.0 arc (native widescreen, aim rework D332-D338/D404, HUD scale, rainbow fix, stability wave) 2026-09-28 01:12:56 -04:00
James Dansereau f84b8023dd release: v0.4.0 release notes (what's-new since v0.3.0 + true residual known-issues set) 2026-09-28 01:10:23 -04:00
James Dansereau 2621163f03 D405: record post-merge verification (sweep 21/21, MSAA=16 boot check, link ritual) 2026-09-28 01:09:17 -04:00
James Dansereau ed58593215 graphics backlog: track issue #105 (Dam water-reflection cyan fill residual) 2026-09-28 01:07:01 -04:00
James Dansereau 50e3426aca fast3d: clamp MSAA to GL_MAX_SAMPLES and bind the default framebuffer as GL name 0 (PR #106, italoarruda; security-reviewed 2026-09-28, D405)
Port-layer only: resolve_msaa_color_buffer clamps msaa_level to the driver's
GL_MAX_SAMPLES (pre-fix: unallocated multisample renderbuffers -> black
screen when MSAA is set beyond driver support); the resolve/copy paths now
bind current_framebuffer ? framebuffers[i].fbo : 0 (the default framebuffer
is GL name 0, not framebuffers[0]). Affects both Windows (opengl32) and
Linux builds. Code file from the PR head (fc092d99); docs in house style,
label rebased D323 -> D405 (collision with our G_TL_LOD finding).
2026-09-28 01:03:00 -04:00
James Dansereau 4b7cae63f9 v0.4.0 final review: D404 pad-centred aim (N64-parity quadratic curve) + full campaign-playtest sign-off bookkeeping
- input.c: padDirectCompute() — pad twin of the mouse Centred aim; the natural
  pitch path routes AIMMODE_CENTRED through it, AIMMODE_N64 keeps classic
  stick-deflection behavior. Parity pass uses bondview2's verbatim N64
  quadratic curve (sign(v)*clamp(defl/70,+-1)^2 * fov/60 * 3.5 deg/poll), so
  full-stick Centred matches N64's top rate exactly.
- optionsoverlay: aim rows device-neutral (Aim style / Aim range).
- findings.md: D404 RESOLVED (user-validated on Steam Deck, both passes);
  21 sign-off status updates from the user's full campaign playtest
  (D175/D224/D235/D236/D240/D241/D245/D249/D281/D286/D287/D289/D291/D294/
  D303/D306/D307/D308/D311/D320/D322/D75/D387/D395/D396/D399/D400); stale
  options-wave rows closed (D346-D391 batch); D383/D394 kept PARTIAL with
  v0.5.0 scopes; D281 root cause -> v0.5.0; D258 -> NTSC-only for v0.4.0.
- README: Known issues = the true residual set (D318, D75 Rareware logo,
  AllUnlocked EXPERIMENTAL, NTSC-only); stale v0.3.0 clause removed.
- AGENTS.md: native-reexec guard status re-confirmed for 2026-09-28.
2026-09-28 01:02:09 -04:00
James Dansereau 39d1fd381e input: implement Wave A controller options + Turok-verbatim labels (v0.5.0)
Port-layer only (port/src/input.c, optionsoverlay.c); zero src/game edits.
All new knobs off/neutral at default = byte-identical at defaults.

New controller input options (CONTROLLER-INPUT-PLAN Wave A):
- Input.PadLookSensX/Y: per-axis right-stick look sensitivity (100 = native)
- Input.PadSouthpaw: swap fire<->grenade triggers (applied after edge capture,
  so edge-detection stays consistent)
- Input.PadDeadzoneL/R: per-stick deadzone; legacy Input.PadDeadzone key kept
  registered (no row) + one-time migration in inputInit() seeds any unset L/R
  from it (C-init sentinel PAD_DZ_UNSET) before the first configSave
- Input.PadLookSmooth: 0-10 per-pad EMA low-pass on the natural-pitch look
  output (default 0 = off), reset on pad hot-unplug
- Input.MouseYScale: pre-existing registered key finally gets an INPUT row

Verbiage baseline (Turok PC options menu, user-provided verbatim): Mouse
horizontal/vertical sensitivity, X axis/Y axis look sensitivity, Look
smoothing, Southpaw, Vibration (was "Rumble strength"), Deadzone
(left/right stick). GE keeps one flat INPUT section (D356), so the two
Invert-look rows retain their (mouse)/(controller) suffixes.

Display baseline (Turok scales): sensitivity + deadzone rows render 0-100
with 50 = default (existing calibratedDefault path); look smoothing renders
0-10 via a new dispMax "N/M" row formatter (alongside the existing N/100 and
N/255 special cases).

Tested on a real pad (Windows build) - all six options behave as intended.
2026-09-28 00:30:21 -04:00
James Dansereau 83ece6c370 docs: add CONTROLLER-INPUT-PLAN (v0.5.0 controller/input options wave)
Low-hanging-fruit controller/input options ported from the Turok PC port's
menu, scoped as port-layer-only (zero src/ edits): right-stick look X/Y
sensitivity, southpaw trigger swap, per-stick deadzone (with the legacy
single-deadzone migration), look smoothing, and a mouse-vertical-sensitivity
row. All off-by-default (byte-identical at defaults, golden gate preserved).
Documents what the GE port already has, the per-item code shape + insertion
points in input.c, and the Tier B/C items explicitly out of scope (head bob,
bloom/shadows, death-cam, uncapped-FPS -> UNLOCKED-FPS-PLAN, controller
rebind -> PR #109).
2026-09-28 00:00:11 -04:00
James Dansereau d934a93253 docs: D403 resolved — Deck front-end logo/copyright page confirmed fixed
After regenerating the Deck's pcmodels/pccg sidecars from the current
converter (M-197 blob fix + D303) and pushing them, the user re-checked
the front end on the Steam Deck and confirmed the Nintendo/GoldenEye logo
+ copyright/legal page now render correctly. D403 was the stale-sidecar
test artifact all along; no code was ever at fault.
2026-09-28 00:00:11 -04:00
James Dansereau 7f6d745f25 docs: D403 disambiguation performed — regenerate + push Deck sidecars
The Deck bundle's stale 0.3.0-era pcmodels/pccg sidecars were regenerated
from the current Python-source converter (prepare-assets.py + d43/d69/d88,
ALL CHECKS PASSED) on the NTSC ROM and pushed to the Deck (sha256-verified),
preserving the user's ge007.eep + ge007.ini. Awaiting the user's by-eye
front-end recheck (logo/copyright page) to close the loop.
2026-09-27 23:54:08 -04:00
James Dansereau 001690568f docs: log D402/D403/D404 + Steam Deck v0.4.0-pre test results
- D402: first clean Linux build fix (shim include-cycle + _SHIFTL).
- D403 (new): Deck front-end logo/copyright page broken + graphics not
  updated is a test artifact — the bundle was seeded with 0.3.0-era
  sidecars that predate the D75/M-197 blob fix and D303; not a code
  regression. Disambiguation: regenerate the Deck's data/ sidecars.
- D404 (new): 'Aim style: Centred (PC)' is inert on a gamepad; the row's
  doc comment over-promises (applies to pad trigger) but the centred
  path is mouse-only (input.c:1783, D337 device-aware gate).
- Deck test confirmations: D175 gains a low-utilisation (~15-30%)
  frame-pacing/present data point; D395 pad-binding retest satisfied
  (not stuck); D401 rumble + D287 idle/resume-from-sleep confirmed on
  the Deck's Steam Controller / SteamOS.
2026-09-27 23:53:03 -04:00
James Dansereau ed991dd1cb port: D402 — fix the first clean Linux (glibc/SteamOS) build
The release/v0.4.0 branch had never been compiled on Linux; two
port-layer include-resolution spots that MinGW tolerated break under
glibc. Shim-only fixes, zero src/ edits, no rule-2:

- port/shim/PR/ucode.h + port/shim/bondconstants.h: break the
  bondconstants.h -> ultra64.h -> pc_protos.h -> bondtypes.h ->
  bondconstants.h first-include re-entry by deferring pc_protos.h during
  bondconstants.h's own ultra64.h pass (_PORT_DEFER_PC_PROTOS).
- port/shim/PR/gbi.h: define _SHIFTL/_SHIFTR when absent, so video.c's
  gbi.h macros keep their mbi.h definitions on Linux.

Builds + links clean on Ubuntu 24.04 (glibc 2.39 <= SteamOS 2.41).
2026-09-27 23:53:03 -04:00
James Dansereau 9fb381eab1 M7 (v0.4.0, D387): ship AllUnlocked as loudly-documented EXPERIMENTAL/irreversible
Per the user's release decision, keep the toggle (default OFF) but make it
impossible to miss in-game: the row is now labelled 'All unlocked
(EXPERIMENTAL)' and its ON value renders 'ON - UNSAFE' in both the F10
overlay and the front PC Options screen (both read the shared row table).
ON value now bright-highlights like a normal On. Port-only, display-only
(config still stores 0/1); a safe architecture is v0.5.0 work.

Housekeeping: track docs/dev/M7-ALLUNLOCKED-PLAN.md (records the decision);
gitignore the stray repo-root Python/ install; refresh the D387 status.
2026-09-27 23:27:49 -04:00
James Dansereau 471eecd6d3 D401: Rumble Pak -> real gamepad haptics (re-promotes D224/M-87)
Port layer only (zero src/ edits), per docs/dev/RUMBLE-PLAN.md:
- port/src/input.c: inputRumbleSupported/inputRumble -> SDL_GameControllerRumble;
  detection via SDL_GameControllerHasRumble (SDL >= 2.0.18) else
  SDL_JoystickIsHaptic + known-type Windows fallback; zeroed on pad close.
  Single global gRumbleScale (dflt 0.5) registered as Input.RumbleScale.
- port/src/libultra.c: the two M-87 blockers resolved - g_contStatus[i].status
  now sets CONT_CARD_ON for connected rumble-capable pads (so
  joyRumblePakInit arms) and osPfsInit returns PFS_ERR_DEVICE for them (so
  osMotorInit is attempted); osMotorInit/Start/Stop drive the haptics API.
- port/src/optionsoverlay.c: one global 'Rumble strength' ROW_SLIDER
  (Input.RumbleScale, 0.05 detents, %.2f) in the INPUT section +
  kResetDefaults entry. The four per-player Input.PlayerN.RumbleScale keys
  were dropped (user decision 2026-09-28); stale keys in an existing ini
  log four 'unknown key' LOG_NOTE lines and self-clean on next configSave.
- Real-pad haptics confirmed working by the user (2026-09-28).

Build env: build-pc.sh self-heal guard revision - re-exec now writes a
self-contained .ps1 (msys->native argv conversion mangles $-bearing
-Command strings; file write is conversion-free), builds PATH explicitly,
picks TMP from writable candidates (GetTempPath honours the broken
inherited TMP), self-logs to build-pc/ge007-native-reexec-*.log, and
treats a null LASTEXITCODE as 'did not execute' (PS 5.1 piped native
commands error non-terminating). OPEN: the guard still fails inside
build-pc.sh while the identical standalone .ps1 invocation works - AGENTS.md
documents the workaround. docs: RUMBLE-PLAN.md (new, tracked), findings.md
D401 entry + index rows, QOL-INVENTORY D224 -> DONE (D401),
findings-index.csv regenerated.
2026-09-27 23:23:05 -04:00
James Dansereau a548fc4de6 port: D397 — fix file-select/gun-barrel comb via RDP scanline-range snap in gfx_draw_rectangle
Root cause H2 confirmed: the gun-barrel / file-select vertical gradient is
built from 0.75-native-pixel-tall gSPTextureRectangle row strips (title2.c
(<<2)-1 bottom idiom). On the N64 RDP the scan converter floors the U10.2
edges to whole scanlines, so each strip rasterizes to exactly one scanline;
gfx_draw_rectangle passed the fractional edges straight to the GPU's
continuous rasterizer, aliasing the 0.75px pitch into a periodic 'comb'
(fixed ~3-native-row period; window period = 3*scale — confirmed by a
3-scale 640/1024/1280 GE_PCDUMP test).

Fix (port-layer, surgical): after the sub-pixel offset, floor the top edge to
its scanline and the bottom edge to the last covered scanline (the RDP
scanline range [top_scan, bot_scan+1]) before NDC conversion. No-op for
whole-pixel rects (edges already 4k/4k-1), so only sub-pixel strips change
and normal fills are untouched.

Also: remove the temporary GE_D397SH / D397SHM env-gated shader probes
(gfx_opengl.cpp, gfx_pc.cpp) now that the root cause is settled.

Docs: findings.md D397 -> RESOLVED (+3-scale confirmation + fix record),
findings-index.csv regenerated, porting-notes.md section D15 marked resolved
with the landed fix.

Verified by playtest: gun-barrel + file-select gradient render clean, comb
gone.
2026-09-27 22:42:43 -04:00
James Dansereau 2a60b8a912 port: D397 — D397SHM input-mapping probe; H1 LERP-factor variant ruled out
New env-gated D397SHM probe in gfx_generate_cc dumps which G_CCMUX
inputs a combine feeds as vInput1..N. For the gun-barrow row-strip
shader (id0=0000000010001218): vInput1=PRIMITIVE, vInput2=ENV_ALPHA,
so the front.c LERP renders out = PRIM + (TEXEL-PRIM)*(envA/255).

The PD ground-truth port feeds the identical env_color.a/255 factor for
the same ENV_ALPHA LERP input, so the LERP factor is not a port-side
scaling bug (H1's 1/255-vs-1/32 variant refuted). A uniform factor
cannot produce the *periodic* comb, which points to H2 (row-strip
geometry / 256-tri vertex-ring wrap). Next: Q3 gfx_flush() probe +
Q5 native FBO capture. Findings §D397 + handoff updated.
2026-09-27 22:15:17 -04:00
James Dansereau 65875ad45b port: D397 — retract the ineffective CI->I import block; correct the finding record
Per scratch/d397_fs/HANDOFF-D397.md: the stale-RENDERTILE hypothesis is
REFUTED (D161 already routes CI + G_TT_NONE to the I8 import; the GE_TEXI
logs show palfmt=0 on all 299 row strips), so the D397 block added to
import_texture had no effect (12px frame diff) and is removed.

The finding's true state: data path proven clean (byte-exact I8 uploads
vs the ground-truth PGM); MSAA/mips/noise/quant/cache ruled out.
Leading cause H1 = the file-select custom-CC LERP feeding ENV_ALPHA 0x14
as a 20/255 mix factor (black texels render ~0.92x prim = the measured
27/28/17 census); the N64 RDP 5-bit coefficient scaling (gmain.s / PD
CC engine) is the open root-cause question. H2 = possible separate
row-strip-geometry comb. GE_D397SH probe stays in-tree until the root
cause lands. findings table + tail section + CSV corrected.
2026-09-27 22:05:19 -04:00
James Dansereau 2ba72eb75f docs: v0.4.0 plan/README/backlog/porting-notes refresh for the modern-options wave
- V0.4.0-PLAN: 2026-09-27 refresh (M-wave state, D393-D397 session
  additions, M7 deferral decision).
- README: known-issues + options documentation for the landed
  crosshair/controller/options work.
- GRAPHICS-BACKLOG / porting-notes: D392/D397 and crosshair entries.
- .gitignore: per-landing sweep capture dirs.
2026-09-27 22:04:07 -04:00
James Dansereau a2b2f78dd1 port: D397 — file-select background + gun-barrel comb look: stale RENDERTILE import (fix in tree, by-eye owed)
Root-caused the D397 interlaced/comb symptom on the file-select
background and intro gun-barrel (first display, not round-trip):
titleRenderFolderMenuBackgroundLines loads 299 one-pixel 440-byte I8
rows with gDPLoadTextureBlock(I, 8b) and samples G_TX_RENDERTILE but
never emits gSPSetTile, so the tile's fmt/siz is whatever the previous
screen left (CI/4b spectrum-screen leftover, D116 probe). fast3d ran
the I8 bytes through import_texture_ci4 against a stale/all-zero
16-entry palette -> periodic black rows (GL texture-cache artifact,
not a ground-truth dither — no ROM RLE decode needed).

- gfx_pc.cpp import_texture: route the import through the source's
  fmt/siz when a CI/RGBA tile genuinely disagrees with an I8 8b load
  (mirrors the D229 case); real CI/RGBA textures untouched.
- gfx_opengl.cpp: GE_D397SH env-gated shader-formula probe for the
  file-select gunbarrel combine (label initially written as D398,
  renamed to avoid the PC-Options-label finding collision).
- findings: D397 row -> FIX LANDED (by-eye + PCDUMP verification
  owed); tail section notes the fix. CSV regenerated.

Cross-ref D182(2) (same symptom family), D159/D183 (disproven leads),
D229 (mirror-case precedent).
2026-09-27 22:04:03 -04:00
James Dansereau 545b2c7792 port: v0.4.0 modern controller + options-UI wave (D371-D388, D393-D396)
Input (input.c/h):
- D380/D386: single effective PC layout; ini values ARE the bindings
  (no hidden defaults); versioned migration materialises effective
  GEPD defaults once (inputMigrateBinds, bindsVersion).
- D385: keyboard keys and pad buttons 1..5 share the two bind slots;
  legacy extra ini tokens are migration-only. D386: SDL button-number
  correction in the D385 defaults.
- D383/D384: opt-in inputBindingProbe (restores ini state); the PC
  settings editor must not navigate with live game keys.
- D393/D394: Xbox 1.1 Jinx face map — A use, X reload, Y weapon
  cycle, B owned-gadget cycle (no N64 equivalent, port-side), L3/R3
  crouch, LB aim; retires LB/RB weapon cycling.
- D395: both options UIs refuse pad-initiated keyboard/mouse capture;
  pad B cancels a capture started by keyboard/mouse.

Options UI (optionsoverlay.c/h):
- D388: nested Input -> Bindings / Gameplay -> HUD roots in both
  F10 and front-options; redundant Low-end toggle retired (FPS cap /
  MSAA remain independent, stored values preserved on migration).
- D391: hit bands follow rendered glyph baselines; dead zone +
  out-of-card click rejection.
- D396: F10 pad B backs/closes a page (closes at root), A/X
  accepts/toggles without shifting sliders; left/right still adjust.

All behind #ifdef PORT; N64 input/menu paths untouched. M7 (D387
AllUnlocked save-safety) intentionally NOT in this wave.
2026-09-27 22:04:00 -04:00
James Dansereau 4bd49f739f port: v0.4.0 M2 crosshair wave (D373/D379/D381) — opt-in hide/colour/size/style, default N64-intact
gunDrawSight (gunfire.c, #ifdef PORT) now routes through portCrosshair*
accessors: hide flag, colour presets + custom RGB, 100% default size,
and an opt-in beta crosshair sprite. With all defaults the original
red sprite, 16-unit half-size and N64 combiner are untouched; non-PORT
builds keep the original literals and control flow.

- D373: crosshide/tint plumbing (was rule-2 sign-off PENDING at M2
  authoring; the PORT-guarded pattern in gunDrawSight is the sign-off
  record).
- D379: only recoloured reticles switch to the texture-alpha silhouette
  combine (portCrosshairApplyTintCombine); the original keeps the N64
  G_CC_FADEA commands.
- D381: size/style/colour surface + live config apply
  (videoRequestLiveConfigForKey) in video.c.

Rule-2 framing: port-layer feature behind the gunDrawSight #ifdef PORT;
zero N64-path change.
2026-09-27 22:03:53 -04:00
James Dansereau 368daf1242 port: D392 — train-intro soldier pose: read firing-table fields by name on PC (ABI/layout only)
chrlvUpdateAimendbackShoulders read the leading anim union of
weapon_firing_animation_table through raw (f32*) slots [12/13/16/17].
On PC the union widens four->eight bytes, so those offsets alias the
wrong fields and the intro soldier hunched with the hand through the
torso (D392, vs the 1964 reference).

The #ifdef PORT arm reads the intended limits/arm fractions by name
(config->max_up/max_down, free_arm_frac_up/down); the non-PORT arm is
untouched. No logic or behavior change beyond the pointer-width
misread; D392 finding + Train aim-angle probe confirm, user visually
verified against 1964.
2026-09-27 22:03:48 -04:00
James Dansereau c214fa7815 D398-D400: PC Options label work + findings.md tail-section recovery
- D398: replace D348 procedural slider glyph with ROM-native IMG_DOT
  texture (texSelect + display_image_at_position, Copy/Erase pattern);
  superseded by D400.
- D399: file-select bottom row shifted 15px left as a block (user
  sign-off); selectpos.f[0] behind a new #ifdef PORT in front.c.
- D400: icon removed on user sign-off; PC Options is now a text-only
  label exactly like Copy/Erase (one textMeasure + one textRender,
  game's packed 0xEBD879FF gold). Fixed two measurement bugs:
  textMeasure(textheight, textwidth) args were passed swapped (label
  35px above the bar, hit band transposed) and the bare label measured
  h=0 vs 14 for newline-terminated Copy/Erase (7px low); height now
  measured with kLabelNL. LABEL_GAP 20->28, LABEL_X 343->351.
  PCDUMP frame 195: tops aligned 279.8 vs 279.3, 31px clearance from
  Erase. By-eye check owed.
- docs: findings.md had been truncated to its section table (686
  lines), losing all ## Dxx tail sections D376-D400. Recovered:
  table D376-D400 rows + body/sections D001-D375 from HEAD;
  D376-D387, D396-D399 sections recovered verbatim from pi session
  transcripts; D398 section recovered from the 2026-09-28 session;
  D388-D395 rebuilt as explicit reconstructed stubs from the
  table/CSV one-liners (original detail unrecoverable); D400 section
  written fresh. findings-index.csv regenerated and verified
  byte-identical to the pre-truncation copy.

Build clean (ntsc-final). Verified: PCDUMP frame 195 (no overlaps,
tops aligned), CSV matches pre-truncation backup.
2026-09-27 21:58:48 -04:00
James Dansereau 2e0643c70f v0.4.0 D375: crouch now emits C-down (the engine's real crouch input), not B
bondview2.c reads crouchDown = insightaimmode && (buttons & (D_JPAD|D_CBUTTONS))
(5318/5579): crouch is C-down WHILE IN AIM MODE, never the B button. M3's
IA_CROUCH -> GE_CONT_B (and the CrouchMode=1 latch) was inert, so crouch
never fired in the GEPD layout. Hold + latch now emit GE_CONT_D (0x0004).
N64-faithful side effect: S (IA_BACK, also C-down) crouches while aiming.
User re-test: aim (RMB/Left Shift) + Left Ctrl; hold or F10 Toggle.
2026-09-27 16:47:55 -04:00
James Dansereau fca07bdd9a v0.4.0 M2 (D373): crosshair on/off + colour; D374: GEPD becomes the default key layout
M2 (the wave's only rule-2 item, sign-off recorded via user direction):
#ifdef PORT hook in gunfire.c gunDrawSight -- Video.CrosshairHide skips
the draw, Video.CrosshairColor tints the RGB (7 named tints, 0 = the
N64 white); non-PORT builds keep the original literals. F10 GRAPHICS
rows + kResetDefaults.

D374 (M3 playtest fix, user decision): GEPD is now the DEFAULT key
layout (Input.Layout 0 = GEPD, 1 = N64-era binds; a mouse FPS layout is
the natural default and the N64 never had a keyboard). The preset is
now the true effective default: only EXPLICIT per-key [Input.Bind]
overrides beat it; persisted values equal to the N64 defaults count as
unset. This fixes the playtest bug where a stale persisted
Fire=Left Ctrl masked the GEPD preset and made Ctrl fire+crouch at the
same time. Boot log reports the applied layout. One-off: pre-D374
Layout=1 (ex-GEPD) inis mean N64 now -- flip to 0 (release note).
2026-09-27 16:43:04 -04:00
James Dansereau b95b54ecc7 v0.4.0 M5: low-end performance preset row (D372)
Video.LowEndMode (default off) in F10 VIDEO: ON writes FpsCap 30 +
MSAA x1 (restart row); OFF restores the compiled defaults (60/2) rather
than per-user pre-preset values. The key records the last selected
preset; the effect flows through the two real knobs.
2026-09-27 16:30:32 -04:00
James Dansereau 40ef53e395 v0.4.0 M3: GEPD key-layout preset + crouch/reload bindings (D371)
Input.Layout (0=FPS default, 1=GEPD) + Input.CrouchMode (hold/toggle) rows
in F10 INPUT (Turok-standard functional section; the planned MODERN bucket
is dropped per D356). The GEPD preset acts as the per-key effective
default under [Input.Bind] overrides; new IA_RELOAD/IA_CROUCH actions emit
GE_CONT_B (unbound by default, N64-original). Toggle crouch latches B with
a menu-boundary latch drop. optionsoverlay rowSetCommit hook re-derives
the binds via inputLayoutApply(). inputRebuildBinds no longer warns on
intentionally-empty defaults. Boot + ini round-trip + F10 page verified;
in-game feel-check owed (D371).
2026-09-27 16:29:18 -04:00
James Dansereau c2c6fbdd68 checkpoint: F10 GE-style refresh + distance defaults retune, D360-D370 series (local WIP; D370 pending user acceptance) — pre-wave baseline for the v0.4.0 modern-options wave 2026-09-27 16:18:20 -04:00
James Dansereau d8971fded0 options UI: settle file terminology on the end-user term 'Profile' (D359)
'Game file' (the manual's term) reads, in modern PC usage, as the
program's own files, not the user's save. 'Profile' is the clearest
end-user term for what these files actually are -- a per-player
bundle of progress + per-file settings -- and '(per profile)'
expresses the tag's scope where '(save)' read as a verb.

Strings (both UIs: front options + F10 overlay):
- front top row: 'Save file' / 'File N'  ->  'Profile' / 'N'
- section annotation: '(File N)' / '(no file)'  ->  '(Profile N)' / '(none)'
- per-file row tag: '(game file)'  ->  '(per profile)'
- F10 unavailable value: 'Select game file'  ->  'Select a profile'

Display layer only: identifiers and ini keys (Bond.* rows,
watchSettings*, ini) are untouched. D357 plan section 4 is the
terminology record; new D359 finding + index row; manual
'game file' -> 'profile' sync noted as a TODO (port-owned doc,
not in this repo). Build + headless smoke clean.
2026-09-27 15:03:24 -04:00
James Dansereau 44d2b4353a options UI: anchor all file terminology on the manual's 'game file' (English review)
Full-string audit of the settings UI (front options + F10 overlay):
- front top-row label 'Save file' -> 'Game file' (the instruction
  manual's term)
- per-file row tag '(profile)' -> '(game file)', both UIs
- F10 unavailable value 'Select file' -> 'Select game file'
- kept: 'File N' values, the '(File N)' section annotation and the
  '(no file)' unavailable state (short forms; the annotation's host
  word is the section title, which says the file number)
- 'Bond file' now appears only in identifiers/config keys
  (Bond.* rows, watchSettings* names, ini keys), never user-visible
Docs: D357 plan section 4 is now the terminology record (final string
table); D358 finding notes the (profile) -> (game file) supersession.
Build + headless smoke clean.
2026-09-27 15:00:01 -04:00
James Dansereau 8775ca6435 docs: D358 (D356 level-1 overlap fix) finding + index/CSV 2026-09-27 14:55:54 -04:00
James Dansereau 4147b55865 untrack local build-pc-cmd.bat (machine-specific paths); gitignore it 2026-09-27 14:55:44 -04:00
James Dansereau f8f94cdd87 frontoptions: fix level-1 overlap (save-file row painted under the first content row) + off-by-one item mapping; (save) tag -> (profile); D357 values plan
- The front options screen numbers items 0..s_rowN (0 = the top
  save-file row, k = content row k-1), but the level-1 draw loop painted
  content row k at rowY(k) -- the save row's own line -- and mapped
  s_hl (item-numbered) straight into s_rowIdx (content-numbered): the
  'Save file' row overlapped the first content row, highlights/adjusts
  hit the wrong row, the last content row was dead, and s_rowIdx[s_hl]
  could read one past the built rows. Content rows now draw at rowY(k+1)
  and all s_hl -> s_rowIdx uses take s_hl - 1 (A-press, L/R repeat,
  reset-maintain); hit-test/cursor were already item-numbered and are
  untouched.
- Per-file row tag '(save)' -> '(profile)' (maintainer request), both
  UIs (front options + F10 overlay) plus the stale comments.
- docs/dev/D357-SETTINGS-VALUES-PLAN.md (PROPOSAL): row-by-row audit of
  current defaults/ranges/steps/displays vs the PD port (local checkout)
  and the Turok PC list (maintainer notes); proposals: mouse sensitivity
  as a x multiplier, deadzone as a whole-% key (D333 legacy-alias
  pattern), texture filter '3-Point' -> Bilinear, audio step 128 -> 328
  (whole-%), MSAA +16x, FPS-cap preset grid, FOV degrees; kResetDefaults
  lockstep gate + GE_WSPROBE_RESET re-verification.

Build clean (248 targets), headless menu boot smoke clean; visual
check of the front options screen + F10 owed to the maintainer.
2026-09-27 14:55:41 -04:00
James Dansereau fe57d73924 optionsoverlay/watchsettings/frontoptions: D356 settings regroup — functional sections, save-file scoping, per-section reset-to-defaults (Gate E)
- 5 sections (INPUT/GAMEPLAY/GRAPHICS/AUDIO/VIDEO, all below MAX_PROWS):
  DISPLAY+GRAPHICS merged into GRAPHICS; AUDIO carries the watch music/FX
  sliders out of the Bond-file page; VIDEO keeps the pure video rows;
  __HdrMouse/__HdrPad merged into INPUT; __HdrBond/__BondFile retired for
  the front-only top save-file row (frontoptions.c)
- save-file scoping: per-file sections (GAMEPLAY, AUDIO) annotated
  '(File N)'/'(no file)' via the new Row.saveScoped flag +
  watchSettingsActiveFolder(); per-file rows in mixed sections carry a dim
  '(save)' tag; the D353 optionsRowIsBondChooser special-case is
  generalized (both UIs)
- N64-watch rows Bond.Look / Bond.AimControl commented out of the menu
  surface (D181/D216 style: keys + watch paths stay live)
- per-section 'Reset to defaults' replaces the Turok rows (plan Gate E):
  edge-triggered two-step arm->confirm within 3 s, one commit, disarm on
  timeout / navigate-away / close (optionsResetMaintain/Clear);
  rowResetSection walks the section's declared range: watch rows ->
  BLANKSAVEDATA through the D352 commit path (front direct, stage queue),
  ini rows -> kResetDefaults[] (the port's C initializers); __Resolution
  is a documented exclusion (action-backed)
- GE_WSPROBE_RESET probe: front tick-120 prepare/dispatch/verify, stage
  tick-120 dispatch / tick-121 verify; a direct -level_XX boot starts its
  timer from phase 0 (front prepare is front-only)
- docs: findings.md D356 + index + CSV, WATCH-SETTINGS-PLAN status,
  OPTIONS-MENU-PLAN pointer, plan doc status -> LANDED

Verified headless: GE_WSPROBE_RESET front (all 5 sections failures=0,
__Resolution untouched, file-2 scope isolation OK) and -level_33 (6
commands queued, all sections verified post-drain, saved music/sfx = 0xFF);
GE_WSPROBE / GE_WSPROBE_FRONT regressions clean; 248/248 build + link.
2026-09-27 14:49:08 -04:00
James Dansereau 95f8f5f8b5 docs: D356 settings-regroup plan with tightened reset/save-file contracts (maintainer sign-off) 2026-09-27 14:03:06 -04:00
James Dansereau 2b4c5ba7dc watchsettings.c: resync in-stage BGM (track 1) on Music commit and level entry (D355) 2026-09-27 13:53:36 -04:00
James Dansereau 61263ad303 watchsettings.c: front-end F10 routing + transparent default Bond-file selection, auto-init fallback, headless probes (D354) 2026-09-27 13:48:03 -04:00
James Dansereau 462675cf47 optionsoverlay.c: Turok-style regroup - DISPLAY/GRAPHICS split, BOND FILE absorbs music/FX, designated rows, overflow log, file-scope title annotation (D353) 2026-09-27 13:32:39 -04:00
James Dansereau 8e9bee6ef0 watchsettings.c: D350-bridge robustness - hold-not-drop at stage transitions, chooser spinlock, queue coalescing, warning logs (D352) 2026-09-27 13:32:18 -04:00
James Dansereau 1303c0ebe1 D350: expose watch-backed Bond settings in PC options and F10
Add a game-thread bridge and field-scoped per-file persistence for PC UI edits, with an explicit file chooser; keep watch-only edits session-only. Fix D351 row initializer offsets for units and auto-hide. Document verification and review follow-ups.
2026-09-27 13:20:21 -04:00
James Dansereau 98a24a07f4 Docs: close D343 (NTSC verified; PAL/JP not capturable locally) 2026-09-27 12:30:14 -04:00
James Dansereau 050c3981d6 D348: mini slider glyph beside the file-select PC Options label
No settings icon exists in the game art (mainfolderimages holds only
copy/del/select-arrow/X/check/dot), so a miniature slider control is drawn
instead: three menu-box tracks with offset knobs in the 14px gap after Erase
(10px wide, 2px margins), INK_DIM tracks, knobs matching the label ink
(white / gold while hot). Tracks the dynamic label x (JP-safe), text position
unchanged; hot region extended to include the glyph. PCDUMP pixel-verified.
2026-09-27 12:24:56 -04:00
James Dansereau 7e07d9e018 D347: F10 overlay controller value-adjust + hold-to-repeat
D-pad left/right and stick-X now adjust the selected row's value (A/X/B/Y
kept); 18/4-frame hold-to-repeat added to value adjust and up/down nav,
matching the options screen's D345(e)/(f) cadence. Port-only; user
controller test verified.
2026-09-27 12:18:36 -04:00
James Dansereau 7ff9ddbe14 D345/D346: options-screen pointer + keyboard nav fixes; settings wording pass
D345 (a-g): re-assert window on menu change; cursorToItem skips snap while
the 1:1 pointer is live; W/S emit stick in menus under NaturalPitch;
F10-style discrete row stepping + arrow left/right value adjust replace raw
drift (first pass shipped broken, fixed); screen-placed cursor parks in the
left gutter off the row text.

D346 (+b): labels/values aligned to Nightdive/Turok + PD-port conventions
(title-case On/Off, Frame rate cap, Anti-aliasing/None, Anisotropic
filtering, units in values not labels, deadzone as %, self-explanatory
auto-FOV toggles); VIEW section merged into VIDEO (MAX_PROWS 12->15,
ROW_DY 20->18). Display-only: config keys and stored values untouched.

Port-only; no src/game edits. User playtest verified.
2026-09-27 12:12:32 -04:00
James Dansereau 835035916d D343: PC Options joins the file-select bottom bar; Copy/Erase shift left
Rule-2 layout edit (user sign-off 2026-09-27): Copy 247/225 -> 222/200,
Erase 357/335 -> 304/282 under #ifdef PORT; their click boxes follow.
"PC Options" is drawn by the port hook right after Erase's measured text
end (min x 352), so wider localised labels push it right. The top-right
label is gone.
2026-09-27 11:01:58 -04:00
James Dansereau 13473d5ec6 D343: PC options as a GE front-end screen (MENU_PC_OPTIONS)
Replaces the M2 panel. Built like the Cheat Options screen: open dossier
(tabs + blank CLASSIFIED page), black Zurich ink via frontPrintText, GE's
highlight box, PREVIOUS tab as back, the game's crosshair. Page 0 is a
numbered section list; each section lists the F10 overlay's rows with a
value column (ON in the cheat red) and slider bars.

Game code (Rule 2, user sign-off 2026-09-27): MENU_PC_OPTIONS enum value
and five one-line dispatch cases, all #ifdef PORT. The file-select label
now enters the screen via frontChangeMenu. The M2 button hand-off in
input.c is gone; F10/Select don't open the overlay on this screen.
2026-09-27 10:58:27 -04:00
James Dansereau e4cf012410 D343/D344: record user verification on PC 2026-09-27 10:41:25 -04:00
James Dansereau fd82dda717 D343 M2: GE-styled options panel on file select; D344 docs
The file-select Options label opens a panel drawn in the same hook:
sections as tabs, rows from the F10 overlay's table via an exported row
API, the game's crosshair as pointer (input.c passes the stick, hands the
buttons to the panel). Quit to desktop now goes through videoRequestQuit.
Also repairs two escaped-newline typos in the D343 docs.
2026-09-27 10:38:16 -04:00
James Dansereau 461ea871c2 D344: orderly quit so exit never lands inside the GL driver; GE_QUITFRAME
Quit (quit event, window close, Alt+F4, from either SDL pump) used to
exit(0) immediately while the render thread could be mid-frame in the
driver: the likely trigger of the host's 0x119 bugchecks. Now quits are
requested; the render thread glFinish()es, unbinds the context and parks
at a frame boundary, and the host exits after (max 2 s). GE_QUITFRAME=<n>
gives the harness a clean self-quit; golden_gate.sh uses it.
2026-09-27 10:38:16 -04:00
James Dansereau c07af11fae D343: record user playtest (all but a physical controller confirmed) 2026-09-27 10:07:22 -04:00
James Dansereau 413014b8f6 D343: file-select Options label opens the settings overlay; F10 idle-timer fix
One Rule-2 #ifdef PORT draw hook in constructor_menu05_fileselect (user
sign-off 2026-09-27). The label's hit test and open request live in
optionsoverlay.c; the open is applied on the input thread. While the
overlay is open on file select, g_MenuTimer is held at 0 so the screen no
longer drops to the legal screen after 30 s.
2026-09-27 10:01:27 -04:00
James Dansereau bd8ade5c1e D307: note camera reaction timing is tick-based and faithful 2026-09-27 00:31:57 -04:00
James Dansereau 60f12f2bba D245 follow-up: water base-level crop never ran (coloured dashes)
The crop tested loaded_texture.line_size_bytes, which is the whole
LoadBlock (1400 B), so the water still uploaded 32x43 while UVs were
normalised to 32 rows; the mip rows showed as coloured dashes. Test the
tile line size instead. User-verified on Frigate; golden 3/3.
2026-09-27 00:31:24 -04:00
James Dansereau 4ba1454ba8 D342: file-select folders vanished after backing out of a file
The PC wallet model (0x1664C B, 0x17000 reservation) loads at the start of
ptr_logo_and_walletbond_DL, but the file-select scratch DL and the
briefing text still used the N64 offset +0xA000 -- inside the model.
After main menu -> back the model is not reloaded, so the overwritten
folder bodies/photos disappeared. Both now use +0x17000 (same 0x6e000
budget). User-verified; golden gate 3/3. D341 also user-verified.
2026-09-27 00:16:18 -04:00
James Dansereau 5c643e3acb D341: intro gun-barrel blood drip drew static garbage
Two fast3d defects. (1) The 1-cycle blood texture rectangle sampled a
stale tile-1 CI8 declaration: the title leaves G_TL_LOD set and the D236
detail-base rule redirected texunit 0 to tile 1. LOD tile selection is
2-cycle-only on the RDP, so texrects outside 2-cycle now sample their own
tile. (2) The drip image is regenerated in place in the dyn pool (reached
via the KSEG0 mirror); the address-only cache key froze it on its first
image. Dyn-pool textures now key on a content hash. Headless-verified,
golden 3/3. A/B: GE_DYNTEXHASH_OFF.
2026-09-26 19:20:06 -04:00
James Dansereau f242992360 D245: water tiled at the wrong size + s16 sky/water vertices; D242 closed
The IsWater 32x32 CI8 image (drawn through an RGBA16 tile, D229) was
imported with its mip chain as 32x43 and normalised as 16 wide, so the
pattern ran at 2x and wrapped every 43 rows instead of the N64's 32:
fold steps made it jump. Import the base level only and use CI8
geometry in the tri path. Sky/water fans now go through a port-only
G_FLOATVTX_EXT (float clip positions + S/T) instead of s16 Vtx, removing
the tc shift and wScale quantisation jitter. User-verified vs 1964;
golden 3/3; Win + Linux build. A/B: GE_D245_OLDVTX / GE_D245_OLDTEX.
2026-09-26 18:56:52 -04:00
James Dansereau d5f41d6a37 D242: headless death auto-advances without input; KIA screen needs a menu-launch check 2026-09-26 18:22:39 -04:00
James Dansereau d061ca3d12 D303: model converter copied 1/4 of each star muzzle flash's vertices
The op-22 DisplayListPrimaryRecord count is the number of star-flash
arms; dorottex (and PD's modelRenderNodeStarGunfire) read count*4
vertices. d43_emit/d43_convert sized the array as count vertices, so
3/4 of every muzzle star came from neighbouring sidecar bytes and drew
as long spikes (M16 "shooting up"). Size it 16*4*count. Emitter
round-trip checks all pass; M16 renders a clean star headless.

Also TEMP GE_STARTWEAPON (bondview_r.c) for weapon repros. Re-run
tools_pc/d43_emit.py to regenerate data/pcmodels-*.
2026-09-26 18:15:17 -04:00
James Dansereau 00b0006971 D307: security cameras read the mount pad as their look-at pad
CCTVRecord's own s32 `pad` (the look-at pad) shadows the inherited
ObjectRecord `pad` (mount pad) under IDO. The PC struct renamed it
`lookpad` to satisfy GCC, which silently re-pointed setupCctv's reads at
the mount pad, so every camera's look vector was its lens offset and the
lens faced the wall. Read `lookpad` on PC (#ifdef PORT, A1 class);
matches PD's setupCreateCctv (lookatpadnum). User-verified vs 1964,
golden gate 3/3. Porting-notes gains the duplicate-member rename trap.
2026-09-26 18:00:40 -04:00
James Dansereau 40b6994504 Findings: 1964 comparisons — D174/D308 faithful; D307/D303/D245 confirmed port bugs; D242 N64 reference 2026-09-26 17:46:57 -04:00
James Dansereau 116a9db798 Findings: close D183 D298 D202 D315; D220 merged into D303; D242/D303 to 1964 list 2026-09-26 17:39:29 -04:00
James Dansereau 035d54dd66 Findings bookkeeping: user status calls + stale-row cleanup (M-201)
User-confirmed fixed/closed: D289 D285 D160 D156 D152 D235; approved
closes D286 D296 D85, D323 parked as an enhancement; D218 shipped as
DrawDistance. Shipped QoL rows D180-D216 and D333-D338 marked fixed;
D318/D320/D321 fixed via D329; D236 sub-passes D265-D280 closed.
D186/D339/D202/D207/D174/D308 annotated with user direction.
2026-09-26 17:36:48 -04:00
James Dansereau 506cd7ed11 D207/D241: shot-sound handle probe; live captures refute drop/starvation
TEMP GE_D207S (gunfire.c, #ifdef PORT, read-only) logs every player
shot-sound decision (H1/H2/SKIP). Four user captures incl. a 7-weapon
stress test at 60 fps: 0 SKIP, 0 voice drops, audio production at rate.
The one captured drop-out ran under GE_AUDIOTRACE, whose audio-path file
I/O is a likely cause. Still open as intermittent.
2026-09-26 17:26:06 -04:00
James Dansereau b8e34c7fac D287: user-confirmed fixed (idle-unfocused click-in, mouse checks) 2026-09-26 16:55:58 -04:00
James Dansereau 8f838316c0 Q7: declare atoi/lround for port TUs; D207: ZHOLD/ZREL harness, findings
optionsoverlay.c called atoi and lround through implicit int declarations
(GE's stub stdlib.h/math.h shadow the CRT, D324 class); atoi joins the
other K&R decls in port/shim/stdlib.h, lround gets a local prototype.
Windows + Linux builds clean of both warnings.

GE_INPUTSCRIPT gains ZHOLD/ZREL (sustained fire) for automatic-weapon
audio repros. D207/D241: headless burst-fire at 60 vs 30 fps with the
alarm forced logged zero voice drops at both caps; owed a real-play
capture. Golden gate 3/3.
2026-09-26 16:53:54 -04:00
James Dansereau 0097469810 D291/D306: close Dam intro truck glitch as faithful; add repro probes
D291 (user-captured) is D306: Dam intro camera 5, truck over the walkway
camera; reproduces at FovScale 100. All PC-specific leads refuted with
evidence: FOV, depth precision/DrawDistance, depth state (every truck
triangle is opaque z-tested), near-plane handling, wheel transforms. The
image is a depth-correct view of the authored model from under the truck.
GE_ZF's earlier "real fighting" was a +-255 z quantisation artefact.

TEMP tools: GE_INTROCAM=<n> pins the level intro's first camera
(bondview_r.c, #ifdef PORT, PRNG draw still consumed); GE_D306C depth-state
census in gfx_pc.cpp. Golden gate 3/3.
2026-09-26 15:54:46 -04:00
James Dansereau f1207e915b D252: re-sync compiled explosion DLs on every stage load; D314 confirmed
gimgSyncCompiledGlobalDLs (D68 shim) only copied texLoad's resolved
texture pointers into the compiled globalDL shadows while a slot still
held the 0xABCD IMAGESEG marker, i.e. only for the first stage (title).
Every later stage kept pointers into the title's freed texture pool, so
explosion smoke/fire/debris rendered as rainbow garbage once the stage
overwrote that memory (Facility: past the lockers). Learn the slots once,
re-sync them every stage. User-verified; golden gate 3/3.

Also: TEMP GE_D252POOL texpool/sync probe; GE_D157 F12 burst and caps
(uncapped colour match made live play 4-6 fps). D314 F10 flicker
user-confirmed fixed. Findings M-201, porting-notes C2.
2026-09-26 11:43:30 -04:00
James Dansereau aedc98e247 D252/D314/D291: explosion-debris investigation, overlay wheel race fix, Dam truck notes
- D252 (M-200): the 'rainbow confetti' is the explosion debris
  (explosionInitFlyingParticles). Statically clean for colour; 4 headless
  repros including the user's grenade-launcher trigger are all clean. Still OPEN.
- d320repro (TEMP): new explode= and cheat= actions for headless explosion
  captures; documented in GE-ENV-PROBES.
- D314: optionsOverlayScroll (host thread) rebuilt s_visIdx/s_visN and wrote
  s_sel while the scheduler thread draws the overlay. Wheel notches are now
  queued atomically and applied in HandleInput (D287 pattern). Emit and
  HandleInput share the scheduler thread. Headless file/mission select is
  pixel-stable; likely fixed together with D287, needs a user check.
- D291: truck AI mapped (ai_9 / 0x040a, path 7); headless walk did not reach it.
2026-09-25 23:20:38 -04:00
James Dansereau d07ed0f2d0 D287: apply SDL mouse-mode/cursor changes on the window thread only
input.c called SDL_SetRelativeMouseMode / SDL_ShowCursor from the scheduler
thread (every controller poll) and from the host thread's focus/click
handling at the same time. SDL's mouse API is not thread-safe; on Windows
relative mode starts/stops the raw-input thread, and clicking back into the
window after being unfocused is exactly when both threads flip it - the D287
freeze trigger. Callers now record the wanted state; inputApplyMouseRequests()
applies it on the host thread from videoPumpEvents(). Queue-deadlock leads
ruled out statically. Win+Linux build clean, golden 3/3; freeze re-test owed.
2026-09-25 22:37:46 -04:00
James Dansereau 2ed84ed38b Q7 audit fixes: missing returns in front.c menus, getenv prototype, dram.c shift UB
- front.c: constructor_menu07_missionsel / constructor_menu0D_missioncomplete
  fall off the end while the caller uses the Gfx* result; return DL under
  AVOID_UB (porting-notes D6). Old/new objects disassemble identically at -O2,
  so no behaviour change on this compiler; clang/arm64 no longer rely on luck.
- libultra/audio/event.c: include <stdlib.h> under PORT so getenv() is not an
  implicit int-returning declaration (D324 class).
- dram.c: DRAM_SIZE >> 32 on a 32-bit unsigned long (Win64) was UB.
Golden gate 3/3.
2026-09-25 22:30:48 -04:00
James Dansereau edddf87429 D322: prefer DirectSound over SDL2's WASAPI backend on Windows
Four simultaneous drain monitors on the same USB interface: WASAPI (512 and
2048 samples) fell to 81-88% drain for ~30-50 s every ~317 s and lost 1.4% of
playback, while DirectSound stayed at exact real time. Each WASAPI shortfall
overflowed the audio queue and dropped blocks (the periodic garbled bursts).
audioInit() now hints directsound,wasapi; SDL_AUDIODRIVER still overrides.
Golden gate 3/3; 60 s GE_D204 run clean after load.
2026-09-25 22:25:13 -04:00
James Dansereau 2a20a93318 D322: periodic 'garbled' bursts are the host audio device, not the port
A no-game SDL drain monitor (new tools_pc/sdl_drain_monitor.c, opens SDL
exactly like port/src/audio.c) shows the maintainer's Focusrite USB interface
draining at 88-95% for ~15 s every ~312 s, matching the in-game overflow
bursts' period. Level loads, combat, the SDL pull pattern and a
pacemaker-vs-vsync beat were ruled out. Remaining D322 items: the 8-voice SFX
cap (D207/D241) and #87's progressive decay. porting-notes: measure the host
device before chasing periodic audio glitches.
2026-09-25 19:15:22 -04:00
James Dansereau 82548a0fe9 findings: 2026-09-25 release playtest close-outs + D322 capture
D311 FIXED (root cause D336; 0 anomaly lines incl. Caverns combat), D288
CLOSED, D294 and D330 user-confirmed, D235 still unreproduced. D322: pools
healthy (leak hypothesis refuted); SFX soft-cap saturation in firefights
(D207/D241) plus a new periodic SDL output-queue overflow every ~314 s that
starts at the title screen, so it should reproduce headless.
2026-09-25 18:40:26 -04:00
James Dansereau 7baf490020 tools_pc: golden_gate.sh — one-command per-patch golden gate
Pins data/ge007.ini to a defaults-only 640x480 window (restored on any exit),
captures Bunker 1 at 640-1120:240 and runs framediff.py against the golden
baseline. --level/--dump give a capture-only smoke run (exit 0 = frames
captured and no crash). Full framediff output goes to scratch/.
2026-09-25 16:46:03 -04:00
James Dansereau 251fcc4194 docs: fold drop-in ROM Part B backlog (issue #85) into release-dropin-rom-plan 2026-09-25 10:47:59 -04:00
James Dansereau 684dee9127 D231: park mute-on-focus-loss/screenshot QoL (deprioritized; branch retired from GitHub) 2026-09-25 10:45:11 -04:00
James Dansereau 709959c66a docs: cut-content research round 2 — decomp-only discoveries + full music alignment
New findings not covered by TCRF's articles (full detail in local
backlog/cut-content/RESEARCH.md):

- The shipped game's M16 pickup text still reads 'an AR33 assault rifle'
  (LpropobjE PROPOBJ_STR_2A, propobj.c:10471); unused 'US AR33' strings and
  PROP_CHRM16 comments survive too.
- Klobb rename scar verified: GUN_STR_6B is the only out-of-alphabetical-order
  weapon name in LgunE.c, exactly as TCRF's prerelease page describes.
- cartrifle + wristdart: full pickup/prop resources, no ITEM_ enum, no weapon
  stats — cut weapons missing from TCRF's unused-items list (wrist dart = the
  AMMO_DARTS hardware; decomp comments it '(BETA)').
- All four Bonds mapped: CUFF_/BOND_ Connery/Dalton/Moore enums + the
  actor-switch code in bondview2.c with every branch flattened to Brosnan;
  no former-actor models exist in the ROM (80 C*Z chr models enumerated).
- Cuba (LlenE.c) is the only orphan level with recoverable text: cut Natalya
  dialogue, title card, alternate credits cast.
- Orphan-level geometry confirmed present in ROM (obseg.h segment decls);
  what's missing is mission setup, not geometry.
- Music enum vs Notes-page GS index aligned slot-for-slot through 0x2C with
  four local mismatches past it (49/52/54/59) pending in-game audition.
2026-09-25 10:44:44 -04:00
James Dansereau 019ec2f233 D226: cap HUD scale at 150% (user playtest: works, little benefit above 150) 2026-09-24 11:40:43 -04:00
James Dansereau 062f605520 plan: reconcile v0.4.0 rows (D226, D237, D238, D294, D311) + session additions (D336-D339, #105 note) 2026-09-24 11:29:21 -04:00