diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index d0ed2e28..ff151342 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -17,4 +17,6 @@ jobs: --style=file \ ISLE/*.cpp ISLE/*.h \ LEGO1/*.cpp LEGO1/*.h \ - LEGO1/realtime/*.cpp LEGO1/realtime/*.h \ No newline at end of file + LEGO1/realtime/*.cpp LEGO1/realtime/*.h \ + LEGO1/tgl/*.h \ + LEGO1/viewmanager/*.cpp LEGO1/viewmanager/*.h \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a297f7f4..d4d9ccb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,7 @@ add_library(lego1 SHARED LEGO1/legopartpresenter.cpp LEGO1/legopathactor.cpp LEGO1/legopathcontroller.cpp + LEGO1/legopathcontrollerlist.cpp LEGO1/legopathpresenter.cpp LEGO1/legophonemepresenter.cpp LEGO1/legoplantmanager.cpp @@ -144,7 +145,6 @@ add_library(lego1 SHARED LEGO1/mxloopingflcpresenter.cpp LEGO1/mxloopingmidipresenter.cpp LEGO1/mxloopingsmkpresenter.cpp - LEGO1/mxmatrix.cpp LEGO1/mxmediamanager.cpp LEGO1/mxmediapresenter.cpp LEGO1/mxmidipresenter.cpp @@ -183,7 +183,6 @@ add_library(lego1 SHARED LEGO1/mxtype17notificationparam.cpp LEGO1/mxvariable.cpp LEGO1/mxvariabletable.cpp - LEGO1/mxvector.cpp LEGO1/mxvideomanager.cpp LEGO1/mxvideoparam.cpp LEGO1/mxvideoparamflags.cpp @@ -201,23 +200,27 @@ add_library(lego1 SHARED LEGO1/racestate.cpp LEGO1/radio.cpp LEGO1/radiostate.cpp + LEGO1/realtime/matrix.cpp + LEGO1/realtime/orientableroi.cpp LEGO1/realtime/realtime.cpp LEGO1/realtime/realtimeview.cpp + LEGO1/realtime/vector.cpp LEGO1/registrationbook.cpp LEGO1/score.cpp LEGO1/scorestate.cpp LEGO1/skateboard.cpp LEGO1/towtrack.cpp LEGO1/towtrackmissionstate.cpp - LEGO1/viewmanager.cpp + LEGO1/viewmanager/viewmanager.cpp + LEGO1/viewmanager/viewroi.cpp ) if (MINGW) target_compile_definitions(lego1 PRIVATE DIRECTINPUT_VERSION=0x0500) endif() # Additional include directories -include_directories("${CMAKE_SOURCE_DIR}/3rdparty/vec") -include_directories("${CMAKE_SOURCE_DIR}/3rdparty/smk") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/3rdparty/vec") +target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/smk") if (ISLE_USE_SMARTHEAP) add_library(SmartHeap::SmartHeap STATIC IMPORTED) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9a20eb09..99f25975 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,6 +21,12 @@ Please keep your pull requests small and understandable; you may be able to shoo This repository currently has only one goal: accuracy to the original executables. We are byte/instruction matching as much as possible, which means the priority is making the original compiler (MSVC 4.20) produce code that matches the original game. As such, modernizations and bug fixes will probably be rejected for the time being. +## Overview + +* `3rdparty`: Contains code obtained from third parties, not including Mindscape. Generally, these are libraries that have been placed in the public domain or are freely available on the web. As these are unaltered files, our style guide (see below) does not apply. +* `ISLE`: Decompilation of `ISLE.EXE`. It depends on some code in `LEGO1`. +* `LEGO1`: Decompilation of `LEGO1.DLL`. This folder contains code from Mindscape's custom in-house engine called **Omni** (file pattern: `mx*`), the LEGO Island-specific extensions for Omni and the game's code (file pattern: `lego*`) as well as several utility libraries (`realtime`, `tgl`, `viewmanager`) developed by Mindscape. + ## Code Style In general, we're not exhaustively strict about coding style, but there are some preferable guidelines to follow that have been adopted from what we know about the original codebase: @@ -31,11 +37,13 @@ We are currently using [clang-format](https://clang.llvm.org/docs/ClangFormat.ht ### Naming conventions +The following conventions should generally be applied everywhere except for the utility libraries (`LEGO1/realtime`, `LEGO1/tgl`, `LEGO1/viewmanager`) and any 3rd party libraries (`3rdparty`). + - `PascalCase` for classes, function names, and enumerations. - `m_camelCase` for member variables. - `g_camelCase` for global variables. - `p_camelCase` for function parameters. -- Instead of C++ primitives (e.g. `int`, `long`, etc.), use types in [`mxtypes.h`](LEGO1/mxtypes.h) instead. This will help us ensure that variables will be the correct size regardless of the underlying compiler/platform/architecture. +- Within the Omni engine (file pattern: `mx*`), instead of C++ primitives (e.g. `int`, `long`, etc.), use types in [`mxtypes.h`](LEGO1/mxtypes.h) instead. This will help us ensure that variables will be the correct size regardless of the underlying compiler/platform/architecture. ## Questions? diff --git a/LEGO1/helicopter.cpp b/LEGO1/helicopter.cpp index 005d9b56..6e159a26 100644 --- a/LEGO1/helicopter.cpp +++ b/LEGO1/helicopter.cpp @@ -24,9 +24,9 @@ Helicopter::~Helicopter() } // OFFSET: LEGO1 0x100032c0 -MxResult Helicopter::InitFromMxDSObject(MxDSObject& p_dsObject) +MxResult Helicopter::Create(MxDSObject& p_dsObject) { - MxResult result = IslePathActor::InitFromMxDSObject(p_dsObject); + MxResult result = IslePathActor::Create(p_dsObject); LegoWorld* world = GetCurrentWorld(); SetWorld(world); if (world->IsA("Act3")) { diff --git a/LEGO1/helicopter.h b/LEGO1/helicopter.h index d9de2854..0701c437 100644 --- a/LEGO1/helicopter.h +++ b/LEGO1/helicopter.h @@ -3,7 +3,7 @@ #include "helicopterstate.h" #include "islepathactor.h" -#include "mxmatrix.h" +#include "realtime/matrix.h" // VTABLE 0x100d40f8 // SIZE 0x230 @@ -24,7 +24,7 @@ class Helicopter : public IslePathActor { return !strcmp(name, Helicopter::ClassName()) || IslePathActor::IsA(name); } - virtual MxResult InitFromMxDSObject(MxDSObject& p_dsObject) override; // vtable+0x18 + virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 virtual void VTable0xe4() override; // OFFSET: LEGO1 0x10003210 TEMPLATE @@ -32,11 +32,11 @@ class Helicopter : public IslePathActor { virtual ~Helicopter() override; // vtable+0x0 protected: - MxMatrixData m_unk160; - MxMatrixData m_unk1a8; + Matrix4Data m_unk160; + Matrix4Data m_unk1a8; undefined4 m_unk1f0; - MxVector4Data m_unk1f4; - MxVector4Data m_unk20c; + Vector4Data m_unk1f4; + Vector4Data m_unk20c; undefined4 m_unk224; HelicopterState* m_state; MxAtomId m_unk22c; diff --git a/LEGO1/islepathactor.cpp b/LEGO1/islepathactor.cpp index 9aca029b..21fca59a 100644 --- a/LEGO1/islepathactor.cpp +++ b/LEGO1/islepathactor.cpp @@ -44,9 +44,9 @@ IslePathActor::IslePathActor() } // OFFSET: LEGO1 0x1001a280 -MxResult IslePathActor::InitFromMxDSObject(MxDSObject& p_dsObject) +MxResult IslePathActor::Create(MxDSObject& p_dsObject) { - return MxEntity::InitFromMxDSObject(p_dsObject); + return MxEntity::Create(p_dsObject); } // OFFSET: LEGO1 0x1001a350 STUB diff --git a/LEGO1/islepathactor.h b/LEGO1/islepathactor.h index c0222047..7885fbb2 100644 --- a/LEGO1/islepathactor.h +++ b/LEGO1/islepathactor.h @@ -28,16 +28,16 @@ class IslePathActor : public LegoPathActor { // IslePathActor::`scalar deleting destructor' inline virtual ~IslePathActor() override { IslePathActor::Destroy(TRUE); } - virtual MxResult InitFromMxDSObject(MxDSObject& p_dsObject) override; // vtable+0x18 - virtual void VTable0xcc(); // vtable+0xcc - virtual void VTable0xd0(); // vtable+0xd0 - virtual void VTable0xd4(); // vtable+0xd4 - virtual void VTable0xd8(); // vtable+0xd8 - virtual void VTable0xdc(); // vtable+0xdc - virtual void VTable0xe0(); // vtable+0xe0 - virtual void VTable0xe4(); // vtable+0xe4 - virtual void VTable0xe8(MxU32 p_1, MxBool p_2, MxU8 p_3); // vtable+0xe8 - virtual void VTable0xec(); // vtable+0xec + virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + virtual void VTable0xcc(); // vtable+0xcc + virtual void VTable0xd0(); // vtable+0xd0 + virtual void VTable0xd4(); // vtable+0xd4 + virtual void VTable0xd8(); // vtable+0xd8 + virtual void VTable0xdc(); // vtable+0xdc + virtual void VTable0xe0(); // vtable+0xe0 + virtual void VTable0xe4(); // vtable+0xe4 + virtual void VTable0xe8(MxU32 p_1, MxBool p_2, MxU8 p_3); // vtable+0xe8 + virtual void VTable0xec(); // vtable+0xec inline void SetWorld(LegoWorld* p_world) { m_pLegoWorld = p_world; } inline LegoWorld* GetWorld() { return m_pLegoWorld; } diff --git a/LEGO1/lego3dview.h b/LEGO1/lego3dview.h index 68c8f57d..626ecbd6 100644 --- a/LEGO1/lego3dview.h +++ b/LEGO1/lego3dview.h @@ -1,7 +1,7 @@ #ifndef LEGO3DVIEW_H #define LEGO3DVIEW_H -#include "viewmanager.h" +#include "viewmanager/viewmanager.h" class Lego3DView { public: diff --git a/LEGO1/legoentity.cpp b/LEGO1/legoentity.cpp index 2a9b4b76..f5c6477c 100644 --- a/LEGO1/legoentity.cpp +++ b/LEGO1/legoentity.cpp @@ -36,13 +36,13 @@ void LegoEntity::ResetWorldTransform(MxBool p_inVehicle) } // OFFSET: LEGO1 0x10010790 STUB -void LegoEntity::SetWorldTransform(MxVector3& p_loc, MxVector3& p_dir, MxVector3& p_up) +void LegoEntity::SetWorldTransform(Vector3Impl& p_loc, Vector3Impl& p_dir, Vector3Impl& p_up) { // TODO } // OFFSET: LEGO1 0x100107e0 -MxResult LegoEntity::InitFromMxDSObject(MxDSObject& p_dsObject) +MxResult LegoEntity::Create(MxDSObject& p_dsObject) { m_mxEntityId = p_dsObject.GetObjectId(); m_atom = p_dsObject.GetAtomId(); diff --git a/LEGO1/legoentity.h b/LEGO1/legoentity.h index c0a16c32..0c559fb7 100644 --- a/LEGO1/legoentity.h +++ b/LEGO1/legoentity.h @@ -6,7 +6,7 @@ #include "legoroi.h" #include "mxdsobject.h" #include "mxentity.h" -#include "mxvector.h" +#include "realtime/vector.h" // VTABLE 0x100d4858 // SIZE 0x68 (probably) @@ -32,12 +32,12 @@ class LegoEntity : public MxEntity { return !strcmp(name, LegoEntity::ClassName()) || MxEntity::IsA(name); } - virtual MxResult InitFromMxDSObject(MxDSObject& p_dsObject); // vtable+0x18 - virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c - virtual void ParseAction(char*); // vtable+0x20 - virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 - virtual void SetWorldTransform(MxVector3& p_loc, MxVector3& p_dir, MxVector3& p_up); // vtable+0x28 - virtual void ResetWorldTransform(MxBool p_inVehicle); // vtable+0x2c + virtual MxResult Create(MxDSObject& p_dsObject); // vtable+0x18 + virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c + virtual void ParseAction(char*); // vtable+0x20 + virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 + virtual void SetWorldTransform(Vector3Impl& p_loc, Vector3Impl& p_dir, Vector3Impl& p_up); // vtable+0x28 + virtual void ResetWorldTransform(MxBool p_inVehicle); // vtable+0x2c // OFFSET: LEGO1 0x10001090 virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 virtual void VTable0x34(); // vtable+0x34 @@ -54,12 +54,12 @@ class LegoEntity : public MxEntity { undefined m_unk10; undefined m_unk11; - MxVector3Data m_worldLocation; // 0x14 - MxVector3Data m_worldDirection; // 0x28 - MxVector3Data m_worldUp; // 0x3c - MxFloat m_worldSpeed; // 0x50 - LegoROI* m_roi; // 0x54 - MxBool m_cameraFlag; // 0x58 + Vector3Data m_worldLocation; // 0x14 + Vector3Data m_worldDirection; // 0x28 + Vector3Data m_worldUp; // 0x3c + MxFloat m_worldSpeed; // 0x50 + LegoROI* m_roi; // 0x54 + MxBool m_cameraFlag; // 0x58 undefined m_unk59; // For tokens from the extra string that look like this: // "Action:openram;\lego\scripts\Race\CarRaceR;0" diff --git a/LEGO1/legoinputmanager.cpp b/LEGO1/legoinputmanager.cpp index e9a82cc6..fb0fc079 100644 --- a/LEGO1/legoinputmanager.cpp +++ b/LEGO1/legoinputmanager.cpp @@ -5,6 +5,7 @@ #include "mxautolocker.h" DECOMP_SIZE_ASSERT(LegoInputManager, 0x338); +DECOMP_SIZE_ASSERT(LegoEventQueue, 0x18); // OFFSET: LEGO1 0x1005b790 LegoInputManager::LegoInputManager() @@ -55,6 +56,27 @@ MxResult LegoInputManager::Create(HWND p_hwnd) return SUCCESS; } +// OFFSET: LEGO1 0x1005bb80 TEMPLATE +// MxCollection::Compare + +// OFFSET: LEGO1 0x1005bc30 TEMPLATE +// MxCollection::Destroy + +// OFFSET: LEGO1 0x1005bc80 TEMPLATE +// MxList::~MxList + +// OFFSET: LEGO1 0x1005bd50 TEMPLATE +// MxCollection::`scalar deleting destructor' + +// OFFSET: LEGO1 0x1005bdc0 TEMPLATE +// MxList::`scalar deleting destructor' + +// OFFSET: LEGO1 0x1005beb0 TEMPLATE +// LegoEventQueue::`scalar deleting destructor' + +// OFFSET: LEGO1 0x1005bf70 TEMPLATE +// MxQueue::`scalar deleting destructor' + // OFFSET: LEGO1 0x1005bfe0 void LegoInputManager::Destroy() { @@ -270,3 +292,6 @@ void LegoInputManager::KillTimer() ::KillTimer(omni->GetWindowHandle(), m_timer); } } + +// OFFSET: LEGO1 0x1005d010 TEMPLATE +// MxListEntry::GetValue diff --git a/LEGO1/legoinputmanager.h b/LEGO1/legoinputmanager.h index c583a64a..542bd02d 100644 --- a/LEGO1/legoinputmanager.h +++ b/LEGO1/legoinputmanager.h @@ -12,7 +12,17 @@ class LegoControlManager; +// VTABLE 0x100d87b8 TEMPLATE +// class MxCollection + +// VTABLE 0x100d87d0 TEMPLATE +// class MxList + +// VTABLE 0x100d87e8 TEMPLATE +// class MxQueue + // VTABLE 0x100d8800 +// SIZE 0x18 class LegoEventQueue : public MxQueue {}; // VTABLE 0x100d8760 @@ -80,37 +90,4 @@ class LegoInputManager : public MxPresenter { MxBool m_unk0x336; }; -// OFFSET: LEGO1 0x1005bb80 TEMPLATE -// MxListParent::Compare - -// OFFSET: LEGO1 0x1005bc30 TEMPLATE -// MxListParent::Destroy - -// OFFSET: LEGO1 0x1005bc80 TEMPLATE -// MxList::~MxList - -// OFFSET: LEGO1 0x1005bd50 TEMPLATE -// MxListParent::`scalar deleting destructor' - -// OFFSET: LEGO1 0x1005bdc0 TEMPLATE -// MxList::`scalar deleting destructor' - -// OFFSET: LEGO1 0x1005beb0 TEMPLATE -// LegoEventQueue::`scalar deleting destructor' - -// OFFSET: LEGO1 0x1005bf70 TEMPLATE -// MxQueue::`scalar deleting destructor' - -// OFFSET: LEGO1 0x1005d010 TEMPLATE -// MxListEntry::GetValue - -// VTABLE 0x100d87e8 TEMPLATE -// class MxQueue - -// VTABLE 0x100d87d0 TEMPLATE -// class MxList - -// VTABLE 0x100d87b8 TEMPLATE -// class MxListParent - #endif // LEGOINPUTMANAGER_H diff --git a/LEGO1/legopalettepresenter.cpp b/LEGO1/legopalettepresenter.cpp index 86b99b0a..6b3981a7 100644 --- a/LEGO1/legopalettepresenter.cpp +++ b/LEGO1/legopalettepresenter.cpp @@ -8,14 +8,34 @@ LegoPalettePresenter::LegoPalettePresenter() Init(); } -// OFFSET: LEGO1 0x1007a070 STUB +// OFFSET: LEGO1 0x1007a070 LegoPalettePresenter::~LegoPalettePresenter() { - // TODO + Destroy(TRUE); } // OFFSET: LEGO1 0x1007a0d0 void LegoPalettePresenter::Init() { - this->m_unk64 = 0; + m_palette = NULL; +} + +// OFFSET: LEGO1 0x1007a0e0 +void LegoPalettePresenter::Destroy(MxBool p_fromDestructor) +{ + m_criticalSection.Enter(); + if (m_palette) { + delete m_palette; + } + Init(); + m_criticalSection.Leave(); + if (!p_fromDestructor) { + MxVideoPresenter::Destroy(FALSE); + } +} + +// OFFSET: LEGO1 0x1007a120 +void LegoPalettePresenter::Destroy() +{ + Destroy(FALSE); } diff --git a/LEGO1/legopalettepresenter.h b/LEGO1/legopalettepresenter.h index 7688d0af..9d500e08 100644 --- a/LEGO1/legopalettepresenter.h +++ b/LEGO1/legopalettepresenter.h @@ -2,6 +2,7 @@ #define LEGOPALETTEPRESENTER_H #include "decomp.h" +#include "mxpalette.h" #include "mxvideopresenter.h" // VTABLE 0x100d9aa0 @@ -9,7 +10,7 @@ class LegoPalettePresenter : public MxVideoPresenter { public: LegoPalettePresenter(); - virtual ~LegoPalettePresenter(); // vtable+0x0 + virtual ~LegoPalettePresenter() override; // vtable+0x0 // OFFSET: LEGO1 0x10079f30 inline const char* ClassName() const override // vtable+0xc @@ -24,10 +25,12 @@ class LegoPalettePresenter : public MxVideoPresenter { return !strcmp(name, ClassName()) || MxVideoPresenter::IsA(name); } + virtual void Destroy() override; // vtable+0x38 private: void Init(); + void Destroy(MxBool p_fromDestructor); - undefined4 m_unk64; + MxPalette* m_palette; }; #endif // LEGOPALETTEPRESENTER_H diff --git a/LEGO1/legopathcontrollerlist.cpp b/LEGO1/legopathcontrollerlist.cpp new file mode 100644 index 00000000..762217c0 --- /dev/null +++ b/LEGO1/legopathcontrollerlist.cpp @@ -0,0 +1,42 @@ +#include "legopathcontrollerlist.h" + +#include "decomp.h" +#include "legopathcontroller.h" + +DECOMP_SIZE_ASSERT(LegoPathControllerList, 0x18); + +// OFFSET: LEGO1 0x1001d210 +MxS8 LegoPathControllerList::Compare(LegoPathController* p_a, LegoPathController* p_b) +{ + return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; +} + +// OFFSET: LEGO1 0x1001d230 TEMPLATE +// MxCollection::Compare + +// OFFSET: LEGO1 0x1001d240 TEMPLATE +// MxList::MxList + +// OFFSET: LEGO1 0x1001d2d0 TEMPLATE +// MxCollection::~MxCollection + +// OFFSET: LEGO1 0x1001d320 TEMPLATE +// MxCollection::Destroy + +// OFFSET: LEGO1 0x1001d330 TEMPLATE +// MxList::~MxList + +// OFFSET: LEGO1 0x1001d3c0 +void LegoPathControllerList::Destroy(LegoPathController* p_controller) +{ + delete p_controller; +} + +// OFFSET: LEGO1 0x1001d490 TEMPLATE +// MxCollection::`scalar deleting destructor' + +// OFFSET: LEGO1 0x1001d500 TEMPLATE +// MxList::`scalar deleting destructor' + +// OFFSET: LEGO1 0x1001d5b0 TEMPLATE +// MxPtrList::`scalar deleting destructor' diff --git a/LEGO1/legopathcontrollerlist.h b/LEGO1/legopathcontrollerlist.h new file mode 100644 index 00000000..f69472d6 --- /dev/null +++ b/LEGO1/legopathcontrollerlist.h @@ -0,0 +1,26 @@ +#ifndef LEGOPATHCONTROLLERLIST_H +#define LEGOPATHCONTROLLERLIST_H + +#include "legopathcontroller.h" +#include "mxlist.h" +#include "mxtypes.h" + +// VTABLE 0x100d6320 TEMPLATE +// class MxPtrList + +// VTABLE 0x100d6338 +// SIZE 0x18 +class LegoPathControllerList : public MxPtrList { +public: + LegoPathControllerList() : MxPtrList(Destroy) {} + virtual MxS8 Compare(LegoPathController*, LegoPathController*) override; // vtable+0x14 + static void Destroy(LegoPathController*); +}; + +// VTABLE 0x100d6380 TEMPLATE +// class MxCollection + +// VTABLE 0x100d6398 TEMPLATE +// class MxList + +#endif // LEGOPATHCONTROLLERLIST_H diff --git a/LEGO1/legoworld.h b/LEGO1/legoworld.h index b2ad8793..7f46ff58 100644 --- a/LEGO1/legoworld.h +++ b/LEGO1/legoworld.h @@ -3,7 +3,9 @@ #include "legocameracontroller.h" #include "legoentity.h" +#include "legopathcontrollerlist.h" #include "mxpresenter.h" +#include "mxpresenterlist.h" // VTABLE 0x100d6280 // SIZE 0xf8 @@ -39,9 +41,12 @@ class LegoWorld : public LegoEntity { void EndAction(MxPresenter* p_presenter); protected: - undefined m_unk68[0x30]; - LegoCameraController* m_camera; - undefined m_unk9c[0x5a]; + LegoPathControllerList m_list0x68; // 0x68 + MxPresenterList m_list0x80; // 0x80 + LegoCameraController* m_camera; // 0x98 + undefined m_unk9c[0x1c]; + MxPresenterList m_list0xb8; // 0xb8 + undefined m_unkd0[0x26]; undefined m_unkf6; undefined m_unkf7; }; diff --git a/LEGO1/mxaudiopresenter.cpp b/LEGO1/mxaudiopresenter.cpp index bd6a5c87..fcb8c0ea 100644 --- a/LEGO1/mxaudiopresenter.cpp +++ b/LEGO1/mxaudiopresenter.cpp @@ -5,13 +5,13 @@ DECOMP_SIZE_ASSERT(MxAudioPresenter, 0x54); // OFFSET: LEGO1 0x1000d260 -undefined4 MxAudioPresenter::vtable5c() +MxU32 MxAudioPresenter::GetVolume() { - return this->m_unk50; + return m_volume; } // OFFSET: LEGO1 0x1000d270 -void MxAudioPresenter::vtable60(undefined4 p_unk50) +void MxAudioPresenter::SetVolume(MxU32 p_volume) { - this->m_unk50 = p_unk50; + m_volume = p_volume; } diff --git a/LEGO1/mxaudiopresenter.h b/LEGO1/mxaudiopresenter.h index 717c8b4d..9fc92457 100644 --- a/LEGO1/mxaudiopresenter.h +++ b/LEGO1/mxaudiopresenter.h @@ -5,9 +5,10 @@ #include "mxmediapresenter.h" // VTABLE 0x100d4c70 +// SIZE 0x54 class MxAudioPresenter : public MxMediaPresenter { public: - MxAudioPresenter() { m_unk50 = 100; } + MxAudioPresenter() { m_volume = 100; } // OFFSET: LEGO1 0x1000d280 inline virtual const char* ClassName() const override // vtable+0x0c @@ -22,10 +23,11 @@ class MxAudioPresenter : public MxMediaPresenter { return !strcmp(name, MxAudioPresenter::ClassName()) || MxMediaPresenter::IsA(name); } - virtual undefined4 vtable5c(); - virtual void vtable60(undefined4); + virtual MxU32 GetVolume(); // vtable+0x5c + virtual void SetVolume(MxU32 p_volume); // vtable+0x60 - undefined4 m_unk50; +private: + MxU32 m_volume; }; #endif // MXAUDIOPRESENTER_H diff --git a/LEGO1/mxbackgroundaudiomanager.cpp b/LEGO1/mxbackgroundaudiomanager.cpp index 26d399f7..2099cbc4 100644 --- a/LEGO1/mxbackgroundaudiomanager.cpp +++ b/LEGO1/mxbackgroundaudiomanager.cpp @@ -159,7 +159,7 @@ void MxBackgroundAudioManager::StartAction(MxParam& p) m_action2.SetAtomId(m_unk138->GetAction()->GetAtomId()); m_action2.SetObjectId(m_unk138->GetAction()->GetObjectId()); m_targetVolume = ((MxDSSound*) (m_unk138->GetAction()))->GetVolume(); - m_unk138->vtable60(0); + m_unk138->SetVolume(0); } // OFFSET: LEGO1 0x1007f200 @@ -257,15 +257,15 @@ void MxBackgroundAudioManager::FUN_1007ef40() if (m_unk148 == 0) { compare = m_unk148; } - volume = m_unk138->vtable5c(); + volume = m_unk138->GetVolume(); if (volume < compare) { - if (m_unk140 + m_unk138->vtable5c() <= compare) { + if (m_unk140 + m_unk138->GetVolume() <= compare) { compare = m_unk140 + compare; } - m_unk138->vtable60(compare); + m_unk138->SetVolume(compare); } else { - m_unk138->vtable60(compare); + m_unk138->SetVolume(compare); m_unka0 = m_unk138; m_action1 = m_action2; m_unk138 = NULL; @@ -276,16 +276,16 @@ void MxBackgroundAudioManager::FUN_1007ef40() } } else if (m_unka0->GetAction() != NULL) { - if (m_unka0->vtable5c() == 0) { + if (m_unka0->GetVolume() == 0) { DeleteObject(*m_unka0->GetAction()); } else { - compare = m_unka0->vtable5c(); + compare = m_unka0->GetVolume(); volume = 0; if (compare != m_unk140 && -1 < compare - m_unk140) { - volume = m_unka0->vtable5c() - m_unk140; + volume = m_unka0->GetVolume() - m_unk140; } - m_unk138->vtable60(volume); + m_unk138->SetVolume(volume); } } } @@ -295,7 +295,7 @@ void MxBackgroundAudioManager::FadeInOrFadeOut() { // This function probably is the fade in/out routine if (m_unka0 != NULL) { - undefined4 volume = m_unka0->vtable5c(); + undefined4 volume = m_unka0->GetVolume(); MxU32 compare = 30; if (m_unk148 == 0) { compare = m_targetVolume; @@ -306,17 +306,17 @@ void MxBackgroundAudioManager::FadeInOrFadeOut() if (compare <= volume) { volume = compare; } - m_unka0->vtable60(volume); + m_unka0->SetVolume(volume); } else if (compare < volume) { volume = volume - m_unk140; if (volume <= compare) { volume = compare; } - m_unka0->vtable60(volume); + m_unka0->SetVolume(volume); } else { - m_unka0->vtable60(volume); + m_unka0->SetVolume(volume); m_unk13c = 0; } } diff --git a/LEGO1/mxcollection.h b/LEGO1/mxcollection.h index 0f32a064..903ba8bd 100644 --- a/LEGO1/mxcollection.h +++ b/LEGO1/mxcollection.h @@ -18,8 +18,8 @@ class MxCollection : public MxCore { virtual MxS8 Compare(T, T) { return 0; } protected: - MxU32 m_count; // +0x8 - void (*m_customDestructor)(T); // +0xc + MxU32 m_count; // 0x8 + void (*m_customDestructor)(T); // 0xc }; #endif // MXCOLLECTION_H diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index e986438f..86f74f14 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -3,7 +3,7 @@ #include "mxdsobject.h" #include "mxtypes.h" -#include "mxvector.h" +#include "realtime/vector.h" class MxOmni; @@ -62,7 +62,7 @@ class MxDSAction : public MxDSObject { inline MxLong GetStartTime() const { return m_startTime; } inline MxS32 GetLoopCount() { return m_loopCount; } inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } - inline const MxVector3Data& GetLocation() const { return m_location; } + inline const Vector3Data& GetLocation() const { return m_location; } inline void SetUnknown84(MxCore* p_unk84) { m_unk84 = p_unk84; } inline MxCore* GetUnknown8c() { return m_unk8c; } inline void SetUnknown8c(MxCore* p_unk8c) { m_unk8c = p_unk8c; } @@ -70,26 +70,20 @@ class MxDSAction : public MxDSObject { inline MxBool IsLooping() const { return m_flags & Flag_Looping; } inline MxBool IsBit3() const { return m_flags & Flag_Bit3; } -private: - MxU32 m_sizeOnDisk; - MxU32 m_flags; - MxLong m_startTime; - -protected: - MxLong m_duration; - MxS32 m_loopCount; - -private: - MxVector3Data m_location; - MxVector3Data m_direction; - MxVector3Data m_up; - char* m_extraData; - MxU16 m_extraLength; - MxCore* m_unk84; - undefined4 m_unk88; - MxCore* m_unk8c; - protected: + MxU32 m_sizeOnDisk; // 0x2c + MxU32 m_flags; // 0x30 + MxLong m_startTime; // 0x34 + MxLong m_duration; // 0x38 + MxS32 m_loopCount; // 0x3c + Vector3Data m_location; // 0x40 + Vector3Data m_direction; // 0x54 + Vector3Data m_up; // 0x68 + char* m_extraData; // 0x7c + MxU16 m_extraLength; // 0x80 + MxCore* m_unk84; // 0x84 + undefined4 m_unk88; // 0x88 + MxCore* m_unk8c; // 0x8c MxLong m_unkTimingField; // 0x90 }; diff --git a/LEGO1/mxdsactionlist.cpp b/LEGO1/mxdsactionlist.cpp index 2959ffcd..123a38eb 100644 --- a/LEGO1/mxdsactionlist.cpp +++ b/LEGO1/mxdsactionlist.cpp @@ -17,3 +17,18 @@ void MxDSActionList::Destroy(MxDSAction* p_action) if (p_action) delete p_action; } + +// OFFSET: LEGO1 0x100c9cc0 TEMPLATE +// MxCollection::Compare + +// OFFSET: LEGO1 0x100c9d20 TEMPLATE +// MxCollection::Destroy + +// OFFSET: LEGO1 0x100c9d30 TEMPLATE +// MxList::~MxList + +// OFFSET: LEGO1 0x100c9e30 TEMPLATE +// MxCollection::`scalar deleting destructor' + +// OFFSET: LEGO1 0x100c9ea0 TEMPLATE +// MxList::`scalar deleting destructor' diff --git a/LEGO1/mxdsactionlist.h b/LEGO1/mxdsactionlist.h index d3bafbbb..b6ca0c11 100644 --- a/LEGO1/mxdsactionlist.h +++ b/LEGO1/mxdsactionlist.h @@ -6,13 +6,19 @@ class MxDSAction; +// VTABLE 0x100dcea8 TEMPLATE +// class MxCollection + +// VTABLE 0x100dcec0 TEMPLATE +// class MxList + // VTABLE 0x100dced8 // SIZE 0x1c class MxDSActionList : public MxList { public: MxDSActionList() { this->m_unk18 = 0; } - virtual MxS8 Compare(MxDSAction*, MxDSAction*) override; // +0x14 + virtual MxS8 Compare(MxDSAction*, MxDSAction*) override; // vtable+0x14 static void Destroy(MxDSAction* p_action); @@ -22,13 +28,4 @@ class MxDSActionList : public MxList { typedef MxListCursorChild MxDSActionListCursor; -// OFFSET: LEGO1 0x100c9cc0 TEMPLATE -// MxListParent::Compare - -// OFFSET: LEGO1 0x100c9d20 TEMPLATE -// MxListParent::Destroy - -// OFFSET: LEGO1 0x100c9d30 TEMPLATE -// MxList::~MxList - #endif // MXDSACTIONLIST_H diff --git a/LEGO1/mxdsmediaaction.h b/LEGO1/mxdsmediaaction.h index f987e8f9..adeb049e 100644 --- a/LEGO1/mxdsmediaaction.h +++ b/LEGO1/mxdsmediaaction.h @@ -37,17 +37,17 @@ class MxDSMediaAction : public MxDSAction { inline MxLong GetSustainTime() const { return this->m_sustainTime; } private: - MxU32 m_sizeOnDisk; - char* m_mediaSrcPath; + MxU32 m_sizeOnDisk; // 0x94 + char* m_mediaSrcPath; // 0x98 struct { undefined4 m_unk00; undefined4 m_unk04; - } m_unk9c; - MxS32 m_framesPerSecond; - MxS32 m_mediaFormat; - MxS32 m_paletteManagement; - MxLong m_sustainTime; - undefined4 m_unkb4; + } m_unk9c; // 0x9c + MxS32 m_framesPerSecond; // 0xa4 + MxS32 m_mediaFormat; // 0xa8 + MxS32 m_paletteManagement; // 0xac + MxLong m_sustainTime; // 0xb0 + undefined4 m_unkb4; // 0xb4 }; #endif // MXDSMEDIAACTION_H diff --git a/LEGO1/mxentity.cpp b/LEGO1/mxentity.cpp index 27067e37..524bb293 100644 --- a/LEGO1/mxentity.cpp +++ b/LEGO1/mxentity.cpp @@ -14,7 +14,7 @@ MxEntity::~MxEntity() } // OFFSET: LEGO1 0x10001070 -MxResult MxEntity::SetEntityId(MxS32 p_id, const MxAtomId& p_atom) +MxResult MxEntity::Create(MxS32 p_id, const MxAtomId& p_atom) { this->m_mxEntityId = p_id; this->m_atom = p_atom; diff --git a/LEGO1/mxentity.h b/LEGO1/mxentity.h index 4ec82f1c..aa8df045 100644 --- a/LEGO1/mxentity.h +++ b/LEGO1/mxentity.h @@ -27,8 +27,8 @@ class MxEntity : public MxCore { return !strcmp(name, MxEntity::ClassName()) || MxCore::IsA(name); } - virtual MxResult SetEntityId(MxS32 p_id, const MxAtomId& p_atom); // vtable+0x14 - inline MxResult InitFromMxDSObject(MxDSObject& p_dsObject) + virtual MxResult Create(MxS32 p_id, const MxAtomId& p_atom); // vtable+0x14 + inline MxResult Create(MxDSObject& p_dsObject) { m_mxEntityId = p_dsObject.GetObjectId(); m_atom = p_dsObject.GetAtomId(); diff --git a/LEGO1/mxflcpresenter.cpp b/LEGO1/mxflcpresenter.cpp index 5c8c23a5..991e0bbe 100644 --- a/LEGO1/mxflcpresenter.cpp +++ b/LEGO1/mxflcpresenter.cpp @@ -1,6 +1,10 @@ #include "mxflcpresenter.h" #include "decomp.h" +#include "mxbitmap.h" +#include "mxomni.h" +#include "mxpalette.h" +#include "mxvideomanager.h" DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); @@ -19,3 +23,13 @@ MxFlcPresenter::~MxFlcPresenter() delete this->m_unk64; } } + +// OFFSET: LEGO1 0x100b3620 +void MxFlcPresenter::VTable0x70() +{ + MxPalette* pal = m_bitmap->CreatePalette(); + MVideoManager()->RealizePalette(pal); + + if (pal) + delete pal; +} diff --git a/LEGO1/mxflcpresenter.h b/LEGO1/mxflcpresenter.h index 99035172..6fcf8973 100644 --- a/LEGO1/mxflcpresenter.h +++ b/LEGO1/mxflcpresenter.h @@ -24,6 +24,8 @@ class MxFlcPresenter : public MxVideoPresenter { return !strcmp(name, MxFlcPresenter::ClassName()) || MxVideoPresenter::IsA(name); } + virtual void VTable0x70() override; // vtable+0x70 + undefined4* m_unk64; }; diff --git a/LEGO1/mxhashtable.h b/LEGO1/mxhashtable.h index a276cfd8..b09bf28c 100644 --- a/LEGO1/mxhashtable.h +++ b/LEGO1/mxhashtable.h @@ -59,16 +59,16 @@ class MxHashTable : protected MxCollection { protected: void _NodeInsert(MxHashTableNode*); - MxHashTableNode** m_slots; // +0x10 - MxU32 m_numSlots; // +0x14 - MxU32 m_autoResizeRatio; // +0x18 - HashTableOpt m_resizeOption; // +0x1c + MxHashTableNode** m_slots; // 0x10 + MxU32 m_numSlots; // 0x14 + MxU32 m_autoResizeRatio; // 0x18 + HashTableOpt m_resizeOption; // 0x1c // FIXME: or FIXME? This qword is used as an integer or double depending // on the value of m_resizeOption. Hard to say whether this is how the devs // did it, but a simple cast in either direction doesn't match. union { - MxU32 m_increaseAmount; // +0x20 - double m_increaseFactor; // +0x20 + MxU32 m_increaseAmount; // 0x20 + double m_increaseFactor; // 0x20 }; }; @@ -156,13 +156,13 @@ void MxHashTable::DeleteAll() while (t) { MxHashTableNode* next = t->m_next; - m_customDestructor(t->m_obj); + this->m_customDestructor(t->m_obj); delete t; t = next; } } - m_count = 0; + this->m_count = 0; memset(m_slots, 0, sizeof(MxHashTableNode*) * m_numSlots); delete[] m_slots; @@ -188,7 +188,7 @@ inline void MxHashTable::Resize() MxHashTableNode** new_table = new MxHashTableNode*[m_numSlots]; m_slots = new_table; memset(m_slots, 0, sizeof(MxHashTableNode*) * m_numSlots); - m_count = 0; + this->m_count = 0; for (MxS32 i = 0; i != old_size; i++) { MxHashTableNode* t = old_table[i]; @@ -214,13 +214,13 @@ inline void MxHashTable::_NodeInsert(MxHashTableNode* p_node) m_slots[bucket]->m_prev = p_node; m_slots[bucket] = p_node; - m_count++; + this->m_count++; } template inline void MxHashTable::Add(T p_newobj) { - if (m_resizeOption && ((m_count + 1) / m_numSlots) > m_autoResizeRatio) + if (m_resizeOption && ((this->m_count + 1) / m_numSlots) > m_autoResizeRatio) MxHashTable::Resize(); MxU32 hash = Hash(p_newobj); diff --git a/LEGO1/mxlist.h b/LEGO1/mxlist.h index 11f0e8ba..d44d6c8f 100644 --- a/LEGO1/mxlist.h +++ b/LEGO1/mxlist.h @@ -1,6 +1,7 @@ #ifndef MXLIST_H #define MXLIST_H +#include "mxcollection.h" #include "mxcore.h" #include "mxtypes.h" @@ -9,6 +10,12 @@ class MxList; template class MxListCursor; +template +class MxPtrList : public MxList { +public: + MxPtrList(void (*p_destroy)(T*) = Destroy) { m_customDestructor = p_destroy; } +}; + template class MxListEntry { public: @@ -40,29 +47,9 @@ class MxListEntry { MxListEntry* m_next; }; -// SIZE 0x10 -template -class MxListParent : public MxCore { -public: - MxListParent() - { - m_count = 0; - m_customDestructor = Destroy; - } - - virtual ~MxListParent() {} - virtual MxS8 Compare(T, T) { return 0; }; - - static void Destroy(T){}; - -protected: - MxU32 m_count; // +0x8 - void (*m_customDestructor)(T); // +0xc -}; - // SIZE 0x18 template -class MxList : protected MxListParent { +class MxList : protected MxCollection { public: MxList() { @@ -80,8 +67,8 @@ class MxList : protected MxListParent { friend class MxListCursor; protected: - MxListEntry* m_first; // +0x10 - MxListEntry* m_last; // +0x14 + MxListEntry* m_first; // 0x10 + MxListEntry* m_last; // 0x14 void _DeleteEntry(MxListEntry* match); MxListEntry* _InsertEntry(T, MxListEntry*, MxListEntry*); diff --git a/LEGO1/mxmatrix.h b/LEGO1/mxmatrix.h deleted file mode 100644 index b9d5420d..00000000 --- a/LEGO1/mxmatrix.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef MXMATRIX_H -#define MXMATRIX_H - -#include "mxvector.h" - -// VTABLE 0x100d4350 -// SIZE 0x8 -class MxMatrix { -public: - inline MxMatrix(float* p_data) : m_data(p_data) {} - - // vtable + 0x00 - virtual void EqualsMxMatrix(const MxMatrix* p_other); - virtual void EqualsMatrixData(const float* p_matrix); - virtual void SetData(float* p_data); - virtual void AnotherSetData(float* p_data); - - // vtable + 0x10 - virtual float* GetData(); - virtual const float* GetData() const; - virtual float* Element(int p_row, int p_col); - virtual const float* Element(int p_row, int p_col) const; - - // vtable + 0x20 - virtual void Clear(); - virtual void SetIdentity(); - virtual void operator=(const MxMatrix& p_other); - virtual MxMatrix* operator+=(const float* p_matrix); - - // vtable + 0x30 - virtual void TranslateBy(const float* p_x, const float* p_y, const float* p_z); - virtual void SetTranslation(const float* p_x, const float* p_y, const float* p_z); - virtual void EqualsMxProduct(const MxMatrix* p_a, const MxMatrix* p_b); - virtual void EqualsDataProduct(const float* p_a, const float* p_b); - - // vtable + 0x40 - virtual void ToQuaternion(MxVector4* p_resultQuat); - virtual MxResult FUN_10002710(const MxVector3* p_vec); - - inline float& operator[](size_t idx) { return m_data[idx]; } - -private: - float* m_data; -}; - -// VTABLE 0x100d4300 -// SIZE 0x48 -class MxMatrixData : public MxMatrix { -public: - inline MxMatrixData() : MxMatrix(e) {} - - // No idea why there's another equals. Maybe to some other type like the - // DirectX Retained Mode Matrix type which is also a float* alias? - // vtable + 0x44 - virtual void operator=(const MxMatrixData& p_other); - - // Alias an easy way to access the translation part of the matrix, because - // various members / other functions benefit from the clarity. - union { - float e[16]; - struct { - float _[12]; - float x, y, z, w; - }; - }; -}; - -#endif // MXMATRIX_H diff --git a/LEGO1/mxmediapresenter.cpp b/LEGO1/mxmediapresenter.cpp index 919b1fa8..0a4d691a 100644 --- a/LEGO1/mxmediapresenter.cpp +++ b/LEGO1/mxmediapresenter.cpp @@ -129,7 +129,7 @@ void MxMediaPresenter::StreamingTickle() else if (m_action->GetFlags() & MxDSAction::Flag_Looping) { AppendChunk(m_currentChunk); - if (!MxPresenter::IsEnabled()) { + if (!IsEnabled()) { m_subscriber->FUN_100b8390(m_currentChunk); m_currentChunk = NULL; } @@ -141,7 +141,7 @@ void MxMediaPresenter::StreamingTickle() // OFFSET: LEGO1 0x100b5e10 void MxMediaPresenter::RepeatingTickle() { - if (MxPresenter::IsEnabled() && !m_currentChunk) { + if (IsEnabled() && !m_currentChunk) { if (m_cursor) if (!m_cursor->Next(m_currentChunk)) m_cursor->Next(m_currentChunk); @@ -173,7 +173,7 @@ void MxMediaPresenter::DoneTickle() // OFFSET: LEGO1 0x100b6030 void MxMediaPresenter::Enable(MxBool p_enable) { - if (MxPresenter::IsEnabled() != p_enable) { + if (IsEnabled() != p_enable) { MxPresenter::Enable(p_enable); if (p_enable) { diff --git a/LEGO1/mxmidipresenter.cpp b/LEGO1/mxmidipresenter.cpp index 59e30fa3..37b6ea9c 100644 --- a/LEGO1/mxmidipresenter.cpp +++ b/LEGO1/mxmidipresenter.cpp @@ -6,6 +6,13 @@ DECOMP_SIZE_ASSERT(MxMIDIPresenter, 0x58); +// OFFSET: LEGO1 0x100c25a0 STUB +MxResult MxMIDIPresenter::AddToManager() +{ + // TODO + return SUCCESS; +} + // OFFSET: LEGO1 0x100c25e0 MxMIDIPresenter::MxMIDIPresenter() { @@ -30,10 +37,46 @@ void MxMIDIPresenter::Destroy(MxBool p_fromDestructor) // TODO } +// OFFSET: LEGO1 0x100c2890 STUB +void MxMIDIPresenter::ReadyTickle() +{ + // TODO +} + +// OFFSET: LEGO1 0x100c28d0 STUB +void MxMIDIPresenter::StartingTickle() +{ + // TODO +} + +// OFFSET: LEGO1 0x100c2910 STUB +void MxMIDIPresenter::StreamingTickle() +{ + // TODO +} + // OFFSET: LEGO1 0x100c2940 void MxMIDIPresenter::DoneTickle() { - if (!MusicManager()->GetMIDIInitialized()) { - this->EndAction(); - } + if (!MusicManager()->GetMIDIInitialized()) + EndAction(); +} + +// OFFSET: LEGO1 0x100c2960 STUB +void MxMIDIPresenter::Destroy() +{ + // TODO +} + +// OFFSET: LEGO1 0x100c2970 STUB +undefined4 MxMIDIPresenter::PutData() +{ + // TODO + return 0; +} + +// OFFSET: LEGO1 0x100c29e0 STUB +void MxMIDIPresenter::EndAction() +{ + // TODO } diff --git a/LEGO1/mxmidipresenter.h b/LEGO1/mxmidipresenter.h index 675f79b5..245adb34 100644 --- a/LEGO1/mxmidipresenter.h +++ b/LEGO1/mxmidipresenter.h @@ -4,6 +4,7 @@ #include "mxmusicpresenter.h" // VTABLE 0x100dca20 +// SIZE 0x58 class MxMIDIPresenter : public MxMusicPresenter { public: MxMIDIPresenter(); @@ -22,11 +23,18 @@ class MxMIDIPresenter : public MxMusicPresenter { return !strcmp(name, MxMIDIPresenter::ClassName()) || MxMusicPresenter::IsA(name); } - virtual void DoneTickle() override; // vtable+0x2c + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void StreamingTickle() override; // vtable+0x20 + virtual void DoneTickle() override; // vtable+0x2c + virtual MxResult AddToManager() override; // vtable+0x34 + virtual void Destroy() override; // vtable+0x38 + virtual void EndAction() override; // vtable+0x40 + virtual undefined4 PutData() override; // vtable+0x4c private: void Init(); - void Destroy(MxBool); + void Destroy(MxBool p_fromDestructor); undefined4 m_unk54; }; diff --git a/LEGO1/mxmusicpresenter.h b/LEGO1/mxmusicpresenter.h index 02edf1a5..2f96d64e 100644 --- a/LEGO1/mxmusicpresenter.h +++ b/LEGO1/mxmusicpresenter.h @@ -7,6 +7,9 @@ // SIZE 0x54 class MxMusicPresenter : public MxAudioPresenter { public: + MxMusicPresenter(); + virtual ~MxMusicPresenter() override; + // OFFSET: LEGO1 0x100c23a0 inline virtual const char* ClassName() const override // vtable+0xc { @@ -20,9 +23,6 @@ class MxMusicPresenter : public MxAudioPresenter { return !strcmp(name, MxMusicPresenter::ClassName()) || MxAudioPresenter::IsA(name); } - MxMusicPresenter(); - virtual ~MxMusicPresenter() override; - virtual MxResult AddToManager() override; // vtable+0x34 virtual void Destroy() override; // vtable+0x38 diff --git a/LEGO1/mxpresenter.cpp b/LEGO1/mxpresenter.cpp index 8843bef5..85579b64 100644 --- a/LEGO1/mxpresenter.cpp +++ b/LEGO1/mxpresenter.cpp @@ -123,7 +123,7 @@ MxResult MxPresenter::StartAction(MxStreamController*, MxDSAction* p_action) this->m_action = p_action; - const MxVector3Data& location = this->m_action->GetLocation(); + const Vector3Data& location = this->m_action->GetLocation(); MxS32 previousTickleState = this->m_currentTickleState; this->m_location = MxPoint32(this->m_action->GetLocation()[0], this->m_action->GetLocation()[1]); diff --git a/LEGO1/mxpresenterlist.cpp b/LEGO1/mxpresenterlist.cpp index f6ed6594..da625f24 100644 --- a/LEGO1/mxpresenterlist.cpp +++ b/LEGO1/mxpresenterlist.cpp @@ -10,3 +10,27 @@ MxS8 MxPresenterList::Compare(MxPresenter* p_a, MxPresenter* p_b) { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } + +// OFFSET: LEGO1 0x1001cd20 TEMPLATE +// MxCollection::Compare + +// OFFSET: LEGO1 0x1001cd30 TEMPLATE +// MxCollection::Destroy + +// OFFSET: LEGO1 0x1001cd40 TEMPLATE +// MxList::MxList + +// OFFSET: LEGO1 0x1001cdd0 TEMPLATE +// MxCollection::~MxCollection + +// OFFSET: LEGO1 0x1001ce20 TEMPLATE +// MxList::~MxList + +// OFFSET: LEGO1 0x1001cf70 TEMPLATE +// MxCollection::`scalar deleting destructor' + +// OFFSET: LEGO1 0x1001cfe0 TEMPLATE +// MxList::`scalar deleting destructor' + +// OFFSET: LEGO1 0x1001d090 TEMPLATE +// MxPtrList::`scalar deleting destructor' diff --git a/LEGO1/mxpresenterlist.h b/LEGO1/mxpresenterlist.h index 350d6c17..b8c95950 100644 --- a/LEGO1/mxpresenterlist.h +++ b/LEGO1/mxpresenterlist.h @@ -5,30 +5,22 @@ class MxPresenter; -// Unclear what the purpose of this class is -// VTABLE 0x100d62f0 -// SIZE 0x18 -class MxPresenterListParent : public MxList { -public: - MxPresenterListParent() { m_customDestructor = Destroy; } -}; +// VTABLE 0x100d62f0 TEMPLATE +// class MxPtrList // VTABLE 0x100d6308 // SIZE 0x18 -class MxPresenterList : public MxPresenterListParent { +class MxPresenterList : public MxPtrList { public: - virtual MxS8 Compare(MxPresenter*, MxPresenter*) override; // +0x14 + virtual MxS8 Compare(MxPresenter*, MxPresenter*) override; // vtable+0x14 }; typedef MxListCursorChildChild MxPresenterListCursor; -// OFFSET: LEGO1 0x1001cd20 TEMPLATE -// MxListParent::Compare +// VTABLE 0x100d6350 TEMPLATE +// class MxCollection -// OFFSET: LEGO1 0x1001cd30 TEMPLATE -// MxListParent::Destroy - -// OFFSET: LEGO1 0x1001ce20 TEMPLATE -// MxList::~MxList +// VTABLE 0x100d6368 TEMPLATE +// class MxList #endif // MXPRESENTERLIST_H diff --git a/LEGO1/mxregion.h b/LEGO1/mxregion.h index ac6acd5e..a0fa7475 100644 --- a/LEGO1/mxregion.h +++ b/LEGO1/mxregion.h @@ -21,7 +21,7 @@ struct MxRegionTopBottom { inline void SetTop(MxS32 p_top) { m_top = p_top; } inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; } - friend class MxRegionListParent; + friend class MxRegionList; private: MxS32 m_top; diff --git a/LEGO1/mxregionlist.cpp b/LEGO1/mxregionlist.cpp index a33d78b7..74e5739a 100644 --- a/LEGO1/mxregionlist.cpp +++ b/LEGO1/mxregionlist.cpp @@ -3,7 +3,7 @@ #include "mxregion.h" // OFFSET: LEGO1 0x100c33e0 -void MxRegionListParent::Destroy(MxRegionTopBottom* p_topBottom) +void MxRegionList::Destroy(MxRegionTopBottom* p_topBottom) { if (p_topBottom) { if (p_topBottom->m_leftRightList) @@ -13,7 +13,52 @@ void MxRegionListParent::Destroy(MxRegionTopBottom* p_topBottom) } // OFFSET: LEGO1 0x100c4e80 -void MxRegionLeftRightListParent::Destroy(MxRegionLeftRight* p_leftRight) +void MxRegionLeftRightList::Destroy(MxRegionLeftRight* p_leftRight) { delete p_leftRight; } + +// OFFSET: LEGO1 0x100c32e0 TEMPLATE +// MxCollection::Compare + +// OFFSET: LEGO1 0x100c3340 TEMPLATE +// MxCollection::Destroy + +// OFFSET: LEGO1 0x100c34d0 TEMPLATE +// MxCollection::`scalar deleting destructor' + +// OFFSET: LEGO1 0x100c3540 TEMPLATE +// MxList::`scalar deleting destructor' + +// OFFSET: LEGO1 0x100c35f0 TEMPLATE +// MxPtrList::`scalar deleting destructor' + +// OFFSET: LEGO1 0x100c4d80 TEMPLATE +// MxCollection::Compare + +// OFFSET: LEGO1 0x100c4de0 TEMPLATE +// MxCollection::Destroy + +// OFFSET: LEGO1 0x100c4f50 TEMPLATE +// MxCollection::`scalar deleting destructor' + +// OFFSET: LEGO1 0x100c4fc0 TEMPLATE +// MxList::`scalar deleting destructor' + +// OFFSET: LEGO1 0x100c5070 TEMPLATE +// MxPtrList::`scalar deleting destructor' + +// OFFSET: LEGO1 0x100c54f0 TEMPLATE +// MxListCursor::MxListCursor + +// OFFSET: LEGO1 0x100c58c0 TEMPLATE +// MxList::_InsertEntry + +// OFFSET: LEGO1 0x100c5970 TEMPLATE +// MxList::_InsertEntry + +// OFFSET: LEGO1 0x100c5a20 TEMPLATE +// MxListEntry::MxListEntry + +// OFFSET: LEGO1 0x100c5a40 TEMPLATE +// MxList::_DeleteEntry diff --git a/LEGO1/mxregionlist.h b/LEGO1/mxregionlist.h index 52336d38..c3a5d2ef 100644 --- a/LEGO1/mxregionlist.h +++ b/LEGO1/mxregionlist.h @@ -6,51 +6,44 @@ struct MxRegionTopBottom; struct MxRegionLeftRight; -// VTABLE 0x100dcb40 -// SIZE 0x18 -class MxRegionListParent : public MxList { -public: - static void Destroy(MxRegionTopBottom* p_topBottom); +// VTABLE 0x100dcb10 TEMPLATE +// class MxCollection - MxRegionListParent() { m_customDestructor = Destroy; } -}; +// VTABLE 0x100dcb28 TEMPLATE +// class MxList + +// VTABLE 0x100dcb40 TEMPLATE +// class MxPtrList // VTABLE 0x100dcb58 // SIZE 0x18 -class MxRegionList : public MxRegionListParent {}; +class MxRegionList : public MxPtrList { +public: + MxRegionList() : MxPtrList(Destroy) {} + static void Destroy(MxRegionTopBottom*); +}; // VTABLE 0x100dcb88 typedef MxListCursorChildChild MxRegionListCursor; -// OFFSET: LEGO1 0x100c5970 TEMPLATE -// MxList::_InsertEntry - -// OFFSET: LEGO1 0x100c5a20 TEMPLATE -// MxListEntry::MxListEntry - -// VTABLE 0x100dcc70 -// SIZE 0x18 -class MxRegionLeftRightListParent : public MxList { -public: - static void Destroy(MxRegionLeftRight* p_leftRight); - - MxRegionLeftRightListParent() { m_customDestructor = Destroy; } -}; - -// VTABLE 0x100dcc88 -// SIZE 0x18 -class MxRegionLeftRightList : public MxRegionLeftRightListParent {}; - // VTABLE 0x100dcc10 typedef MxListCursorChildChild MxRegionLeftRightListCursor; -// OFFSET: LEGO1 0x100c54f0 TEMPLATE -// MxListCursor::MxListCursor +// VTABLE 0x100dcc40 TEMPLATE +// class MxCollection -// OFFSET: LEGO1 0x100c58c0 TEMPLATE -// MxList::_InsertEntry +// VTABLE 0x100dcc58 TEMPLATE +// class MxList -// OFFSET: LEGO1 0x100c5a40 TEMPLATE -// MxList::_DeleteEntry +// VTABLE 0x100dcc70 TEMPLATE +// class MxPtrList + +// VTABLE 0x100dcc88 +// SIZE 0x18 +class MxRegionLeftRightList : public MxPtrList { +public: + MxRegionLeftRightList() : MxPtrList(Destroy) {} + static void Destroy(MxRegionLeftRight*); +}; #endif // MXREGIONLIST_H diff --git a/LEGO1/mxsoundmanager.cpp b/LEGO1/mxsoundmanager.cpp index a57672d3..8e32345e 100644 --- a/LEGO1/mxsoundmanager.cpp +++ b/LEGO1/mxsoundmanager.cpp @@ -145,7 +145,7 @@ void MxSoundManager::SetVolume(MxS32 p_volume) MxPresenterListCursor cursor(m_presenters); while (cursor.Next(presenter)) - ((MxAudioPresenter*) presenter)->vtable60(((MxAudioPresenter*) presenter)->vtable5c()); + ((MxAudioPresenter*) presenter)->SetVolume(((MxAudioPresenter*) presenter)->GetVolume()); m_criticalSection.Leave(); } diff --git a/LEGO1/mxsoundpresenter.cpp b/LEGO1/mxsoundpresenter.cpp index 3935a97c..540dcbac 100644 --- a/LEGO1/mxsoundpresenter.cpp +++ b/LEGO1/mxsoundpresenter.cpp @@ -11,6 +11,12 @@ MxSoundPresenter::~MxSoundPresenter() Destroy(TRUE); } +// OFFSET: LEGO1 0x1000d490 +void MxSoundPresenter::Destroy() +{ + Destroy(FALSE); +} + // OFFSET: LEGO1 0x100b1a50 void MxSoundPresenter::Destroy(MxBool p_fromDestructor) { @@ -37,9 +43,3 @@ MxResult MxSoundPresenter::AddToManager() return ret; } - -// OFFSET: LEGO1 0x1000d490 -void MxSoundPresenter::Destroy() -{ - Destroy(FALSE); -} diff --git a/LEGO1/mxsoundpresenter.h b/LEGO1/mxsoundpresenter.h index 57997646..408dbe88 100644 --- a/LEGO1/mxsoundpresenter.h +++ b/LEGO1/mxsoundpresenter.h @@ -5,6 +5,7 @@ #include "mxomni.h" // VTABLE 0x100d4b08 +// SIZE 0x54 class MxSoundPresenter : public MxAudioPresenter { public: virtual ~MxSoundPresenter() override; @@ -26,7 +27,7 @@ class MxSoundPresenter : public MxAudioPresenter { virtual void Destroy() override; // vtable+0x38 private: - void Destroy(MxBool); + void Destroy(MxBool p_fromDestructor); }; #endif // MXSOUNDPRESENTER_H diff --git a/LEGO1/mxstreamchunklist.cpp b/LEGO1/mxstreamchunklist.cpp index 8c76452e..46a610ad 100644 --- a/LEGO1/mxstreamchunklist.cpp +++ b/LEGO1/mxstreamchunklist.cpp @@ -17,3 +17,18 @@ void MxStreamChunkList::Destroy(MxStreamChunk* p_chunk) if (p_chunk) delete p_chunk; } + +// OFFSET: LEGO1 0x100b5930 TEMPLATE +// MxCollection::Compare + +// OFFSET: LEGO1 0x100b5990 TEMPLATE +// MxCollection::Destroy + +// OFFSET: LEGO1 0x100b59a0 TEMPLATE +// MxList::~MxList + +// OFFSET: LEGO1 0x100b5aa0 TEMPLATE +// MxCollection::`scalar deleting destructor' + +// OFFSET: LEGO1 0x100b5b10 TEMPLATE +// MxList::`scalar deleting destructor' diff --git a/LEGO1/mxstreamchunklist.h b/LEGO1/mxstreamchunklist.h index 3a19950b..9a84e572 100644 --- a/LEGO1/mxstreamchunklist.h +++ b/LEGO1/mxstreamchunklist.h @@ -6,29 +6,23 @@ class MxStreamChunk; +// VTABLE 0x100dc5d0 TEMPLATE +// class MxCollection + +// VTABLE 0x100dc5e8 TEMPLATE +// class MxList + // VTABLE 0x100dc600 // SIZE 0x18 class MxStreamChunkList : public MxList { public: MxStreamChunkList() { m_customDestructor = Destroy; } - virtual MxS8 Compare(MxStreamChunk*, MxStreamChunk*) override; // +0x14 + virtual MxS8 Compare(MxStreamChunk*, MxStreamChunk*) override; // vtable+0x14 static void Destroy(MxStreamChunk* p_chunk); }; typedef MxListCursorChild MxStreamChunkListCursor; -// OFFSET: LEGO1 0x100b5930 TEMPLATE -// MxListParent::Compare - -// OFFSET: LEGO1 0x100b5990 TEMPLATE -// MxListParent::Destroy - -// OFFSET: LEGO1 0x100b59a0 TEMPLATE -// MxList::~MxList - -// OFFSET: LEGO1 0x100b5b10 TEMPLATE -// MxList::`scalar deleting destructor' - #endif // MXSTREAMCHUNKLIST_H diff --git a/LEGO1/mxstringlist.cpp b/LEGO1/mxstringlist.cpp index 8a0a2ddc..9279e8cf 100644 --- a/LEGO1/mxstringlist.cpp +++ b/LEGO1/mxstringlist.cpp @@ -3,3 +3,24 @@ #include "decomp.h" DECOMP_SIZE_ASSERT(MxListEntry, 0x18) + +// OFFSET: LEGO1 0x100cb3c0 TEMPLATE +// MxCollection::Compare + +// OFFSET: LEGO1 0x100cb470 TEMPLATE +// MxCollection::Destroy + +// OFFSET: LEGO1 0x100cb4c0 TEMPLATE +// MxList::~MxList + +// OFFSET: LEGO1 0x100cbb40 TEMPLATE +// MxList::Append + +// OFFSET: LEGO1 0x100cc2d0 TEMPLATE +// MxList::_InsertEntry + +// OFFSET: LEGO1 0x100cc3c0 TEMPLATE +// MxListEntry::MxListEntry + +// OFFSET: LEGO1 0x100cc450 TEMPLATE +// MxListEntry::GetValue diff --git a/LEGO1/mxstringlist.h b/LEGO1/mxstringlist.h index d80c4777..f397fbf7 100644 --- a/LEGO1/mxstringlist.h +++ b/LEGO1/mxstringlist.h @@ -11,25 +11,4 @@ class MxStringList : public MxList {}; // VTABLE 0x100dd058 typedef MxListCursorChild MxStringListCursor; -// OFFSET: LEGO1 0x100cb3c0 TEMPLATE -// MxListParent::Compare - -// OFFSET: LEGO1 0x100cb470 TEMPLATE -// MxListParent::Destroy - -// OFFSET: LEGO1 0x100cb4c0 TEMPLATE -// MxList::~MxList - -// OFFSET: LEGO1 0x100cbb40 TEMPLATE -// MxList::Append - -// OFFSET: LEGO1 0x100cc2d0 TEMPLATE -// MxList::_InsertEntry - -// OFFSET: LEGO1 0x100cc3c0 TEMPLATE -// MxListEntry::MxListEntry - -// OFFSET: LEGO1 0x100cc450 TEMPLATE -// MxListEntry::GetValue - #endif // MXSTRINGLIST_H diff --git a/LEGO1/mxtypes.h b/LEGO1/mxtypes.h index f8158a73..153289a1 100644 --- a/LEGO1/mxtypes.h +++ b/LEGO1/mxtypes.h @@ -33,8 +33,14 @@ typedef unsigned int MxULong; typedef MxS32 MxTime; typedef MxLong MxResult; -const MxResult SUCCESS = 0; -const MxResult FAILURE = -1; + +#ifndef SUCCESS +#define SUCCESS 0 +#endif + +#ifndef FAILURE +#define FAILURE -1 +#endif typedef MxU8 MxBool; diff --git a/LEGO1/mxvariabletable.h b/LEGO1/mxvariabletable.h index 872aa49f..1df02204 100644 --- a/LEGO1/mxvariabletable.h +++ b/LEGO1/mxvariabletable.h @@ -17,8 +17,8 @@ class MxVariableTable : public MxHashTable { // OFFSET: LEGO1 0x100afdb0 static void Destroy(MxVariable* p_obj) { p_obj->Destroy(); } - virtual MxS8 Compare(MxVariable*, MxVariable*) override; // +0x14 - virtual MxU32 Hash(MxVariable*) override; // +0x18 + virtual MxS8 Compare(MxVariable*, MxVariable*) override; // vtable+0x14 + virtual MxU32 Hash(MxVariable*) override; // vtable+0x18 }; // OFFSET: LEGO1 0x100afcd0 TEMPLATE diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index e39a92bf..25a2d850 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -1,12 +1,14 @@ #include "mxvideopresenter.h" +#include "mxautolocker.h" +#include "mxdsmediaaction.h" #include "mxvideomanager.h" DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64); DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0xc); // OFFSET: LEGO1 0x1000c700 -void MxVideoPresenter::VTable0x5c(undefined4 p_unknown1) +void MxVideoPresenter::VTable0x5c(MxStreamChunk* p_chunk) { // Empty } @@ -18,7 +20,7 @@ void MxVideoPresenter::VTable0x60() } // OFFSET: LEGO1 0x1000c720 -void MxVideoPresenter::VTable0x68(undefined4 p_unknown1) +void MxVideoPresenter::VTable0x68(MxStreamChunk* p_chunk) { // Empty } @@ -232,10 +234,20 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) MxMediaPresenter::Destroy(FALSE); } -// OFFSET: LEGO1 0x100b28b0 STUB +// OFFSET: LEGO1 0x100b28b0 void MxVideoPresenter::VTable0x64() { - // TODO + MxStreamChunk* chunk = NextChunk(); + + if (chunk->GetFlags() & MxStreamChunk::Flag_Bit2) { + m_subscriber->FUN_100b8390(chunk); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Repeating; + } + else { + VTable0x68(chunk); + m_subscriber->FUN_100b8390(chunk); + } } // OFFSET: LEGO1 0x100b2900 @@ -306,6 +318,175 @@ void MxVideoPresenter::VTable0x6c() // TODO } +// OFFSET: LEGO1 0x100b2f60 +void MxVideoPresenter::ReadyTickle() +{ + MxStreamChunk* chunk = NextChunk(); + + if (chunk) { + VTable0x5c(chunk); + m_subscriber->FUN_100b8390(chunk); + ParseExtra(); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Starting; + } +} + +// OFFSET: LEGO1 0x100b2fa0 +void MxVideoPresenter::StartingTickle() +{ + MxStreamChunk* chunk = FUN_100b5650(); + + if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { + VTable0x60(); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Streaming; + } +} + +// OFFSET: LEGO1 0x100b2fe0 +void MxVideoPresenter::StreamingTickle() +{ + if (m_action->GetFlags() & MxDSAction::Flag_Bit9) { + if (!m_currentChunk) + MxMediaPresenter::StreamingTickle(); + + if (m_currentChunk) { + VTable0x68(m_currentChunk); + m_currentChunk = NULL; + } + } + else { + for (MxS16 i = 0; i < m_unk5c; i++) { + if (!m_currentChunk) { + MxMediaPresenter::StreamingTickle(); + + if (!m_currentChunk) + break; + } + + if (m_action->GetElapsedTime() < m_currentChunk->GetTime()) + break; + + VTable0x68(m_currentChunk); + m_subscriber->FUN_100b8390(m_currentChunk); + m_currentChunk = NULL; + m_flags |= Flag_Bit1; + + if (m_currentTickleState != TickleState_Streaming) + break; + } + + if (m_flags & Flag_Bit1) + m_unk5c = 5; + } +} + +// OFFSET: LEGO1 0x100b3080 +void MxVideoPresenter::RepeatingTickle() +{ + if (IsEnabled()) { + if (m_action->GetFlags() & MxDSAction::Flag_Bit9) { + if (!m_currentChunk) + MxMediaPresenter::RepeatingTickle(); + + if (m_currentChunk) { + VTable0x68(m_currentChunk); + m_currentChunk = NULL; + } + } + else { + for (MxS16 i = 0; i < m_unk5c; i++) { + if (!m_currentChunk) { + MxMediaPresenter::RepeatingTickle(); + + if (!m_currentChunk) + break; + } + + if (m_action->GetElapsedTime() % m_action->GetLoopCount() < m_currentChunk->GetTime()) + break; + + VTable0x68(m_currentChunk); + m_currentChunk = NULL; + m_flags |= Flag_Bit1; + + if (m_currentTickleState != TickleState_Repeating) + break; + } + + if (m_flags & Flag_Bit1) + m_unk5c = 5; + } + } +} + +// OFFSET: LEGO1 0x100b3130 +void MxVideoPresenter::Unk5Tickle() +{ + MxLong sustainTime = ((MxDSMediaAction*) m_action)->GetSustainTime(); + + if (sustainTime != -1) { + if (sustainTime) { + if (m_unk60 == -1) + m_unk60 = m_action->GetElapsedTime(); + + if (m_action->GetElapsedTime() >= m_unk60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) { + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Done; + } + } + else { + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Done; + } + } +} + +// OFFSET: LEGO1 0x100b31a0 +MxResult MxVideoPresenter::AddToManager() +{ + MxResult result = FAILURE; + + if (MVideoManager()) { + result = SUCCESS; + MVideoManager()->AddPresenter(*this); + } + + return result; +} + +// OFFSET: LEGO1 0x100b31d0 +void MxVideoPresenter::EndAction() +{ + if (m_action) { + MxMediaPresenter::EndAction(); + MxAutoLocker lock(&m_criticalSection); + + if (m_bitmap) { + MxLong height = m_bitmap->GetBmiHeightAbs(); + MxLong width = m_bitmap->GetBmiWidth(); + MxS32 x = m_location.m_x; + MxS32 y = m_location.m_y; + + MxRect32 rect(x, y, x + width, y + height); + + MVideoManager()->InvalidateRect(rect); + } + } +} + +// OFFSET: LEGO1 0x100b3280 +undefined4 MxVideoPresenter::PutData() +{ + MxAutoLocker lock(&m_criticalSection); + + if (IsEnabled() && m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_unk5) + VTable0x6c(); + + return 0; +} + // OFFSET: LEGO1 0x100b3300 undefined MxVideoPresenter::VTable0x74() { diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index 14ad2d78..34406255 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -6,10 +6,14 @@ #include "mxmediapresenter.h" // VTABLE 0x100d4be8 +// SIZE 0x64 class MxVideoPresenter : public MxMediaPresenter { public: - MxVideoPresenter() { Init(); } + enum { + Flag_Bit1 = 0x01, + }; + MxVideoPresenter() { Init(); } virtual ~MxVideoPresenter() override; // vtable+0x0 // OFFSET: LEGO1 0x1000c820 @@ -28,13 +32,20 @@ class MxVideoPresenter : public MxMediaPresenter { void Init(); void Destroy(MxBool p_fromDestructor); - virtual void Destroy() override; // vtable+0x38 - + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void Unk5Tickle() override; // vtable+0x28 + virtual MxResult AddToManager() override; // vtable+0x34 + virtual void Destroy() override; // vtable+0x38 + virtual void EndAction() override; // vtable+0x40 + virtual undefined4 PutData() override; // vtable+0x4c virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) override; // vtable+0x50 - virtual void VTable0x5c(undefined4 p_unknown1); // vtable+0x5c + virtual void VTable0x5c(MxStreamChunk* p_chunk); // vtable+0x5c virtual void VTable0x60(); // vtable+0x60 virtual void VTable0x64(); // vtable+0x64 - virtual void VTable0x68(undefined4 p_unknown1); // vtable+0x68 + virtual void VTable0x68(MxStreamChunk* p_chunk); // vtable+0x68 virtual void VTable0x6c(); // vtable+0x6c virtual void VTable0x70(); // vtable+0x70 virtual undefined VTable0x74(); // vtable+0x74 @@ -56,12 +67,12 @@ class MxVideoPresenter : public MxMediaPresenter { MxS32 IsHit(MxU32 p_x, MxU32 p_y); }; - MxBitmap* m_bitmap; - AlphaMask* m_alpha; - LPDIRECTDRAWSURFACE m_unk58; - undefined2 m_unk5c; - unsigned char m_flags; // 0x5e - MxLong m_unk60; + MxBitmap* m_bitmap; // 0x50 + AlphaMask* m_alpha; // 0x54 + LPDIRECTDRAWSURFACE m_unk58; // 0x58 + MxS16 m_unk5c; // 0x5c + MxU8 m_flags; // 0x5e + MxLong m_unk60; // 0x60 }; #endif // MXVIDEOPRESENTER_H diff --git a/LEGO1/realtime/lodlist.h b/LEGO1/realtime/lodlist.h new file mode 100644 index 00000000..8e40d92a --- /dev/null +++ b/LEGO1/realtime/lodlist.h @@ -0,0 +1,180 @@ +#ifndef LODLIST_H +#define LODLIST_H + +#include "assert.h" + +#include // size_t + +class LODObject; + +// disable: identifier was truncated to '255' characters in the debug information +#pragma warning(disable : 4786) + +////////////////////////////////////////////////////////////////////////////// +// +// LODListBase +// +// An LODListBase is an ordered list of LODObjects +// where each successive object in the list has a more complex +// geometric representation than the one preceeding it. +// + +class LODListBase { +protected: + LODListBase(size_t capacity); + + const LODObject* PushBack(const LODObject*); + const LODObject* PopBack(); + +public: + virtual ~LODListBase(); + const LODObject* operator[](int) const; + + // current number of LODObject* in LODListBase + size_t Size() const; + + // maximum number of LODObject* LODListBase can hold + size_t Capacity() const; + +#ifdef _DEBUG + virtual void Dump(void (*pTracer)(const char*, ...)) const; +#endif + +private: + // not implemented + LODListBase(const LODListBase&); + LODListBase& operator=(const LODListBase&); + +private: + const LODObject** m_ppLODObject; + size_t m_capacity; + size_t m_size; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// LODList +// + +template +class LODList : public LODListBase { +public: + LODList(size_t capacity); + + const T* operator[](int) const; + const T* PushBack(const T*); + const T* PopBack(); +}; + +////////////////////////////////////////////////////////////////////////////// +// +// LODListBase implementation + +inline LODListBase::LODListBase(size_t capacity) + : m_capacity(capacity), m_size(0), m_ppLODObject(new const LODObject*[capacity]) +{ +#ifdef _DEBUG + int i; + + for (i = 0; i < (int) m_capacity; i++) { + m_ppLODObject[i] = 0; + } +#endif +} + +inline LODListBase::~LODListBase() +{ + // all LODObject* should have been popped by client + assert(m_size == 0); + + delete[] m_ppLODObject; +} + +inline size_t LODListBase::Size() const +{ + return m_size; +} + +inline size_t LODListBase::Capacity() const +{ + return m_capacity; +} + +inline const LODObject* LODListBase::operator[](int i) const +{ + assert((0 <= i) && (i < (int) m_size)); + + return m_ppLODObject[i]; +} + +inline const LODObject* LODListBase::PushBack(const LODObject* pLOD) +{ + assert(m_size < m_capacity); + + m_ppLODObject[m_size++] = pLOD; + return pLOD; +} + +inline const LODObject* LODListBase::PopBack() +{ + const LODObject* pLOD; + + assert(m_size > 0); + + pLOD = m_ppLODObject[--m_size]; + +#ifdef _DEBUG + m_ppLODObject[m_size] = 0; +#endif + + return pLOD; +} + +#ifdef _DEBUG +inline void LODListBase::Dump(void (*pTracer)(const char*, ...)) const +{ + int i; + + pTracer("LODListBase<0x%x>: Capacity=%d, Size=%d\n", (void*) this, m_capacity, m_size); + + for (i = 0; i < (int) m_size; i++) { + pTracer(" [%d]: LOD<0x%x>\n", i, m_ppLODObject[i]); + } + + for (i = (int) m_size; i < (int) m_capacity; i++) { + assert(m_ppLODObject[i] == 0); + } +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// LODList implementation + +template +inline LODList::LODList(size_t capacity) : LODListBase(capacity) +{ +} + +template +inline const T* LODList::operator[](int i) const +{ + return static_cast(LODListBase::operator[](i)); +} + +template +inline const T* LODList::PushBack(const T* pLOD) +{ + return static_cast(LODListBase::PushBack(pLOD)); +} + +template +inline const T* LODList::PopBack() +{ + return static_cast(LODListBase::PopBack()); +} + +// re-enable: identifier was truncated to '255' characters in the debug information +#pragma warning(default : 4786) + +#endif // LODLIST_H diff --git a/LEGO1/mxmatrix.cpp b/LEGO1/realtime/matrix.cpp similarity index 59% rename from LEGO1/mxmatrix.cpp rename to LEGO1/realtime/matrix.cpp index 97a65727..0b6b90b1 100644 --- a/LEGO1/mxmatrix.cpp +++ b/LEGO1/realtime/matrix.cpp @@ -1,137 +1,133 @@ -#include "mxmatrix.h" +#include "matrix.h" -#include "decomp.h" +#include "../decomp.h" #include "math.h" #include -DECOMP_SIZE_ASSERT(MxMatrix, 0x8); -DECOMP_SIZE_ASSERT(MxMatrixData, 0x48); - -// OFFSET: LEGO1 0x10002340 -void MxMatrix::EqualsMxMatrix(const MxMatrix* p_other) -{ - memcpy(m_data, p_other->m_data, 16 * sizeof(float)); -} +DECOMP_SIZE_ASSERT(Matrix4, 0x40); +DECOMP_SIZE_ASSERT(Matrix4Impl, 0x8); +DECOMP_SIZE_ASSERT(Matrix4Data, 0x48); // OFFSET: LEGO1 0x10002320 -void MxMatrix::EqualsMatrixData(const float* p_matrix) +void Matrix4Impl::EqualsMatrixData(const Matrix4& p_matrix) { - memcpy(m_data, p_matrix, 16 * sizeof(float)); + *m_data = p_matrix; } -// OFFSET: LEGO1 0x10002370 -void MxMatrix::SetData(float* p_data) +// OFFSET: LEGO1 0x10002340 +void Matrix4Impl::EqualsMatrixImpl(const Matrix4Impl* p_other) { - m_data = p_data; + *m_data = *p_other->m_data; } // OFFSET: LEGO1 0x10002360 -void MxMatrix::AnotherSetData(float* p_data) +void Matrix4Impl::AnotherSetData(Matrix4& p_data) { - m_data = p_data; + m_data = &p_data; } -// OFFSET: LEGO1 0x10002390 -float* MxMatrix::GetData() +// OFFSET: LEGO1 0x10002370 +void Matrix4Impl::SetData(Matrix4& p_data) { - return m_data; + m_data = &p_data; } // OFFSET: LEGO1 0x10002380 -const float* MxMatrix::GetData() const +const Matrix4* Matrix4Impl::GetData() const { return m_data; } -// OFFSET: LEGO1 0x100023c0 -float* MxMatrix::Element(int p_row, int p_col) +// OFFSET: LEGO1 0x10002390 +Matrix4* Matrix4Impl::GetData() { - return &m_data[p_row * 4 + p_col]; + return m_data; } // OFFSET: LEGO1 0x100023a0 -const float* MxMatrix::Element(int p_row, int p_col) const +const float* Matrix4Impl::Element(int p_row, int p_col) const { - return &m_data[p_row * 4 + p_col]; + return &(*m_data)[p_row][p_col]; +} + +// OFFSET: LEGO1 0x100023c0 +float* Matrix4Impl::Element(int p_row, int p_col) +{ + return &(*m_data)[p_row][p_col]; } // OFFSET: LEGO1 0x100023e0 -void MxMatrix::Clear() +void Matrix4Impl::Clear() { memset(m_data, 0, 16 * sizeof(float)); } // OFFSET: LEGO1 0x100023f0 -void MxMatrix::SetIdentity() +void Matrix4Impl::SetIdentity() { Clear(); - m_data[0] = 1.0f; - m_data[5] = 1.0f; - m_data[10] = 1.0f; - m_data[15] = 1.0f; -} - -// OFFSET: LEGO1 0x10002850 -void MxMatrix::operator=(const MxMatrix& p_other) -{ - EqualsMxMatrix(&p_other); + (*m_data)[0][0] = 1.0f; + (*m_data)[1][1] = 1.0f; + (*m_data)[2][2] = 1.0f; + (*m_data)[3][3] = 1.0f; } // OFFSET: LEGO1 0x10002430 -MxMatrix* MxMatrix::operator+=(const float* p_matrix) +Matrix4Impl* Matrix4Impl::operator+=(const Matrix4& p_matrix) { for (int i = 0; i < 16; ++i) - m_data[i] += p_matrix[i]; + ((float*) m_data)[i] += ((float*) &p_matrix)[i]; return this; } // Matches but instructions are significantly out of order. Probably not wrong // code given that the very similar SetTranslation does match. // OFFSET: LEGO1 0x10002460 -void MxMatrix::TranslateBy(const float* p_x, const float* p_y, const float* p_z) +void Matrix4Impl::TranslateBy(const float* p_x, const float* p_y, const float* p_z) { - m_data[12] += *p_x; - m_data[13] += *p_y; - m_data[14] += *p_z; + ((float*) m_data)[12] += *p_x; + ((float*) m_data)[13] += *p_y; + ((float*) m_data)[14] += *p_z; } // OFFSET: LEGO1 0x100024a0 -void MxMatrix::SetTranslation(const float* p_x, const float* p_y, const float* p_z) +void Matrix4Impl::SetTranslation(const float* p_x, const float* p_y, const float* p_z) { - m_data[12] = *p_x; - m_data[13] = *p_y; - m_data[14] = *p_z; -} - -// OFFSET: LEGO1 0x10002530 -void MxMatrix::EqualsMxProduct(const MxMatrix* p_a, const MxMatrix* p_b) -{ - EqualsDataProduct(p_a->m_data, p_b->m_data); + (*m_data)[3][0] = *p_x; + (*m_data)[3][1] = *p_y; + (*m_data)[3][2] = *p_z; } // OFFSET: LEGO1 0x100024d0 -void MxMatrix::EqualsDataProduct(const float* p_a, const float* p_b) +void Matrix4Impl::EqualsDataProduct(const Matrix4& p_a, const Matrix4& p_b) { - float* cur = m_data; + float* cur = (float*) m_data; for (int row = 0; row < 4; ++row) { for (int col = 0; col < 4; ++col) { *cur = 0.0f; for (int k = 0; k < 4; ++k) { - *cur += p_a[row * 4 + k] * p_b[k * 4 + col]; + *cur += p_a[row][k] * p_b[k][col]; } cur++; } } } +// OFFSET: LEGO1 0x10002530 +void Matrix4Impl::EqualsMxProduct(const Matrix4Impl* p_a, const Matrix4Impl* p_b) +{ + EqualsDataProduct(*p_a->m_data, *p_b->m_data); +} + // Not close, Ghidra struggles understinging this method so it will have to // be manually worked out. Included since I at least figured out what it was // doing with rotateIndex and what overall operation it's trying to do. // OFFSET: LEGO1 0x10002550 STUB -void MxMatrix::ToQuaternion(MxVector4* p_outQuat) +void Matrix4Impl::ToQuaternion(Vector4Impl* p_outQuat) { + /* float trace = m_data[0] + m_data[5] + m_data[10]; if (trace > 0) { trace = sqrt(trace + 1.0); @@ -166,18 +162,25 @@ void MxMatrix::ToQuaternion(MxVector4* p_outQuat) p_outQuat->GetData()[3] = (m_data[next + 4 * nextNext] - m_data[nextNext + 4 * next]) * traceValue; p_outQuat->GetData()[next] = (m_data[next + 4 * largest] + m_data[largest + 4 * next]) * traceValue; p_outQuat->GetData()[nextNext] = (m_data[nextNext + 4 * largest] + m_data[largest + 4 * nextNext]) * traceValue; + */ } // No idea what this function is doing and it will be hard to tell until // we have a confirmed usage site. // OFFSET: LEGO1 0x10002710 STUB -MxResult MxMatrix::FUN_10002710(const MxVector3* p_vec) +int Matrix4Impl::FUN_10002710(const Vector3Impl* p_vec) { - return FAILURE; + return -1; +} + +// OFFSET: LEGO1 0x10002850 +void Matrix4Impl::operator=(const Matrix4Impl& p_other) +{ + EqualsMatrixImpl(&p_other); } // OFFSET: LEGO1 0x10002860 -void MxMatrixData::operator=(const MxMatrixData& p_other) +void Matrix4Data::operator=(const Matrix4Data& p_other) { - EqualsMxMatrix(&p_other); + EqualsMatrixImpl(&p_other); } diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h new file mode 100644 index 00000000..4f65e50b --- /dev/null +++ b/LEGO1/realtime/matrix.h @@ -0,0 +1,91 @@ +#ifndef MATRIX_H +#define MATRIX_H + +#include "vector.h" + +/* + * A simple array of four Vector4s that can be indexed into. + */ +class Matrix4 { +public: + float rows[4][4]; // storage is public for easy access + + inline Matrix4() {} + /* + Matrix4(const Vector4& x_axis, const Vector4& y_axis, const Vector4& z_axis, const Vector4& position) + { + rows[0] = x_axis; + rows[1] = y_axis; + rows[2] = z_axis; + rows[3] = position; + } + Matrix4(const float m[4][4]) + { + rows[0] = m[0]; + rows[1] = m[1]; + rows[2] = m[2]; + rows[3] = m[3]; + } + */ + const float* operator[](long i) const { return rows[i]; } + float* operator[](long i) { return rows[i]; } +}; + +// VTABLE 0x100d4350 +// SIZE 0x8 +class Matrix4Impl { +public: + inline Matrix4Impl(Matrix4& p_data) : m_data(&p_data) {} + + // vtable + 0x00 + virtual void EqualsMatrixImpl(const Matrix4Impl* p_other); + virtual void EqualsMatrixData(const Matrix4& p_matrix); + virtual void SetData(Matrix4& p_data); + virtual void AnotherSetData(Matrix4& p_data); + + // vtable + 0x10 + virtual Matrix4* GetData(); + virtual const Matrix4* GetData() const; + virtual float* Element(int p_row, int p_col); + virtual const float* Element(int p_row, int p_col) const; + + // vtable + 0x20 + virtual void Clear(); + virtual void SetIdentity(); + virtual void operator=(const Matrix4Impl& p_other); + virtual Matrix4Impl* operator+=(const Matrix4& p_matrix); + + // vtable + 0x30 + virtual void TranslateBy(const float* p_x, const float* p_y, const float* p_z); + virtual void SetTranslation(const float* p_x, const float* p_y, const float* p_z); + virtual void EqualsMxProduct(const Matrix4Impl* p_a, const Matrix4Impl* p_b); + virtual void EqualsDataProduct(const Matrix4& p_a, const Matrix4& p_b); + + // vtable + 0x40 + virtual void ToQuaternion(Vector4Impl* p_resultQuat); + virtual int FUN_10002710(const Vector3Impl* p_vec); + + inline float& operator[](size_t idx) { return ((float*) m_data)[idx]; } + +protected: + // TODO: Currently unclear whether this class contains a Matrix4* or float*. + Matrix4* m_data; +}; + +// VTABLE 0x100d4300 +// SIZE 0x48 +class Matrix4Data : public Matrix4Impl { +public: + inline Matrix4Data() : Matrix4Impl(m_matrix) {} + inline Matrix4Data(Matrix4Data& p_other) : Matrix4Impl(m_matrix) { m_matrix = *p_other.m_data; } + inline Matrix4& GetMatrix() { return *m_data; } + + // No idea why there's another equals. Maybe to some other type like the + // DirectX Retained Mode Matrix type which is also a float* alias? + // vtable + 0x44 + virtual void operator=(const Matrix4Data& p_other); + + Matrix4 m_matrix; +}; + +#endif // MATRIX_H diff --git a/LEGO1/realtime/orientableroi.cpp b/LEGO1/realtime/orientableroi.cpp new file mode 100644 index 00000000..a1fd6832 --- /dev/null +++ b/LEGO1/realtime/orientableroi.cpp @@ -0,0 +1,68 @@ +#include "orientableroi.h" + +#include "../decomp.h" + +DECOMP_SIZE_ASSERT(OrientableROI, 0xdc) + +// OFFSET: LEGO1 0x100a5910 +void OrientableROI::VTable0x1c() +{ + UpdateWorldBoundingVolumes(); + UpdateWorldVelocity(); +} + +// OFFSET: LEGO1 0x100a5930 +void OrientableROI::SetLocalTransform(const Matrix4Impl& p_transform) +{ + reinterpret_cast(m_local2world) = p_transform; + UpdateWorldBoundingVolumes(); + UpdateWorldVelocity(); +} + +// OFFSET: LEGO1 0x100a5960 +void OrientableROI::VTable0x24(const Matrix4Data& p_transform) +{ + Matrix4Data l_matrix(m_local2world); + m_local2world.EqualsMxProduct(&p_transform, &l_matrix); + UpdateWorldBoundingVolumes(); + UpdateWorldVelocity(); +} + +// OFFSET: LEGO1 0x100a59b0 +void OrientableROI::UpdateWorldData(const Matrix4Data& p_transform) +{ + Matrix4Data l_matrix(m_local2world); + m_local2world.EqualsMxProduct(&l_matrix, &p_transform); + UpdateWorldBoundingVolumes(); + UpdateWorldVelocity(); + + // iterate over comps + if (m_comp) + for (CompoundObject::iterator iter = m_comp->begin(); !(iter == m_comp->end()); iter++) { + ROI* child = *iter; + static_cast(child)->UpdateWorldData(p_transform); + } +} + +// OFFSET: LEGO1 0x100a5a50 +void OrientableROI::UpdateWorldVelocity() +{ +} + +// OFFSET: LEGO1 0x100a5d80 +const Vector3& OrientableROI::GetWorldVelocity() const +{ + return (Vector3&) *m_world_velocity.GetData(); +} + +// OFFSET: LEGO1 0x100a5d90 +const BoundingBox& OrientableROI::GetWorldBoundingBox() const +{ + return m_world_bounding_box; +} + +// OFFSET: LEGO1 0x100a5da0 +const BoundingSphere& OrientableROI::GetWorldBoundingSphere() const +{ + return m_world_bounding_sphere; +} diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h new file mode 100644 index 00000000..958ca322 --- /dev/null +++ b/LEGO1/realtime/orientableroi.h @@ -0,0 +1,49 @@ +#ifndef ORIENTABLEROI_H +#define ORIENTABLEROI_H + +#include "matrix.h" +#include "roi.h" + +class OrientableROI : public ROI { +public: + // OFFSET: LEGO1 0x100a4420 + OrientableROI() + { + FILLVEC3(m_world_bounding_box.Min(), 888888.8); + FILLVEC3(m_world_bounding_box.Max(), -888888.8); + ZEROVEC3(m_world_bounding_sphere.Center()); + m_world_bounding_sphere.Radius() = 0.0; + ZEROVEC3(m_world_velocity); + IDENTMAT4(m_local2world.GetMatrix()); + } + // OFFSET: LEGO1 0x100a4630 TEMPLATE + // OrientableROI::`scalar deleting destructor' + + virtual const Vector3& GetWorldVelocity() const; + virtual const BoundingBox& GetWorldBoundingBox() const; + virtual const BoundingSphere& GetWorldBoundingSphere() const; + +protected: + // vtable + 0x14 + virtual void VTable0x14() { VTable0x1c(); } + virtual void UpdateWorldBoundingVolumes() = 0; + +public: + virtual void VTable0x1c(); + // vtable + 0x20 + virtual void SetLocalTransform(const Matrix4Impl& p_transform); + virtual void VTable0x24(const Matrix4Data& p_transform); + virtual void UpdateWorldData(const Matrix4Data& p_transform); + virtual void UpdateWorldVelocity(); + +protected: + char m_unkc; + Matrix4Data m_local2world; // 0x10 + BoundingBox m_world_bounding_box; // 0x58 + BoundingSphere m_world_bounding_sphere; // 0xa8 + Vector3Data m_world_velocity; // 0xc0 + unsigned int m_unkd4; + unsigned int m_unkd8; +}; + +#endif // ORIENTABLEROI_H diff --git a/LEGO1/realtime/realtime.cpp b/LEGO1/realtime/realtime.cpp index f654f92d..d2eea110 100644 --- a/LEGO1/realtime/realtime.cpp +++ b/LEGO1/realtime/realtime.cpp @@ -2,19 +2,19 @@ // OFFSET: LEGO1 0x100a5b40 void CalcLocalTransform( - const MxVector3& p_posVec, - const MxVector3& p_dirVec, - const MxVector3& p_upVec, - MxMatrix& p_outMatrix + const Vector3Impl& p_posVec, + const Vector3Impl& p_dirVec, + const Vector3Impl& p_upVec, + Matrix4Impl& p_outMatrix ) { - MxFloat x_axis[3], y_axis[3], z_axis[3]; + float x_axis[3], y_axis[3], z_axis[3]; // This is an unrolled version of the "NORMVEC3" macro, // used here to apply a silly hack to get a 100% match { - const MxFloat dirVec1Operation = (p_dirVec)[1] * (p_dirVec)[1]; - MxDouble len = sqrt(((p_dirVec)[0] * (p_dirVec)[0] + dirVec1Operation + (p_dirVec)[2] * (p_dirVec)[2])); + const float dirVec1Operation = (p_dirVec)[1] * (p_dirVec)[1]; + double len = sqrt(((p_dirVec)[0] * (p_dirVec)[0] + dirVec1Operation + (p_dirVec)[2] * (p_dirVec)[2])); ((z_axis)[0] = (p_dirVec)[0] / (len), (z_axis)[1] = (p_dirVec)[1] / (len), (z_axis)[2] = (p_dirVec)[2] / (len)); } @@ -24,8 +24,8 @@ void CalcLocalTransform( // Exact same thing as pointed out by the above comment { - const MxFloat axis2Operation = (x_axis)[2] * (x_axis)[2]; - MxDouble len = sqrt(((x_axis)[0] * (x_axis)[0] + axis2Operation + (x_axis)[1] * (x_axis)[1])); + const float axis2Operation = (x_axis)[2] * (x_axis)[2]; + double len = sqrt(((x_axis)[0] * (x_axis)[0] + axis2Operation + (x_axis)[1] * (x_axis)[1])); ((x_axis)[0] = (x_axis)[0] / (len), (x_axis)[1] = (x_axis)[1] / (len), (x_axis)[2] = (x_axis)[2] / (len)); } @@ -33,8 +33,8 @@ void CalcLocalTransform( // Again, the same thing { - const MxFloat axis2Operation = (y_axis)[2] * (y_axis)[2]; - MxDouble len = sqrt(((y_axis)[0] * (y_axis)[0] + axis2Operation + (y_axis)[1] * (y_axis)[1])); + const float axis2Operation = (y_axis)[2] * (y_axis)[2]; + double len = sqrt(((y_axis)[0] * (y_axis)[0] + axis2Operation + (y_axis)[1] * (y_axis)[1])); ((y_axis)[0] = (y_axis)[0] / (len), (y_axis)[1] = (y_axis)[1] / (len), (y_axis)[2] = (y_axis)[2] / (len)); } diff --git a/LEGO1/realtime/realtime.h b/LEGO1/realtime/realtime.h index feca3493..ae166dfa 100644 --- a/LEGO1/realtime/realtime.h +++ b/LEGO1/realtime/realtime.h @@ -1,19 +1,19 @@ #ifndef REALTIME_H #define REALTIME_H -#include "../mxmatrix.h" +#include "matrix.h" #define NORMVEC3(dst, src) \ { \ - MxDouble len = sqrt(NORMSQRD3(src)); \ + double len = sqrt(NORMSQRD3(src)); \ VDS3(dst, src, len); \ } void CalcLocalTransform( - const MxVector3& p_posVec, - const MxVector3& p_dirVec, - const MxVector3& p_upVec, - MxMatrix& p_outMatrix + const Vector3Impl& p_posVec, + const Vector3Impl& p_dirVec, + const Vector3Impl& p_upVec, + Matrix4Impl& p_outMatrix ); #endif // REALTIME_H diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h new file mode 100644 index 00000000..66c17a84 --- /dev/null +++ b/LEGO1/realtime/roi.h @@ -0,0 +1,107 @@ +#ifndef ROI_H +#define ROI_H + +// ROI stands for Real-time Object Instance. + +#include "../compat.h" +#include "../mxstl.h" +#include "../realtime/realtime.h" +#include "lodlist.h" +#include "vector.h" + +/* + * A simple bounding box object with Min and Max accessor methods. + */ +class BoundingBox { +public: + const Vector3Data& Min() const { return min; } + Vector3Data& Min() { return min; } + const Vector3Data& Max() const { return max; } + Vector3Data& Max() { return max; } + +private: + Vector3Data min; + Vector3Data max; + Vector3Data m_unk28; + Vector3Data m_unk3c; +}; + +/* + * A simple bounding sphere object with center and radius accessor methods. + */ +class BoundingSphere { +public: + const Vector3Data& Center() const { return center; } + Vector3Data& Center() { return center; } + const float& Radius() const { return radius; } + float& Radius() { return radius; } + +private: + Vector3Data center; + float radius; +}; + +/* + * Abstract base class representing a single LOD version of + * a geometric object. + */ +class LODObject { +public: + // LODObject(); + virtual ~LODObject() {} + virtual float Cost(float pixels_covered) const = 0; + virtual float AveragePolyArea() const = 0; + virtual int NVerts() const = 0; +}; + +/* + * A CompoundObject is simply a set of ROI objects which + * all together represent a single object with sub-parts. + */ +class ROI; +// typedef std::set > CompoundObject; +typedef list CompoundObject; + +/* + * A ROIList is a list of ROI objects. + */ +typedef vector ROIList; + +/* + * A simple list of integers. + * Returned by RealtimeView::SelectLODs as indices into an ROIList. + */ +typedef vector IntList; + +class ROI { +public: + ROI() + { + m_comp = 0; + m_lods = 0; + } + virtual ~ROI() + { + // if derived class set the comp and lods, it should delete them + assert(!m_comp); + assert(!m_lods); + } + virtual float IntrinsicImportance() const = 0; + virtual const Vector3& GetWorldVelocity() const = 0; + virtual const BoundingBox& GetWorldBoundingBox() const = 0; + virtual const BoundingSphere& GetWorldBoundingSphere() const = 0; + + const LODListBase* GetLODs() const { return m_lods; } + const LODObject* GetLOD(int i) const + { + assert(m_lods); + return (*m_lods)[i]; + } + int GetLODCount() const { return m_lods ? m_lods->Size() : 0; } + const CompoundObject* GetComp() const { return m_comp; } + +protected: + CompoundObject* m_comp; + LODListBase* m_lods; +}; +#endif // ROI_H diff --git a/LEGO1/mxvector.cpp b/LEGO1/realtime/vector.cpp similarity index 67% rename from LEGO1/mxvector.cpp rename to LEGO1/realtime/vector.cpp index 17d3de9b..4cdcec83 100644 --- a/LEGO1/mxvector.cpp +++ b/LEGO1/realtime/vector.cpp @@ -1,183 +1,183 @@ -#include "mxvector.h" +#include "vector.h" -#include "decomp.h" +#include "../decomp.h" #include #include -DECOMP_SIZE_ASSERT(MxVector2, 0x8); -DECOMP_SIZE_ASSERT(MxVector3, 0x8); -DECOMP_SIZE_ASSERT(MxVector4, 0x8); -DECOMP_SIZE_ASSERT(MxVector3Data, 0x14); -DECOMP_SIZE_ASSERT(MxVector4Data, 0x18); +DECOMP_SIZE_ASSERT(Vector2Impl, 0x8); +DECOMP_SIZE_ASSERT(Vector3Impl, 0x8); +DECOMP_SIZE_ASSERT(Vector4Impl, 0x8); +DECOMP_SIZE_ASSERT(Vector3Data, 0x14); +DECOMP_SIZE_ASSERT(Vector4Data, 0x18); // OFFSET: LEGO1 0x100020a0 -const float* MxVector2::GetData() const +const float* Vector2Impl::GetData() const { return m_data; } // OFFSET: LEGO1 0x10002090 -float* MxVector2::GetData() +float* Vector2Impl::GetData() { return m_data; } // OFFSET: LEGO1 0x10002130 -float MxVector2::Dot(MxVector2* p_a, float* p_b) const +float Vector2Impl::Dot(Vector2Impl* p_a, float* p_b) const { return DotImpl(p_a->m_data, p_b); } // OFFSET: LEGO1 0x10002110 -float MxVector2::Dot(float* p_a, MxVector2* p_b) const +float Vector2Impl::Dot(float* p_a, Vector2Impl* p_b) const { return DotImpl(p_a, p_b->m_data); } // OFFSET: LEGO1 0x100020f0 -float MxVector2::Dot(MxVector2* p_a, MxVector2* p_b) const +float Vector2Impl::Dot(Vector2Impl* p_a, Vector2Impl* p_b) const { return DotImpl(p_a->m_data, p_b->m_data); } // OFFSET: LEGO1 0x100020d0 -float MxVector2::Dot(float* p_a, float* p_b) const +float Vector2Impl::Dot(float* p_a, float* p_b) const { return DotImpl(p_a, p_b); } // OFFSET: LEGO1 0x10002160 -MxResult MxVector2::Unitize() +int Vector2Impl::Unitize() { float sq = LenSquared(); if (sq > 0.0f) { float root = sqrt(sq); if (root > 0) { DivScalarImpl(&root); - return SUCCESS; + return 0; } } - return FAILURE; + return -1; } // OFFSET: LEGO1 0x100021e0 -void MxVector2::AddVector(MxVector2* p_other) +void Vector2Impl::AddVector(Vector2Impl* p_other) { AddVectorImpl(p_other->m_data); } // OFFSET: LEGO1 0x100021d0 -void MxVector2::AddVector(float* p_other) +void Vector2Impl::AddVector(float* p_other) { AddVectorImpl(p_other); } // OFFSET: LEGO1 0x100021c0 -void MxVector2::AddScalar(float p_value) +void Vector2Impl::AddScalar(float p_value) { AddScalarImpl(p_value); } // OFFSET: LEGO1 0x10002200 -void MxVector2::SubVector(MxVector2* p_other) +void Vector2Impl::SubVector(Vector2Impl* p_other) { SubVectorImpl(p_other->m_data); } // OFFSET: LEGO1 0x100021f0 -void MxVector2::SubVector(float* p_other) +void Vector2Impl::SubVector(float* p_other) { SubVectorImpl(p_other); } // OFFSET: LEGO1 0x10002230 -void MxVector2::MullScalar(float* p_value) +void Vector2Impl::MullScalar(float* p_value) { MullScalarImpl(p_value); } // OFFSET: LEGO1 0x10002220 -void MxVector2::MullVector(MxVector2* p_other) +void Vector2Impl::MullVector(Vector2Impl* p_other) { MullVectorImpl(p_other->m_data); } // OFFSET: LEGO1 0x10002210 -void MxVector2::MullVector(float* p_other) +void Vector2Impl::MullVector(float* p_other) { MullVectorImpl(p_other); } // OFFSET: LEGO1 0x10002240 -void MxVector2::DivScalar(float* p_value) +void Vector2Impl::DivScalar(float* p_value) { DivScalarImpl(p_value); } // OFFSET: LEGO1 0x10002260 -void MxVector2::SetVector(MxVector2* p_other) +void Vector2Impl::SetVector(Vector2Impl* p_other) { EqualsImpl(p_other->m_data); } // OFFSET: LEGO1 0x10002250 -void MxVector2::SetVector(float* p_other) +void Vector2Impl::SetVector(float* p_other) { EqualsImpl(p_other); } // OFFSET: LEGO1 0x10001fa0 -void MxVector2::AddScalarImpl(float p_value) +void Vector2Impl::AddScalarImpl(float p_value) { m_data[0] += p_value; m_data[1] += p_value; } // OFFSET: LEGO1 0x10001f80 -void MxVector2::AddVectorImpl(float* p_value) +void Vector2Impl::AddVectorImpl(float* p_value) { m_data[0] += p_value[0]; m_data[1] += p_value[1]; } // OFFSET: LEGO1 0x10001fc0 -void MxVector2::SubVectorImpl(float* p_value) +void Vector2Impl::SubVectorImpl(float* p_value) { m_data[0] -= p_value[0]; m_data[1] -= p_value[1]; } // OFFSET: LEGO1 0x10002000 -void MxVector2::MullScalarImpl(float* p_value) +void Vector2Impl::MullScalarImpl(float* p_value) { m_data[0] *= *p_value; m_data[1] *= *p_value; } // OFFSET: LEGO1 0x10001fe0 -void MxVector2::MullVectorImpl(float* p_value) +void Vector2Impl::MullVectorImpl(float* p_value) { m_data[0] *= p_value[0]; m_data[1] *= p_value[1]; } // OFFSET: LEGO1 0x10002020 -void MxVector2::DivScalarImpl(float* p_value) +void Vector2Impl::DivScalarImpl(float* p_value) { m_data[0] /= *p_value; m_data[1] /= *p_value; } // OFFSET: LEGO1 0x10002040 -float MxVector2::DotImpl(float* p_a, float* p_b) const +float Vector2Impl::DotImpl(float* p_a, float* p_b) const { return p_b[0] * p_a[0] + p_b[1] * p_a[1]; } // OFFSET: LEGO1 0x10002070 -void MxVector2::EqualsImpl(float* p_data) +void Vector2Impl::EqualsImpl(float* p_data) { float* vec = m_data; vec[0] = p_data[0]; @@ -185,7 +185,7 @@ void MxVector2::EqualsImpl(float* p_data) } // OFFSET: LEGO1 0x100020b0 -void MxVector2::Clear() +void Vector2Impl::Clear() { float* vec = m_data; vec[0] = 0.0f; @@ -193,13 +193,13 @@ void MxVector2::Clear() } // OFFSET: LEGO1 0x10002150 -float MxVector2::LenSquared() const +float Vector2Impl::LenSquared() const { return m_data[0] * m_data[0] + m_data[1] * m_data[1]; } // OFFSET: LEGO1 0x10003a90 -void MxVector3::AddScalarImpl(float p_value) +void Vector3Impl::AddScalarImpl(float p_value) { m_data[0] += p_value; m_data[1] += p_value; @@ -207,7 +207,7 @@ void MxVector3::AddScalarImpl(float p_value) } // OFFSET: LEGO1 0x10003a60 -void MxVector3::AddVectorImpl(float* p_value) +void Vector3Impl::AddVectorImpl(float* p_value) { m_data[0] += p_value[0]; m_data[1] += p_value[1]; @@ -215,7 +215,7 @@ void MxVector3::AddVectorImpl(float* p_value) } // OFFSET: LEGO1 0x10003ac0 -void MxVector3::SubVectorImpl(float* p_value) +void Vector3Impl::SubVectorImpl(float* p_value) { m_data[0] -= p_value[0]; m_data[1] -= p_value[1]; @@ -223,7 +223,7 @@ void MxVector3::SubVectorImpl(float* p_value) } // OFFSET: LEGO1 0x10003b20 -void MxVector3::MullScalarImpl(float* p_value) +void Vector3Impl::MullScalarImpl(float* p_value) { m_data[0] *= *p_value; m_data[1] *= *p_value; @@ -231,7 +231,7 @@ void MxVector3::MullScalarImpl(float* p_value) } // OFFSET: LEGO1 0x10003af0 -void MxVector3::MullVectorImpl(float* p_value) +void Vector3Impl::MullVectorImpl(float* p_value) { m_data[0] *= p_value[0]; m_data[1] *= p_value[1]; @@ -239,7 +239,7 @@ void MxVector3::MullVectorImpl(float* p_value) } // OFFSET: LEGO1 0x10003b50 -void MxVector3::DivScalarImpl(float* p_value) +void Vector3Impl::DivScalarImpl(float* p_value) { m_data[0] /= *p_value; m_data[1] /= *p_value; @@ -247,13 +247,13 @@ void MxVector3::DivScalarImpl(float* p_value) } // OFFSET: LEGO1 0x10003b80 -float MxVector3::DotImpl(float* p_a, float* p_b) const +float Vector3Impl::DotImpl(float* p_a, float* p_b) const { return p_a[0] * p_b[0] + p_a[2] * p_b[2] + p_a[1] * p_b[1]; } // OFFSET: LEGO1 0x10003ba0 -void MxVector3::EqualsImpl(float* p_data) +void Vector3Impl::EqualsImpl(float* p_data) { float* vec = m_data; vec[0] = p_data[0]; @@ -262,7 +262,7 @@ void MxVector3::EqualsImpl(float* p_data) } // OFFSET: LEGO1 0x10003bc0 -void MxVector3::Clear() +void Vector3Impl::Clear() { float* vec = m_data; vec[0] = 0.0f; @@ -271,13 +271,13 @@ void MxVector3::Clear() } // OFFSET: LEGO1 0x10003bd0 -float MxVector3::LenSquared() const +float Vector3Impl::LenSquared() const { return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2]; } // OFFSET: LEGO1 0x10002270 -void MxVector3::EqualsCrossImpl(float* p_a, float* p_b) +void Vector3Impl::EqualsCrossImpl(float* p_a, float* p_b) { m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; @@ -285,25 +285,25 @@ void MxVector3::EqualsCrossImpl(float* p_a, float* p_b) } // OFFSET: LEGO1 0x10002300 -void MxVector3::EqualsCross(float* p_a, MxVector3* p_b) +void Vector3Impl::EqualsCross(float* p_a, Vector3Impl* p_b) { EqualsCrossImpl(p_a, p_b->m_data); } // OFFSET: LEGO1 0x100022e0 -void MxVector3::EqualsCross(MxVector3* p_a, float* p_b) +void Vector3Impl::EqualsCross(Vector3Impl* p_a, float* p_b) { EqualsCrossImpl(p_a->m_data, p_b); } // OFFSET: LEGO1 0x100022c0 -void MxVector3::EqualsCross(MxVector3* p_a, MxVector3* p_b) +void Vector3Impl::EqualsCross(Vector3Impl* p_a, Vector3Impl* p_b) { EqualsCrossImpl(p_a->m_data, p_b->m_data); } // OFFSET: LEGO1 0x10003bf0 -void MxVector3::EqualsScalar(float* p_value) +void Vector3Impl::EqualsScalar(float* p_value) { m_data[0] = *p_value; m_data[1] = *p_value; @@ -311,7 +311,7 @@ void MxVector3::EqualsScalar(float* p_value) } // OFFSET: LEGO1 0x100028b0 -void MxVector4::AddScalarImpl(float p_value) +void Vector4Impl::AddScalarImpl(float p_value) { m_data[0] += p_value; m_data[1] += p_value; @@ -320,7 +320,7 @@ void MxVector4::AddScalarImpl(float p_value) } // OFFSET: LEGO1 0x10002870 -void MxVector4::AddVectorImpl(float* p_value) +void Vector4Impl::AddVectorImpl(float* p_value) { m_data[0] += p_value[0]; m_data[1] += p_value[1]; @@ -329,7 +329,7 @@ void MxVector4::AddVectorImpl(float* p_value) } // OFFSET: LEGO1 0x100028f0 -void MxVector4::SubVectorImpl(float* p_value) +void Vector4Impl::SubVectorImpl(float* p_value) { m_data[0] -= p_value[0]; m_data[1] -= p_value[1]; @@ -338,7 +338,7 @@ void MxVector4::SubVectorImpl(float* p_value) } // OFFSET: LEGO1 0x10002970 -void MxVector4::MullScalarImpl(float* p_value) +void Vector4Impl::MullScalarImpl(float* p_value) { m_data[0] *= *p_value; m_data[1] *= *p_value; @@ -347,7 +347,7 @@ void MxVector4::MullScalarImpl(float* p_value) } // OFFSET: LEGO1 0x10002930 -void MxVector4::MullVectorImpl(float* p_value) +void Vector4Impl::MullVectorImpl(float* p_value) { m_data[0] *= p_value[0]; m_data[1] *= p_value[1]; @@ -356,7 +356,7 @@ void MxVector4::MullVectorImpl(float* p_value) } // OFFSET: LEGO1 0x100029b0 -void MxVector4::DivScalarImpl(float* p_value) +void Vector4Impl::DivScalarImpl(float* p_value) { m_data[0] /= *p_value; m_data[1] /= *p_value; @@ -365,13 +365,13 @@ void MxVector4::DivScalarImpl(float* p_value) } // OFFSET: LEGO1 0x100029f0 -float MxVector4::DotImpl(float* p_a, float* p_b) const +float Vector4Impl::DotImpl(float* p_a, float* p_b) const { return p_a[0] * p_b[0] + p_a[2] * p_b[2] + (p_a[1] * p_b[1] + p_a[3] * p_b[3]); } // OFFSET: LEGO1 0x10002a20 -void MxVector4::EqualsImpl(float* p_data) +void Vector4Impl::EqualsImpl(float* p_data) { float* vec = m_data; vec[0] = p_data[0]; @@ -381,7 +381,7 @@ void MxVector4::EqualsImpl(float* p_data) } // OFFSET: LEGO1 0x10002b00 -void MxVector4::Clear() +void Vector4Impl::Clear() { float* vec = m_data; vec[0] = 0.0f; @@ -391,13 +391,13 @@ void MxVector4::Clear() } // OFFSET: LEGO1 0x10002b20 -float MxVector4::LenSquared() const +float Vector4Impl::LenSquared() const { return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2] + m_data[3] * m_data[3]; } // OFFSET: LEGO1 0x10002b40 -void MxVector4::EqualsScalar(float* p_value) +void Vector4Impl::EqualsScalar(float* p_value) { m_data[0] = *p_value; m_data[1] = *p_value; @@ -406,13 +406,13 @@ void MxVector4::EqualsScalar(float* p_value) } // OFFSET: LEGO1 0x10002ae0 -void MxVector4::SetMatrixProduct(MxVector4* p_a, float* p_b) +void Vector4Impl::SetMatrixProduct(Vector4Impl* p_a, float* p_b) { SetMatrixProductImpl(p_a->m_data, p_b); } // OFFSET: LEGO1 0x10002a40 -void MxVector4::SetMatrixProductImpl(float* p_vec, float* p_mat) +void Vector4Impl::SetMatrixProductImpl(float* p_vec, float* p_mat) { m_data[0] = p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + p_vec[2] * p_mat[8] + p_vec[3] * p_mat[12]; m_data[1] = p_vec[0] * p_mat[1] + p_vec[1] * p_mat[5] + p_vec[2] * p_mat[9] + p_vec[4] * p_mat[13]; @@ -423,7 +423,7 @@ void MxVector4::SetMatrixProductImpl(float* p_vec, float* p_mat) // Note close yet, included because I'm at least confident I know what operation // it's trying to do. // OFFSET: LEGO1 0x10002b70 STUB -MxResult MxVector4::NormalizeQuaternion() +int Vector4Impl::NormalizeQuaternion() { float* v = m_data; float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; @@ -435,16 +435,16 @@ MxResult MxVector4::NormalizeQuaternion() v[0] *= magnitude; v[1] *= magnitude; v[2] *= magnitude; - return SUCCESS; + return 0; } - return FAILURE; + return -1; } // OFFSET: LEGO1 0x10002bf0 -void MxVector4::UnknownQuaternionOp(MxVector4* p_a, MxVector4* p_b) +void Vector4Impl::UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b) { - MxFloat* bDat = p_b->m_data; - MxFloat* aDat = p_a->m_data; + float* bDat = p_b->m_data; + float* aDat = p_a->m_data; this->m_data[3] = aDat[3] * bDat[3] - (bDat[0] * aDat[0] + aDat[2] * bDat[2] + aDat[1] * aDat[1]); this->m_data[0] = bDat[2] * aDat[1] - bDat[1] * aDat[2]; diff --git a/LEGO1/mxvector.h b/LEGO1/realtime/vector.h similarity index 50% rename from LEGO1/mxvector.h rename to LEGO1/realtime/vector.h index 783f3f22..aaed9556 100644 --- a/LEGO1/mxvector.h +++ b/LEGO1/realtime/vector.h @@ -1,16 +1,67 @@ -#ifndef MXVECTOR_H -#define MXVECTOR_H - -#include "mxtypes.h" +#ifndef VECTOR_H +#define VECTOR_H #include +/* + * A simple array of three floats that can be indexed into. + */ +class Vector3 { +public: + float elements[3]; // storage is public for easy access + + Vector3() {} + Vector3(float x, float y, float z) + { + elements[0] = x; + elements[1] = y; + elements[2] = z; + } + + Vector3(const float v[3]) + { + elements[0] = v[0]; + elements[1] = v[1]; + elements[2] = v[2]; + } + + const float& operator[](long i) const { return elements[i]; } + float& operator[](long i) { return elements[i]; } +}; + +/* + * A simple array of four floats that can be indexed into. + */ +struct Vector4 { +public: + float elements[4]; // storage is public for easy access + + inline Vector4() {} + Vector4(float x, float y, float z, float w) + { + elements[0] = x; + elements[1] = y; + elements[2] = z; + elements[3] = w; + } + Vector4(const float v[4]) + { + elements[0] = v[0]; + elements[1] = v[1]; + elements[2] = v[2]; + elements[3] = v[3]; + } + + const float& operator[](long i) const { return elements[i]; } + float& operator[](long i) { return elements[i]; } +}; + // VTABLE 0x100d4288 // SIZE 0x8 -class MxVector2 { +class Vector2Impl { public: // OFFSET: LEGO1 0x1000c0f0 - inline MxVector2(float* p_data) { this->SetData(p_data); } + inline Vector2Impl(float* p_data) { this->SetData(p_data); } // vtable + 0x00 (no virtual destructor) virtual void AddScalarImpl(float p_value) = 0; @@ -28,37 +79,37 @@ class MxVector2 { // vtable + 0x20 virtual void EqualsImpl(float* p_data) = 0; - virtual const float* GetData() const; virtual float* GetData(); + virtual const float* GetData() const; virtual void Clear() = 0; // vtable + 0x30 - virtual float Dot(MxVector2* p_a, float* p_b) const; - virtual float Dot(float* p_a, MxVector2* p_b) const; - virtual float Dot(MxVector2* p_a, MxVector2* p_b) const; + virtual float Dot(Vector2Impl* p_a, float* p_b) const; + virtual float Dot(float* p_a, Vector2Impl* p_b) const; + virtual float Dot(Vector2Impl* p_a, Vector2Impl* p_b) const; virtual float Dot(float* p_a, float* p_b) const; // vtable + 0x40 virtual float LenSquared() const = 0; - virtual MxResult Unitize(); + virtual int Unitize(); // vtable + 0x48 - virtual void AddVector(MxVector2* p_other); + virtual void AddVector(Vector2Impl* p_other); virtual void AddVector(float* p_other); virtual void AddScalar(float p_value); // vtable + 0x54 - virtual void SubVector(MxVector2* p_other); + virtual void SubVector(Vector2Impl* p_other); virtual void SubVector(float* p_other); // vtable + 0x5C virtual void MullScalar(float* p_value); - virtual void MullVector(MxVector2* p_other); + virtual void MullVector(Vector2Impl* p_other); virtual void MullVector(float* p_other); virtual void DivScalar(float* p_value); // vtable + 0x6C - virtual void SetVector(MxVector2* p_other); + virtual void SetVector(Vector2Impl* p_other); virtual void SetVector(float* p_other); inline float& operator[](size_t idx) { return m_data[idx]; } @@ -70,9 +121,9 @@ class MxVector2 { // VTABLE 0x100d4518 // SIZE 0x8 -class MxVector3 : public MxVector2 { +class Vector3Impl : public Vector2Impl { public: - inline MxVector3(float* p_data) : MxVector2(p_data) {} + inline Vector3Impl(float* p_data) : Vector2Impl(p_data) {} void AddScalarImpl(float p_value); @@ -92,9 +143,9 @@ class MxVector3 : public MxVector2 { // vtable + 0x74 virtual void EqualsCrossImpl(float* p_a, float* p_b); - virtual void EqualsCross(float* p_a, MxVector3* p_b); - virtual void EqualsCross(MxVector3* p_a, float* p_b); - virtual void EqualsCross(MxVector3* p_a, MxVector3* p_b); + virtual void EqualsCross(float* p_a, Vector3Impl* p_b); + virtual void EqualsCross(Vector3Impl* p_a, float* p_b); + virtual void EqualsCross(Vector3Impl* p_a, Vector3Impl* p_b); virtual void EqualsScalar(float* p_value); inline void Fill(float p_value) { EqualsScalar(&p_value); } @@ -102,9 +153,9 @@ class MxVector3 : public MxVector2 { // VTABLE 0x100d45a0 // SIZE 0x8 -class MxVector4 : public MxVector3 { +class Vector4Impl : public Vector3Impl { public: - inline MxVector4(float* p_data) : MxVector3(p_data) {} + inline Vector4Impl(float* p_data) : Vector3Impl(p_data) {} void AddScalarImpl(float p_value); @@ -125,53 +176,41 @@ class MxVector4 : public MxVector3 { void EqualsScalar(float* p_value); // vtable + 0x84 - virtual void SetMatrixProduct(MxVector4* p_a, float* p_b); + virtual void SetMatrixProduct(Vector4Impl* p_a, float* p_b); virtual void SetMatrixProductImpl(float* p_vec, float* p_mat); - virtual MxResult NormalizeQuaternion(); - virtual void UnknownQuaternionOp(MxVector4* p_a, MxVector4* p_b); + virtual int NormalizeQuaternion(); + virtual void UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b); }; // VTABLE 0x100d4488 // SIZE 0x14 -class MxVector3Data : public MxVector3 { +class Vector3Data : public Vector3Impl { public: - inline MxVector3Data() : MxVector3(storage) {} - inline MxVector3Data(float p_x, float p_y, float p_z) : MxVector3(storage), x(p_x), y(p_y), z(p_z) {} + inline Vector3Data() : Vector3Impl(m_vector.elements) {} + inline Vector3Data(float p_x, float p_y, float p_z) : Vector3Impl(m_vector.elements), m_vector(p_x, p_y, p_z) {} - union { - float storage[3]; - struct { - float x; - float y; - float z; - }; - }; - - void CopyFrom(MxVector3Data& p_other) + void CopyFrom(Vector3Data& p_other) { EqualsImpl(p_other.m_data); - float* dest = this->storage; - float* src = p_other.storage; - for (size_t i = sizeof(storage) / sizeof(float); i > 0; --i) + float* dest = m_vector.elements; + float* src = p_other.m_vector.elements; + for (size_t i = sizeof(m_vector) / sizeof(float); i > 0; --i) *dest++ = *src++; } + +private: + Vector3 m_vector; }; // VTABLE 0x100d41e8 // SIZE 0x18 -class MxVector4Data : public MxVector4 { +class Vector4Data : public Vector4Impl { public: - inline MxVector4Data() : MxVector4(storage) {} - union { - float storage[4]; - struct { - float x; - float y; - float z; - float w; - }; - }; + inline Vector4Data() : Vector4Impl(m_vector.elements) {} + +private: + Vector4 m_vector; }; -#endif // MXVECTOR_H +#endif // VECTOR_H diff --git a/LEGO1/score.cpp b/LEGO1/score.cpp index 1c122482..2b7f2d95 100644 --- a/LEGO1/score.cpp +++ b/LEGO1/score.cpp @@ -74,7 +74,7 @@ MxBool Score::VTable0x5c() } // OFFSET: LEGO1 0x100012a0 -MxResult Score::InitFromMxDSObject(MxDSObject& p_dsObject) +MxResult Score::Create(MxDSObject& p_dsObject) { MxResult result = SetAsCurrentWorld(p_dsObject); diff --git a/LEGO1/score.h b/LEGO1/score.h index 612bba4c..756ba089 100644 --- a/LEGO1/score.h +++ b/LEGO1/score.h @@ -29,13 +29,13 @@ class Score : public LegoWorld { } // OFFSET: LEGO1 0x100011e0 TEMPLATE - // Helicopter::`scalar deleting destructor' + // Score::`scalar deleting destructor' - virtual MxResult InitFromMxDSObject(MxDSObject& p_dsObject) override; // vtable+18 - virtual void Stop() override; // vtable+50 - virtual MxBool VTable0x5c() override; // vtable+5c - virtual MxBool VTable0x64() override; // vtable+64 - virtual void VTable0x68(MxBool p_add) override; // vtable+68 + virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+18 + virtual void Stop() override; // vtable+50 + virtual MxBool VTable0x5c() override; // vtable+5c + virtual MxBool VTable0x64() override; // vtable+64 + virtual void VTable0x68(MxBool p_add) override; // vtable+68 void Paint(); MxLong FUN_10001510(MxEndActionNotificationParam& p); diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h new file mode 100644 index 00000000..5dec4a56 --- /dev/null +++ b/LEGO1/tgl/tgl.h @@ -0,0 +1,365 @@ +#ifndef TGL_H +#define TGL_H + +#ifdef _WIN32 + +#define NOMINMAX // to avoid conflict with STL +#include +#include +#include // HWND + +#endif /* _WIN32 */ + +#include "tglVector.h" + +namespace Tgl +{ + +// ??? +enum ColorModel { + Ramp, + RGB +}; + +// ??? +enum ShadingModel { + Wireframe, + UnlitFlat, + Flat, + Gouraud, + Phong +}; + +// ????? +enum LightType { + Ambient, + Point, + Spot, + Directional, + ParallelPoint +}; + +// ??? +enum ProjectionType { + Perspective, + Orthographic +}; + +enum TextureMappingMode { + Linear, + PerspectiveCorrect +}; + +struct PaletteEntry { + unsigned char m_red; + unsigned char m_green; + unsigned char m_blue; +}; + +#ifdef _WIN32 + +struct DeviceDirectDrawCreateData { + const GUID* m_driverGUID; + HWND m_hWnd; // ??? derive from m_pDirectDraw + IDirectDraw* m_pDirectDraw; + IDirectDrawSurface* m_pFrontBuffer; // ??? derive from m_pDirectDraw + IDirectDrawSurface* m_pBackBuffer; + IDirectDrawPalette* m_pPalette; // ??? derive from m_pDirectDraw + int m_isFullScreen; // ??? derive from m_pDirectDraw +}; + +struct DeviceDirect3DCreateData { + IDirect3D* m_pDirect3D; + IDirect3DDevice* m_pDirect3DDevice; +}; + +#else + +struct DeviceDirectDrawCreateData {}; + +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Result (return value type) + +enum Result { + Error = 0, + Success = 1 +}; + +inline int Succeeded(Result result) +{ + return (result == Success); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Forward declarations + +class Renderer; +class Object; +class Device; +class View; +class Light; +class Camera; +class Group; +class Mesh; +class Texture; + +////////////////////////////////////////////////////////////////////////////// +// +// Object + +class Object { +public: + virtual ~Object() {} + + // returns pointer to implementation data + virtual void* ImplementationDataPtr() = 0; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Renderer + +// ??? for now until we figured out how an app should pass the Renderer around +Renderer* CreateRenderer(); + +class Renderer : public Object { +public: + virtual Device* CreateDevice(const DeviceDirectDrawCreateData&) = 0; + virtual Device* CreateDevice(const DeviceDirect3DCreateData&) = 0; + virtual View* CreateView( + const Device*, + const Camera*, + unsigned long x, + unsigned long y, + unsigned long width, + unsigned long height + ) = 0; + virtual Camera* CreateCamera() = 0; + virtual Light* CreateLight(LightType, double r, double g, double b) = 0; + virtual Group* CreateGroup(const Group* pParent = 0) = 0; + + // pTextureCoordinates is pointer to array of vertexCount elements + // (each element being two floats), or NULL + // pFaceData is faceCount tuples, each of format + // [vertex1index, ... vertexNindex], where N = vertexPerFaceCount + virtual Mesh* CreateMesh( + unsigned long vertexCount, + const float (*pVertices)[3], + const float (*pTextureCoordinates)[2], + unsigned long faceCount, + unsigned long vertexPerFaceCount, + unsigned long* pFaceData + ) = 0; + // pTextureCoordinates is pointer to array of vertexCount elements + // (each element being two floats), or NULL + // pFaceData is: + // [face1VertexCount face1Vertex1index, ... face1VertexMindex + // face2VertexCount face2Vertex1index, ... face2VertexNindex + // ... + // 0] + virtual Mesh* CreateMesh( + unsigned long vertexCount, + const float (*pVertices)[3], + const float (*pTextureCoordinates)[2], + unsigned long* pFaceData + ) = 0; + virtual Texture* CreateTexture( + int width, + int height, + int bitsPerTexel, + const void* pTexels, + int pTexelsArePersistent, + int paletteEntryCount, + const PaletteEntry* pEntries + ) = 0; + virtual Texture* CreateTexture() = 0; + + virtual Result SetTextureDefaultShadeCount(unsigned long) = 0; + virtual Result SetTextureDefaultColorCount(unsigned long) = 0; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Device + +class Device : public Object { +public: + virtual unsigned long GetWidth() = 0; + virtual unsigned long GetHeight() = 0; + virtual Result SetColorModel(ColorModel) = 0; + virtual Result SetShadingModel(ShadingModel) = 0; + virtual Result SetShadeCount(unsigned long) = 0; + virtual Result SetDither(int) = 0; + virtual Result Update() = 0; + + // ??? should this be handled by app ??? + // ??? this needs to be called when the window on which the device is ... + // is being activated + virtual void HandleActivate(int bActivate) = 0; + + // ??? this needs to be called when the window on which this device is based + // needs to be repainted + virtual void HandlePaint(void*) = 0; + +#ifdef _DEBUG + virtual unsigned long GetDrawnTriangleCount() = 0; +#endif +}; + +////////////////////////////////////////////////////////////////////////////// +// +// View + +class View : public Object { +public: + virtual Result Add(const Light*) = 0; + virtual Result Remove(const Light*) = 0; + + virtual Result SetCamera(const Camera*) = 0; + virtual Result SetProjection(ProjectionType) = 0; + virtual Result SetFrustrum(double frontClippingDistance, double backClippingDistance, double degrees) = 0; + virtual Result SetBackgroundColor(double r, double g, double b) = 0; + + virtual Result Clear() = 0; + virtual Result Render(const Group*) = 0; + // ??? needed for fine grain control when using DirectDraw/D3D ??? + virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) = 0; + + // ??? for now: used by Mesh Cost calculation + virtual Result TransformWorldToScreen(const double world[3], double screen[4]) = 0; + + // Pick(): + // x, y: + // view coordinates + // + // ppGroupsToPickFrom: + // array of (Group*) in any order + // Groups to pick from + // + // groupsToPickFromCount: + // size of ppGroupsToPickFrom + // + // rppPickedGroups: + // output parameter + // array of (Group*) representing a Group hierarchy + // top-down order (element 0 is root/scene) + // caller must deallocate array + // ref count of each element (Group*) has not been increased + // an element will be 0, if a corresponding Group was not found in ppGroupsToPickFrom + // + // rPickedGroupCount: + // output parameter + // size of rppPickedGroups + virtual Result Pick( + unsigned long x, + unsigned long y, + const Group** ppGroupsToPickFrom, + int groupsToPickFromCount, + const Group**& rppPickedGroups, + int& rPickedGroupCount + ) = 0; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Camera + +class Camera : public Object { +public: +#if 0 + virtual Result SetPosition(const double[3]) = 0; + virtual Result SetOrientation(const double direction[3], + const double up[3]) = 0; +#endif + virtual Result SetTransformation(const FloatMatrix4&) = 0; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Light + +class Light : public Object { +public: +#if 0 + virtual Result SetPosition(const double[3]) = 0; + virtual Result SetOrientation(const double direction[3], + const double up[3]) = 0; +#endif + virtual Result SetTransformation(const FloatMatrix4&) = 0; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Group + +class Group : public Object { +public: +#if 0 + virtual Result SetPosition(const double[3]) = 0; + virtual Result SetOrientation(const double direction[3], + const double up[3]) = 0; +#endif + // TODO: The type was changed from `FloatMatrix` to `Matrix` to make code in UpdateWorldData match. + // However, this is unlikely to be correct and will have to be figured out at some point. + virtual Result SetTransformation(const Matrix4&) = 0; + + // ??? not yet fully implemented + virtual Result SetColor(double r, double g, double b) = 0; + virtual Result SetTexture(const Texture*) = 0; + + virtual Result Add(const Group*) = 0; + virtual Result Add(const Mesh*) = 0; + + virtual Result Remove(const Group*) = 0; + virtual Result Remove(const Mesh*) = 0; + + virtual Result RemoveAll() = 0; + + // ??? for now: used by Mesh Cost calculation + virtual Result TransformLocalToWorld(const double local[3], double world[3]) = 0; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Mesh + +class Mesh : public Object { +public: + // ??? also on Group + virtual Result SetColor(double r, double g, double b) = 0; + virtual Result SetTexture(const Texture*) = 0; + virtual Result SetTextureMappingMode(TextureMappingMode) = 0; + virtual Result SetShadingModel(ShadingModel) = 0; + +#ifdef _DEBUG + virtual Result GetBoundingBox(float min[3], float max[3]) = 0; + virtual unsigned long GetFaceCount() = 0; + virtual unsigned long GetVertexCount() = 0; +#endif +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Texture + +class Texture : public Object { +public: + virtual Result SetTexels( + int width, + int height, + int bitsPerTexel, + const void* pTexels, + int pTexelsArePersistent + ) = 0; + virtual Result SetPalette(int entryCount, const PaletteEntry* pEntries) = 0; +}; + +////////////////////////////////////////////////////////////////////////////// + +} // namespace Tgl + +#endif // TGL_H diff --git a/LEGO1/tgl/tglvector.h b/LEGO1/tgl/tglvector.h new file mode 100644 index 00000000..a617928d --- /dev/null +++ b/LEGO1/tgl/tglvector.h @@ -0,0 +1,277 @@ +#ifndef TGLVECTOR_H +#define TGLVECTOR_H + +#include "math.h" // ??? sin() in RotateAroundY() + +#include // offsetof() + +namespace Tgl +{ + +namespace Constant +{ +const float Pi = 3.14159265358979323846; +}; + +inline float DegreesToRadians(float degrees) +{ + return Constant::Pi * (degrees / 180.0); +} + +inline float RadiansToDegrees(float radians) +{ + return (radians / Constant::Pi) * 180.0; +} + +////////////////////////////////////////////////////////////////////////////// +// +// Array + +template +class Array { +public: + Array() {} + Array(const Array& rArray) { *this = rArray; } + ~Array() {} + + const T& operator[](int i) const { return m_elements[i]; }; + T& operator[](int i) { return m_elements[i]; }; + + Array& operator=(const Array&); + void operator+=(const Array&); + +protected: + T m_elements[N]; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Array implementation + +template +inline Array& Array::operator=(const Array& rArray) +{ + int i; + + for (i = 0; i < N; i++) { + m_elements[i] = rArray.m_elements[i]; + } + + return *this; +} + +template +inline void Array::operator+=(const Array& rArray) +{ + int i; + + for (i = 0; i < N; i++) { + m_elements[i] += rArray.m_elements[i]; + } +} + +////////////////////////////////////////////////////////////////////////////// +// +// FloatMatrix4 + +class FloatMatrix4 : public Array, 4> { +public: + FloatMatrix4() {} + FloatMatrix4(const FloatMatrix4& rMatrix) { *this = rMatrix; } + FloatMatrix4(const FloatMatrix4&, const FloatMatrix4&); + + void operator*=(const FloatMatrix4&); +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FloatMatrix4 implementation + +inline FloatMatrix4::FloatMatrix4(const FloatMatrix4& rMatrix1, const FloatMatrix4& rMatrix2) +{ + for (int row = 0; row < 4; row++) { + for (int column = 0; column < 4; column++) { + float element = 0; + + for (int i = 0; i < 4; i++) { + element += rMatrix1[row][i] * rMatrix2[i][column]; + } + + m_elements[row][column] = element; + } + } +} + +inline void FloatMatrix4::operator*=(const FloatMatrix4& rMatrix) +{ + FloatMatrix4 temp(*this, rMatrix); + + // *this = FloatMatrix4(*this, rMatrix); + *this = temp; +} + +////////////////////////////////////////////////////////////////////////////// +// +// Transformation matrices + +class Translation : public FloatMatrix4 { +public: + Translation(const float[3]); + Translation(float x, float y, float z); + +protected: + void Init(float x, float y, float z); +}; + +class Scale : public FloatMatrix4 { +public: + Scale(const float[3]); + Scale(float x, float y, float z); + Scale(float); + +protected: + void Init(float x, float y, float z); +}; + +class RotationX : public FloatMatrix4 { +public: + RotationX(float radians); +}; + +class RotationY : public FloatMatrix4 { +public: + RotationY(float radians); +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Transformation matrices implementation + +inline Translation::Translation(const float vector[3]) +{ + Init(vector[0], vector[1], vector[2]); +} + +inline Translation::Translation(float x, float y, float z) +{ + Init(x, y, z); +} + +inline void Translation::Init(float x, float y, float z) +{ + m_elements[0][0] = 1; + m_elements[0][1] = 0; + m_elements[0][2] = 0; + m_elements[0][3] = 0; + + m_elements[1][0] = 0; + m_elements[1][1] = 1; + m_elements[1][2] = 0; + m_elements[1][3] = 0; + + m_elements[2][0] = 0; + m_elements[2][1] = 0; + m_elements[2][2] = 1; + m_elements[2][3] = 0; + + m_elements[3][0] = x; + m_elements[3][1] = y; + m_elements[3][2] = z; + m_elements[3][3] = 1; +} + +inline Scale::Scale(const float vector[3]) +{ + Init(vector[0], vector[1], vector[2]); +} + +inline Scale::Scale(float x, float y, float z) +{ + Init(x, y, z); +} + +inline Scale::Scale(float scale) +{ + Init(scale, scale, scale); +} + +inline void Scale::Init(float x, float y, float z) +{ + m_elements[0][0] = x; + m_elements[0][1] = 0; + m_elements[0][2] = 0; + m_elements[0][3] = 0; + + m_elements[1][0] = 0; + m_elements[1][1] = y; + m_elements[1][2] = 0; + m_elements[1][3] = 0; + + m_elements[2][0] = 0; + m_elements[2][1] = 0; + m_elements[2][2] = z; + m_elements[2][3] = 0; + + m_elements[3][0] = 0; + m_elements[3][1] = 0; + m_elements[3][2] = 0; + m_elements[3][3] = 1; +} + +inline RotationX::RotationX(float radians) +{ + float cosRadians = cos(radians); + float sinRadians = sin(radians); + + m_elements[0][0] = 1; + m_elements[0][1] = 0; + m_elements[0][2] = 0; + m_elements[0][3] = 0; + + m_elements[1][0] = 0; + m_elements[1][1] = cosRadians; + m_elements[1][2] = -sinRadians; + m_elements[1][3] = 0; + + m_elements[2][0] = 0; + m_elements[2][1] = sinRadians; + m_elements[2][2] = cosRadians; + m_elements[2][3] = 0; + + m_elements[3][0] = 0; + m_elements[3][1] = 0; + m_elements[3][2] = 0; + m_elements[3][3] = 1; +} + +inline RotationY::RotationY(float radians) +{ + float cosRadians = cos(radians); + float sinRadians = sin(radians); + + m_elements[0][0] = cosRadians; + m_elements[0][1] = 0; + m_elements[0][2] = sinRadians; + m_elements[0][3] = 0; + + m_elements[1][0] = 0; + m_elements[1][1] = 1; + m_elements[1][2] = 0; + m_elements[1][3] = 0; + + m_elements[2][0] = -sinRadians; + m_elements[2][1] = 0; + m_elements[2][2] = cosRadians; + m_elements[2][3] = 0; + + m_elements[3][0] = 0; + m_elements[3][1] = 0; + m_elements[3][2] = 0; + m_elements[3][3] = 1; +} + +////////////////////////////////////////////////////////////////////////////// + +} // namespace Tgl + +#endif // TLGVECTOR_H diff --git a/LEGO1/viewmanager/viewlodlist.h b/LEGO1/viewmanager/viewlodlist.h new file mode 100644 index 00000000..12817ff9 --- /dev/null +++ b/LEGO1/viewmanager/viewlodlist.h @@ -0,0 +1,116 @@ +#ifndef VIEWLODLIST_H +#define VIEWLODLIST_H + +#include "../compat.h" +#include "../realtime/lodlist.h" +#include "assert.h" + +#pragma warning(disable : 4786) + +class ViewLOD; +class ViewLODListManager; + +////////////////////////////////////////////////////////////////////////////// +// ViewLODList +// +// An ViewLODList is an LODList that is shared among instances of the "same ROI". +// +// ViewLODLists are managed (created and destroyed) by ViewLODListManager. +// + +class ViewLODList : public LODList { + friend ViewLODListManager; + +protected: + ViewLODList(size_t capacity); + ~ViewLODList(); + +public: + inline int AddRef(); + inline int Release(); + +#ifdef _DEBUG + void Dump(void (*pTracer)(const char*, ...)) const; +#endif + +private: + int m_refCount; + ViewLODListManager* m_owner; +}; + +////////////////////////////////////////////////////////////////////////////// +// + +// ??? for now, until we have symbol management +typedef const char* ROIName; +struct ROINameComparator { + bool operator()(const ROIName& rName1, const ROIName& rName2) const + { + return strcmp((const char*) rName1, (const char*) rName2) > 0; + } +}; + +////////////////////////////////////////////////////////////////////////////// +// +// ViewLODListManager +// +// ViewLODListManager manages creation and sharing of ViewLODLists. +// It stores ViewLODLists under a name, the name of the ROI where +// the ViewLODList belongs. + +class ViewLODListManager { + + typedef map ViewLODListMap; + +public: + ViewLODListManager(); + virtual ~ViewLODListManager(); + + // ??? should LODList be const + + // creates an LODList with room for lodCount LODs for a named ROI + // returned LODList has a refCount of 1, i.e. caller must call Release() + // when it no longer holds on to the list + ViewLODList* Create(const ROIName&, int lodCount); + + // returns an LODList for a named ROI + // returned LODList's refCount is increased, i.e. caller must call Release() + // when it no longer holds on to the list + ViewLODList* Lookup(const ROIName&) const; + void Destroy(ViewLODList* lodList); + +#ifdef _DEBUG + void Dump(void (*pTracer)(const char*, ...)) const; +#endif + +private: + ViewLODListMap m_map; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// ViewLODList implementation + +inline ViewLODList::ViewLODList(size_t capacity) : LODList(capacity), m_refCount(0) +{ +} + +inline ViewLODList::~ViewLODList() +{ + assert(m_refCount == 0); +} + +inline int ViewLODList::AddRef() +{ + return ++m_refCount; +} + +inline int ViewLODList::Release() +{ + assert(m_refCount > 0); + if (!--m_refCount) + m_owner->Destroy(this); + return m_refCount; +} + +#endif // VIEWLODLIST_H diff --git a/LEGO1/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp similarity index 100% rename from LEGO1/viewmanager.cpp rename to LEGO1/viewmanager/viewmanager.cpp diff --git a/LEGO1/viewmanager.h b/LEGO1/viewmanager/viewmanager.h similarity index 100% rename from LEGO1/viewmanager.h rename to LEGO1/viewmanager/viewmanager.h diff --git a/LEGO1/viewmanager/viewroi.cpp b/LEGO1/viewmanager/viewroi.cpp new file mode 100644 index 00000000..50100444 --- /dev/null +++ b/LEGO1/viewmanager/viewroi.cpp @@ -0,0 +1,45 @@ +#include "viewroi.h" + +#include "../decomp.h" + +DECOMP_SIZE_ASSERT(ViewROI, 0xe0) + +// OFFSET: LEGO1 0x100a9eb0 +float ViewROI::IntrinsicImportance() const +{ + return .5; +} // for now + +// OFFSET: LEGO1 0x100a9ec0 +const Tgl::Group* ViewROI::GetGeometry() const +{ + return geometry; +} + +// OFFSET: LEGO1 0x100a9ed0 +Tgl::Group* ViewROI::GetGeometry() +{ + return geometry; +} + +// OFFSET: LEGO1 0x100a9ee0 +void ViewROI::UpdateWorldData(const Matrix4Data& parent2world) +{ + OrientableROI::UpdateWorldData(parent2world); + if (geometry) { + // Tgl::FloatMatrix4 tgl_mat; + Matrix4 mat; + SETMAT4(mat, m_local2world.GetMatrix()); + Tgl::Result result = geometry->SetTransformation(mat); + // assert(Tgl::Succeeded(result)); + } +} + +// OFFSET: LEGO1 0x100aa250 TEMPLATE +// ViewROI::`scalar deleting destructor' +inline ViewROI::~ViewROI() +{ + // SetLODList() will decrease refCount of LODList + SetLODList(0); + delete geometry; +} diff --git a/LEGO1/viewmanager/viewroi.h b/LEGO1/viewmanager/viewroi.h new file mode 100644 index 00000000..99e73d34 --- /dev/null +++ b/LEGO1/viewmanager/viewroi.h @@ -0,0 +1,47 @@ +#ifndef VIEWROI_H +#define VIEWROI_H + +#include "../realtime/orientableroi.h" +#include "../tgl/tgl.h" +#include "viewlodlist.h" + +/* + ViewROI objects represent view objects, collections of view objects, + etc. Basically, anything which can be placed in a scene and manipilated + by the view manager is a ViewROI. +*/ +class ViewROI : public OrientableROI { +public: + inline ViewROI(Tgl::Renderer* pRenderer, ViewLODList* lodList) + { + SetLODList(lodList); + geometry = pRenderer->CreateGroup(); + } + inline ~ViewROI(); + inline void SetLODList(ViewLODList* lodList) + { + // ??? inherently type unsafe - kind of... because, now, ROI + // does not expose SetLODs() ... + // solution: create pure virtual LODListBase* ROI::GetLODList() + // and let derived ROI classes hold the LODList + + if (m_lods) { + reinterpret_cast(m_lods)->Release(); + } + + m_lods = lodList; + + if (m_lods) { + reinterpret_cast(m_lods)->AddRef(); + } + } + virtual float IntrinsicImportance() const; + virtual Tgl::Group* GetGeometry(); + virtual const Tgl::Group* GetGeometry() const; + +protected: + Tgl::Group* geometry; + void UpdateWorldData(const Matrix4Data& parent2world); +}; + +#endif // VIEWROI_H diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index 610b10d8..5e295f7d 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -14,6 +14,7 @@ import re from isledecomp.dir import walk_source_dir from isledecomp.parser import find_code_blocks +from pystache import Renderer parser = argparse.ArgumentParser(allow_abbrev=False, description='Recompilation Compare: compare an original EXE with a recompiled EXE + PDB.') @@ -529,50 +530,38 @@ def can_resolve_register_differences(original_asm, new_asm): htmlinsert.append(f'{{address: "0x{addr:x}", name: "{html.escape(recinfo.name)}", matching: {effective_ratio}, diff: "{escaped}"}}') -def gen_html(html_path, data): - templatedata = None - with open(get_file_in_script_dir('template.html')) as templatefile: - templatedata = templatefile.read() +def gen_html(html_file, data): + output_data = Renderer().render_path(get_file_in_script_dir('template.html'), + { + "data": ','.join(data) + } + ) - templatedata = templatedata.replace('/* INSERT DATA HERE */', ','.join(data), 1) - - with open(html_path, 'w') as htmlfile: - htmlfile.write(templatedata) + with open(html_file, 'w') as htmlfile: + htmlfile.write(output_data) -def gen_svg(svg, name, icon, implemented_funcs, total_funcs, raw_accuracy): - templatedata = None - with open(get_file_in_script_dir('template.svg')) as templatefile: - templatedata = templatefile.read() +def gen_svg(svg_file, name_svg, icon, svg_implemented_funcs, total_funcs, raw_accuracy): + icon_data = None + if icon: + with open(icon, 'rb') as iconfile: + icon_data = base64.b64encode(iconfile.read()).decode('utf-8') - # TODO: Use templating engine (e.g. pystache) - # Replace icon - if args.svg_icon: - with open(args.svg_icon, 'rb') as iconfile: - templatedata = templatedata.replace('{icon}', base64.b64encode(iconfile.read()).decode('utf-8'), 1) - - # Replace name - templatedata = templatedata.replace('{name}', name, 1) - - # Replace implemented statistic - templatedata = templatedata.replace('{implemented}', f'{(implemented_funcs / total_funcs * 100):.2f}% ({implemented_funcs}/{total_funcs})', 1) - - # Replace accuracy statistic - templatedata = templatedata.replace('{accuracy}', f'{(raw_accuracy / implemented_funcs * 100):.2f}%', 1) - - # Generate progress bar width total_statistic = raw_accuracy / total_funcs - percenttemplate = '{progbar' - percentstart = templatedata.index(percenttemplate) - percentend = templatedata.index('}', percentstart) - progwidth = float(templatedata[percentstart + len(percenttemplate) + 1:percentend]) * total_statistic - templatedata = templatedata[0:percentstart] + str(progwidth) + templatedata[percentend + 1:] + full_percentbar_width = 127.18422 + output_data = Renderer().render_path(get_file_in_script_dir('template.svg'), + { + "name": name_svg, + "icon": icon_data, + "implemented": f'{(svg_implemented_funcs / total_funcs * 100):.2f}% ({svg_implemented_funcs}/{total_funcs})', + "accuracy": f'{(raw_accuracy / svg_implemented_funcs * 100):.2f}%', + "progbar": total_statistic * full_percentbar_width, + "percent": f'{(total_statistic * 100):.2f}%', + } + ) + with open(svg_file, 'w') as svgfile: + svgfile.write(output_data) - # Replace percentage statistic - templatedata = templatedata.replace('{percent}', f'{(total_statistic * 100):.2f}%', 2) - - with open(svg, 'w') as svgfile: - svgfile.write(templatedata) if html_path: gen_html(html_path, htmlinsert) diff --git a/tools/reccmp/requirements.txt b/tools/reccmp/requirements.txt index 36bffdc5..c7de0d0c 100644 --- a/tools/reccmp/requirements.txt +++ b/tools/reccmp/requirements.txt @@ -1,3 +1,4 @@ -colorama capstone -isledecomp \ No newline at end of file +colorama +isledecomp +pystache \ No newline at end of file diff --git a/tools/reccmp/template.html b/tools/reccmp/template.html index f3087688..25de983a 100644 --- a/tools/reccmp/template.html +++ b/tools/reccmp/template.html @@ -75,7 +75,7 @@ }