Commit Graph
18 Commits
Author SHA1 Message Date
CydandClaude Fable 5 ff6ec8c56a SteamNetTransport: the Steam wire is implemented and live
Steamworks SDK 1.64 vendored at extern/steamworks_sdk_164 (headers +
win32 redistributables only; .gitignore trims the rest). Both projects
build with RP412_STEAM; activation stays behind the RP412STEAM=1
environment switch, so plain desktop runs never touch Steam.

L4STEAMTRANSPORT.cpp implements NetTransport on ISteamNetworkingSockets
with FakeIP: SteamNetTransport_Install brings up SteamAPI, relay
network access, and a two-port FakeIP identity (fake port 0 = console
channel, 1 = game mesh), then swaps the process wire; any failure logs
the reason and the game carries on over TCP. Addressing keeps the
engine untouched: all pods share the -net port convention, eggs carry
fakeip:engineport, and the transport alone translates engine ports to
Steam fake ports via the lobby-fed peer table (RegisterPeer). Connect
mirrors the TCP retry-while-refused loop; Receive normalizes message
lanes back into the stream semantics CheckBuffers expects.

Runtime verified on this box: RP412STEAM=1 under AppID 480 came up as
169.254.59.52 (fake ports 32256/32257); without Steam credentials it
falls back to TCP cleanly; default boot logs no Steam lines at all.
steam_api.dll ships in the dist.

Next: the lobby layer (ISteamMatchmaking member data -> RegisterPeer +
egg build + RPL4CONSOLE marshal), which needs a second account to test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 20:34:07 -05:00
CydandClaude Fable 5 7315f3488d Two-pod LAN mesh test: multiplayer verified through the seam
tools/two-pod-test.ps1 stands up two -net pods on loopback and
marshals them with a minimal console feeder speaking the Munga
protocol (TeslaSuite vendored Munga Net.dll): state polling, egg
chunk delivery with ACK-after-mesh, RunMission when both pods reach
WaitingForLaunch, StopMission(0) at time expiry, EndMission score
intake.

First run passed clean: pod A listened on its game port, pod B
connected from its bound port, both ACKed after the mesh completed,
raced the same 60s mission on Wiseguy's Wake, stopped on command,
and reported final scores. The deterministic TCP mesh works end to
end through the NetTransport seam - the feeder logic is exactly the
marshal the Steam lobby owner will run in-process.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 20:14:47 -05:00
CydandClaude Fable 5 22421fb418 NetTransport seam: the wire moves behind an interface
The Steam-multiplayer prerequisite from the design doc: L4NET keeps
hosts, message queues, and the deterministic mesh ordering, while
connect/listen/accept/close, send/receive, startup/cleanup, the local
interface list, and ip[:port] parsing move behind NetTransport
(L4NETTRANSPORT.h). WinsockNetTransport carries the existing TCP
behavior over verbatim - including the connect retry-while-refused
loop the egg-ACK ordering relies on - and is the process default;
NetTransport_Set installs a replacement before the network manager
comes up.

L4STEAMTRANSPORT.h documents the ISteamNetworkingSockets mapping
per method (FakeIP keeps [pilots] entries as IPv4 strings) behind
RP412_STEAM until the Steamworks SDK lands.

Also fixed in passing: the ExclusiveBroadcast path sent
sizeof(network_packet) - four bytes of pointer - instead of the
message size, which would have sheared the stream framing had it
ever fired.

Verified: single-player race cycle (menu, race, results, menu, race)
green; -net 8000 boots, listens for a console through the transport,
and idles stable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 19:38:37 -05:00
CydandClaude Fable 5 9f79508257 LocalConsole: the in-process marshal that ends missions
Domain correction from playtest: hand-fed eggs are a developer shortcut
- a mission only ends on a console command, so the clock hits 00:00 and
counts up forever. Even single-player games need a console marshal.

RPL4CONSOLE is that console. Like the real one it lives on its own
thread: it owns the mission clock and raises the stop request at the
selected length; the app-manager per-frame hook (new gPerFrameHook seam
in APPMGR, called while the application global is live - the loop
condition NULLs it on exit, which ate the first attempt) executes the
engine-safe part, dispatching the same StopMissionMessage TeslaConsole
sent. Final scores flow in through a new RP-layer sink
(gConsoleScoreSink in RPCNSL): RPPlayer feeds it the same score it
sends a real console at mission end.

It also inherits the launcher role: the application tears down after a
stop (arcade pods were relaunched per mission by TeslaLauncher), so
WinMain respawns the process when the console ended the mission,
landing back on the race-setup screen. L4NetworkManager grows
FeedLocalEgg (the single-user egg-inject path, callable mid-session)
for the future in-process loop.

Verified end to end: menu -> 3:00 race -> stop dispatched exactly on
time -> final score collected (host 1 = 4113) -> process respawned with
the front end up. -egg runs stay unmarshaled (the dev shortcut).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 18:10:02 -05:00
CydandClaude Fable 5 58eb25a792 In-game front end: race setup menu builds the mission egg locally
Starting without -egg, -net, or -mr now boots a race-setup screen
(RP_L4/RPL4FE.cpp) instead of aborting: track / vehicle / color / badge
/ time-of-day / weather / race length plus pilot name, populated from
TeslaConsole''s RPConfig.xml catalog (Death Race scenario). LAUNCH
builds the egg exactly as the console did - the RPMission.ToEggString
port, including the pilot name pre-rendered to 1bpp plasma bitmaps
(128x32 + 64x16) via GDI with the console''s auto-shrink font logic and
the verbatim ordinal graphics - writes frontend.egg, and injects it
into the standard egg-load path (new L4Application::
SetEggNotationFileName).

The menu is a GDI child of the main window (pod green-on-black, double
buffered, mouse driven, EDIT control for the name) running a modal loop
before engine init; closing the window exits cleanly. Found and fixed
along the way: the empty egg CString holds a NULL representation
(operator! is the safe emptiness test), and the modal loop needed a
queue nudge for launch clicks delivered via SendMessage.

Verified end to end: boot -> menu -> LAUNCH -> generated egg (7.5KB) ->
racing in the 1080p cockpit with score and mission clock running.
start-windowed.bat now boots into the front end.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 16:20:05 -05:00
CydandClaude Fable 5 f842425452 Front-end design notes: TeslaConsole control code analysis + Steam plan
Findings from TeslaConsole.RedPlanet and L4NET: the pod lifecycle
(egg chunks/ACK, RunMission, telemetry, results), the egg as the entire
mission definition (NotationFile text incl. pre-rendered plasma name
bitmaps), the RPConfig.xml catalog, and the key topology finding -
every pod gets the same egg and builds a deterministic full TCP mesh
from the ordered pilots list (connect to earlier entries, listen for
later). Maps 1:1 onto Steam: lobby owner = console, SteamIDs = pilot
addresses, ISteamNetworkingSockets P2P = the mesh, with a NetTransport
seam at L4NET mirroring the RIOBase pattern. Implementation options and
open decisions listed for signoff.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 15:53:34 -05:00
CydandClaude Fable 5 aa24968c3d Assemble the whole cockpit in a single window
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>
2026-07-12 14:52:26 -05:00
CydandClaude Fable 5 1058de326d Cockpit buttons on the split displays, lamp-lit and clickable
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>
2026-07-12 14:22:38 -05:00
CydandClaude Fable 5 214a8e079c Un-pack the 7-display cockpit in-engine (L4MFDSPLIT=1)
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>
2026-07-12 14:10:52 -05:00
CydandClaude Fable 5 de5a97d37d Workstream A prototype: play without the cockpit
Splits the control surface the game consumes from the RIO board into
RIOBase (8 virtuals + the five analog scalars); the serial RIO is now one
implementation of it. Adds two new ones:

- PadRIO (L4CONTROLS=PAD): in-process RIO speaking the full surface from
  an XInput controller + PC keyboard using vRIO's default profile (left
  stick/WASD = stick, triggers/Q,E = pedals, right stick Y/PgUp,PgDn =
  rate throttle that holds position, A/Space = trigger, B/R = reverse,
  dpad/arrows = hat, Start,Back/F1,F2 = config). Samples in GetNextEvent
  so button latency does not depend on the 15 s menu-time analog cadence;
  hot-plugs pads; L4PADFLIP=XY inverts stick axes; lamp commands land in
  lampState[] for the planned on-screen cockpit panel. The stock
  VTVRIOMapper/lamp/button path runs unchanged.

- PlasmaScreen (L4PLASMA=SCREEN): the 128x32 plasma glass as a desktop
  window in plasma orange (L4PLASMASCALE, default x4), rendering the same
  Video8BitBuffered surface the gauge system always drew; no COM port.

Verified in the sandbox with vRIO off and no serial devices: boots to a
running mission, controller hot-detected, plasma window drawing live game
content (score readout). BUILD.md 4 documents the desktop environ.ini and
bindings; roadmap updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 13:13:37 -05:00
CydandClaude Fable 5 d6745353b1 L4D3D: survive missing textures instead of crashing at mission load
d3d_OBJECT::LoadTexture never checked D3DXCreateTextureFromFileA, cached
the NULL texture, and unconditionally AddRef()ed it - an access violation
on any missing/unreadable texture, hit by every bare working copy because
the pod skins (VIDEO\player1-8) come from the presets/replacement-material
path, not the depot. Failures now log the filename+hr and the draw op
renders untextured, matching the existing no-texture-filename path. Also
guard the unchecked gReplacementData->find() in LoadObject (same latent
UB one branch earlier).

Verified in the sandbox working copy: the game now boots to a running
RPL4 window with -windowed -egg TEST.EGG (RIO served by vRIO), logging
the eight missing pod skins instead of dying in MakeEntityRenderables.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 12:41:29 -05:00
CydandClaude Fable 5 12b31187f9 Move the build to VS2022 (v143) with runtime parity against VC9
Hand-converted the four .vcproj projects to .vcxproj (Win32, v143,
Windows 11 SDK + DXSDK June 2010 for d3dx9/dxerr only). WinTesla.sln now
builds the v143 projects; the legacy solution is kept as WinTesla_vc9.sln.

Kept: /Zp1 in Munga_L4+RP_L4, Unicode, x86, /DYNAMICBASE:NO,
/FORCE:MULTIPLE (header-defined globals still duplicated across TUs).
Changed: CRT unified to /MD(d); import libs linked by the exes instead of
merged into Munga_L4.lib; WINDOWS_IGNORE_PACKING_MISMATCH and
_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS defined;
legacy_stdio_definitions.lib for the June-2010 dxerr.lib.

Source fixes, all behavior-preserving: Time gains standard (non-volatile)
copy-ctor/assignment overloads (rvalues cannot bind to volatile& in
standard C++); operator==(SOCKADDR_IN&,...) made inline; L4DINPUT's
Enum*Callback pair renamed DIEnum* (collided with L4CTRL's under LTCG);
std::ios.in -> std::ios::in in CAMMGR.cpp.

Verified: VC9 baseline rebuilt from this tree first, then the v143 build
compared against it in a sandboxed game working copy - identical logs and
behavior through RIO init (against vRIO) and mission load, including the
same pre-existing AV in d3d_OBJECT::LoadTexture (L4D3D.cpp:262) that both
toolchains hit; documented in BUILD.md 4 as the next debugging target.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 12:22:31 -05:00
CydandClaude Fable 5 467934c968 RP412: fork from RP411 — Steam + internet-multiplayer line
Consumer port of Red Planet: sellable on Steam, internet multiplayer,
playable without cockpit hardware. Adds the project README and
docs/RP412-ROADMAP.md covering the three workstreams (vRIO-derived
input/display, TeslaConsole-derived session UI, Steamworks networking)
and the Steam logistics assessment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 11:08:48 -05:00
CydandClaude Opus 4.8 3b8b729ecb Add complete game working copy under assets/ (runtime data + binaries)
Imports the full shipped working copy of Red Planet v4.10 so the repo is
self-contained: buildable (source) and runnable (data). ~110 MB, committed
directly to git per project decision.

Contents (assets/RP411/):
- AUDIO/  (~97 MB) 223 .wav + audio config/res
- VIDEO/  (~10 MB) .X meshes, .SKL/.det/.sph geometry, .met materials,
          .pcc/.png/.pcx textures, .vsh/.psh shaders, material tables
- GAUGE/  (~0.8 MB) HUD .GIM images, .PCC/.PCX bitmaps, gauge config
- SPOOLS/ runtime replay output dir (kept via .gitkeep)
- Root config/launch: environ.ini, RPDPL.INI, JOYSTICK.INI, TEST.EGG,
  RPL4.RES, *.bat launchers
- Runtime binaries: rpl4opt.exe (shipped reference build), libsndfile-1.dll,
  oalinst.exe (OpenAL redist installer), sleep.exe

Housekeeping:
- .gitignore: re-include assets/**/*.exe and *.dll (global rules skip them);
  keep Thumbs.db and runtime *.spl out.
- .gitattributes: mark asset media (.wav/.png/.pcc/.gim/.x/.skl/... ) binary.
- docs/ASSETS.md: runtime layout, config chain (environ.ini -> RPDPL.INI ->
  video/audio/gauge paths), launch args, and per-directory asset inventory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 10:11:47 -05:00
CydandClaude Opus 4.8 8d18ce0ee4 Wire up remaining DirectX SDK paths; build now succeeds
Verified full build with VC++ 2008 Express SP1 + Windows SDK v6.0A + DirectX
SDK (June 2010): 4 Projects succeeded, 0 failed (Release|Win32). Outputs:
Release\rpl4opt.exe, Release\RPL4TOOL.exe, lib\Munga_L4.lib, lib\DivLoader.lib.

Two projects referenced DirectX but were never repointed at $(DXSDK_DIR)
(they had no hardcoded path to replace earlier):

- DivLoader.vcproj: add "$(DXSDK_DIR)Include" to both compiler configs
  (was failing on D3DX9.h).
- RPL4TOOL.vcproj / RPL4TOOL VS2008.vcproj: add "$(DXSDK_DIR)Lib\x86" to the
  linker search path (was failing with LNK1181 on dinput8.lib).

.gitignore: ignore the build-output static libs that land in lib/
(Munga_L4.lib, DivLoader.lib); the dependency libs OpenAL32.lib and
libsndfile-1.lib stay tracked.

BUILD.md / docs/BUILD-NOTES.md: record the verified build, the CLI recipe,
and the DXSDK_DIR stale-environment gotcha.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 09:56:19 -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 2229f154d1 Clean solution, un-hardcode DirectX SDK path, add build docs
- WinTesla.sln: remove 6 dangling project references (BT410_L4, TextureExp,
  MeshExp, SphereExp, DetailExp, MatReplaceExp) that are not present in the
  repo, plus their config entries. Solution now builds the 4 present projects:
  Munga_L4, RP_L4, RPL4TOOL, DivLoader.
- Munga_L4.vcproj / RP_L4.vcproj: replace hardcoded
  "C:\Program Files (x86)\Microsoft DirectX SDK (March 2009)\" include/lib
  paths with the installer-provided $(DXSDK_DIR) variable, matching the
  existing VS2008 project variants.
- Add BUILD.md (toolchain/SDK requirements and build steps) and
  docs/BUILD-NOTES.md (findings, cleanup history, orphaned files).
- .gitignore: ignore *.sln.cache.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 09:12:29 -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