BT410 5.3.106: MISSION REVIEW LINKS -- the playback app, the winners circle, and the last Fail() in main

BTL4PB.CPP reconstructed against its AUTHENTIC surviving header (BTL4PB.HPP)
from the binary's 0x4d3b74-0x4d40d8 cluster, cross-checked against the
surviving RP411 twin -- and the review/camera launch in BTL4.CPP's main() is
real code now.  btl4.lib 11 -> 12 members, link clean, zero unresolved: the
linker pulled the entire playback chain for the first time.

The launch decode closed on two identifications:

  The `if (spool_file)` guard in the decomp means the manager getter is
  GetStoredSpoolFile -- the empty-spool getter cannot fail, so a review pod
  with no recorded battle simply starts nothing, which is the right field
  behaviour.

  The camera app's ctor (FUN_0047c3fc) sits in the ENGINE range with the
  (ResourceFile*, ApplicationID) shape: the camera pod's recorder IS the
  engine's own L4SpoolingApplication -- restored one commit ago -- started
  with ApplicationID 1 == BTL4.  BT shipped no camera app of its own.

What the playback app does, all binary-anchored: BTSpoolerTask pumps
recorded packets through DispatchPacket -> the client's own
ReceiveNetworkPacket; RunMission synchronises the clock (timeBias = Now -
the recorded run packet's stamp); the frame loop runs controls ONLY in
interactive review (mode 2), then update/interest/renderer/intercom; and
StopMission plays the WINNERS CIRCLE -- release the spool, park each
player's mech on the dropzone named "win1".."winN" by finishing rank,
freeze it (DoNothing performance), and tilt the camera up 45 degrees over
the tableau.

DOS-authentic ctor shape throughout: the binary's base call is (resource,
0x3eb, DefaultData) -- no windowing parameters ever existed in 4.10; the
RP411 twin's HINSTANCE/HWND threading is port drift, dropped.

Also fixed from 5.3.105's debt: L4PlaybackNetworkManager chains
NetworkManager::DefaultData -- the 1995 header declares no statics of its
own; the RP411 self-reference was drift too.

One [T3] in source: the idle frame's renderer service (the descendant's
ExecuteIdle) has no 1995 entry point; pre-egg the idle frame spins.

RUNTIME TEST PENDING, stated plainly: exercising review needs a
camera/review egg and a recorded spool on the rig (CAMERA-REVIEW-NOTES.md
has the roles).  The normal pod path regressed clean (mode gate untouched).

The Fail() census moves: BTL4.CPP and SEQCTL.CPP are now stub-free; 22
stubs remain across 15 files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-03 15:54:31 -05:00
co-authored by Claude Fable 5
parent f85e5f5bcd
commit d2be54a3b9
4 changed files with 647 additions and 157 deletions
+128 -91
View File
@@ -1,91 +1,128 @@
//===========================================================================// //===========================================================================//
// File: btl4.cpp // // File: btl4.cpp //
// Project: BattleTech Brick: BattleTech LBE Application // // Project: BattleTech Brick: BattleTech LBE Application //
// Contents: Application launcher (main) // // Contents: Application launcher (main) //
//---------------------------------------------------------------------------// //---------------------------------------------------------------------------//
// Date Who Modification // // Date Who Modification //
// -------- --- ---------------------------------------------------------- // // -------- --- ---------------------------------------------------------- //
// // // //
//---------------------------------------------------------------------------// //---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. // // Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide // // All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================// //===========================================================================//
#include <btl4.hpp> #include <btl4.hpp>
#pragma hdrstop #pragma hdrstop
#if !defined(BTL4APP_HPP) #if !defined(BTL4APP_HPP)
# include <btl4app.hpp> # include <btl4app.hpp>
#endif #endif
#if !defined(APPMGR_HPP) #if !defined(APPMGR_HPP)
# include <appmgr.hpp> # include <appmgr.hpp>
#endif #endif
#if !defined(BTL4VER_HPP) #if !defined(BTL4VER_HPP)
# include <btl4ver.hpp> # include <btl4ver.hpp>
#endif #endif
//########################################################################## #if !defined(BTL4PB_HPP)
//#################### BTL4Application Globals ####################### # include <btl4pb.hpp> // BTL4PlaybackApplication -- the review app
//########################################################################## #endif
extern const char* const ProgName; #if !defined(SPOOLER_HPP)
const char* const ProgName = "btl4"; # include <spooler.hpp> // MissionReviewApplicationManager / SpoolFile
#endif
static Byte
version[3] = //##########################################################################
{MAJOR_DATA_VERSION, RELEASE_VERSION, MINOR_DATA_VERSION}; //#################### BTL4Application Globals #######################
//##########################################################################
//
//############################################################################# extern const char* const ProgName;
// main const char* const ProgName = "btl4";
//#############################################################################
// static Byte
int version[3] =
main(int argc, char *argv[]) {MAJOR_DATA_VERSION, RELEASE_VERSION, MINOR_DATA_VERSION};
{
DEBUG_STREAM << "BattleTech v4.10" << endl; //
//#############################################################################
if (!L4Application::ParseCommandLine(argc, argv, L4Application::ParseToken)) // main
{ //#############################################################################
return 1; //
} int
main(int argc, char *argv[])
StreamableResourceFile {
resources("btl4.res", version); DEBUG_STREAM << "BattleTech v4.10" << endl;
ApplicationManager if (!L4Application::ParseCommandLine(argc, argv, L4Application::ParseToken))
*application_manager = NULL; {
return 1;
if (L4Application::GetMissionReviewMode() < 1) }
{
application_manager = StreamableResourceFile
new ApplicationManager(GetTicksPerSecond()); resources("btl4.res", version);
Application ApplicationManager
*application = new BTL4Application(&resources); *application_manager = NULL;
application_manager->StartApplication(application); if (L4Application::GetMissionReviewMode() < 1)
} {
else application_manager =
{ new ApplicationManager(GetTicksPerSecond());
//
//------------------------------------------------------------------- Application
// Mission review / live-camera launch (missionReviewMode >= 1): *application = new BTL4Application(&resources);
// a MissionReviewApplicationManager with a SPOOLSIZE-byte packet
// spool plus BTL4PlaybackApplication -- those bricks are not yet application_manager->StartApplication(application);
// reconstructed (see BTL4.NOTES.md for the decompiled structure). }
//------------------------------------------------------------------- else
// {
Fail("btl4.cpp -- mission review/camera launch not yet reconstructed"); //
return 1; //-------------------------------------------------------------------
} // Mission review / live-camera launch (mode 1 = camera, 2 = review).
//
application_manager->RunMissions(); // The manager owns SPOOLSIZE-byte packet spools (default 8MB); a
// STORED spool starts the playback application over it, and camera
delete application_manager; // mode additionally starts the engine's spooling application -- the
// recorder -- as a second app (the binary's FUN_0047c3fc ctor is
return Exit_Code; // 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;
}
+70 -65
View File
@@ -1,65 +1,70 @@
# BTL4.CPP — reconstruction notes # BTL4.CPP — reconstruction notes
**Status: RECONSTRUCTED (normal launch path); review/camera branch staged with Fail().** **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 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). `btl4.obj` as a bare object next to the libs — it was never a lib member).
## Evidence base ## Evidence base
1. **Ghidra decomp of the 4.11 binary**`C:\VWE\BT411\reference\decomp\all\part_000.c`, 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`). `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. 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 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" offset ~917884: `"btl4" "HEAPSIZE" "BattleTech v4.10" "btl4.res" "SPOOLSIZE"
"Spool size = "` — banner text and resource name byte-exact. "Spool size = "` — banner text and resource name byte-exact.
3. **Surviving 1995 launcher-style TU** `CODE/RP/RP_L4/RPL4TOOL.CPP` — house 3. **Surviving 1995 launcher-style TU** `CODE/RP/RP_L4/RPL4TOOL.CPP` — house
style for `main(int, char*[])` and the `ProgName` global pattern. style for `main(int, char*[])` and the `ProgName` global pattern.
4. **BT411's win32 launcher** `game/btl4main.cpp` (adapted from RP's RPL4.CPP) 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}` independently reconstructs the same skeleton and pins `version[3] = {1,0,6}`
against the RESOURCE.cpp version check. against the RESOURCE.cpp version check.
## Decoded decomp → source mapping ## Decoded decomp → source mapping
| decomp | source | | decomp | source |
|---|---| |---|---|
| `FUN_004dbb24(&cout, "BattleTech v4.10", 0); FUN_004d9c38(&cout)` | `DEBUG_STREAM << "BattleTech v4.10" << endl` | | `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_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) | | `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_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) | | `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(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) | | `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_0044f318(mgr, app)` | `application_manager->StartApplication(application)` |
| `FUN_0044f344(mgr)` | `application_manager->RunMissions()` | | `FUN_0044f344(mgr)` | `application_manager->RunMissions()` |
| vcall slot 0 (mgr, 3) | `delete application_manager` | | vcall slot 0 (mgr, 3) | `delete application_manager` |
| `return DAT_004efc98` | `return Exit_Code` (APP.HPP:542) | | `return DAT_004efc98` | `return Exit_Code` (APP.HPP:542) |
## Review/camera branch (NOT yet reconstructed — staged Fail) ## Review/camera branch (NOT yet reconstructed — staged Fail)
Decomp structure for `missionReviewMode >= 1` (mode 1 = camera, 2 = review per Decomp structure for `missionReviewMode >= 1` (mode 1 = camera, 2 = review per
emulator/CAMERA-REVIEW-NOTES.md): emulator/CAMERA-REVIEW-NOTES.md):
``` ```
spool_size = getenv("SPOOLSIZE") ? atoi(...) : 0x800000; // "Spool size = " printed spool_size = getenv("SPOOLSIZE") ? atoi(...) : 0x800000; // "Spool size = " printed
mgr = new(0x38) MissionReviewApplicationManager(ticksPerSecond, mgr = new(0x38) MissionReviewApplicationManager(ticksPerSecond,
(mode != 2) ? 2 : 1, spool_size); (mode != 2) ? 2 : 1, spool_size);
spool_file = <mgr getter, FUN_0044fa14>; spool_file = <mgr getter, FUN_0044fa14>;
if (spool_file) if (spool_file)
mgr->StartApplication(new(0xd8) BTL4PlaybackApplication(&resources, spool_file)); mgr->StartApplication(new(0xd8) BTL4PlaybackApplication(&resources, spool_file));
if (mode == 1) if (mode == 1)
mgr->StartApplication(new(0xd8) <camera app, FUN_0047c3fc>(&resources, 1)); mgr->StartApplication(new(0xd8) <camera app, FUN_0047c3fc>(&resources, 1));
``` ```
Class declarations survive: `BTL4PlaybackApplication` (CODE/BT/BT_L4/BTL4PB.HPP), RECONSTRUCTED 2026-08-03: the branch is real. BTL4PB.CPP reconstructs the
spooler bricks in CODE/RP/MUNGA_L4/L4SPLR.HPP (`MissionReviewApplicationManager` playback app against its authentic surviving header; L4SPLR.CPP back-dates the
referenced there). Their .CPP bodies are not staged, so the branch Fails loudly RP411 descendant onto the authentic 1995 engine header (see each sidecar). Two
instead of linking half a subsystem. identifications closed it: the `if (spool_file)` guard means the getter is
GetStoredSpoolFile (the empty-spool getter cannot fail), and the camera app's
## Deliberate differences from the binary ctor FUN_0047c3fc sits in the engine range with the (ResourceFile*,
ApplicationID) shape — the camera app IS the engine's L4SpoolingApplication,
- `HEAPSIZE` string sits in the pool between ProgName and the banner but is not started with ApplicationID 1 == BTL4. RUNTIME TEST PENDING: needs a
referenced from the decompiled main — it likely belongs to the runtime heap camera/review egg and a recorded spool on the rig (CAMERA-REVIEW-NOTES.md).
init, not this TU. Not reproduced.
- `Register_Object`/`Start_Registering` debug bookkeeping is absent from the ## Deliberate differences from the binary
optimized binary (DEBUG_LEVEL=0 compiles it out), so it is not written here.
- `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.
+444
View File
@@ -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 <btl4.hpp>
#pragma hdrstop
#if !defined(BTL4PB_HPP)
# include <btl4pb.hpp>
#endif
#if !defined(MISSION_HPP)
# include <mission.hpp>
#endif
#if !defined(L4NET_HPP)
# include <l4net.hpp>
#endif
#if !defined(UPDATE_HPP)
# include <update.hpp>
#endif
#if !defined(RENDERER_HPP)
# include <renderer.hpp>
#endif
#if !defined(ICOM_HPP)
# include <icom.hpp>
#endif
#if !defined(DROPZONE_HPP)
# include <dropzone.hpp>
#endif
#if !defined(DIRECTOR_HPP)
# include <director.hpp>
#endif
#if !defined(NTTMGR_HPP)
# include <nttmgr.hpp>
#endif
#if !defined(MECH_HPP)
# include <mech.hpp>
#endif
#if !defined(L4VIDEO_HPP)
# include <l4video.hpp>
#endif
#if !defined(L4CTRL_HPP)
# include <l4ctrl.hpp>
#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<Node *>
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();
}
+5 -1
View File
@@ -202,8 +202,12 @@ void
//###################### L4PlaybackNetworkManager ######################### //###################### 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(): L4PlaybackNetworkManager::L4PlaybackNetworkManager():
NetworkManager(L4PlaybackNetworkManager::DefaultData) NetworkManager(NetworkManager::DefaultData)
{ {
} }