Settings -> Enable Custom Bitmaps was a static bool with no backing store: it defaulted to off on every launch, so an operator had to re-tick it each session and any custom plasma art was silently ignored until they did. New ConsoleSettings persists machine-level menu toggles as XML in %ProgramData%\Tesla Console\console.settings, alongside RPDefaults.rpd / BTDefaults.btd / local.siteconfig. It is loaded once from Main and never from a static initializer: the differential suite drives PlasmaBitmaps directly and must keep seeing the original defaults rather than whatever this machine has saved. A missing file is the first-run case; a corrupt one is ignored and rewritten by the next toggle, because losing a menu setting must never stop the console starting. Custom art is now version-controlled and rolls with the release. New Console\Plasma Images\ is copied into the package, and the lookup searches %ProgramData%\Tesla Console\Plasma Images first and the exe-relative folder second, so a release can never clobber a site's own name bitmaps. install.bat creates the data-dir folder before the icacls grant so an unelevated operator can write it. Ships with three 128x32 name bitmaps (Deadmeat, Muerte, Phrogg); Muerte arrived as "Muerte_128x32-2.bmp", a name the lookup can never build, so it is renamed to match its pilot. Two fixes fell out of making the flag sticky. Path.Combine ran on the raw participant name outside the try block, so with the option on a pilot named "A:B" threw ArgumentException straight out of egg generation; names that cannot be a Windows file name now just render procedurally. And the art was loaded with Image.FromFile, which keeps the bitmap backed by the file and locked for its whole lifetime — it is copied out through a stream now, so art can be swapped between missions without restarting the console. Verified against the built net40 exe: all three shipped bitmaps resolve by pilot name, ProgramData wins over the shipped copy, a wrong-size file is ignored, an illegal-character name does not throw, the file is not left locked, and the settings round-trip and corrupt-file tolerance both hold. Diff suite 106/106. Version bumped 4.11.4.4 -> 4.11.4.5 across Console, Launcher, vPOD, the install/build banners, the diff-suite version assertion and the README's latest-release pointer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
TeslaLauncher (XP11 — single binary)
.NET Framework 4.0 (framework-dependent) rewrite of the original Elsewhen Studios LLC
software. One TeslaLauncher.exe runs on Windows XP SP3 through Windows 11:
net40 is the newest framework XP can install, and net40 assemblies load in-place on the
4.8 runtime built into Windows 10/11. XP pods need the .NET 4.0 redistributable
(installed automatically by install.bat when dotnet40\ is in the package);
Win10/11 pods need nothing extra.
Architecture
One userland tray application — no Windows Service, no IPC.
The original Elsewhen software was a single service (on Win2k/XP a service could still touch the desktop). The modern rewrite split it into Service + Agent purely to work around Vista+ Session 0 isolation. XP11 closes the loop: everything runs in the auto-logged-in kiosk session, where the desktop, audio, and game processes live anyway.
TeslaLauncher (WinForms tray app, user session)
- Listens on TCP 53290 for OFB-encrypted framed-JSON RPC from TeslaConsole
- Handles first-boot network configuration (SecureConfig) and shows the Request ID / Passphrase on screen + COM2 plasma
- Handles game file transfers from the Console (InstallProduct →
C:\Games,postinstall.bat,pre-uninstall.baton uninstall) - Launches/kills/watches simulation apps, controls volume, manages
LaunchApps.xml - Registers with WER for restart-after-crash (Vista+; no-op on XP)
Requires the kiosk account (Firestorm) to be in Administrators — SecureConfig's
netsh/hostname writes and product postinstall.bat driver installs need the admin
token (UAC is disabled by the installer on modern Windows, so no prompts).
SecureConfig (first-boot protocol)
- Assigns a temporary IP and broadcasts a UDP beacon so the Console can discover the pod
- Operator reads the Passphrase off the pod screen and enters it into the Console
- Console sends AES-encrypted network configuration (IP, mask, gateway, DNS, hostname)
- TCP handshake establishes an OFB-encrypted session with RSA key exchange
- Session key is saved for all subsequent Console connections
Uses the old-style netsh interface ip commands throughout — they update the live
TCP/IP stack immediately and are the only form XP understands.
Communication Flow
TeslaConsole ──TCP 53290 (OFB + framed JSON)──> TeslaLauncher.exe (user session)
Files
| File | Description |
|---|---|
TeslaLauncher.cs |
The whole launcher: tray, TCP listener, RPC dispatch, install, processes, volume |
TeslaLauncher.csproj |
net40 WinForms exe project |
MiniZip.cs |
Central-directory ZIP extractor (net40 has no ZipFile; stored + deflate + ZIP64) |
SecureConfig.cs |
First-boot secure configuration protocol + OFB duplex stream |
build.bat |
Builds + assembles the package |
install.bat |
Dual-OS installer (XP SP3 and Win10/11 code paths; run as Administrator) |
Building
Requirements:
- .NET SDK (6.0+) to drive the build
- Internet access for NuGet restore (first build only)
build.bat :: build + assemble the package
Output goes to dist\TeslaLauncher\ (with App\ plus install.bat and redist
folders) and dist\TeslaLauncher-podpkg.zip. The project is published in place
(framework-dependent net40) — it references ../Contract, so it cannot be staged
into a temp folder. App\ holds the exe plus Newtonsoft.Json.dll and
TeslaConsoleLaunchLib.dll (the net40 leg of the shared contract).
Bench-testing switches
TeslaLauncher.exe /skipconfig :: skip the DHCP SecureConfig gate
TeslaLauncher.exe /port:53291 :: listen on a non-standard port
Installation
- Copy the
TeslaLauncher\folder to each cockpit PC (XP SP3 or Win10/11) - Run
TeslaLauncher\install.batas Administrator
The installer detects the OS and branches where the tooling differs:
| Step | XP SP3 | Windows 10/11 |
|---|---|---|
| .NET | installs 4.0 redist from dotnet40\ if missing |
4.8 built in — nothing |
| ACLs | cacls |
icacls |
| Firewall off | netsh firewall |
netsh advfirewall |
| SMB1 / DirectPlay | native — skipped | dism /Enable-Feature |
| DHCP reset | netsh interface ip set address ... dhcp |
PowerShell Set-NetIPInterface |
| Notifications / UAC | n/a | policy keys + EnableLUA=0 |
| UltraVNC | UltraVNC_x86_Setup.exe (if bundled) |
UltraVNC_x64_Setup.exe |
Common to both: auto-login (Firestorm), HKLM Run key for the launcher
(no service registration), C:\Games + data dir creation, shares, workgroup,
power settings, reboot.
First Boot
- Cockpit boots with DHCP (unconfigured state), auto-logs into the kiosk account
- Launcher runs SecureConfig: broadcasts beacon, displays codes on screen + plasma
- Console operator sees the pod's Request ID and enters the Passphrase
- Console sends encrypted network configuration
- Pod applies the configuration and is ready for normal operation
Normal Operation
The Console connects to each configured pod on TCP 53290 and can:
- Install/uninstall simulation games
- Launch/kill applications
- Get/set volume level
- Query pod status (FullUpdate)
- Shutdown or reboot the pod
Key Paths
<CommonAppData> is C:\ProgramData on Vista+, and
C:\Documents and Settings\All Users\Application Data on XP — the launcher and
installer both resolve it per-OS; nothing hardcodes C:\ProgramData anymore.
| Path | Purpose |
|---|---|
<CommonAppData>\TeslaLauncher\TeslaKeyStore.key |
Session key (32 bytes) |
<CommonAppData>\TeslaLauncher\LaunchApps.xml |
Installed games registry (same XML shape as the two-process Agent wrote) |
<CommonAppData>\TeslaLauncher\podconf.log |
Launcher log (was next to the exe pre-XP11) |
<CommonAppData>\TeslaLauncher\configuring.json |
Transient: SecureConfig codes (kept for external diagnostics) |
C:\Games\ |
Game installation directory |
Wire Protocol
The Console talks to the launcher with length-prefixed JSON frames over the
OFB-encrypted TCP stream (dispatch by method name) — see
../Contract/PodRpcProtocol.cs, shared by both ends. Since the whole suite went
net40 (XP11), both ends serialize with Newtonsoft.Json and the Contract is
net40-only (its former net48/System.Text.Json leg wrote shape-identical JSON and
was dropped once the Console moved to net40). The request reader keeps date
strings raw so a Ping echo returns byte-identical.
Volume on XP falls back from CoreAudio (Vista+) to nircmd.exe / winmm
waveOutSetVolume.