v0.5.0: settings UI, control styles, save import, documentation

PD-style F10 menu with six groups, checkbox/slider/dropdown controls (D504),
wording pass and real-unit sliders (D505-D509), overlay/FPS-counter window
scaling (D510, D512), small settings (D511), control scheme Ext/Original
(D513) with the game's own N64 styles (D516-D518), emulator-format save
import on first launch (D514), build arch tag (D515), converter argv quoting
and sidecar size check, one PC options UI (D519) with by-eye follow-ups,
antialiased overlay sliders (D520), README settings paths, ROADMAP trim,
D441 tier-1 all-level sweep (21/21 pass).

Refs: D503-D520 D349 D441
This commit is contained in:
James Dansereau committed 2026-10-06 18:35:43 -04:00
1 parent daa2522511
commit aa5a1b81fe
36 files changed
+2911 -1812

No files matched your search

+4
View File
@@ -1414,6 +1414,7 @@ A port stub that forces a value to `-1` (D154 `texnum`, D135) can hide latent la
- **Triage trap:** check whether a `PROPFLAG_*` hit is on `prop->flags` (runtime u8) or on `obj->flags` / pdef flags (u32 definition bits) before treating it as a reader (`propobj.c:8417`, `prop.c` 233-467 are the latter).
- **Remaining class member:** FOV/widescreen widening of `camIsPosInScreen` and `c_lodscalez` (D222).
- **Fixed-size per-frame budgets are readers too (D500):** the dyn.c vtx pool (`-mvtx`, as low as 40 KB) is bump-allocated with no bounds check and sized for what the N64 could see; widened views overran it (Aztec triangles). Look for unchecked per-frame pools sized by per-level tokens when a widening feature shows corruption only in busy scenes.
- **A pixel ratio is not a fog factor (D503):** "~97% fogged" was a pixel-colour ratio; derive any fog snap cutoff from measured vertex fog, not from it. And before blaming fog for a far object, do the cheap 4:3 + N64-FOV test: if it vanishes, the cause is the widened frustum, not fog.
- **Reveal, not regression (D503):** the N64's 16-bit framebuffer hid 2-5 level differences (near-full fog against haze); 32-bit output shows them, plus the room-scissor edges of nearly fogged objects. Measure pixel values against the fog colour before blaming draw distance.
## D19. A "click after the shot" report needs the trigger-hold duration, not just the state machine (D433/D467)
@@ -1876,3 +1877,6 @@ Also the read side: D496 (`generate_language_specific_text_for_weapon` strcat'd
**Audio device/gain changes belong on the producer thread (D470).** The SDL audio path is a queue (`SDL_QueueAudio`), fed and sized only from `audioSetNextBuffer`/`audioGetAiLengthBytes`. To change the device live, have UI/event threads only set atomics and do the close/reopen at the top of `audioSetNextBuffer`; never close `dev` from the UI thread. Apply master gain to a scratch copy (never the game's buffer) and pass the original pointer through at 100 so the default stays byte-identical. `SDL_AUDIODEVICEREMOVED.which` is the opened device id for output devices.
**Overlay/menu input must name its owner pad; never hard-code seat 0 (D472).** When several pads can open a shared UI, keep a per-pad edge array (one shared `prev` flag masks edges and double-toggles), record the opener, and resolve the effective owner (opener -> lowest attached -> 0) at read time so a detach cannot strand the UI. Port-layer 2D that must pillarbox under native widescreen: wrap it in `PORT_HUD_ASPECT(CENTER)` and map the mouse through `vis = (4/3)/portNativeAspect()`.
### The options row table has two UIs; new row kinds need a front-end answer (menu PD alignment)
`port/src/optionsoverlay.c`'s `rows[]` is consumed by the F10 overlay and by `frontoptions.c` through the `optionsRow*` accessors. A row kind that only one UI understands (separator, Back, hub-only actions) must be hidden from the other in `optionsRowIsShown()`, and should be a `ROW_ACTION` with a key prefix so the section-reset and reset-probe loops (which skip `ROW_ACTION`) stay correct. Moving a row between sections silently changes what that section's "Reset to defaults" resets: re-run `GE_WSPROBE_RESET` after any regroup.