diff --git a/restoration/source410/BT_L4/BTL4.CPP b/restoration/source410/BT_L4/BTL4.CPP index cef1c512..b041565b 100644 --- a/restoration/source410/BT_L4/BTL4.CPP +++ b/restoration/source410/BT_L4/BTL4.CPP @@ -1,91 +1,128 @@ -//===========================================================================// -// File: btl4.cpp // -// Project: BattleTech Brick: BattleTech LBE Application // -// Contents: Application launcher (main) // -//---------------------------------------------------------------------------// -// Date Who Modification // -// -------- --- ---------------------------------------------------------- // -// // -//---------------------------------------------------------------------------// -// Copyright (C) 1995, Virtual World Entertainment, Inc. // -// All Rights reserved worldwide // -// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // -//===========================================================================// - -#include -#pragma hdrstop - -#if !defined(BTL4APP_HPP) -# include -#endif - -#if !defined(APPMGR_HPP) -# include -#endif - -#if !defined(BTL4VER_HPP) -# include -#endif - -//########################################################################## -//#################### BTL4Application Globals ####################### -//########################################################################## - -extern const char* const ProgName; -const char* const ProgName = "btl4"; - -static Byte - version[3] = - {MAJOR_DATA_VERSION, RELEASE_VERSION, MINOR_DATA_VERSION}; - -// -//############################################################################# -// main -//############################################################################# -// -int - main(int argc, char *argv[]) -{ - DEBUG_STREAM << "BattleTech v4.10" << endl; - - if (!L4Application::ParseCommandLine(argc, argv, L4Application::ParseToken)) - { - return 1; - } - - StreamableResourceFile - resources("btl4.res", version); - - ApplicationManager - *application_manager = NULL; - - if (L4Application::GetMissionReviewMode() < 1) - { - application_manager = - new ApplicationManager(GetTicksPerSecond()); - - Application - *application = new BTL4Application(&resources); - - application_manager->StartApplication(application); - } - else - { - // - //------------------------------------------------------------------- - // Mission review / live-camera launch (missionReviewMode >= 1): - // a MissionReviewApplicationManager with a SPOOLSIZE-byte packet - // spool plus BTL4PlaybackApplication -- those bricks are not yet - // reconstructed (see BTL4.NOTES.md for the decompiled structure). - //------------------------------------------------------------------- - // - Fail("btl4.cpp -- mission review/camera launch not yet reconstructed"); - return 1; - } - - application_manager->RunMissions(); - - delete application_manager; - - return Exit_Code; -} +//===========================================================================// +// File: btl4.cpp // +// Project: BattleTech Brick: BattleTech LBE Application // +// Contents: Application launcher (main) // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(BTL4APP_HPP) +# include +#endif + +#if !defined(APPMGR_HPP) +# include +#endif + +#if !defined(BTL4VER_HPP) +# include +#endif + +#if !defined(BTL4PB_HPP) +# include // BTL4PlaybackApplication -- the review app +#endif + +#if !defined(SPOOLER_HPP) +# include // MissionReviewApplicationManager / SpoolFile +#endif + +//########################################################################## +//#################### BTL4Application Globals ####################### +//########################################################################## + +extern const char* const ProgName; +const char* const ProgName = "btl4"; + +static Byte + version[3] = + {MAJOR_DATA_VERSION, RELEASE_VERSION, MINOR_DATA_VERSION}; + +// +//############################################################################# +// main +//############################################################################# +// +int + main(int argc, char *argv[]) +{ + DEBUG_STREAM << "BattleTech v4.10" << endl; + + if (!L4Application::ParseCommandLine(argc, argv, L4Application::ParseToken)) + { + return 1; + } + + StreamableResourceFile + resources("btl4.res", version); + + ApplicationManager + *application_manager = NULL; + + if (L4Application::GetMissionReviewMode() < 1) + { + application_manager = + new ApplicationManager(GetTicksPerSecond()); + + Application + *application = new BTL4Application(&resources); + + application_manager->StartApplication(application); + } + else + { + // + //------------------------------------------------------------------- + // Mission review / live-camera launch (mode 1 = camera, 2 = review). + // + // The manager owns SPOOLSIZE-byte packet spools (default 8MB); a + // STORED spool starts the playback application over it, and camera + // mode additionally starts the engine's spooling application -- the + // recorder -- as a second app (the binary's FUN_0047c3fc ctor is + // L4SpoolingApplication's, ApplicationID 1 == BTL4). + //------------------------------------------------------------------- + // + int + spool_size = + (getenv("SPOOLSIZE") != NULL) + ? atoi(getenv("SPOOLSIZE")) + : 0x800000; + DEBUG_STREAM << "Spool size = " << spool_size << endl; + + MissionReviewApplicationManager + *review_manager = + new MissionReviewApplicationManager( + GetTicksPerSecond(), + (L4Application::GetMissionReviewMode() != 2) ? 2 : 1, + spool_size + ); + application_manager = review_manager; + + SpoolFile + *spool_file = review_manager->GetStoredSpoolFile(); + if (spool_file != NULL) + { + review_manager->StartApplication( + new BTL4PlaybackApplication(&resources, spool_file)); + } + if (L4Application::GetMissionReviewMode() == 1) + { + review_manager->StartApplication( + new L4SpoolingApplication(&resources, (ApplicationID)1)); + } + } + + application_manager->RunMissions(); + + delete application_manager; + + return Exit_Code; +} diff --git a/restoration/source410/BT_L4/BTL4.NOTES.md b/restoration/source410/BT_L4/BTL4.NOTES.md index f629b15e..5b289142 100644 --- a/restoration/source410/BT_L4/BTL4.NOTES.md +++ b/restoration/source410/BT_L4/BTL4.NOTES.md @@ -1,65 +1,70 @@ -# BTL4.CPP — reconstruction notes - -**Status: RECONSTRUCTED (normal launch path); review/camera branch staged with Fail().** - -The 4.10 main TU. No original survives anywhere in the archive (OPT.MAK links -`btl4.obj` as a bare object next to the libs — it was never a lib member). - -## Evidence base - -1. **Ghidra decomp of the 4.11 binary** — `C:\VWE\BT411\reference\decomp\all\part_000.c`, - `FUN_0040109c` (the 524-byte function the Borland startup calls = `main`). - The 4.10 and 4.11 binaries share the same string pool layout for this TU. -2. **String pool of the original 4.10 `BTL4OPT.EXE`** (ALPHA_1/REL410/BT), file - offset ~917884: `"btl4" "HEAPSIZE" "BattleTech v4.10" "btl4.res" "SPOOLSIZE" - "Spool size = "` — banner text and resource name byte-exact. -3. **Surviving 1995 launcher-style TU** `CODE/RP/RP_L4/RPL4TOOL.CPP` — house - style for `main(int, char*[])` and the `ProgName` global pattern. -4. **BT411's win32 launcher** `game/btl4main.cpp` (adapted from RP's RPL4.CPP) - independently reconstructs the same skeleton and pins `version[3] = {1,0,6}` - against the RESOURCE.cpp version check. - -## Decoded decomp → source mapping - -| decomp | source | -|---|---| -| `FUN_004dbb24(&cout, "BattleTech v4.10", 0); FUN_004d9c38(&cout)` | `DEBUG_STREAM << "BattleTech v4.10" << endl` | -| `FUN_0047b2ec(argc, argv, &LAB_0047af8c)` | `L4Application::ParseCommandLine(argc, argv, L4Application::ParseToken)` | -| `FUN_00407218(stack84, "btl4.res", &DAT_004e0070, 3)` | `StreamableResourceFile resources("btl4.res", version)` (match_level=3 is the declared default) | -| `DAT_004e0070` = 3 bytes | `version[3]` = `{MAJOR_DATA_VERSION, RELEASE_VERSION, MINOR_DATA_VERSION}` = {1,0,6} from BTL4VER.HPP | -| `DAT_004fd550 < 1` | `L4Application::GetMissionReviewMode() < 1` (inline static accessor) | -| `new(0x28) FUN_0044f29c(this, DAT_0052140c)` | `new ApplicationManager(GetTicksPerSecond())` (inline friend accessor, TIME.HPP:49) — DAT_0052140c is set to 28.0f by `SystemClock::SystemClock()` (L4TIME.CPP:93) when `L4TIMER=FAST` | -| `new(0xd4) FUN_004d34c4(this, &resources, 0x3EB, &DAT_0051e8d8)` | `new BTL4Application(&resources)` — 0x3EB/`DefaultData` are the declared default args (BTL4APP.HPP:34) | -| `FUN_0044f318(mgr, app)` | `application_manager->StartApplication(application)` | -| `FUN_0044f344(mgr)` | `application_manager->RunMissions()` | -| vcall slot 0 (mgr, 3) | `delete application_manager` | -| `return DAT_004efc98` | `return Exit_Code` (APP.HPP:542) | - -## Review/camera branch (NOT yet reconstructed — staged Fail) - -Decomp structure for `missionReviewMode >= 1` (mode 1 = camera, 2 = review per -emulator/CAMERA-REVIEW-NOTES.md): - -``` -spool_size = getenv("SPOOLSIZE") ? atoi(...) : 0x800000; // "Spool size = " printed -mgr = new(0x38) MissionReviewApplicationManager(ticksPerSecond, - (mode != 2) ? 2 : 1, spool_size); -spool_file = ; -if (spool_file) - mgr->StartApplication(new(0xd8) BTL4PlaybackApplication(&resources, spool_file)); -if (mode == 1) - mgr->StartApplication(new(0xd8) (&resources, 1)); -``` - -Class declarations survive: `BTL4PlaybackApplication` (CODE/BT/BT_L4/BTL4PB.HPP), -spooler bricks in CODE/RP/MUNGA_L4/L4SPLR.HPP (`MissionReviewApplicationManager` -referenced there). Their .CPP bodies are not staged, so the branch Fails loudly -instead of linking half a subsystem. - -## Deliberate differences from the binary - -- `HEAPSIZE` string sits in the pool between ProgName and the banner but is not - referenced from the decompiled main — it likely belongs to the runtime heap - init, not this TU. Not reproduced. -- `Register_Object`/`Start_Registering` debug bookkeeping is absent from the - optimized binary (DEBUG_LEVEL=0 compiles it out), so it is not written here. +# BTL4.CPP — reconstruction notes + +**Status: FULLY RECONSTRUCTED (2026-08-03) — both launch paths. The review/camera branch links against the real BTL4PB + L4SPLR bricks; no Fail() remains in this TU.** + +The 4.10 main TU. No original survives anywhere in the archive (OPT.MAK links +`btl4.obj` as a bare object next to the libs — it was never a lib member). + +## Evidence base + +1. **Ghidra decomp of the 4.11 binary** — `C:\VWE\BT411\reference\decomp\all\part_000.c`, + `FUN_0040109c` (the 524-byte function the Borland startup calls = `main`). + The 4.10 and 4.11 binaries share the same string pool layout for this TU. +2. **String pool of the original 4.10 `BTL4OPT.EXE`** (ALPHA_1/REL410/BT), file + offset ~917884: `"btl4" "HEAPSIZE" "BattleTech v4.10" "btl4.res" "SPOOLSIZE" + "Spool size = "` — banner text and resource name byte-exact. +3. **Surviving 1995 launcher-style TU** `CODE/RP/RP_L4/RPL4TOOL.CPP` — house + style for `main(int, char*[])` and the `ProgName` global pattern. +4. **BT411's win32 launcher** `game/btl4main.cpp` (adapted from RP's RPL4.CPP) + independently reconstructs the same skeleton and pins `version[3] = {1,0,6}` + against the RESOURCE.cpp version check. + +## Decoded decomp → source mapping + +| decomp | source | +|---|---| +| `FUN_004dbb24(&cout, "BattleTech v4.10", 0); FUN_004d9c38(&cout)` | `DEBUG_STREAM << "BattleTech v4.10" << endl` | +| `FUN_0047b2ec(argc, argv, &LAB_0047af8c)` | `L4Application::ParseCommandLine(argc, argv, L4Application::ParseToken)` | +| `FUN_00407218(stack84, "btl4.res", &DAT_004e0070, 3)` | `StreamableResourceFile resources("btl4.res", version)` (match_level=3 is the declared default) | +| `DAT_004e0070` = 3 bytes | `version[3]` = `{MAJOR_DATA_VERSION, RELEASE_VERSION, MINOR_DATA_VERSION}` = {1,0,6} from BTL4VER.HPP | +| `DAT_004fd550 < 1` | `L4Application::GetMissionReviewMode() < 1` (inline static accessor) | +| `new(0x28) FUN_0044f29c(this, DAT_0052140c)` | `new ApplicationManager(GetTicksPerSecond())` (inline friend accessor, TIME.HPP:49) — DAT_0052140c is set to 28.0f by `SystemClock::SystemClock()` (L4TIME.CPP:93) when `L4TIMER=FAST` | +| `new(0xd4) FUN_004d34c4(this, &resources, 0x3EB, &DAT_0051e8d8)` | `new BTL4Application(&resources)` — 0x3EB/`DefaultData` are the declared default args (BTL4APP.HPP:34) | +| `FUN_0044f318(mgr, app)` | `application_manager->StartApplication(application)` | +| `FUN_0044f344(mgr)` | `application_manager->RunMissions()` | +| vcall slot 0 (mgr, 3) | `delete application_manager` | +| `return DAT_004efc98` | `return Exit_Code` (APP.HPP:542) | + +## Review/camera branch (NOT yet reconstructed — staged Fail) + +Decomp structure for `missionReviewMode >= 1` (mode 1 = camera, 2 = review per +emulator/CAMERA-REVIEW-NOTES.md): + +``` +spool_size = getenv("SPOOLSIZE") ? atoi(...) : 0x800000; // "Spool size = " printed +mgr = new(0x38) MissionReviewApplicationManager(ticksPerSecond, + (mode != 2) ? 2 : 1, spool_size); +spool_file = ; +if (spool_file) + mgr->StartApplication(new(0xd8) BTL4PlaybackApplication(&resources, spool_file)); +if (mode == 1) + mgr->StartApplication(new(0xd8) (&resources, 1)); +``` + +RECONSTRUCTED 2026-08-03: the branch is real. BTL4PB.CPP reconstructs the +playback app against its authentic surviving header; L4SPLR.CPP back-dates the +RP411 descendant onto the authentic 1995 engine header (see each sidecar). Two +identifications closed it: the `if (spool_file)` guard means the getter is +GetStoredSpoolFile (the empty-spool getter cannot fail), and the camera app's +ctor FUN_0047c3fc sits in the engine range with the (ResourceFile*, +ApplicationID) shape — the camera app IS the engine's L4SpoolingApplication, +started with ApplicationID 1 == BTL4. RUNTIME TEST PENDING: needs a +camera/review egg and a recorded spool on the rig (CAMERA-REVIEW-NOTES.md). + +## Deliberate differences from the binary + +- `HEAPSIZE` string sits in the pool between ProgName and the banner but is not + referenced from the decompiled main — it likely belongs to the runtime heap + init, not this TU. Not reproduced. +- `Register_Object`/`Start_Registering` debug bookkeeping is absent from the + optimized binary (DEBUG_LEVEL=0 compiles it out), so it is not written here. diff --git a/restoration/source410/BT_L4/BTL4PB.CPP b/restoration/source410/BT_L4/BTL4PB.CPP new file mode 100644 index 00000000..257976c7 --- /dev/null +++ b/restoration/source410/BT_L4/BTL4PB.CPP @@ -0,0 +1,444 @@ +//===========================================================================// +// File: btl4pb.cpp // +// Project: BattleTech Brick: BattleTech LBE Application // +// Contents: BTL4PlaybackApplication -- the mission-review application, and // +// BTSpoolerTask, the pump that replays recorded NetworkPackets // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// +// +// RECONSTRUCTED against the AUTHENTIC surviving header (BTL4PB.HPP) from the +// shipped binary's 0x4d3b74-0x4d40d8 cluster, cross-checked against the +// surviving RP411 descendant RPL4PB.cpp (a line-for-line structural twin). +// The binary's own base-ctor call (FUN_004d34c4(this, resource, 0x3eb, +// DefaultData)) confirms the DOS ctor shape this file uses -- no windowing +// parameters ever existed in 4.10. +// + +#include +#pragma hdrstop + +#if !defined(BTL4PB_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif +#if !defined(L4NET_HPP) +# include +#endif +#if !defined(UPDATE_HPP) +# include +#endif +#if !defined(RENDERER_HPP) +# include +#endif +#if !defined(ICOM_HPP) +# include +#endif +#if !defined(DROPZONE_HPP) +# include +#endif +#if !defined(DIRECTOR_HPP) +# include +#endif +#if !defined(NTTMGR_HPP) +# include +#endif +#if !defined(MECH_HPP) +# include +#endif +#if !defined(L4VIDEO_HPP) +# include +#endif +#if !defined(L4CTRL_HPP) +# include +#endif + +//############################################################################# +//########################## BTSpoolerTask ############################## +//############################################################################# + +// +// @004d3b74 / @004d3bb8 -- chain-only construction; the task adds no data. +// +BTSpoolerTask::BTSpoolerTask() +{ +} + +BTSpoolerTask::~BTSpoolerTask() +{ + Check_Fpu(); +} + +// +//############################################################################# +// @004d3b90 / @004d3ba8 -- the pump's two callbacks forward to the running +// playback application. +//############################################################################# +// +void + BTSpoolerTask::DispatchPacket(NetworkPacket *packet) +{ + BTL4PlaybackApplication + *playback_app = + Cast_Object(BTL4PlaybackApplication *, application); + playback_app->DispatchPacket(packet); + Check_Fpu(); +} + +long + BTSpoolerTask::GetTimeBias() +{ + BTL4PlaybackApplication + *playback_app = + Cast_Object(BTL4PlaybackApplication *, application); + return playback_app->GetTimeBias(); +} + +//############################################################################# +//####################### BTL4PlaybackApplication ####################### +//############################################################################# + +const Receiver::HandlerEntry + BTL4PlaybackApplication::MessageHandlerEntries[] = +{ + MESSAGE_ENTRY(BTL4PlaybackApplication, RunMission), // @004d3ef8 + MESSAGE_ENTRY(BTL4PlaybackApplication, StopMission) // @004d3f44 +}; + +BTL4PlaybackApplication::MessageHandlerSet + BTL4PlaybackApplication::MessageHandlers( + ELEMENTS(BTL4PlaybackApplication::MessageHandlerEntries), + BTL4PlaybackApplication::MessageHandlerEntries, + BTL4Application::MessageHandlers + ); + +Derivation + BTL4PlaybackApplication::ClassDerivations( + BTL4Application::ClassDerivations, + "BTL4PlaybackApplication" // @0051f182 + ); + +BTL4PlaybackApplication::SharedData + BTL4PlaybackApplication::DefaultData( // @0051ee5c + BTL4PlaybackApplication::ClassDerivations, + BTL4PlaybackApplication::MessageHandlers + ); + +// +//############################################################################# +// @004d3be4 -- the binary's base call is (resource, 0x3eb, DefaultData): the +// L4ApplicationClassID, no windowing. The spool lands in the inherited +// spoolFile slot. +//############################################################################# +// +BTL4PlaybackApplication::BTL4PlaybackApplication( + ResourceFile *resource_file, + SpoolFile *spool_file +): + BTL4Application(resource_file, L4ApplicationClassID, DefaultData) +{ + spoolFile = spool_file; + timeBias = 0; + Check_Fpu(); +} + +BTL4PlaybackApplication::~BTL4PlaybackApplication() +{ + Check_Fpu(); +} + +Logical + BTL4PlaybackApplication::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +// +//############################################################################# +// @004d3c14 -- playback drives the spool-fed network manager, not a live one. +//############################################################################# +// +NetworkManager * + BTL4PlaybackApplication::MakeNetworkManager() +{ + Check_Fpu(); + return new L4PlaybackNetworkManager; +} + +// +//############################################################################# +// @004d3c34 +//############################################################################# +// +void + BTL4PlaybackApplication::Initialize() +{ + Check(this); + L4Application::InitializeTillConsole(); +} + +// +//############################################################################# +// @004d3c44 -- the playback task pipeline: our own spool pump first, then the +// stock event / gauge / cycle / audio tasks. +//############################################################################# +// +void + BTL4PlaybackApplication::LoadBackgroundTasks() +{ + Check(this); + + ApplicationTask + *application_task; + + application_task = new BTSpoolerTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new ProcessEventTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new GaugeRendererTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new CompleteCyclesTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new AudioRendererTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + Check_Fpu(); +} + +// +//############################################################################# +// @004d3d40 -- the mission-review frame loop. Idle until frames execute; +// controls only in INTERACTIVE review (mode 2); then the update, interest, +// renderer and intercom managers; and while running, keep the game clock +// current from the recorded start. +//############################################################################# +// +Logical + BTL4PlaybackApplication::ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ) +{ + SET_FOREGROUND_PROCESSING(); + + Check(this); + + if (!executeFrames || GetApplicationState() == WaitingForEgg) + { + // + // [T3] The binary services a renderer idle slot here (the RP411 + // descendant names it ExecuteIdle); no such entry exists in the + // 1995 renderer headers, and pre-egg there is nothing to draw -- + // the idle frame simply spins. Revisit if the review screen shows + // stale video before the egg arrives. + // + CLEAR_FOREGROUND_PROCESSING(); + return executeFrames && !Exit_Code; + } + + Time + frame_ticks; + frame_ticks = frame_duration; + + if (GetMissionReviewMode() == 2) + { + Check(controlsManager); + ((LBE4ControlsManager *)controlsManager)->Execute(); + } + + SET_UPDATE_MANAGER(); + Check(updateManager); + updateManager->Execute(start_of_frame); + CLEAR_UPDATE_MANAGER(); + + Check(rendererManager); + rendererManager->UpdateInterestOrigins(start_of_frame); + Check(interestManager); + interestManager->Execute(); + + SET_RENDERER_MANAGER(); + Check(rendererManager); + rendererManager->Execute(start_of_frame, frame_ticks, frame_ticks); + CLEAR_RENDERER_MANAGER(); + + Check(intercomManager); + intercomManager->Execute(); + + if (GetApplicationState() == RunningMission) + { + secondsRemainingInGame = + currentMission->GetGameLength() - (Now() - gameStarted); + } + + CLEAR_FOREGROUND_PROCESSING(); + Check_Fpu(); + return executeFrames && !Exit_Code; +} + +// +//############################################################################# +// Inherited-shape background task (the OPT build emitted no BT override; the +// body matches the L4 base, kept for the header's declaration). +//############################################################################# +// +void + BTL4PlaybackApplication::ExecuteBackgroundTask() +{ + Check(this); + + if (ProcessOneEvent(HighEventPriority)) + { + return; + } + + Check(backgroundTasks); + backgroundTasks->Execute(); +} + +// +//############################################################################# +// @004d3ecc -- route a recorded packet to its client. +//############################################################################# +// +void + BTL4PlaybackApplication::DispatchPacket(NetworkPacket *packet) +{ + Check(this); + + NetworkManager + *net_mgr = GetNetworkManager(); + Check(net_mgr); + NetworkClient + *client = net_mgr->GetNetworkClientPointer(packet->clientID); + Check(client); + client->ReceiveNetworkPacket(packet, &packet->messageData); + Check_Fpu(); +} + +// +//############################################################################# +// @004d3ef8 -- first launch synchronises the playback clock: the bias is the +// difference between NOW and the recorded RunMission packet's timestamp, and +// every replayed packet is re-timed by it. +//############################################################################# +// +void + BTL4PlaybackApplication::RunMissionMessageHandler(RunMissionMessage *message) +{ + Check(this); + + if (GetApplicationState() == WaitingForLaunch) + { + SpoolFile + *spool = GetSpoolFile(); + Check(spool); + NetworkPacket + *packet = (NetworkPacket *)spool->GetPointer(); + timeBias = Now().ticks - packet->timeStamp.ticks; + spool->NextPacket(); + } + + BTL4Application::RunMissionMessageHandler(message); + Check_Fpu(); +} + +// +//############################################################################# +// @004d3f44 -- the WINNERS CIRCLE. When the recorded mission ends, release +// the spool, park every player's mech on the dropzone matching its finishing +// rank ("win1".."winN"), freeze them, refresh the name bitmaps and tilt the +// camera up 45 degrees for the final tableau. +//############################################################################# +// + +static char + winners_spot[] = "win?"; // @0051ee63 + +void + BTL4PlaybackApplication::StopMissionMessageHandler(StopMissionMessage *message) +{ + MissionReviewApplicationManager + *app_mgr = GetApplicationManager(); + Check(app_mgr); + + SpoolFile + *spool = GetSpoolFile(); + if (spool) + { + app_mgr->ReleaseSpoolFile(spool); + spoolFile = NULL; + + EntityManager + *entity_manager = application->GetEntityManager(); + EntityGroup + *dropzones = entity_manager->FindGroup("DropZones"); + char + *place = winners_spot + 3; + + Player + *player; + int + rank; + for ( + rank = 0; + (player = CameraDirector::FindPlayerByRank(rank)) != NULL; + ++rank + ) + { + *place = (char)('1' + rank); + + ChainIteratorOf + iterator(dropzones->groupMembers); + DropZone + *dropzone; + while ((dropzone = (DropZone *)iterator.ReadAndNext()) != NULL) + { + if (!strcmp(dropzone->GetDropZoneName(), winners_spot)) + { + break; + } + } + if (!dropzone) + { + continue; + } + + Mech + *mech = (Mech *)player->GetPlayerVehicle(); + if (mech->GetClassID() == RegisteredClass::MechClassID) + { + mech->Reset(dropzone->localOrigin, False); + mech->SetPerformance( + (Mech::Performance)&Simulation::DoNothing); + mech->FlushEvents(); + } + } + + DPLRenderer + *dpl_renderer = (DPLRenderer *)GetVideoRenderer(); + Check(dpl_renderer); + dpl_renderer->SortAndReloadNameBitmaps(); + dpl_renderer->SetViewAngle(Degree(45.0f)); + } + + BTL4Application::StopMissionMessageHandler(message); + Check_Fpu(); +} diff --git a/restoration/source410/MUNGA_L4/L4SPLR.CPP b/restoration/source410/MUNGA_L4/L4SPLR.CPP index 35a79d42..f304d538 100644 --- a/restoration/source410/MUNGA_L4/L4SPLR.CPP +++ b/restoration/source410/MUNGA_L4/L4SPLR.CPP @@ -202,8 +202,12 @@ void //###################### L4PlaybackNetworkManager ######################### //############################################################################# +// +// The 1995 header declares no statics of its own (the DefaultData reference +// in the RP411 descendant was later-era drift); chain the base's. +// L4PlaybackNetworkManager::L4PlaybackNetworkManager(): - NetworkManager(L4PlaybackNetworkManager::DefaultData) + NetworkManager(NetworkManager::DefaultData) { }