Commit Graph
5 Commits
Author SHA1 Message Date
CydandClaude Opus 5 aa294071f9 The render target is the size that was asked for
A crosshair off-centre on the second race, and underneath it every race
after the first was a different race.

Windowed, BackBufferWidth/Height were left at zero, so D3D sized the back
buffer to the device window's client area at the moment the device was
created. Everything downstream is built from the size we ASKED for
instead - the projection matrix takes its aspect from it, the reticle is
centred on it - so a window that was not exactly that size rendered at
the wrong shape and got rescaled on the way to the viewscreen pane.

-fit decided which window that was, and it decided differently for the
first mission than for the rest. Its borderless full-monitor placement
lived only in SVGA16's cockpit build, which does not run until a mission
starts - just after that mission has built its device. So race one was
set up against a still-bordered client and every race after it against
the borderless monitor. On a 3440x1440 panel that is a 1.778 image drawn
across a 2.389 target, against 1.816 the first time.

That is not a cosmetic difference. The simulation advances on wall-clock
deltas, so frame cost is physics: two render targets that size and scale
differently are two different races from one lobby and one set of
settings. A racing sim does not get to do that.

So: the back buffer is the requested size windowed as well as
full-screen, and -fit takes its shape at startup rather than four
screens later. SVGA16 still applies the same rect when it builds the
cockpit - that call is now a no-op instead of a change, which is the
point. The first lobby also stops being the only one with a title bar.

The reticle keeps its own share of the blame and is fixed on its own
terms, so it cannot drift again if a target ever does move:

- It is measured against the viewport at draw time and rebuilt when that
  changes, rather than baked once in the constructor from the renderer's
  requested size. One GetViewport a frame, no rewrite until it moves.
- The arms are quads, not lines. D3D9 line rasterisation follows the
  diamond-exit rule and is free to differ between drivers on a segment
  running along a pixel boundary, which is how a crosshair loses one
  pair of arms and keeps the other - and full-screen, where both
  dimensions are usually even and both pairs sit on boundaries, how it
  can lose the lot.
- Arm thickness follows the target rather than being one pixel whatever
  the resolution. One pixel is a width the presentation can throw away
  in a downscale, and it was a hairline at 1440 next to the pod's line
  at 480.

The log names the viewport, the requested size and where the crosshair
landed, and says TARGET DISAGREES with both aspects when the first two
do not match - so the next report of this arrives with its own diagnosis.

Window creation cleaned up while in there: it computed a style and then
handed CreateWindowEx a literal WS_OVERLAPPEDWINDOW regardless, so the
full-screen path never got the WS_POPUP it thought it was asking for.
Borderless modes are now born borderless instead of being restyled a
moment after. The requested size also goes through AdjustWindowRect,
because -res is a render size and was being used as the OUTER rectangle
with the chrome taken out of the middle - which is how -res 640 480 came
to present into a 624x441 client and started all of this.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 22:19:39 -05:00
CydandClaude Fable 5 8dc6605a07 Cockpit: buttons under the glass, -fit, and player display layout
Button banks
  The exploded diagnostic view was still display-only - it predates the
  button work - so it now builds the same banks as the cockpit, with
  the pod arrangement laid out from the panes measured sizes rather
  than a hardcoded 640/480 grid (the banks make each window bigger than
  its glass, and the bottom row hung off the work area otherwise).

  The map side columns were spread height/6 from the top, but the maps
  own legend grid is not sixths: measured off the bitmap it starts 13
  rows down with six 102-tall cells on a 105 pitch. Every button sat
  high of its label, worst at the bottom. Each buttons top and bottom
  now come off that grid separately and are subtracted - scaling a
  height directly would let rounding drift them back out of step on a
  resized cockpit.

  Depth 100 to 240: against the 480 glass the two banks meet in the
  middle bar the strips, so practically the whole display is a press
  target. This mattered most in the cockpit, where the panes are small
  enough that the halfway clamp governs - at 100 the MFDs had a 110px
  dead band straight through the middle of the glass.

-fit (also spelled -windowed-fullscreen)
  Borderless over the whole monitor, with the render size chosen to
  match. The cockpit presents the 3D into a viewscreen that fills its
  canvas, so the right -res is that canvas at the scale the cockpit
  will settle on; computing it with identical arithmetic makes the
  stretch a copy. On the 3440x1440 panel that is 133% and -res 2553
  1436, against 125% for the windowed path that pays for the taskbar.

  The pick runs after the whole command line, so an explicit -res wins
  from either side of -fit. Capped at 3840x2160. Cockpit mode only -
  mode 0 has to stay playable on real pod hardware and mode 2 is a dev
  view - so those get the resolution and keep their windows.

Display layout, in environ.ini
  L4MFDSCALE sizes all five MFDs, L4MFDSCALE_UL and friends override
  any one of them, L4RADARSCALE the radar, and L4RADARPOS puts the
  radar bottom centre, in either bottom corner, or halfway up either
  side. Scaling is applied in canvas units before the canvas is fitted
  to the window, so a number means the same thing on every monitor.

  Sizing each display separately let the clamps become exact rather
  than one conservative rule for all five: what limits a display is its
  actual neighbour. Which neighbour that is depends on the radar, so
  the clamps follow it - on the bottom edge it clears the one MFD above
  its column, but centred on a side it has one above AND below and
  grows from the middle both ways, so it must clear the taller twice
  over. Clamping shrinks uniformly; these are photographs of real
  instruments and a one-axis clamp would squash them.

Verified on the ultrawide: all five radar positions, per-display and
group scaling with the clamps biting, -fit with and without an explicit
-res, and the button geometry measured back off the screen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 14:05:02 -05:00
CydandClaude Fable 5 fbd23ff1ca Key-command audit: the up arrow was the abort key; bombs disarmed
Full input-surface audit of the PC keyboard channel. The arcade abort
was the typed ampersand character (0x26), but the Win32 port feeds
WM_KEYUP VIRTUAL-KEY codes into the same channel - and VK_UP is also
0x26. The hat look-up key aborted the mission: that was every mystery
abort across the multiplayer test rounds. Likewise the E key (0x45,
the right pedal!) dumped the event queue on every release.

Disarmed: plain 0x26 and E are swallowed at the L4 layer; the abort
answers only to the deliberate Alt+Q chord (translated to the legacy
engine code, so APP.cpp is untouched); the debug toggles (wireframe
Alt+W, predator vision Alt+V, frame dump Alt+F, perf stats, event
queue on Alt+E now) arm only with RP412DEVKEYS=1. The cheat-string
manager has no PC-keyboard strings and the trace-log keys are
compiled out of release - both inert.

Verified live: a volley of VK_UP releases mid-race leaves the mission
running; Alt+Q aborts on demand. Docs and the dist README updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 09:47:04 -05:00
CydandClaude Opus 4.8 f849415c02 Remove ATL dependency so VC++ Express can build
The Express editions of Visual C++ ship without ATL. The only ATL usage was
in MUNGA_L4/L4APP.cpp (atlbase.h/atlconv.h + USES_CONVERSION/W2A macros, all
in that one file) for wide-to-ANSI conversion of command-line arguments.

- Replace the ATL includes with a self-contained L4WideToAnsi helper (a
  WideCharToMultiByte wrapper) and local USES_CONVERSION/W2A macros that
  reproduce ATL's W2A semantics. All call sites consume the result immediately
  (stricmp / CString assignment / atoi / atol), so behaviour is unchanged.
- Set UseOfATL="0" in Munga_L4.vcproj, RP_L4.vcproj and their VS2008 variants.
- Document the Express build path and the confirmed June 2010 DirectX SDK in
  BUILD.md (new section 6) and docs/BUILD-NOTES.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 09:30:08 -05:00
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00