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.
This commit is contained in:
James Dansereau committed 2026-09-27 14:55:41 -04:00
1 parent fe57d73924
commit f8f94cdd87
4 files changed
+177 -16

No files matched your search

+14 -9
View File
@@ -330,8 +330,10 @@ void frontOptionsMenuInterface(void)
* D352 chooser; folders only, "none" retired, plan §5.5). */
playSfx(DOOR_LOCK_SFX);
watchSettingsChooseFile(1);
} else if (s_hl >= 0 && s_hl < s_rowN) {
int i = s_rowIdx[s_hl];
} else if (s_hl >= 1 && s_hl <= s_rowN) {
/* s_hl is item-numbered (0 = the save-file row); content row k
* is item k+1, so the row index is s_hl - 1. */
int i = s_rowIdx[s_hl - 1];
playSfx(DOOR_LOCK_SFX);
if (optionsRowIsSlider(i) && cursor_h_pos >= BAR_X0 - 4 &&
cursor_h_pos <= BAR_X1 + 4) {
@@ -384,7 +386,7 @@ void frontOptionsMenuInterface(void)
if (s_hl == 0) {
watchSettingsChooseFile(dir); /* save-file row */
} else {
int i = s_rowIdx[s_hl];
int i = s_rowIdx[s_hl - 1];
if (optionsRowIsReset(i))
optionsRowActivateReset(i);
else
@@ -399,7 +401,7 @@ void frontOptionsMenuInterface(void)
/* D356: reset arm state -- the screen's selected rows[] index (s_hl 0 is
* the save row, not a rows[] entry); moving on disarms, goBack clears. */
optionsResetMaintain(s_level == 1 && s_hl > 0 ? s_rowIdx[s_hl] : -1);
optionsResetMaintain(s_level == 1 && s_hl > 0 ? s_rowIdx[s_hl - 1] : -1);
/* The dossier: tabs + a blank CLASSIFIED page, as the cheat screen. */
disable_all_switches(walletinst[0]);
@@ -518,19 +520,22 @@ Gfx *frontOptionsMenuDraw(Gfx *DL)
for (int k = 0; k < s_rowN; k++) {
int i = s_rowIdx[k];
int y = rowY(k);
/* Content row k is item k+1 (item 0 is the save-file row), so
* it sits one line below the save row -- rowY() already shifts
* level-1 items down by one. */
int y = rowY(k + 1);
char label[48];
snprintf(label, sizeof(label), "%s\n", optionsRowLabel(i));
if (k == s_hl) {
if (k + 1 == s_hl) {
DL = microcode_constructor_related_to_menus(DL, ROW_X - 2, y - 1,
ROW_X + measureW(label) + 5, y + 0xE, HILITE);
}
DL = ink(DL, ROW_X, y, label, INK);
/* D356: per-file rows in the mixed-scope section carry a dim
* "(save)" tag (the section title already says which file). */
/* D357: per-file rows in the mixed-scope section carry a dim
* "(profile)" tag (the section title already says which file). */
if (optionsRowIsSaveScoped(i)) {
DL = ink(DL, ROW_X + measureW(label) + 4, y, "(save)\n", INK_DIM);
DL = ink(DL, ROW_X + measureW(label) + 4, y, "(profile)\n", INK_DIM);
}
if (optionsRowIsSlider(i)) {
+7 -7
View File
@@ -146,7 +146,7 @@ struct Row {
int dispDiv;
/* D356: 1 = this row's value lives in the selected save file (per-file
* watch rows). Carries the dim "(save)" tag on the only section that
* watch rows). Carries the dim "(profile)" tag on the only section that
* mixes scopes (GAMEPLAY); on headers the flag is recomputed at init to
* mean "this section contains per-file rows" (drives the "(File N)"
* title annotation in both UIs). */
@@ -158,7 +158,7 @@ static struct Row rows[] = {
* GAMEPLAY, GRAPHICS, AUDIO, VIDEO; docs/dev/D356-SETTINGS-REGROUP-PLAN.md).
* The D353 "BOND FILE" section -- the one named after WHERE a value is
* saved -- is gone: its surviving rows split into GAMEPLAY (the per-file
* watch toggles, dim "(save)" tagged since the section mixes scopes) and
* watch toggles, dim "(profile)" tagged since the section mixes scopes) and
* AUDIO (the per-file volume sliders, homogeneous so title annotation
* only), and the "Edit file" chooser row is retired in favour of the
* single top save-file row on the front options screen (frontoptions.c).
@@ -198,7 +198,7 @@ static struct Row rows[] = {
* Bond.AimControl collides with Input.AimMode (two rows fighting over
* the same N64-vs-PC aim model).
* The four surviving per-file toggles move here from the D353 BOND FILE
* section and carry .saveScoped (dim "(save)" tag, the only mixed-scope
* section and carry .saveScoped (dim "(profile)" tag, the only mixed-scope
* section). */
/* { .key="Bond.Look", .label="Look up/down (watch; stacks)", .kind=ROW_TOGGLE,
.names=kReverse, .found=1, .uiMax=1, .cfgMax=1 }, */
@@ -1436,11 +1436,11 @@ Gfx *optionsOverlayEmit(void)
}
gdl = drawText(gdl, OV_LABEL_X, rowY, (char *)r->label,
r->found ? col : 0x808080ff);
/* D356: per-file rows in the mixed-scope section carry a dim
* "(save)" tag (the section title already says which file). */
/* D357: per-file rows in the mixed-scope section carry a dim
* "(profile)" tag (the section title already says which file). */
if (r->saveScoped && r->kind != ROW_HEADER) {
gdl = drawText(gdl, OV_LABEL_X + measureText(r->label) + 5, rowY,
"(save)", 0x909090ff);
"(profile)", 0x909090ff);
}
if (!r->found) {
gdl = drawTextR(gdl, right, rowY, "(n/a)", 0x808080ff);
@@ -1520,7 +1520,7 @@ int optionsRowIsBondChooser(int i)
/* D356: content rows carry the literal per-file flag from the table; header
* rows were recomputed at init to "this section contains per-file rows".
* Both drive UI decoration (the "(save)" tag, the "(File N)" annotation).
* Both drive UI decoration (the "(profile)" tag, the "(File N)" annotation).
* The F10 overlay and the front options screen are the only consumers. */
int optionsRowIsSaveScoped(int i)
{