Files
TeslaRel410/emulator/pod-launch/Modes.cs
T
CydandClaude Fable 5 72da9b2f14 Emulator: parity-safe EMU8000 sample counter -- AWEUTIL runs; wire the
VGL_LABS cockpit test suite as pod-launch 'test' mode

The WC hang, root-caused in three layers (each necessary):
1. WC was rendered-samples + 100ms-capped interpolation; AWEUTIL's poll
   storm (~550k port-ops/s) starved the render thread of awe_lock, so the
   clock crawled ~90x slow. Fixed: free-running host-clock derivation +
   a fairness gate so the render thread can always take the lock.
2. Free-running at true 44.1kHz still failed: trapped port reads cost
   ~30us -- MORE than one 22.7us tick -- so consecutive reads skipped
   counter values, and AWEUTIL's WaitUntilWC (decoded at COM offset
   0x5F42) exits only on EQUALITY with a target tick: skipped value =
   missed target = 1.49s wrap penalty, or forever.
3. Advancing +1 per read still failed: WaitUntilWC reads WC TWICE per
   iteration, so its equality sample saw only every 2nd value -- wrong
   parity = infinite loop. Final semantics: during a poll storm the
   counter advances once per FOUR reads (every value observable by all
   of AWEUTIL's loop shapes; its 8192-unchanged-reads dead-clock bailout
   never trips), and resyncs to true wall time after any 50ms idle gap.
   Result: the full stock TEST.BAT (DIAGNOSE + AWEUTIL /S on both cards)
   completes in seconds.

Also: pod-launch 'test' mode -> vwetest.conf (stock TEST.BAT -> TSTALL),
DOSBox window defaults to 900,600 in test mode (the DOS screen is the
suite's UI), VWE_AWE_LOG gains storm bursts with guest cs:ip + caller and
rare-read tracing (the instrumentation that cracked this).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 23:51:52 -05:00

68 lines
3.2 KiB
C#

// Mode dispatch -- the console's ExitCodeID vocabulary -> how the emulator
// launches it.
//
// KEY (see ../CAMERA-REVIEW-NOTES.md): cockpit, Live-Cam, and LIVE mission-review
// are the SAME networked boot -- the console assigns the role per-IP via the
// egg's hostType= (0 pod / 1 camera / 2 review), so they are NOT separate launch
// modes. `bt` and `rp` cover all three. The only genuinely distinct launches are
// review PLAYBACK (replays last.spl through the non-networked playback app) and
// the DOS diagnostics; their launch mechanics aren't in the archive, so they're
// recognized here but marked unsupported (fail clean, don't guess).
using System;
using System.Text;
namespace VwePod
{
internal sealed class Mode
{
public string Name;
public string ConfBase; // rendered conf basename (no ext); null if not a conf-launch
public bool Supported;
public string Note;
}
internal static class Modes
{
private static readonly Mode[] All =
{
new Mode { Name = "bt", ConfBase = "net_loop", Supported = true,
Note = "BattleTech, networked cockpit. Also serves the camera ship and LIVE mission-review -- the console sets the role per-IP via the egg hostType, so no separate mode is needed." },
new Mode { Name = "rp", ConfBase = "net_rp", Supported = true,
Note = "Red Planet, networked cockpit (also camera / live mission-review via egg hostType)." },
new Mode { Name = "test", ConfBase = "vwetest", Supported = true,
Note = "VGL_LABS factory cockpit test suite (C:\\VWETEST TEST.BAT -> TSTALL.EXE): RIO, plasma, audio (both AWE cards), video/Division calibration, Munga-net diagnostics." },
// Distinct launches, mechanics not yet wired on the emulator:
new Mode { Name = "review", ConfBase = null, Supported = false,
Note = "Mission-review PLAYBACK: replays last.spl through the non-networked playback app (BTL4PlaybackApplication). The DOS launch arg for playback mode is not in the archive -- confirm before wiring." },
new Mode { Name = "test-plasma", ConfBase = null, Supported = false,
Note = "TestPlasmaDisplay diagnostic -- DOS launch mechanic not yet wired." },
new Mode { Name = "reset-rio", ConfBase = null, Supported = false,
Note = "ResetRIO diagnostic -- not yet wired." },
new Mode { Name = "audio-test", ConfBase = null, Supported = false,
Note = "RunAudioTest diagnostic -- not yet wired." },
};
public static Mode Find(string name)
{
if (name == null) return null;
foreach (var m in All)
if (string.Equals(m.Name, name, StringComparison.OrdinalIgnoreCase)) return m;
return null;
}
public static string Names()
{
var sb = new StringBuilder();
foreach (var m in All)
{
if (sb.Length > 0) sb.Append(", ");
sb.Append(m.Name);
if (!m.Supported) sb.Append("(unsupported)");
}
return sb.ToString();
}
}
}