Files
RP412/pack-dist.ps1
T
CydandClaude Fable 5 3194d3f973 Martian Football: the second scenario is playable
The setup menu gains a SCENARIO group. Picking Football relayouts the
menu live: the track list swaps to the football-legal set (drops
Paingod Passage and the race build of Freezemoon Freeway, adds the
football build headmf - RPConfig per-scenario invalid lists), the
COLOR and BADGE columns become TEAM and POSITION, and the title
reads MARTIAN FOOTBALL.

The egg builder was restructured around one flat pilot table so both
scenarios share it. Football emits scenario=football, per-pilot team=
and position= entries, and the [teams] / [team::X] / [pilots::X] /
[teambitmap] blocks in RPFootballMission layout (team name bitmaps
generated by the same GDI plasma renderer as pilot names). Colors are
derived rather than chosen, as the arcade did it: the runner wears the
team runner color, crushers and blockers the team color. Multi-pod
games alternate pilots across two teams and give each team exactly one
runner, honoring the host own position pick.

Verified end to end: Football launches from the menu, the engine loads
the football mission (the cockpit shows the RUNNER - GO FOR POINTS
panel), the console marshals it to a scored finish, and the Death Race
path still passes its regression unchanged.

Known gap: lobby members cannot pick their own team or position yet -
the host pick seeds a deterministic assignment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 19:42:33 -05:00

273 lines
11 KiB
PowerShell

# ============================================================================
# pack-dist.ps1 - assemble a runnable Red Planet 4.12 package into dist\
# ============================================================================
#
# Collects everything the game needs at run time:
# - Release\rpl4opt.exe (+ .pdb for crash debugging)
# - game data from assets\RP411 (AUDIO, GAUGE, VIDEO, INIs, RPL4.RES,
# TEST.EGG) - but not the arcade launch scripts or the old 4.10 exe
# - libsndfile-1.dll beside the exe; OpenAL32.dll copied from the system
# when installed, with oalinst.exe included as the fallback installer
# - a desktop environ.ini (PAD;KEYBOARD controls, on-screen plasma)
# - start-windowed.bat and a README
#
# Usage: powershell -ExecutionPolicy Bypass -File pack-dist.ps1 [-Zip]
#
param(
[switch]$Zip
)
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $MyInvocation.MyCommand.Path
$dist = Join-Path $root 'dist'
$assets = Join-Path $root 'assets\RP411'
$exe = Join-Path $root 'Release\rpl4opt.exe'
if (-not (Test-Path $exe)) {
throw "Release\rpl4opt.exe not found - build first (see BUILD.md 2)."
}
# Refuse to touch a dist the game is currently running from.
$running = Get-Process rpl4opt -ErrorAction SilentlyContinue |
Where-Object { $_.Path -like "$dist\*" }
if ($running) {
throw "rpl4opt.exe is running from $dist (PID $($running.Id)) - close the game first."
}
Write-Host "Packing into $dist"
if (Test-Path $dist) { Remove-Item -Recurse -Force $dist }
New-Item -ItemType Directory -Force "$dist\SPOOLS" | Out-Null
# --- game binary -----------------------------------------------------------
Copy-Item $exe $dist
$pdb = Join-Path $root 'Release\rpl4opt.pdb'
if (Test-Path $pdb) { Copy-Item $pdb $dist }
# steam_api.dll: the exe imports it (RP412_STEAM build). The Steam wire
# only activates with RP412STEAM=1; plain desktop runs never touch it.
Copy-Item (Join-Path $root 'extern\steamworks_sdk_164\sdk\redistributable_bin\steam_api.dll') $dist
# --- game data -------------------------------------------------------------
foreach ($dir in 'AUDIO', 'GAUGE', 'VIDEO') {
Write-Host " copying $dir..."
Copy-Item -Recurse (Join-Path $assets $dir) $dist
}
foreach ($file in 'RPDPL.INI', 'JOYSTICK.INI', 'RPL4.RES', 'TEST.EGG',
'libsndfile-1.dll', 'oalinst.exe') {
Copy-Item (Join-Path $assets $file) $dist
}
# --- OpenAL runtime --------------------------------------------------------
# The exe links OpenAL32.dll (32-bit). Prefer shipping the already-installed
# runtime beside the exe; oalinst.exe covers machines where that misses.
$openal = "$env:WINDIR\SysWOW64\OpenAL32.dll"
if (-not (Test-Path $openal)) { $openal = "$env:WINDIR\System32\OpenAL32.dll" }
if (Test-Path $openal) {
Copy-Item $openal $dist
$wrap = Join-Path (Split-Path $openal) 'wrap_oal.dll'
if (Test-Path $wrap) { Copy-Item $wrap $dist }
Write-Host " OpenAL runtime copied from $(Split-Path $openal)"
} else {
Write-Warning "OpenAL32.dll not found on this system - dist relies on oalinst.exe"
}
# --- desktop configuration -------------------------------------------------
Set-Content -Path "$dist\environ.ini" -Encoding ascii -Value @"
# ============================================================================
# environ.ini - Red Planet 4.12 configuration
# ============================================================================
# One KEY=VALUE per line, read at game start. Lines starting with # or ;
# are comments; anything without an = is ignored. Delete a line (or
# comment it out) to fall back to the built-in default.
#
# Input bindings live in bindings.txt beside the exe (written with the
# full documented layout on first run; delete it to restore defaults).
# ---- Core (the shipped configuration) --------------------------------------
# Control stack: tokens separated by ; or , processed left to right.
# PAD the virtual RIO (XInput controller + keyboard,
# rebindable via bindings.txt)
# RIO real serial cockpit hardware on COM1
# RIO:COMn same, on another port (RIO:COM3, ...)
# KEYBOARD the engine keyboard handler
# MOUSE, JOYSTICK, FLIGHTSTICKPRO, THRUSTMASTER, DIJOYSTICK
# legacy pointer/joystick drivers (untested here)
# Unset falls back to KEYBOARD alone.
L4CONTROLS=PAD;KEYBOARD
# Renderer bring-up argument. Only its presence is checked (the DPL
# resolution parsing it once fed is gone) and the game refuses to start
# without it - any non-empty value works. Leave as shipped.
DPLARG=1
# DPL (renderer/scene) configuration file, searched beside the exe.
# Any notation file name; RPDPL.INI is the one that ships.
L4DPLCFG=RPDPL.INI
# Gauge (MFD/instrument) canvas. Must name a page of GAUGE\L4GAUGE.INI:
# 640x480x8 | 640x480x16 | 800x600x16
# Unset disables the gauge renderer (and with it all MFDs).
L4GAUGE=640x480x16
# Plasma display.
# SCREEN render the pod's plasma glass in-window (currently
# parked off-layout)
# COM1, COM2... drive real plasma glass on that serial port
# (9600 baud, N81)
# Unset = no plasma display.
L4PLASMA=SCREEN
# 0 = classic separate gauge windows; 1 = the single-window glass
# cockpit (all seven displays composed on a locked 1920x1080 canvas
# around the viewscreen); 2 = exploded diagnostic view (each display
# in its own native-resolution desktop window - MFDs 640x480, map
# 480x640 - decoded exactly as the pod's VDB split them, no downscale).
L4MFDSPLIT=1
# Simulation/render frame rate, integer frames/second. The desktop
# default is 60; the arcade pods shipped at 25.
TARGETFPS=60
# 1 = Steam networking (lobbies, FakeIP mesh). Needs the Steam client
# running and steam_appid.txt beside the exe; without them the game
# logs the reason and falls back to plain TCP. 0 = TCP only.
RP412STEAM=1
# ---- Optional ---------------------------------------------------------------
# RGB keyboard lamp mirror (Windows Dynamic Lighting): keys bound to
# lamp buttons glow with the panel, flash modes and all.
# Unset or nonzero = on (the default); 0 = off.
#RP412KEYLIGHT=0
# Invert the stick on top of whatever bindings.txt produces:
# X = invert X only, Y = invert Y only, XY = both (case-insensitive).
#L4PADFLIP=XY
# Anti-aliasing sample count, passed straight to Direct3D 9:
# 0 = off, else 2..16 as the GPU supports (1 selects the driver's
# "nonmaskable" mode; unsupported counts fail device creation).
#MULTISAMPLE=0
# Particle budget, integer. Default 8192.
#MAXPARTICLES=8192
# On-screen plasma glass (L4PLASMA=SCREEN only). SCALE = integer pixel
# size 1..16, default 4 (out-of-range values are ignored). POS = window
# top-left as X,Y screen coordinates; unset = auto, parked below the
# main window.
#L4PLASMASCALE=4
#L4PLASMAPOS=0,0
# Fixed random seed (repeatable runs): any unsigned integer.
# Unset seeds from the clock.
#RANDOM=12345
# ---- LAN play without Steam -------------------------------------------------
# Host a race over plain TCP: list the member pods' console channels
# (members run: rpl4opt.exe -windowed -res 1920 1080 -net 1501).
# RP412HOSTPODS comma-separated IP[:port] list, one entry per member
# pod; port defaults to 1501 per entry
# RP412HOSTPORT this machine's console port, integer > 0
# (default 1501)
# RP412HOSTADDR this machine's LAN IP as members can reach it
# (default 127.0.0.1)
#RP412HOSTPODS=192.168.1.20:1501,192.168.1.21:1501
#RP412HOSTPORT=1501
#RP412HOSTADDR=192.168.1.10
# ---- Developer / testing ----------------------------------------------------
# Nonzero arms the debug keys: Alt+W wireframe, Alt+V predator vision,
# Alt+F frame dump, Alt+/ perf stats, Alt+E event-queue dump.
# 0 or unset = off. (Alt+Q, the mission abort, is always live.)
#RP412DEVKEYS=1
# Console race-length override, integer seconds (short test races).
# Values <= 0 are ignored.
#L4CONSOLELEN=30
# Nonzero = Steam transport loopback self-test at boot (logs PASS/FAIL).
#RP412STEAMSELFTEST=1
# ---- Arcade heritage (multi-monitor pods; not used on the desktop) ----------
# PRIMGAUGE / SECGAUGE / MFDGAUGE / MFDGAUGE2 pin a display to a monitor
# by adapter index (0, 1, 2...). SPANDISABLE: 0 = let the MFDs span one
# wide surface, nonzero = separate windows (setting MFDGAUGE2 alone also
# forces spanning off). L4EYES = "x y z xrot yrot zrot [type]" floats
# for a detached camera; a type starting with r offsets it relative to
# the pod. L4INTERCOM enables the crew intercom - only its presence
# matters (traditionally COM2). NOMODES skips the mode/lamp programming;
# presence alone triggers it, even NOMODES=0. LOGSIZE > 0 sizes the
# trace log in dev builds compiled with tracing.
#PRIMGAUGE=1
#SECGAUGE=2
#MFDGAUGE=3
#MFDGAUGE2=4
#SPANDISABLE=1
#L4EYES=1
#L4INTERCOM=COM2
#NOMODES=1
#LOGSIZE=1000000
"@
Set-Content -Path "$dist\start-windowed.bat" -Encoding ascii -Value @"
@echo off
rem Red Planet 4.12 - desktop prototype. Boots into the game-setup
rem front end; the cockpit canvas is 1920x1080 and -res matches it.
rem (Add -egg TEST.EGG to skip the menu and run the canned mission.)
cd /d "%~dp0"
start rpl4opt.exe -windowed -res 1920 1080
"@
Set-Content -Path "$dist\README.txt" -Encoding ascii -Value @"
Red Planet 4.12.2
=================
Run start-windowed.bat (or: rpl4opt.exe -windowed -res 800 600 -egg TEST.EGG).
No cockpit hardware needed. If there is no sound, run oalinst.exe once.
Controls (XInput controller and/or keyboard) - EVERY input is
rebindable: edit bindings.txt beside the exe (written with the full
documented default layout on first run; delete it to restore).
Left stick / NumPad 8462 joystick (8=fwd 2=back 4=left 6=right)
LT / RT or NumPad 7,9 left / right pedal
Right stick Y throttle (holds position)
Shift / Ctrl throttle up / down
A / Space / NumPad 0 joystick trigger
RB / Alt reverse thrust
DPad / arrow keys joystick hat (look)
Start,Back / 9,0 config buttons
Number+letter rows MFD bank buttons (as printed on the panel)
F1-F12 secondary / screen columns
Alt+Q abort the mission (score banked)
The full pod cockpit comes up in a single window: three green MFDs
across the top, the 3D viewscreen centered with the orange plasma glass
at its left, and the lower MFDs flanking the portrait map. The red
buttons around each MFD and the amber buttons beside the map are the
pod's real button banks: click them with the mouse, and they light up
as the game commands their lamps.
environ.ini is self-documenting: every option ships in the file with
a comment (Steam networking, keyboard lighting, stick inversion, LAN
hosting, developer keys, and more).
Known prototype notes: pods race untextured (the player1-8 skins come
from the presets system, not shipped data), and text drawn on the plasma
glass may appear rotated.
Source: https://gitea.mysticmachines.com/VWE/RP412
"@
# --- summary / optional zip ------------------------------------------------
$size = (Get-ChildItem $dist -Recurse | Measure-Object Length -Sum).Sum
Write-Host ("dist ready: {0:N1} MB" -f ($size / 1MB))
if ($Zip) {
$zipPath = Join-Path $root 'RedPlanet-4.12.2.zip'
Write-Host "zipping to $zipPath..."
Compress-Archive -Path "$dist\*" -DestinationPath $zipPath -Force
}