New: tools/SiteConfigMerge (net48 console app) - dump: decode any .siteconfig (squads, pods, IPs, MACs, host types) - merge: combine <siteName>.siteconfig inputs into master.siteconfig, renaming squads "<siteName>-<original squad name>" - Pod records pass through byte-for-byte; only squad records (the rename) are re-serialized, under the TeslaConsole assembly identity captured from the input. Stand-in types + SerializationBinder, so no build dependency on TeslaSuite. - Warns on duplicate pod GUID/MAC and cross-site IP overlap. - Verified end-to-end: the real TeslaConsole.exe 4.11.4.1 loaded the merged master via its own Site.LoadFromFile (reflection harness). Doc updates from operator decisions: - Operating model settled: sites voluntarily hand console authority to the central console for the duration of a SiteLink event, by contributing their siteconfig. Federation ruled out at current scale. - Siteconfig "secrets" framing corrected: pod keys have no practical value outside the air-gapped bay; files are exchanged per event and never stored in this repo (tools only). - Fleet scale recorded: 6 active pod bays, <120 cockpits in existence; bay sizes range console+2 cockpits up to the full 20-node complement. Open question 9 answered. - Hub hosting direction: neutral Firestorm host at the WireGuard hub; the FS server usually IS the Live Cam, so stream its output to all sites and optionally to the public internet. Mission Review instance runs at the hub too - one authoritative debrief streamed everywhere. - Virtual PDF scoresheet printer at the hub: event debriefings print centrally, retrievable from any site on the link. - Voice (Mumble) backburnered - revisit only on event interest. - .gitignore: build outputs; siteconfig exclusion rationale reworded. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
195 lines
13 KiB
Markdown
195 lines
13 KiB
Markdown
# The Pod Bay ecosystem — what SiteLink has to work with
|
||
|
||
Surveyed 2026-07-10 from the sibling repos under `C:\VWE`. Every claim below has a source
|
||
pointer so it can be re-verified as those repos evolve.
|
||
|
||
## 1. Physical bay composition and fleet scale
|
||
|
||
A Pod Bay is **an air-gapped network of up to ~20 computers**. Sizes vary widely:
|
||
the smallest active bay is a console + 2 cockpits; the full complement is below.
|
||
Fleet scale (2026): **fewer than 120 cockpits left in existence, 6 currently active
|
||
pod bays** — every design choice in SiteLink should assume single-digit sites and
|
||
a ~120-seat ceiling.
|
||
|
||
| Count | Machine | Software role |
|
||
|------:|---------|---------------|
|
||
| 1 | Command console | Operator station: TeslaConsole (pod management) + the game's console/lobby (Firestorm "BattleTech Console" ConLobby, or the era console for BT/RP) |
|
||
| 16 | Cockpit computers | Run the game exe in pod mode (`-ctcltype 2` for Firestorm) with cockpit I/O (RIO boards → RioJoy/VRio joystick layer) |
|
||
| 1 | Live Cam station | Firestorm: game exe as camera ship (`-ctcltype 3`, `ctcl-camera.ini`) |
|
||
| 1 | Mission Review station | Firestorm: `ctcl-mr.ini`; engine has a dedicated `MSRSpectator` project (`firestorm\Gameleap\code\mw4\Code\MSRSpectator`) |
|
||
| 1 | Printer | Debriefing / scoresheet output (`printdebriefing` flag in PQS game config) |
|
||
|
||
Air-gapped is a *feature*: the cockpit boxes run era Windows images, deliberately hardened
|
||
and never internet-exposed (TeslaLauncher's `install.bat` hardens the box). SiteLink must
|
||
preserve that property — the linked fleet becomes one bigger air-gapped network, not 20×N
|
||
machines on the internet.
|
||
|
||
## 2. Addressing conventions found in the wild
|
||
|
||
- **Dev/legacy bays:** `200.0.0.x` — pods at `.1–.8` and `.11–.18`, camera ship at `.9`
|
||
(see `firestorm\MW4\ctcl-game.ini` `[teslas]`). Note `200.0.0.0/8` is *public* address
|
||
space — harmless while air-gapped, a real conflict once bays are routed together.
|
||
- **FS507D 2016 LAN-center release:** per-machine `10.0.0.x` (release `postinstall.bat`,
|
||
ctcl inis) — already in RFC1918 space, and the convention the SiteLink seed proposal
|
||
generalizes to `10.0.<site>.x`.
|
||
|
||
## 3. Components and their wire protocols
|
||
|
||
### TeslaConsole ↔ TeslaLauncher (pod management plane)
|
||
- **TCP 53290**, length-prefixed JSON frames over an OFB-encrypted stream; per-pod key
|
||
(`TeslaSuite\Contract\PodRpcProtocol.cs`). Console provisions, installs products on,
|
||
and launches games on pods.
|
||
- **First-boot provisioning:** UDP beacons + RSA key exchange (`TeslaSuite\SecureConfig\`)
|
||
— *broadcast-based, local-subnet only*. Provisioning is inherently an on-site act.
|
||
- **`local.siteconfig`** (`C:\VWE\local.siteconfig`): .NET BinaryFormatter graph of
|
||
`TeslaConsole.Squad` (mGuid, mName, mOnline) → `TeslaConsole.Pod` records:
|
||
`mId, mIPAddress, mGateway, mDns, mSubnet, mHostName, mKey, mMacAddress, mName,
|
||
mPodArtPath, mHostType, mOnline`. Two consequences for SiteLink:
|
||
1. "Concatenating" siteconfigs = a real deserialize/merge/reserialize tool — **built:
|
||
[`tools/SiteConfigMerge`](../tools/SiteConfigMerge/README.md)** decodes
|
||
`<siteName>.siteconfig` files and merges them into `master.siteconfig`, renaming
|
||
squads `<siteName>-<original squad name>`. Verified against the real
|
||
TeslaConsole 4.11.4.1 loader. The `Squad` concept maps naturally to
|
||
"one squad per site".
|
||
2. `mKey` is the credential that lets a console command a pod — but it has **no
|
||
practical value outside the bay**: pods live on an air-gapped network, and
|
||
anyone with physical bay access has the siteconfig anyway. Handing your
|
||
siteconfig to the central console is simply how a site joins an event (see the
|
||
brainstorm's authority-handover model). Siteconfigs are exchanged
|
||
operator-to-operator as `<siteName>.siteconfig` and are not stored in this
|
||
repo — they change over time; the repo carries only the tools.
|
||
- **vPOD** (`TeslaSuite\vPOD\`): impersonates both a pod's launcher (TCP 53290) and a
|
||
game client (Munga TCP 1501). **This is our test double for a whole remote bay** — we
|
||
can prototype every SiteLink flow without touching cockpit hardware.
|
||
|
||
### Firestorm (MW4/Gameleap engine) — the flagship game
|
||
- **Game transport: DirectPlay 4** (`IDirectPlay4A`, TCP/IP service provider, DirectPlay
|
||
reliable protocol enabled) — `firestorm\...\GameOS\Net_Main.cpp:387,2226`.
|
||
- Port: registry value `DirectPlayPort` (`Games_LAN.cpp:2307`); `0` = stock DirectPlay
|
||
ports (TCP/UDP 47624 enumeration + dynamic 2300–2400 range). Setting it fixed makes
|
||
firewalling exact.
|
||
- **Directed join works without broadcast:** `TryToJoinASpecificGame(szIPAddress, name)`
|
||
builds a compound address with `DPAID_INet = host IP` and unicasts the session
|
||
enumeration (`Net_Main.cpp:2887–2937`). Broadcast is only the "browse LAN games"
|
||
path. **This is what makes routed (L3) site-linking viable.**
|
||
- Player cap: compiled default **16** (`MW4Shell.cpp:13319`); engine arrays go to 255.
|
||
A drafted, phased **16→32 plan** exists in `firestorm\CLAUDE.md` (code defaults +
|
||
lobby UI + ≥32 drop zones per map). Two full bays in one match needs it; one bay's
|
||
16 split across two sites does not.
|
||
- Replication is ~O(n²) at the session host — host placement/upstream matters.
|
||
- **CTCL — the console↔Tesla control layer:** `ctcl.dll` (client, compiled into
|
||
game/launcher/editor from shared `ctcl.cpp`) + `ctcls.dll` (server side,
|
||
`code\ctcls\`) + per-role inis (`ctcl-game.ini`, `ctcl-camera.ini`, `ctcl-mr.ini`):
|
||
`[teslas]` maps pod IP → pilot seat; `[Games]` lines carry the exe + `-ctcltype`
|
||
role; aux-message and taunt tables. The bay roster is **static config**, which is
|
||
exactly what a site-ID-based addressing scheme can template.
|
||
- *Naming note:* the acronym is never expanded anywhere in source, comments, or
|
||
docs. What **is** attested (`ctcl.h`, `ctcl.cpp`, `ctcl_params.h`): message
|
||
directions are commented "Console 2 Launcher" / "Launcher 2 Console"; role
|
||
constants are `_ECTCL_Console` / `_ECTCL_Launcher`; the API is Tesla-centric
|
||
(`CTCL_GetTeslaCount`, `STeslaInfo`, `MAX_TESLAS 16`, `MAX_CAMERAS 4`) and
|
||
coin-op-aware (`CTCL_CoinDisplay`). So "Console↔Tesla Control Layer/Link" is our
|
||
best reading — treat it as inference, not fact. *(Provenance question is out
|
||
with VWE veterans — update here when word comes back.)*
|
||
- **Game-agnostic:** app-type constants `_EAT_MW4` and `_EAT_RP` (`ctcl_params.h`)
|
||
— the same control layer drives both Firestorm and Red Planet. One layer for
|
||
SiteLink to reason about, not two.
|
||
- **Own ports:** `PORT_Launcher 1000`, `PORT_Game 1001`, `PORT_CameraShip 1001`
|
||
(`Launcher\ctcl.cpp`) — distinct from Munga 1501 and DirectPlay (transport
|
||
details unverified; confirm in Phase 0).
|
||
- **Dedicated server exists:** `mw4dedicatedui` project (`...\mw4\Code\mw4dedicatedui`) —
|
||
option to host cross-site matches on a neutral box instead of one bay's console.
|
||
- **Dormant internet-era code:** MSN Zone "GUN" matchmaking (`Games_GUN.cpp`,
|
||
`GUNGameList.h`) and GameSpy advertisement (`Games_GSpy.cpp`) — dead services, live
|
||
code paths; a revival hook if SiteLink ever wants a fleet-wide game browser.
|
||
- **Voice: backburnered.** The 2016 FS507D release integrated Mumble, but only one
|
||
operator ever ran it. Cross-site voice is technically easy (one server on the shared
|
||
network) — revisit only if event interest warrants it.
|
||
|
||
### BT411 (classic BattleTech — Tesla 4.10 reconstruction, native Win32)
|
||
- **Console-push model over plain TCP:** the console connects to each pod's `-net <port>`
|
||
listener (convention 1501/1601), streams the mission egg in 1040-byte framed chunks,
|
||
then sends `RunMission` twice (`BT411\tools\btconsole.py` documents the full wire
|
||
format, verified against the engine).
|
||
- Pods form their mesh from the egg's `[pilots]` list; the console must stay connected
|
||
for the duration (engine quirk: console loss also closes the game listener).
|
||
- Cross-site implication: `btconsole.py MP.EGG 10.0.1.11:1501 10.0.2.11:1501` is *already*
|
||
a cross-site game launch, modulo whatever the pod↔pod mesh needs (open question: does
|
||
the `[pilots]` list carry literal IPs? → see BRAINSTORM open questions).
|
||
- Status: entity/movement replication works; cross-pod combat in progress.
|
||
|
||
### Red Planet (RP411 — classic Red Planet, Tesla 4.10 reconstruction, native Win32)
|
||
- Same lineage as BT411: the classic Tesla 4.10 title carried forward as a native
|
||
Win32 port (MUNGA engine + L4 platform layer, DX9). Console game-control via
|
||
**Munga protocol, TCP 1501** (vendored `Munga Net.dll` in TeslaConsole 4.11.4).
|
||
Same console-directed model as BT411 (shared `MUNGA_L4\L4NET.CPP`).
|
||
|
||
### TeslaRel410 — the *original* Tesla 4.10 games under emulation
|
||
The third route to the classic titles (`C:\VWE\TeslaRel410`): don't port the game —
|
||
**emulate the 1996 pod computer** and run the original, unmodified DOS executables on
|
||
the current Windows 10 cockpit hardware. Full plan: `TeslaRel410\emulator\PLAN.md`.
|
||
|
||
- **What it is:** archival snapshot of the 1994–96 Tesla:BattleTech and
|
||
Tesla:Red Planet source + content (Borland C++ 5.0 / TASM, MUNGA + MUNGA_L4), plus
|
||
complete runnable DOS installs (`sda4\BTLIVE`, `sda4\RPLIVE`).
|
||
- **The approach:** a custom **DOSBox-X fork** whose main addition is a
|
||
high-level-emulation device impersonating **Division Ltd.'s VPX render board** at
|
||
its host interface (INMOS C012 link adapter, polled I/O at port 0x150) and
|
||
rendering via OpenGL. The cockpit's real **RIO (COM1)** and **plasma display
|
||
(COM2)** are passed through to physical serial ports so the game's own 1996
|
||
drivers run the actual cockpit hardware; SB16 emulation feeds the speakers.
|
||
- **Ultimate goal:** deploy to the current pods — power-on boots straight into the
|
||
game, playable in the cockpit (plan estimates ~3–5 months focused work; gauges
|
||
deferred). *Note: none of the cockpit software has an attract mode — these titles
|
||
were never deployed as walk-up public arcade machines. Firestorm had plans for
|
||
one, never finished.*
|
||
- **Networking — the SiteLink-relevant part:** the original pods networked over
|
||
Ethernet using **WATTCP (DOS TCP/IP) via VWE's NetNub layer**
|
||
(`CODE\*\MUNGA_L4\NETNUB\`). Pod addressing is static configuration. (BOOTP
|
||
appears in a few WATTCP headers but was never actually implemented anywhere —
|
||
don't design against it.) The emulator exposes the stack through **NE2000
|
||
emulation bridged via pcap** — i.e. the emulated game gets a real presence on the
|
||
bay LAN with its own MAC/IP. Consequences:
|
||
1. It's plain IP — in principle it routes across a SiteLink VPN like any other
|
||
bay host (an emulated pod could be a `10.0.y.x` address).
|
||
2. Pod-to-pod/console addressing inside NetNub (discovery, mesh formation,
|
||
latency assumptions of a 30 Hz 1996 sim) is unverified for cross-subnet play —
|
||
open question, testable cheaply since emulator instances run on any PC.
|
||
- **Relationship to BT411/RP411:** two complementary strategies for the same
|
||
titles — native reconstruction (BT411/RP411, modern netcode we control) vs
|
||
faithful emulation (TeslaRel410, original binaries, original protocols). SiteLink
|
||
should assume *both* may want cross-site play eventually.
|
||
|
||
### Support tooling
|
||
- **PQS — Pod Queue System** (`C:\VWE\PQS`): operator-built event tooling — developed
|
||
by the pod owner to manage traffic flow when bringing pods to events, not part of
|
||
the standard bay network. XAMPP (Apache/PHP/MySQL): registration, callsigns,
|
||
combined queue displays, history/search. The game/console side polls simple HTTP
|
||
endpoints (`getFSgame.php` = next mission's type/map/condition flags;
|
||
`getFSplayers.php` = roster; MySQL db `pqs`). **SiteLink scope: support tooling for
|
||
now** — but it's the natural seed if cross-site queue/roster coordination is wanted
|
||
later.
|
||
- **VncThumbnailViewer** (`C:\VWE\VncThumbnailViewer`): operator monitoring of pod
|
||
screens — works fine across a VPN, and a master console could reuse it for fleet-wide
|
||
eyes-on.
|
||
- **RioJoy / VRio**: cockpit hardware I/O → joystick. Purely local to each cockpit;
|
||
SiteLink never touches it.
|
||
- **SheepShaver**: classic-Mac emulation (the original 1990s VGL-era console stack) —
|
||
heritage/reference only.
|
||
- **blackthorn**: archived site builds (Airlock standard install 2018, Firestorm SMT
|
||
builds) — useful as references for how deployed sites were actually configured.
|
||
|
||
## 4. Port map (current, single bay)
|
||
|
||
| Port | Proto | Flow | Purpose |
|
||
|------|-------|------|---------|
|
||
| 53290 | TCP | console → pod | TeslaLauncher RPC (provision/install/launch), OFB-encrypted framed JSON |
|
||
| (local bcast) | UDP | pod ↔ console | SecureConfig first-boot beacons (on-site only) |
|
||
| 1501 | TCP | console → pod | Munga game control (RP; BT411 uses same convention, port per `-net`) |
|
||
| 1000 / 1001 | TCP/UDP (unverified) | console ↔ launcher/game/camera | CTCL control channel (`PORT_Launcher`/`PORT_Game`/`PORT_CameraShip` in `firestorm\...\Launcher\ctcl.cpp`) |
|
||
| 47624 + 2300–2400, or fixed `DirectPlayPort` | TCP/UDP | pod ↔ session host | Firestorm DirectPlay 4 session + game traffic |
|
||
| 80 | TCP | console/game → PQS box | PQS HTTP endpoints (event tooling, when deployed) |
|
||
| 3306 | TCP | PQS internal | MySQL (localhost) |
|
||
| 64738 | TCP/UDP | all → voice server | Mumble (2016 release convention; voice is backburnered) |
|
||
| 5900 | TCP | operator → pods | VNC monitoring (optional) |
|