forked from Ports/goldeneye-pc-port
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.
This commit is contained in:
1 parent
0097469810
commit
8f838316c0
5 files changed
+29
-4
No files matched your search
@@ -20,7 +20,7 @@ Two classes:
|
||||
| Env var | File:line | What it does | Status |
|
||||
|---|---|---|---|
|
||||
| `GE_PCDUMP` | `port/fast3d/gfx_opengl.cpp:1079` (`is_pcdump`), `gfx_opengl.cpp:700`, `port/src/video.c:188`, `port/src/config.c:46` (`configGetFrameDump`) | Per-frame framebuffer PPM dump to `$PCDUMP` dir (verification-ritual golden captures, `tools_pc/framediff.py`/`pixcount.py`). Also settable via `[Debug] FrameDump` ini (env wins). **M-33/D168: the writer now emits rows top-to-bottom — captures before that fix are vertically flipped.** | **live** |
|
||||
| `GE_INPUTSCRIPT` | `port/src/input.c:306` | Headless scripted controller-0 input: `"<frame>:<tok>,…;…"` (`SUP/SDOWN/SLEFT/SRIGHT/SNONE` sustain, buttons pulse). Sole input source when set. | **live** |
|
||||
| `GE_INPUTSCRIPT` | `port/src/input.c:306` | Headless scripted controller-0 input: `"<frame>:<tok>,…;…"` (`SUP/SDOWN/SLEFT/SRIGHT/SNONE` sustain, buttons pulse; `ZHOLD`/`ZREL` sustain fire, D207 M-201). Sole input source when set. | **live** |
|
||||
| `GE_INPUTLOG` | `port/src/input.c:329`, `port/src/config.c:53` (`configGetInputLog`) | Logs computed pad state (buttons + stick) each poll when non-zero. Also `[Debug] InputLog` ini. Also traces D165 `menuptr est/tgt/eff/stick`. | **live** |
|
||||
| `GE_STARTMENU` (+ `GE_STARTMENU_PAGE`, `GE_STARTMENU_DIFF`) | `src/game/lv.c:398-402` (`#ifdef PORT`) | Boot straight into a front-end menu id (13=MISSION_COMPLETE, 10=BRIEFING, 7=MISSION_SELECT, 12=MISSION_FAILED, 6=MODE_SELECT); `_PAGE`=folder row (def 1=Dam), `_DIFF`=0..3. Crash-test a screen fast. | **live** |
|
||||
| `GE_UNLOCK_ALL` | `src/game/debugmenu_handler.c:1098` (`get_debug_enable_all_levels_flag`, `#ifdef PORT`) | Mission-select shows every solo level (playtest jump-to-any-level aid). Cached in a `static int c`. | **live** |
|
||||
|
||||
@@ -11370,6 +11370,13 @@ the Surface 1 spawn capture is unchanged across the strip.
|
||||
|
||||
**Status (from §F table):** **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).
|
||||
|
||||
**2026-09-26 (M-201, v0.4.0): user still hears gunshot drop-outs "with rapid fire guns while a lot of other sound effects occur" (D322 garbling itself is gone). Headless measurements, no drop reproduced.**
|
||||
|
||||
- **Static:** player shots (`gunfire.c:3296-3340`) and guard shots (`chraction.c:5630`) both stop the previous shot sound and start a new one, using at most 2 handles per hand, rate-limited by `SoundTriggerRate` against `g_GlobalTimer`. At 1 tick/frame a shot sound can start every `rate+1` ticks; at the N64's 2–3 ticks/frame the check rounds up to frame boundaries (rate 3: every 6 ticks at 3 ticks/frame vs 4 on PC), so the port plays up to ~1.5x more shot sounds (a D13-class divergence) but does not hold more simultaneous voices. `sndDeactivate` only posts `AL_SNDP_DEACTIVATE_EVT`; the slot frees in `sndDisposeSound`.
|
||||
- **Runtime (Dam, invincibility + all guns, `GE_FORCEALARM=1`, PP7 held in bursts via new `GE_INPUTSCRIPT` `ZHOLD`/`ZREL`, ~100 s each):** `GE_AUDIOTRACE` `[D207-DROP]` = 0 at both FpsCap 60 and 30 (peak SFX slots 8/8 and 7/8); `GE_D322` at 60 fps: worst sample `sfx` 7/8, `pv free` 9/24, `evtq` 9/64, audio `q` 720/2880, `drop=0`. Both drop paths (`preempt-scan` = 8-cap, `no-limit` = physical pool) are covered by `[D207-DROP]`; failing sounds first retry every 33 ms (audible as late, not missing).
|
||||
- **Harness limits:** `gunRequestHandWeaponChange` / the level-start equip call did not switch weapons mid-level from the harness, so the automatic-weapon case (AK47/Klobb) is untested headless.
|
||||
- **Next:** capture the user's real scenario with `GE_AUDIOTRACE=1 GE_D322=1 GE_D204=1` (`scratch/playtest_audio.bat`), noting level, weapon and time of each drop-out; any `[D207-DROP]` line names the layer. If none appear, the "drop-out" is the faithful stop-then-restart of the per-hand shot sound, not a lost voice.
|
||||
|
||||
## 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…
|
||||
|
||||
**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.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
extern double atof();
|
||||
extern double strtod();
|
||||
extern long int strtol();
|
||||
extern int atoi();
|
||||
extern int atexit();
|
||||
/* D324: getenv was previously declared only on non-Windows, on the (wrong)
|
||||
* assumption that MinGW's other CRT headers leak a prototype -- config.c gets
|
||||
|
||||
+15
-3
@@ -589,7 +589,8 @@ static void inputOpenPads(void)
|
||||
#define INPUTSCRIPT_PULSE 6
|
||||
|
||||
struct scriptEntry { long frame; unsigned mask; int sx, sy; int hasStick;
|
||||
int hasMouse, mdx, mdy; int hasHold, hold; }; /* D337 mouse/aim tokens */
|
||||
int hasMouse, mdx, mdy; int hasHold, hold; /* D337 mouse/aim tokens */
|
||||
int hasZHold, zhold; }; /* D207: sustained fire */
|
||||
static struct scriptEntry scriptEntries[INPUTSCRIPT_MAX];
|
||||
static int scriptCount = -1; /* -1 = not parsed yet, 0 = parsed empty */
|
||||
static long scriptFrame = 0;
|
||||
@@ -626,6 +627,10 @@ static void scriptApplyToken(struct scriptEntry *e, const char *s, int n)
|
||||
if (n == 5 && SDL_strncasecmp("RHOLD", s, 5) == 0) { e->hasHold = 1; e->hold = 1; return; }
|
||||
if (n == 5 && SDL_strncasecmp("LHOLD", s, 5) == 0) { e->hasHold = 1; e->hold = 2; return; }
|
||||
if (n == 4 && SDL_strncasecmp("RREL", s, 4) == 0) { e->hasHold = 1; e->hold = 0; return; }
|
||||
/* D207: ZHOLD / ZREL hold / release fire (Z) for automatic weapons;
|
||||
* independent of RHOLD so aim + fire can be held together. */
|
||||
if (n == 5 && SDL_strncasecmp("ZHOLD", s, 5) == 0) { e->hasZHold = 1; e->zhold = 1; return; }
|
||||
if (n == 4 && SDL_strncasecmp("ZREL", s, 4) == 0) { e->hasZHold = 1; e->zhold = 0; return; }
|
||||
e->hasStick = 1;
|
||||
if (n == 3 && SDL_strncasecmp("SUP", s, 3) == 0) { e->sy = STICK_MAX; return; }
|
||||
if (n == 5 && SDL_strncasecmp("SDOWN", s, 5) == 0) { e->sy = -STICK_MAX; return; }
|
||||
@@ -659,6 +664,7 @@ static void scriptParse(void)
|
||||
e->hasStick = 0;
|
||||
e->hasMouse = e->mdx = e->mdy = 0;
|
||||
e->hasHold = e->hold = 0;
|
||||
e->hasZHold = e->zhold = 0;
|
||||
while (*p && *p != ';') {
|
||||
const char *tok = p;
|
||||
while (*p && *p != ',' && *p != ';') ++p;
|
||||
@@ -686,10 +692,10 @@ static int scriptIsActive(void)
|
||||
* Returns the scripted button mask for the current frame; advances the frame
|
||||
* counter (call exactly once per controller-0 read). */
|
||||
/* D337: current sustained scripted mouse delta / aim hold (latest entry). */
|
||||
static int s_scriptMouseOn = 0, s_scriptMDX = 0, s_scriptMDY = 0, s_scriptHold = 0;
|
||||
static int s_scriptMouseOn = 0, s_scriptMDX = 0, s_scriptMDY = 0, s_scriptHold = 0, s_scriptZHold = 0;
|
||||
static void scriptPreMouse(void)
|
||||
{
|
||||
long bestM = -1, bestH = -1;
|
||||
long bestM = -1, bestH = -1, bestZ = -1;
|
||||
for (int i = 0; i < scriptCount; ++i) {
|
||||
long d = scriptFrame - scriptEntries[i].frame;
|
||||
if (d < 0) continue;
|
||||
@@ -703,6 +709,10 @@ static void scriptPreMouse(void)
|
||||
bestH = scriptEntries[i].frame;
|
||||
s_scriptHold = scriptEntries[i].hold;
|
||||
}
|
||||
if (scriptEntries[i].hasZHold && scriptEntries[i].frame > bestZ) {
|
||||
bestZ = scriptEntries[i].frame;
|
||||
s_scriptZHold = scriptEntries[i].zhold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,6 +721,7 @@ static unsigned scriptApply(unsigned button)
|
||||
if (!scriptIsActive()) {
|
||||
return button;
|
||||
}
|
||||
scriptPreMouse(); /* D207: refresh sustained holds even off the mouse path (idempotent) */
|
||||
unsigned m = 0;
|
||||
long bestStickFrame = -1;
|
||||
for (int i = 0; i < scriptCount; ++i) {
|
||||
@@ -727,6 +738,7 @@ static unsigned scriptApply(unsigned button)
|
||||
}
|
||||
if (s_scriptHold == 1) m |= GE_CONT_R; /* D337 RHOLD */
|
||||
if (s_scriptHold == 2) m |= GE_CONT_L; /* D337 LHOLD (Q / "LeanLeft") */
|
||||
if (s_scriptZHold) m |= GE_CONT_G; /* D207 ZHOLD (fire) */
|
||||
scriptFrame++;
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,11 @@
|
||||
#include "optionsoverlay.h"
|
||||
#include "../fast3d/gfx_api.h"
|
||||
|
||||
/* D324 class: -Iinclude resolves <math.h> to GE's N64 stub, which does not
|
||||
* declare lround; without this the call is an implicit `int lround()`
|
||||
* (GCC only rescued it via its builtin signature). */
|
||||
long lround(double x);
|
||||
|
||||
/* ---- game symbols (rendering/UI only; see input.c for the same pattern) ---- */
|
||||
struct font;
|
||||
struct fontchar;
|
||||
|
||||
Reference in new issue
Block a user