mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
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).
This commit is contained in:
1 parent
c2c6fbdd68
commit
40ef53e395
5 files changed
+160
-3
No files matched your search
@@ -247,3 +247,4 @@ D367,?,F10 full-width control boxes misaligned with their contents (2026-09-27).
|
||||
D368,?,Simplify F10 click targets:,"INPUT RULE KEPT; tinted strips user-rejected, removed in D369."
|
||||
D369,FIXED,Remove F10 row boxes/strips entirely (2026-09-27).,FIXED (awaiting live acceptance):
|
||||
D370,PARTIAL,F10 distance/volume drags hurt frame rate (2026-09-27).,PARTIAL (user live test):
|
||||
D371,FIXED,"GEPD key-layout preset + reload/crouch bindings, v0.4.0 modern options wave M3 (2026-09-27).",FIXED (headless-verified; awaiting user live accept):
|
||||
|
@@ -655,6 +655,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
||||
| D368 | **Simplify F10 click targets: setting name selects, the rest changes (2026-09-27).** — full `## D368` entry at file tail | INPUT RULE KEPT; tinted strips user-rejected, removed in D369. |
|
||||
| D369 | **Remove F10 row boxes/strips entirely (2026-09-27).** — full `## D369` entry at file tail | FIXED (awaiting live acceptance): no row backgrounds, control rectangles or hover paint; selected setting distinguished by brighter text, slider tracks remain. Input rule from D368 unchanged. |
|
||||
| D370 | **F10 distance/volume drags hurt frame rate (2026-09-27).** — full `## D370` entry at file tail | PARTIAL (user live test): mostly improved; rapid spam can still lower FPS. Unchanged-detent/audio and Draw/LOD reapply fixed; other image sliders still request full video pass (live log shows frequent FOV passes). No further churn without focused repro. |
|
||||
| D371 | **GEPD key-layout preset + reload/crouch bindings, v0.4.0 modern options wave M3 (2026-09-27).** full `## D371` entry at file tail | FIXED (headless-verified; awaiting user live accept): `Input.Layout` (0=FPS, 1=GEPD) + `Input.CrouchMode` (hold/toggle) in F10 INPUT; GEPD preset acts as per-key effective default under `[Input.Bind]` overrides; new IA_RELOAD/IA_CROUCH emit B (unbound by default). MODERN section dropped per D356 Turok-standard rule (rows land in functional INPUT). Boot/ini-round-trip/F10-page verified; in-game feel-check owed. |
|
||||
|
||||
Phase 2 replaced the Phase-1 demo loop with the real `mainproc()` on real OS
|
||||
threads, compiled GE's real `src/sched.c`, and brought in PD's fast3d software
|
||||
@@ -14309,3 +14310,50 @@ Residual not isolated: the latest playtest log shows repeated full video
|
||||
config passes while changing FOV (not Draw/LOD) and several watch EEPROM
|
||||
persists; sustained high Draw/LOD also increases actual GPU work. Parked as
|
||||
polish until a focused repro identifies which slider/spam pattern dominates.
|
||||
|
||||
## D371 — GEPD key-layout preset + reload/crouch bindings (v0.4.0 modern options wave, M3) (2026-09-27)
|
||||
|
||||
**Spec:** `docs/dev/notes/MODERN-OPTIONS-PLAN.md` M3. **Deviation from plan
|
||||
(user decision, 2026-09-27):** the planned "MODERN" F10 section is DROPPED —
|
||||
it is a provenance bucket, not a functional category, which conflicts with
|
||||
the D356 Turok-standard "every section is functional, baseline names" rule
|
||||
(the same rule that retired the D353 BOND FILE section). The rows land in
|
||||
the functional section (INPUT); no new category, no `__ResetModern` — the
|
||||
existing per-section reset rows cover the new keys via `kResetDefaults`.
|
||||
|
||||
**Implementation (port-only; `port/src/input.c`, `port/include/input.h`,
|
||||
`port/src/optionsoverlay.c`):**
|
||||
- New actions `IA_RELOAD` / `IA_CROUCH` (emits `GE_CONT_B` both; on N64 the
|
||||
single B button does reload-tap vs crouch-hold, and the game's own
|
||||
`bond_interact_object` context logic makes that choice — so the port
|
||||
emits B and leaves the decision to the game, as on the N64). Defaults are
|
||||
empty strings = unbound (byte-identical N64 layout out of the box).
|
||||
- `Input.Layout` (0 = FPS defaults, 1 = GEPD) + `Input.CrouchMode`
|
||||
(0 = hold, 1 = toggle/latched). The GEPD preset
|
||||
(GEPORT-REFERENCE-DEEPDIVE.md section 7.3: Action=Q, Cancel=E, Reload=R,
|
||||
Crouch=Left Ctrl, Fire="" — LMB fires/RMB aims, LeanLeft="" — lean is
|
||||
GEPD-removed) acts as the EFFECTIVE DEFAULT only for actions the user has
|
||||
not individually overridden in `[Input.Bind]`; per-key ini values layer
|
||||
on top, so switching layouts never clobbers explicit binds. Revert =
|
||||
switching back.
|
||||
- Toggle crouch latches B; the latch is dropped on entering a menu (a
|
||||
latched B would read as back/cancel) and on `inputLayoutApply()`.
|
||||
- F10 rows: "Key layout" (kKeyLayout) + "Crouch mode" (reuses kHold) under
|
||||
INPUT, before its reset row.
|
||||
- `inputRebuildBinds`: an intentionally-empty string no longer logs the
|
||||
"action unbound" warning; only a NON-empty string that yields no valid
|
||||
keys warns (D214's warning was written when no default was ever empty).
|
||||
- `optionsoverlay.c` `rowSetCommit` hook: `Input.Layout` /
|
||||
`Input.CrouchMode` -> `inputLayoutApply()` (scheduler thread; a mid-poll
|
||||
rebuild can at worst drop/add one scancode for one frame — the D214
|
||||
thread-pairing, just at F10 commit time instead of boot).
|
||||
|
||||
**Verification:** NTSC build clean. GEPD boot (`Layout=1`, `CrouchMode=1`,
|
||||
`Bind.Reload=R`, `Bind.Crouch=Left Ctrl`): no crash, no spurious warnings.
|
||||
ini round-trip via orderly `GE_QUITFRAME` exit: `Layout`/`CrouchMode`
|
||||
persist under `[Input]`; `Reload`/`Crouch` under `[Input.Bind]` (config.c
|
||||
`splitKey` splits on the LAST dot — pre-existing D214 behaviour, binds were
|
||||
always saved there with bare leaf names). F10 INPUT page
|
||||
(`GE_OPTIONSOVERLAY=2`) boots clean, both rows resolve. **Owed:** live F10
|
||||
layout-switch feel-check (GEPD vs FPS), in-game crouch toggle/reload B
|
||||
semantics + menu-latch-reset, PAL/JP.
|
||||
@@ -68,6 +68,11 @@ short inputPadAxis(int idx, SDL_GameControllerAxis a);
|
||||
* ignored -- GE only cycles forward on a bare A edge. */
|
||||
void inputPostWheel(int notches);
|
||||
|
||||
/* v0.4.0 M3: re-derive the keyboard binds after an F10 change to
|
||||
* Input.Layout / Input.CrouchMode (optionsoverlay rowSetCommit hook).
|
||||
* Also drops the latched-crouch state. Scheduler thread only. */
|
||||
void inputLayoutApply(void);
|
||||
|
||||
/* D345(b): 1 while the 1:1 menu pointer owns cursor_h/v_pos (in a menu,
|
||||
* abs pointer available, mouse used within the re-assert window). Port
|
||||
* screens that teleport the crosshair should skip their snap when set. */
|
||||
|
||||
+77
-3
@@ -868,7 +868,12 @@ static int keyDown(const Uint8 *ks, SDL_Scancode sc)
|
||||
* ---------------------------------------------------------------------- */
|
||||
enum {
|
||||
IA_FORWARD, IA_BACK, IA_STRAFE_L, IA_STRAFE_R, IA_TURN_L, IA_TURN_R,
|
||||
IA_FIRE, IA_AIM, IA_ACTION, IA_CANCEL, IA_LEAN_L, IA_START, IA_COUNT
|
||||
IA_FIRE, IA_AIM, IA_ACTION, IA_CANCEL, IA_LEAN_L, IA_START,
|
||||
/* v0.4.0 M3 (modern options wave): GEPD-layout actions. Both map to
|
||||
* the N64 B button -- the game's own B-context logic
|
||||
* (bond_interact_object) picks reload (tap, gun in hand, no
|
||||
* interact target) vs crouch (held) exactly as on the N64. */
|
||||
IA_RELOAD, IA_CROUCH, IA_COUNT
|
||||
};
|
||||
|
||||
static const struct { const char *key; const char *def; } kBindDefs[IA_COUNT] = {
|
||||
@@ -884,8 +889,30 @@ static const struct { const char *key; const char *def; } kBindDefs[IA_COUNT] =
|
||||
[IA_CANCEL] = { "Input.Bind.Cancel", "X,R,F,Escape" },
|
||||
[IA_LEAN_L] = { "Input.Bind.LeanLeft", "Q" },
|
||||
[IA_START] = { "Input.Bind.Start", "Return,Tab" },
|
||||
[IA_RELOAD] = { "Input.Bind.Reload", "" },
|
||||
[IA_CROUCH] = { "Input.Bind.Crouch", "" },
|
||||
};
|
||||
|
||||
/* v0.4.0 M3: GEPD key-layout preset (docs/dev/notes/GEPORT-REFERENCE-
|
||||
* DEEPDIVE.md section 7.3). The preset is the EFFECTIVE DEFAULT for any action
|
||||
* the user has not overridden per-key in [Bind]; a per-key ini value
|
||||
* layers on top, so switching layouts never clobbers explicit binds.
|
||||
* Fire loses its Left Ctrl key in this layout (LMB fires, RMB aims;
|
||||
* Ctrl becomes crouch); LeanLeft is unbound (lean is GEPD-removed).
|
||||
* NULL entries keep the FPS default. */
|
||||
static const char *const kGepdPreset[IA_COUNT] = {
|
||||
[IA_FIRE] = "",
|
||||
[IA_ACTION] = "Q",
|
||||
[IA_CANCEL] = "E",
|
||||
[IA_LEAN_L] = "",
|
||||
[IA_RELOAD] = "R",
|
||||
[IA_CROUCH] = "Left Ctrl",
|
||||
};
|
||||
static int keyLayout = 0; /* 0 = FPS defaults, 1 = GEPD preset */
|
||||
static int crouchMode = 0; /* 0 = hold, 1 = toggle (latched B) */
|
||||
static int s_crouchLatch = 0;
|
||||
static int s_crouchHeldPrev = 0;
|
||||
|
||||
#define BIND_MAX_KEYS 4
|
||||
static char g_bindStr[IA_COUNT][64];
|
||||
static SDL_Scancode g_bind[IA_COUNT][BIND_MAX_KEYS];
|
||||
@@ -896,9 +923,18 @@ static void inputRebuildBinds(void)
|
||||
for (int k = 0; k < BIND_MAX_KEYS; k++) {
|
||||
g_bind[a][k] = SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
/* v0.4.0 M3: the GEPD preset fills the actions the user has not
|
||||
* individually overridden (empty g_bindStr); FPS layout = the
|
||||
* kBindDefs defaults, byte-identical to the pre-wave binds. */
|
||||
const char *def = kBindDefs[a].def;
|
||||
if (keyLayout == 1) {
|
||||
const char *preset = kGepdPreset[a];
|
||||
if (preset) def = preset;
|
||||
}
|
||||
char buf[64];
|
||||
strncpy(buf, g_bindStr[a][0] ? g_bindStr[a] : kBindDefs[a].def, sizeof(buf) - 1);
|
||||
strncpy(buf, g_bindStr[a][0] ? g_bindStr[a] : def, sizeof(buf) - 1);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
int hadInput = (buf[0] != 0); /* before strtok clobbers buf */
|
||||
|
||||
int n = 0;
|
||||
for (char *tok = strtok(buf, ","); tok && n < BIND_MAX_KEYS; tok = strtok(NULL, ",")) {
|
||||
@@ -914,13 +950,32 @@ static void inputRebuildBinds(void)
|
||||
}
|
||||
g_bind[a][n++] = sc;
|
||||
}
|
||||
if (n == 0) {
|
||||
/* v0.4.0 M3: an intentionally-empty string (a preset or default
|
||||
* that leaves an action unbound, e.g. GEPD Fire) is silent --
|
||||
* only a non-empty string that produced no valid keys warns. */
|
||||
if (n == 0 && hadInput) {
|
||||
sysLogPrintf(LOG_WARNING, "input: %s has no valid keys; action unbound",
|
||||
kBindDefs[a].key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* v0.4.0 M3: re-derive the binds after an F10 change to Input.Layout /
|
||||
* Input.CrouchMode (optionsoverlay rowSetCommit hook, scheduler thread).
|
||||
* g_bind is read per-frame by the game thread's actHeld(): a mid-poll
|
||||
* rebuild can at worst drop or add one scancode for one frame (the
|
||||
* D214 startup-rebuild is the same thread-pairing, just at boot).
|
||||
* Also drops the crouch latch so a latched crouch never carries B into
|
||||
* a menu (where B = back/cancel). */
|
||||
void inputLayoutApply(void)
|
||||
{
|
||||
s_crouchLatch = 0;
|
||||
s_crouchHeldPrev = 0;
|
||||
inputRebuildBinds();
|
||||
sysLogPrintf(LOG_INFO, "input: key layout %s, crouch %s applied",
|
||||
keyLayout ? "GEPD" : "FPS", crouchMode ? "toggle" : "hold");
|
||||
}
|
||||
|
||||
static int actHeld(const Uint8 *ks, int act)
|
||||
{
|
||||
for (int k = 0; k < BIND_MAX_KEYS; k++) {
|
||||
@@ -1126,6 +1181,21 @@ unsigned inputComputePad(int idx, signed char *stick_x, signed char *stick_y)
|
||||
}
|
||||
if (actHeld(ks, IA_CANCEL)) /* D145: Escape is in the default Cancel bind */
|
||||
button |= GE_CONT_B;
|
||||
/* v0.4.0 M3: reload (B tap, same as any B press) and crouch
|
||||
* (hold, or a latched toggle). Both are unbound by default (the
|
||||
* N64-original layout), so this is a no-op out of the box; the
|
||||
* game's B-context logic decides reload-vs-crouch as on N64. */
|
||||
if (actHeld(ks, IA_RELOAD))
|
||||
button |= GE_CONT_B;
|
||||
int crouchNow = actHeld(ks, IA_CROUCH);
|
||||
if (crouchMode == 1) {
|
||||
if (crouchNow && !s_crouchHeldPrev) s_crouchLatch ^= 1;
|
||||
if (menuMode) s_crouchLatch = 0; /* never carry B into a menu */
|
||||
if (s_crouchLatch) button |= GE_CONT_B;
|
||||
s_crouchHeldPrev = crouchNow;
|
||||
} else if (crouchNow) {
|
||||
button |= GE_CONT_B;
|
||||
}
|
||||
if (actHeld(ks, IA_LEAN_L))
|
||||
button |= GE_CONT_L;
|
||||
if (actHeld(ks, IA_START))
|
||||
@@ -1998,6 +2068,10 @@ PD_CONSTRUCTOR static void inputConfigInit(void)
|
||||
configRegisterInt("Input.PadDeadzone", &padDeadzone, 0, 30000);
|
||||
configRegisterInt("Input.PadTriggerPct", &padTriggerPct, 1, 99);
|
||||
configRegisterInt("Input.PadLookInvertY", &padLookInvertY, 0, 1);
|
||||
/* v0.4.0 M3 (modern options wave): key-layout preset + crouch bind
|
||||
* mode; both default to the N64-original FPS layout / hold. */
|
||||
configRegisterInt("Input.Layout", &keyLayout, 0, 1);
|
||||
configRegisterInt("Input.CrouchMode", &crouchMode, 0, 1);
|
||||
|
||||
/* D214: keyboard rebinding. Seed each buffer with its default so the knob
|
||||
* is visible/editable in a fresh ge007.ini; configLoad() overwrites any the
|
||||
|
||||
@@ -91,6 +91,17 @@ static const char *const kTexFilter[] = { "Nearest", "Bilinear", "3-Point", NULL
|
||||
static const char *const kAimMode[] = { "N64", "Centred (PC)", NULL }; /* D337 */
|
||||
static const char *const kAimRange[] = { "PC", "N64", NULL }; /* D338 */
|
||||
static const int kMsaaSeq[] = { 1, 2, 4, 8 };
|
||||
/* v0.4.0 modern options wave: value names for the new rows (they land
|
||||
* in the functional sections -- Turok standard, D356 -- not a bucket). */
|
||||
static const char *const kOnOffRev[] = { "On", "Off", NULL }; /* 0 = On */
|
||||
/* M2: named crosshair tints; index 0 = the N64 white (no tint applied). */
|
||||
static const char *const kCrosshairColor[] = {
|
||||
"White", "Green", "Red", "Blue", "Yellow", "Cyan", "Magenta",
|
||||
NULL,
|
||||
};
|
||||
/* M3: key-layout preset (0 = the FPS default binds, byte-identical to the
|
||||
* current defaults; 1 = the GEPD mouse-injector layout) + crouch bind mode */
|
||||
static const char *const kKeyLayout[] = { "FPS (default)", "GEPD", NULL };
|
||||
/* D186: the sim's own tick pacemaker is hardcoded to the console's native VI
|
||||
* rate (60Hz NTSC / 50Hz PAL, port/src/libultra.c) -- Video.FpsCap can only
|
||||
* throttle down from there, never past it, and throttling it below 30
|
||||
@@ -190,6 +201,13 @@ static struct Row rows[] = {
|
||||
{ .key="Input.PadLookInvertY", .label="Invert look (controller)", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="Input.PadDeadzone", .label="Stick deadzone", .kind=ROW_SLIDER, .step=500 },
|
||||
{ .key="Input.PadTriggerPct", .label="Trigger threshold", .kind=ROW_SLIDER, .step=1 },
|
||||
/* v0.4.0 M3 (modern options wave, D371): the GEPD mouse-injector
|
||||
* key-layout preset (docs/dev/notes/GEPORT-REFERENCE-DEEPDIVE.md
|
||||
* section 7.3) + the crouch bind's fire mode. Turok standard: these are
|
||||
* control bindings, so they live in INPUT -- no provenance bucket.
|
||||
* Defaults are the N64-original FPS layout / hold. */
|
||||
{ .key="Input.Layout", .label="Key layout", .kind=ROW_ENUM, .step=1, .names=kKeyLayout },
|
||||
{ .key="Input.CrouchMode", .label="Crouch mode", .kind=ROW_ENUM, .step=1, .names=kHold },
|
||||
{ .key="__ResetInput", .label="Reset to defaults", .kind=ROW_ACTION },
|
||||
|
||||
{ .key="__HdrGameplay", .label="GAMEPLAY", .kind=ROW_HEADER },
|
||||
@@ -726,6 +744,15 @@ static void rowSetCommit(struct Row *r, double v, int commit)
|
||||
videoRequestLiveConfig();
|
||||
}
|
||||
|
||||
/* v0.4.0 M3: key-layout preset / crouch mode -- re-derive the binds
|
||||
* (inputRebuildBinds via inputLayoutApply; also drops the crouch latch).
|
||||
* Safe at scheduler-thread commit time; a mid-poll rebuild can only
|
||||
* drop/add one scancode for one frame (D214 thread-pairing). */
|
||||
if (strcmp(r->key, "Input.Layout") == 0 ||
|
||||
strcmp(r->key, "Input.CrouchMode") == 0) {
|
||||
inputLayoutApply();
|
||||
}
|
||||
|
||||
/* Linked aim/turn sensitivity (Input.SensLink, default on): moving either
|
||||
* knob scales the other to hold the stock default ratio -- AimModeSens 38
|
||||
* : MouseTurnSpeed 50 (the D194/D238 calibrated defaults). */
|
||||
@@ -871,6 +898,8 @@ static const struct { const char *key; double def; } kResetDefaults[] = {
|
||||
{ "Input.PadLookInvertY", 0 }, /* = 0 */
|
||||
{ "Input.PadDeadzone", 7000 },/* = STICK_DEADZONE (7000) */
|
||||
{ "Input.PadTriggerPct", 23 }, /* = 23 */
|
||||
{ "Input.Layout", 0 }, /* = 0 (FPS defaults) */
|
||||
{ "Input.CrouchMode", 0 }, /* = 0 (hold) */
|
||||
/* GRAPHICS (port/src/video.c initializers) */
|
||||
{ "Video.MSAA", 2 }, /* = 2 */
|
||||
{ "Video.TextureFilter", 1 }, /* = 1 (bilinear) */
|
||||
|
||||
Reference in new issue
Block a user