Files
TeslaSuite/vPOD/vPOD.csproj
T
CydandClaude Opus 5 2a5a387381 Console: remember Enable Custom Bitmaps, ship the art; bump suite to 4.11.4.5
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>
2026-07-28 13:16:11 -05:00

87 lines
4.0 KiB
XML

<Project Sdk="Microsoft.NET.Sdk">
<!--
vPOD - a virtual pod / game-client stand-in for testing the Tesla game
consoles (Red Planet and BattleTech) without real cockpit hardware.
It speaks the Munga command/control protocol as a SERVER on TCP 1501 (the
console connects to it exactly as it would a real rpl4opt.exe / btl4.exe),
emulates the pod ApplicationState machine, reassembles the streamed egg,
and shows both on a live display. Deployable to a pod machine via the
console's Manage Site -> Install Product (see dist\ + Console\RedPlanet\Apps.xml).
net40 (XP11): runs on XP SP3 through Windows 11, like the Launcher and the
Console — one flavor everywhere (Contract and SecureConfig included). The
differential tests' net48 host loads all of it fine (net40 and net48 are both
CLR4). The vendored Munga Net.dll is CLR2 pure-IL, so it loads anywhere.
WinForms comes via plain framework references: UseWindowsForms is not wired
up for net40, and all UI here is code-built (no designer).
-->
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net40</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>disable</Nullable>
<ImplicitUsings>disable</ImplicitUsings>
<AssemblyName>vPOD</AssemblyName>
<RootNamespace>VPod</RootNamespace>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<!-- Versioned with the suite since v4.11.4.3 (was its own 1.0.0 line). -->
<AssemblyVersion>4.11.4.5</AssemblyVersion>
<Version>4.11.4.5</Version>
<Product>vPOD</Product>
</PropertyGroup>
<ItemGroup>
<!-- .NET Framework reference assemblies so this builds without a full
targeting pack installed (resolves per-TFM, covers net40 and net48) -->
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Drawing" />
</ItemGroup>
<!-- JSON for LaunchApps.json persistence + RPC arg materialization: Newtonsoft,
matching the Contract (System.Text.Json has no net40 target). -->
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<!-- The differential suite drives the real PodManagerConnection client against
vPOD's LauncherRpcServer in-process (VPodLauncherServerTests). -->
<InternalsVisibleTo Include="TeslaConsole.DiffTests" />
</ItemGroup>
<ItemGroup>
<!-- InstallProduct zips are extracted with the Launcher's own MiniZip on BOTH
legs (ZipFile/ZipArchive are net45+, absent on net40): identical extraction
behavior to the real pod service, and the differential suite's install
round-trip exercises MiniZip against real ZipArchive-built archives. -->
<Compile Include="..\Launcher\MiniZip.cs" Link="MiniZip.cs" />
<!-- The real pod's master-volume chain (nircmd -> CoreAudio -> winmm), for
the "Actually set system volume" mode. Same linked-source sharing. -->
<Compile Include="..\Launcher\VolumeControl.cs" Link="VolumeControl.cs" />
</ItemGroup>
<ItemGroup>
<!-- The Munga wire types (messages, header, enums), vendored under the
console's lib\. Copied next to vPOD.exe so the deployable package is
self-contained. -->
<Reference Include="Munga Net">
<HintPath>..\Console\lib\Munga Net.dll</HintPath>
<Private>true</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<!-- The shared console<->launcher wire libraries, so vPOD can also stand in
for the pod's TeslaLauncher service (Site Management / Install Product):
PodRpc framing + ILauncherService wire types, and the SecureConfig
provisioning protocol + OFB crypto-stream handshake. vPOD implements the
SERVER side of the existing contract only - no new RPCs. -->
<ProjectReference Include="..\Contract\Tesla.Contract.csproj" />
<ProjectReference Include="..\SecureConfig\Tesla.SecureConfig.csproj" />
</ItemGroup>
</Project>