RP412MFDLAYOUT already kept the exploded view's display panes where they
were dragged. The main window is the one people move most, and it was
still being placed fresh every launch, so it joins them.
MFDSplitView_LoadLayout/SaveLayout become RPWindowLayout_Load/Save, with
Register/Forget taking any HWND rather than the module reaching into a
pane registry. Same file, same format, one more line in it.
What comes back depends on the window, so Register takes it as a flag:
display panes position only, as before. A pane's size follows its
content and its button banks, so an old size from a
different build must not distort it.
the game window position and size in the cockpit view. Nothing
derives that size - the cockpit fits itself to
whatever client area it is given - so a window sized
to suit a monitor should come back that way, and
half-restoring it would be the strange behaviour. In
the exploded view its size IS the render resolution
-res asked for, so there only the position returns.
Registered after the CockpitShellProc subclass is installed, on purpose:
the restore's WM_SIZE then runs LayoutCockpit again and the canvas
re-fits the restored client area. -fit does not register at all - it
owns the whole monitor, so there is no placement of the player's to
keep.
CockpitShellProc gained the WM_EXITSIZEMOVE hook the panes already had,
so dragging or resizing the shell writes the file immediately rather
than waiting for teardown.
Two hazards the panes were small enough to get away with and the game
window is not:
- Save reads rcNormalPosition rather than GetWindowRect. A minimised
window reports a nonsense rect and a maximised one reports the
screen; since the file is rewritten whole, either would have
replaced a good line with a useless one. rcNormalPosition is the
restored placement whatever state the window is in.
- Load drops any placement that intersects none of the monitors
currently plugged in. Restoring the game window onto a display that
is no longer there would leave nothing to drag back.
Verified by round trip in both views. Cockpit: dragged and resized to
240,120 1000x620, the file took it, a fresh launch in load mode came up
exactly there with a 984x581 client - and a screenshot confirms the
canvas re-fit it, displays at the corners and the map centred at the
bottom, nothing spilling. Exploded: the shell came back at 60,60 still
1280x720 from -res while Map came back at 777,333, which is the
size-flag split doing its job.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ported from BT411's BT_GLASS_LAYOUT (29c502d).
The exploded view's panes are draggable desktop windows, but the
arrangement is recomputed on every launch, so dragging one somewhere
useful never survived the menu-race-menu loop.
RP412MFDLAYOUT persists it to mfd_layout.cfg beside bindings.txt:
off / 0 / unset computed arrangement only, no file (default)
load / restore restore saved positions at startup, never write
save / adjust restore, then rewrite on each finished drag
(WM_EXITSIZEMOVE) and on teardown
One "<title>=x,y,w,h" line per pane. Position is restored and the size
read and discarded: a pane's size follows its content and its button
banks, so letting an old size back in would misshape it after any
geometry change - and this port has changed that geometry twice already.
Load runs after the computed arrangement rather than instead of it, so a
pane the file does not mention simply keeps its computed spot. Only the
exploded view registers: the composited cockpit's panes are chrome-less
children with nothing to drag, so they have no position worth keeping.
RP412 needs no equivalent of BT411's "restored" flag. Its re-snap is
LayoutCockpit on WM_SIZE, which only runs in cockpit mode, so nothing
comes back later to overwrite a hand-placed window.
Verified by round trip: dragged Map to 777,333 in save mode, the file
took all six panes, and a fresh launch in load mode put it physically
back at 777,333. The harness also resized the window while moving it,
which incidentally proved the saved size really is ignored - the pane
came back correctly sized from a cfg that recorded 136x39.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The six secondary displays sit over the viewscreen like the pod's bezels
and have nothing to say once the race is over. Worse, the radar sits dead
centre along the bottom edge - directly on top of the winner's spot, so
the one position that matters was the one you could not see.
They are hidden when the podium comes up, which uncovers the canvas the
3D is already being drawn on. No matching show: the mission is over by
then, and the next race builds a fresh cockpit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
The canvas was capped at 100%, so a bigger monitor got a 1920x1080
cockpit in the corner of the screen and maximising did nothing - the
layout only ran once at startup.
Now the fit is one uniform scale with no ceiling, recomputed whenever
the window changes size (maximise, restore, drag), and the canvas is
centred in whatever client area it gets. Uniform scale is what locks
the aspect: a wider-than-16:9 desktop letterboxes with even black bars
instead of stretching the cockpit. Panes gained Resize() so the glass
and its button banks re-scale with the canvas; the pixel buffers keep
their native source resolution.
Scaling up is free quality on the MFDs - their glass is a downscale of
a native 640x480 channel until about 200%.
Verified on the 3440x1392 ultrawide: opens at 125% (2400x1350) instead
of 100%, maximises to 126% centred with even bars, a 1884x661 window
fits 61% letterboxed left/right, 1084x961 fits 56% letterboxed top/
bottom, and a 2584x1461 client scales up to 134%.
The 3D still renders at -res and D3D stretches it to the canvas, so
raise -res to match a large screen for 1:1 pixels; start-windowed.bat
and the README say so.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two pieces of MFD work that had been sitting in the tree (already in
every build and dist since).
The compact cockpit glass shows the full 640x480 gauge canvas at about
half size, and COLORONCOLOR did that by dropping every other row and
column - which shredded the 1-bit vector strokes and small text.
HALFTONE area-averages instead (with the brush origin set, as MSDN
requires) so the downscaled MFDs stay legible.
L4MFDSPLIT=2 adds an exploded diagnostic view: every display in its
own full-size desktop window at native resolution, decoded exactly as
the pod VDB split them from the single gauge canvas, with no cockpit
compositing and no downscale. It makes an individual MFD readable and
screenshottable at full resolution for comparison against the
emulator per-channel reference windows. L4MFDSPLIT=1 keeps the
composited glass cockpit and stays the default.
Also: .gitignore now covers the packaged RedPlanet-*.zip releases,
which live on the Gitea release page rather than in the tree.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The map/radar glass grows from 240x320 to 360x480 on the 1920x1080
canvas (user request - the radar reads best big). The flanking
Secondary/Screen columns, bottom-center placement, and canvas scaling
all follow from the measured size automatically.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SS_BLACKRECT paints the system window-frame color - gray on modern
Windows - so the viewscreen child is now a plain STATIC subclassed to
erase true black. The MFD/map panes flickered because Paint() cleared
the on-screen surface before redrawing at the fill cadence; the pane
now composes off screen and lands in a single BitBlt.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Playtest direction on the canvas layout: all five MFDs at the compact
320x240 glass size - upper pair pushed to the top corners, score glass
top-center, lower pair in the bottom corners, map bottom-center - and
the viewscreen now fills the entire 1920x1080 canvas. Launched with
-res 1920 1080 the 3D renders native 1:1 (the 2007 D3D9 path takes the
1080p backbuffer and 16:9 aspect without complaint). start-windowed.bat
updated accordingly.
Verified live: full-screen native 3D with the cockpit floating over its
edges, mission running, preset lamp lit on the map column.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The cockpit is now a fixed 1920x1080 canvas (uniformly scaled down on
smaller monitors, min 25%):
[ MFD UL 640 ][ MFD UC 640 ][ MFD UR 640 ] <- native glass, 1920 wide
[ viewscreen 800x600 centered ]
[ MFD LL ] [ Map ] [ MFD LR ] <- bottom edge
Playtest direction: the original pods MFDs partially occluded the main
display, and that is used here on purpose - the panes overlap the
viewscreen and render over it (viewscreen pinned to the bottom of the
sibling z-order, WS_CLIPSIBLINGS everywhere, so the 3D present clips
around every pane). Top-row glasses are gauge-canvas native 640x480 -
three across is exactly 1920. Red MFD buttons at half height; the amber
map columns stack contiguous like the pod strips. The auto-fit
scale/L4MFDSCALE machinery is gone - the canvas is the design space.
Verified live at 100% scale: contiguous native top row over the
centered viewscreen, bottom cluster overlapping its lower edge, map and
gauges updating (BOOST values moving, presets lit).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The assembled shell could exceed the work area (1291px tall at default
scale) - on a 1080p monitor the whole lower row, map included, hung off
the bottom of the screen, which read as the map not rendering, and the
lamp-reactive preset buttons were unreachable down there. (The render
and click paths themselves were verified fine: a synthetic press on a
map preset button lights it through the game lamp command.)
The layout now measures SPI_GETWORKAREA and fits: the pane scale steps
down (to 20% minimum) and the viewscreen takes the leftover height at
the 3D aspect, shrinking below native when needed - Present stretches,
so the scene scales cleanly. Rows and viewscreen center in the shell,
which is sized to the work area. Verified: at 70% panes in a 1392-high
work area the viewscreen reduced to 609x457 with everything on screen.
The plasma glass sits out of the cockpit for the moment
(PlasmaScreen::Hide) per playtest direction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The main game window becomes the cockpit shell (enlarged, clipping
children); every display folds in as a chrome-less child pane in the
pod interior arrangement:
[ MFD UL ] [ MFD UC ] [ MFD UR ]
[ plasma (reduced) ][ viewscreen (centered) ]
[ MFD LL ] [ Map ] [ MFD LR ]
The 3D scene presents into a black STATIC viewscreen child via
Present's hDestWindowOverride (new gMainPresentWindow global) - no
swap-chain changes, and STATIC's transparent hit-testing keeps mouse
input over the 3D view flowing to the game window. MFDSplitView gains a
parent/child mode; PlasmaScreen::Position reparents the glass into the
shell. Main window class background goes black for the cockpit gaps.
Verified by screenshot: live green gauges (LIFT CUT / BOOST / CHUTE /
trigger-program screens) with their red button strips, the 3D canyon in
the centered viewscreen, plasma score glass at its left, map with lit
amber preset lamps - one window, 976x1132 client at 50% scale.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
[ MFD UL ] [ MFD UC ] [ MFD UR ]
[ plasma (reduced) ][ main screen (centered) ]
[ MFD LL ] [ Map ] [ MFD LR ]
SVGA16 moves the main game window into the middle band (centered under
the MFD columns) and shrinks the plasma glass to fill the space at its
left via a new PlasmaScreen::Position hook (the glass paint stretches to
the client area, so resizing rescales it). Lower row sits below the
main screen band.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pod stacks its displays vertically - upper MFDs above the
viewscreen, weapon MFDs + secondary below. Default grid now places the
lower row (MFD LL / Map / MFD LR) at the main screen's bottom edge
instead of directly under the upper row, so the main screen reads as
the middle band, with the plasma glass at its lower-left.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The side-button columns widened the map window, drifting the glass right
of center; shift the default position left by one column width.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Each MFDSplitView window now carries its display's physical button bank,
placed as in the pod (addresses per vRIO CockpitLayout): a 4x2 red
cluster around each MFD glass (anchors 0x2F/0x27/0x37 upper, 0x0F/0x07
lower, addresses descending row-major) and 6 amber buttons down each
side of the map - Secondary 0x10-0x15 left, Screen 0x18-0x1D right; the
remaining column addresses are Tesla relays, per the pod wiring, so they
get no buttons.
Buttons light from the lamp state the game commands: PadRIO grows a
static active-instance hook (SetScreenButton/GetLampState); mouse
press/release feeds PadRIO's desired-state sampling alongside pad and
keyboard, and paint decodes the lamp byte (state1/state2 brightness,
solid/slow/med/fast flash animated by tick). With real serial hardware
(no PadRIO) the buttons draw dark and inert.
Verified: map flank buttons light per the game's preset lamps, aligned
with the labels the glass draws at its edges; MFD clusters render 4+4.
Roadmap: queued the vRIO Dynamic Lighting RGB-keyboard lamp mirror as a
polish-pass item. dist repacked.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pod drove five monochrome MFDs from the color channels of two video
outputs - SVGA16 packs bit-slices of the shared gauge canvas into R/G/B
of gauge window 3 (upper MFDs) and R/G of window 4 (lower MFDs), with the
map palettized on the secondary and physically mounted portrait. The
desktop reconstruction previously required an external BitBlt-mirror
wrapper.
With L4MFDSPLIT=1, SVGA16 renders each display into its own window
(MFDSplitView, plain GDI) straight from the canvas + port bit-masks:
five green-screen MFD windows and the 90CW-rotated Map, tiled in the pod
grid to the right of the main view (L4MFDSCALE percent, default 50). The
packed D3D windows stay hidden but keep presenting off-screen, leaving
the original path untouched. Handles spanning mode (2-window setups).
Also: the plasma glass now opens directly below the main view (clamped
to the work area; L4PLASMAPOS=x,y overrides) per playtest feedback.
Verified: window grid comes up as main + 5 MFDs + Map + plasma with the
packed windows hidden; screenshots confirm a green MFD score readout and
the portrait tactical map rendering correctly. dist packer and BUILD.md
updated; the launcher wrapper is obsolete for split-mode use.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>