D211 didn't affect the in-level view (user test): the fast3d gfx_apply_fov_scale hook only recognised *pure* perspective matrix loads, but GE draws the world through g_CurrentPlayer->field_10E0 -- a projection x view matrix pre-combined on the CPU (bondview2.c:8224) -- which failed the guard. Only the pause/watch model + sky FOV changed. Fix: scale fovy game-side at the guPerspectiveF chokepoint (src/fr.c, #ifdef PORT, frFovY *= portFovScale, clamp 160deg), which lands before the CPU combine. Removed the fast3d hook + gfx_api.h decl; port/src/video.c now sets f32 portFovScale. Gated to lvlGetCurrentStageToLoad() != LEVELID_TITLE so the front end (which renders through the same path) keeps its authored FOV. User-verified: menu unaffected, in-level view widens (Dam tunnel). Caveat: currentPlayerSetCameraScale keeps nominal FOV for frustum-cull / screen<->world math (edge geometry culls slightly early at high scale). Adds src/fr.c as a #ifdef PORT game-code touch (D181 policy class). Docs (this test pass): - D214: config.c sections by the last dot, so binds live in [Input.Bind] not [Bind]. Doc-only fix (finding, index, QOL-INVENTORY); code unchanged. - D217 (OPEN): viewmodel + 3rd-person Bond model textures render garbled -- stale-palette CI-texture bug (D161 family), surfaced by D215. - D218 (LOGGED, parked): wide FOV exposes the per-level FarFog draw-distance boundary; Video.DrawDistance fix proposed.
4.6 KiB
QoL Inventory — PD-vs-GE options diff
Status: partially implemented. M-83 landed three port-only quick wins —
DisplayFPS (D213), anisotropic filtering (D212), and the FOV slider (D211, via
WIDESCREEN-FOV-PLAN.md Phase 4). Rebinding / SkipIntro / per-pad tuning /
window HiDpi still open. Companion to WIDESCREEN-FOV-PLAN.md and
UNLOCKED-FPS-PLAN.md.
Method: diffed the config surface of both ports — every configRegister*
key in pd_port/port/src/*.c vs port/src/config.c + the F10 overlay
(port/src/optionsoverlay.c) + PD's optionsmenu.c. Principle applied:
where PD has a QoL feature that is achievable here, it is the standard;
GE keeps its own extras.
Classification key — P = port-only (no rules issues), G = needs a
game-code exception (rule #2 sign-off, per WIDESCREEN-FOV-PLAN.md framing).
GE already has (baseline — keep)
Input: mouse enable/capture/aim+turn speed/invert Y/Y scale/smoothing/raw
input, aim band, hipfire pitch speed, menu pointer speed + mode (GE's menu
cursor is injected entirely in port/src/input.c — no game code), pad
deadzone/trigger %. Video: VSync, FpsCap, MSAA, TextureFilter,
FixMipTextures, WrapFix, Fullscreen, Window geometry. Game:
ScreenShakeIntensity. Debug: FrameDump, InputLog.
PD has, GE lacks (candidates)
| Feature | PD location | Class | Effort | Notes / priority |
|---|---|---|---|---|
| Key rebinding (DONE M-83, D214) | port/src/input.c [Input.Bind] section |
P | M | Keyboard only, 12 actions, Input.Bind.* = Key,Key (SDL scancode names), file-driven like PD. Defaults = prior FPS layout (verified). Per-controller pad rebinding + a UI still open. |
| SkipIntro | main.c:139 (STAGE_TITLE → STAGE_CITRAINING) |
P | S | High. GE analogue: stage-override path already exists (boss.c:385-393, g_StageNum = LEVELID_TITLE at :98); wire a flag + arg. 10-min check on what feeds tokenFindLevel. |
| DisplayFPS (DONE M-83, D213) | config Video.DisplayFPS |
P | S | Top-right readout, config-only; ~0.5 s sample window. |
| Anisotropic filtering (DONE M-83, D212) | Video.Anisotropy (1–16, dflt 4) |
P | S | fast3d already had the GL hook + a hardcoded 4×; M-83 exposed it as config. MipmapFilter / TextureFilter2D still not surfaced. |
| Per-pad tuning: per-stick deadzones, stick scale, rumble scale, device index, swap sticks, C-button mapping | input.c padsCfg block |
P | M | Medium. Matters for real-controller users; PD pattern is a config section per pad. |
| FakeGamepads / FirstGamepadNum / UseHIDAPI | input.c |
P | S–M | Niche (local MP on PC); defer until MP is actually played. |
| Window polish: DefaultFullscreen/Maximize, CenterWindow, AllowHiDpi, ExclusiveFullscreen | video.c vid* block |
P | S | HiDpi + center are the useful ones on modern Windows. |
| VSync adaptive (−1..10) | Video.VSync range |
P | S | Note for FPS plan — GE's 0/1 toggle is fine until then. |
| CenterHUD (0/1/2 = left/center/right) | Game.CenterHUD → g_HudAlignModeL/R |
G* | — | Already scoped in WIDESCREEN-FOV-PLAN.md Option B (Phase 1 decision). Not a separate item. |
| Per-player FovY + FovAffectsZoom | Game.Player%d.FovY, g_PlayerExtCfg |
G | M | PD does this in game code. GE's port-only RSP FOV slider (widescreen plan Phase 4) covers the global case; per-player is a stretch goal needing the exception class. |
| MemorySize (4–2048 MB emulated RAM) | Game.MemorySize → g_OsMemSizeMb |
P? | S | Check how GE sizes its OS memory heap; if fixed, make it a config knob (stability lever for heavy levels). |
| MaxExplosions / GEMuzzleFlashes / DisableMpDeathMusic | PD decomp edits | G | S | Low priority; rule-#2 cost > benefit. Skip unless asked. |
| GlareBrightness / OverexposureScale / FramebufferEffects | PD post-FX | — | — | Not applicable: GE's fast3d has no framebuffer-effect path. Excluded. |
GE has, PD lacks (keep as-is)
Video.FixMipTextures, Video.WrapFix, Input.AimBand,
Input.HipfirePitchSpeed, Input.MouseSmoothing, Debug.FrameDump,
Debug.InputLog. No action.
Suggested Phase 4 order (after audio; ordering vs widescreen/FPS TBD)
- Quick wins (all P, small): SkipIntro, DisplayFPS, aniso + mipmap filters, window HiDpi/center.
- Rebinding (P, medium) — the headline Phase 4 item; PD pattern is config-string driven, no UI required for parity.
- Per-pad tuning (P, medium).
- Niche: fake gamepads / HIDAPI (when MP gets played); MemorySize knob (after the heap check).
Everything here is parked behind audio like the other plans; nothing in this inventory implies an implementation decision yet.