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>
The Launcher's XP11 port (8730b9b) now extends to everything: one net40
flavor across Console, vPOD, Contract, and SecureConfig (Newtonsoft.Json
everywhere; the net48/System.Text.Json legs and their #if splits are gone
since nothing consumed them).
Console (net40, single TFM like the Launcher):
- The ~31 BinaryFormatter bitmap blobs in the .resx files became raw
embedded files under assets/icons/ (extracted byte-faithfully via a
serialization surrogate — the animated square_throbber.gif survives),
loaded by Properties.Resources.EmbeddedBitmap/EmbeddedIcon. Reason:
System.Resources.Extensions' DeserializingResourceReader is net461+
and cannot load on net40. Strings stay in the .resx.
- IReadOnlyList -> IList in AppRegistry (net45+ interface).
vPOD (net40, single TFM):
- Zip extraction now shares the Launcher's MiniZip.cs (linked source), so
the diff-test install round-trip exercises it against ZipArchive zips.
- RPC args as JTokens; LaunchApps.json persistence via Newtonsoft;
Thread.VolatileRead instead of Volatile.Read.
Contract/SecureConfig: net40-only; Client/** (PodManagerConnection) now
ships in the one build. The Launcher package gains
TeslaSecureConfiguration.dll as a dependency of the client half.
Tests: the net48 xunit host loads the net40 assemblies (both CLR4), so
the suite exercises exactly what ships — 106/106 green. Also verified
live: net40 console provisioned, managed, and ran a full RP mission
against net40 vPOD (beacon/passphrase/RSA, 53290 RPC, egg load,
Run/Stop Mission).
Version: 4.11.4.3 across Launcher, Console, and vPOD (vPOD joins the
suite version line; was 1.0.0). Ship the dotNetFx40 redistributable in
Launcher/assets for XP-era pods.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
vPOD has outgrown its home inside the console's folder: it now emulates both
halves of a pod (Munga game client + TeslaLauncher service / provisioning),
so it lives at the repo root beside Console/, Launcher/, Contract/ and
SecureConfig/, like the peer it has become.
Accompanying changes: project references rebased (Contract, SecureConfig,
the console's vendored Munga Net.dll), solution + DiffTests reference paths,
the console csproj's now-obsolete vPOD source exclusion removed, and the
root README / Apps.xml / vPOD README path mentions updated. pack.ps1 is
self-relative and now emits vPOD/dist/vPOD.zip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
vPOD impersonates a Tesla game client (rpl4opt.exe / btl4.exe) so the Red
Planet and BattleTech operator consoles can be exercised without real cockpit
hardware. New net48 WinForms project under Console\vPOD:
- MungaPodServer: the server half of the Munga control protocol (TCP 1501).
The vendored MungaSocket is client-only, so this reimplements the identical
framing ([16-byte header][12-byte base + body], dispatched by
ClientID+MessageID) for the listening side, reusing the vendored message
classes' WriteTo/BinaryReader serialization.
- PodSimulator: the ApplicationState machine driven by the console's messages -
answers StateQuery, reassembles the streamed egg and acknowledges it, and
walks WaitingForEgg -> LoadingMission -> WaitingForLaunch -> RunningMission
and back on Run/Stop/Abort/Suspend/Resume.
- VPodForm: live display of listening/connection status, the colour-coded
ApplicationState, an egg viewer (fields + summary), and a newest-first
protocol log. A Red Planet / BattleTech toggle changes which ApplicationID
the pod reports, live, so one vPOD stands in for either game.
- PodArguments: parses the real client's launch flags (-net/-app/-lc/-mr/
-host/-res).
Deployable from Manage Site -> Install Product: a catalog product in
RedPlanet\Apps.xml (Game Client / Live Camera / Mission Review entries) plus
pack.ps1, which builds dist\vPOD.zip laying out vPOD\vPOD.exe for the launcher
to extract to C:\Games\vPOD. CatalogTests updated to 5 products / 11 entries
with the four vPOD entry assertions (88/88 pass). TeslaConsole.csproj excludes
vPOD\** from its **/*.cs glob; the project is added to the solution.
Verified end-to-end over real TCP: a console-role client using the vendored
MungaSocket drives connect -> WaitingForEgg -> stream egg -> (ack) ->
WaitingForLaunch -> Run -> RunningMission -> Stop -> WaitingForEgg, with vPOD
reporting the correct state at each step. MungaGame (what the console's game
windows use) is a thin wrapper over MungaSocket, so this exercises the exact
wire behaviour.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Completes the BattleTech console feature to parity with Red Planet:
- BTPrintDocument: the per-pilot landscape score sheet (mech portrait,
placing, kill/death/damage stats, randomized mission-highlights narrative,
pilot-vs-pilot damage matrix, place-over-time chart), mirroring
RPPrintDocument minus the football/lap/boost/score-zone concepts. Wired into
BTGame (Auto Print checkbox + Print Last Mission button) and the shell's File
menu (BT Mission Print Preview / Print BT Mission, loading .btm files).
- BTStrings(.xml): the BT mission-highlight narrative pools (damage tiers,
kill, death-without-honor, recap), loaded from BattleTech\BTStrings.xml like
RPStrings.
- BTDefaultsDialog: two-column (Free For All / No Return) editor for the BT
operator defaults, reachable from Settings (Change/Import/Export BattleTech
Defaults). Verified via UI Automation: opens with all 18 option combos
populated.
- Apps.xml: the BattleTech 4.11 product (btl4.exe on the shared RP411 engine,
same -net/-res/-lc/-mr command line; deploys to C:\Games\BT411) with Game
Client / Live Camera / Mission Review launch entries. CatalogTests updated to
4 products / 8 entries plus the three new BT entry assertions.
Role model spelling corrected to "noreturn": the Mac Console.ini tag and the
game's BTL4.RES role resource are dfltrole/NoReturn; the 4.10 console's eggs
emitted a broken "noretun" that cannot resolve against the RES. BTGoldenEggTests
and BTConfig.xml updated accordingly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New TeslaConsole.BattleTech namespace mirroring TeslaConsole.RedPlanet's
mission layer: BTMission/BTFreeForAllMission (egg serializer; RP wire framing
and ordinal bitmaps reused verbatim), BTParticipant/BTPlayer/BTCamera (BT
participant fields: advancedDamage, experience, vehicleValue, patch, role),
and the BTConfig/BTScenario/BTMap/BTVehicle/BTWeather/BTRole catalog loaded
from BattleTech\BTConfig.xml (reconstructed from the Mac Console 4.10 ini BT
tree). Free For All and No Return share one mission class - both send
scenario=freeforall; the mode is the role assigned to each pilot.
BTGoldenEggTests (7 tests, recovered-only) diff the generated egg
field-by-field against two eggs captured from the original consoles
(cavern.egg, TESTARN.EGG): order-independent per-section compare with
font-rendered bitmap pixel rows excluded, ordinal art byte-exact vs
TESTARN.EGG, EggFileMessage framing reassembly, role de-dup, No Return role
semantics, and shipped-catalog contents. Invoker gains BTEggString/
BTEggFraming reflection cases.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Make the Console<->Launcher system source-built and modern now that the console
is under our control and the WinXP-era pods are gone.
Contract extraction (Contract/Tesla.Contract.csproj):
- One multi-targeted (net48;net8.0-windows) source project for the RPC contract,
replacing the vendored TeslaConsoleLaunchLib.dll and the hand-synced Tesla.Net
replica in Launcher/LaunchModels_Shared.cs. Emits assembly TeslaConsoleLaunchLib.
SecureConfig extraction (SecureConfig/Tesla.SecureConfig.csproj):
- net48 source of the first-boot provisioning protocol (UDP beacons, OFB crypto,
RSA key exchange), replacing the vendored TeslaSecureConfiguration.dll.
Remove BinaryFormatter from the wire (RCE sink + the reason net6 was pinned):
- Console<->Launcher RPC is now length-prefixed System.Text.Json frames
(Contract/PodRpcProtocol.cs) over the unchanged OFB transport; dispatch by
method name. Deleted the SerializationBinder / MethodInfoProxy machinery.
- Console-local BinaryFormatter (Site config, mission replays) intentionally
retained: local net48 file I/O, not the network surface.
Runtime modernization:
- Launcher Service + Agent: net6 -> net8, win-x86 -> win-x64 (all pods are
64-bit Win10). Kept the SHA1-default PBKDF2 (Console key-derivation compat)
with SYSLIB0041 suppressed and documented.
Tests: differential suite now 73 green. Added SecureConfigCompatTests (OFB
ciphertext byte-identical to the vendored DLL) and PodRpcProtocolTests (JSON
round-trip of every request/response shape); removed the now-obsolete
BinaryFormatter byte-identity guard.
Build hygiene: per-project obj dirs (Launcher/Directory.Build.props) fix a
NuGet restore collision between the two Launcher projects sharing one folder.
NOT runtime-verified against a live pod.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-locate the two cockpit-pod projects into a single repository:
- Console/ : TeslaConsole, the net48 WinForms operator console (decompiled
reconstruction) plus its differential + catalog test suite.
- Launcher/ : TeslaLauncher, the net6 pod-side Service + Agent rewrite.
Adds a combined TeslaSuite.sln, root README documenting the shared wire
contract (and its current duplication, the main follow-up), and a root
.gitignore. Histories were not preserved per request; this is a fresh start
from the current working state of both projects.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>