D343: PC Options joins the file-select bottom bar; Copy/Erase shift left

Rule-2 layout edit (user sign-off 2026-09-27): Copy 247/225 -> 222/200,
Erase 357/335 -> 304/282 under #ifdef PORT; their click boxes follow.
"PC Options" is drawn by the port hook right after Erase's measured text
end (min x 352), so wider localised labels push it right. The top-right
label is gone.
This commit is contained in:
James Dansereau committed 2026-09-27 11:01:58 -04:00
1 parent 13473d5ec6
commit 835035916d
3 files changed
+46 -9

No files matched your search

+11
View File
@@ -13570,6 +13570,17 @@ Implemented as `Input.PdMouseAim` (**default off**, because it changes aim feel)
- The hook calls `microcode_constructor()` after the panel, so the Copy/Erase icons and the cursor drawn after it keep their render state.
- **Verified headless (self-quitting runs, D344):** panel render at 640x480; tab/section switching, D-pad select + A toggle (Mouse invert Y OFF to ON, nothing else changed), B close; label click opens it; open for 2450 frames with no legal-screen drop; clean exit every run. User playtest 2026-09-27: works on PC (mouse/keyboard, window close, Alt+F4). Owed: physical controller; widescreen captures of the panel.
**Route B, final (2026-09-27, user sign-off for both game-code edits): the panel above is RETIRED.** Two reviews flagged the panel's weak points (a sub-state of file select, a button hand-off in input.c, a per-frame g_MenuTimer write). PC options are now a real GE front-end screen, `MENU_PC_OPTIONS`, built like the Cheat Options screen:
- **Game code (all `#ifdef PORT`):** one enum value before `MENU_MAX` (`src/bondconstants.h`; nothing is sized by `MENU_MAX`); five one-line dispatch cases in `front.c` (debug name, update, init, interface, constructor); `front.c` includes `frontoptions.h`.
- **Screen (`port/src/frontoptions.c`):** `frontOptionsMenuInit` copies `init_menu15_cheat` (tab state reset, `load_walletbond()`) and sets `selected_folder_num` to folder 1, as a return from mode select does, because `frontSetupMenuBackground` frames `folderpositions[selected_folder_num]`. The interface sets the view like the cheat screen, highlights rows from the crosshair's y (not while A is held), and uses A/Z/Start to open a section, toggle/cycle/step a row, or set and drag a slider from the crosshair's x. D-pad/C left-right (keyboard A/D) adjusts with hold-repeat; B or the PREVIOUS tab goes back (section to list, list to file select, which saves the config). The dossier is shown with tabs + blank CLASSIFIED page, the cheat screen's switches. The constructor draws the black fill, `frontSetupMenuBackground`, black Zurich ink via `frontPrintText`, GE's 0x32 highlight boxes, ON in the cheat red (0xA00000FF), slider bars as two menu boxes, then `frontAddPreviousTabText` and `frontDrawCursor`.
- Page 0 is a numbered section list ("1. Display" ... "5. Game", title case from the row headers); page 1 lists one section's rows under a title.
- `input.c`'s M2 button hand-off is removed. F10 and Select don't open the overlay while `MENU_PC_OPTIONS` is up. The file-select hook keeps only the label and the F10 idle-timer fix.
- **Bottom bar (`constructor_menu05_fileselect`, `#ifdef PORT`):** Copy text/icon 247/225 moved to 222/200 and Erase 357/335 to 304/282, making room for "PC Options" at the right end of the same bar (y centred on 285). The click boxes follow the draw positions. The label is drawn by the port hook at `max(352, Erase bound.right + 14)`, so a wider localised Erase (JP) pushes it right instead of overlapping. The old top-right label is gone.
- **Verified headless (self-quitting runs):** `GE_STARTMENU=26` boots the screen; a script opened section 2 (View), went back to the list, then back to file select, confirmed by log lines. A scripted crosshair click on the bottom label opened the screen once, and the click did not carry into it. Captures at 640x480, 854x480 and 1120x480 are pillarboxed correctly. The Erase click box (to ~338) clears the label's (from 348). Golden gate 3/3.
- **Not verifiable here:** PAL/JP captures, because only the NTSC ROM is present. PAL shares the canvas, strings and constants; JP relies on the dynamic label x.
- **Owed:** user playtest (mouse, keyboard, pad; music/ambience on entering and leaving; "PC Options" sits close to the right edge, ending about x 428 of 440); a physical controller.
## D344 — Host PC bugchecks (0x119) during game runs: unclean multi-threaded quit (2026-09-27)
+15 -7
View File
@@ -57,6 +57,7 @@ extern void load_walletbond(void);
extern void disable_all_switches(Model *arg0); /* front.c:967 */
extern void set_item_visibility_in_objinstance(Model *objinstance, s32 item, s32 mode); /* front.c:968 */
extern s32 folder_selection_screen_option_icon;
extern struct rectbbox folder_option_ERASE_bound; /* front.c:439 */
/* ---- colours on the paper (RRGGBBAA; 0xFF = opaque black, GE's ink) ---- */
#define INK 0x000000FFu
@@ -77,16 +78,17 @@ extern s32 folder_selection_screen_option_icon;
#define ROW_HIT_X0 40.0f
#define ROW_HIT_X1 385.0f
/* ---- file-select label ---- */
#define LABEL_RIGHT 392
#define LABEL_Y 24
/* ---- file-select label: right end of the Select / Copy / Erase bar ---- */
#define LABEL_X 352 /* Erase's text now ends ~338 (front.c, D343 shift) */
#define LABEL_CY 285 /* the bar's centre line, as Copy/Erase */
#define LABEL_GAP 14 /* space after Erase's text */
#define HIT_PAD 4
#define MAX_PAGES 8
#define MAX_PROWS 12 /* the paper fits 12 rows, like the cheat list */
static const char kLabel[] = "Options"; /* ASCII only: issue #87 / D295 */
static const char kLabelNL[] = "Options\n";
static const char kLabel[] = "PC Options"; /* ASCII only: issue #87 / D295 */
static const char kLabelNL[] = "PC Options\n";
/* ---- screen state (game thread) ---- */
static int s_level = 0; /* 0 = section list, 1 = a section's rows */
@@ -421,8 +423,14 @@ Gfx *optionsFileSelectLabel(Gfx *gdl)
* height with a trailing newline (front.c's folder text does the same). */
textMeasure(&unusedw, &w, (char *)kLabel, ptrFontZurichBoldChars, ptrFontZurichBold, 0);
textMeasure(&h, &unusedw, (char *)kLabelNL, ptrFontZurichBoldChars, ptrFontZurichBold, 0);
x = LABEL_RIGHT - w;
y = LABEL_Y;
/* Follow the Erase label's measured right edge (set by the constructor
* just before this hook), so a wider localised "Erase" (JP glyphs) pushes
* the label right instead of overlapping it. NTSC/PAL: 352. */
x = (s32)folder_option_ERASE_bound.right + LABEL_GAP;
if (x < LABEL_X) {
x = LABEL_X;
}
y = LABEL_CY - h / 2;
hot = !optionsOverlayIsOpen()
&& menu_update == MENU_INVALID
+20 -2
View File
@@ -2778,7 +2778,13 @@ Gfx *constructor_menu05_fileselect(Gfx *DL)
textMeasure(&textsize.p[1], &textsize.p[0], langp, ptrFontZurichBoldChars, ptrFontZurichBold, 0);
textpos.p[0] = 285 - (textsize.p[1] / 2);
#ifdef PORT
/* D343 (user sign-off 2026-09-27): Copy/Erase shift left to make room
* for "PC Options" at the right end of the bar (N64: 247/225/357/335). */
textpos.p[1] = 222;
#else
textpos.p[1] = 247;
#endif
DL = textRender(DL, &textpos.p[1], &textpos.p[0], langp, ptrFontZurichBoldChars, ptrFontZurichBold, -1, viGetX(), viGetY(), 0, 0);
folder_option_COPY_bound.right = (f32) (textsize.p[0] + textpos.p[1]);
@@ -2790,7 +2796,11 @@ Gfx *constructor_menu05_fileselect(Gfx *DL)
textMeasure(&textsize.p[1], &textsize.p[0], langp, ptrFontZurichBoldChars, ptrFontZurichBold, 0);
#ifdef PORT
textpos.p[1] = 304; /* D343: see Copy above */
#else
textpos.p[1] = 357;
#endif
textpos.p[0] = 285 - (textsize.p[1] / 2);
DL = textRender(DL, &textpos.p[1], &textpos.p[0], langp, ptrFontZurichBoldChars, ptrFontZurichBold, -1, viGetX(), viGetY(), 0, 0);
@@ -2798,12 +2808,16 @@ Gfx *constructor_menu05_fileselect(Gfx *DL)
folder_option_ERASE_bound.right = (f32) (textsize.p[0] + textpos.p[1]);
#ifdef PORT
/* D343: PC "Options" label; a click enters MENU_PC_OPTIONS. All
* logic lives in port/src/frontoptions.c. */
/* D343: "PC Options" at the right end of this bar; a click enters
* MENU_PC_OPTIONS. All logic lives in port/src/frontoptions.c. */
DL = optionsFileSelectLabel(DL);
#endif
#ifdef PORT
copypos.f[0] = 200.0f; /* D343 */
#else
copypos.f[0] = 225.0f;
#endif
copypos.f[1] = 285.0f;
copyhalfsize.f[0] = (f32) (mainfolderimages + IMG_COPY)->width * 0.5f;
@@ -2816,7 +2830,11 @@ Gfx *constructor_menu05_fileselect(Gfx *DL)
folder_option_COPY_bound.up = copypos.f[1] - copyhalfsize.f[1];
folder_option_COPY_bound.down = copypos.f[1] + copyhalfsize.f[1];
#ifdef PORT
erasepos.f[0] = 282.0f; /* D343 */
#else
erasepos.f[0] = 335.0f;
#endif
erasepos.f[1] = 285.0f;
erasehalfsize.f[0] = (mainfolderimages + IMG_DEL)->width * 0.5f;