Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
298 lines
6.2 KiB
C++
298 lines
6.2 KiB
C++
#pragma once
|
|
|
|
#include "plug.h"
|
|
#include "chain.h"
|
|
#include "time.h"
|
|
#include "config.h"
|
|
|
|
#if defined(TRACE_ON)
|
|
|
|
struct TraceSample
|
|
{
|
|
Scalar sampleFraction;
|
|
Word sampleFrame;
|
|
Byte traceNumber;
|
|
Byte sampleType;
|
|
|
|
enum Type
|
|
{
|
|
GoingUp = 0,
|
|
GoingDown,
|
|
Marker,
|
|
IntegerSnapshot,
|
|
ScalarSnapshot,
|
|
SuspendSampling,
|
|
ResumeSampling
|
|
};
|
|
};
|
|
|
|
template <class T> struct SnapshotOf : public TraceSample
|
|
{
|
|
T snapShot;
|
|
};
|
|
|
|
class Trace : public Plug
|
|
{
|
|
friend class TraceManager;
|
|
|
|
public:
|
|
enum Type
|
|
{
|
|
BitType,
|
|
IntegerType,
|
|
ScalarType
|
|
};
|
|
|
|
protected:
|
|
static Byte NextTraceID;
|
|
|
|
const char *traceName;
|
|
long lastFrameActivity;
|
|
Scalar lastFractionActivity;
|
|
Byte traceNumber;
|
|
Byte traceType;
|
|
|
|
Trace(const char* name, Type type);
|
|
|
|
MemoryStream *GetTraceLog();
|
|
void IncrementSampleCount();
|
|
|
|
virtual void DumpTraceStatus()=0;
|
|
virtual void ResetTrace()=0;
|
|
|
|
#if defined(USE_TIME_ANALYSIS)
|
|
virtual void StartTiming()=0;
|
|
virtual Scalar CalcuateUsage(long frame, Scalar fraction, double sample_time)=0;
|
|
virtual void PrintUsage(Scalar usage);
|
|
#endif
|
|
};
|
|
|
|
class BitTrace : public Trace
|
|
{
|
|
protected:
|
|
static Byte NextActiveLine;
|
|
|
|
Logical traceUp;
|
|
double lastUpTime, totalUpTime;
|
|
Byte activeLine;
|
|
|
|
#if defined(USE_ACTIVE_PROFILE)
|
|
static void SetLineImplementation(Byte line);
|
|
static void ClearLineImplementation(Byte line);
|
|
static Logical IsLineValidImplementation(Byte line);
|
|
#endif
|
|
|
|
void DumpTraceStatus();
|
|
void ResetTrace();
|
|
#if defined(USE_TIME_ANALYSIS)
|
|
void StartTiming();
|
|
Scalar CalculateUsage(long frame, Scalar fraction, double sample_time);
|
|
void PrintUsage(Scalar usage);
|
|
#endif
|
|
|
|
public:
|
|
BitTrace(const char *name);
|
|
|
|
void Set();
|
|
void Clear();
|
|
|
|
double GetLastUpTime()
|
|
{
|
|
Check(this);
|
|
return lastUpTime;
|
|
}
|
|
|
|
double GetTotalUpTime()
|
|
{
|
|
Check(this);
|
|
return totalUpTime;
|
|
}
|
|
};
|
|
|
|
template <class T> class TraceOf : public Trace
|
|
{
|
|
protected:
|
|
double weightedSum;
|
|
T currentValue;
|
|
|
|
TraceSample::Type sampleType;
|
|
|
|
void DumpTraceStatus();
|
|
void ResetTrace();
|
|
#if defined(USE_TIME_ANALYSIS)
|
|
void StartTiming();
|
|
Scalar CalculateUsage(long frame, Scalar fraction, double sample_time);
|
|
void PrintUsage(Scalar usage);
|
|
#endif
|
|
|
|
public:
|
|
TraceOf(const char* name, const T& initial_value, Type trace_type, TraceSample::Type sample_type);
|
|
|
|
void TakeSnapshot(const T& value);
|
|
};
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
template <class T> TraceOf<T>::TraceOf(const char* name, const T& initial_value, Type trace_type, TraceSample::Type sample_type) : Trace(name, trace_type)
|
|
{
|
|
currentValue = initial_value;
|
|
sampleType = sample_type;
|
|
TraceOf<T>::ResetTrace();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
template <class T> void TraceOf<T>::DumpTraceStatus()
|
|
{
|
|
Check(this);
|
|
DEBUG_STREAM << currentValue << std::flush;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
template <class T> void TraceOf<T>::ResetTrace()
|
|
{
|
|
#if defined(USE_TIME_ANALYSIS)
|
|
weightedSum = 0.0;
|
|
#endif
|
|
}
|
|
|
|
#if defined(USE_TIME_ANALYSIS)
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
template <class T> void TraceOf<T>::StartTiming()
|
|
{
|
|
Check(this);
|
|
weightedSum = 0.0;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
template <class T> Scalar TraceOf<T>::CalculateUsage(long frame, Scalar fraction, double sample_time)
|
|
{
|
|
double last_part = frame - lastFrameActivity;
|
|
last_part += fraction - lastFractionActivity;
|
|
weightedSum += last_part * currentValue;
|
|
Scalar result = weightedSum / sample_time;
|
|
Check_Fpu();
|
|
weightedSum = 0.0;
|
|
return result;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
template <class T> void TraceOf<T>::PrintUsage(Scalar usage)
|
|
{
|
|
Check(this);
|
|
|
|
DEBUG_STREAM << usage << std::flush;
|
|
}
|
|
|
|
#endif
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
template <class T> void TraceOf<T>::TakeSnapshot(const T& value)
|
|
{
|
|
Check(this);
|
|
|
|
#if defined(USE_TIME_ANALYSIS) || defined(USE_TRACE_LOG)
|
|
long frame = Now().ticks;
|
|
Scalar fraction = Get_Frame_Percent_Used();
|
|
#endif
|
|
|
|
#if defined(USE_TIME_ANALYSIS)
|
|
double last_part = frame - lastFrameActivity;
|
|
last_part += fraction - lastFractionActivity;
|
|
weightedSum += last_part * currentValue;
|
|
lastFrameActivity = frame;
|
|
lastFractionActivity = fraction;
|
|
#endif
|
|
|
|
currentValue = value;
|
|
|
|
#if defined(USE_TRACE_LOG)
|
|
IncrementSampleCount();
|
|
MemoryStream *log = GetTraceLog();
|
|
if (log)
|
|
{
|
|
Check(log);
|
|
SnapshotOf<T> *sample = (SnapshotOf<T>*)log->GetPointer();
|
|
sample->sampleType = (Byte)sampleType;
|
|
sample->traceNumber = traceNumber;
|
|
sample->sampleFrame = (Word)frame;
|
|
sample->sampleFraction = fraction;
|
|
sample->snapShot = currentValue;
|
|
log->AdvancePointer(sizeof(*sample));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//#######################################################################
|
|
//##################### TraceManager ##############################
|
|
//#######################################################################
|
|
|
|
class TraceManager SIGNATURED
|
|
{
|
|
friend class Trace;
|
|
|
|
protected:
|
|
ChainOf<Trace*> traceChain;
|
|
long sampleStartFrame;
|
|
Scalar sampleStartFraction;
|
|
int actualSampleCount, ignoredSampleCount;
|
|
MemoryStream *allocatedTraceLog, *activeTraceLog;
|
|
Byte traceCount;
|
|
|
|
void Add(Trace *trace);
|
|
|
|
public:
|
|
TraceManager();
|
|
~TraceManager();
|
|
|
|
Byte GetTraceCount()
|
|
{
|
|
Check(this);
|
|
return traceCount;
|
|
}
|
|
|
|
void DumpTracesStatus();
|
|
void ResetTraces();
|
|
|
|
#if defined(USE_TIME_ANALYSIS)
|
|
void StartTimingAnalysis();
|
|
int SnapshotTimingAnalysis(Logical print = false);
|
|
#endif
|
|
|
|
#if defined(USE_TRACE_LOG)
|
|
void CreateTraceLog(size_t max_trace_samples, Logical start_sampling);
|
|
void SaveTraceLog(const char* filename);
|
|
void MarkTraceLog();
|
|
void SuspendTraceLogging();
|
|
void ResumeTraceLogging();
|
|
#endif
|
|
|
|
Logical TestInstance() const;
|
|
};
|
|
|
|
extern TraceManager trace_manager;
|
|
|
|
inline MemoryStream* Trace::GetTraceLog()
|
|
{
|
|
Check(this);
|
|
Check(&trace_manager);
|
|
return trace_manager.activeTraceLog;
|
|
}
|
|
|
|
inline void Trace::IncrementSampleCount()
|
|
{
|
|
Check(this);
|
|
Check(&trace_manager);
|
|
if (!trace_manager.activeTraceLog)
|
|
++trace_manager.ignoredSampleCount;
|
|
else
|
|
++trace_manager.actualSampleCount;
|
|
}
|
|
|
|
# endif
|