forked from Ports/goldeneye-pc-port
optionsoverlay.c: Turok-style regroup - DISPLAY/GRAPHICS split, BOND FILE absorbs music/FX, designated rows, overflow log, file-scope title annotation (D353)
This commit is contained in:
1 parent
8e9bee6ef0
commit
462675cf47
6 files changed
+98
-35
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# Watch-backed settings in PC Options and F10 — proposal for review
|
||||
|
||||
Status: **watch-backed subset implemented (D350), headless-verified; maintainer reports tests good, detailed review requested next session.** Wider M3 remains outstanding. PC-only per-file persistence and explicit Bond-file chooser approved; details below. See `docs/dev/findings.md` D350 for verification and D351 for a pre-existing row initializer fix. This is the watch-integration part of M3, not a replacement for the native watch menu. The older tracked `docs/dev/OPTIONS-MENU-PLAN.md` and local `docs/dev/notes/OPTIONS-MENU-PLAN.md` describe the wider M3 scope (master volume, window mode/display, resets).
|
||||
Status: **watch-backed subset implemented (D350), robustness fixes landed (D352: transition hold-not-drop, chooser spinlock, queue coalescing, warning logs), and the Turok-style regrouping is done (D353: DISPLAY/GRAPHICS split, BOND FILE absorbs the music/FX sliders, designated rows, overflow guard, file-scope title annotation).** Wider M3 remains outstanding: master volume, window-mode/display rows, per-section reset (Gate E), key rebinding. PC-only per-file persistence and explicit Bond-file chooser approved; details below. See `docs/dev/findings.md` D350–D353 for verification. This is the watch-integration part of M3, not a replacement for the native watch menu. The older tracked `docs/dev/OPTIONS-MENU-PLAN.md` and local `docs/dev/notes/OPTIONS-MENU-PLAN.md` describe the wider M3 scope (master volume, window mode/display, resets).
|
||||
|
||||
## Goal and ownership
|
||||
|
||||
@@ -39,7 +39,7 @@ Thus a front-end row that edits only live watch state will be silently undone be
|
||||
## Sequence / review gates
|
||||
|
||||
- **Gate A — behavior audit + D349:** re-verify the erase-only write and stage-start reload (including indirect save paths); record the ground-truth quirk, defaults, stored control-type preservation, erase cross-file edge and exact API for each row. Trace folder-to-physical-slot mapping, FX/music setter readiness, watch-to-gameplay consumers, composed inversion and the F10/game-thread boundary. Approved policy: explicit chooser + PC-UI edits persist; watch edits remain session-only.
|
||||
- **Gate B — foundation: IMPLEMENTED in D350**, including explicit file chooser, CRC guard, stage/file identity and thread-safe F10 command/snapshot path. Manual gamepad/mouse playtest still owed.
|
||||
- **Gate B — foundation: IMPLEMENTED in D350**, including explicit file chooser, CRC guard, stage/file identity and thread-safe F10 command/snapshot path. D352 (review of `1303c0eb`) fixed the remaining robustness gaps: pending commands now survive stage transitions (hold-not-drop), the UI-thread chooser state is spinlocked with a front-screen guard, the queue coalesces to one pending command per field, and every silent no-op path logs a warning. Manual gamepad/mouse playtest still owed.
|
||||
- **Gate C — audio: ROWS IMPLEMENTED in D350**, Music/FX save path headless-verified. Watch↔F10 live and audible checks still owed. Global master gain is a separate, not-yet-implemented M3 item.
|
||||
- **Gate D — watch gameplay: ROWS IMPLEMENTED in D350** for six GE watch booleans; auto-aim and watch look-bit per-file saves headless-verified. Each watch/in-game effect and two-file isolation still need hands-on checks. Screen/Ratio remain a separate product decision.
|
||||
- **Gate E — control style and resets:** design decisions first, then separate work. Avoid exposing a control-style row that the port immediately overwrites. Do not make a global reset wipe per-file watch settings.
|
||||
@@ -56,3 +56,4 @@ Thus a front-end row that edits only live watch state will be silently undone be
|
||||
|
||||
- **Approved:** PC-UI edits persist per selected Bond file; watch-only edits stay session-only. The front screen gets an explicit file chooser; F10 uses the active file. Preserve stored controller type; toggles/enums save on change, slider drags on release. No `src/game` behavior change or N64 save-format change.
|
||||
- **Still separate product decisions:** whether/how to expose GE Screen/Ratio alongside PC video settings; whether to expose control style at all given the port's forced mapping (deferred); whether Bond-file reset needs its own confirmation rather than being bundled with global PC defaults.
|
||||
- **Landed 2026-09-27 (D352/D353, port-only):** bridge robustness fixes (D352) and the Turok-style row-table regrouping (D353: six sections — DISPLAY, GRAPHICS, BOND FILE, MOUSE / AIM, CONTROLLER, GAME; the music/FX sliders sit in BOND FILE; the page title annotates the selected file; `buildPages` overflow logs). A standalone AUDIO section (master volume + the config-side volume keys) and per-section reset-to-defaults (Gate E) are the next settings-scope items; key rebinding stays Phase 4.
|
||||
@@ -230,3 +230,4 @@ D349,PARTIAL,GE watch settings are not normally saved to the Bond file:,ANALYZED
|
||||
D350,PARTIAL,Watch-backed PC options:,"PARTIAL (implemented; user reports tests good, review pending):"
|
||||
D351,FIXED,Existing D346 value/unit rows had positional initializers shifted into hidePtr:,"FIXED (port-only): designated row initializers restore unit, deadzone divisor and hide-if-auto fields; build clean, headless smoke clean."
|
||||
D352,FIXED,D350 review of 1303c0eb:,"FIXED (port-only, port/src/watchsettings.c):"
|
||||
D353,FIXED,Turok-style settings regrouping:,"FIXED (port-only, optionsoverlay.c/frontoptions.c):"
|
||||
|
@@ -638,6 +638,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
||||
| D350 | **Watch-backed PC options: shared front/F10 Bond-file rows, explicit chooser, game-thread F10 bridge and field-scoped PC-only persistence.** — full `## D350` entry at file tail | PARTIAL (implemented; user reports tests good, review pending): headless front + F10 write/reload probes, NTSC build/golden 3/3, save CRC/control-style preserved; two-file targeting checked. Detailed edge-case coverage not specified by user. |
|
||||
| D351 | **Existing D346 value/unit rows had positional initializers shifted into `hidePtr`: %/x rows hidden or formatted without units.** — full `## D351` entry at file tail | FIXED (port-only): designated row initializers restore unit, deadzone divisor and hide-if-auto fields; build clean, headless smoke clean. Manual settings visual check owed. |
|
||||
| D352 | **D350 review of 1303c0eb: stage transitions silently drop queued F10 setting changes (queue drained before the `stageActive` check); the UI thread's chooser state is unsynchronized; rapid slider drags push one RSP command per detent and re-persist the same value each frame; persist failures are silent (2026-09-27).** — full `## D352` entry at file tail | FIXED (port-only, `port/src/watchsettings.c`): hold-not-drop at stage transitions, spinlock on chooser state + front-screen guard, per-field coalesced queue commits, warning logs on all no-op paths, `PersistField` made static. NTSC build clean, headless menu smoke clean. |
|
||||
| D353 | **Turok-style settings regrouping: the D346 VIDEO mega-section (14–15 rows, at the MAX_PROWS limit) re-split into DISPLAY + GRAPHICS, the "AUDIO (BOND FILE)" hack header dropped (music/FX sliders fold into BOND FILE), all remaining rows converted to designated initializers, `buildPages` overflow now logs, and the Bond-file page title annotates the selected file (2026-09-27).** — full `## D353` entry at file tail | FIXED (port-only, `optionsoverlay.c`/`frontoptions.c`): 6 sections of 3–11 rows, all rows designated-initialized, `optionsRowIsBondChooser` accessor, build clean + headless smoke clean. Master-volume row, per-section reset (Gate E) and key rebinding remain in the M3 backlog. |
|
||||
|
||||
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
|
||||
@@ -13806,3 +13807,15 @@ Design review of `1303c0eb` (D350) of the game-thread bridge in `port/src/watchs
|
||||
4. **L3/L6 — visible failures, smaller API.** Every silent no-op path now logs a one-line `LOG_WARNING` (`frontoptions`/`watchSettings`-tagged): stage transition holding the queue (rate-limited by the coalescing), front-path commit with nothing staged, F10 commit with no valid save, no loaded player record, save absent from the EEPROM range. `watchSettingsPersistField` was only ever called inside `watchsettings.c` — made `static`, removed from the public header.
|
||||
|
||||
Verification: NTSC build clean (no new warnings in `watchsettings.c`), headless menu smoke boots to the front end and renders (frames advancing, EEPROM load). Edge cases (setting F10 during a level transition; rapid slider drag; committing with an invalid file) are log-visible but need a manual pass to confirm by eye.
|
||||
|
||||
## D353 — Turok-style settings regrouping: DISPLAY/GRAPHICS split, AUDIO(BOND FILE) header dropped, designated rows, overflow guard (2026-09-27)
|
||||
|
||||
The D346 "single Video section" compromise (14–15 rows, exactly at `MAX_PROWS=15`) is re-grouped along the Turok/Nightdive menu axes (per `docs/dev/notes/OPTIONS-MENU-PLAN.md` §6), all port-side, no config-key renames:
|
||||
|
||||
- **VIDEO → DISPLAY + GRAPHICS.** DISPLAY: fullscreen, resolution, vsync, frame-rate cap (the window-management block Turok's "Video" panel covers). GRAPHICS: MSAA, texture filter, anisotropy, FOV scale, native widescreen, auto-FOV pair, overscan crop, the two draw/LOD-distance sliders and their auto-FOV hide-ifs. 4 + 11 rows, both well under the page limit.
|
||||
- **"AUDIO (BOND FILE)" hack header dropped.** The music/FX sliders now sit under the BOND FILE section, next to the other persisted-per-file watch rows — the section is exactly the per-file save, so the parenthetical header is redundant. No standalone master-volume row yet (that is the M3 addition, which will land in a future AUDIO section alongside the config-side volume keys).
|
||||
- **Scope annotation.** The Bond-file page title carries the chooser's value ("Game\n(File 2)" / "(no file)" in dim ink), so a player navigating from the front end sees which save the section writes without scrolling to the "Edit file" row. `frontoptions.c` level-1 draw only; F10 shows the chooser row inline (its value already there) so no annotation is needed.
|
||||
- **Full designated-initializer conversion.** The remaining positional `struct Row` entries (all of them) are now designated, per the D351 policy: new fields (like `found`) can never silently shift a value into the wrong member again. Keys, labels, clamps, steps, names, hide-ifs, units are all carried over unchanged — this is a display-only regroup, no value or config-key change.
|
||||
- **Overflow guard + accessor.** `buildPages` logs a `LOG_WARNING` naming the section and the last visible row if a section ever outgrows `MAX_PROWS` (the D346 VIDEO section truncated silently at exactly 15 rows before this); `optionsRowIsBondChooser()` is exported so the front-end title annotation and future F10 code can find the chooser row by role instead of index.
|
||||
|
||||
Section order: DISPLAY, GRAPHICS, BOND FILE, MOUSE / AIM, CONTROLLER, GAME (6 sections, under `MAX_PAGES=8`). Per-section "reset to defaults" (Gate E) and the §6-missing master-volume row remain outstanding. Verification: NTSC build clean, headless menu smoke boots to the front end; the regrouped page flow (arrows through 6 pages, annotation visible, no overflow log) needs a manual visual pass.
|
||||
@@ -51,6 +51,7 @@ int optionsRowIsHeader(int i);
|
||||
int optionsRowIsShown(int i);
|
||||
const char *optionsRowLabel(int i);
|
||||
int optionsRowIsSlider(int i);
|
||||
int optionsRowIsBondChooser(int i); /* D353: the Bond-file chooser row */
|
||||
int optionsRowNeedsRestart(int i);
|
||||
double optionsRowFraction(int i);
|
||||
void optionsRowSetFraction(int i, double f);
|
||||
|
||||
+38
-5
@@ -69,10 +69,11 @@ extern struct rectbbox folder_option_ERASE_bound; /* front.c:439 */
|
||||
#define TITLE_Y 0x2B
|
||||
#define ROW_X 0x37 /* the cheat list's x */
|
||||
#define ROW_Y0 0x41 /* cheat list starts 0x35; +12 for the title line */
|
||||
/* D346b: 20 -> 18 px so the merged Video section (14 rows default, 15 with
|
||||
* "Draw dist. follows FOV" off) fits the paper on one page. Hit bands stay
|
||||
* contiguous at any pitch >= 6; the 22px highlight box still clears the next
|
||||
* row (y+14 < y+17). */
|
||||
/* D346b: 20 -> 18 px so a full section fits the paper on one page. Hit bands
|
||||
* stay contiguous at any pitch >= 6; the 22px highlight box still clears the
|
||||
* next row (y+14 < y+17). D353: the largest section is now GRAPHICS at 11
|
||||
* rows (both auto-FOV toggles off); MAX_PROWS=15 keeps headroom, and
|
||||
* buildPages() logs any future overflow instead of silently truncating. */
|
||||
#define ROW_DY 18
|
||||
#define NUM_X 0x37 /* "1." on the section list */
|
||||
#define SEC_X 0x4B
|
||||
@@ -169,11 +170,22 @@ static void buildPages(void)
|
||||
}
|
||||
s_rowN = 0;
|
||||
if (s_pageN > 0) {
|
||||
int overflow = 0;
|
||||
for (int i = s_pageHdr[s_page] + 1; i < n && !optionsRowIsHeader(i); i++) {
|
||||
if (optionsRowIsShown(i) && s_rowN < MAX_PROWS) {
|
||||
if (!optionsRowIsShown(i)) continue;
|
||||
if (s_rowN < MAX_PROWS) {
|
||||
s_rowIdx[s_rowN++] = i;
|
||||
} else {
|
||||
overflow++;
|
||||
}
|
||||
}
|
||||
/* D353: the old code stopped at MAX_PROWS silently; a section that
|
||||
* outgrew the page (the D346b VIDEO section did, at exactly 15) lost
|
||||
* rows with no trace. */
|
||||
if (overflow)
|
||||
sysLogPrintf(LOG_WARNING, "frontoptions: section '%s' has %d row(s) past MAX_PROWS=%d; last visible: '%s'",
|
||||
optionsRowLabel(s_pageHdr[s_page]), overflow, MAX_PROWS,
|
||||
optionsRowLabel(s_rowIdx[MAX_PROWS - 1]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,9 +446,30 @@ Gfx *frontOptionsMenuDraw(Gfx *DL)
|
||||
} else {
|
||||
char title[32];
|
||||
titleCase(optionsRowLabel(s_pageHdr[s_page]), title, sizeof(title));
|
||||
int titleW = measureW(title);
|
||||
strcat(title, "\n");
|
||||
DL = ink(DL, ROW_X, TITLE_Y, title, INK);
|
||||
|
||||
/* D353: scope annotation -- the Bond-file section's title carries
|
||||
* the chooser's value ("(File 2)" / "(no file)"), so the player sees
|
||||
* which save the per-file toggles and sliders touch without scrolling
|
||||
* to the "Edit file" row. */
|
||||
{
|
||||
int bondRow = -1;
|
||||
for (int k = 0; k < s_rowN; k++) {
|
||||
if (optionsRowIsBondChooser(s_rowIdx[k])) { bondRow = k; break; }
|
||||
}
|
||||
if (bondRow >= 0) {
|
||||
char vt[32] = "", note[40];
|
||||
optionsRowValueText(s_rowIdx[bondRow], vt, sizeof(vt));
|
||||
if (vt[0] && strcmp(vt, "Select file") != 0)
|
||||
snprintf(note, sizeof(note), "(%s)", vt);
|
||||
else
|
||||
snprintf(note, sizeof(note), "(no file)");
|
||||
DL = ink(DL, ROW_X + titleW + 8, TITLE_Y, note, INK_DIM);
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < s_rowN; k++) {
|
||||
int i = s_rowIdx[k];
|
||||
int y = rowY(k);
|
||||
|
||||
+42
-28
@@ -142,27 +142,32 @@ struct Row {
|
||||
};
|
||||
|
||||
static struct Row rows[] = {
|
||||
{ "__HdrDisplay", "VIDEO", ROW_HEADER, 0, NULL, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Video.Fullscreen", "Fullscreen", ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "__Resolution", "Resolution", ROW_RES, 0, NULL, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Video.VSync", "VSync", ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Video.FpsCap", "Frame rate cap", ROW_FPSCAP, 0, NULL, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Video.MSAA", "Anti-aliasing", ROW_MSAA, 0, NULL, 1, 0, 0, 0,0,0,0,0 },
|
||||
{ "Video.TextureFilter", "Texture filter", ROW_ENUM, 1, kTexFilter, 0, 0, 0, 0,0,0,0,0 },
|
||||
/* D353: Turok-style regrouping. The D346b single 15-row VIDEO section
|
||||
* sat exactly at the front page's MAX_PROWS cap (a new row would have
|
||||
* been silently truncated). Split into DISPLAY (presentation) and
|
||||
* GRAPHICS (quality + distance); sections now top out at 11 rows
|
||||
* (GRAPHICS with both auto-FOV toggles off). All rows use designated
|
||||
* initializers (D351 class: positional shifts into hidePtr/unit). */
|
||||
{ .key="__HdrDisplay", .label="DISPLAY", .kind=ROW_HEADER },
|
||||
{ .key="Video.Fullscreen", .label="Fullscreen", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="__Resolution", .label="Resolution", .kind=ROW_RES },
|
||||
{ .key="Video.VSync", .label="VSync", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="Video.FpsCap", .label="Frame rate cap", .kind=ROW_FPSCAP },
|
||||
{ .key="__HdrGraphics", .label="GRAPHICS", .kind=ROW_HEADER },
|
||||
{ .key="Video.MSAA", .label="Anti-aliasing", .kind=ROW_MSAA, .restart=1 },
|
||||
{ .key="Video.TextureFilter", .label="Texture filter", .kind=ROW_ENUM, .step=1, .names=kTexFilter },
|
||||
{ .key="Video.Anisotropy", .label="Anisotropic filtering", .kind=ROW_SLIDER, .step=1, .unit="x" },
|
||||
/* D346b: the old VIEW section (FOV / widescreen / draw distance) is merged
|
||||
* into VIDEO -- one Nightdive-style "video" section; rows keep order. */
|
||||
{ .key="Video.FovScale", .label="FOV scale", .kind=ROW_SLIDER, .step=5, .unit="%" },
|
||||
/* D334: native widescreen (world projected at the window aspect, Hor+).
|
||||
* While on, "Widescreen auto FOV" has no effect (it was the stretch-era
|
||||
* vertical-FOV compensation). */
|
||||
{ "Video.NativeWidescreen", "Native widescreen",ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Video.WidescreenAuto", "Widescreen auto FOV",ROW_TOGGLE,1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Video.SafeAreaCrop", "Crop overscan", ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="Video.NativeWidescreen", .label="Native widescreen", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="Video.WidescreenAuto", .label="Widescreen auto FOV", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="Video.SafeAreaCrop", .label="Crop overscan", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="Video.DrawDistance", .label="Draw distance", .kind=ROW_SLIDER, .step=25, .hiddenIfOn="Video.DrawDistanceAutoFov", .unit="%" },
|
||||
{ "Video.DrawDistanceAutoFov","Draw dist. follows FOV",ROW_TOGGLE,1,kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="Video.DrawDistanceAutoFov", .label="Draw dist. follows FOV", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="Video.LodDistance", .label="LOD distance", .kind=ROW_SLIDER, .step=25, .hiddenIfOn="Video.LodDistanceAutoFov", .unit="%" },
|
||||
{ "Video.LodDistanceAutoFov", "LOD dist. follows FOV",ROW_TOGGLE,1,kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="Video.LodDistanceAutoFov", .label="LOD dist. follows FOV", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
/* Aim row edits Input.AimModeSens -- the knob the default GEPD aim path
|
||||
* actually uses (Input.MouseAimSpeed only feeds the legacy velocity-stick
|
||||
* fallback, so it was inert here). D304: both this row and the turn-speed
|
||||
@@ -206,14 +211,16 @@ static struct Row rows[] = {
|
||||
.names=kOnOff, .found=1, .uiMax=1, .cfgMax=1 },
|
||||
{ .key="Bond.Ammo", .label="Ammo on screen", .kind=ROW_TOGGLE,
|
||||
.names=kOnOff, .found=1, .uiMax=1, .cfgMax=1 },
|
||||
{ .key="__HdrBondAudio", .label="AUDIO (BOND FILE)", .kind=ROW_HEADER, .found=1 },
|
||||
/* D353: the separate "AUDIO (BOND FILE)" header is retired -- the two
|
||||
* sliders belong to the same per-file section as the watch toggles. A
|
||||
* port-level master volume (M3) will start a real AUDIO section. */
|
||||
{ .key="Bond.Music", .label="Music volume", .kind=ROW_SLIDER, .step=128,
|
||||
.uiMax=32767, .cfgMax=32767, .found=1, .unit="%", .dispDiv=328 },
|
||||
{ .key="Bond.FX", .label="FX volume", .kind=ROW_SLIDER, .step=128,
|
||||
.uiMax=32767, .cfgMax=32767, .found=1, .unit="%", .dispDiv=328 },
|
||||
{ "__HdrMouse", "MOUSE / AIM", ROW_HEADER, 0, NULL, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Input.MouseSensitivity", "Mouse sensitivity",ROW_SLIDER, 5, NULL, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Input.MouseInvertY", "Invert look (mouse)",ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="__HdrMouse", .label="MOUSE / AIM", .kind=ROW_HEADER },
|
||||
{ .key="Input.MouseSensitivity", .label="Mouse sensitivity", .kind=ROW_SLIDER, .step=5 },
|
||||
{ .key="Input.MouseInvertY", .label="Invert look (mouse)", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
/* Input.PdMouseAim (findings D332): the Perfect Dark port's mouse-aim
|
||||
* model. The port only accumulates the mouse; the game's own crosshair
|
||||
* integrator is driven by the port-supplied turn with PD's near-zero damp
|
||||
@@ -224,14 +231,14 @@ static struct Row rows[] = {
|
||||
* with the mouse fed through the game's integrator at PD's mouse damp --
|
||||
* the default. CENTRED (PC) = opt-in FPS-style aim (#104), not N64. Applies
|
||||
* to every aim input (RMB, Shift, Q/L, pad trigger, Toggle mode). */
|
||||
{ "Input.AimMode", "Aim style", ROW_ENUM, 1, kAimMode, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="Input.AimMode", .label="Aim style", .kind=ROW_ENUM, .step=1, .names=kAimMode },
|
||||
/* D338: how far the N64-style crosshair travels. PC = to the screen edge
|
||||
* (GEPD / mouse-injector feel, default); N64 = the original stick limits
|
||||
* (65% of the half-width, camera turn from ~49%). Hidden while the aim
|
||||
* style is CENTRED (PC), where the crosshair doesn't travel. */
|
||||
{ "Input.AimRange", "Aim range", ROW_ENUM, 1, kAimRange, 0, 0, 0, 0,0,0,0,0, "Input.AimMode" },
|
||||
{ "__HdrPad", "CONTROLLER", ROW_HEADER, 0, NULL, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Input.PadLookInvertY", "Invert look (controller)",ROW_TOGGLE,1,kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="Input.AimRange", .label="Aim range", .kind=ROW_ENUM, .step=1, .names=kAimRange, .hiddenIfOn="Input.AimMode" },
|
||||
{ .key="__HdrPad", .label="CONTROLLER", .kind=ROW_HEADER },
|
||||
{ .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, .unit="%", .dispDiv=300 },
|
||||
{ .key="Input.PadTriggerPct", .label="Trigger threshold", .kind=ROW_SLIDER, .step=1, .unit="%" },
|
||||
/* D181/Game.ScreenShakeIntensity: user testing (v0.2.1) found the slider
|
||||
@@ -243,13 +250,13 @@ static struct Row rows[] = {
|
||||
* hook stay in place. */
|
||||
/* D232: the community "no damage flash" toggle (suppresses the red/green
|
||||
* hit-flash overlay in bondview2). */
|
||||
{ "__HdrGame", "GAME", ROW_HEADER, 0, NULL, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="__HdrGame", .label="GAME", .kind=ROW_HEADER },
|
||||
/* D226: scales the ammo counter, pickup / status messages and dialogue
|
||||
* about their screen anchors. 100% = original, nothing emitted. */
|
||||
{ .key="Game.HudScale", .label="HUD scale", .kind=ROW_SLIDER, .step=5, .unit="%" },
|
||||
{ "Game.SkipIntro", "Skip intro", ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Video.DisplayFPS", "Show FPS", ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ "Game.NoHitFlash", "No hit flash", ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="Game.SkipIntro", .label="Skip intro", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="Video.DisplayFPS", .label="Show FPS", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
{ .key="Game.NoHitFlash", .label="No hit flash", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
/* D216/Game.SkipIntro: user report (v0.2.1 testing) that it breaks audio
|
||||
* -- pulled from the menu until root-caused. Not exposed to players; the
|
||||
* config var + lv.c hook stay in place (dead unless an existing ini has
|
||||
@@ -257,12 +264,12 @@ static struct Row rows[] = {
|
||||
* fixing the underlying issue first. */
|
||||
/* D257: everything-unlocked goodie (default ON). Consumed at startup by
|
||||
* main.c -- applies from the next launch. */
|
||||
{ "Game.AllUnlocked", "All unlocked", ROW_TOGGLE, 1, kOnOff, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="Game.AllUnlocked", .label="All unlocked", .kind=ROW_TOGGLE, .step=1, .names=kOnOff },
|
||||
/* D293: only quit path used to be the OS window-close / Alt+F4 -- no
|
||||
* discoverable in-game way to exit, a real gap on Deck/controller-only
|
||||
* setups. Not config-backed (like __Resolution); activating it exits
|
||||
* the same way video.c's SDL_QUIT/Alt+F4 handlers already do. */
|
||||
{ "__QuitToDesktop", "Quit to desktop", ROW_ACTION, 0, NULL, 0, 0, 0, 0,0,0,0,0 },
|
||||
{ .key="__QuitToDesktop", .label="Quit to desktop", .kind=ROW_ACTION },
|
||||
};
|
||||
#define NUM_ROWS ((int)(sizeof(rows) / sizeof(rows[0])))
|
||||
|
||||
@@ -1269,6 +1276,13 @@ int optionsRowIsSlider(int i)
|
||||
return r && r->kind == ROW_SLIDER && rowHi(r) > rowLo(r);
|
||||
}
|
||||
|
||||
/* D353: the explicit Bond-file chooser row (front options screen only). */
|
||||
int optionsRowIsBondChooser(int i)
|
||||
{
|
||||
struct Row *r = rowAt(i);
|
||||
return r && r->kind == ROW_BOND_FILE;
|
||||
}
|
||||
|
||||
int optionsRowNeedsRestart(int i)
|
||||
{
|
||||
struct Row *r = rowAt(i);
|
||||
|
||||
Reference in new issue
Block a user