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:
@@ -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 <btl4.hpp>
|
||||
#pragma hdrstop
|
||||
|
||||
#if !defined(BTL4APP_HPP)
|
||||
# include <btl4app.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(APPMGR_HPP)
|
||||
# include <appmgr.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BTL4VER_HPP)
|
||||
# include <btl4ver.hpp>
|
||||
#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 <btl4.hpp>
|
||||
#pragma hdrstop
|
||||
|
||||
#if !defined(BTL4APP_HPP)
|
||||
# include <btl4app.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(APPMGR_HPP)
|
||||
# include <appmgr.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BTL4VER_HPP)
|
||||
# include <btl4ver.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BTL4PB_HPP)
|
||||
# include <btl4pb.hpp> // BTL4PlaybackApplication -- the review app
|
||||
#endif
|
||||
|
||||
#if !defined(SPOOLER_HPP)
|
||||
# include <spooler.hpp> // 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;
|
||||
}
|
||||
|
||||
@@ -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 = <mgr getter, FUN_0044fa14>;
|
||||
if (spool_file)
|
||||
mgr->StartApplication(new(0xd8) BTL4PlaybackApplication(&resources, spool_file));
|
||||
if (mode == 1)
|
||||
mgr->StartApplication(new(0xd8) <camera app, FUN_0047c3fc>(&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 = <mgr getter, FUN_0044fa14>;
|
||||
if (spool_file)
|
||||
mgr->StartApplication(new(0xd8) BTL4PlaybackApplication(&resources, spool_file));
|
||||
if (mode == 1)
|
||||
mgr->StartApplication(new(0xd8) <camera app, FUN_0047c3fc>(&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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user