forked from Ports/goldeneye-pc-port
D245: reopen -- live playtest shows the allowShift=TRUE fix did not resolve the seam
User report on Frigate post-fix: water still glitches between two patterns and still changes with view angle, unlike the sky (which uses the same skyPortBeginFan/skyPortEmitTileShift mechanism post-D227 and no longer has this problem). The mechanistic writeup and GE_D227V trace from the same session looked correct but were evidently not sufficient evidence -- a single static frame/angle capture never exercised whatever actually causes the live symptom. Reopening honestly rather than leaving a stale FIXED label; the superseded analysis is kept in the row for reference but flagged as unconfirmed. No code change in this commit (docs only). Claude-Session: https://claude.ai/code/session_016DQUKGLZxFtPy52MkKXXog
This commit is contained in:
1 parent
a088bb51e7
commit
53c9a879f3
2 files changed
+2
-2
No files matched your search
@@ -126,6 +126,6 @@ D240,OPEN,"Player gunshot SFX timing/cadence reportedly does not match the N64 o
|
||||
D241,OPEN,Player gunshot SFX goes silent under some conditions —,"OPEN — not newly root-caused; high confidence this is D207 reproduced, not an independent bug."
|
||||
D242,?,Player-death sequence UX regression vs N64 original:,NOT A PORT-LOGIC BUG as far as static analysis can tell.
|
||||
D243,OPEN,"Dam end-of-level cutscene (the abseil/bungee sequence, D148/D160's subject):",OPEN — M-109 re-analysis of the same session's raw logs corrects the timing/pattern claims above; the D134/pendingGfx race hypothesis is likely wrong.
|
||||
D245,FIXED,IsWater water: two competing patterns with a visible seam that moves as the player looks around (mouse/aim) —,"FIXED (port-layer, src/game/sky.c, #ifdef PORT) —"
|
||||
D245,OPEN,IsWater water: two competing patterns with a visible seam that moves as the player looks around (mouse/aim) —,"OPEN — REOPENED (M-116 live playtest, same session):"
|
||||
D246,OPEN,"Tiny pixel strips at the left and right edges of the screen, ""like overscan"" —","OPEN — one candidate ruled out (M-116 follow-up), root cause not found."
|
||||
D247,RESOLVED,Black bars top and bottom of screen —,"NOT A BUG — confirmed faithful, unmodified N64 decomp behaviour, no code change made."
|
||||
|
@@ -522,7 +522,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
||||
| D241 | **Player gunshot SFX goes silent under some conditions — reported on Bunker with the alarm sounding, "or some other factor" — but only for PP7 and AK47, Klobb unaffected (M-106, user QA report, concrete repro).** This is very likely **D207 finally reproduced.** D207 (M-77) root-caused that GE's SFX player has a hard **8-voice cap** (`MUSIC_SFX_SEQ_MAYBE_MAX_SOUNDS`, `src/music.c:76`) and that D206's fix made the alarm klaxon (`ALARM3_SFX`=163, triggered from `handle_alarm_gas_timer_calldamage()`, `src/game/propobj.c:14457`) a genuine **infinite ADPCM loop** that now legitimately occupies one of those 8 voices for the alarm's whole duration; the manual preemption scan (`snd.c:~347-392`) refuses to steal any *owned* LOOPED voice (the M-65 carve-out only exempts *ownerless* loops), so once 8/8 voices are held, a new one-shot request is silently dropped via `sndDisposeSound` (`snd.c:391`). D207's own M-77b session built a `GE_FORCEALARM=1` BUNKER1 harness and could **not** reproduce audible drops (`[D207-DROP]=0`), and explicitly left as "owed": *"needs a real repro from the user: which level, which weapon/situation."* This report supplies exactly that (Bunker, alarm). **Investigated why PP7/AK47 and not Klobb, inconclusive at the code level:** Klobb (`ITEM_SKORPION` — confirmed GE's internal name for the Klobb via `src/game/player.c:576`, `skorpion_stats` in `assets/obseg/gun/skorpion/gunWeaponStat.inc.c`) and AK47 (`ak47_stats`, `assets/obseg/gun/ak47/gunWeaponStat.inc.c`) share the **same** `AutomaticFiringRate=0x03` (fast auto), while PP7 (`wppk_stats`, `assets/obseg/gun/wppk/gunWeaponStat.inc.c`) is semi-auto only (`AutomaticFiringRate=0xFF`) — so a naive "fires faster ⇒ more self-inflicted voice contention" theory does not cleanly explain grouping PP7 with AK47 against Klobb. All three weapons' fire SFX (`GUN_B1_MGUN3_3_SFX`=Klobb, `GUN_B2_HEAVY_SFX`=PP7, `GUN_B4_BOLTACTION_SFX`=AK47 — `src/bondconstants.h:2277-2280`) go through the identical one-shot, priority-0x40 `sndPlaySfx` path (`gunfire.c:3246-3286`); no per-weapon distinction exists in the trigger or priority *code*. A real distinction, if one exists, most likely lives in the **sample bank data itself** (per-sample envelope/decay length — a longer-tailed sample stays `PLAYING` and stealable/held longer, changing its odds in the preemption scan) — that data is ROM-derived binary content, not inspectable without the extracted ROM (`./data/`, absent in this worktree). Confirmed the voice-allocation/preemption code is unmodified `src/snd.c` game logic, not a `port/` mixer bug: `port/src/mixer.c`/`port/src/audio.c` implement DSP synthesis and device output only (per D199), with no SDL `Mix_*`-style channel-priority layer in the port to have introduced a new bug. Per AGENTS.md non-negotiable #2, any real fix belongs in D207's already-designed (reverted, M-77b) last-resort LOOPED-preemption pass in `snd.c`, not in `port/`. | **OPEN — not newly root-caused; high confidence this is D207 reproduced, not an independent bug.** Recommend folding this repro into D207 (or closing D241 as a duplicate once D207 is reopened) rather than tracking separately. Next: re-run M-77's `GE_FORCEALARM=1` harness on `-level_09` with scripted PP7 and AK47 fire (not just generic fire) against Klobb as a control, watching `g_sndAllocatedVoicesCount` / the (currently reverted) `[D207-DROP]` counters to see whether the 8-cap is actually hit for two of the three weapons and not the third — or whether it is really the sample-envelope-length distinction above. No runtime verification possible in this environment (no ROM/display). |
|
||||
| D242 | **Player-death sequence UX regression vs N64 original: PC requires an LMB click to proceed to the mission-failed/file-select screen; user recalls N64 auto-plays 3 death-camera angles then transitions with no input needed (M-106, user QA report).** **The 3-angle auto-replay and its no-input auto-transition both exist, unmodified, in the decomp — confirmed, not a design difference removed for the port.** `bondviewSetCameraMode(CAMERAMODE_DEATH_CAM_SP)` (`src/game/bondview2.c:901-1010`) calls `pickDeathCameraAngles()` (`bondview2.c:641-782`, picks a fresh random valid camera angle each call) to stage each replay; when it returns 0 — no further valid angle found — the code calls `bossRunTitleStage()` directly, and the source comment at `bondview2.c:1006-1007` literally reads *"...or when the three death replays are finished."* The 3-cycle count is driven by `bondviewAdvanceCameraMode()` (`bondview2.c:1041-1078`): `CAMERAMODE_DEATH_CAM_SP` → `CAMERAMODE_DEATH_CAM_MP` → `camera_mode++`, looping back to `DEATH_CAM_SP` while `camera_mode < CAMERAMODE_SWIRL` (three iterations). Each individual replay's own advance is driven purely by animation/timer state (`bondview2.c:1467-1490`): the `g_CameraAfterCinema` flag that `bondviewAdvanceCameraMode()` acts on is set automatically once `modelGetAnimFrame(bodyModel) >= modelGetAnimEndFrame(bodyModel)`, or after a `camera_transition_timer >= 180.0f` tick-timeout fallback when there is no body model — **no button check in that branch; fully automatic.** **The button-press the user is hitting is a real, intentional N64 skip-ahead shortcut, not a port-added gate:** the same code block (`bondview2.c:1483-1489`) *also* fires the identical advance immediately on `(buttons & ~oldbuttons & (CONT_A | B_BUTTON | Z_TRIG | START_BUTTON))` whenever `bonddead && redbloodfinished && deathanimfinished` — i.e. on real N64 hardware, pressing A/B/Z/Start at any point during a death replay skips straight to the end, by design. **On the port, LMB (mouse fire) is mapped to `GE_CONT_G`, which is Z_TRIG** (`port/src/input.c:664-665`: `(mb & SDL_BUTTON(SDL_BUTTON_LEFT)) ... button \|= GE_CONT_G`; binding table `input.c:351`: `{"Z",GE_CONT_G}`) — exactly one of the four original skip buttons. So an LMB click during the death sequence is GE's own original cutscene-skip input, faithfully wired through the port's control remap, not a port-invented "click to continue" prompt. **What this investigation could not determine** (no build/runtime access in this worktree): whether the *automatic*, no-input path actually completes on PC in a reasonable time. `camera_transition_timer` accumulates via `g_GlobalTimerDelta` (`bondview2.c:1470,1493`), which is set from the same `g_ClockTimer`/`speedgraphframes`/`deltaFrames` chain flagged in D240 above and investigated under D155/D186/D193/D204/D209 — if any residual in that chain stalls or mis-scales specifically in this state, the auto-advance could take far longer on PC than on N64 (or effectively never complete before the player gives up and clicks), which would make an LMB click *feel* mandatory even though the ground-truth logic never requires one. | **NOT A PORT-LOGIC BUG as far as static analysis can tell.** Confidence HIGH that the LMB-click skip path is faithful original behavior (Z_TRIG-mapped, exists unmodified in `bondview2.c`), not a defect to remove. Confidence LOW (untested) on whether the no-click automatic path is actually healthy on PC. Needs a human playtest: die, then **deliberately touch no input** during the death sequence and time whether/how long until the mission-failed screen appears on its own. If it never arrives without a click, the real bug is a `g_GlobalTimerDelta`/`camera_transition_timer` stall in the D240 clock family — cross-reference D240 — not a wrongly-added input gate, so there is still no `#ifdef PORT` skip-gate to remove per AGENTS.md #2. No runtime verification possible in this environment (no ROM/display). |
|
||||
| D243 | **Dam end-of-level cutscene (the abseil/bungee sequence, D148/D160's subject): the camera violently shakes/"spazzes" during each of the scripted camera-angle cuts (M-107, live `GE_D160=1` trace, two interactive `-level_33` runs + one fresh-save normal-progression run).** **First, corrects D160's own premise: the cutscene is NOT skipped on the current build.** Both debug-loaded runs show exactly the AI-script-scripted sequence firing: `bondviewSetCameraMode(7)` (`CAMERAMODE_POSEND`, the cutscene camera-lock state) called 2-3 times, matching `ai_17`'s three `camera_switch` commands in `UsetupdamZ.c`'s abseil ailist (`assets/obseg/setup/UsetupdamZ.c:2656`+), followed by `bossReturnTitleStage`. So D160's original (b)/(c) hypotheses (AI trigger never fires / puppet renders invisibly) are **refuted on this build** — the mechanism runs; what's broken is what it renders. **Root cause candidate, directly observed:** right in the camera-cut window, fast3d's D146 catch-all (`port/fast3d/gfx_pc.cpp:3037`, "unknown GBI opcode … ending DL") fired a tight burst — same 4 memory addresses repeating every frame for ~10 frames, then clean — with payload bytes `0xfafbfbfcfcfbfdfc`/`0xfcfafbfbfafbfafb`: a **freed/uninitialized-memory fill pattern**, not real GBI commands. This reads as a stale-pointer display-list read, not a decode bug — some segment/scene buffer backing the outgoing camera shot's geometry got freed or recycled while a still-in-flight display list (queued ahead in the port's double-buffered render pipeline — see D134's "pendingGfx" note, `port/src/libultra.c:733-746`, on how many frames of latency the sched round-trip can carry) still referenced it. **Independent evidence of a race, not a fixed-order bug:** the two `-level_33` debug-load runs show the camera_switch(7) calls landing in a *different order relative to* `bossReturnTitleStage` between runs (run 1: three switches, then the stage-return call; run 2: two switches, the stage-return call, *then* a third switch arriving after) — and the D146 corruption burst appeared in run 1 but not run 2 at all, non-deterministically. That pattern (symptom present/absent, call order shuffling) is the signature of a genuine timing race between the AI-list's cutscene commands and the level-exit/report-transition code, not a deterministic logic bug. **User-confirmed on real (non-debug-boot) play, not just the debug harness:** a fresh-save normal playthrough into Dam still hit the camera glitch on this same cutscene — ruling out "artifact of the `-level_33` debug boot" for this specific symptom (unlike the secondary "no report screen, straight to file-select" symptom seen only on the debug-loaded runs, which did NOT reproduce on the fresh-save run and is therefore most likely a `-level_N` debug-boot artifact per the D190 precedent, not filed as its own bug here). | **OPEN — M-109 re-analysis of the same session's raw logs corrects the timing/pattern claims above; the D134/pendingGfx race hypothesis is likely wrong.** Confidence MEDIUM on the correction, LOW-MEDIUM on the new lead. Re-reading `data/playtest_d160.log`/`_run2.log` at the `g_framesRendered` level (not just grepping for `D146`) shows the D146 burst fires **~1600-3900 frames (tens of real seconds) *after*** `bossReturnTitleStage`/the `camera_switch(7)` calls, not during them, in **both** runs — "right in the camera-cut window" and "run 1 only" are both wrong as stated above. This also weakens the D134/`pendingGfx` citation: `osSpTaskStartGo` runs `gfx_run()` synchronously and inline (`port/src/libultra.c:1232-1258`), so nothing from the cutscene's own DL submission is still in flight by the time any teardown code runs — the port doesn't have the async-RSP race the hypothesis above assumes. **New lead:** whatever screen renders in that multi-thousand-frame gap after mission-complete is the more likely site — probably `MENU_MISSION_COMPLETE` (`front.c:7267`, `constructor_menu0D_missioncomplete`) or an adjacent briefing/file-select screen in that chain, same general class as D75 (front-end model absence) / D141 (menu bad-pointer bug), not a cutscene-render race. Of the 4 repeating fault addresses, 3 read as literal zero words and only 1 matches the `0xfafbfbfc…` pattern, arguing against a deliberate poison-fill (none found anywhere in `port/`) and for either genuinely-unwritten memory or a decode landing inside unrelated valid data. Next: an env-gated `front.c` menu-transition trace (`MENU_*` id + `g_framesRendered` on every transition after `bossReturnTitleStage`) plus a `GE_PCDUMP` window over frames ~4500-8000 (not the camera-cut window) to name the exact screen/segment. Cross-ref D160 (this supersedes its stale "cutscene skipped" framing with a "cutscene renders corrupted" one, now further corrected to "corruption isn't in the cutscene render at all") and D173 (Cradle's Bond-floating/spinning cutscene bug — same subsystem family, unconfirmed shared root cause). |
|
||||
| D245 | **IsWater water: two competing patterns with a visible seam that moves as the player looks around (mouse/aim) — "looks almost exactly like skybox" (M-116, user QA report, post-D229-fix build).** The symptom is D227's exact signature class (s16 `Vtx.tc` overflow → rasteriser interpolates between wrapped coordinates → two differently-wrong screen regions + a seam at the wrap boundary; on the sky quad the split ran on the 0–3 diagonal). Water draws through the same port path: `src/game/sky.c` water block (~905–956) — `texSelect(&skywaterimages[WaterImageId])` + `sub_GAME_7F09343C` (two-texunit cross-fade; both tiles re-declared RGBA/16b @ tmem 0, the draw D229 fixed) then a `skyRenderTri` fan over `sp274[]` under `skyPortBeginFan(sp274, s1, FALSE)` — and **the `FALSE` is a documented, deliberate tolerance of exactly this overflow**: the comment above `skyPortBeginFan` (sky.c ~1738) records that the IsWater quad is excluded from D227's tile-shift safety valve because both texunits read the same vertex tc, so a tc rescale would need matched shifts on BOTH tiles and "shifting both makes them sample identically, which flattens the cross-fade"; the 2026-09 decision was that "the water quad keeps the plain 1:1 tc and simply tolerates the overflow on its horizon vertex, exactly as it did before D227." The mechanism is real: `unk20/unk24` are S10.5 units reaching tens of thousands near the horizon; the fold rebases to a multiple of `SKY_TC_WRAP` (2048) but with k=0 an s16 tc holds only ±32767, so any wider span wraps. It was invisible before D229 because every water texel was green mottle garbage anyway; with correct blue texels the wrapped region now reads as a visibly different pattern + seam, and it tracks the view because the fan's S/T depend on camera orientation. (On N64 this draw is a verbatim RDP `G_TRI_SHADE_TXTR` coefficient block with no s16 tc — the overflow constraint is a port artifact of re-emitting as `gSPVertex` batches, same class as D227.) | **FIXED (port-layer, `src/game/sky.c`, `#ifdef PORT`) — confirmed the `allowShift=FALSE` tolerance was the cause, and the "flattens the cross-fade" objection was wrong.** Changed the water quad's call from `skyPortBeginFan(sp274, s1, FALSE)` to `..., TRUE)`, so it now gets D227's tc-shift safety valve like every other sky fan. Why the old objection doesn't hold: `skyPortEmitTileShift` replays **both** tiles' captured `SETTILE` commands with the identical `k`, so both texunits' decoded S/T are rescaled by the same `2^k` *before* each tile's own (unshifted, tile-native) `uls`/`ult` offset is applied by the RDP — the offset between tile 0 and tile 1's sample points (what drives the cross-fade) is preserved, not flattened, because the shift and the offset act at different stages. **Verified mechanistically:** `GE_D227V=1` on Frigate (`-level_26`) shows a water fan vertex spanning S=-166..299317, T=-6451..288410 in S10.5 units — tens of thousands of texels, the same order of magnitude as D227's pre-fix sky overflow — now getting `kS=4 kT=4` (previously forced to 0), decoding to small in-range tc values (100s, not wrapped). **Verified no regression:** `verify.sh frigate` and `verify.sh "surface 2"` (the two `IsWater` levels) both PASS crash-free post-fix; non-water sky levels (`statue`/`-level_22`) unaffected since only the water call site changed. Screenshot comparison at a fixed scripted-intro camera angle (frame 500, both builds) showed no regression, but that specific angle didn't happen to frame the overflowing part of the fan either before or after — the sinf()-driven cross-fade also makes frame-for-frame screenshot diffs across separate runs noisy (each run's shimmer phase differs), so a same-frame pixel diff wasn't a clean confirmation tool here; the `GE_D227V` trace is the real evidence. **Owed:** a live human playtest looking around at the Frigate/Surface 2 horizon (the mouse/aim-tracking seam the user actually reported) to close this out with an eyeball, same as every other rendering fix landed without display access this session. Cross-ref D227 (mechanism), D229 (made this visible). |
|
||||
| D245 | **IsWater water: two competing patterns with a visible seam that moves as the player looks around (mouse/aim) — "looks almost exactly like skybox" (M-116, user QA report, post-D229-fix build).** The symptom is D227's exact signature class (s16 `Vtx.tc` overflow → rasteriser interpolates between wrapped coordinates → two differently-wrong screen regions + a seam at the wrap boundary; on the sky quad the split ran on the 0–3 diagonal). Water draws through the same port path: `src/game/sky.c` water block (~905–956) — `texSelect(&skywaterimages[WaterImageId])` + `sub_GAME_7F09343C` (two-texunit cross-fade; both tiles re-declared RGBA/16b @ tmem 0, the draw D229 fixed) then a `skyRenderTri` fan over `sp274[]` under `skyPortBeginFan(sp274, s1, FALSE)` — and **the `FALSE` is a documented, deliberate tolerance of exactly this overflow**: the comment above `skyPortBeginFan` (sky.c ~1738) records that the IsWater quad is excluded from D227's tile-shift safety valve because both texunits read the same vertex tc, so a tc rescale would need matched shifts on BOTH tiles and "shifting both makes them sample identically, which flattens the cross-fade"; the 2026-09 decision was that "the water quad keeps the plain 1:1 tc and simply tolerates the overflow on its horizon vertex, exactly as it did before D227." The mechanism is real: `unk20/unk24` are S10.5 units reaching tens of thousands near the horizon; the fold rebases to a multiple of `SKY_TC_WRAP` (2048) but with k=0 an s16 tc holds only ±32767, so any wider span wraps. It was invisible before D229 because every water texel was green mottle garbage anyway; with correct blue texels the wrapped region now reads as a visibly different pattern + seam, and it tracks the view because the fan's S/T depend on camera orientation. (On N64 this draw is a verbatim RDP `G_TRI_SHADE_TXTR` coefficient block with no s16 tc — the overflow constraint is a port artifact of re-emitting as `gSPVertex` batches, same class as D227.) | **OPEN — REOPENED (M-116 live playtest, same session): the `allowShift=TRUE` mechanistic fix below did NOT resolve the symptom.** User report on Frigate post-fix: water still "glitches, kinda goes back and forth between two graphics too quickly," and still "changes depending on your view unlike the sky" (i.e. the sky, using the identical `skyPortBeginFan`/`skyPortEmitTileShift` mechanism post-D227, no longer has this problem, but water still does after getting the same treatment). This means the `allowShift=FALSE→TRUE` change either isn't the actual fix, or there's a second mechanism specific to water's two-texunit cross-fade that the tc-shift alone doesn't address — most likely candidate: the shift only rescales the *shared* vertex tc uniformly, but the tile-0-vs-tile-1 sample-point difference is set by each tile's own `uls`/`ult` (RDP tile-space, not vertex-tc-space) — if per-frame `k` changes granularity of the *quantized* shared coordinate before each tile's independent `uls`/`ult` subtraction, the two tiles' effective sampled texel could drift relative to each other frame-to-frame in a way the static `GE_D227V` trace (single frame, single camera angle) never exercised. Needs a fresh live investigation, not a repeat of the same static-trace approach — a scripted or live multi-frame capture while rotating view, watching both tiles' *decoded* texel positions (not just vertex tc) frame over frame. Do not re-apply the same `allowShift=TRUE` reasoning without new evidence; the superseded mechanism write-up below is unconfirmed-by-playtest and may be wrong. The code change (`allowShift=TRUE` on the water quad) is left in place — it's not shown to be actively harmful, and reverting it isn't obviously better than leaving it, pending the fresh investigation. **Superseded analysis (unconfirmed by playtest, kept for reference):** ~~FIXED (port-layer, `src/game/sky.c`, `#ifdef PORT`) — confirmed the `allowShift=FALSE` tolerance was the cause, and the "flattens the cross-fade" objection was wrong.~~ Changed the water quad's call from `skyPortBeginFan(sp274, s1, FALSE)` to `..., TRUE)`, so it now gets D227's tc-shift safety valve like every other sky fan. Why the old objection doesn't hold: `skyPortEmitTileShift` replays **both** tiles' captured `SETTILE` commands with the identical `k`, so both texunits' decoded S/T are rescaled by the same `2^k` *before* each tile's own (unshifted, tile-native) `uls`/`ult` offset is applied by the RDP — the offset between tile 0 and tile 1's sample points (what drives the cross-fade) is preserved, not flattened, because the shift and the offset act at different stages. **Verified mechanistically:** `GE_D227V=1` on Frigate (`-level_26`) shows a water fan vertex spanning S=-166..299317, T=-6451..288410 in S10.5 units — tens of thousands of texels, the same order of magnitude as D227's pre-fix sky overflow — now getting `kS=4 kT=4` (previously forced to 0), decoding to small in-range tc valuesLine truncated
|
||||
| D246 | **Tiny pixel strips at the left and right edges of the screen, "like overscan" — look like raw pixels, not 3D graphics (M-116, user QA report).** Uninvestigated. The port renders at native 640×480 (`GE_NATIVE_W/H`; `gfx_current_native_aspect` set in `port/src/video.c:253,570`) and scales to the window on present, so the leading candidate is a scaling/blit rounding artifact: non-integer scale factors leaving 1–2 columns of uncleared backbuffer content at the edges (or an off-by-one in the blit rect). Secondary candidates: an RDP fill-rect/scissor off-by-one in a game DL or the F10 overlay hook (`gfx_run()` seam, D184), or GL edge filtering on the scaled texture. | **OPEN — one candidate ruled out (M-116 follow-up), root cause not found.** Step (1) from the original plan is done: a `GE_PCDUMP` capture (Frigate, native 640×483 buffer, both against the existing save and a fresh EEPROM) shows clean, continuous scene content in the leftmost/rightmost columns — no dead/black/garbage strip at either edge. That means the defect is **not** baked into the native render itself (rules out an RDP fill-rect/scissor off-by-one in a game DL, and rules out D227/D245-style tc issues) — it must be introduced later, specifically in the SDL-window presentation path that `GE_PCDUMP` bypasses entirely (`gfx_run()` reads back the game's own render target directly, never the actual window backbuffer the user sees). Re-examined `gfx_adjust_viewport_or_scissor` (`gfx_pc.cpp:2174`): its floor/ceil rounding is already deliberately anti-gap (comment: "prevents sub-pixel gaps at viewport edges"), so a plain rounding bug there is a weaker lead than it looked; more likely candidates now are the `game_renders_to_framebuffer`-path MSAA resolve `glBlitFramebuffer` (`gfx_opengl.cpp:1252`, only exercised when `Video.MSAA>1` or the window size actually differs from the game's target size mid-frame — a path `GE_PCDUMP`'s headless capture doesn't exercise the same way a live resizable window does) or a genuine sub-pixel/DPI scaling remainder specific to the user's actual window dimensions. **Next, still needs the user (no live window access in this environment):** (1) confirm current `Video.MSAA` setting and window size/aspect at the time the strips were seen; (2) if `MSAA>1`, retest with `Video.MSAA=1` to see if the strips disappear (isolates the resolve-blit path); (3) report whether the strip width changes with window size (fixed 1px = blit-rect off-by-one; scales with window = scale-factor remainder). Cross-ref D247 (separate, now closed — don't conflate the two; D247's letterbox is confirmed-intended and top/bottom only, D246 is left/right and still unexplained). |
|
||||
| D247 | **Black bars top and bottom of screen — possible aspect-ratio defect (M-116, user QA report).** Uninvestigated. Context: the port currently renders native 4:3 (640×480); widescreen is a *parked proposal* (`docs/dev/WIDESCREEN-FOV-PLAN.md` — PD-parity native 16:9 render, needs rule-#2 sign-off for its game-code HUD wave), so if the user's window/display is wider than 4:3 and the present path letterboxes to preserve aspect, the bars are current intended behaviour rather than a bug. If they appear in a 4:3 window too, it is a real defect (framebuffer sized wrong vs window, `videoCreateFramebuffer(w,h,upscale,autoresize)` → `gfx_create_framebuffer`). | **NOT A BUG — confirmed faithful, unmodified N64 decomp behaviour, no code change made.** `GE_PCDUMP` captures (both against the pre-existing save and a fresh-EEPROM run, to rule out a stale `Screen` option from earlier test sessions) show the exact same inset on Frigate: real scene content occupies rows ~20–459 of a 640×483 capture (the 483 vs 480 is a separate, harmless 3-row capture-tool rounding quirk, not investigated further), i.e. roughly 220/240 of the vertical field — and `src/game/fr.h:34` defines `VIEWPORT_HEIGHT_DEFAULT_NTSC 220` (240 for the full field), consumed unmodified by `bondviewGetCurrentPlayerViewportHeight()` (`bondview2.c:7858`) as the **default in-game viewport height whenever `PLAYER_OPTION_SCREEN` is `SCREEN_SIZE_FULLSCREEN`** (the decomp's own default value, `options.c:128`) — `VIEWPORT_HEIGHT_FULLSCREEN` (304, no inset) is a red herring name; it's only reachable via the `cameraBufferToggle` branch, not normal solo play. This is GoldenEye 007's well-documented original TV-safe-area letterboxing, baked into ground-truth decomp constants with no `#ifdef PORT` anywhere near it — the N64 game genuinely doesn't fill the full field during normal gameplay. Ruled out a stale/leftover EEPROM `Screen=Wide/Cinema` setting from earlier QoL-testing sessions as an alternative explanation: a fresh EEPROM (default options) shows the identical inset. **No fix needed; this row closes.** If the user's window shows noticeably *thicker* bars than this ~8–9%-per-edge margin, or bars appear on the *sides* instead of top/bottom, that would be a genuinely different (and real) symptom worth reopening under a new label — but "thin bars top and bottom, present at any window size" is correct, original behaviour. Cross-ref D226 (separate, already-tracked HUD-scale QoL ask — unrelated mechanism, don't conflate). |
|
||||
|
||||
|
||||
Reference in new issue
Block a user