diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eb41a6d..2cedd429 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(lego1 SHARED LEGO1/buildingentity.cpp LEGO1/bumpbouy.cpp LEGO1/carrace.cpp + LEGO1/define.cpp LEGO1/dllmain.cpp LEGO1/dunebuggy.cpp LEGO1/elevatorbottom.cpp @@ -46,9 +47,9 @@ add_library(lego1 SHARED LEGO1/jukeboxentity.cpp LEGO1/jukeboxstate.cpp LEGO1/legoact2state.cpp - LEGO1/legoactor.cpp LEGO1/legoactioncontrolpresenter.cpp LEGO1/legoactor.cpp + LEGO1/legoactor.cpp LEGO1/legoanimactor.cpp LEGO1/legoanimationmanager.cpp LEGO1/legoanimmmpresenter.cpp @@ -64,6 +65,7 @@ add_library(lego1 SHARED LEGO1/legoentity.cpp LEGO1/legoentitypresenter.cpp LEGO1/legoflctexturepresenter.cpp + LEGO1/legofullscreenmovie.cpp LEGO1/legogamestate.cpp LEGO1/legohideanimpresenter.cpp LEGO1/legoinputmanager.cpp @@ -91,8 +93,10 @@ add_library(lego1 SHARED LEGO1/legoworld.cpp LEGO1/legoworldpresenter.cpp LEGO1/motorcycle.cpp + LEGO1/mxactionnotificationparam.cpp LEGO1/mxatomid.cpp LEGO1/mxatomidcounter.cpp + LEGO1/mxaudiomanager.cpp LEGO1/mxaudiopresenter.cpp LEGO1/mxautolocker.cpp LEGO1/mxbackgroundaudiomanager.cpp @@ -102,12 +106,15 @@ add_library(lego1 SHARED LEGO1/mxcontrolpresenter.cpp LEGO1/mxcore.cpp LEGO1/mxcriticalsection.cpp + LEGO1/mxdirect3d.cpp LEGO1/mxdirectdraw.cpp LEGO1/mxdiskstreamcontroller.cpp LEGO1/mxdiskstreamprovider.cpp LEGO1/mxdisplaysurface.cpp LEGO1/mxdsaction.cpp + LEGO1/mxdsactionlist.cpp LEGO1/mxdsanim.cpp + LEGO1/mxdsbuffer.cpp LEGO1/mxdschunk.cpp LEGO1/mxdsevent.cpp LEGO1/mxdsfile.cpp @@ -118,10 +125,10 @@ add_library(lego1 SHARED LEGO1/mxdsparallelaction.cpp LEGO1/mxdsselectaction.cpp LEGO1/mxdsserialaction.cpp - LEGO1/mxdsstreamingaction.cpp LEGO1/mxdssound.cpp LEGO1/mxdssource.cpp LEGO1/mxdsstill.cpp + LEGO1/mxdsstreamingaction.cpp LEGO1/mxdssubscriber.cpp LEGO1/mxentity.cpp LEGO1/mxeventmanager.cpp @@ -135,29 +142,35 @@ add_library(lego1 SHARED LEGO1/mxmediamanager.cpp LEGO1/mxmediapresenter.cpp LEGO1/mxmidipresenter.cpp + LEGO1/mxmusicmanager.cpp LEGO1/mxmusicpresenter.cpp LEGO1/mxnotificationmanager.cpp + LEGO1/mxnotificationparam.cpp LEGO1/mxobjectfactory.cpp LEGO1/mxomni.cpp LEGO1/mxomnicreateflags.cpp LEGO1/mxomnicreateparam.cpp - LEGO1/mxomnicreateparambase.cpp LEGO1/mxpalette.cpp LEGO1/mxparam.cpp LEGO1/mxpresenter.cpp + LEGO1/mxpresenterlist.cpp + LEGO1/mxramstreamcontroller.cpp + LEGO1/mxramstreamprovider.cpp LEGO1/mxscheduler.cpp LEGO1/mxsemaphore.cpp LEGO1/mxsmkpresenter.cpp LEGO1/mxsoundmanager.cpp LEGO1/mxsoundpresenter.cpp LEGO1/mxstillpresenter.cpp + LEGO1/mxstreamcontroller.cpp LEGO1/mxstreamer.cpp + LEGO1/mxstreamprovider.cpp LEGO1/mxstring.cpp + LEGO1/mxstringlist.cpp LEGO1/mxthread.cpp LEGO1/mxticklemanager.cpp LEGO1/mxtimer.cpp LEGO1/mxtransitionmanager.cpp - LEGO1/mxunknown100dc6e0.cpp LEGO1/mxvariable.cpp LEGO1/mxvariabletable.cpp LEGO1/mxvector.cpp @@ -205,7 +218,7 @@ if (ISLE_USE_DX5) endif() # Link libraries -target_link_libraries(lego1 PRIVATE ddraw dsound winmm) +target_link_libraries(lego1 PRIVATE ddraw dsound dxguid dinput winmm) # Make sure filenames are ALL CAPS set_property(TARGET lego1 PROPERTY OUTPUT_NAME LEGO1) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9d3364a..005f599c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,7 @@ This repository currently has only one goal: accuracy to the original executable 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: - Indent: 2 spaces -- `PascalCase` for classes and function names. +- `PascalCase` for classes, function names, and enumerations. - `m_camelCase` for member variables. - `g_camelCase` for global variables. - `p_camelCase` for function parameters. diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 198389a3..a4a73035 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -3,14 +3,25 @@ #include -#include "legoomni.h" #include "legoanimationmanager.h" #include "legobuildingmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" #include "legomodelpresenter.h" +#include "legoomni.h" #include "legopartpresenter.h" +#include "legoroi.h" +#include "legovideomanager.h" #include "legoworldpresenter.h" +#include "mxbackgroundaudiomanager.h" #include "mxdirectdraw.h" #include "mxdsaction.h" +#include "mxomnicreateflags.h" +#include "mxomnicreateparam.h" +#include "mxstreamer.h" +#include "mxticklemanager.h" +#include "mxtimer.h" +#include "mxtransitionmanager.h" #include "res/resource.h" @@ -91,9 +102,9 @@ void IsleApp::Close() VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager()->RemoveAll(NULL); Lego()->RemoveWorld(ds.GetAtomId(), ds.GetObjectId()); - Lego()->vtable24(ds); + Lego()->DeleteObject(ds); TransitionManager()->SetWaitIndicator(NULL); - Lego()->vtable3c(); + Lego()->StopTimer(); MxLong lVar8; do { @@ -101,7 +112,7 @@ void IsleApp::Close() } while (lVar8 == 0); while (Lego()) { - if (Lego()->vtable28(ds) != FALSE) { + if (Lego()->DoesEntityExist(ds)) { break; } @@ -232,23 +243,19 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine g_reqEnableRMDevice = 0; VideoManager()->EnableRMDevice(); g_rmDisabled = 0; - Lego()->vtable3c(); + Lego()->StopTimer(); } if (g_closed) { break; } - if (g_mousedown == 0) { -LAB_00401bc7: - if (g_mousemoved) { - g_mousemoved = FALSE; - } - } else if (g_mousemoved) { - if (g_isle) { - g_isle->Tick(0); - } - goto LAB_00401bc7; + if (g_mousedown && g_mousemoved && g_isle) { + g_isle->Tick(0); + } + + if (g_mousemoved) { + g_mousemoved = FALSE; } } } @@ -379,7 +386,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } else if (!valid) { g_rmDisabled = 1; - Lego()->vtable38(); + Lego()->StartTimer(); VideoManager()->DisableRMDevice(); } } @@ -701,7 +708,7 @@ inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) } if (this->m_frameDelta + g_lastFrameTime < currentTime) { - if (!Lego()->vtable40()) { + if (!Lego()->IsTimerRunning()) { TickleManager()->Tickle(); } g_lastFrameTime = currentTime; @@ -727,7 +734,7 @@ inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) return; } - ds.SetAtomId(stream->atom); + ds.SetAtomId(stream->GetAtom()); ds.SetUnknown24(-1); ds.SetObjectId(0); VideoManager()->EnableFullScreenMovie(TRUE, TRUE); @@ -736,7 +743,7 @@ inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) return; } } else { - ds.SetAtomId(stream->atom); + ds.SetAtomId(stream->GetAtom()); ds.SetUnknown24(-1); ds.SetObjectId(0); if (Start(&ds) != SUCCESS) { diff --git a/LEGO1/act2brick.cpp b/LEGO1/act2brick.cpp index 84c8bbb3..dde79d0b 100644 --- a/LEGO1/act2brick.cpp +++ b/LEGO1/act2brick.cpp @@ -21,7 +21,7 @@ MxLong Act2Brick::Notify(MxParam &p) } // OFFSET: LEGO1 0x1007a7f0 STUB -MxLong Act2Brick::Tickle() +MxResult Act2Brick::Tickle() { // TODO diff --git a/LEGO1/act2brick.h b/LEGO1/act2brick.h index bf909198..65aba252 100644 --- a/LEGO1/act2brick.h +++ b/LEGO1/act2brick.h @@ -12,7 +12,7 @@ class Act2Brick : public LegoPathActor virtual ~Act2Brick() override; // vtable+0x0 virtual MxLong Notify(MxParam &p) override; // vtable+0x4 - virtual MxLong Tickle() override; // vtable+0x08 + virtual MxResult Tickle() override; // vtable+0x08 // OFFSET: LEGO1 0x1007a360 inline virtual const char *ClassName() const override // vtable+0x0c diff --git a/LEGO1/ambulance.cpp b/LEGO1/ambulance.cpp index 6b5e76ad..707f7a8d 100644 --- a/LEGO1/ambulance.cpp +++ b/LEGO1/ambulance.cpp @@ -1,7 +1,21 @@ #include "ambulance.h" -// OFFSET: LEGO1 0x10035ee0 STUB +#include "decomp.h" + +DECOMP_SIZE_ASSERT(Ambulance, 0x184); + +// OFFSET: LEGO1 0x10035ee0 Ambulance::Ambulance() { - // TODO + this->m_unk168 = 0; + this->m_unk16a = -1; + this->m_unk164 = 0; + this->m_unk16c = 0; + this->m_unk174 = -1; + this->m_unk16e = 0; + this->m_unk178 = -1; + this->m_unk170 = 0; + this->m_unk172 = 0; + this->m_unk13c = 40.0; + this->m_unk17c = 1.0; } \ No newline at end of file diff --git a/LEGO1/ambulance.h b/LEGO1/ambulance.h index dd89af3c..3371830f 100644 --- a/LEGO1/ambulance.h +++ b/LEGO1/ambulance.h @@ -22,7 +22,20 @@ class Ambulance : public IslePathActor { return !strcmp(name, Ambulance::ClassName()) || IslePathActor::IsA(name); } - +private: + // TODO: Ambulance fields + undefined m_unk160[4]; + MxS32 m_unk164; + MxS16 m_unk168; + MxS16 m_unk16a; + MxS16 m_unk16c; + MxS16 m_unk16e; + MxS16 m_unk170; + MxS16 m_unk172; + MxS32 m_unk174; + MxS32 m_unk178; + MxFloat m_unk17c; + undefined m_unk180[4]; }; #endif // AMBULANCE_H diff --git a/LEGO1/bike.cpp b/LEGO1/bike.cpp index ac741a44..217e8c64 100644 --- a/LEGO1/bike.cpp +++ b/LEGO1/bike.cpp @@ -1,8 +1,12 @@ #include "bike.h" -// OFFSET: LEGO1 0x10076670 STUB +DECOMP_SIZE_ASSERT(Bike, 0x164); + +// OFFSET: LEGO1 0x10076670 Bike::Bike() { - // TODO + this->m_unk13c = 20.0; + this->m_unk150 = 3.0; + this->m_unk148 = 1; } diff --git a/LEGO1/bike.h b/LEGO1/bike.h index 8d2de0f1..af8711a5 100644 --- a/LEGO1/bike.h +++ b/LEGO1/bike.h @@ -1,6 +1,7 @@ #ifndef BIKE_H #define BIKE_H +#include "decomp.h" #include "islepathactor.h" // VTABLE 0x100d9808 @@ -22,7 +23,9 @@ class Bike : public IslePathActor { return !strcmp(name, Bike::ClassName()) || IslePathActor::IsA(name); } - +private: + // TODO: Bike fields + undefined m_unk160[4]; }; diff --git a/LEGO1/compat.h b/LEGO1/compat.h index 33b97d5a..ba0b9d34 100644 --- a/LEGO1/compat.h +++ b/LEGO1/compat.h @@ -18,6 +18,9 @@ // Impossible to avoid this if using STL map or set. // This removes most (but not all) occurrences of the warning. #pragma warning( disable : 4786 ) +// To really remove *all* of the warnings, we have to employ the following, +// obscure workaround from https://www.earthli.com/news/view_article.php?id=376 +static class msVC6_4786WorkAround { public: msVC6_4786WorkAround() {} } msVC6_4786WorkAround; #define MSVC420_VERSION 1020 diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp new file mode 100644 index 00000000..84073b9d --- /dev/null +++ b/LEGO1/define.cpp @@ -0,0 +1,10 @@ +#include "define.h" + +// 0x10101eac +const char *g_parseExtraTokens = ":;"; + +// 0x10101edc +const char *g_strWORLD = "WORLD"; + +// 0x10102040 +const char *g_strACTION = "ACTION"; diff --git a/LEGO1/define.h b/LEGO1/define.h new file mode 100644 index 00000000..ec41943e --- /dev/null +++ b/LEGO1/define.h @@ -0,0 +1,8 @@ +#ifndef DEFINE_H +#define DEFINE_H + +extern const char *g_parseExtraTokens; +extern const char *g_strWORLD; +extern const char *g_strACTION; + +#endif // DEFINE_H \ No newline at end of file diff --git a/LEGO1/dunebuggy.cpp b/LEGO1/dunebuggy.cpp index babf21cb..42fd4c37 100644 --- a/LEGO1/dunebuggy.cpp +++ b/LEGO1/dunebuggy.cpp @@ -1,7 +1,12 @@ #include "dunebuggy.h" -// OFFSET: LEGO1 0x10067bb0 STUB +#include "decomp.h" + +DECOMP_SIZE_ASSERT(DuneBuggy, 0x16c); + +// OFFSET: LEGO1 0x10067bb0 DuneBuggy::DuneBuggy() { - // TODO + this->m_unk13c = 25.0; + this->m_unk164 = 1.0; } \ No newline at end of file diff --git a/LEGO1/dunebuggy.h b/LEGO1/dunebuggy.h index 1f89784e..1a083207 100644 --- a/LEGO1/dunebuggy.h +++ b/LEGO1/dunebuggy.h @@ -1,6 +1,7 @@ #ifndef DUNEBUGGY_H #define DUNEBUGGY_H +#include "decomp.h" #include "islepathactor.h" // VTABLE 0x100d8f98 @@ -22,7 +23,11 @@ class DuneBuggy : public IslePathActor { return !strcmp(name, DuneBuggy::ClassName()) || IslePathActor::IsA(name); } - +private: + // TODO: Double check DuneBuggy field types + undefined4 m_unk160; + MxFloat m_unk164; + undefined4 m_unk168; }; #endif // DUNEBUGGY_H diff --git a/LEGO1/extra.h b/LEGO1/extra.h new file mode 100644 index 00000000..05ed5f07 --- /dev/null +++ b/LEGO1/extra.h @@ -0,0 +1,21 @@ +#ifndef EXTRA_H +#define EXTRA_H + +// Items related to the Extra string of key-value pairs found in MxOb + +enum ExtraActionType +{ + ExtraActionType_opendisk = 1, + ExtraActionType_openram = 2, + ExtraActionType_close = 3, + ExtraActionType_start = 4, + ExtraActionType_stop = 5, + ExtraActionType_run = 6, + ExtraActionType_exit = 7, + ExtraActionType_enable = 8, + ExtraActionType_disable = 9, + ExtraActionType_notify = 10, + ExtraActionType_unknown = 11, +}; + +#endif // EXTRA_H diff --git a/LEGO1/gasstation.cpp b/LEGO1/gasstation.cpp index 33590dc9..eb178ef0 100644 --- a/LEGO1/gasstation.cpp +++ b/LEGO1/gasstation.cpp @@ -21,7 +21,7 @@ MxLong GasStation::Notify(MxParam &p) } // OFFSET: LEGO1 0x10005c90 STUB -MxLong GasStation::Tickle() +MxResult GasStation::Tickle() { // TODO diff --git a/LEGO1/gasstation.h b/LEGO1/gasstation.h index 7f2263d0..e88c028a 100644 --- a/LEGO1/gasstation.h +++ b/LEGO1/gasstation.h @@ -13,7 +13,7 @@ class GasStation : public LegoWorld virtual ~GasStation() override; // vtable+0x0 virtual MxLong Notify(MxParam &p) override; // vtable+0x4 - virtual MxLong Tickle() override; // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 // OFFSET: LEGO1 0x10004780 inline virtual const char *ClassName() const override // vtable+0x0c diff --git a/LEGO1/infocenter.cpp b/LEGO1/infocenter.cpp index b9ea67c6..eb7e65fc 100644 --- a/LEGO1/infocenter.cpp +++ b/LEGO1/infocenter.cpp @@ -21,7 +21,7 @@ MxLong Infocenter::Notify(MxParam &p) } // OFFSET: LEGO1 0x10070af0 STUB -MxLong Infocenter::Tickle() +MxResult Infocenter::Tickle() { // TODO diff --git a/LEGO1/infocenter.h b/LEGO1/infocenter.h index a6e06f0f..1d385993 100644 --- a/LEGO1/infocenter.h +++ b/LEGO1/infocenter.h @@ -12,7 +12,7 @@ class Infocenter : public LegoWorld virtual ~Infocenter() override; virtual MxLong Notify(MxParam &p) override; // vtable+0x4 - virtual MxLong Tickle() override; // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 // OFFSET: LEGO1 0x1006eb40 inline virtual const char *ClassName() const override // vtable+0x0c diff --git a/LEGO1/jetski.cpp b/LEGO1/jetski.cpp index 50676253..20993cf3 100644 --- a/LEGO1/jetski.cpp +++ b/LEGO1/jetski.cpp @@ -1,7 +1,11 @@ #include "jetski.h" -// OFFSET: LEGO1 0x1007e3b0 STUB +DECOMP_SIZE_ASSERT(Jetski, 0x164); + +// OFFSET: LEGO1 0x1007e3b0 Jetski::Jetski() { - // TODO + this->m_unk13c = 25.0; + this->m_unk150 = 2.0; + this->m_unk148 = 1; } \ No newline at end of file diff --git a/LEGO1/jetski.h b/LEGO1/jetski.h index 7cabea4d..d5de5a76 100644 --- a/LEGO1/jetski.h +++ b/LEGO1/jetski.h @@ -1,6 +1,7 @@ #ifndef JETSKI_H #define JETSKI_H +#include "decomp.h" #include "islepathactor.h" // VTABLE 0x100d9ec8 @@ -22,7 +23,9 @@ class Jetski : public IslePathActor { return !strcmp(name, Jetski::ClassName()) || IslePathActor::IsA(name); } - +private: + // TODO: Jetski fields + undefined m_unk160[4]; }; diff --git a/LEGO1/legoactor.cpp b/LEGO1/legoactor.cpp index c26cc1fc..7faa3b0d 100644 --- a/LEGO1/legoactor.cpp +++ b/LEGO1/legoactor.cpp @@ -1,3 +1,8 @@ #include "legoactor.h" DECOMP_SIZE_ASSERT(LegoActor, 0x78) + +// OFFSET: LEGO1 0x1002d110 STUB +LegoActor::LegoActor() +{ +} \ No newline at end of file diff --git a/LEGO1/legoactor.h b/LEGO1/legoactor.h index cc8778db..fe5e43a0 100644 --- a/LEGO1/legoactor.h +++ b/LEGO1/legoactor.h @@ -9,6 +9,8 @@ class LegoActor : public LegoEntity { public: + LegoActor(); + // OFFSET: LEGO1 0x1002d210 inline virtual const char *ClassName() const override // vtable+0x0c { diff --git a/LEGO1/legoanimationmanager.cpp b/LEGO1/legoanimationmanager.cpp index d396d431..20e0a0e3 100644 --- a/LEGO1/legoanimationmanager.cpp +++ b/LEGO1/legoanimationmanager.cpp @@ -23,7 +23,7 @@ MxLong LegoAnimationManager::Notify(MxParam &p) } // OFFSET: LEGO1 0x10061cc0 STUB -MxLong LegoAnimationManager::Tickle() +MxResult LegoAnimationManager::Tickle() { // TODO diff --git a/LEGO1/legoanimationmanager.h b/LEGO1/legoanimationmanager.h index 49b95f94..ec07603d 100644 --- a/LEGO1/legoanimationmanager.h +++ b/LEGO1/legoanimationmanager.h @@ -12,7 +12,7 @@ class LegoAnimationManager : public MxCore virtual ~LegoAnimationManager() override; // vtable+0x0 virtual MxLong Notify(MxParam &p) override; // vtable+0x4 - virtual MxLong Tickle() override; // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 // OFFSET: LEGO1 0x1005ec80 inline virtual const char *ClassName() const override // vtable+0x0c diff --git a/LEGO1/legobackgroundcolor.cpp b/LEGO1/legobackgroundcolor.cpp index e1d6beca..cc1483b3 100644 --- a/LEGO1/legobackgroundcolor.cpp +++ b/LEGO1/legobackgroundcolor.cpp @@ -3,6 +3,9 @@ #include "legoomni.h" #include "legoutil.h" #include "legovideomanager.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(LegoBackgroundColor, 0x30) const char *g_delimiter = "\t"; const char *g_set = "set"; diff --git a/LEGO1/legobackgroundcolor.h b/LEGO1/legobackgroundcolor.h index aff62fe8..884a477b 100644 --- a/LEGO1/legobackgroundcolor.h +++ b/LEGO1/legobackgroundcolor.h @@ -3,11 +3,13 @@ #include "mxvariable.h" +// VTABLE 0x100d74a8 +// SIZE 0x30 class LegoBackgroundColor : public MxVariable { public: __declspec(dllexport) LegoBackgroundColor(const char *p_key, const char *p_value); - void SetValue(const char *p_colorString); + virtual void SetValue(const char *p_colorString) override; private: float h; diff --git a/LEGO1/legocarbuild.cpp b/LEGO1/legocarbuild.cpp index c9254c37..e204529b 100644 --- a/LEGO1/legocarbuild.cpp +++ b/LEGO1/legocarbuild.cpp @@ -21,7 +21,7 @@ MxLong LegoCarBuild::Notify(MxParam &p) } // OFFSET: LEGO1 0x100238b0 STUB -MxLong LegoCarBuild::Tickle() +MxResult LegoCarBuild::Tickle() { // TODO diff --git a/LEGO1/legocarbuild.h b/LEGO1/legocarbuild.h index d320cd6e..1d68b0c1 100644 --- a/LEGO1/legocarbuild.h +++ b/LEGO1/legocarbuild.h @@ -12,7 +12,7 @@ class LegoCarBuild : public LegoWorld virtual ~LegoCarBuild() override; virtual MxLong Notify(MxParam &p) override; // vtable+0x4 - virtual MxLong Tickle() override; // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 // OFFSET: LEGO1 0x10022940 inline virtual const char *ClassName() const override // vtable+0x0c diff --git a/LEGO1/legocontrolmanager.cpp b/LEGO1/legocontrolmanager.cpp index 16733e13..91ff8c39 100644 --- a/LEGO1/legocontrolmanager.cpp +++ b/LEGO1/legocontrolmanager.cpp @@ -13,7 +13,7 @@ LegoControlManager::~LegoControlManager() } // OFFSET: LEGO1 0x10029600 STUB -MxLong LegoControlManager::Tickle() +MxResult LegoControlManager::Tickle() { // TODO diff --git a/LEGO1/legocontrolmanager.h b/LEGO1/legocontrolmanager.h index c4563776..0088ac0f 100644 --- a/LEGO1/legocontrolmanager.h +++ b/LEGO1/legocontrolmanager.h @@ -10,7 +10,7 @@ class LegoControlManager : public MxCore LegoControlManager(); virtual ~LegoControlManager() override; // vtable+0x0 - virtual MxLong Tickle() override; // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 // OFFSET: LEGO1 0x10028cb0 inline virtual const char *ClassName() const override // vtable+0x0c diff --git a/LEGO1/legoentity.cpp b/LEGO1/legoentity.cpp index b8ed69f9..e7601cc2 100644 --- a/LEGO1/legoentity.cpp +++ b/LEGO1/legoentity.cpp @@ -1,11 +1,15 @@ #include "legoentity.h" +#include "legoomni.h" +#include "legoutil.h" +#include "define.h" + DECOMP_SIZE_ASSERT(LegoEntity, 0x68) // OFFSET: LEGO1 0x1000c290 LegoEntity::~LegoEntity() { - Destroy(); + Destroy(TRUE); } // OFFSET: LEGO1 0x100114f0 STUB @@ -16,8 +20,58 @@ MxLong LegoEntity::Notify(MxParam &p) return 0; } -// OFFSET: LEGO1 0x10010810 STUB -void LegoEntity::Destroy() +// OFFSET: LEGO1 0x100105f0 +void LegoEntity::Reset() { - // TODO + m_vec1.Fill(0); + m_vec2.Fill(0); + m_unk50 = 0; + m_unk54 = 0; + m_unk58 = 0; + m_actionArgString = NULL; + m_unk10 = 0; + m_unk11 = 0; + m_actionType = ExtraActionType_unknown; + m_actionArgNumber = -1; + m_unk59 = 4; +} + +// OFFSET: LEGO1 0x100107e0 STUB +void LegoEntity::vtable18() +{ + +} + +// OFFSET: LEGO1 0x10010810 STUB +void LegoEntity::Destroy(MxBool) +{ + if (m_unk54) { + // TODO + } + + delete[] m_actionArgString; + Reset(); +} + +// OFFSET: LEGO1 0x10010e10 +void LegoEntity::ParseAction(char *p_extra) +{ + char copy[1024]; + char actionValue[1024]; + strcpy(copy, p_extra); + + if (KeyValueStringParse(actionValue, g_strACTION, copy)) { + m_actionType = MatchActionString(strtok(actionValue, g_parseExtraTokens)); + + if (m_actionType != ExtraActionType_exit) { + char *token = strtok(NULL, g_parseExtraTokens); + + m_actionArgString = new char[strlen(token) + 1]; + strcpy(m_actionArgString, token); + + if (m_actionType != ExtraActionType_run) { + m_actionArgNumber = atoi(strtok(NULL, g_parseExtraTokens)); + } + } + } } diff --git a/LEGO1/legoentity.h b/LEGO1/legoentity.h index fdfe997f..79acca27 100644 --- a/LEGO1/legoentity.h +++ b/LEGO1/legoentity.h @@ -2,6 +2,9 @@ #define LEGOENTITY_H #include "mxentity.h" +#include "mxvector.h" +#include "extra.h" +#include "decomp.h" // VTABLE 0x100d4858 // SIZE 0x68 (probably) @@ -31,7 +34,27 @@ class LegoEntity : public MxEntity return !strcmp(name, LegoEntity::ClassName()) || MxEntity::IsA(name); } - virtual void Destroy() override; // vtable+0x1c + virtual void vtable18(); // vtable+0x18 + virtual void Destroy(MxBool); // vtable+0x1c + virtual void ParseAction(char *); // vtable+0x20 + +protected: + void Reset(); + + undefined m_unk10; + undefined m_unk11; + MxVector3Data m_vec1; // 0x14 + MxVector3Data m_vec2; // 0x28 + MxVector3Data m_vec3; // 0x3c + undefined4 m_unk50; + undefined4 m_unk54; + undefined m_unk58; + undefined m_unk59; + // For tokens from the extra string that look like this: + // "Action:openram;\lego\scripts\Race\CarRaceR;0" + ExtraActionType m_actionType; // 0x5c + char *m_actionArgString; // 0x60 + MxS32 m_actionArgNumber; // 0x64 }; diff --git a/LEGO1/legofullscreenmovie.cpp b/LEGO1/legofullscreenmovie.cpp new file mode 100644 index 00000000..cb803133 --- /dev/null +++ b/LEGO1/legofullscreenmovie.cpp @@ -0,0 +1,43 @@ +#include "legofullscreenmovie.h" + +#include "legoomni.h" +#include "legovideomanager.h" +#include "mxtypes.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(LegoFullScreenMovie, 0x24) + +// 0x100f3be8 +const char *g_str_enable = "enable"; + +// 0x100f3bf4 +const char *g_str_disable = "disable"; + +// OFFSET: LEGO1 0x1003c500 +LegoFullScreenMovie::LegoFullScreenMovie(const char *p_key, const char *p_value) +{ + m_key = p_key; + m_key.ToUpperCase(); + SetValue(p_value); +} + +// OFFSET: LEGO1 0x1003c5c0 +void LegoFullScreenMovie::SetValue(const char *p_option) +{ + m_value = p_option; + m_value.ToLowerCase(); + + LegoVideoManager *videomanager = VideoManager(); + if (videomanager) { + + if (!strcmp(m_value.GetData(), g_str_enable)) { + videomanager->EnableFullScreenMovie(TRUE); + return; + } + + if (!strcmp(m_value.GetData(), g_str_disable)) { + videomanager->EnableFullScreenMovie(FALSE); + return; + } + } +} diff --git a/LEGO1/legofullscreenmovie.h b/LEGO1/legofullscreenmovie.h new file mode 100644 index 00000000..ffe350f5 --- /dev/null +++ b/LEGO1/legofullscreenmovie.h @@ -0,0 +1,15 @@ +#ifndef LEGOFULLSCREENMOVIE_H +#define LEGOFULLSCREENMOVIE_H + +#include "mxvariable.h" + +// VTABLE 0x100d74b8 +// SIZE 0x24 +class LegoFullScreenMovie : public MxVariable +{ +public: + LegoFullScreenMovie(const char *p_key, const char *p_value); + virtual void SetValue(const char *p_option) override; +}; + +#endif // LEGOFULLSCREENMOVIE_H diff --git a/LEGO1/legogamestate.cpp b/LEGO1/legogamestate.cpp index 344cf1ca..a08ce8e2 100644 --- a/LEGO1/legogamestate.cpp +++ b/LEGO1/legogamestate.cpp @@ -1,10 +1,28 @@ #include "legogamestate.h" + #include "legoomni.h" +#include "mxvariabletable.h" +#include "decomp.h" + +// Based on the highest dword offset (0x42c) referenced in the constructor. +// There may be other members that come after. +DECOMP_SIZE_ASSERT(LegoGameState, 0x430) // OFFSET: LEGO1 0x10039550 LegoGameState::LegoGameState() { // TODO + m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68"); + VariableTable()->SetVariable(m_backgroundColor); + + m_tempBackgroundColor = new LegoBackgroundColor("tempBackgroundcolor", "set 56 54 68"); + VariableTable()->SetVariable(m_tempBackgroundColor); + + m_fullScreenMovie = new LegoFullScreenMovie("fsmovie", "disable"); + VariableTable()->SetVariable(m_fullScreenMovie); + + VariableTable()->SetVariable("lightposition", "2"); + SerializeScoreHistory(1); } // OFFSET: LEGO1 0x10039720 diff --git a/LEGO1/legogamestate.h b/LEGO1/legogamestate.h index ef2eeb1e..b1cd8b60 100644 --- a/LEGO1/legogamestate.h +++ b/LEGO1/legogamestate.h @@ -1,8 +1,12 @@ #ifndef LEGOGAMESTATE_H #define LEGOGAMESTATE_H +#include "decomp.h" #include "mxtypes.h" +#include "legobackgroundcolor.h" +#include "legofullscreenmovie.h" +// SIZE 0x430 (at least) class LegoGameState { public: @@ -15,7 +19,12 @@ class LegoGameState __declspec(dllexport) void SetSavePath(char *p); private: - char *m_savePath; + char *m_savePath; // 0x0 + undefined m_unk04[20]; + LegoBackgroundColor *m_backgroundColor; // 0x18 + LegoBackgroundColor *m_tempBackgroundColor; // 0x1c + LegoFullScreenMovie *m_fullScreenMovie; // 0x20 + undefined m_unk24[1036]; }; #endif // LEGOGAMESTATE_H diff --git a/LEGO1/legoinputmanager.cpp b/LEGO1/legoinputmanager.cpp index 90be0c2c..3aaaec76 100644 --- a/LEGO1/legoinputmanager.cpp +++ b/LEGO1/legoinputmanager.cpp @@ -1,25 +1,175 @@ #include "legoinputmanager.h" +#include "legocontrolmanager.h" +#include "legoomni.h" -#include "decomp.h" +#include "mxautolocker.h" -DECOMP_SIZE_ASSERT(LegoInputManager, 0x338); // 0x10059085 +DECOMP_SIZE_ASSERT(LegoInputManager, 0x338); -// OFFSET: LEGO1 0x1005b790 STUB +// OFFSET: LEGO1 0x1005b790 LegoInputManager::LegoInputManager() { - // TODO + m_unk0x5c = NULL; + m_unk0x64 = 0; + m_unk0x60 = 0; + m_unk0x68 = NULL; + m_unk0x80 = 0; + m_timer = 0; + m_unk0x6c = 0; + m_unk0x70 = 0; + m_controlManager = NULL; + m_unk0x81 = 0; + m_unk0x88 = FALSE; + m_directInput = NULL; + m_directInputDevice = NULL; + m_unk0x94 = 0; + m_unk0x195 = 0; + m_joyid = -1; + m_joystickIndex = -1; + m_useJoystick = FALSE; + m_unk0x335 = FALSE; + m_unk0x336 = FALSE; + m_unk0x74 = 0x19; + m_timeout = 1000; } -// OFFSET: LEGO1 0x1005b8f0 STUB +// OFFSET: LEGO1 0x1005b8b0 STUB +MxResult LegoInputManager::Tickle() +{ + // TODO + return SUCCESS; +} + +// OFFSET: LEGO1 0x1005b8f0 LegoInputManager::~LegoInputManager() { - // TODO + Destroy(); } -// OFFSET: LEGO1 0x1005c740 STUB -void LegoInputManager::QueueEvent(NotificationId id, unsigned char p2, MxLong p3, MxLong p4, unsigned char p5) +// OFFSET: LEGO1 0x1005bfe0 +void LegoInputManager::Destroy() { - // TODO + ReleaseDX(); + + if (m_unk0x5c) + delete m_unk0x5c; + m_unk0x5c = NULL; + + if (m_unk0x68) + delete m_unk0x68; + m_unk0x68 = NULL; + + if (m_controlManager) + delete m_controlManager; +} + +// OFFSET: LEGO1 0x1005c030 +void LegoInputManager::CreateAndAcquireKeyboard(HWND hwnd) +{ + HINSTANCE hinstance = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE); + HRESULT hresult = DirectInputCreate(hinstance, 0x500, &m_directInput, NULL); // 0x500 for DX5 + + if (hresult == DI_OK) { + HRESULT createdeviceresult = m_directInput->CreateDevice(GUID_SysKeyboard, &m_directInputDevice, NULL); + if (createdeviceresult == DI_OK) { + m_directInputDevice->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); + m_directInputDevice->SetDataFormat(&c_dfDIKeyboard); + m_directInputDevice->Acquire(); + } + } +} + +// OFFSET: LEGO1 0x1005c0a0 +void LegoInputManager::ReleaseDX() +{ + if (m_directInputDevice != NULL) { + m_directInputDevice->Unacquire(); + m_directInputDevice->Release(); + m_directInputDevice = NULL; + } + + if (m_directInput != NULL) { + m_directInput->Release(); + m_directInput = NULL; + } +} + +// OFFSET: LEGO1 0x1005c240 +MxResult LegoInputManager::GetJoystickId() +{ + JOYINFOEX joyinfoex; + + if (m_useJoystick != FALSE) { + MxS32 joyid = m_joystickIndex; + if (joyid >= 0) { + joyinfoex.dwSize = 0x34; + joyinfoex.dwFlags = 0xFF; + + if (joyGetPosEx(joyid, &joyinfoex) == JOYERR_NOERROR && joyGetDevCaps(joyid, &m_joyCaps, 0x194) == JOYERR_NOERROR) { + m_joyid = joyid; + return SUCCESS; + } + } + + for (joyid = JOYSTICKID1; joyid < 16; joyid++) { + joyinfoex.dwSize = 0x34; + joyinfoex.dwFlags = 0xFF; + if (joyGetPosEx(joyid, &joyinfoex) == JOYERR_NOERROR && joyGetDevCaps(joyid, &m_joyCaps, 0x194) == JOYERR_NOERROR) { + m_joyid = joyid; + return SUCCESS; + } + } + } + + return FAILURE; +} + +// OFFSET: LEGO1 0x1005c320 +MxResult LegoInputManager::GetJoystickState(MxU32 *joystick_x, MxU32 *joystick_y, DWORD *buttons_state, MxU32 *pov_position) +{ + if (m_useJoystick != FALSE) { + if (m_joyid < 0 && GetJoystickId() == -1) { + m_useJoystick = FALSE; + return FAILURE; + } + + JOYINFOEX joyinfoex; + joyinfoex.dwSize = 0x34; + joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNBUTTONS; + MxU32 capabilities = m_joyCaps.wCaps; + + if ((capabilities & JOYCAPS_HASPOV) != 0) { + joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNPOV | JOY_RETURNBUTTONS; + + if ((capabilities & JOYCAPS_POVCTS) != 0) + joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNPOV | JOY_RETURNBUTTONS | JOY_RETURNPOVCTS; + } + + MMRESULT mmresult = joyGetPosEx(m_joyid, &joyinfoex); + + if (mmresult == MMSYSERR_NOERROR) { + *buttons_state = joyinfoex.dwButtons; + MxU32 xmin = m_joyCaps.wXmin; + MxU32 ymax = m_joyCaps.wYmax; + MxU32 ymin = m_joyCaps.wYmin; + MxS32 ydiff = ymax - ymin; + *joystick_x = ((joyinfoex.dwXpos - xmin) * 100) / (m_joyCaps.wXmax - xmin); + *joystick_y = ((joyinfoex.dwYpos - m_joyCaps.wYmin) * 100) / ydiff; + if ((m_joyCaps.wCaps & (JOYCAPS_POV4DIR | JOYCAPS_POVCTS)) != 0) { + if (joyinfoex.dwPOV == JOY_POVCENTERED) { + *pov_position = (MxU32) -1; + return SUCCESS; + } + *pov_position = joyinfoex.dwPOV / 100; + return SUCCESS; + } + else { + *pov_position = (MxU32) -1; + return SUCCESS; + } + } + } + return FAILURE; } // OFFSET: LEGO1 0x1005c470 STUB @@ -34,11 +184,25 @@ void LegoInputManager::UnRegister(MxCore *) // TODO } -// OFFSET: LEGO1 0x1005b8b0 STUB -MxLong LegoInputManager::Tickle() +// OFFSET: LEGO1 0x1005c740 STUB +void LegoInputManager::QueueEvent(NotificationId id, unsigned char p2, MxLong p3, MxLong p4, unsigned char p5) { // TODO - - return 0; } +// OFFSET: LEGO1 0x1005cfb0 +void LegoInputManager::SetTimer() +{ + LegoOmni* omni = LegoOmni::GetInstance(); + UINT timer = ::SetTimer(omni->GetWindowHandle(), 1, m_timeout, NULL); + m_timer = timer; +} + +// OFFSET: LEGO1 0x1005cfd0 +void LegoInputManager::KillTimer() +{ + if (m_timer != 0) { + LegoOmni* omni = LegoOmni::GetInstance(); + ::KillTimer(omni->GetWindowHandle(), m_timer); + } +} diff --git a/LEGO1/legoinputmanager.h b/LEGO1/legoinputmanager.h index 7ae2dd62..a44aef32 100644 --- a/LEGO1/legoinputmanager.h +++ b/LEGO1/legoinputmanager.h @@ -3,6 +3,9 @@ #include "decomp.h" #include "mxpresenter.h" +#include "mxlist.h" + +#include enum NotificationId { @@ -14,6 +17,8 @@ enum NotificationId TIMER = 15 }; +class LegoControlManager; + // VTABLE 0x100d8760 // SIZE 0x338 class LegoInputManager : public MxPresenter @@ -26,12 +31,44 @@ class LegoInputManager : public MxPresenter __declspec(dllexport) void Register(MxCore *); __declspec(dllexport) void UnRegister(MxCore *); - virtual MxLong Tickle() override; // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 - undefined m_pad40[0x15c]; - int m_joystickIndex; - undefined m_pad200[0x194]; + void Destroy(); + void CreateAndAcquireKeyboard(HWND hwnd); + void ReleaseDX(); + MxResult GetJoystickId(); + MxResult GetJoystickState(MxU32 *joystick_x, MxU32 *joystick_y, DWORD *buttons_state, MxU32 *pov_position); + void SetTimer(); + void KillTimer(); + +//private: + MxCriticalSection m_criticalSection; + MxList *m_unk0x5c; // list or hash table + undefined4 m_unk0x60; + undefined4 m_unk0x64; + MxList *m_unk0x68; // list or hash table + undefined4 m_unk0x6c; + undefined4 m_unk0x70; + undefined4 m_unk0x74; + UINT m_timer; + UINT m_timeout; + undefined m_unk0x80; + undefined m_unk0x81; + LegoControlManager* m_controlManager; + MxBool m_unk0x88; + IDirectInput *m_directInput; + IDirectInputDevice *m_directInputDevice; + undefined m_unk0x94; + undefined4 m_unk0x98; + undefined m_unk0x9c[0xF8]; + undefined m_unk0x194; + MxBool m_unk0x195; + MxS32 m_joyid; + MxS32 m_joystickIndex; + JOYCAPS m_joyCaps; MxBool m_useJoystick; + MxBool m_unk0x335; + MxBool m_unk0x336; }; #endif // LEGOINPUTMANAGER_H diff --git a/LEGO1/legonavcontroller.cpp b/LEGO1/legonavcontroller.cpp index 90c0a485..1f056f59 100644 --- a/LEGO1/legonavcontroller.cpp +++ b/LEGO1/legonavcontroller.cpp @@ -1,6 +1,7 @@ #include "legonavcontroller.h" #include "legoomni.h" +#include "legovideomanager.h" #include "legoutil.h" // 0x100f4c28 diff --git a/LEGO1/legoomni.cpp b/LEGO1/legoomni.cpp index b5cbca8e..33f88a58 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/legoomni.cpp @@ -1,7 +1,12 @@ #include "legoomni.h" +#include "mxbackgroundaudiomanager.h" +#include "mxdsfile.h" +#include "legogamestate.h" +#include "legoutil.h" + // 0x100f4588 -char *g_nocdSourceName = NULL; +MxAtomId *g_nocdSourceName = NULL; // 0x101020e8 void (*g_omniUserMessage)(const char *,int); @@ -37,10 +42,58 @@ int LegoOmni::GetCurrPathInfo(LegoPathBoundary **,int &) return 0; } -// OFFSET: LEGO1 0x100b6ff0 STUB -void MakeSourceName(char *, const char *) +// OFFSET: LEGO1 0x100b6ff0 +void MakeSourceName(char *p_output, const char *p_input) { - // TODO + const char *cln = strchr(p_input, ':'); + if (cln) { + p_input = cln + 1; + } + + strcpy(p_output, p_input); + + strlwr(p_output); + + char *extLoc = strstr(p_output, ".si"); + if (extLoc) { + *extLoc = 0; + } +} + +// OFFSET: LEGO1 0x100b7050 +MxBool KeyValueStringParse(char *p_outputValue, const char *p_key, const char *p_source) +{ + MxBool didMatch = FALSE; + + MxS16 len = strlen(p_source); + char *temp = new char[len + 1]; + strcpy(temp, p_source); + + char *token = strtok(temp, ", \t\r\n:"); + while (token) { + len -= (strlen(token) + 1); + + if (strcmpi(token, p_key) == 0) { + if (p_outputValue && len > 0) { + char *cur = &token[strlen(p_key)]; + cur++; + while (*cur != ',') { + if (*cur == ' ' || *cur == '\0' || *cur == '\t' || *cur == '\n' || *cur == '\r') + break; + *p_outputValue++ = *cur++; + } + *p_outputValue = '\0'; + } + + didMatch = TRUE; + break; + } + + token = strtok(NULL, ", \t\r\n:"); + } + + delete[] temp; + return didMatch; } // OFFSET: LEGO1 0x100b7210 @@ -49,11 +102,10 @@ void SetOmniUserMessage(void (*p_userMsg)(const char *,int)) g_omniUserMessage = p_userMsg; } -// OFFSET: LEGO1 0x100acf50 STUB -MxLong Start(MxDSAction *) +// OFFSET: LEGO1 0x100acf50 +MxResult Start(MxDSAction* p_dsAction) { - // TODO - return 0; + return MxOmni::GetInstance()->Start(p_dsAction); } // OFFSET: LEGO1 0x1005ad10 @@ -111,10 +163,38 @@ MxBackgroundAudioManager *BackgroundAudioManager() return LegoOmni::GetInstance()->GetBackgroundAudioManager(); } -// OFFSET: LEGO1 0x100c0280 STUB -MxDSObject *CreateStreamObject(MxDSFile *,MxS16) +// OFFSET: LEGO1 0x100c0280 +MxDSObject *CreateStreamObject(MxDSFile *p_file, MxS16 p_ofs) { - // TODO + char *buf; + _MMCKINFO tmp_chunk; + + if (p_file->Seek(((MxLong*)p_file->GetBuffer())[p_ofs], 0)) { + return NULL; + } + + if (p_file->Read((MxU8*)&tmp_chunk.ckid, 8) == 0 && tmp_chunk.ckid == FOURCC('M', 'x', 'S', 't')) { + if (p_file->Read((MxU8*)&tmp_chunk.ckid, 8) == 0 && tmp_chunk.ckid == FOURCC('M', 'x', 'O', 'b')) { + + buf = new char[tmp_chunk.cksize]; + if (!buf) { + return NULL; + } + + if (p_file->Read((MxU8*)buf, tmp_chunk.cksize) != 0) { + return NULL; + } + + // Save a copy so we can clean up properly, because + // this function will alter the pointer value. + char *copy = buf; + MxDSObject *obj = DeserializeDSObjectDispatch(&buf, -1); + delete[] copy; + return obj; + } + return NULL; + } + return NULL; } @@ -145,7 +225,7 @@ MxTransitionManager *TransitionManager() // OFFSET: LEGO1 0x10053430 const char *GetNoCD_SourceName() { - return g_nocdSourceName; + return g_nocdSourceName->GetInternal(); } // OFFSET: LEGO1 0x1005b5f0 @@ -172,64 +252,95 @@ LegoEntity *PickEntity(MxLong,MxLong) // OFFSET: LEGO1 0x10058bd0 void LegoOmni::Init() { - // FIXME: Stub + MxOmni::Init(); + m_unk68 = 0; + m_inputMgr = NULL; + m_unk6c = 0; + m_unk74 = 0; + m_unk78 = 0; + m_currentWorld = NULL; + m_unk80 = FALSE; + m_isle = NULL; + m_unk8c = 0; + m_plantManager = NULL; + m_gameState = NULL; + m_animationManager = NULL; + m_buildingManager = NULL; + m_bkgAudioManager = NULL; + m_unk13c = TRUE; + m_transitionManager = NULL; } // OFFSET: LEGO1 0x10058e70 MxResult LegoOmni::Create(COMPAT_CONST MxOmniCreateParam &p) { // FIXME: Stub + MxOmni::Create(p); + m_gameState = new LegoGameState(); + m_bkgAudioManager = new MxBackgroundAudioManager(); + return SUCCESS; } +// OFFSET: LEGO1 0x10058c30 STUB void LegoOmni::Destroy() { // FIXME: Stub } -void LegoOmni::vtable20() +// OFFSET: LEGO1 0x1005b580 +MxResult LegoOmni::Start(MxDSAction* action) +{ + MxResult result = MxOmni::Start(action); + this->m_action.SetAtomId(action->GetAtomId()); + this->m_action.SetObjectId(action->GetObjectId()); + this->m_action.SetUnknown24(action->GetUnknown24()); + return result; +} + +void LegoOmni::DeleteObject(MxDSAction &ds) { // FIXME: Stub } -void LegoOmni::vtable24(MxDSAction &ds) -{ - // FIXME: Stub -} - -MxBool LegoOmni::vtable28(MxDSAction &ds) +MxBool LegoOmni::DoesEntityExist(MxDSAction &ds) { // FIXME: Stub return TRUE; } -void LegoOmni::vtable2c() +void LegoOmni::vtable0x2c() { // FIXME: Stub } -void LegoOmni::vtable30() -{ - // FIXME: Stub -} - -void LegoOmni::vtable34() -{ - // FIXME: Stub -} - -void LegoOmni::vtable38() -{ - // FIXME: Stub -} - -void LegoOmni::vtable3c() -{ - // FIXME: Stub -} - -unsigned char LegoOmni::vtable40() +int LegoOmni::vtable0x30(char*, int, MxCore*) { // FIXME: Stub return 0; } + +void LegoOmni::NotifyCurrentEntity() +{ + // FIXME: Stub +} + +// OFFSET: LEGO1 0x1005b640 +void LegoOmni::StartTimer() +{ + MxOmni::StartTimer(); + SetAppCursor(2); +} + +// OFFSET: LEGO1 0x1005b650 +void LegoOmni::StopTimer() +{ + MxOmni::StopTimer(); + SetAppCursor(0); +} + +// OFFSET: LEGO1 0x100157a0 +LegoWorld *GetCurrentWorld() +{ + return LegoOmni::GetInstance()->GetCurrentWorld(); +} diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index 0ba27cf2..e4074463 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -2,25 +2,26 @@ #define LEGOOMNI_H #include "compat.h" -#include "legoentity.h" -#include "legoinputmanager.h" -#include "legogamestate.h" -#include "legonavcontroller.h" -#include "legopathboundary.h" -#include "legoroi.h" -#include "legovideomanager.h" -#include "mxatomid.h" -#include "mxbackgroundaudiomanager.h" -#include "mxdsaction.h" -#include "mxdsfile.h" -#include "mxdsobject.h" #include "mxomni.h" -#include "mxtransitionmanager.h" -#include "isle.h" -#include "legobuildingmanager.h" -#include "legoplantmanager.h" +#include "mxdsaction.h" +class Isle; +class LegoAnimationManager; +class LegoBuildingManager; +class LegoEntity; +class LegoGameState; +class LegoInputManager; +class LegoNavController; +class LegoPathBoundary; +class LegoPlantManager; +class LegoROI; class LegoSoundManager; +class LegoVideoManager; +class LegoWorld; +class MxAtomId; +class MxBackgroundAudioManager; +class MxDSFile; +class MxTransitionManager; // VTABLE 0x100d8638 // SIZE: 0x140 @@ -36,33 +37,32 @@ class LegoOmni : public MxOmni LegoOmni(); virtual ~LegoOmni(); // vtable+00 - virtual MxLong Notify(MxParam &p); // vtable+04 + virtual MxLong Notify(MxParam &p) override; // vtable+04 // OFFSET: LEGO1 0x10058aa0 - inline virtual const char *ClassName() const // vtable+0c + inline virtual const char *ClassName() const override // vtable+0c { // 0x100f671c return "LegoOmni"; } // OFFSET: LEGO1 0x10058ab0 - inline virtual MxBool IsA(const char *name) const // vtable+10 + inline virtual MxBool IsA(const char *name) const override // vtable+10 { return !strcmp(name, LegoOmni::ClassName()) || MxOmni::IsA(name); } - virtual void Init(); // vtable+14 - virtual MxResult Create(COMPAT_CONST MxOmniCreateParam &p); // vtable+18 - virtual void Destroy(); // vtable+1c - virtual void vtable20(); - virtual void vtable24(MxDSAction &ds); - virtual MxBool vtable28(MxDSAction &ds); - virtual void vtable2c(); - virtual void vtable30(); - virtual void vtable34(); - virtual void vtable38(); - virtual void vtable3c(); - virtual unsigned char vtable40(); + virtual void Init() override; // vtable+14 + virtual MxResult Create(COMPAT_CONST MxOmniCreateParam &p) override; // vtable+18 + virtual void Destroy() override; // vtable+1c + virtual MxResult Start(MxDSAction* action) override; + virtual void DeleteObject(MxDSAction &ds) override; + virtual MxBool DoesEntityExist(MxDSAction &ds) override; + virtual void vtable0x2c() override; + virtual int vtable0x30(char*, int, MxCore*) override; + virtual void NotifyCurrentEntity() override; + virtual void StartTimer() override; + virtual void StopTimer() override; LegoVideoManager *GetVideoManager() { return (LegoVideoManager *) m_videoManager; } LegoSoundManager *GetSoundManager() { return (LegoSoundManager *)m_soundManager;} @@ -74,24 +74,27 @@ class LegoOmni : public MxOmni LegoGameState *GetGameState() { return m_gameState; } LegoNavController *GetNavController() { return m_navController; } MxTransitionManager *GetTransitionManager() { return m_transitionManager; } + LegoWorld *GetCurrentWorld() { return m_currentWorld; } private: int m_unk68; int m_unk6c; LegoInputManager *m_inputMgr; // 0x70 - char m_unk74[0x10]; + undefined4 m_unk74; + undefined4 m_unk78; + LegoWorld *m_currentWorld; + MxBool m_unk80; LegoNavController *m_navController; // 0x84 Isle* m_isle; // 0x88 - char m_unk8c[0x4]; + undefined4 m_unk8c; LegoPlantManager* m_plantManager; // 0x90 - char m_unk94[0x4]; + LegoAnimationManager* m_animationManager; LegoBuildingManager* m_buildingManager; // 0x98 LegoGameState *m_gameState; // 0x9c MxDSAction m_action; MxBackgroundAudioManager *m_bkgAudioManager; // 0x134 MxTransitionManager *m_transitionManager; // 0x138 - int m_unk13c; - + MxBool m_unk13c; }; __declspec(dllexport) MxBackgroundAudioManager * BackgroundAudioManager(); @@ -105,13 +108,14 @@ __declspec(dllexport) LegoEntity * PickEntity(MxLong,MxLong); __declspec(dllexport) LegoROI * PickROI(MxLong,MxLong); __declspec(dllexport) void SetOmniUserMessage(void (*)(const char *,int)); __declspec(dllexport) LegoSoundManager * SoundManager(); -__declspec(dllexport) MxLong Start(MxDSAction *); +__declspec(dllexport) MxResult Start(MxDSAction*); __declspec(dllexport) MxTransitionManager * TransitionManager(); __declspec(dllexport) LegoVideoManager * VideoManager(); -__declspec(dllexport) MxLong Start(MxDSAction *a); LegoBuildingManager* BuildingManager(); Isle* GetIsle(); LegoPlantManager* PlantManager(); +MxBool KeyValueStringParse(char *, const char *, const char *); +LegoWorld *GetCurrentWorld(); #endif // LEGOOMNI_H diff --git a/LEGO1/legopalettepresenter.cpp b/LEGO1/legopalettepresenter.cpp index 07b9cb99..575ada4a 100644 --- a/LEGO1/legopalettepresenter.cpp +++ b/LEGO1/legopalettepresenter.cpp @@ -1,5 +1,7 @@ #include "legopalettepresenter.h" +DECOMP_SIZE_ASSERT(LegoPalettePresenter, 0x68) + // OFFSET: LEGO1 0x10079e50 LegoPalettePresenter::LegoPalettePresenter() { @@ -12,8 +14,8 @@ LegoPalettePresenter::~LegoPalettePresenter() // TODO } -// OFFSET: LEGO1 0x1007a0d0 STUB +// OFFSET: LEGO1 0x1007a0d0 void LegoPalettePresenter::Init() { - // TODO + this->m_unk64 = 0; } diff --git a/LEGO1/legopalettepresenter.h b/LEGO1/legopalettepresenter.h index d5fbefba..4cdda5ab 100644 --- a/LEGO1/legopalettepresenter.h +++ b/LEGO1/legopalettepresenter.h @@ -1,6 +1,7 @@ #ifndef LEGOPALETTEPRESENTER_H #define LEGOPALETTEPRESENTER_H +#include "decomp.h" #include "mxvideopresenter.h" // VTABLE 0x100d9aa0 @@ -27,6 +28,7 @@ class LegoPalettePresenter : public MxVideoPresenter private: void Init(); + undefined4 m_unk64; }; diff --git a/LEGO1/legopathactor.h b/LEGO1/legopathactor.h index 7e524b08..41c6d843 100644 --- a/LEGO1/legopathactor.h +++ b/LEGO1/legopathactor.h @@ -25,11 +25,15 @@ class LegoPathActor : public LegoActor { return !strcmp(name, LegoPathActor::ClassName()) || LegoActor::IsA(name); } - - // TODO: the types. Pizza needs this as public: +protected: + // TODO: the types undefined unk78[0xc4]; - MxS32 m_unk13c; - undefined unk140[0x14]; + MxFloat m_unk13c; + MxS32 m_unk140; + MxS32 m_unk144; + undefined m_unk148; + MxS32 m_unk14c; + MxFloat m_unk150; }; #endif // LEGOPATHACTOR_H diff --git a/LEGO1/legopathcontroller.cpp b/LEGO1/legopathcontroller.cpp index 0cebbc0f..f8b64109 100644 --- a/LEGO1/legopathcontroller.cpp +++ b/LEGO1/legopathcontroller.cpp @@ -13,7 +13,7 @@ LegoPathController::~LegoPathController() } // OFFSET: LEGO1 0x10045c10 STUB -MxLong LegoPathController::Tickle() +MxResult LegoPathController::Tickle() { // TODO return 0; diff --git a/LEGO1/legopathcontroller.h b/LEGO1/legopathcontroller.h index ba415076..61dbdcfe 100644 --- a/LEGO1/legopathcontroller.h +++ b/LEGO1/legopathcontroller.h @@ -11,7 +11,7 @@ class LegoPathController : public MxCore LegoPathController(); virtual ~LegoPathController() override; - virtual MxLong Tickle() override; // vtable+08 + virtual MxResult Tickle() override; // vtable+08 // OFFSET: LEGO1 0x10045110 inline const char *ClassName() const override // vtable+0xc diff --git a/LEGO1/legoplantmanager.cpp b/LEGO1/legoplantmanager.cpp index eee83726..515d330d 100644 --- a/LEGO1/legoplantmanager.cpp +++ b/LEGO1/legoplantmanager.cpp @@ -13,7 +13,7 @@ LegoPlantManager::~LegoPlantManager() } // OFFSET: LEGO1 0x10026e00 STUB -MxLong LegoPlantManager::Tickle() +MxResult LegoPlantManager::Tickle() { // TODO diff --git a/LEGO1/legoplantmanager.h b/LEGO1/legoplantmanager.h index 3e8bfefe..b8e8dd9d 100644 --- a/LEGO1/legoplantmanager.h +++ b/LEGO1/legoplantmanager.h @@ -11,7 +11,7 @@ class LegoPlantManager : public MxCore LegoPlantManager(); virtual ~LegoPlantManager() override; // vtable+0x0 - virtual MxLong Tickle() override; // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 // OFFSET: LEGO1 0x10026290 inline const char *ClassName() const override // vtable+0xc diff --git a/LEGO1/legosoundmanager.cpp b/LEGO1/legosoundmanager.cpp index e56747f6..01f8fee5 100644 --- a/LEGO1/legosoundmanager.cpp +++ b/LEGO1/legosoundmanager.cpp @@ -13,7 +13,7 @@ LegoSoundManager::~LegoSoundManager() } // OFFSET: LEGO1 0x1002a3a0 STUB -MxLong LegoSoundManager::Tickle() +MxResult LegoSoundManager::Tickle() { // TODO return 0; diff --git a/LEGO1/legosoundmanager.h b/LEGO1/legosoundmanager.h index 1d191e03..90e23fba 100644 --- a/LEGO1/legosoundmanager.h +++ b/LEGO1/legosoundmanager.h @@ -10,7 +10,7 @@ class LegoSoundManager : public MxSoundManager public: LegoSoundManager(); virtual ~LegoSoundManager() override; - virtual MxLong Tickle() override; // vtable+08 + virtual MxResult Tickle() override; // vtable+08 private: void Init(); diff --git a/LEGO1/legoutil.cpp b/LEGO1/legoutil.cpp index bac8f284..cd46c902 100644 --- a/LEGO1/legoutil.cpp +++ b/LEGO1/legoutil.cpp @@ -1,7 +1,38 @@ #include "legoutil.h" +#include "mxomni.h" #include "mxtypes.h" +#include + +// OFFSET: LEGO1 0x1003e300 +ExtraActionType MatchActionString(const char *p_str) { + ExtraActionType result = ExtraActionType_unknown; + + if (!strcmpi("openram", p_str)) + result = ExtraActionType_openram; + else if (!strcmpi("opendisk", p_str)) + result = ExtraActionType_opendisk; + else if (!strcmpi("close", p_str)) + result = ExtraActionType_close; + else if (!strcmpi("start", p_str)) + result = ExtraActionType_start; + else if (!strcmpi("stop", p_str)) + result = ExtraActionType_stop; + else if (!strcmpi("run", p_str)) + result = ExtraActionType_run; + else if (!strcmpi("exit", p_str)) + result = ExtraActionType_exit; + else if (!strcmpi("enable", p_str)) + result = ExtraActionType_enable; + else if (!strcmpi("disable", p_str)) + result = ExtraActionType_disable; + else if (!strcmpi("notify", p_str)) + result = ExtraActionType_notify; + + return result; +} + // OFFSET: LEGO1 0x1003eae0 void ConvertHSVToRGB(float h, float s, float v, float *r_out, float *b_out, float *g_out) { @@ -71,3 +102,9 @@ void ConvertHSVToRGB(float h, float s, float v, float *r_out, float *b_out, floa return; } } + +// OFFSET: LEGO1 0x1003ef40 +void SetAppCursor(WPARAM p_wparam) +{ + PostMessageA(MxOmni::GetInstance()->GetWindowHandle(), 0x5400, p_wparam, 0); +} diff --git a/LEGO1/legoutil.h b/LEGO1/legoutil.h index 6a0113e8..cc54da74 100644 --- a/LEGO1/legoutil.h +++ b/LEGO1/legoutil.h @@ -1,6 +1,10 @@ #ifndef LEGOUTIL_H #define LEGOUTIL_H +#include + +#include "extra.h" + template inline T Abs(T p_t) { @@ -19,6 +23,37 @@ inline T Max(T p_t1, T p_t2) return p_t1 > p_t2 ? p_t1 : p_t2; } +template +inline void GetScalar(char **p_source, T& p_dest) +{ + p_dest = *(T*) *p_source; + *p_source += sizeof(T); +} + +template +inline T GetScalar(T **p_source) +{ + T val = **p_source; + *p_source += 1; + return val; +} + +template +inline void GetDouble(char **p_source, T& p_dest) +{ + p_dest = *(double*) *p_source; + *p_source += sizeof(double); +} + +template +inline void GetString(char **p_source, const char *&p_dest, T *p_obj, void (T::*p_setter)(const char*)) +{ + (p_obj->*p_setter)(*p_source); + *p_source += strlen(p_dest) + 1; +} + +ExtraActionType MatchActionString(const char *); void ConvertHSVToRGB(float r, float g, float b, float* out_r, float* out_g, float* out_b); +void SetAppCursor(WPARAM p_wparam); #endif // LEGOUTIL_H diff --git a/LEGO1/legovideomanager.cpp b/LEGO1/legovideomanager.cpp index 9c1044e2..ca7926b9 100644 --- a/LEGO1/legovideomanager.cpp +++ b/LEGO1/legovideomanager.cpp @@ -1,5 +1,6 @@ #include "legovideomanager.h" -#include + +DECOMP_SIZE_ASSERT(LegoVideoManager, 0x590); // OFFSET: LEGO1 0x1007aa20 STUB LegoVideoManager::LegoVideoManager() @@ -27,26 +28,44 @@ int LegoVideoManager::DisableRMDevice() return 0; } +// OFFSET: LEGO1 0x1007c300 +void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable) +{ + EnableFullScreenMovie(p_enable, TRUE); +} + // OFFSET: LEGO1 0x1007c310 STUB -void LegoVideoManager::EnableFullScreenMovie(unsigned char a, unsigned char b) +void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) { // TODO } -// OFFSET: LEGO1 0x1007b6a0 STUB -void LegoVideoManager::MoveCursor(int x, int y) +// OFFSET: LEGO1 0x1007b6a0 +void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) { - // TODO + m_cursorX = p_cursorX; + m_cursorY = p_cursorY; + m_cursorMoved = TRUE; + + if (623 < p_cursorX) + m_cursorX = 623; + + if (463 < p_cursorY) + m_cursorY = 463; } // OFFSET: LEGO1 0x1007c440 -void LegoVideoManager::SetSkyColor(float red, float green, float blue) +void LegoVideoManager::SetSkyColor(float p_red, float p_green, float p_blue) { - PALETTEENTRY colorStrucure; // [esp+0h] [ebp-4h] BYREF + PALETTEENTRY colorStrucure; - colorStrucure.peRed = (red* 255.0); - colorStrucure.peGreen = (green * 255.0); - colorStrucure.peBlue = (blue * 255.0); + colorStrucure.peRed = (p_red * 255.0f); + colorStrucure.peGreen = (p_green * 255.0f); + colorStrucure.peBlue = (p_blue * 255.0f); colorStrucure.peFlags = -124; - // TODO + m_videoParam.GetPalette()->SetSkyColor(&colorStrucure); + m_videoParam.GetPalette()->SetOverrideSkyColor(TRUE); + + // TODO 3d manager + //m_3dManager->m_pViewport->vtable1c(red, green, blue) } diff --git a/LEGO1/legovideomanager.h b/LEGO1/legovideomanager.h index 60f670fb..cc051f16 100644 --- a/LEGO1/legovideomanager.h +++ b/LEGO1/legovideomanager.h @@ -6,6 +6,8 @@ #include "lego3dmanager.h" #include "decomp.h" +#include + // VTABLE 0x100d9c88 // SIZE 0x590 class LegoVideoManager : public MxVideoManager @@ -16,13 +18,18 @@ class LegoVideoManager : public MxVideoManager __declspec(dllexport) int EnableRMDevice(); __declspec(dllexport) int DisableRMDevice(); - __declspec(dllexport) void EnableFullScreenMovie(unsigned char a, unsigned char b); + void EnableFullScreenMovie(MxBool p_enable); + __declspec(dllexport) void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale); __declspec(dllexport) void MoveCursor(int x, int y); inline Lego3DManager *Get3DManager() { return this->m_3dManager; } inline MxDirect3D *GetDirect3D() { return this->m_direct3d; } void SetSkyColor(float r, float g, float b); + inline void SetUnkE4(MxBool p_unk0xe4) { this->m_unk0xe4 = p_unk0xe4; } + + // OFFSET: LEGO1 0x1007c4c0 + void OverrideSkyColor(MxBool p_shouldOverride) { this->m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride);} private: undefined4 m_unk64; @@ -30,6 +37,14 @@ class LegoVideoManager : public MxVideoManager undefined4 m_unk6c; undefined4 m_unk70; MxDirect3D *m_direct3d; + undefined m_pad0x78[0x6c]; + MxBool m_unk0xe4; + undefined m_pad0xe8[0x41c]; + MxBool m_cursorMoved; // 0x501 + undefined m_pad0x502[0x8]; + MxS32 m_cursorX; // 0x50c + MxS32 m_cursorY; // 0x510 + undefined m_pad0x514[0x7c]; }; #endif // LEGOVIDEOMANAGER_H diff --git a/LEGO1/motorcycle.cpp b/LEGO1/motorcycle.cpp index 9b0e0e40..59188fc4 100644 --- a/LEGO1/motorcycle.cpp +++ b/LEGO1/motorcycle.cpp @@ -1,7 +1,12 @@ #include "motorcycle.h" -// OFFSET: LEGO1 0x100357b0 STUB +DECOMP_SIZE_ASSERT(Motorcycle, 0x16c); + +// OFFSET: LEGO1 0x100357b0 Motorcycle::Motorcycle() { - // TODO + this->m_unk13c = 40.0; + this->m_unk150 = 1.75; + this->m_unk148 = 1; + this->m_unk164 = 1.0; } diff --git a/LEGO1/motorcycle.h b/LEGO1/motorcycle.h index 5ba746a8..ee39fe24 100644 --- a/LEGO1/motorcycle.h +++ b/LEGO1/motorcycle.h @@ -1,6 +1,7 @@ #ifndef MOTORCYCLE_H #define MOTORCYCLE_H +#include "decomp.h" #include "islepathactor.h" // VTABLE 0x100d7090 @@ -22,7 +23,10 @@ class Motorcycle : public IslePathActor { return !strcmp(name, Motorcycle::ClassName()) || IslePathActor::IsA(name); } - +private: + undefined m_unk160[4]; + MxFloat m_unk164; + undefined m_unk168[4]; }; #endif // MOTORCYCLE_H diff --git a/LEGO1/mxactionnotificationparam.cpp b/LEGO1/mxactionnotificationparam.cpp new file mode 100644 index 00000000..33395c4d --- /dev/null +++ b/LEGO1/mxactionnotificationparam.cpp @@ -0,0 +1,16 @@ +#include "mxactionnotificationparam.h" + +DECOMP_SIZE_ASSERT(MxActionNotificationParam, 0x14) +DECOMP_SIZE_ASSERT(MxEndActionNotificationParam, 0x14) + +// OFFSET: LEGO1 0x100510c0 +MxNotificationParam *MxActionNotificationParam::Clone() +{ + return new MxActionNotificationParam(this->m_type, this->m_sender, this->m_action, this->m_realloc); +} + +// OFFSET: LEGO1 0x10051270 +MxNotificationParam *MxEndActionNotificationParam::Clone() +{ + return new MxEndActionNotificationParam(MXSTREAMER_UNKNOWN, this->m_sender, this->m_action, this->m_realloc); +} diff --git a/LEGO1/mxactionnotificationparam.h b/LEGO1/mxactionnotificationparam.h new file mode 100644 index 00000000..4229e252 --- /dev/null +++ b/LEGO1/mxactionnotificationparam.h @@ -0,0 +1,59 @@ +#ifndef MXACTIONNOTIFICATIONPARAM_H +#define MXACTIONNOTIFICATIONPARAM_H + +#include "mxnotificationparam.h" +#include "mxdsaction.h" + +// VTABLE 0x100d8350 +// SIZE 0x14 +class MxActionNotificationParam : public MxNotificationParam +{ +public: + inline MxActionNotificationParam(MxParamType p_type, MxCore *p_sender, MxDSAction *p_action, MxBool p_reallocAction) : MxNotificationParam(p_type, p_sender) + { + MxDSAction *oldAction = p_action; + this->m_realloc = p_reallocAction; + + if (p_reallocAction) + this->m_action = new MxDSAction(); + else { + this->m_action = oldAction; + return; + } + + this->m_action->SetAtomId(oldAction->GetAtomId()); + this->m_action->SetObjectId(oldAction->GetObjectId()); + this->m_action->SetUnknown24(oldAction->GetUnknown24()); + } + + // OFFSET: LEGO1 0x10051050 + inline virtual MxActionNotificationParam::~MxActionNotificationParam() override + { + if (!this->m_realloc) + return; + + if (this->m_action) + delete this->m_action; + } + + virtual MxNotificationParam *Clone() override; // vtable+0x4 + +protected: + MxDSAction *m_action; // 0xc + MxBool m_realloc; // 0x10 +}; + +// VTABLE 0x100d8358 +// SIZE 0x14 +class MxEndActionNotificationParam : public MxActionNotificationParam +{ +public: + inline MxEndActionNotificationParam(MxParamType p_type, MxCore *p_sender, MxDSAction *p_action, MxBool p_reallocAction) + : MxActionNotificationParam(p_type, p_sender, p_action, p_reallocAction) {} + + inline virtual ~MxEndActionNotificationParam() override {}; // 0x100513a0 + + virtual MxNotificationParam *Clone() override; // vtable+0x4 +}; + +#endif \ No newline at end of file diff --git a/LEGO1/mxatomid.h b/LEGO1/mxatomid.h index 8efef679..7c89f35f 100644 --- a/LEGO1/mxatomid.h +++ b/LEGO1/mxatomid.h @@ -28,8 +28,11 @@ class MxAtomId { return this->m_internal == other.m_internal; } + void Clear(); + const char *GetInternal() const { return m_internal; } + private: MxAtomIdCounter* GetCounter(const char *, LookupMode); void Destroy(); diff --git a/LEGO1/mxaudiomanager.cpp b/LEGO1/mxaudiomanager.cpp new file mode 100644 index 00000000..bb358e47 --- /dev/null +++ b/LEGO1/mxaudiomanager.cpp @@ -0,0 +1,78 @@ +#include "mxaudiomanager.h" + +DECOMP_SIZE_ASSERT(MxAudioManager, 0x30); + +// GLOBAL: LEGO1 0x10102108 +MxS32 MxAudioManager::g_unkCount = 0; + +// OFFSET: LEGO1 0x100b8d00 +MxAudioManager::MxAudioManager() +{ + Init(); +} + +// OFFSET: LEGO1 0x100b8d90 +MxAudioManager::~MxAudioManager() +{ + LockedReinitialize(TRUE); +} + +// OFFSET: LEGO1 0x100b8df0 +void MxAudioManager::Init() +{ + this->m_volume = 100; +} + +// OFFSET: LEGO1 0x10029910 +MxS32 MxAudioManager::GetVolume() +{ + return this->m_volume; +} + +// OFFSET: LEGO1 0x100b8ea0 +void MxAudioManager::SetVolume(MxS32 p_volume) +{ + this->m_criticalSection.Enter(); + this->m_volume = p_volume; + this->m_criticalSection.Leave(); +} + +// OFFSET: LEGO1 0x100b8e00 +void MxAudioManager::LockedReinitialize(MxBool p_skipDestroy) +{ + this->m_criticalSection.Enter(); + g_unkCount--; + Init(); + this->m_criticalSection.Leave(); + + if (!p_skipDestroy) + MxMediaManager::Destroy(); +} + +// OFFSET: LEGO1 0x100b8e40 +MxResult MxAudioManager::InitPresenters() +{ + MxResult result = FAILURE; + MxBool success = FALSE; + + if (MxMediaManager::InitPresenters() == SUCCESS) { + this->m_criticalSection.Enter(); + success = TRUE; + result = SUCCESS; + g_unkCount++; + } + + if (result) + Destroy(); + + if (success) + this->m_criticalSection.Leave(); + + return result; +} + +// OFFSET: LEGO1 0x100b8e90 +void MxAudioManager::Destroy() +{ + LockedReinitialize(FALSE); +} \ No newline at end of file diff --git a/LEGO1/mxaudiomanager.h b/LEGO1/mxaudiomanager.h new file mode 100644 index 00000000..1ba5b6fd --- /dev/null +++ b/LEGO1/mxaudiomanager.h @@ -0,0 +1,30 @@ +#ifndef MXAUDIOMANAGER_H +#define MXAUDIOMANAGER_H + +#include "decomp.h" +#include "mxmediamanager.h" + +// VTABLE 0x100dc6e0 +class MxAudioManager : public MxMediaManager +{ +public: + MxAudioManager(); + virtual ~MxAudioManager() override; + + virtual MxResult InitPresenters() override; // vtable+14 + virtual void Destroy() override; // vtable+18 + virtual MxS32 GetVolume(); // vtable+28 + virtual void SetVolume(MxS32 p_volume); // vtable+2c + +private: + void LockedReinitialize(MxBool p_skipDestroy); + + static MxS32 g_unkCount; + +protected: + void Init(); + + MxS32 m_volume; // 0x2c +}; + +#endif // MXAUDIOMANAGER_H diff --git a/LEGO1/mxaudiopresenter.cpp b/LEGO1/mxaudiopresenter.cpp index ac634362..48a02377 100644 --- a/LEGO1/mxaudiopresenter.cpp +++ b/LEGO1/mxaudiopresenter.cpp @@ -3,3 +3,15 @@ #include "decomp.h" DECOMP_SIZE_ASSERT(MxAudioPresenter, 0x54); + +// OFFSET: LEGO1 0x1000d260 +undefined4 MxAudioPresenter::vtable5c() +{ + return this->m_unk50; +} + +// OFFSET: LEGO1 0x1000d270 +void MxAudioPresenter::vtable60(undefined4 p_unk50) +{ + this->m_unk50 = p_unk50; +} diff --git a/LEGO1/mxaudiopresenter.h b/LEGO1/mxaudiopresenter.h index c1001a13..fb2e75a8 100644 --- a/LEGO1/mxaudiopresenter.h +++ b/LEGO1/mxaudiopresenter.h @@ -1,6 +1,7 @@ #ifndef MXAUDIOPRESENTER_H #define MXAUDIOPRESENTER_H +#include "decomp.h" #include "mxmediapresenter.h" // VTABLE 0x100d4c70 @@ -24,7 +25,10 @@ class MxAudioPresenter : public MxMediaPresenter return !strcmp(name, MxAudioPresenter::ClassName()) || MxMediaPresenter::IsA(name); } - int m_unk50; + virtual undefined4 vtable5c(); + virtual void vtable60(undefined4); + + undefined4 m_unk50; }; #endif // MXAUDIOPRESENTER_H diff --git a/LEGO1/mxbackgroundaudiomanager.cpp b/LEGO1/mxbackgroundaudiomanager.cpp index a24286ad..40891bef 100644 --- a/LEGO1/mxbackgroundaudiomanager.cpp +++ b/LEGO1/mxbackgroundaudiomanager.cpp @@ -1,5 +1,7 @@ #include "mxbackgroundaudiomanager.h" +#include "mxomni.h" + DECOMP_SIZE_ASSERT(MxBackgroundAudioManager, 0x150) // OFFSET: LEGO1 0x1007ea90 diff --git a/LEGO1/mxbackgroundaudiomanager.h b/LEGO1/mxbackgroundaudiomanager.h index c6f2f1e7..a2c4cae3 100644 --- a/LEGO1/mxbackgroundaudiomanager.h +++ b/LEGO1/mxbackgroundaudiomanager.h @@ -28,8 +28,9 @@ class MxBackgroundAudioManager : public MxCore } __declspec(dllexport) void Enable(unsigned char p); -private: + void Stop(); +private: void Init(); MxBool m_musicEnabled; // 0x8 diff --git a/LEGO1/mxbitmap.cpp b/LEGO1/mxbitmap.cpp index 5987f31f..8f33fc22 100644 --- a/LEGO1/mxbitmap.cpp +++ b/LEGO1/mxbitmap.cpp @@ -1,12 +1,13 @@ #include "mxbitmap.h" #include "decomp.h" -DECOMP_SIZE_ASSERT(MxBITMAPINFO, 1064); +DECOMP_SIZE_ASSERT(MxBitmap, 0x20); +DECOMP_SIZE_ASSERT(MxBITMAPINFO, 0x428); -// The way that the BITMAPFILEHEADER structure ensures the file type is by ensuring it is "BM", which is literally just 0x424d. +// Bitmap header magic string "BM" (42 4d) // Sources: https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapfileheader, DirectX Complete (1998) // GLOBAL: LEGO1 0x10102184 -undefined2 g_bitmapSignature = 0x424d; +MxU16 g_bitmapSignature = TWOCC('B', 'M'); // OFFSET: LEGO1 0x100bc980 MxBitmap::MxBitmap() @@ -15,7 +16,7 @@ MxBitmap::MxBitmap() this->m_bmiHeader = NULL; this->m_paletteData = NULL; this->m_data = NULL; - this->m_bitDepth = LOWCOLOR; + this->m_isHighColor = FALSE; this->m_palette = NULL; } @@ -30,43 +31,54 @@ MxBitmap::~MxBitmap() delete m_palette; } +// Bit mask trick to round up to the nearest multiple of four. +// Pixel data may be stored with padding. +// https://learn.microsoft.com/en-us/windows/win32/medfound/image-stride +inline MxLong AlignToFourByte(MxLong p_value) +{ + return (p_value + 3) & -4; +} + +// Same as the one from legoutil.h, but flipped the other way +// TODO: While it's not outside the realm of possibility that they +// reimplemented Abs for only this file, that seems odd, right? +inline MxLong _Abs(MxLong p_value) +{ + return p_value > 0 ? p_value : -p_value; +} + // OFFSET: LEGO1 0x100bcc40 MxResult MxBitmap::ImportBitmap(MxBitmap *p_bitmap) { - MxLong height; MxResult result = FAILURE; this->m_info = new MxBITMAPINFO; if(this->m_info) { - height = p_bitmap->m_bmiHeader->biHeight; - if (height <= 0L) { - height = -height; - } - this->m_data = (LPVOID*) new MxU8[(p_bitmap->m_bmiHeader->biWidth + 3U & -4) * height]; + MxLong height = _Abs(p_bitmap->m_bmiHeader->biHeight); + this->m_data = new MxU8[AlignToFourByte(p_bitmap->m_bmiHeader->biWidth) * height]; if(this->m_data) { - memcpy(this->m_info, p_bitmap->m_info, sizeof(MxBITMAPINFO)); - - height = p_bitmap->m_bmiHeader->biHeight; - if (height <= 0L) { - height = -height; - } - memcpy(this->m_data, p_bitmap->m_data, (p_bitmap->m_bmiHeader->biWidth + 3U & -4) * height); + memcpy(this->m_info, p_bitmap->m_info, sizeof(*this->m_info)); + height = _Abs(p_bitmap->m_bmiHeader->biHeight); + memcpy(this->m_data, p_bitmap->m_data, AlignToFourByte(p_bitmap->m_bmiHeader->biWidth) * height); result = SUCCESS; this->m_bmiHeader = &this->m_info->bmiHeader; this->m_paletteData = this->m_info->bmiColors; } } + if (result != SUCCESS) { if (this->m_info) { delete this->m_info; this->m_info = NULL; } + if (this->m_data) { delete this->m_data; this->m_data = NULL; } } + return result; } @@ -76,29 +88,31 @@ MxResult MxBitmap::ImportBitmapInfo(MxBITMAPINFO *p_info) MxResult result = FAILURE; MxLong width = p_info->bmiHeader.biWidth; MxLong height = p_info->bmiHeader.biHeight; - // ((width + 3) & -4) clamps width to nearest 4-byte boundary - MxLong size = ((width + 3) & -4) * height; + MxLong size = AlignToFourByte(width) * height; this->m_info = new MxBITMAPINFO; if (this->m_info) { - this->m_data = (LPVOID*) new MxU8[size]; + this->m_data = new MxU8[size]; if(this->m_data) { - memcpy(this->m_info, p_info, sizeof(MxBITMAPINFO)); + memcpy(this->m_info, p_info, sizeof(*this->m_info)); this->m_bmiHeader = &this->m_info->bmiHeader; this->m_paletteData = this->m_info->bmiColors; result = SUCCESS; } } + if (result != SUCCESS) { if (this->m_info) { delete this->m_info; this->m_info = NULL; } + if (this->m_data) { delete this->m_data; this->m_data = NULL; } } + return result; } @@ -118,7 +132,7 @@ MxResult MxBitmap::ImportColorsToPalette(RGBQUAD* p_rgbquad, MxPalette* p_palett return ret; } - for (int i = 0; i < 256; i++) { + for (MxS32 i = 0; i < 256; i++) { p_rgbquad[i].rgbRed = entries[i].peRed; p_rgbquad[i].rgbGreen = entries[i].peGreen; p_rgbquad[i].rgbBlue = entries[i].peBlue; @@ -130,14 +144,14 @@ MxResult MxBitmap::ImportColorsToPalette(RGBQUAD* p_rgbquad, MxPalette* p_palett } // OFFSET: LEGO1 0x100bcaa0 -MxResult MxBitmap::SetSize(int p_width, int p_height, MxPalette *p_palette, int p_bitDepth) +MxResult MxBitmap::SetSize(MxS32 p_width, MxS32 p_height, MxPalette *p_palette, MxBool p_isHighColor) { MxResult ret = FAILURE; - MxLong size = ((p_width + 3) & -4) * p_height; + MxLong size = AlignToFourByte(p_width) * p_height; m_info = new MxBITMAPINFO; if (m_info) { - m_data = (LPVOID*) new MxU8[size]; + m_data = new MxU8[size]; if (m_data) { m_bmiHeader = &m_info->bmiHeader; m_paletteData = m_info->bmiColors; @@ -152,7 +166,7 @@ MxResult MxBitmap::SetSize(int p_width, int p_height, MxPalette *p_palette, int m_bmiHeader->biSizeImage = size; if (!ImportColorsToPalette(m_paletteData, p_palette)) { - if (!SetBitDepth(p_bitDepth)) { + if (!SetBitDepth(p_isHighColor)) { ret = SUCCESS; } } @@ -177,34 +191,26 @@ MxResult MxBitmap::SetSize(int p_width, int p_height, MxPalette *p_palette, int // OFFSET: LEGO1 0x100bcd60 MxResult MxBitmap::LoadFile(HANDLE p_handle) { - BOOL ret; - LPVOID* lpBuffer; - MxLong height; MxResult result = FAILURE; DWORD bytesRead; BITMAPFILEHEADER hdr; - MxLong size; - ret = ReadFile(p_handle, &hdr, sizeof(hdr), &bytesRead, NULL); + BOOL ret = ReadFile(p_handle, &hdr, sizeof(hdr), &bytesRead, NULL); if (ret && (hdr.bfType == g_bitmapSignature)) { this->m_info = new MxBITMAPINFO; - if(this->m_info) { - ret = ReadFile(p_handle, this->m_info, sizeof(MxBITMAPINFO), &bytesRead, NULL); - if (ret && ((this->m_info->bmiHeader).biBitCount == 8)) { - size = hdr.bfSize - (sizeof(MxBITMAPINFO) + sizeof(BITMAPFILEHEADER)); - lpBuffer = (LPVOID*) new MxU8[size]; - this->m_data = lpBuffer; - if (lpBuffer) { - ret = ReadFile(p_handle, lpBuffer, size, &bytesRead, NULL); - if(ret) { + if (this->m_info) { + ret = ReadFile(p_handle, this->m_info, sizeof(*this->m_info), &bytesRead, NULL); + if (ret && (this->m_info->bmiHeader.biBitCount == 8)) { + MxLong size = hdr.bfSize - (sizeof(MxBITMAPINFO) + sizeof(BITMAPFILEHEADER)); + this->m_data = new MxU8[size]; + if (this->m_data) { + ret = ReadFile(p_handle, this->m_data, size, &bytesRead, NULL); + if (ret) { this->m_bmiHeader = &this->m_info->bmiHeader; this->m_paletteData = this->m_info->bmiColors; - if((this->m_info->bmiHeader).biSizeImage == 0) { - height = (this->m_info->bmiHeader).biHeight; - if (height <= 0L) { - height = -height; - } - (this->m_info->bmiHeader).biSizeImage = ((this->m_info->bmiHeader).biWidth + 3U & -4) * height; + if (this->m_info->bmiHeader.biSizeImage == 0) { + MxLong height = _Abs(this->m_info->bmiHeader.biHeight); + this->m_info->bmiHeader.biSizeImage = AlignToFourByte(this->m_info->bmiHeader.biWidth) * height; } result = SUCCESS; } @@ -212,16 +218,19 @@ MxResult MxBitmap::LoadFile(HANDLE p_handle) } } } + if (result != SUCCESS) { if (this->m_info) { delete this->m_info; this->m_info = NULL; } + if (this->m_data) { delete this->m_data; this->m_data = NULL; } } + return result; } @@ -270,14 +279,14 @@ MxPalette *MxBitmap::CreatePalette() MxBool success = FALSE; MxPalette *palette = NULL; - switch (this->m_bitDepth) { - case LOWCOLOR: + switch (this->m_isHighColor) { + case FALSE: palette = new MxPalette(this->m_paletteData); if (palette) success = TRUE; break; - case HIGHCOLOR: + case TRUE: palette = this->m_palette->Clone(); if (palette) success = TRUE; @@ -295,14 +304,13 @@ MxPalette *MxBitmap::CreatePalette() // OFFSET: LEGO1 0x100bd280 void MxBitmap::ImportPalette(MxPalette* p_palette) { - // This is weird but it matches. Maybe m_bmiColorsProvided had more - // potential values than just true/false at some point? - switch (this->m_bitDepth) { - case LOWCOLOR: + // Odd to use a switch on a boolean, but it matches. + switch (this->m_isHighColor) { + case FALSE: ImportColorsToPalette(this->m_paletteData, p_palette); break; - case HIGHCOLOR: + case TRUE: if (this->m_palette) { delete this->m_palette; } @@ -312,18 +320,17 @@ void MxBitmap::ImportPalette(MxPalette* p_palette) } // OFFSET: LEGO1 0x100bd2d0 -MxResult MxBitmap::SetBitDepth(MxBool p_bitDepth) +MxResult MxBitmap::SetBitDepth(MxBool p_isHighColor) { MxResult ret = FAILURE; MxPalette *pal = NULL; - if (m_bitDepth == p_bitDepth) { + if (m_isHighColor == p_isHighColor) { // no change: do nothing. ret = SUCCESS; } else { - // TODO: Another switch used for this boolean value? Is it not a bool? - switch (p_bitDepth) { - case 0: + switch (p_isHighColor) { + case FALSE: ImportColorsToPalette(m_paletteData, m_palette); if (m_palette) delete m_palette; @@ -331,7 +338,7 @@ MxResult MxBitmap::SetBitDepth(MxBool p_bitDepth) m_palette = NULL; break; - case 1: + case TRUE: pal = NULL; pal = new MxPalette(m_paletteData); if (pal) { @@ -343,7 +350,7 @@ MxResult MxBitmap::SetBitDepth(MxBool p_bitDepth) buf[i] = i; } - m_bitDepth = p_bitDepth; + m_isHighColor = p_isHighColor; ret = SUCCESS; } break; @@ -359,12 +366,12 @@ MxResult MxBitmap::SetBitDepth(MxBool p_bitDepth) } // OFFSET: LEGO1 0x100bd3e0 -MxResult MxBitmap::StretchBits(HDC p_hdc, int p_xSrc, int p_ySrc, int p_xDest, int p_yDest, int p_destWidth, int p_destHeight) +MxResult MxBitmap::StretchBits(HDC p_hdc, MxS32 p_xSrc, MxS32 p_ySrc, MxS32 p_xDest, MxS32 p_yDest, MxS32 p_destWidth, MxS32 p_destHeight) { // Compression fix? if ((this->m_bmiHeader->biCompression != 16) && (0 < this->m_bmiHeader->biHeight)) { p_ySrc = (this->m_bmiHeader->biHeight - p_destHeight) - p_ySrc; } - return StretchDIBits(p_hdc, p_xDest, p_yDest, p_destWidth, p_destHeight, p_xSrc, p_ySrc, p_destWidth, p_destHeight, this->m_data, (BITMAPINFO*)this->m_info, this->m_bitDepth, SRCCOPY); -} \ No newline at end of file + return StretchDIBits(p_hdc, p_xDest, p_yDest, p_destWidth, p_destHeight, p_xSrc, p_ySrc, p_destWidth, p_destHeight, this->m_data, (BITMAPINFO*)this->m_info, this->m_isHighColor, SRCCOPY); +} diff --git a/LEGO1/mxbitmap.h b/LEGO1/mxbitmap.h index ba90b7da..53b01e16 100644 --- a/LEGO1/mxbitmap.h +++ b/LEGO1/mxbitmap.h @@ -21,10 +21,8 @@ struct MxBITMAPINFO { RGBQUAD bmiColors[256]; }; -// These values are the bit depth, set in the registry -#define LOWCOLOR 0 // 256 color -#define HIGHCOLOR 1 // High Color (16-bit) - +// SIZE 0x20 +// VTABLE 0x100dc7b0 class MxBitmap : public MxCore { public: @@ -33,7 +31,7 @@ class MxBitmap : public MxCore virtual MxResult ImportBitmap(MxBitmap *p_bitmap); // vtable+14 virtual MxResult ImportBitmapInfo(MxBITMAPINFO *p_info); // vtable+18 - virtual MxResult SetSize(int p_width, int p_height, MxPalette *p_palette, int); // vtable+1c + virtual MxResult SetSize(MxS32 p_width, MxS32 p_height, MxPalette *p_palette, MxBool); // vtable+1c virtual MxResult LoadFile(HANDLE p_handle); // vtable+20 __declspec(dllexport) virtual MxLong Read(const char *p_filename); // vtable+24 virtual int vtable28(int); @@ -42,7 +40,9 @@ class MxBitmap : public MxCore __declspec(dllexport) virtual MxPalette *CreatePalette(); // vtable+34 virtual void ImportPalette(MxPalette* p_palette); // vtable+38 virtual MxResult SetBitDepth(MxBool); // vtable+3c - virtual MxResult StretchBits(HDC p_hdc, int p_xSrc, int p_ySrc, int p_xDest, int p_yDest, int p_destWidth, int p_destHeight); // vtable+40 + virtual MxResult StretchBits(HDC p_hdc, MxS32 p_xSrc, MxS32 p_ySrc, MxS32 p_xDest, MxS32 p_yDest, MxS32 p_destWidth, MxS32 p_destHeight); // vtable+40 + + inline BITMAPINFOHEADER *GetBmiHeader() const { return m_bmiHeader; } private: MxResult ImportColorsToPalette(RGBQUAD*, MxPalette*); @@ -50,8 +50,8 @@ class MxBitmap : public MxCore MxBITMAPINFO *m_info; // 0x8 BITMAPINFOHEADER *m_bmiHeader; // 0xc RGBQUAD *m_paletteData; // 0x10 - LPVOID *m_data; // 0x14 - MxBool m_bitDepth; // 0x18 + MxU8 *m_data; // 0x14 + MxBool m_isHighColor; // 0x18 MxPalette *m_palette; // 0x1c }; diff --git a/LEGO1/mxcompositepresenter.cpp b/LEGO1/mxcompositepresenter.cpp index 342f3d96..06477c94 100644 --- a/LEGO1/mxcompositepresenter.cpp +++ b/LEGO1/mxcompositepresenter.cpp @@ -1,17 +1,18 @@ #include "mxcompositepresenter.h" #include "decomp.h" +#include "mxnotificationmanager.h" DECOMP_SIZE_ASSERT(MxCompositePresenter, 0x4c); -// OFFSET: LEGO1 0x100b60b0 STUB +// OFFSET: LEGO1 0x100b60b0 MxCompositePresenter::MxCompositePresenter() { - // TODO + NotificationManager()->Register(this); } -// OFFSET: LEGO1 0x100b6390 STUB +// OFFSET: LEGO1 0x100b6390 MxCompositePresenter::~MxCompositePresenter() { - // TODO + NotificationManager()->Unregister(this); } diff --git a/LEGO1/mxcompositepresenter.h b/LEGO1/mxcompositepresenter.h index 9f517652..0be080f0 100644 --- a/LEGO1/mxcompositepresenter.h +++ b/LEGO1/mxcompositepresenter.h @@ -2,6 +2,7 @@ #define MXCOMPOSITEPRESENTER_H #include "mxpresenter.h" +#include "mxunklist.h" // VTABLE 0x100dc618 // SIZE 0x4c @@ -24,9 +25,7 @@ class MxCompositePresenter : public MxPresenter return !strcmp(name, MxCompositePresenter::ClassName()) || MxPresenter::IsA(name); } - undefined m_unk40; - undefined4 *m_unk44; - undefined4 m_unk48; + MxUnkList m_list; }; #endif // MXCOMPOSITEPRESENTER_H diff --git a/LEGO1/mxcontrolpresenter.cpp b/LEGO1/mxcontrolpresenter.cpp index e9e10ef8..7210952c 100644 --- a/LEGO1/mxcontrolpresenter.cpp +++ b/LEGO1/mxcontrolpresenter.cpp @@ -1,7 +1,14 @@ #include "mxcontrolpresenter.h" -// OFFSET: LEGO1 0x10043f50 STUB +DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) + +// OFFSET: LEGO1 0x10043f50 MxControlPresenter::MxControlPresenter() { - // TODO + this->m_unk4c = 0; + this->m_unk4e = -1; + this->m_unk50 = 0; + this->m_unk52 = 0; + this->m_unk58 = 0; + this->m_unk54 = 0; } \ No newline at end of file diff --git a/LEGO1/mxcontrolpresenter.h b/LEGO1/mxcontrolpresenter.h index 909a3502..18af66a3 100644 --- a/LEGO1/mxcontrolpresenter.h +++ b/LEGO1/mxcontrolpresenter.h @@ -1,6 +1,8 @@ #ifndef MXCONTROLPRESENTER_H #define MXCONTROLPRESENTER_H +#include "decomp.h" + #include "mxcompositepresenter.h" // VTABLE 0x100d7b88 @@ -22,7 +24,13 @@ class MxControlPresenter : public MxCompositePresenter { return !strcmp(name, MxControlPresenter::ClassName()) || MxCompositePresenter::IsA(name); } - +private: + undefined2 m_unk4c; + MxS16 m_unk4e; + undefined m_unk50; + undefined2 m_unk52; + undefined2 m_unk54; + undefined4 m_unk58; }; diff --git a/LEGO1/mxcore.cpp b/LEGO1/mxcore.cpp index 78441d8d..ab73e242 100644 --- a/LEGO1/mxcore.cpp +++ b/LEGO1/mxcore.cpp @@ -22,7 +22,7 @@ MxLong MxCore::Notify(MxParam &p) } // OFFSET: LEGO1 0x10001f70 -MxLong MxCore::Tickle() +MxResult MxCore::Tickle() { return 0; } \ No newline at end of file diff --git a/LEGO1/mxdirect3d.cpp b/LEGO1/mxdirect3d.cpp index e69de29b..6d6a43e3 100644 --- a/LEGO1/mxdirect3d.cpp +++ b/LEGO1/mxdirect3d.cpp @@ -0,0 +1,191 @@ +#include "mxdirect3d.h" +#include // for vsprintf + +DECOMP_SIZE_ASSERT(MxDirect3D, 0x894); +DECOMP_SIZE_ASSERT(MxDeviceModeFinder, 0xe4); +DECOMP_SIZE_ASSERT(MxDeviceEnumerate, 0x198); + +// OFFSET: LEGO1 0x1009b0a0 +MxDirect3D::MxDirect3D() +{ + this->m_pDirect3d = NULL; + this->m_pDirect3dDevice = NULL; + this->m_unk88c = NULL; + this->m_pDeviceModeFinder = NULL; +} + +// OFFSET: LEGO1 0x1009b140 +MxDirect3D::~MxDirect3D() +{ + Destroy(); +} + +// OFFSET: LEGO1 0x1009b1a0 +BOOL MxDirect3D::Create( + HWND hWnd, + BOOL fullscreen_1, + BOOL surface_fullscreen, + BOOL onlySystemMemory, + int width, + int height, + int bpp, + const PALETTEENTRY* pPaletteEntries, + int paletteEntryCount) +{ + BOOL success = FALSE; + + BOOL ret = MxDirectDraw::Create(hWnd, fullscreen_1, surface_fullscreen, + onlySystemMemory, width, height, bpp, + pPaletteEntries, paletteEntryCount); + + if (ret && CreateIDirect3D() && D3DSetMode()) + success = TRUE; + + if (!success) + FUN_1009D920(); + + return success; +} + +// OFFSET: LEGO1 0x1009b210 +void MxDirect3D::Destroy() +{ + if (this->m_pDirect3dDevice) { + this->m_pDirect3dDevice->Release(); + this->m_pDirect3dDevice = NULL; + } + + if (this->m_pDirect3d) { + this->m_pDirect3d->Release(); + this->m_pDirect3d = NULL; + } + + if (this->m_pDeviceModeFinder) { + delete m_pDeviceModeFinder; + this->m_pDeviceModeFinder = NULL; + } + + // This should get deleted by MxDirectDraw::Destroy + if (m_pCurrentDeviceModesList) { + // delete m_pCurrentDeviceModesList; // missing? + m_pCurrentDeviceModesList = NULL; + } + + MxDirectDraw::Destroy(); +} + +// OFFSET: LEGO1 0x1009b290 +void MxDirect3D::Clear() +{ + if(this->m_pDirect3dDevice) { + this->m_pDirect3dDevice->Release(); + this->m_pDirect3dDevice = NULL; + } + if(this->m_pDirect3d) { + this->m_pDirect3d->Release(); + this->m_pDirect3d = NULL; + } + MxDirectDraw::DestroyButNotDirectDraw(); +} + +// OFFSET: LEGO1 0x1009b2d0 +BOOL MxDirect3D::CreateIDirect3D() +{ + MxResult ret = IDirect3D_QueryInterface(m_pDirectDraw, + IID_IDirect3D2, + (LPVOID*)&m_pDirect3d); + + if (ret) { + Error("Creation of IDirect3D failed", ret); + return FALSE; + } + + return TRUE; +} + +// OFFSET: LEGO1 0x1009b310 STUB +BOOL MxDirect3D::D3DSetMode() +{ + // TODO + //if (m_pDeviceModeFinder) + Error("This device cannot support the current display mode", 0); + OutputDebugString("MxDirect3D::D3DSetMode() front lock failed\n"); + OutputDebugString("MxDirect3D::D3DSetMode() back lock failed\n"); + return TRUE; +} + +// OFFSET: LEGO1 0x1009b8b0 +MxDeviceModeFinder::MxDeviceModeFinder() +{ + memset(this, 0, sizeof(*this)); +} + +// OFFSET: LEGO1 0x1009b8d0 +MxDeviceModeFinder::~MxDeviceModeFinder() +{ + if (m_deviceInfo) { + delete m_deviceInfo; + m_deviceInfo = NULL; + } +} + +// OFFSET: LEGO1 0x1009c070 STUB +BOOL MxDeviceEnumerate::FUN_1009c070() +{ + // TODO + // HRESULT ret = DirectDrawCreate(); + HRESULT ret = 0; + if (ret) { + MxDirect3D::BuildErrorString("GetCaps failed: %s\n", + EnumerateErrorToString(ret)); + } + //IDirect3D2_EnumDevices + return TRUE; +} + +// OFFSET: LEGO1 0x1009c4c0 +void MxDirect3D::BuildErrorString(const char *p_format, ...) +{ + va_list args; + char buf[512]; + + va_start(args, p_format); + vsprintf(buf, p_format, args); + va_end(args); + + OutputDebugString(buf); +} + +// OFFSET: LEGO1 0x1009c6c0 +MxResult MxDeviceEnumerate::_DoEnumerate() +{ + // TODO: what does ECX refer to in this context? + if (m_unk010_flag) + return FAILURE; + + HRESULT ret = DirectDrawEnumerate(EnumerateCallback, this); + if (ret) { + MxDirect3D::BuildErrorString("DirectDrawEnumerate returned error %s\n", + EnumerateErrorToString(ret)); + return FAILURE; + } + + m_unk010_flag = TRUE; + return SUCCESS; +} + +// OFFSET: LEGO1 0x1009c710 STUB +BOOL FAR PASCAL EnumerateCallback(GUID FAR *, LPSTR, LPSTR, LPVOID) +{ + // TODO + return FALSE; +} + +// OFFSET: LEGO1 0x1009c730 STUB +char *MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) +{ + // TODO: This is a list of error messages, similar to the function in + // MxDirectDraw, except that this one now contains the Direct3D errors. + // Probably just copied from a sample file in the dx5 sdk. + return ""; +} diff --git a/LEGO1/mxdirect3d.h b/LEGO1/mxdirect3d.h index ecc1f0aa..03e9f1ac 100644 --- a/LEGO1/mxdirect3d.h +++ b/LEGO1/mxdirect3d.h @@ -2,24 +2,77 @@ #define MXDIRECT3D_H #include "mxdirectdraw.h" +#include "mxtypes.h" #include "decomp.h" #include -class MxDeviceModeFinder; +// SIZE 0xe4 +class MxDeviceModeFinder +{ +public: + MxDeviceModeFinder(); + ~MxDeviceModeFinder(); + undefined4 m_unknown[56]; + MxDirectDraw::DeviceModesInfo *m_deviceInfo; // +0xe0 +}; + +// VTABLE 0x100db814 (or 0x100d9cc8?) +// SIZE 0x198 +class MxDeviceEnumerate +{ +public: + MxDeviceEnumerate(); + virtual MxResult _DoEnumerate(); + BOOL FUN_1009c070(); + + char *EnumerateErrorToString(HRESULT p_error); + + undefined4 m_unk004; + undefined4 m_unk008; + undefined4 m_unk00c; + MxBool m_unk010_flag; // +0x10 + + undefined4 m_unknown[97]; +}; + +// VTABLE 0x100db800 // SIZE 0x894 class MxDirect3D : public MxDirectDraw { public: + MxDirect3D(); + + void Clear(); inline MxDeviceModeFinder *GetDeviceModeFinder() { return this->m_pDeviceModeFinder; }; + virtual ~MxDirect3D(); + virtual BOOL Create( + HWND hWnd, + BOOL fullscreen_1, + BOOL surface_fullscreen, + BOOL onlySystemMemory, + int width, + int height, + int bpp, + const PALETTEENTRY* pPaletteEntries, + int paletteEntryCount); + virtual void Destroy(); + + BOOL CreateIDirect3D(); + BOOL D3DSetMode(); + + static void BuildErrorString(const char *, ...); + private: - MxDeviceModeFinder *m_pDeviceModeFinder; - IDirect3D *m_pDirect3d; + MxDeviceModeFinder *m_pDeviceModeFinder; // +0x880 + IDirect3D *m_pDirect3d; // +0x884 IDirect3DDevice *m_pDirect3dDevice; undefined4 m_unk88c; undefined4 m_unk890; }; +BOOL FAR PASCAL EnumerateCallback(GUID FAR *, LPSTR, LPSTR, LPVOID); + #endif // MXDIRECT3D_H \ No newline at end of file diff --git a/LEGO1/mxdirectdraw.cpp b/LEGO1/mxdirectdraw.cpp index 625a6fae..099e9bc6 100644 --- a/LEGO1/mxdirectdraw.cpp +++ b/LEGO1/mxdirectdraw.cpp @@ -1,8 +1,8 @@ - #include "mxdirectdraw.h" #include "decomp.h" DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880); +DECOMP_SIZE_ASSERT(MxDirectDraw::DeviceModesInfo, 0x17c); #ifndef DDSCAPS_3DDEVICE #define DDSCAPS_3DDEVICE 0x00002000l @@ -30,6 +30,12 @@ void EnableResizing(HWND hwnd, BOOL flag) } } +// OFFSET: LEGO1 0x1009efb0 +MxDirectDraw::DeviceModesInfo::DeviceModesInfo() +{ + memset(this, 0, sizeof(*this)); +} + // OFFSET: LEGO1 0x1009EFD0 MxDirectDraw::DeviceModesInfo::~DeviceModesInfo() { diff --git a/LEGO1/mxdirectdraw.h b/LEGO1/mxdirectdraw.h index 3e2c710a..8cee9477 100644 --- a/LEGO1/mxdirectdraw.h +++ b/LEGO1/mxdirectdraw.h @@ -1,4 +1,3 @@ - #ifndef MXDIRECTDRAW_H #define MXDIRECTDRAW_H @@ -7,6 +6,7 @@ extern BOOL g_is_PALETTEINDEXED8; +// VTABLE 0x100db818 // SIZE 0x880 class MxDirectDraw { @@ -37,11 +37,12 @@ class MxDirectDraw DDCAPS m_ddcaps; void* a_178; + DeviceModesInfo(); ~DeviceModesInfo(); }; -private: +protected: BOOL m_bOnlySoftRender; BOOL m_bFlipSurfaces; IDirectDraw* m_pDirectDraw; @@ -94,7 +95,7 @@ class MxDirectDraw virtual void DestroyButNotDirectDraw(); virtual const char* ErrorToString(HRESULT error); -private: +protected: BOOL CacheOriginalPaletteEntries(); HRESULT CreateDDSurface( LPDDSURFACEDESC a2, diff --git a/LEGO1/mxdiskstreamcontroller.cpp b/LEGO1/mxdiskstreamcontroller.cpp index 61243410..0c74c3a7 100644 --- a/LEGO1/mxdiskstreamcontroller.cpp +++ b/LEGO1/mxdiskstreamcontroller.cpp @@ -13,9 +13,55 @@ MxDiskStreamController::~MxDiskStreamController() } // OFFSET: LEGO1 0x100c8640 STUB -MxLong MxDiskStreamController::Tickle() +MxResult MxDiskStreamController::Tickle() { // TODO - return 0; } + +// OFFSET: LEGO1 0x100c7790 STUB +MxResult MxDiskStreamController::Open(const char *p_filename) +{ + // TODO + return FAILURE; +} + +// OFFSET: LEGO1 0x100c7880 +MxResult MxDiskStreamController::vtable0x18(undefined4 p_unknown, undefined4 p_unknown2) +{ + return SUCCESS; +} + +// OFFSET: LEGO1 0x100c7ff0 STUB +MxResult MxDiskStreamController::vtable0x20(MxDSAction* p_action) +{ + // TODO + return FAILURE; +} + +// OFFSET: LEGO1 0x100c8160 STUB +MxResult MxDiskStreamController::vtable0x24(undefined4 p_unknown) +{ + // TODO + return FAILURE; +} + +// OFFSET: LEGO1 0x100c7ac0 STUB +MxResult MxDiskStreamController::vtable0x28() +{ + // TODO + return FAILURE; +} + +// OFFSET: LEGO1 0x100c7c00 STUB +MxResult MxDiskStreamController::vtable0x30(undefined4 p_unknown) +{ + // TODO + return FAILURE; +} + +// OFFSET: LEGO1 0x100c7960 +MxResult MxDiskStreamController::vtable0x34(undefined4 p_unknown) +{ + return FAILURE; +} diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/mxdiskstreamcontroller.h index c0142663..5457a9b5 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/mxdiskstreamcontroller.h @@ -14,7 +14,14 @@ class MxDiskStreamController : public MxStreamController MxDiskStreamController(); virtual ~MxDiskStreamController() override; - virtual MxLong Tickle() override; // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 + virtual MxResult Open(const char *p_filename) override; // vtable+0x14 + virtual MxResult vtable0x18(undefined4 p_unknown, undefined4 p_unknown2) override; //vtable+0x18 + virtual MxResult vtable0x20(MxDSAction* p_action) override; //vtable+0x20 + virtual MxResult vtable0x24(undefined4 p_unknown) override; //vtable+0x24 + virtual MxResult vtable0x28() override; //vtable+0x28 + virtual MxResult vtable0x30(undefined4 p_unknown) override; //vtable+0x30 + virtual MxResult vtable0x34(undefined4 p_unknown); //vtable+0x34 // OFFSET: LEGO1 0x100c7360 inline virtual const char *ClassName() const override // vtable+0x0c diff --git a/LEGO1/mxdiskstreamprovider.cpp b/LEGO1/mxdiskstreamprovider.cpp index 38d5cddc..9555a8cf 100644 --- a/LEGO1/mxdiskstreamprovider.cpp +++ b/LEGO1/mxdiskstreamprovider.cpp @@ -2,6 +2,8 @@ #include "mxthread.h" +DECOMP_SIZE_ASSERT(MxDiskStreamProvider, 0x60); + // OFFSET: LEGO1 0x100d0f30 MxResult MxDiskStreamProviderThread::Run() { @@ -15,7 +17,9 @@ MxResult MxDiskStreamProviderThread::Run() // OFFSET: LEGO1 0x100d0f70 MxDiskStreamProvider::MxDiskStreamProvider() { - // TODO + this->m_pFile = NULL; + this->m_remainingWork = 0; + this->m_unk35 = 0; } // OFFSET: LEGO1 0x100d1240 @@ -31,7 +35,7 @@ MxResult MxDiskStreamProvider::WaitForWorkToComplete() while (m_remainingWork != 0) { m_busySemaphore.Wait(INFINITE); - if (m_unk1 != 0) + if (m_unk35 != 0) PerformWork(); } return SUCCESS; @@ -41,4 +45,41 @@ MxResult MxDiskStreamProvider::WaitForWorkToComplete() void MxDiskStreamProvider::PerformWork() { // TODO -} \ No newline at end of file +} + +// OFFSET: LEGO1 0x100d13d0 STUB +MxResult MxDiskStreamProvider::SetResourceToGet(void* p_resource) +{ + // TODO + return FAILURE; +} + +// OFFSET: LEGO1 0x100d1e90 +MxU32 MxDiskStreamProvider::GetFileSize() +{ + return m_pFile->GetBufferSize(); +} + +// OFFSET: LEGO1 0x100d1ea0 +MxU32 MxDiskStreamProvider::GetStreamBuffersNum() +{ + return m_pFile->GetStreamBuffersNum(); +} + +// OFFSET: LEGO1 0x100d15e0 STUB +void MxDiskStreamProvider::vtable0x20(undefined4 p_unknown1) +{ + // TODO +} + +// OFFSET: LEGO1 0x100d1eb0 +MxU32 MxDiskStreamProvider::GetLengthInDWords() +{ + return m_pFile->GetLengthInDWords(); +} + +// OFFSET: LEGO1 0x100d1ec0 +MxU32* MxDiskStreamProvider::GetBufferForDWords() +{ + return m_pFile->GetBuffer(); +} diff --git a/LEGO1/mxdiskstreamprovider.h b/LEGO1/mxdiskstreamprovider.h index 58679055..de807e3d 100644 --- a/LEGO1/mxdiskstreamprovider.h +++ b/LEGO1/mxdiskstreamprovider.h @@ -1,9 +1,11 @@ #ifndef MXDISKSTREAMPROVIDER_H #define MXDISKSTREAMPROVIDER_H +#include "decomp.h" #include "mxstreamprovider.h" #include "mxthread.h" #include "mxcriticalsection.h" +#include "mxunklist.h" class MxDiskStreamProvider; @@ -47,15 +49,20 @@ class MxDiskStreamProvider : public MxStreamProvider void PerformWork(); + virtual MxResult SetResourceToGet(void* p_resource) override; //vtable+0x14 + virtual MxU32 GetFileSize() override; //vtable+0x18 + virtual MxU32 GetStreamBuffersNum() override; //vtable+0x1c + virtual void vtable0x20(undefined4 p_unknown1) override; //vtable+0x20 + virtual MxU32 GetLengthInDWords() override; //vtable+0x24 + virtual MxU32* GetBufferForDWords() override; //vtable+0x28 + private: - MxDiskStreamProviderThread m_thread; - MxSemaphore m_busySemaphore; - byte m_remainingWork; - byte m_unk1; - MxCriticalSection m_criticalSection; - byte unk2[4]; - void* unk3; - void *unk4; + MxDiskStreamProviderThread m_thread; // 0x10 + MxSemaphore m_busySemaphore; // 0x2c + undefined m_remainingWork; // 0x34 + undefined m_unk35; // 0x35 + MxCriticalSection m_criticalSection; // 0x38 + MxUnkList m_list; }; #endif // MXDISKSTREAMPROVIDER_H diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index 4f02aeb6..af7e57db 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -1,5 +1,7 @@ #include "mxdisplaysurface.h" + #include "mxomni.h" +#include "mxvideomanager.h" DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); @@ -174,7 +176,7 @@ void MxDisplaySurface::SetPalette(MxPalette *p_palette) } // OFFSET: LEGO1 0x100bc200 STUB -void MxDisplaySurface::vtable24(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) +void MxDisplaySurface::vtable24(LPDDSURFACEDESC, MxBitmap*, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) { } @@ -186,7 +188,7 @@ MxBool MxDisplaySurface::vtable28(undefined4, undefined4, undefined4, undefined4 } // OFFSET: LEGO1 0x100bc630 STUB -MxBool MxDisplaySurface::vtable2c(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool) +MxBool MxDisplaySurface::vtable2c(LPDDSURFACEDESC, MxBitmap*, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool) { return 0; } @@ -230,3 +232,9 @@ undefined4 MxDisplaySurface::vtable44(undefined4, undefined4*, undefined4, undef { return 0; } + +// OFFSET: LEGO1 0x100ba640 STUB +void MxDisplaySurface::FUN_100ba640() +{ + // TODO +} diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index c76266d7..8a80a0f4 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -3,6 +3,7 @@ #include +#include "mxbitmap.h" #include "mxcore.h" #include "mxpalette.h" #include "mxvideoparam.h" @@ -19,13 +20,15 @@ class MxDisplaySurface : public MxCore void Reset(); + void FUN_100ba640(); + virtual MxResult Init(MxVideoParam &p_videoParam, LPDIRECTDRAWSURFACE p_ddSurface1, LPDIRECTDRAWSURFACE p_ddSurface2, LPDIRECTDRAWCLIPPER p_ddClipper); virtual MxResult Create(MxVideoParam &p_videoParam); virtual void Clear(); virtual void SetPalette(MxPalette *p_palette); - virtual void vtable24(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); + virtual void vtable24(LPDDSURFACEDESC, MxBitmap*, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); virtual MxBool vtable28(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); - virtual MxBool vtable2c(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool); + virtual MxBool vtable2c(LPDDSURFACEDESC, MxBitmap*, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool); virtual MxBool vtable30(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool); virtual undefined4 vtable34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); virtual void Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); @@ -33,6 +36,9 @@ class MxDisplaySurface : public MxCore virtual void ReleaseDC(HDC p_hdc); virtual undefined4 vtable44(undefined4, undefined4*, undefined4, undefined4); + inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } + inline LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return this->m_ddSurface2; } + private: MxVideoParam m_videoParam; LPDIRECTDRAWSURFACE m_ddSurface1; diff --git a/LEGO1/mxdsaction.cpp b/LEGO1/mxdsaction.cpp index e9b65037..153a6498 100644 --- a/LEGO1/mxdsaction.cpp +++ b/LEGO1/mxdsaction.cpp @@ -1,5 +1,9 @@ #include "mxdsaction.h" +#include "mxomni.h" +#include "mxtimer.h" +#include "legoutil.h" + #include #include @@ -13,28 +17,15 @@ MxDSAction::MxDSAction() { this->m_flags = 32; this->m_startTime = INT_MIN; - this->m_unkData = NULL; - this->m_unkLength = 0; + this->m_extraData = NULL; + this->m_extraLength = 0; this->m_duration = INT_MIN; this->m_loopCount = -1; this->SetType(MxDSType_Action); - - { - float value = FLT_MAX; - this->m_location.EqualsScalar(&value); - } - - { - float value = FLT_MAX; - this->m_direction.EqualsScalar(&value); - } - - { - float value = FLT_MAX; - this->m_up.EqualsScalar(&value); - } - + this->m_location.Fill(FLT_MAX); + this->m_direction.Fill(FLT_MAX); + this->m_up.Fill(FLT_MAX); this->m_unk84 = 0; this->m_unk88 = 0; this->m_omni = NULL; @@ -44,7 +35,7 @@ MxDSAction::MxDSAction() // OFFSET: LEGO1 0x100ada80 MxDSAction::~MxDSAction() { - delete[] this->m_unkData; + delete[] this->m_extraData; } // OFFSET: LEGO1 0x100adaf0 @@ -60,7 +51,7 @@ void MxDSAction::CopyFrom(MxDSAction &p_dsAction) this->m_direction.CopyFrom(p_dsAction.m_direction); this->m_up.CopyFrom(p_dsAction.m_up); - AppendData(p_dsAction.m_unkLength, p_dsAction.m_unkData); + AppendData(p_dsAction.m_extraLength, p_dsAction.m_extraData); this->m_unk84 = p_dsAction.m_unk84; this->m_unk88 = p_dsAction.m_unk88; this->m_omni = p_dsAction.m_omni; @@ -83,7 +74,7 @@ MxU32 MxDSAction::GetSizeOnDisk() { MxU32 totalSizeOnDisk; - totalSizeOnDisk = MxDSObject::GetSizeOnDisk() + 90 + this->m_unkLength; + totalSizeOnDisk = MxDSObject::GetSizeOnDisk() + 90 + this->m_extraLength; this->m_sizeOnDisk = totalSizeOnDisk - MxDSObject::GetSizeOnDisk(); return totalSizeOnDisk; @@ -94,38 +85,24 @@ void MxDSAction::Deserialize(char **p_source, MxS16 p_unk24) { MxDSObject::Deserialize(p_source, p_unk24); - this->m_flags = *(MxU32*) *p_source; - *p_source += sizeof(MxU32); - this->m_startTime = *(DWORD*) *p_source; - *p_source += sizeof(DWORD); - this->m_duration = *(MxLong*) *p_source; - *p_source += sizeof(MxLong); - this->m_loopCount = *(MxS32*) *p_source; - *p_source += sizeof(MxS32); - this->m_location[0] = *(double*) *p_source; - *p_source += sizeof(double); - this->m_location[1] = *(double*) *p_source; - *p_source += sizeof(double); - this->m_location[2] = *(double*) *p_source; - *p_source += sizeof(double); - this->m_direction[0] = *(double*) *p_source; - *p_source += sizeof(double); - this->m_direction[1] = *(double*) *p_source; - *p_source += sizeof(double); - this->m_direction[2] = *(double*) *p_source; - *p_source += sizeof(double); - this->m_up[0] = *(double*) *p_source; - *p_source += sizeof(double); - this->m_up[1] = *(double*) *p_source; - *p_source += sizeof(double); - this->m_up[2] = *(double*) *p_source; - *p_source += sizeof(double); + GetScalar(p_source, this->m_flags); + GetScalar(p_source, this->m_startTime); + GetScalar(p_source, this->m_duration); + GetScalar(p_source, this->m_loopCount); + GetDouble(p_source, this->m_location[0]); + GetDouble(p_source, this->m_location[1]); + GetDouble(p_source, this->m_location[2]); + GetDouble(p_source, this->m_direction[0]); + GetDouble(p_source, this->m_direction[1]); + GetDouble(p_source, this->m_direction[2]); + GetDouble(p_source, this->m_up[0]); + GetDouble(p_source, this->m_up[1]); + GetDouble(p_source, this->m_up[2]); - MxU16 unkLength = *(MxU16*) *p_source; - *p_source += sizeof(MxU16); - if (unkLength) { - AppendData(unkLength, *p_source); - *p_source += unkLength; + MxU16 extraLength = GetScalar((MxU16**) p_source); + if (extraLength) { + AppendData(extraLength, *p_source); + *p_source += extraLength; } } @@ -186,13 +163,13 @@ void MxDSAction::MergeFrom(MxDSAction &p_dsAction) this->m_up[2] = p_dsAction.m_up[2]; // TODO - MxU16 unkLength = p_dsAction.m_unkLength; - char *unkData = p_dsAction.m_unkData; - if (unkLength && unkData) { - if (!this->m_unkData || !strncmp("XXX", this->m_unkData, 3)) { - delete[] this->m_unkData; - this->m_unkLength = 0; - AppendData(unkLength, unkData); + MxU16 extraLength = p_dsAction.m_extraLength; + char *extraData = p_dsAction.m_extraData; + if (extraLength && extraData) { + if (!this->m_extraData || !strncmp("XXX", this->m_extraData, 3)) { + delete[] this->m_extraData; + this->m_extraLength = 0; + AppendData(extraLength, extraData); } } } @@ -215,6 +192,9 @@ MxLong MxDSAction::GetSomeTimingField() return this->m_someTimingField; } +// Win32 defines GetCurrentTime to GetTickCount +#undef GetCurrentTime + // OFFSET: LEGO1 0x100adcd0 MxLong MxDSAction::GetCurrentTime() { @@ -222,29 +202,29 @@ MxLong MxDSAction::GetCurrentTime() } // OFFSET: LEGO1 0x100ade60 -void MxDSAction::AppendData(MxU16 p_unkLength, const char *p_unkData) +void MxDSAction::AppendData(MxU16 p_extraLength, const char *p_extraData) { - if (this->m_unkData == p_unkData || !p_unkData) + if (this->m_extraData == p_extraData || !p_extraData) return; - if (this->m_unkLength) { - char *concat = new char[p_unkLength + this->m_unkLength + sizeof(g_unkSep)]; - memcpy(concat, this->m_unkData, this->m_unkLength); + if (this->m_extraLength) { + char *concat = new char[p_extraLength + this->m_extraLength + sizeof(g_unkSep)]; + memcpy(concat, this->m_extraData, this->m_extraLength); - *(MxU16*) &concat[this->m_unkLength] = g_unkSep; - memcpy(&concat[this->m_unkLength + sizeof(g_unkSep)], p_unkData, p_unkLength); + *(MxU16*) &concat[this->m_extraLength] = g_unkSep; + memcpy(&concat[this->m_extraLength + sizeof(g_unkSep)], p_extraData, p_extraLength); - this->m_unkLength += p_unkLength + sizeof(g_unkSep); - delete[] this->m_unkData; - this->m_unkData = concat; + this->m_extraLength += p_extraLength + sizeof(g_unkSep); + delete[] this->m_extraData; + this->m_extraData = concat; } else { - char *copy = new char[p_unkLength]; - this->m_unkData = copy; + char *copy = new char[p_extraLength]; + this->m_extraData = copy; if (copy) { - this->m_unkLength = p_unkLength; - memcpy(copy, p_unkData, p_unkLength); + this->m_extraLength = p_extraLength; + memcpy(copy, p_extraData, p_extraLength); } } } diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index a85e6494..57d1f200 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -2,8 +2,10 @@ #define MXDSACTION_H #include "mxdsobject.h" +#include "mxtypes.h" #include "mxvector.h" -#include "mxomni.h" + +class MxOmni; // VTABLE 0x100dc098 // SIZE 0x94 @@ -12,7 +14,12 @@ class MxDSAction : public MxDSObject public: enum { + Flag_Looping = 0x01, + Flag_Bit3 = 0x04, + Flag_Bit5 = 0x10, Flag_Enabled = 0x20, + Flag_Parsed = 0x80, + Flag_Bit9 = 0x200, }; __declspec(dllexport) MxDSAction(); @@ -34,10 +41,10 @@ class MxDSAction : public MxDSObject return !strcmp(name, MxDSAction::ClassName()) || MxDSObject::IsA(name); } - virtual MxU32 GetSizeOnDisk(); // vtable+18; - virtual void Deserialize(char **p_source, MxS16 p_unk24); // vtable+1c; + virtual MxU32 GetSizeOnDisk() override; // vtable+18; + virtual void Deserialize(char **p_source, MxS16 p_unk24) override; // vtable+1c; virtual MxLong GetDuration(); // vtable+24; - virtual void SetDuration(LONG p_duration); // vtable+28; + virtual void SetDuration(MxLong p_duration); // vtable+28; virtual MxDSAction *Clone(); // vtable+2c; virtual void MergeFrom(MxDSAction &p_dsAction); // vtable+30; virtual MxBool HasId(MxU32 p_objectId); // vtable+34; @@ -45,15 +52,25 @@ class MxDSAction : public MxDSObject virtual MxLong GetSomeTimingField(); // vtable+3c; virtual MxLong GetCurrentTime(); // vtable+40; - void AppendData(MxU16 p_unkLength, const char *p_unkData); + void AppendData(MxU16 p_extraLength, const char *p_extraData); - inline MxU32 GetFlags() { return this->m_flags; } - inline void SetFlags(MxU32 m_flags) { this->m_flags = m_flags; } + inline MxU32 GetFlags() { return m_flags; } + inline void SetFlags(MxU32 p_flags) { m_flags = p_flags; } + inline char *GetExtraData() { return m_extraData; } + inline MxU16 GetExtraLength() const { return m_extraLength; } + 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 void SetOmni(MxOmni *p_omni) { m_omni = p_omni; } + + 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; - DWORD m_startTime; + MxLong m_startTime; protected: MxLong m_duration; @@ -63,11 +80,13 @@ class MxDSAction : public MxDSObject MxVector3Data m_location; MxVector3Data m_direction; MxVector3Data m_up; - char *m_unkData; - MxU16 m_unkLength; + char *m_extraData; + MxU16 m_extraLength; undefined4 m_unk84; undefined4 m_unk88; MxOmni *m_omni; // 0x8c + +protected: MxLong m_someTimingField; // 0x90 }; diff --git a/LEGO1/mxdsactionlist.cpp b/LEGO1/mxdsactionlist.cpp new file mode 100644 index 00000000..46eb4e36 --- /dev/null +++ b/LEGO1/mxdsactionlist.cpp @@ -0,0 +1,22 @@ +#include "mxdsactionlist.h" +#include "mxdsaction.h" + +DECOMP_SIZE_ASSERT(MxDSActionList, 0x1c); +DECOMP_SIZE_ASSERT(MxDSActionListCursor, 0x10); + +// OFFSET: LEGO1 0x100c9c90 +MxS8 MxDSActionList::Compare(MxDSAction *p_var0, MxDSAction *p_var1) +{ + if (p_var1 == p_var0) + return 0; + if (p_var1 <= p_var0) + return 1; + return -1; +} + +// OFFSET: LEGO1 0x100c9cb0 +void MxDSActionList::Destroy(MxDSAction *p_action) +{ + if (p_action) + delete p_action; +} \ No newline at end of file diff --git a/LEGO1/mxdsactionlist.h b/LEGO1/mxdsactionlist.h new file mode 100644 index 00000000..fe0e162c --- /dev/null +++ b/LEGO1/mxdsactionlist.h @@ -0,0 +1,37 @@ +#ifndef MXDSACTIONLIST_H +#define MXDSACTIONLIST_H + +#include "decomp.h" +#include "mxlist.h" + +class MxDSAction; + +// VTABLE 0x100dced8 +// SIZE 0x1c +class MxDSActionList : public MxList +{ +public: + MxDSActionList() { + this->m_unk18 = 0; + } + + virtual MxS8 Compare(MxDSAction *, MxDSAction *); // +0x14 + + static void Destroy(MxDSAction *p_action); + +private: + undefined m_unk18; +}; + +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/mxdsanim.h b/LEGO1/mxdsanim.h index 92890e8e..1bc77558 100644 --- a/LEGO1/mxdsanim.h +++ b/LEGO1/mxdsanim.h @@ -27,7 +27,7 @@ class MxDSAnim : public MxDSMediaAction return !strcmp(name, MxDSAnim::ClassName()) || MxDSMediaAction::IsA(name); } - virtual MxDSAction *Clone(); // vtable+2c; + virtual MxDSAction *Clone() override; // vtable+2c; }; #endif // MXDSANIM_H diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp new file mode 100644 index 00000000..686627a4 --- /dev/null +++ b/LEGO1/mxdsbuffer.cpp @@ -0,0 +1,13 @@ +#include "mxdsbuffer.h" + +// OFFSET: LEGO1 0x100c6470 +MxDSBuffer::MxDSBuffer() +{ + // TODO +} + +// OFFSET: LEGO1 0x100c6530 +MxDSBuffer::~MxDSBuffer() +{ + // TODO +} diff --git a/LEGO1/mxdsbuffer.h b/LEGO1/mxdsbuffer.h new file mode 100644 index 00000000..cb962cea --- /dev/null +++ b/LEGO1/mxdsbuffer.h @@ -0,0 +1,20 @@ +#ifndef MXDSBUFFER_H +#define MXDSBUFFER_H + +#include "decomp.h" +#include "mxcore.h" + +// VTABLE 0x100dcca0 +// SIZE 0x34 +class MxDSBuffer : public MxCore +{ +public: + MxDSBuffer(); + virtual ~MxDSBuffer() override; + +private: + undefined m_unk08[0x2C]; + +}; + +#endif // MXDSBUFFER_H diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index f9b1d9d0..367dcb4d 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/mxdschunk.h @@ -1,7 +1,6 @@ #ifndef MXDSCHUNK_H #define MXDSCHUNK_H - #include "mxcore.h" #include "mxtypes.h" diff --git a/LEGO1/mxdsevent.h b/LEGO1/mxdsevent.h index b8fedace..576c8b14 100644 --- a/LEGO1/mxdsevent.h +++ b/LEGO1/mxdsevent.h @@ -25,7 +25,7 @@ class MxDSEvent : public MxDSMediaAction return !strcmp(name, MxDSEvent::ClassName()) || MxDSMediaAction::IsA(name); } - virtual MxDSAction *Clone(); // vtable+2c; + virtual MxDSAction *Clone() override; // vtable+2c; }; #endif // MXDSEVENT_H diff --git a/LEGO1/mxdsfile.cpp b/LEGO1/mxdsfile.cpp index 8bccf914..d1c87032 100644 --- a/LEGO1/mxdsfile.cpp +++ b/LEGO1/mxdsfile.cpp @@ -47,13 +47,13 @@ MxLong MxDSFile::Open(MxULong uStyle) } // OFFSET: LEGO1 0x100cc780 -MxLong MxDSFile::Read(unsigned char *pch, MxULong cch) +MxResult MxDSFile::Read(unsigned char *p_buf, MxULong p_nbytes) { - if (m_io.Read((char*)pch, cch) != cch) - return -1; + if (m_io.Read(p_buf, p_nbytes) != p_nbytes) + return FAILURE; - m_position += cch; - return 0; + m_position += p_nbytes; + return SUCCESS; } // OFFSET: LEGO1 0x100cc620 @@ -72,7 +72,7 @@ MxLong MxDSFile::ReadChunks() return -1; } - m_io.Read((char*)&m_header, 0xc); + m_io.Read(&m_header, 0xc); if ((m_header.majorVersion == SI_MAJOR_VERSION) && (m_header.minorVersion == SI_MINOR_VERSION)) { childChunk.ckid = FOURCC('M', 'x', 'O', 'f'); @@ -80,9 +80,9 @@ MxLong MxDSFile::ReadChunks() return -1; } MxULong* pLengthInDWords = &m_lengthInDWords; - m_io.Read((char *)pLengthInDWords, 4); - m_pBuffer = malloc(*pLengthInDWords * 4); - m_io.Read((char*)m_pBuffer, *pLengthInDWords * 4); + m_io.Read(pLengthInDWords, 4); + m_pBuffer = new MxU32[*pLengthInDWords]; + m_io.Read(m_pBuffer, *pLengthInDWords * 4); return 0; } else @@ -120,7 +120,7 @@ MxLong MxDSFile::Close() if (m_lengthInDWords != 0) { m_lengthInDWords = 0; - free(m_pBuffer); + delete[] m_pBuffer; m_pBuffer = NULL; } return 0; diff --git a/LEGO1/mxdsfile.h b/LEGO1/mxdsfile.h index ac812df7..d46a6153 100644 --- a/LEGO1/mxdsfile.h +++ b/LEGO1/mxdsfile.h @@ -4,6 +4,7 @@ #include "mxdssource.h" #include "mxioinfo.h" #include "mxstring.h" +#include "mxtypes.h" // VTABLE 0x100dc890 class MxDSFile : public MxDSSource @@ -27,7 +28,7 @@ class MxDSFile : public MxDSSource __declspec(dllexport) virtual MxLong Open(MxULong); // vtable+0x14 __declspec(dllexport) virtual MxLong Close(); // vtable+0x18 - __declspec(dllexport) virtual MxLong Read(unsigned char *,MxULong); // vtable+0x20 + __declspec(dllexport) virtual MxResult Read(unsigned char *,MxULong); // vtable+0x20 __declspec(dllexport) virtual MxLong Seek(MxLong,int); // vtable+0x24 __declspec(dllexport) virtual MxULong GetBufferSize(); // vtable+0x28 __declspec(dllexport) virtual MxULong GetStreamBuffersNum(); // vtable+0x2c diff --git a/LEGO1/mxdsmediaaction.cpp b/LEGO1/mxdsmediaaction.cpp index d368aa3d..125156d7 100644 --- a/LEGO1/mxdsmediaaction.cpp +++ b/LEGO1/mxdsmediaaction.cpp @@ -1,13 +1,15 @@ #include "mxdsmediaaction.h" +#include "legoutil.h" + DECOMP_SIZE_ASSERT(MxDSMediaAction, 0xb8) // OFFSET: LEGO1 0x100c8b40 MxDSMediaAction::MxDSMediaAction() { this->m_mediaSrcPath = NULL; - this->m_unk9c = 0; - this->m_unka0 = 0; + this->m_unk9c.m_unk00 = 0; + this->m_unk9c.m_unk04 = 0; this->m_framesPerSecond = 0; this->m_mediaFormat = 0; this->m_paletteManagement = 1; @@ -27,10 +29,7 @@ void MxDSMediaAction::CopyFrom(MxDSMediaAction &p_dsMediaAction) { CopyMediaSrcPath(p_dsMediaAction.m_mediaSrcPath); - // TODO this->m_unk9c = p_dsMediaAction.m_unk9c; - this->m_unka0 = p_dsMediaAction.m_unka0; - this->m_framesPerSecond = p_dsMediaAction.m_framesPerSecond; this->m_mediaFormat = p_dsMediaAction.m_mediaFormat; this->m_paletteManagement = p_dsMediaAction.m_paletteManagement; @@ -68,21 +67,13 @@ void MxDSMediaAction::Deserialize(char **p_source, MxS16 p_unk24) { MxDSAction::Deserialize(p_source, p_unk24); - CopyMediaSrcPath(*p_source); - *p_source += strlen(this->m_mediaSrcPath) + 1; - - this->m_unk9c = *(undefined4*) *p_source; - *p_source += sizeof(undefined4); - this->m_unka0 = *(undefined4*) *p_source; - *p_source += sizeof(undefined4); - this->m_framesPerSecond = *(MxS32*) *p_source; - *p_source += sizeof(MxS32); - this->m_mediaFormat = *(MxS32*) *p_source; - *p_source += sizeof(MxS32); - this->m_paletteManagement = *(MxS32*) *p_source; - *p_source += sizeof(MxS32); - this->m_sustainTime = *(MxLong*) *p_source; - *p_source += sizeof(MxLong); + GetString(p_source, this->m_mediaSrcPath, this, &MxDSMediaAction::CopyMediaSrcPath); + GetScalar(p_source, this->m_unk9c.m_unk00); + GetScalar(p_source, this->m_unk9c.m_unk04); + GetScalar(p_source, this->m_framesPerSecond); + GetScalar(p_source, this->m_mediaFormat); + GetScalar(p_source, this->m_paletteManagement); + GetScalar(p_source, this->m_sustainTime); } // OFFSET: LEGO1 0x100c8e80 diff --git a/LEGO1/mxdsmediaaction.h b/LEGO1/mxdsmediaaction.h index 1ebbfdd2..a6303227 100644 --- a/LEGO1/mxdsmediaaction.h +++ b/LEGO1/mxdsmediaaction.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "mxdsaction.h" +#include "mxpoint32.h" // VTABLE 0x100dcd40 // SIZE 0xb8 @@ -28,15 +29,20 @@ class MxDSMediaAction : public MxDSAction return !strcmp(name, MxDSMediaAction::ClassName()) || MxDSAction::IsA(name); } - virtual MxU32 GetSizeOnDisk(); // vtable+18; - virtual void Deserialize(char **p_source, MxS16 p_unk24); // vtable+1c; + virtual MxU32 GetSizeOnDisk() override; // vtable+18; + virtual void Deserialize(char **p_source, MxS16 p_unk24) override; // vtable+1c; void CopyMediaSrcPath(const char *p_mediaSrcPath); + + inline MxS32 GetMediaFormat() const { return this->m_mediaFormat; } + inline MxLong GetSustainTime() const { return this->m_sustainTime; } private: MxU32 m_sizeOnDisk; char *m_mediaSrcPath; - undefined4 m_unk9c; - undefined4 m_unka0; + struct { + undefined4 m_unk00; + undefined4 m_unk04; + } m_unk9c; MxS32 m_framesPerSecond; MxS32 m_mediaFormat; MxS32 m_paletteManagement; diff --git a/LEGO1/mxdsmultiaction.cpp b/LEGO1/mxdsmultiaction.cpp index 4188fb66..2580b813 100644 --- a/LEGO1/mxdsmultiaction.cpp +++ b/LEGO1/mxdsmultiaction.cpp @@ -1,14 +1,154 @@ #include "mxdsmultiaction.h" +DECOMP_SIZE_ASSERT(MxDSMultiAction, 0x9c) + // OFFSET: LEGO1 0x100c9b90 MxDSMultiAction::MxDSMultiAction() { - // TODO this->SetType(MxDSType_MultiAction); + this->m_actions = new MxDSActionList; + this->m_actions->SetDestroy(MxDSActionList::Destroy); } -// OFFSET: LEGO1 0x100ca060 STUB +// OFFSET: LEGO1 0x100ca060 MxDSMultiAction::~MxDSMultiAction() { - // TODO + if (this->m_actions) + delete this->m_actions; } + +// OFFSET: LEGO1 0x100ca0d0 +void MxDSMultiAction::CopyFrom(MxDSMultiAction &p_dsMultiAction) +{ + this->m_actions->DeleteAll(); + + MxDSActionListCursor cursor(p_dsMultiAction.m_actions); + MxDSAction *action; + while (cursor.Next(action)) + this->m_actions->Append(action->Clone()); +} + +// OFFSET: LEGO1 0x100ca260 +MxDSMultiAction &MxDSMultiAction::operator=(MxDSMultiAction &p_dsMultiAction) +{ + if (this == &p_dsMultiAction) + return *this; + + MxDSAction::operator=(p_dsMultiAction); + this->CopyFrom(p_dsMultiAction); + return *this; +} + +// OFFSET: LEGO1 0x100ca290 +void MxDSMultiAction::SetSomeTimingField(MxLong p_someTimingField) +{ + this->m_someTimingField = p_someTimingField; + + MxDSActionListCursor cursor(this->m_actions); + MxDSAction *action; + while (cursor.Next(action)) + action->SetSomeTimingField(p_someTimingField); +} + +// OFFSET: LEGO1 0x100ca370 +void MxDSMultiAction::MergeFrom(MxDSAction &p_dsMultiAction) +{ + MxDSAction::MergeFrom(p_dsMultiAction); + + MxDSActionListCursor cursor(this->m_actions); + MxDSAction *action; + while (cursor.Next(action)) + action->MergeFrom(p_dsMultiAction); +} + +// OFFSET: LEGO1 0x100ca450 +MxBool MxDSMultiAction::HasId(MxU32 p_objectId) +{ + if (this->GetObjectId() == p_objectId) + return TRUE; + + MxDSActionListCursor cursor(this->m_actions); + MxDSAction *action; + while (cursor.Next(action)) { + if (action->HasId(p_objectId)) + return TRUE; + } + + return FALSE; +} + +// OFFSET: LEGO1 0x100ca550 +MxDSAction *MxDSMultiAction::Clone() +{ + MxDSMultiAction *clone = new MxDSMultiAction(); + + if (clone) + *clone = *this; + + return clone; +} + +// OFFSET: LEGO1 0x100ca5e0 +undefined4 MxDSMultiAction::unk14() +{ + undefined4 result = MxDSAction::unk14(); + + MxDSActionListCursor cursor(this->m_actions); + MxDSAction *action; + while (cursor.Next(action)) + result += action->unk14(); + + return result; +} + +// OFFSET: LEGO1 0x100ca6c0 +MxU32 MxDSMultiAction::GetSizeOnDisk() +{ + MxU32 totalSizeOnDisk = MxDSAction::GetSizeOnDisk() + 16; + + MxDSActionListCursor cursor(this->m_actions); + MxDSAction *action; + while (cursor.Next(action)) + totalSizeOnDisk += action->GetSizeOnDisk(); + + this->m_sizeOnDisk = totalSizeOnDisk - MxDSAction::GetSizeOnDisk(); + + return totalSizeOnDisk; +} + +// OFFSET: LEGO1 0x100ca7b0 +void MxDSMultiAction::Deserialize(char **p_source, MxS16 p_unk24) +{ + MxDSAction::Deserialize(p_source, p_unk24); + + MxU32 extraFlag = *(MxU32*)(*p_source + 4) & 1; + *p_source += 12; + + MxU32 count = *(MxU32*) *p_source; + *p_source += sizeof(count); + + if (count) { + while (count--) { + MxU32 extraFlag = *(MxU32*)(*p_source + 4) & 1; + *p_source += 8; + + MxDSAction *action = (MxDSAction*) DeserializeDSObjectDispatch(p_source, p_unk24); + *p_source += extraFlag; + + this->m_actions->Append(action); + } + } + + *p_source += extraFlag; +} + +// OFFSET: LEGO1 0x100ca8c0 +void MxDSMultiAction::SetAtomId(MxAtomId p_atomId) +{ + MxDSAction::SetAtomId(p_atomId); + + MxDSActionListCursor cursor(this->m_actions); + MxDSAction *action; + while (cursor.Next(action)) + action->SetAtomId(p_atomId); +} \ No newline at end of file diff --git a/LEGO1/mxdsmultiaction.h b/LEGO1/mxdsmultiaction.h index af3d69df..4e516333 100644 --- a/LEGO1/mxdsmultiaction.h +++ b/LEGO1/mxdsmultiaction.h @@ -2,6 +2,7 @@ #define MXDSMULTIACTION_H #include "mxdsaction.h" +#include "mxdsactionlist.h" // VTABLE 0x100dcef0 // SIZE 0x9c @@ -11,6 +12,9 @@ class MxDSMultiAction : public MxDSAction MxDSMultiAction(); virtual ~MxDSMultiAction() override; + void CopyFrom(MxDSMultiAction &p_dsMultiAction); + MxDSMultiAction &operator=(MxDSMultiAction &p_dsMultiAction); + // OFFSET: LEGO1 0x100c9f50 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -23,6 +27,19 @@ class MxDSMultiAction : public MxDSAction { return !strcmp(name, MxDSMultiAction::ClassName()) || MxDSAction::IsA(name); } + + virtual undefined4 unk14() override; // vtable+14; + virtual MxU32 GetSizeOnDisk() override; // vtable+18; + virtual void Deserialize(char **p_source, MxS16 p_unk24) override; // vtable+1c; + virtual void SetAtomId(MxAtomId p_atomId) override; // vtable+20; + virtual MxDSAction *Clone() override; // vtable+2c; + virtual void MergeFrom(MxDSAction &p_dsAction) override; // vtable+30; + virtual MxBool HasId(MxU32 p_objectId) override; // vtable+34; + virtual void SetSomeTimingField(MxLong p_someTimingField) override; // vtable+38; + +protected: + MxU32 m_sizeOnDisk; + MxDSActionList *m_actions; }; #endif // MXDSMULTIACTION_H diff --git a/LEGO1/mxdsobject.cpp b/LEGO1/mxdsobject.cpp index 57663cee..f508c53b 100644 --- a/LEGO1/mxdsobject.cpp +++ b/LEGO1/mxdsobject.cpp @@ -3,6 +3,20 @@ #include #include +#include "mxdstypes.h" +#include "mxdsaction.h" +#include "mxdsmediaaction.h" +#include "mxdsanim.h" +#include "mxdssound.h" +#include "mxdsmultiaction.h" +#include "mxdsserialaction.h" +#include "mxdsparallelaction.h" +#include "mxdsevent.h" +#include "mxdsselectaction.h" +#include "mxdsstill.h" +#include "mxdsobjectaction.h" +#include "legoutil.h" + DECOMP_SIZE_ASSERT(MxDSObject, 0x2c); // OFFSET: LEGO1 0x100bf6a0 @@ -115,15 +129,66 @@ MxU32 MxDSObject::GetSizeOnDisk() // OFFSET: LEGO1 0x100bfa20 void MxDSObject::Deserialize(char **p_source, MxS16 p_unk24) { - this->SetSourceName(*p_source); - *p_source += strlen(this->m_sourceName) + 1; - this->m_unk14 = *(undefined4*) *p_source; - *p_source += sizeof(undefined4); - - this->SetObjectName(*p_source); - *p_source += strlen(this->m_objectName) + 1; - this->m_objectId = *(MxU32*) *p_source; - *p_source += sizeof(MxU32); + GetString(p_source, this->m_sourceName, this, &MxDSObject::SetSourceName); + GetScalar(p_source, this->m_unk14); + GetString(p_source, this->m_objectName, this, &MxDSObject::SetObjectName); + GetScalar(p_source, this->m_objectId); this->m_unk24 = p_unk24; } + +// OFFSET: LEGO1 0x100bfb30 +MxDSObject *DeserializeDSObjectDispatch(char **p_source, MxS16 p_flags) +{ + MxU16 type = *(MxU16*) *p_source; + *p_source += 2; + + MxDSObject *obj = NULL; + + switch (type) { + default: + return NULL; + case MxDSType_Object: + obj = new MxDSObject(); + break; + case MxDSType_Action: + obj = new MxDSAction(); + break; + case MxDSType_MediaAction: + obj = new MxDSMediaAction(); + break; + case MxDSType_Anim: + obj = new MxDSAnim(); + break; + case MxDSType_Sound: + obj = new MxDSSound(); + break; + case MxDSType_MultiAction: + obj = new MxDSMultiAction(); + break; + case MxDSType_SerialAction: + obj = new MxDSSerialAction(); + break; + case MxDSType_ParallelAction: + obj = new MxDSParallelAction(); + break; + case MxDSType_Event: + obj = new MxDSEvent(); + break; + case MxDSType_SelectAction: + obj = new MxDSSelectAction(); + break; + case MxDSType_Still: + obj = new MxDSStill(); + break; + case MxDSType_ObjectAction: + obj = new MxDSObjectAction(); + break; + } + + if (obj) { + obj->Deserialize(p_source, p_flags); + } + + return obj; +} \ No newline at end of file diff --git a/LEGO1/mxdsobject.h b/LEGO1/mxdsobject.h index c46ee609..cfb5d6a1 100644 --- a/LEGO1/mxdsobject.h +++ b/LEGO1/mxdsobject.h @@ -36,24 +36,28 @@ class MxDSObject : public MxCore inline const MxAtomId& GetAtomId() { return this->m_atomId; } inline MxU32 GetObjectId() { return this->m_objectId; } + inline MxS16 GetUnknown24() { return this->m_unk24; } inline void SetObjectId(MxU32 p_objectId) { this->m_objectId = p_objectId; } inline void SetUnknown24(MxS16 p_unk24) { this->m_unk24 = p_unk24; } -protected: + inline char *GetSourceName() const { return this->m_sourceName; } + inline void SetType(MxDSType p_type) { this->m_type = p_type; } - inline MxDSType GetType() { return (MxDSType) this->m_type; } + inline MxDSType GetType() const { return (MxDSType) this->m_type; } private: - MxU32 m_sizeOnDisk; - MxU16 m_type; - char* m_sourceName; - undefined4 m_unk14; - char *m_objectName; - MxU32 m_objectId; - MxAtomId m_atomId; - MxS16 m_unk24; - undefined4 m_unk28; + MxU32 m_sizeOnDisk; // 0x8 + MxU16 m_type; // 0xc + char* m_sourceName; // 0x10 + undefined4 m_unk14; // 0x14 + char *m_objectName; // 0x18 + MxU32 m_objectId; // 0x1c + MxAtomId m_atomId; // 0x20 + MxS16 m_unk24; // 0x24 + undefined4 m_unk28; // 0x28 }; +MxDSObject *DeserializeDSObjectDispatch(char **, MxS16); + #endif // MXDSOBJECT_H diff --git a/LEGO1/mxdsobjectaction.h b/LEGO1/mxdsobjectaction.h index 4a1b68bb..07f35758 100644 --- a/LEGO1/mxdsobjectaction.h +++ b/LEGO1/mxdsobjectaction.h @@ -26,7 +26,7 @@ class MxDSObjectAction : public MxDSMediaAction return !strcmp(name, MxDSObjectAction::ClassName()) || MxDSMediaAction::IsA(name); } - virtual MxDSAction *Clone(); // vtable+2c; + virtual MxDSAction *Clone() override; // vtable+2c; virtual void CopyFrom(MxDSObjectAction &p_dsObjectAction); // vtable+44; }; diff --git a/LEGO1/mxdsparallelaction.cpp b/LEGO1/mxdsparallelaction.cpp index 97a8a9d3..564e39c6 100644 --- a/LEGO1/mxdsparallelaction.cpp +++ b/LEGO1/mxdsparallelaction.cpp @@ -1,4 +1,7 @@ #include "mxdsparallelaction.h" +#include "mxdsmediaaction.h" + +DECOMP_SIZE_ASSERT(MxDSParallelAction, 0x9c) // OFFSET: LEGO1 0x100cae80 MxDSParallelAction::MxDSParallelAction() @@ -10,3 +13,74 @@ MxDSParallelAction::MxDSParallelAction() MxDSParallelAction::~MxDSParallelAction() { } + +// OFFSET: LEGO1 0x100cb090 +void MxDSParallelAction::CopyFrom(MxDSParallelAction &p_dsParallelAction) +{ +} + +// OFFSET: LEGO1 0x100cb0a0 +MxDSParallelAction &MxDSParallelAction::operator=(MxDSParallelAction &p_dsParallelAction) +{ + if (this == &p_dsParallelAction) + return *this; + + MxDSMultiAction::operator=(p_dsParallelAction); + this->CopyFrom(p_dsParallelAction); + return *this; +} + +// OFFSET: LEGO1 0x100cb0d0 +MxDSAction *MxDSParallelAction::Clone() +{ + MxDSParallelAction *clone = new MxDSParallelAction(); + + if (clone) + *clone = *this; + + return clone; +} + +// OFFSET: LEGO1 0x100cb160 +MxLong MxDSParallelAction::GetDuration() +{ + if (this->m_duration) + return this->m_duration; + + MxDSActionListCursor cursor(this->m_actions); + MxDSAction *action; + + while (cursor.Next(action)) { + if (!action) + continue; + + MxLong duration = action->GetDuration(); + if (duration == -1) { + this->m_duration = -1; + break; + } + + duration += action->GetStartTime(); + if (action->IsA("MxDSMediaAction")) { + MxLong sustainTime = ((MxDSMediaAction*) action)->GetSustainTime(); + + if (sustainTime == -1) + duration = -1; + else if (sustainTime) + duration += sustainTime; + } + + if (duration == -1) { + this->m_duration = -1; + break; + } + + if (this->m_duration < duration) + this->m_duration = duration; + } + + if (this->IsBit3()) + this->m_duration *= this->m_loopCount; + + return this->m_duration; +} \ No newline at end of file diff --git a/LEGO1/mxdsparallelaction.h b/LEGO1/mxdsparallelaction.h index 067dc82c..e28bfe58 100644 --- a/LEGO1/mxdsparallelaction.h +++ b/LEGO1/mxdsparallelaction.h @@ -11,6 +11,9 @@ class MxDSParallelAction : public MxDSMultiAction MxDSParallelAction(); virtual ~MxDSParallelAction() override; + void CopyFrom(MxDSParallelAction &p_dsParallelAction); + MxDSParallelAction &operator=(MxDSParallelAction &p_dsParallelAction); + // OFFSET: LEGO1 0x100caf00 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -24,6 +27,8 @@ class MxDSParallelAction : public MxDSMultiAction return !strcmp(name, MxDSParallelAction::ClassName()) || MxDSMultiAction::IsA(name); } + virtual MxLong GetDuration() override; // vtable+24; + virtual MxDSAction *Clone() override; // vtable+2c; }; #endif // MXDSPARALLELACTION_H diff --git a/LEGO1/mxdsselectaction.cpp b/LEGO1/mxdsselectaction.cpp index 5cae82fb..e49f587a 100644 --- a/LEGO1/mxdsselectaction.cpp +++ b/LEGO1/mxdsselectaction.cpp @@ -1,14 +1,131 @@ #include "mxdsselectaction.h" +#include "mxvariabletable.h" +#include "mxtimer.h" +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(MxDSSelectAction, 0xb0) // OFFSET: LEGO1 0x100cb2b0 MxDSSelectAction::MxDSSelectAction() { - // TODO this->SetType(MxDSType_SelectAction); + this->m_unk0xac = new MxStringList; } -// OFFSET: LEGO1 0x100cb8d0 STUB +// OFFSET: LEGO1 0x100cb8d0 MxDSSelectAction::~MxDSSelectAction() { - // TODO + if (this->m_unk0xac) + delete this->m_unk0xac; } + +// OFFSET: LEGO1 0x100cb950 +void MxDSSelectAction::CopyFrom(MxDSSelectAction &p_dsSelectAction) +{ + this->m_unk0x9c = p_dsSelectAction.m_unk0x9c; + + this->m_unk0xac->DeleteAll(); + + MxStringListCursor cursor(p_dsSelectAction.m_unk0xac); + MxString string; + while (cursor.Next(string)) + this->m_unk0xac->OtherAppend(string); +} + +// OFFSET: LEGO1 0x100cbd50 +MxDSSelectAction &MxDSSelectAction::operator=(MxDSSelectAction &p_dsSelectAction) +{ + if (this != &p_dsSelectAction) { + MxDSParallelAction::operator=(p_dsSelectAction); + this->CopyFrom(p_dsSelectAction); + } + return *this; +} + +// OFFSET: LEGO1 0x100cbd80 +MxDSAction *MxDSSelectAction::Clone() +{ + MxDSSelectAction *clone = new MxDSSelectAction(); + + if (clone) + *clone = *this; + + return clone; +} + +// OFFSET: LEGO1 0x100cbe10 +MxU32 MxDSSelectAction::GetSizeOnDisk() +{ + MxU32 totalSizeOnDisk = MxDSParallelAction::GetSizeOnDisk(); + + totalSizeOnDisk += strlen(this->m_unk0x9c.GetData()) + 1; + + MxStringListCursor cursor(this->m_unk0xac); + MxString string; + while (cursor.Next(string)) + totalSizeOnDisk += strlen(string.GetData()) + 1; + + // Note: unlike the other classes, MxDSSelectAction does not have its own + // sizeOnDisk member. Instead, it overrides the one from MxDSMultiAction. + this->m_sizeOnDisk = totalSizeOnDisk; + + return totalSizeOnDisk; +} + +// OFFSET: LEGO1 0x100cbf60 +void MxDSSelectAction::Deserialize(char **p_source, MxS16 p_unk24) +{ + MxString string; + MxDSAction::Deserialize(p_source, p_unk24); + + MxU32 extraFlag = *(MxU32*)(*p_source + 4) & 1; + *p_source += 12; + + this->m_unk0x9c = *p_source; + + if (!strnicmp(this->m_unk0x9c.GetData(), "RANDOM_", strlen("RANDOM_"))) { + char buffer[10]; + MxS16 value = atoi(&this->m_unk0x9c.GetData()[strlen("RANDOM_")]); + + srand(Timer()->GetTime()); + MxS32 random = rand() % value; + string = itoa((MxS16) random, buffer, 10); + } + else + string = VariableTable()->GetVariable(*p_source); + + *p_source += strlen(*p_source) + 1; + + MxU32 count = *(MxU32*) *p_source; + *p_source += sizeof(MxU32); + + if (count) { + MxS32 index = -1; + this->m_unk0xac->DeleteAll(); + + MxU32 i; + for (i = 0; i < count; i++) { + if (!strcmp(string.GetData(), *p_source)) + index = i; + + this->m_unk0xac->OtherAppend(*p_source); + *p_source += strlen(*p_source) + 1; + } + + for (i = 0; i < count; i++) { + MxU32 extraFlag = *(MxU32*)(*p_source + 4) & 1; + *p_source += 8; + + MxDSAction *action = (MxDSAction*) DeserializeDSObjectDispatch(p_source, p_unk24); + + if (index == i) + this->m_actions->Append(action); + else + delete action; + + *p_source += extraFlag; + } + } + + *p_source += extraFlag; +} \ No newline at end of file diff --git a/LEGO1/mxdsselectaction.h b/LEGO1/mxdsselectaction.h index cb5374e1..7b668a15 100644 --- a/LEGO1/mxdsselectaction.h +++ b/LEGO1/mxdsselectaction.h @@ -2,6 +2,8 @@ #define MXDSSELECTACTION_H #include "mxdsparallelaction.h" +#include "mxstringlist.h" +#include "decomp.h" // VTABLE 0x100dcfc8 // SIZE 0xb0 @@ -11,6 +13,9 @@ class MxDSSelectAction : public MxDSParallelAction MxDSSelectAction(); virtual ~MxDSSelectAction() override; + void CopyFrom(MxDSSelectAction &p_dsSelectAction); + MxDSSelectAction &operator=(MxDSSelectAction &p_dsSelectAction); + // OFFSET: LEGO1 0x100cb6f0 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -24,6 +29,13 @@ class MxDSSelectAction : public MxDSParallelAction return !strcmp(name, MxDSSelectAction::ClassName()) || MxDSParallelAction::IsA(name); } + virtual MxU32 GetSizeOnDisk() override; // vtable+18; + virtual void Deserialize(char **p_source, MxS16 p_unk24) override; // vtable+1c; + virtual MxDSAction *Clone() override; // vtable+2c; + +private: + MxString m_unk0x9c; + MxStringList *m_unk0xac; }; #endif // MXDSSELECTACTION_H diff --git a/LEGO1/mxdsserialaction.cpp b/LEGO1/mxdsserialaction.cpp index 46964208..7196b1b7 100644 --- a/LEGO1/mxdsserialaction.cpp +++ b/LEGO1/mxdsserialaction.cpp @@ -1,14 +1,80 @@ #include "mxdsserialaction.h" +#include "mxdsmediaaction.h" + +DECOMP_SIZE_ASSERT(MxDSSerialAction, 0xa8) // OFFSET: LEGO1 0x100ca9d0 MxDSSerialAction::MxDSSerialAction() { - // TODO this->SetType(MxDSType_SerialAction); + this->m_cursor = new MxDSActionListCursor(this->m_actions); + this->m_unk0xa0 = 0; } -// OFFSET: LEGO1 0x100cac10 STUB +// OFFSET: LEGO1 0x100caac0 +void MxDSSerialAction::SetDuration(MxLong p_duration) +{ + this->m_duration = p_duration; +} + +// OFFSET: LEGO1 0x100cac10 MxDSSerialAction::~MxDSSerialAction() { - // TODO + if (this->m_cursor) + delete this->m_cursor; + + this->m_cursor = NULL; } + +// OFFSET: LEGO1 0x100cac90 +void MxDSSerialAction::CopyFrom(MxDSSerialAction &p_dsSerialAction) +{ +} + +// OFFSET: LEGO1 0x100caca0 +MxDSSerialAction &MxDSSerialAction::operator=(MxDSSerialAction &p_dsSerialAction) +{ + if (this == &p_dsSerialAction) + return *this; + + MxDSMultiAction::operator=(p_dsSerialAction); + this->CopyFrom(p_dsSerialAction); + return *this; +} + +// OFFSET: LEGO1 0x100cacd0 +MxDSAction *MxDSSerialAction::Clone() +{ + MxDSSerialAction *clone = new MxDSSerialAction(); + + if (clone) + *clone = *this; + + return clone; +} + +// OFFSET: LEGO1 0x100cad60 +MxLong MxDSSerialAction::GetDuration() +{ + if (this->m_duration) + return this->m_duration; + + MxDSActionListCursor cursor(this->m_actions); + MxDSAction *action; + + while (cursor.Next(action)) { + if (!action) + continue; + + this->m_duration += action->GetDuration() + action->GetStartTime(); + + if (action->IsA("MxDSMediaAction")) { + MxLong sustainTime = ((MxDSMediaAction*) action)->GetSustainTime(); + + if (sustainTime && sustainTime != -1) + this->m_duration += sustainTime; + } + } + + return this->m_duration; +} \ No newline at end of file diff --git a/LEGO1/mxdsserialaction.h b/LEGO1/mxdsserialaction.h index 2b260556..4e383681 100644 --- a/LEGO1/mxdsserialaction.h +++ b/LEGO1/mxdsserialaction.h @@ -2,6 +2,7 @@ #define MXDSSERIALACTION_H #include "mxdsmultiaction.h" +#include "decomp.h" // VTABLE 0x100dcf38 // SIZE 0xa8 @@ -11,6 +12,9 @@ class MxDSSerialAction : public MxDSMultiAction MxDSSerialAction(); virtual ~MxDSSerialAction() override; + void CopyFrom(MxDSSerialAction &p_dsSerialAction); + MxDSSerialAction &operator=(MxDSSerialAction &p_dsSerialAction); + // OFFSET: LEGO1 0x100caad0 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -23,6 +27,15 @@ class MxDSSerialAction : public MxDSMultiAction { return !strcmp(name, MxDSSerialAction::ClassName()) || MxDSMultiAction::IsA(name); } + + virtual MxLong GetDuration() override; // vtable+24; + virtual void SetDuration(MxLong p_duration) override; // vtable+28; + virtual MxDSAction *Clone() override; // vtable+2c; + +private: + MxDSActionListCursor *m_cursor; + undefined4 m_unk0xa0; + undefined4 m_unk0xa4; }; #endif // MXDSSERIALACTION_H diff --git a/LEGO1/mxdssound.cpp b/LEGO1/mxdssound.cpp index cbb1c057..ca69ef34 100644 --- a/LEGO1/mxdssound.cpp +++ b/LEGO1/mxdssound.cpp @@ -1,4 +1,5 @@ #include "mxdssound.h" +#include "legoutil.h" DECOMP_SIZE_ASSERT(MxDSSound, 0xc0) @@ -46,8 +47,7 @@ void MxDSSound::Deserialize(char **p_source, MxS16 p_unk24) { MxDSMediaAction::Deserialize(p_source, p_unk24); - this->m_volume = *(MxS32*) *p_source; - *p_source += sizeof(MxS32); + GetScalar(p_source, this->m_volume); } // OFFSET: LEGO1 0x100c9510 diff --git a/LEGO1/mxdssound.h b/LEGO1/mxdssound.h index de345e51..514ef1ec 100644 --- a/LEGO1/mxdssound.h +++ b/LEGO1/mxdssound.h @@ -27,9 +27,9 @@ class MxDSSound : public MxDSMediaAction return !strcmp(name, MxDSSound::ClassName()) || MxDSMediaAction::IsA(name); } - virtual MxU32 GetSizeOnDisk(); // vtable+18; - virtual void Deserialize(char **p_source, MxS16 p_unk24); // vtable+1c; - virtual MxDSAction *Clone(); // vtable+2c; + virtual MxU32 GetSizeOnDisk() override; // vtable+18; + virtual void Deserialize(char **p_source, MxS16 p_unk24) override; // vtable+1c; + virtual MxDSAction *Clone() override; // vtable+2c; private: MxU32 m_sizeOnDisk; diff --git a/LEGO1/mxdssource.cpp b/LEGO1/mxdssource.cpp index 9a94f110..86c4f9fb 100644 --- a/LEGO1/mxdssource.cpp +++ b/LEGO1/mxdssource.cpp @@ -11,4 +11,10 @@ void MxDSSource::SomethingWhichCallsRead(void* pUnknownObject) MxLong MxDSSource::GetLengthInDWords() { return m_lengthInDWords; +} + +// OFFSET: LEGO1 0x100c0000 +MxU32 *MxDSSource::GetBuffer() +{ + return m_pBuffer; } \ No newline at end of file diff --git a/LEGO1/mxdssource.h b/LEGO1/mxdssource.h index 5ff4c33c..626eaf37 100644 --- a/LEGO1/mxdssource.h +++ b/LEGO1/mxdssource.h @@ -29,15 +29,16 @@ class MxDSSource : public MxCore virtual MxLong Open(MxULong) = 0; virtual MxLong Close() = 0; virtual void SomethingWhichCallsRead(void* pUnknownObject); - virtual MxLong Read(unsigned char *, MxULong) = 0; + virtual MxResult Read(unsigned char *, MxULong) = 0; virtual MxLong Seek(MxLong, int) = 0; virtual MxULong GetBufferSize() = 0; virtual MxULong GetStreamBuffersNum() = 0; virtual MxLong GetLengthInDWords(); + virtual MxU32* GetBuffer(); // 0x34 protected: MxULong m_lengthInDWords; - void* m_pBuffer; + MxU32* m_pBuffer; MxLong m_position; }; diff --git a/LEGO1/mxdsstill.h b/LEGO1/mxdsstill.h index 084fe931..3b29c287 100644 --- a/LEGO1/mxdsstill.h +++ b/LEGO1/mxdsstill.h @@ -27,7 +27,7 @@ class MxDSStill : public MxDSMediaAction return !strcmp(name, MxDSStill::ClassName()) || MxDSMediaAction::IsA(name); } - virtual MxDSAction *Clone(); // vtable+2c; + virtual MxDSAction *Clone() override; // vtable+2c; }; #endif // MXDSSTILL_H diff --git a/LEGO1/mxdsstreamingaction.cpp b/LEGO1/mxdsstreamingaction.cpp index ab04c19e..665f079e 100644 --- a/LEGO1/mxdsstreamingaction.cpp +++ b/LEGO1/mxdsstreamingaction.cpp @@ -1,4 +1,5 @@ #include "mxdsstreamingaction.h" +#include "mxdsbuffer.h" DECOMP_SIZE_ASSERT(MxDSStreamingAction, 0xb4) @@ -22,7 +23,6 @@ MxDSStreamingAction::MxDSStreamingAction(MxDSStreamingAction &p_dsStreamingActio // OFFSET: LEGO1 0x100cd150 MxDSStreamingAction::~MxDSStreamingAction() { - // TODO: Implement MxDSBuffer if (this->m_unka0) delete this->m_unka0; if (this->m_unka4) diff --git a/LEGO1/mxdsstreamingaction.h b/LEGO1/mxdsstreamingaction.h index d50dbed8..f95621eb 100644 --- a/LEGO1/mxdsstreamingaction.h +++ b/LEGO1/mxdsstreamingaction.h @@ -24,7 +24,7 @@ class MxDSStreamingAction : public MxDSAction return *this; } - virtual MxBool HasId(MxU32 p_objectId); // vtable+34; + virtual MxBool HasId(MxU32 p_objectId) override; // vtable+34; MxResult Init(); void SetInternalAction(MxDSAction *p_dsAction); diff --git a/LEGO1/mxentity.cpp b/LEGO1/mxentity.cpp index 65adad67..585150f1 100644 --- a/LEGO1/mxentity.cpp +++ b/LEGO1/mxentity.cpp @@ -1,6 +1,6 @@ #include "mxentity.h" -DECOMP_SIZE_ASSERT(MxEntity, 0x68) +DECOMP_SIZE_ASSERT(MxEntity, 0x10) // OFFSET: LEGO1 0x1001d190 MxEntity::MxEntity() diff --git a/LEGO1/mxentity.h b/LEGO1/mxentity.h index 25e74d1b..44afd9c4 100644 --- a/LEGO1/mxentity.h +++ b/LEGO1/mxentity.h @@ -7,7 +7,7 @@ #include "mxtypes.h" // VTABLE 0x100d5390 -// SIZE 0x68 or less +// SIZE 0x10 class MxEntity : public MxCore { public: @@ -31,7 +31,6 @@ class MxEntity : public MxCore private: MxS32 m_mxEntityId; // 0x8 MxAtomId m_atom; // 0xc - undefined m_unk10[0x58]; }; #endif // MXENTITY_H diff --git a/LEGO1/mxeventmanager.cpp b/LEGO1/mxeventmanager.cpp index 5383c25a..0861af77 100644 --- a/LEGO1/mxeventmanager.cpp +++ b/LEGO1/mxeventmanager.cpp @@ -1,4 +1,8 @@ #include "mxeventmanager.h" +#include "mxcriticalsection.h" +#include "mxthread.h" +#include "mxticklemanager.h" +#include "mxomni.h" // OFFSET: LEGO1 0x100c0360 MxEventManager::MxEventManager() @@ -9,10 +13,54 @@ MxEventManager::MxEventManager() // OFFSET: LEGO1 0x100c03f0 MxEventManager::~MxEventManager() { - // TODO: MxMediaManager::TerminateThread call + TerminateThread(TRUE); } // OFFSET: LEGO1 0x100c0450 void MxEventManager::Init() { -} \ No newline at end of file + // This is intentionally left blank +} + +// OFFSET: LEGO1 0x100c04a0 +MxResult MxEventManager::CreateEventThread(MxU32 p_frequencyMS, MxBool p_noRegister) +{ + MxResult status = FAILURE; + MxBool locked = FALSE; + + MxResult result = MxMediaManager::InitPresenters(); + if (result == SUCCESS) + { + if (p_noRegister) + { + this->m_criticalSection.Enter(); + locked = TRUE; + this->m_thread = new MxTickleThread(this, p_frequencyMS); + + if (this->m_thread) + { + if (this->m_thread->Start(0, 0) == SUCCESS) + { + status = SUCCESS; + } + } + } + else + { + TickleManager()->RegisterClient(this, p_frequencyMS); + status = SUCCESS; + } + } + + if (status != SUCCESS) + { + Destroy(); + } + + if (locked) + { + this->m_criticalSection.Leave(); + } + + return status; +} diff --git a/LEGO1/mxeventmanager.h b/LEGO1/mxeventmanager.h index cb89f637..1ef43748 100644 --- a/LEGO1/mxeventmanager.h +++ b/LEGO1/mxeventmanager.h @@ -2,6 +2,7 @@ #define MXEVENTMANAGER_H #include "mxmediamanager.h" +#include "decomp.h" // VTABLE 0x100dc900 // SIZE 0x2c @@ -10,7 +11,7 @@ class MxEventManager : public MxMediaManager public: MxEventManager(); virtual ~MxEventManager() override; - + virtual MxResult CreateEventThread(MxU32 p_frequencyMS, MxBool p_noRegister); // vtable+28 private: void Init(); }; diff --git a/LEGO1/mxflcpresenter.cpp b/LEGO1/mxflcpresenter.cpp index 8bd23d22..79c1ae49 100644 --- a/LEGO1/mxflcpresenter.cpp +++ b/LEGO1/mxflcpresenter.cpp @@ -4,14 +4,18 @@ DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); -// OFFSET: LEGO1 0x100b3310 STUB +// OFFSET: LEGO1 0x100b3310 MxFlcPresenter::MxFlcPresenter() { - // TODO + this->m_unk64 = 0; + this->m_flags &= 0xfd; + this->m_flags &= 0xfb; } -// OFFSET: LEGO1 0x100b3420 STUB +// OFFSET: LEGO1 0x100b3420 MxFlcPresenter::~MxFlcPresenter() { - // TODO + if (this->m_unk64) { + delete this->m_unk64; + } } diff --git a/LEGO1/mxflcpresenter.h b/LEGO1/mxflcpresenter.h index bc34ff12..19535bcd 100644 --- a/LEGO1/mxflcpresenter.h +++ b/LEGO1/mxflcpresenter.h @@ -26,7 +26,7 @@ class MxFlcPresenter : public MxVideoPresenter return !strcmp(name, MxFlcPresenter::ClassName()) || MxVideoPresenter::IsA(name); } - undefined4 m_unk64; + undefined4 *m_unk64; }; #endif // MXFLCPRESENTER_H diff --git a/LEGO1/mxhashtable.h b/LEGO1/mxhashtable.h index f9505bb5..3d91717b 100644 --- a/LEGO1/mxhashtable.h +++ b/LEGO1/mxhashtable.h @@ -67,7 +67,7 @@ class MxHashTable : protected HashTableParent virtual ~MxHashTable(); void Resize(); - void MxHashTable::Add(T* ); + void Add(T* ); virtual MxS8 Compare(T*, T*) = 0; diff --git a/LEGO1/mxlist.h b/LEGO1/mxlist.h new file mode 100644 index 00000000..94798b33 --- /dev/null +++ b/LEGO1/mxlist.h @@ -0,0 +1,232 @@ +#ifndef MXLIST_H +#define MXLIST_H + +#include "mxtypes.h" +#include "mxcore.h" + +template +class MxListEntry +{ +public: + MxListEntry() {} + MxListEntry(T p_obj, MxListEntry *p_prev) { + m_obj = p_obj; + m_prev = p_prev; + m_next = NULL; + } + MxListEntry(T p_obj, MxListEntry *p_prev, MxListEntry *p_next) { + m_obj = p_obj; + m_prev = p_prev; + m_next = p_next; + } + + T GetValue() { return this->m_obj; } + + friend class MxList; + friend class MxListCursor; +private: + T m_obj; + MxListEntry *m_prev; + 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 +{ +public: + MxList() { + m_last = NULL; + m_first = NULL; + } + + virtual ~MxList(); + + void Append(T); + void OtherAppend(T p_obj) { _InsertEntry(p_obj, this->m_last, NULL); }; + void DeleteAll(); + MxU32 GetCount() { return m_count; } + void SetDestroy(void (*p_customDestructor)(T)) { this->m_customDestructor = p_customDestructor; } + + friend class MxListCursor; +protected: + MxListEntry *m_first; // +0x10 + MxListEntry *m_last; // +0x14 + +private: + void _DeleteEntry(MxListEntry *match); + void _InsertEntry(T, MxListEntry *, MxListEntry *); +}; + +template +class MxListCursor : public MxCore +{ +public: + MxListCursor(MxList *p_list) { + m_list = p_list; + m_match = NULL; + } + + MxBool Find(T p_obj); + void Detach(); + MxBool Next(T& p_obj); + void SetValue(T p_obj); + void Head() { m_match = m_list->m_first; } + void Reset() { m_match = NULL; } + +private: + MxList *m_list; + MxListEntry *m_match; +}; + +// Unclear purpose +template +class MxListCursorChild : public MxListCursor +{ +public: + MxListCursorChild(MxList *p_list) : MxListCursor(p_list) {} +}; + +// Unclear purpose +template +class MxListCursorChildChild : public MxListCursorChild +{ +public: + MxListCursorChildChild(MxList *p_list) : MxListCursorChild(p_list) {} +}; + +template +MxList::~MxList() +{ + DeleteAll(); +} + +template +inline void MxList::DeleteAll() +{ + for (MxListEntry *t = m_first;;) { + if (!t) + break; + + MxListEntry *next = t->m_next; + m_customDestructor(t->GetValue()); + delete t; + t = next; + } + + m_count = 0; + m_last = NULL; + m_first = NULL; +} + +template +inline void MxList::Append(T p_newobj) +{ + MxListEntry *currentLast = this->m_last; + MxListEntry *newEntry = new MxListEntry(p_newobj, currentLast); + + if (currentLast) + currentLast->m_next = newEntry; + else + this->m_first = newEntry; + + this->m_last = newEntry; + this->m_count++; +} + +template +inline void MxList::_InsertEntry(T p_newobj, MxListEntry *p_prev, MxListEntry *p_next) +{ + MxListEntry *newEntry = new MxListEntry(p_newobj, p_prev, p_next); + + if (p_prev) + p_prev->m_next = newEntry; + else + this->m_first = newEntry; + + if (p_next) + p_next->m_prev = newEntry; + else + this->m_last = newEntry; + + this->m_count++; +} + +template +inline void MxList::_DeleteEntry(MxListEntry *match) +{ + MxListEntry **pPrev = &match->m_prev; + MxListEntry **pNext = &match->m_next; + + if (match->m_prev) + match->m_prev->m_next = *pNext; + else + m_first = *pNext; + + if (*pNext) + (*pNext)->m_prev = *pPrev; + else + m_last = *pPrev; + + delete match; + m_count--; +} + +template +inline MxBool MxListCursor::Find(T p_obj) +{ + for (m_match = m_list->m_first; + m_match && m_list->Compare(m_match->m_obj, p_obj); + m_match = m_match->m_next); + + return m_match != NULL; +} + +template +inline void MxListCursor::Detach() +{ + m_list->_DeleteEntry(m_match); + m_match = NULL; +} + +template +inline MxBool MxListCursor::Next(T& p_obj) +{ + if (!m_match) + m_match = m_list->m_first; + else + m_match = m_match->m_next; + + if (m_match) + p_obj = m_match->GetValue(); + + return m_match != NULL; +} + +template +inline void MxListCursor::SetValue(T p_obj) +{ + if (m_match) + m_match->m_obj = p_obj; +} + +#endif // MXLIST_H diff --git a/LEGO1/mxloopingflcpresenter.cpp b/LEGO1/mxloopingflcpresenter.cpp index 041ae6a5..58b066f6 100644 --- a/LEGO1/mxloopingflcpresenter.cpp +++ b/LEGO1/mxloopingflcpresenter.cpp @@ -4,20 +4,28 @@ DECOMP_SIZE_ASSERT(MxLoopingFlcPresenter, 0x6c); -// OFFSET: LEGO1 0x100b4310 STUB +// OFFSET: LEGO1 0x100b4310 MxLoopingFlcPresenter::MxLoopingFlcPresenter() { - // TODO + Init(); } -// OFFSET: LEGO1 0x100b43b0 STUB +// OFFSET: LEGO1 0x100b43b0 MxLoopingFlcPresenter::~MxLoopingFlcPresenter() { - // TODO + Destroy(TRUE); } -// OFFSET: LEGO1 0x100b4410 STUB +// OFFSET: LEGO1 0x100b4410 void MxLoopingFlcPresenter::Init() { - // TODO + this->m_unk68 = 0; + this->m_flags &= 0xfd; + this->m_flags &= 0xfb; +} + +// OFFSET: LEGO1 0x100b4432 STUB +void MxLoopingFlcPresenter::Destroy(MxBool p_param) +{ + // TODO } diff --git a/LEGO1/mxloopingflcpresenter.h b/LEGO1/mxloopingflcpresenter.h index 1973c28e..209e2a53 100644 --- a/LEGO1/mxloopingflcpresenter.h +++ b/LEGO1/mxloopingflcpresenter.h @@ -22,6 +22,8 @@ class MxLoopingFlcPresenter : public MxFlcPresenter private: void Init(); + void Destroy(MxBool); + undefined4 m_unk68; }; diff --git a/LEGO1/mxloopingsmkpresenter.cpp b/LEGO1/mxloopingsmkpresenter.cpp index da9223df..f51e2750 100644 --- a/LEGO1/mxloopingsmkpresenter.cpp +++ b/LEGO1/mxloopingsmkpresenter.cpp @@ -10,14 +10,22 @@ MxLoopingSmkPresenter::MxLoopingSmkPresenter() Init(); } -// OFFSET: LEGO1 0x100b4950 STUB +// OFFSET: LEGO1 0x100b4950 MxLoopingSmkPresenter::~MxLoopingSmkPresenter() { - // TODO + Destroy(TRUE); } -// OFFSET: LEGO1 0x100b49b0 STUB +// OFFSET: LEGO1 0x100b49b0 void MxLoopingSmkPresenter::Init() { - // TODO + this->m_unk720 = 0; + this->m_flags &= 0xfd; + this->m_flags &= 0xfb; +} + +// OFFSET: LEGO1 0x100b49d0 STUB +void MxLoopingSmkPresenter::Destroy(MxBool p_bool) +{ + // TODO - theres a chain of destroy and free function calls here (FUN_100b4300 -> FUN_100b3900 -> FUN_100c5d40 -> function at 0x100b27b0) } diff --git a/LEGO1/mxloopingsmkpresenter.h b/LEGO1/mxloopingsmkpresenter.h index 8ca18d20..ae9cfa05 100644 --- a/LEGO1/mxloopingsmkpresenter.h +++ b/LEGO1/mxloopingsmkpresenter.h @@ -22,6 +22,8 @@ class MxLoopingSmkPresenter : public MxSmkPresenter private: void Init(); + void Destroy(MxBool); + undefined4 m_unk720; }; diff --git a/LEGO1/mxmatrix.cpp b/LEGO1/mxmatrix.cpp index 534db6a9..1cc3c550 100644 --- a/LEGO1/mxmatrix.cpp +++ b/LEGO1/mxmatrix.cpp @@ -111,21 +111,20 @@ void MxMatrix::EqualsMxProduct(const MxMatrix *p_a, const MxMatrix *p_b) EqualsDataProduct(p_a->m_data, p_b->m_data); } -// Just a placeholder matrix multiply implementation. I think the decomp will -// look roughly like this but it's not close to matching and won't be until -// an exact match is found given it's all loop and float crunching. -// OFFSET: LEGO1 0x100024d0 STUB +// OFFSET: LEGO1 0x100024d0 void MxMatrix::EqualsDataProduct(const float *p_a, const float *p_b) { + float *cur = m_data; for (int row = 0; row < 4; ++row) { for (int col = 0; col < 4; ++col) { - m_data[row * 4 + col] = 0.0f; + *cur = 0.0f; for (int k = 0; k < 4; ++k) { - m_data[row * 4 + col] += p_a[row * 4 + k] * p_b[k * 4 + col]; + *cur += p_a[row * 4 + k] * p_b[k * 4 + col]; } + cur++; } } } diff --git a/LEGO1/mxmediamanager.cpp b/LEGO1/mxmediamanager.cpp index a6c8a9c0..c992cd42 100644 --- a/LEGO1/mxmediamanager.cpp +++ b/LEGO1/mxmediamanager.cpp @@ -1,5 +1,9 @@ #include "mxmediamanager.h" +#include "mxautolocker.h" +#include "mxpresenter.h" #include "decomp.h" +#include "mxticklemanager.h" +#include "mxomni.h" DECOMP_SIZE_ASSERT(MxMediaManager, 0x2c); @@ -12,22 +16,105 @@ MxMediaManager::MxMediaManager() // OFFSET: LEGO1 0x100b8560 MxMediaManager::~MxMediaManager() { - Teardown(); + Destroy(); } // OFFSET: LEGO1 0x100b85d0 MxResult MxMediaManager::Init() { - this->m_unk08 = NULL; + this->m_presenters = NULL; this->m_thread = NULL; return SUCCESS; } -// OFFSET: LEGO1 0x100b8710 -void MxMediaManager::Teardown() +// OFFSET: LEGO1 0x100b8790 +MxResult MxMediaManager::Tickle() { - if(this->m_unk08) { - delete this->m_unk08; + MxAutoLocker lock(&this->m_criticalSection); + MxPresenter *presenter; + MxPresenterListCursor cursor(this->m_presenters); + + while (cursor.Next(presenter)) + presenter->Tickle(); + + cursor.Reset(); + + while (cursor.Next(presenter)) + presenter->PutData(); + + return SUCCESS; +} + +// OFFSET: LEGO1 0x100b85e0 +MxResult MxMediaManager::InitPresenters() +{ + MxAutoLocker lock(&this->m_criticalSection); + + this->m_presenters = new MxPresenterList; + + if (!this->m_presenters) { + this->Destroy(); + return FAILURE; } + + return SUCCESS; +} + +// OFFSET: LEGO1 0x100b8710 +void MxMediaManager::Destroy() +{ + MxAutoLocker lock(&this->m_criticalSection); + + if (this->m_presenters) + delete this->m_presenters; + Init(); -} \ No newline at end of file +} + +// OFFSET: LEGO1 0x100b88c0 +void MxMediaManager::AddPresenter(MxPresenter &p_presenter) +{ + MxAutoLocker lock(&this->m_criticalSection); + + this->m_presenters->Append(&p_presenter); +} + +// OFFSET: LEGO1 0x100b8980 +void MxMediaManager::RemovePresenter(MxPresenter &p_presenter) +{ + MxAutoLocker lock(&this->m_criticalSection); + MxPresenterListCursor cursor(this->m_presenters); + + if (cursor.Find(&p_presenter)) + cursor.Detach(); +} + +// OFFSET: LEGO1 0x100b8ac0 +void MxMediaManager::StopPresenters() +{ + MxAutoLocker lock(&this->m_criticalSection); + MxPresenter *presenter; + MxPresenterListCursor cursor(this->m_presenters); + + while (cursor.Next(presenter)) + presenter->EndAction(); +} + +// OFFSET: LEGO1 0x100c0460 +void MxMediaManager::TerminateThread(MxBool p_reinit) +{ + if(m_thread != NULL) + { + m_thread->Terminate(); + delete m_thread; + } + else + { + TickleManager()->UnregisterClient(this); + } + + if(!p_reinit) + { + MxMediaManager::Destroy(); + } +} diff --git a/LEGO1/mxmediamanager.h b/LEGO1/mxmediamanager.h index 76af63fb..c17ab300 100644 --- a/LEGO1/mxmediamanager.h +++ b/LEGO1/mxmediamanager.h @@ -4,22 +4,30 @@ #include "mxcore.h" #include "mxcriticalsection.h" #include "mxthread.h" +#include "mxpresenterlist.h" #include "mxtypes.h" // VTABLE 0x100dc6b0 +// SIZE 0x2c class MxMediaManager : public MxCore { public: MxMediaManager(); virtual ~MxMediaManager() override; + virtual MxResult Tickle() override; // vtable+08 + virtual MxResult InitPresenters(); // vtable+14 + virtual void Destroy(); // vtable+18 + virtual void AddPresenter(MxPresenter &p_presenter); // vtable+1c + virtual void RemovePresenter(MxPresenter &p_presenter); // vtable+20 + virtual void StopPresenters(); // vtable+24 + MxResult Init(); - void Teardown(); -private: - void* m_unk08; - MxThread* m_thread; // 0xc + void TerminateThread(MxBool p_reinit); protected: + MxPresenterList *m_presenters; + MxThread *m_thread; // 0xc MxCriticalSection m_criticalSection; // 0x10 }; diff --git a/LEGO1/mxmediapresenter.cpp b/LEGO1/mxmediapresenter.cpp index 58c068ac..00a2b851 100644 --- a/LEGO1/mxmediapresenter.cpp +++ b/LEGO1/mxmediapresenter.cpp @@ -2,15 +2,80 @@ DECOMP_SIZE_ASSERT(MxMediaPresenter, 0x50); +// OFFSET: LEGO1 0x1000c550 +MxMediaPresenter::~MxMediaPresenter() +{ + Destroy(TRUE); +} + // OFFSET: LEGO1 0x100b5d10 STUB -MxLong MxMediaPresenter::Tickle() +MxResult MxMediaPresenter::Tickle() { // TODO return 0; } -// OFFSET: LEGO1 0x100b54e0 STUB +// OFFSET: LEGO1 0x100b54e0 void MxMediaPresenter::Init() +{ + this->m_unk40 = NULL; + this->m_unk44 = NULL; + this->m_unk48 = NULL; + this->m_unk4c = NULL; +} + +// OFFSET: LEGO1 0x100b54f0 STUB +void MxMediaPresenter::Destroy(MxBool p_destroy) +{ + // TODO +} + +// OFFSET: LEGO1 0x100b5d90 STUB +void MxMediaPresenter::StreamingTickle() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b5e10 STUB +void MxMediaPresenter::RepeatingTickle() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b5ef0 +void MxMediaPresenter::DoneTickle() +{ + m_previousTickleStates |= 1 << m_currentTickleState; + m_currentTickleState = TickleState_Idle; + EndAction(); +} + +// OFFSET: LEGO1 0x100b6030 STUB +void MxMediaPresenter::Enable(MxBool p_enable) +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c5b0 +void MxMediaPresenter::InitVirtual() +{ + Destroy(FALSE); +} + +// OFFSET: LEGO1 0x100b5700 STUB +MxLong MxMediaPresenter::StartAction(MxStreamController * p_controller, MxDSAction * p_action) +{ + return 0; +} + +// OFFSET: LEGO1 0x100b5bc0 STUB +void MxMediaPresenter::EndAction() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b5f10 STUB +void MxMediaPresenter::VTable0x58() { // TODO } diff --git a/LEGO1/mxmediapresenter.h b/LEGO1/mxmediapresenter.h index 64de0614..6b8fd552 100644 --- a/LEGO1/mxmediapresenter.h +++ b/LEGO1/mxmediapresenter.h @@ -13,8 +13,9 @@ class MxMediaPresenter : public MxPresenter { Init(); } + virtual ~MxMediaPresenter() override; - virtual MxLong Tickle() override; // vtable+0x8, override MxCore + virtual MxResult Tickle() override; // OFFSET: LEGO1 0x1000c5c0 inline virtual const char *ClassName() const override // vtable+0xc @@ -29,10 +30,21 @@ class MxMediaPresenter : public MxPresenter return !strcmp(name, MxMediaPresenter::ClassName()) || MxPresenter::IsA(name); } + virtual void StreamingTickle() override; + virtual void RepeatingTickle() override; + virtual void DoneTickle() override; + virtual void InitVirtual() override; + virtual MxLong StartAction(MxStreamController *, MxDSAction *) override; + virtual void EndAction() override; + virtual void Enable(MxBool p_enable) override; + virtual void VTable0x58(); + undefined4 m_unk40; undefined4 m_unk44; undefined4 m_unk48; undefined4 m_unk4c; +protected: + void Destroy(MxBool); private: void Init(); diff --git a/LEGO1/mxmidipresenter.h b/LEGO1/mxmidipresenter.h index 1cd65c4a..07fc55a2 100644 --- a/LEGO1/mxmidipresenter.h +++ b/LEGO1/mxmidipresenter.h @@ -8,6 +8,20 @@ class MxMIDIPresenter : public MxMusicPresenter { public: MxMIDIPresenter(); + + // OFFSET: LEGO1 0x100c2650 + inline virtual const char *ClassName() const override // vtable+0xc + { + // 0x10101df8 + return "MxMIDIPresenter"; + } + + // OFFSET: LEGO1 0x100c2660 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, MxMIDIPresenter::ClassName()) || MxMusicPresenter::IsA(name); + } + private: void Init(); undefined4 m_unk54; diff --git a/LEGO1/mxmusicmanager.cpp b/LEGO1/mxmusicmanager.cpp new file mode 100644 index 00000000..6f49adcc --- /dev/null +++ b/LEGO1/mxmusicmanager.cpp @@ -0,0 +1,163 @@ +#include "mxmusicmanager.h" +#include "mxticklemanager.h" +#include "mxomni.h" + +#include + +DECOMP_SIZE_ASSERT(MxMusicManager, 0x58); + +// OFFSET: LEGO1 0x100c05a0 +MxMusicManager::MxMusicManager() +{ + Init(); +} + +// OFFSET: LEGO1 0x100c0630 +MxMusicManager::~MxMusicManager() +{ + LockedReinitialize(TRUE); +} + +// OFFSET: LEGO1 0x100c0b20 +void MxMusicManager::DeinitializeMIDI() +{ + m_criticalSection.Enter(); + + if (this->m_MIDIInitialized) + { + this->m_MIDIInitialized = FALSE; + midiStreamStop(this->m_MIDIStreamH); + midiOutUnprepareHeader(this->m_MIDIStreamH, this->m_MIDIHdrP, sizeof(MIDIHDR)); + midiOutSetVolume(this->m_MIDIStreamH, this->m_MIDIVolume); + midiStreamClose(this->m_MIDIStreamH); + delete this->m_MIDIHdrP; + this->InitData(); + } + + this->m_criticalSection.Leave(); +} + +// OFFSET: LEGO1 0x100c0690 +void MxMusicManager::Init() +{ + this->m_multiplier = 100; + InitData(); +} + +// OFFSET: LEGO1 0x100c06a0 +void MxMusicManager::InitData() +{ + this->m_MIDIStreamH = 0; + this->m_MIDIInitialized = FALSE; + this->m_unk38 = 0; + this->m_unk3c = 0; + this->m_unk40 = 0; + this->m_unk44 = 0; + this->m_unk48 = 0; + this->m_MIDIHdrP = NULL; +} + +// OFFSET: LEGO1 0x100c06c0 +void MxMusicManager::LockedReinitialize(MxBool p_skipDestroy) +{ + if (this->m_thread) + { + this->m_thread->Terminate(); + if (this->m_thread) + { + delete m_thread; + } + } + else + { + TickleManager()->UnregisterClient(this); + } + + this->m_criticalSection.Enter(); + DeinitializeMIDI(); + Init(); + this->m_criticalSection.Leave(); + + if (!p_skipDestroy) + { + MxAudioManager::Destroy(); + } +} + +// OFFSET: LEGO1 0x100c0930 +void MxMusicManager::Destroy() +{ + LockedReinitialize(FALSE); +} + +// OFFSET: LEGO1 0x100c09a0 +MxS32 MxMusicManager::CalculateVolume(MxS32 p_volume) +{ + MxS32 result = (p_volume * 0xffff) / 100; + return (result << 0x10) | result; +} + +// OFFSET: LEGO1 0x100c07f0 +void MxMusicManager::SetMIDIVolume() +{ + MxS32 result = (this->m_volume * this->m_multiplier) / 0x64; + HMIDISTRM streamHandle = this->m_MIDIStreamH; + + if (streamHandle) + { + MxS32 volume = CalculateVolume(result); + midiOutSetVolume(streamHandle, volume); + } +} + +// OFFSET: LEGO1 0x100c0940 +void MxMusicManager::SetVolume(MxS32 p_volume) +{ + MxAudioManager::SetVolume(p_volume); + this->m_criticalSection.Enter(); + SetMIDIVolume(); + this->m_criticalSection.Leave(); +} + +// OFFSET: LEGO1 0x100c0840 +MxResult MxMusicManager::StartMIDIThread(MxU32 p_frequencyMS, MxBool p_noRegister) +{ + MxResult status = FAILURE; + MxBool locked = FALSE; + + MxResult result = MxAudioManager::InitPresenters(); + if (result == SUCCESS) + { + if (p_noRegister) + { + this->m_criticalSection.Enter(); + locked = TRUE; + this->m_thread = new MxTickleThread(this, p_frequencyMS); + + if (this->m_thread) + { + if (this->m_thread->Start(0, 0) == SUCCESS) + { + status = SUCCESS; + } + } + } + else + { + TickleManager()->RegisterClient(this, p_frequencyMS); + status = SUCCESS; + } + } + + if (status != SUCCESS) + { + Destroy(); + } + + if (locked) + { + this->m_criticalSection.Leave(); + } + + return status; +} \ No newline at end of file diff --git a/LEGO1/mxmusicmanager.h b/LEGO1/mxmusicmanager.h index 4288ed1e..1a828c84 100644 --- a/LEGO1/mxmusicmanager.h +++ b/LEGO1/mxmusicmanager.h @@ -1,11 +1,42 @@ #ifndef MXMUSICMANAGER_H #define MXMUSICMANAGER_H -#include "mxcore.h" +#include "decomp.h" +#include "mxaudiomanager.h" // VTABLE 0x100dc930 -class MxMusicManager : public MxCore +// SIZE 0x58 +class MxMusicManager : public MxAudioManager { +public: + MxMusicManager(); + virtual ~MxMusicManager() override; + + virtual void Destroy() override; // vtable+18 + virtual void SetVolume(MxS32 p_volume) override; // vtable+2c + virtual MxResult StartMIDIThread(MxU32 p_frequencyMS, MxU8 p_noRegister); // vtable+30 + +private: + void LockedReinitialize(MxBool p_skipDestroy); + void DeinitializeMIDI(); + + MxS32 CalculateVolume(MxS32 p_volume); + void SetMIDIVolume(); + + HMIDISTRM m_MIDIStreamH; // 0x30 + MxBool m_MIDIInitialized; // 0x34 + undefined4 m_unk38; // 0x38 + undefined4 m_unk3c; // 0x3c + undefined4 m_unk40; // 0x40 + undefined4 m_unk44; // 0x44 + undefined4 m_unk48; // 0x48 + MIDIHDR *m_MIDIHdrP; // 0x4c + MxS32 m_multiplier; // 0x50 + DWORD m_MIDIVolume; // 0x54 + +protected: + void Init(); + void InitData(); }; -#endif // MXMUSICMANAGER_H +#endif // MXMUSICMANAGER_H \ No newline at end of file diff --git a/LEGO1/mxmusicpresenter.cpp b/LEGO1/mxmusicpresenter.cpp index 562f047c..f376c64f 100644 --- a/LEGO1/mxmusicpresenter.cpp +++ b/LEGO1/mxmusicpresenter.cpp @@ -1,7 +1,56 @@ #include "mxmusicpresenter.h" -// OFFSET: LEGO1 0x100c22c0 STUB +#include "decomp.h" +#include "mxmusicmanager.h" +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(MxMusicPresenter, 0x54); + +// OFFSET: LEGO1 0x100c22c0 MxMusicPresenter::MxMusicPresenter() { - // TODO -} \ No newline at end of file + Init(); +} + +// OFFSET: LEGO1 0x100c24e0 +MxMusicPresenter::~MxMusicPresenter() +{ + Destroy(TRUE); +} + +// OFFSET: LEGO1 0x100c2540 +void MxMusicPresenter::Init() +{ +} + +// OFFSET: LEGO1 0x100c2550 +void MxMusicPresenter::Destroy(MxBool p_reinit) +{ + if (MusicManager()) { + MusicManager()->RemovePresenter(*this); + } + m_criticalSection.Enter(); + Init(); + m_criticalSection.Leave(); + if (!p_reinit) { + MxMediaPresenter::Destroy(FALSE); + } +} + +// OFFSET: LEGO1 0x100c25a0 +MxResult MxMusicPresenter::AddToMusicManager() +{ + MxResult result = FAILURE; + if (MusicManager()) { + result = SUCCESS; + MusicManager()->AddPresenter(*this); + } + return result; +} + +// OFFSET: LEGO1 0x100c25d0 +void MxMusicPresenter::vtable38() +{ + // TODO: Name this function when we know what the argument to Destroy does + Destroy(FALSE); +} diff --git a/LEGO1/mxmusicpresenter.h b/LEGO1/mxmusicpresenter.h index e244b036..ff765786 100644 --- a/LEGO1/mxmusicpresenter.h +++ b/LEGO1/mxmusicpresenter.h @@ -4,10 +4,32 @@ #include "mxaudiopresenter.h" // VTABLE 0x100dc9b8 +// SIZE 0x54 class MxMusicPresenter : public MxAudioPresenter { public: + // OFFSET: LEGO1 0x100c23a0 + inline virtual const char *ClassName() const override // vtable+0xc + { + // 0x10101e48 + return "MxMusicPresenter"; + } + + // OFFSET: LEGO1 0x100c23b0 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, MxMusicPresenter::ClassName()) || MxAudioPresenter::IsA(name); + } + MxMusicPresenter(); + virtual ~MxMusicPresenter() override; + + virtual MxResult AddToMusicManager(); // vtable+0x34 + virtual void vtable38(); // vtable+0x38 + +private: + void Init(); + void Destroy(MxBool p_reinit); }; #endif // MXMUSICPRESENTER_H diff --git a/LEGO1/mxnotificationmanager.cpp b/LEGO1/mxnotificationmanager.cpp index fe48c7c2..017df73d 100644 --- a/LEGO1/mxnotificationmanager.cpp +++ b/LEGO1/mxnotificationmanager.cpp @@ -1,7 +1,8 @@ +#include "mxnotificationmanager.h" + #include "legoomni.h" #include "mxautolocker.h" -#include "mxcore.h" -#include "mxnotificationmanager.h" +#include "mxticklemanager.h" #include "mxparam.h" #include "mxtypes.h" @@ -12,7 +13,7 @@ DECOMP_SIZE_ASSERT(MxNotification, 0x8); DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40); // OFFSET: LEGO1 0x100ac220 -MxNotification::MxNotification(MxCore *p_target, MxParam *p_param) +MxNotification::MxNotification(MxCore *p_target, MxNotificationParam *p_param) { m_target = p_target; m_param = p_param->Clone(); @@ -160,7 +161,7 @@ void MxNotificationManager::FlushPending(MxCore *p_listener) } // OFFSET: LEGO1 0x100ac6c0 -MxResult MxNotificationManager::Send(MxCore *p_listener, MxParam *p_param) +MxResult MxNotificationManager::Send(MxCore *p_listener, MxNotificationParam *p_param) { MxAutoLocker lock(&m_lock); @@ -182,4 +183,4 @@ MxResult MxNotificationManager::Send(MxCore *p_listener, MxParam *p_param) } return FAILURE; -} +} \ No newline at end of file diff --git a/LEGO1/mxnotificationmanager.h b/LEGO1/mxnotificationmanager.h index 1c2aee7c..89908871 100644 --- a/LEGO1/mxnotificationmanager.h +++ b/LEGO1/mxnotificationmanager.h @@ -3,6 +3,7 @@ #include "mxcore.h" #include "mxcriticalsection.h" +#include "mxnotificationparam.h" #include "mxtypes.h" #include "compat.h" @@ -10,22 +11,15 @@ class MxNotification { public: - MxNotification(MxCore *p_target, MxParam *p_param); + MxNotification(MxCore *p_target, MxNotificationParam *p_param); ~MxNotification(); - inline MxCore *GetTarget() - { - return m_target; - } - - inline MxParam *GetParam() - { - return m_param; - } + inline MxCore *GetTarget() { return m_target; } + inline MxNotificationParam *GetParam() { return m_param; } private: MxCore *m_target; // 0x0 - MxParam *m_param; // 0x4 + MxNotificationParam *m_param; // 0x4 }; class MxIdList : public list @@ -54,7 +48,7 @@ class MxNotificationManager : public MxCore virtual MxResult Create(MxS32 p_unk1, MxS32 p_unk2); // vtable+0x14 void Register(MxCore *p_listener); void Unregister(MxCore *p_listener); - MxResult Send(MxCore *p_listener, MxParam *p_param); + MxResult Send(MxCore *p_listener, MxNotificationParam *p_param); private: void FlushPending(MxCore *p_listener); diff --git a/LEGO1/mxnotificationparam.cpp b/LEGO1/mxnotificationparam.cpp new file mode 100644 index 00000000..16a0b41f --- /dev/null +++ b/LEGO1/mxnotificationparam.cpp @@ -0,0 +1,11 @@ +#include "mxnotificationparam.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxNotificationParam, 0xc); + +// OFFSET: LEGO1 0x10010390 +MxNotificationParam* MxNotificationParam::Clone() +{ + return new MxNotificationParam(m_type, m_sender); +} diff --git a/LEGO1/mxnotificationparam.h b/LEGO1/mxnotificationparam.h new file mode 100644 index 00000000..a02f33d8 --- /dev/null +++ b/LEGO1/mxnotificationparam.h @@ -0,0 +1,35 @@ +#ifndef MXNOTIFICATIONPARAM_H +#define MXNOTIFICATIONPARAM_H + +#include "compat.h" +#include "mxparam.h" +#include "mxtypes.h" + +class MxCore; + +enum MxParamType +{ + MXSTREAMER_UNKNOWN = 2, + MXPRESENTER_NOTIFICATION = 5, + MXSTREAMER_DELETE_NOTIFY = 6, + MXTRANSITIONMANAGER_TRANSITIONENDED = 24 +}; + +// VTABLE 0x100d56e0 +class MxNotificationParam : public MxParam +{ +public: + inline MxNotificationParam(MxParamType p_type, MxCore *p_sender) : MxParam(), m_type(p_type), m_sender(p_sender){} + + virtual ~MxNotificationParam() override {} // vtable+0x0 (scalar deleting destructor) + virtual MxNotificationParam *Clone(); // vtable+0x4 + + inline MxParamType GetType() const { return m_type; } + inline MxCore *GetSender() const { return m_sender; } + +protected: + MxParamType m_type; // 0x4 + MxCore *m_sender; // 0x8 +}; + +#endif // MXNOTIFICATIONPARAM_H diff --git a/LEGO1/mxomni.cpp b/LEGO1/mxomni.cpp index 4048a0b5..43b9578a 100644 --- a/LEGO1/mxomni.cpp +++ b/LEGO1/mxomni.cpp @@ -1,5 +1,18 @@ #include "mxomni.h" +#include "mxatomidcounter.h" +#include "mxeventmanager.h" +#include "mxmusicmanager.h" +#include "mxnotificationmanager.h" +#include "mxobjectfactory.h" +#include "mxomnicreateparam.h" +#include "mxsoundmanager.h" +#include "mxstreamer.h" +#include "mxticklemanager.h" +#include "mxtimer.h" +#include "mxvideomanager.h" +#include "mxautolocker.h" + // 0x101015b8 char g_hdPath[1024]; @@ -39,7 +52,78 @@ void MxOmni::Init() m_timer = NULL; m_streamer = NULL; m_atomIdCounterSet = NULL; - m_unk64 = NULL; + m_timerRunning = NULL; +} + +// OFFSET: LEGO1 0x100b0090 +MxResult MxOmni::Start(MxDSAction* p_dsAction) +{ + MxResult result = FAILURE; + if(p_dsAction->GetAtomId().GetInternal() != NULL && p_dsAction->GetObjectId() != -1 && m_streamer != NULL) + { + result = m_streamer->Unknown100b99b0(p_dsAction); + } + + return result; +} + +// OFFSET: LEGO1 0x100b00c0 STUB +void MxOmni::DeleteObject(MxDSAction &ds) +{ + // TODO +} + +// OFFSET: LEGO1 0x100b09a0 STUB +MxBool MxOmni::DoesEntityExist(MxDSAction &ds) +{ + // TODO + return FALSE; +} + +// OFFSET: LEGO1 0x100b00e0 STUB +void MxOmni::vtable0x2c() +{ + // TODO +} + +// OFFSET: LEGO1 0x100aefb0 STUB +int MxOmni::vtable0x30(char*, int, MxCore*) +{ + // TODO + return 0; +} + +// OFFSET: LEGO1 0x100aefc0 +void MxOmni::NotifyCurrentEntity(MxParam *p_param) +{ +} + +// OFFSET: LEGO1 0x100b09d0 +void MxOmni::StartTimer() +{ + if (m_timerRunning == FALSE && m_timer != NULL && m_soundManager != NULL) + { + m_timer->Start(); + m_soundManager->vtable0x34(); + m_timerRunning = TRUE; + } +} + +// OFFSET: LEGO1 0x100b0a00 +void MxOmni::StopTimer() +{ + if (m_timerRunning != FALSE && m_timer != NULL && m_soundManager != NULL) + { + m_timer->Stop(); + m_soundManager->vtable0x38(); + m_timerRunning = FALSE; + } +} + +// OFFSET: LEGO1 0x10058a90 +MxBool MxOmni::IsTimerRunning() +{ + return m_timerRunning; } // OFFSET: LEGO1 0x100b0690 @@ -104,7 +188,22 @@ void MxOmni::SetInstance(MxOmni *instance) // OFFSET: LEGO1 0x100af0c0 MxResult MxOmni::Create(MxOmniCreateParam &p) { + MxResult result = FAILURE; m_atomIdCounterSet = new MxAtomIdCounterSet(); + if (m_atomIdCounterSet == NULL) + { + goto failure; + } + m_mediaPath = p.GetMediaPath(); + m_windowHandle = p.GetWindowHandle(); + if (p.CreateFlags().CreateObjectFactory()) + { + MxObjectFactory *objectFactory = new MxObjectFactory(); + this->m_objectFactory = objectFactory; + + if (objectFactory == NULL) + goto failure; + } if (p.CreateFlags().CreateVariableTable()) { @@ -112,7 +211,7 @@ MxResult MxOmni::Create(MxOmniCreateParam &p) this->m_variableTable = variableTable; if (variableTable == NULL) - return FAILURE; + goto failure; } if (p.CreateFlags().CreateTimer()) @@ -124,7 +223,87 @@ MxResult MxOmni::Create(MxOmniCreateParam &p) return FAILURE; } - return SUCCESS; + if (p.CreateFlags().CreateTickleManager()) + { + this->m_tickleManager = new MxTickleManager(); + + if (m_tickleManager == NULL) + goto failure; + } + + if (p.CreateFlags().CreateNotificationManager()) + { + MxNotificationManager *notificationManager = new MxNotificationManager(); + this->m_notificationManager = notificationManager; + + if (notificationManager == NULL || notificationManager->Create(100, 0) != SUCCESS) + goto failure; + } + + if (p.CreateFlags().CreateStreamer()) + { + MxStreamer *streamer = new MxStreamer(); + this->m_streamer = streamer; + + if (streamer == NULL || streamer->Init() != SUCCESS) + goto failure; + } + + if (p.CreateFlags().CreateVideoManager()) + { + MxVideoManager *videoManager = new MxVideoManager(); + this->m_videoManager = videoManager; + + if (videoManager != NULL && videoManager->vtable0x2c(p.GetVideoParam(), 100, 0) != SUCCESS) + { + delete m_videoManager; + m_videoManager = NULL; + } + } + + if (p.CreateFlags().CreateSoundManager()) + { + MxSoundManager *soundManager = new MxSoundManager(); + this->m_soundManager = soundManager; + + //TODO + if (soundManager != NULL && soundManager->StartDirectSound(10, 0) != SUCCESS) + { + delete m_soundManager; + m_soundManager = NULL; + } + } + + if (p.CreateFlags().CreateMusicManager()) + { + MxMusicManager *musicManager = new MxMusicManager(); + this->m_musicManager = musicManager; + if (musicManager != NULL && musicManager->StartMIDIThread(50, 0) != SUCCESS) + { + delete m_musicManager; + m_musicManager = NULL; + } + } + + if (p.CreateFlags().CreateEventManager()) + { + MxEventManager *eventManager = new MxEventManager(); + this->m_eventManager = eventManager; + if (m_eventManager != NULL && m_eventManager->CreateEventThread(50, 0) != SUCCESS) + { + delete m_eventManager; + m_eventManager = NULL; + } + } + + result = SUCCESS; + failure: + if (result != SUCCESS) + { + Destroy(); + } + + return result; } // OFFSET: LEGO1 0x100afe90 @@ -170,8 +349,19 @@ void MxOmni::Destroy() // OFFSET: LEGO1 0x100b07f0 MxLong MxOmni::Notify(MxParam &p) { - // FIXME: Stub - return 0; + MxAutoLocker lock(&this->m_criticalsection); + + if (((MxNotificationParam&) p).GetType() != MXSTREAMER_UNKNOWN) + return 0; + + return HandleNotificationType2(p); +} + +// OFFSET: LEGO1 0x100b0880 STUB +MxResult MxOmni::HandleNotificationType2(MxParam& p_param) +{ + // TODO STUB + return FAILURE; } // OFFSET: LEGO1 0x100acea0 @@ -208,7 +398,7 @@ MxAtomIdCounterSet *AtomIdCounterSet() MxStreamer* Streamer() { return MxOmni::GetInstance()->GetStreamer(); -} +} // OFFSET: LEGO1 0x100acf00 MxSoundManager* MSoundManager() diff --git a/LEGO1/mxomni.h b/LEGO1/mxomni.h index bbaf4cb0..265db29b 100644 --- a/LEGO1/mxomni.h +++ b/LEGO1/mxomni.h @@ -1,20 +1,23 @@ #ifndef MXOMNI_H #define MXOMNI_H +#include "mxcore.h" +#include "mxstring.h" #include "mxcriticalsection.h" -#include "mxeventmanager.h" -#include "mxmusicmanager.h" -#include "mxnotificationmanager.h" -#include "mxobjectfactory.h" -#include "mxomnicreateflags.h" -#include "mxomnicreateparam.h" -#include "mxsoundmanager.h" -#include "mxstreamer.h" -#include "mxticklemanager.h" -#include "mxtimer.h" -#include "mxvariabletable.h" -#include "mxvideomanager.h" -#include "mxatomidcounter.h" + +class MxAtomIdCounterSet; +class MxDSAction; +class MxEventManager; +class MxMusicManager; +class MxNotificationManager; +class MxObjectFactory; +class MxOmniCreateParam; +class MxSoundManager; +class MxStreamer; +class MxTickleManager; +class MxTimer; +class MxVariableTable; +class MxVideoManager; // VTABLE 0x100dc168 // SIZE 0x68 @@ -33,10 +36,19 @@ class MxOmni : public MxCore MxOmni(); virtual ~MxOmni() override; - virtual MxLong Notify(MxParam &p); // vtable+04 + virtual MxLong Notify(MxParam &p) override; // vtable+04 virtual void Init(); // vtable+14 - virtual MxResult Create(MxOmniCreateParam &p); // vtable+18 + virtual MxResult Create(COMPAT_CONST MxOmniCreateParam &p); // vtable+18 virtual void Destroy(); // vtable+1c + virtual MxResult Start(MxDSAction* p_dsAction); // vtable+20 + virtual void DeleteObject(MxDSAction &ds); // vtable+24 + virtual MxBool DoesEntityExist(MxDSAction &ds); // vtable+28 + virtual void vtable0x2c(); // vtable+2c + virtual int vtable0x30(char*, int, MxCore*); // vtable+30 + virtual void NotifyCurrentEntity(MxParam *p_param); // vtable+34 + virtual void StartTimer(); // vtable+38 + virtual void StopTimer(); // vtable+3c + virtual MxBool IsTimerRunning(); //vtable+40 static void SetInstance(MxOmni* instance); HWND GetWindowHandle() const { return this->m_windowHandle; } MxObjectFactory* GetObjectFactory() const { return this->m_objectFactory; } @@ -50,6 +62,7 @@ class MxOmni : public MxCore MxMusicManager* GetMusicManager() const { return this->m_musicManager; } MxEventManager* GetEventManager() const { return this->m_eventManager; } MxAtomIdCounterSet* GetAtomIdCounterSet() const { return this->m_atomIdCounterSet; } + MxResult HandleNotificationType2(MxParam& p_param); protected: static MxOmni* g_instance; @@ -70,7 +83,7 @@ class MxOmni : public MxCore MxCriticalSection m_criticalsection; // 0x48 - unsigned char m_unk64; // 0x64 + MxBool m_timerRunning; // 0x64 }; __declspec(dllexport) MxTickleManager * TickleManager(); __declspec(dllexport) MxTimer * Timer(); diff --git a/LEGO1/mxomnicreateparam.h b/LEGO1/mxomnicreateparam.h index 31dcd447..d4984b24 100644 --- a/LEGO1/mxomnicreateparam.h +++ b/LEGO1/mxomnicreateparam.h @@ -4,16 +4,19 @@ #include #include "mxomnicreateflags.h" -#include "mxomnicreateparambase.h" +#include "mxparam.h" #include "mxstring.h" #include "mxvideoparam.h" -class MxOmniCreateParam : public MxOmniCreateParamBase +class MxOmniCreateParam : public MxParam { public: __declspec(dllexport) MxOmniCreateParam(const char *mediaPath, struct HWND__ *windowHandle, MxVideoParam &vparam, MxOmniCreateFlags flags); const MxOmniCreateFlags& CreateFlags() const { return this->m_createFlags; } + const MxString GetMediaPath() const { return m_mediaPath; } + const HWND GetWindowHandle() const { return m_windowHandle; } + MxVideoParam& GetVideoParam() { return m_videoParam; } private: MxString m_mediaPath; diff --git a/LEGO1/mxomnicreateparambase.cpp b/LEGO1/mxomnicreateparambase.cpp deleted file mode 100644 index 0091785d..00000000 --- a/LEGO1/mxomnicreateparambase.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "mxomnicreateparam.h" diff --git a/LEGO1/mxomnicreateparambase.h b/LEGO1/mxomnicreateparambase.h deleted file mode 100644 index 605f4d30..00000000 --- a/LEGO1/mxomnicreateparambase.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MXOMNICREATEPARAMBASE_H -#define MXOMNICREATEPARAMBASE_H - -// FIXME: Clearly not its real name -class MxOmniCreateParamBase -{ -public: - virtual ~MxOmniCreateParamBase(){} - -}; - -#endif // MXOMNICREATEPARAMBASE_H diff --git a/LEGO1/mxpalette.cpp b/LEGO1/mxpalette.cpp index 7fb02f4f..cdd1597f 100644 --- a/LEGO1/mxpalette.cpp +++ b/LEGO1/mxpalette.cpp @@ -1,5 +1,7 @@ #include "mxpalette.h" + #include "mxomni.h" +#include "mxvideomanager.h" // GLOBAL: LEGO1 0x10102188 0x400 PALETTEENTRY g_defaultPaletteEntries[256] = diff --git a/LEGO1/mxpalette.h b/LEGO1/mxpalette.h index b024330a..7c9568b1 100644 --- a/LEGO1/mxpalette.h +++ b/LEGO1/mxpalette.h @@ -26,6 +26,7 @@ class MxPalette : public MxCore MxResult SetSkyColor(LPPALETTEENTRY p_sky_color); void Reset(MxBool p_ignoreSkyColor); LPDIRECTDRAWPALETTE CreateNativePalette(); + inline void SetOverrideSkyColor(MxBool p_value) { this->m_overrideSkyColor = p_value; } private: LPDIRECTDRAWPALETTE m_palette; PALETTEENTRY m_entries[256]; // 0xc diff --git a/LEGO1/mxparam.cpp b/LEGO1/mxparam.cpp index d7bb36b2..4faa1625 100644 --- a/LEGO1/mxparam.cpp +++ b/LEGO1/mxparam.cpp @@ -1,11 +1 @@ #include "mxparam.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(MxParam, 0xc); - -// OFFSET: LEGO1 0x10010390 -MxParam* MxParam::Clone() -{ - return new MxParam(m_type, m_sender); -} diff --git a/LEGO1/mxparam.h b/LEGO1/mxparam.h index c4150ff7..8f89e2d0 100644 --- a/LEGO1/mxparam.h +++ b/LEGO1/mxparam.h @@ -1,33 +1,10 @@ #ifndef MXPARAM_H #define MXPARAM_H -#include "mxomnicreateparambase.h" -#include "mxtypes.h" - -class MxCore; - -// VTABLE 0x100d56e0 -class MxParam : public MxOmniCreateParamBase +class MxParam { public: - inline MxParam(MxS32 p_type, MxCore *p_sender) : MxOmniCreateParamBase(), m_type(p_type), m_sender(p_sender){} - - virtual ~MxParam(){}; // vtable+0x0 (scalar deleting destructor) - virtual MxParam *Clone(); // vtable+0x4 - - inline MxS32 GetType() const - { - return m_type; - } - - inline MxCore *GetSender() const - { - return m_sender; - } - -private: - MxS32 m_type; // 0x4 - MxCore *m_sender; // 0x8 + virtual ~MxParam() {} }; #endif // MXPARAM_H diff --git a/LEGO1/mxpoint32.h b/LEGO1/mxpoint32.h new file mode 100755 index 00000000..cc0f6327 --- /dev/null +++ b/LEGO1/mxpoint32.h @@ -0,0 +1,20 @@ +#ifndef MXPOINT32_H +#define MXPOINT32_H + +#include "mxtypes.h" + +class MxPoint32 +{ +public: + MxPoint32() { } + MxPoint32(MxS32 p_x, MxS32 p_y) + { + this->m_x = p_x; + this->m_y = p_y; + } + + MxS32 m_x; + MxS32 m_y; +}; + +#endif // MXPOINT32_H diff --git a/LEGO1/mxpresenter.cpp b/LEGO1/mxpresenter.cpp index 5fbdb8e4..86e4ae26 100644 --- a/LEGO1/mxpresenter.cpp +++ b/LEGO1/mxpresenter.cpp @@ -1,7 +1,17 @@ #include "mxpresenter.h" -#include "mxautolocker.h" +#include "legoomni.h" +#include "mxautolocker.h" +#include "mxparam.h" +#include "mxdsanim.h" +#include "mxdssound.h" +#include "mxnotificationmanager.h" +#include "mxactionnotificationparam.h" +#include "mxstreamer.h" #include "decomp.h" +#include "define.h" + +#include DECOMP_SIZE_ASSERT(MxPresenter, 0x40); @@ -10,17 +20,57 @@ void MxPresenter::Init() { m_currentTickleState = TickleState_Idle; m_action = NULL; - m_unk0x18 = 0; - m_unk0x3c = 0; + m_location = MxPoint32(0, 0); + m_displayZ = 0; + m_unkPresenter = NULL; m_previousTickleStates = 0; - m_unk0x10 = 0; - m_unk0x14 = 0; } -// OFFSET: LEGO1 0x100b4fc0 STUB +// OFFSET: LEGO1 0x100b4fc0 void MxPresenter::ParseExtra() { - // TODO + + MxAutoLocker lock(&m_criticalSection); + MxU32 len = m_action->GetExtraLength(); + char *extraData = m_action->GetExtraData(); + + if (len) { + len &= MAXWORD; + char extraCopy[512]; + memcpy(extraCopy, extraData, len); + extraCopy[len] = '\0'; + + char t_worldValue[512]; + if (KeyValueStringParse(t_worldValue, g_strWORLD, extraCopy)) { + char *token = strtok(t_worldValue, g_parseExtraTokens); + char t_token[256]; + strcpy(t_token, token); + + token = strtok(NULL, g_parseExtraTokens); + int val = token ? atoi(token) : 0; + + int result = MxOmni::GetInstance()->vtable0x30(t_token, val, this); + + m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Parsed); + + if (result) + SendTo_unkPresenter(MxOmni::GetInstance()); + + } + } +} + +// OFFSET: LEGO1 0x100b5120 +void MxPresenter::SendTo_unkPresenter(MxOmni *p_omni) +{ + if (m_unkPresenter) { + MxAutoLocker lock(&m_criticalSection); + + NotificationManager()->Send(m_unkPresenter, &MxNotificationParam(MXPRESENTER_NOTIFICATION, this)); + + m_action->SetOmni(p_omni ? p_omni : MxOmni::GetInstance()); + m_unkPresenter = NULL; + } } // OFFSET: LEGO1 0x1000bf00 @@ -29,7 +79,7 @@ MxPresenter::~MxPresenter() } // OFFSET: LEGO1 0x100b5200 -MxLong MxPresenter::Tickle() +MxResult MxPresenter::Tickle() { MxAutoLocker lock(&this->m_criticalSection); @@ -65,21 +115,42 @@ MxLong MxPresenter::Tickle() break; } - return 0; + return SUCCESS; } -// OFFSET: LEGO1 0x100b4d80 STUB -MxLong MxPresenter::StartAction(MxStreamController *, MxDSAction *) +// OFFSET: LEGO1 0x100b4d80 +MxLong MxPresenter::StartAction(MxStreamController *, MxDSAction *p_action) { - // TODO + MxAutoLocker lock(&this->m_criticalSection); - return 0; + this->m_action = p_action; + + const MxVector3Data& location = this->m_action->GetLocation(); + MxS32 previousTickleState = this->m_currentTickleState; + + this->m_location = MxPoint32(location[0], location[1]); + this->m_displayZ = location[2]; + this->m_previousTickleStates |= 1 << (unsigned char)previousTickleState; + this->m_currentTickleState = TickleState_Ready; + + return SUCCESS; } -// OFFSET: LEGO1 0x100b4e40 STUB +// OFFSET: LEGO1 0x100b4e40 void MxPresenter::EndAction() { - // TODO + if (this->m_action == FALSE) + return; + MxAutoLocker lock(&this->m_criticalSection); + if (!this->m_unkPresenter) + { + MxOmni::GetInstance()->NotifyCurrentEntity(&MxEndActionNotificationParam(MXSTREAMER_UNKNOWN, NULL, this->m_action, TRUE)); + } + + this->m_action = FALSE; + MxS32 previousTickleState = 1 << m_currentTickleState; + this->m_previousTickleStates |= previousTickleState; + this->m_currentTickleState = TickleState_Idle; } // OFFSET: LEGO1 0x100b52d0 @@ -95,6 +166,63 @@ void MxPresenter::Enable(MxBool p_enable) } } +// OFFSET: LEGO1 0x100b5310 +char *PresenterNameDispatch(const MxDSAction &p_action) +{ + char *name = p_action.GetSourceName(); + MxS32 format; + + if (!name || strlen(name) == 0) { + switch (p_action.GetType()) { + case MxDSType_Anim: + format = ((MxDSAnim&)p_action).GetMediaFormat(); + switch (format) { + case FOURCC(' ', 'F', 'L', 'C'): + name = !p_action.IsLooping() ? + "MxFlcPresenter" : + "MxLoopingFlcPresenter"; + break; + case FOURCC(' ', 'S', 'M', 'K'): + name = !p_action.IsLooping() ? + "MxSmkPresenter" : + "MxLoopingSmkPresenter"; + break; + } + break; + + case MxDSType_Sound: + format = ((MxDSSound&)p_action).GetMediaFormat(); + switch(format) { + case FOURCC(' ', 'M', 'I', 'D'): + name = !p_action.IsLooping() ? + "MxMIDIPresenter" : + "MxLoopingMIDIPresenter"; + break; + case FOURCC(' ', 'W', 'A', 'V'): + name = "MxWavePresenter"; + break; + } + break; + + case MxDSType_SerialAction: + case MxDSType_ParallelAction: + case MxDSType_SelectAction: + name = "MxCompositePresenter"; + break; + + case MxDSType_Event: + name = "MxEventPresenter"; + break; + + case MxDSType_Still: + name = "MxStillPresenter"; + break; + } + } + + return name; +} + // OFFSET: LEGO1 0x100b54c0 MxBool MxPresenter::IsEnabled() { @@ -176,13 +304,13 @@ MxBool MxPresenter::HasTickleStatePassed(TickleState p_tickleState) } // OFFSET: LEGO1 0x1000bfc0 -undefined4 MxPresenter::VTable0x4c() +undefined4 MxPresenter::PutData() { return 0; } // OFFSET: LEGO1 0x1000bfd0 -undefined MxPresenter::VTable0x50(undefined4, undefined4) +MxBool MxPresenter::IsHit(MxS32 p_x, MxS32 p_y) { - return 0; + return FALSE; } diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index 6f50984e..bcdc5aac 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -2,8 +2,10 @@ #define MXPRESENTER_H #include "mxcore.h" +#include "mxpoint32.h" #include "mxdsaction.h" #include "mxcriticalsection.h" +#include "mxomni.h" #include "decomp.h" @@ -13,7 +15,7 @@ class MxStreamController; class MxPresenter : public MxCore { public: - enum TickleState + enum TickleState { TickleState_Idle = 0, TickleState_Ready, @@ -27,7 +29,7 @@ class MxPresenter : public MxCore MxPresenter() { Init(); } __declspec(dllexport) virtual ~MxPresenter(); // vtable+0x0 - __declspec(dllexport) virtual MxLong Tickle() override; // vtable+0x8 + __declspec(dllexport) virtual MxResult Tickle() override; // vtable+0x8 // OFFSET: LEGO1 0x1000bfe0 inline virtual const char *ClassName() const override// vtable+0xc @@ -60,24 +62,31 @@ class MxPresenter : public MxCore __declspec(dllexport) virtual void EndAction(); // vtable+0x40 virtual void SetTickleState(TickleState p_tickleState); // vtable+0x44 virtual MxBool HasTickleStatePassed(TickleState p_tickleState); // vtable+0x48 - virtual undefined4 VTable0x4c(); // vtable+0x4c - virtual undefined VTable0x50(undefined4, undefined4); // vtable+0x50 + virtual undefined4 PutData(); // vtable+0x4c + virtual MxBool IsHit(MxS32 p_x, MxS32 p_y); // vtable+0x50 __declspec(dllexport) virtual void Enable(MxBool p_enable); // vtable+0x54 MxBool IsEnabled(); + inline MxS32 GetCurrentTickleState() const { return this->m_currentTickleState; } + inline MxPoint32 GetLocation() const { return this->m_location; } + inline MxS32 GetLocationX() const { return this->m_location.m_x; } + inline MxS32 GetLocationY() const { return this->m_location.m_y; } + inline MxS32 GetDisplayZ() const { return this->m_displayZ; } + inline MxDSAction *GetAction() const { return this->m_action; } + protected: __declspec(dllexport) void Init(); - -private: - MxS32 m_currentTickleState; // 0x8 - MxU32 m_previousTickleStates; - undefined4 m_unk0x10; - undefined4 m_unk0x14; - undefined4 m_unk0x18; - MxDSAction* m_action; // 0 - MxCriticalSection m_criticalSection; - undefined4 m_unk0x3c; + void SendTo_unkPresenter(MxOmni *); + TickleState m_currentTickleState; // 0x8 + MxU32 m_previousTickleStates; // 0x0c + MxPoint32 m_location; // 0x10 + MxS32 m_displayZ; // 0x18 + MxDSAction *m_action; // 0x1c + MxCriticalSection m_criticalSection; // 0x20 + MxPresenter *m_unkPresenter; // 0x3c }; +char *PresenterNameDispatch(const MxDSAction &); + #endif // MXPRESENTER_H diff --git a/LEGO1/mxpresenterlist.cpp b/LEGO1/mxpresenterlist.cpp new file mode 100644 index 00000000..1edb6e12 --- /dev/null +++ b/LEGO1/mxpresenterlist.cpp @@ -0,0 +1,15 @@ +#include "mxpresenterlist.h" +#include "mxpresenter.h" + +DECOMP_SIZE_ASSERT(MxPresenterList, 0x18); +DECOMP_SIZE_ASSERT(MxPresenterListCursor, 0x10); + +// OFFSET: LEGO1 0x1001cd00 +MxS8 MxPresenterList::Compare(MxPresenter *p_var0, MxPresenter *p_var1) +{ + if (p_var1 == p_var0) + return 0; + if (p_var1 <= p_var0) + return 1; + return -1; +} diff --git a/LEGO1/mxpresenterlist.h b/LEGO1/mxpresenterlist.h new file mode 100644 index 00000000..0ee54a85 --- /dev/null +++ b/LEGO1/mxpresenterlist.h @@ -0,0 +1,38 @@ +#ifndef MXPRESENTERLIST_H +#define MXPRESENTERLIST_H + +#include "mxlist.h" + +class MxPresenter; + +// Unclear what the purpose of this class is +// VTABLE 0x100d62f0 +// SIZE 0x18 +class MxPresenterListParent : public MxList +{ +public: + MxPresenterListParent() { + m_customDestructor = Destroy; + } +}; + +// VTABLE 0x100d6308 +// SIZE 0x18 +class MxPresenterList : public MxPresenterListParent +{ +public: + virtual MxS8 Compare(MxPresenter *, MxPresenter *); // +0x14 +}; + +typedef MxListCursorChildChild MxPresenterListCursor; + +// OFFSET: LEGO1 0x1001cd20 TEMPLATE +// MxListParent::Compare + +// OFFSET: LEGO1 0x1001cd30 TEMPLATE +// MxListParent::Destroy + +// OFFSET: LEGO1 0x1001ce20 TEMPLATE +// MxList::~MxList + +#endif // MXPRESENTERLIST_H diff --git a/LEGO1/mxramstreamcontroller.cpp b/LEGO1/mxramstreamcontroller.cpp new file mode 100644 index 00000000..9796b05a --- /dev/null +++ b/LEGO1/mxramstreamcontroller.cpp @@ -0,0 +1,25 @@ +#include "mxramstreamcontroller.h" +#include "mxramstreamprovider.h" + +DECOMP_SIZE_ASSERT(MxRAMStreamController, 0x98); + +// OFFSET: LEGO1 0x100c6110 STUB +MxResult MxRAMStreamController::Open(const char *p_filename) +{ + // TODO STUB + return FAILURE; +} + +// OFFSET: LEGO1 0x100c6210 STUB +MxResult MxRAMStreamController::vtable0x20(MxDSAction* p_action) +{ + // TODO STUB + return FAILURE; +} + +// OFFSET: LEGO1 0x100c6320 STUB +MxResult MxRAMStreamController::vtable0x24(undefined4 p_unknown) +{ + // TODO STUB + return FAILURE; +} diff --git a/LEGO1/mxramstreamcontroller.h b/LEGO1/mxramstreamcontroller.h index 09915cbf..62587bca 100644 --- a/LEGO1/mxramstreamcontroller.h +++ b/LEGO1/mxramstreamcontroller.h @@ -1,11 +1,35 @@ #ifndef MXRAMSTREAMCONTROLLER_H #define MXRAMSTREAMCONTROLLER_H +#include "mxdsbuffer.h" #include "mxstreamcontroller.h" // VTABLE 0x100dc728 +// SIZE 0x98 class MxRAMStreamController : public MxStreamController { +public: + inline MxRAMStreamController() {} + + // OFFSET: LEGO1 0x100b9430 + inline virtual const char *ClassName() const override // vtable+0xc + { + // 0x10102130 + return "MxRAMStreamController"; + } + + // OFFSET: LEGO1 0x100b9440 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, MxRAMStreamController::ClassName()) || !strcmp(name, MxStreamController::ClassName()) || MxCore::IsA(name); + } + + virtual MxResult Open(const char *p_filename) override; + virtual MxResult vtable0x20(MxDSAction* p_action) override; + virtual MxResult vtable0x24(undefined4 p_unknown) override; + +private: + MxDSBuffer m_buffer; }; diff --git a/LEGO1/mxramstreamprovider.cpp b/LEGO1/mxramstreamprovider.cpp new file mode 100644 index 00000000..1b44d84f --- /dev/null +++ b/LEGO1/mxramstreamprovider.cpp @@ -0,0 +1,59 @@ +#include "mxramstreamprovider.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxRAMStreamProvider, 0x24); + +// OFFSET: LEGO1 0x100d0730 +MxRAMStreamProvider::MxRAMStreamProvider() +{ + m_bufferSize = 0; + m_fileSize = 0; + m_pBufferOfFileSize = NULL; + m_lengthInDWords = 0; + m_bufferForDWords = NULL; +} + +// OFFSET: LEGO1 0x100d0a50 +MxRAMStreamProvider::~MxRAMStreamProvider() +{ + m_bufferSize = 0; + m_fileSize = 0; + + free(m_pBufferOfFileSize); + m_pBufferOfFileSize = NULL; + + m_lengthInDWords = 0; + + free(m_bufferForDWords); + m_bufferForDWords = NULL; +} + +// OFFSET: LEGO1 0x100d0ae0 STUB +MxResult MxRAMStreamProvider::SetResourceToGet(void* p_resource) +{ + return FAILURE; +} + +// OFFSET: LEGO1 0x100d0930 +MxU32 MxRAMStreamProvider::GetFileSize() +{ + return m_fileSize; +} + +// OFFSET: LEGO1 0x100d0940 +MxU32 MxRAMStreamProvider::GetStreamBuffersNum() +{ + return 1; +} + +// OFFSET: LEGO1 0x100d0950 +MxU32 MxRAMStreamProvider::GetLengthInDWords() +{ + return m_lengthInDWords; +} + +// OFFSET: LEGO1 0x100d0960 +MxU32* MxRAMStreamProvider::GetBufferForDWords() +{ + return m_bufferForDWords; +} diff --git a/LEGO1/mxramstreamprovider.h b/LEGO1/mxramstreamprovider.h index 5422d3b3..48e0dcae 100644 --- a/LEGO1/mxramstreamprovider.h +++ b/LEGO1/mxramstreamprovider.h @@ -6,7 +6,22 @@ // VTABLE 0x100dd0d0 class MxRAMStreamProvider : public MxStreamProvider { +public: + MxRAMStreamProvider(); + virtual ~MxRAMStreamProvider() override; + virtual MxResult SetResourceToGet(void* p_resource) override; //vtable+0x14 + virtual MxU32 GetFileSize() override; //vtable+0x18 + virtual MxU32 GetStreamBuffersNum() override; //vtable+0x1c + virtual MxU32 GetLengthInDWords() override; //vtable+0x24 + virtual MxU32* GetBufferForDWords() override; //vtable+0x28 + +protected: + MxU32 m_bufferSize; + MxU32 m_fileSize; + void* m_pBufferOfFileSize; + MxU32 m_lengthInDWords; + MxU32* m_bufferForDWords; }; #endif // MXRAMSTREAMPROVIDER_H diff --git a/LEGO1/mxregion.h b/LEGO1/mxregion.h new file mode 100644 index 00000000..717be924 --- /dev/null +++ b/LEGO1/mxregion.h @@ -0,0 +1,26 @@ +#ifndef MXREGION_H +#define MXREGION_H + +#include "mxcore.h" + +// VTABLE 0x100dcae8 +// SIZE 0x1c +class MxRegion : public MxCore +{ +public: + MxRegion(); + virtual ~MxRegion() override; + + virtual void Reset(); + virtual void vtable18(); + virtual void vtable1c(); + virtual void vtable20(); + +private: + // A container (probably MxList) holding MxRect32 + // MxList *m_rects; + // 4 coordinates (could be MxRect32) + // MxS32 left, top, right, bottom; +}; + +#endif // MXREGION_H diff --git a/LEGO1/mxsmkpresenter.cpp b/LEGO1/mxsmkpresenter.cpp index cc7efec1..d8699862 100644 --- a/LEGO1/mxsmkpresenter.cpp +++ b/LEGO1/mxsmkpresenter.cpp @@ -15,3 +15,14 @@ void MxSmkPresenter::Init() { // TODO } + +// OFFSET: LEGO1 0x100b3960 +void MxSmkPresenter::VTable0x60() +{ + if (m_bitmap) { + delete m_bitmap; + } + + m_bitmap = new MxBitmap(); + m_bitmap->SetSize(m_smkWidth, m_smkHeight, NULL, FALSE); +} diff --git a/LEGO1/mxsmkpresenter.h b/LEGO1/mxsmkpresenter.h index 325091bb..34a78dab 100644 --- a/LEGO1/mxsmkpresenter.h +++ b/LEGO1/mxsmkpresenter.h @@ -12,7 +12,12 @@ class MxSmkPresenter : public MxVideoPresenter public: MxSmkPresenter(); - undefined4 m_unk64[430]; + virtual void VTable0x60() override; + + undefined4 m_unk64; + MxS32 m_smkWidth; // 0x68 + MxS32 m_smkHeight; // 0x6c + undefined4 m_unk70[427]; undefined4 m_unk71c; private: void Init(); diff --git a/LEGO1/mxsoundmanager.cpp b/LEGO1/mxsoundmanager.cpp index 275d0514..e34534f9 100644 --- a/LEGO1/mxsoundmanager.cpp +++ b/LEGO1/mxsoundmanager.cpp @@ -1,4 +1,8 @@ #include "mxsoundmanager.h" +#include "mxticklemanager.h" +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(MxSoundManager, 0x3c); // OFFSET: LEGO1 0x100ae740 MxSoundManager::MxSoundManager() @@ -6,16 +10,59 @@ MxSoundManager::MxSoundManager() Init(); } -// OFFSET: LEGO1 0x100ae7d0 STUB +// OFFSET: LEGO1 0x100ae7d0 MxSoundManager::~MxSoundManager() { - // TODO + Destroy(TRUE); } // OFFSET: LEGO1 0x100ae830 void MxSoundManager::Init() { m_unk30 = 0; - m_unk34 = 0; + m_dsBuffer = NULL; } +// OFFSET: LEGO1 0x100ae840 +void MxSoundManager::Destroy(MxBool p_param) +{ + if (this->m_thread) { + this->m_thread->Terminate(); + delete this->m_thread; + } + else { + TickleManager()->UnregisterClient(this); + } + + this->m_criticalSection.Enter(); + + if (this->m_dsBuffer) { + this->m_dsBuffer->Release(); + } + + Init(); + this->m_criticalSection.Leave(); + + if (!p_param) { + MxAudioManager::Destroy(); + } +} + +// OFFSET: LEGO1 0x100ae8b0 STUB +MxResult MxSoundManager::StartDirectSound(undefined4 p_unknown1, MxBool p_unknown2) +{ + // TODO STUB + return FAILURE; +} + +// OFFSET: LEGO1 0x100aed10 STUB +void MxSoundManager::vtable0x34() +{ + // TODO STUB +} + +// OFFSET: LEGO1 0x100aee10 STUB +void MxSoundManager::vtable0x38() +{ + // TODO STUB +} diff --git a/LEGO1/mxsoundmanager.h b/LEGO1/mxsoundmanager.h index 4d74fa95..46eef2e7 100644 --- a/LEGO1/mxsoundmanager.h +++ b/LEGO1/mxsoundmanager.h @@ -1,21 +1,30 @@ #ifndef MXSOUNDMANAGER_H #define MXSOUNDMANAGER_H -#include "mxunknown100dc6e0.h" +#include "decomp.h" +#include "mxaudiomanager.h" + +#include // VTABLE 0x100dc128 // SIZE 0x3c -// Base vtables are: MxCore -> 0x100dc6b0 -> 0x100dc6e0 -> MxSoundManager -class MxSoundManager : public MxUnknown100dc6e0 +class MxSoundManager : public MxAudioManager { public: MxSoundManager(); virtual ~MxSoundManager() override; // vtable+0x0 + virtual MxResult StartDirectSound(undefined4 p_unknown1, MxBool p_unknown2); //vtable+0x30 + virtual void vtable0x34(); // vtable+0x34 + virtual void vtable0x38(); // vtable+0x38 + private: void Init(); - int m_unk30; - int m_unk34; + void Destroy(MxBool); + + undefined4 m_unk30; + LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x34 + undefined m_unk35[4]; }; #endif // MXSOUNDMANAGER_H diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp new file mode 100644 index 00000000..89b2fa51 --- /dev/null +++ b/LEGO1/mxstreamcontroller.cpp @@ -0,0 +1,93 @@ +#include "mxstreamcontroller.h" + +#include "mxautolocker.h" +#include "legoomni.h" + +// OFFSET: LEGO1 0x100c0b90 STUB +MxStreamController::MxStreamController() +{ + // TODO +} + +// OFFSET: LEGO1 0x100c1290 STUB +MxStreamController::~MxStreamController() +{ + // TODO +} + +// OFFSET: LEGO1 0x100c20d0 STUB +MxBool MxStreamController::FUN_100c20d0(MxDSObject &p_obj) +{ + // TODO + return TRUE; +} + +// OFFSET: LEGO1 0x100c1520 +MxResult MxStreamController::Open(const char *p_filename) +{ + char sourceName [256]; + MxAutoLocker locker(&m_criticalSection); + + MakeSourceName(sourceName, p_filename); + this->atom = MxAtomId(sourceName, LookupMode_LowerCase2); + return SUCCESS; +} + +// OFFSET: LEGO1 0x100b9400 +MxResult MxStreamController::vtable0x18(undefined4 p_unknown, undefined4 p_unknown2) +{ + return FAILURE; +} + +// OFFSET: LEGO1 0x100b9410 +MxResult MxStreamController::vtable0x1C(undefined4 p_unknown, undefined4 p_unknown2) +{ + return FAILURE; +} + +// OFFSET: LEGO1 0x100c1690 +MxResult MxStreamController::vtable0x20(MxDSAction* p_action) +{ + MxAutoLocker locker(&m_criticalSection); + + MxResult result; + MxU32 offset = 0; + + MxS32 objectId = p_action->GetObjectId(); + MxStreamProvider *provider = m_provider; + + if ((MxS32) provider->GetLengthInDWords() > objectId) + offset = provider->GetBufferForDWords()[objectId]; + + if (offset) + result = vtable0x2c(p_action, offset); + else + result = FAILURE; + + return result; +} + +// OFFSET: LEGO1 0x100c1740 STUB +MxResult MxStreamController::vtable0x24(undefined4 p_unknown) +{ + // TODO STUB + return FAILURE; +} + +// OFFSET: LEGO1 0x100b9420 +MxResult MxStreamController::vtable0x28() +{ + return SUCCESS; +} + +// OFFSET: LEGO1 0x100c1c10 STUB +MxResult MxStreamController::vtable0x2c(MxDSAction* p_action, MxU32 p_bufferval) +{ + return FAILURE; +} + +// OFFSET: LEGO1 0x100c1ce0 STUB +MxResult MxStreamController::vtable0x30(undefined4 p_unknown) +{ + return FAILURE; +} diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/mxstreamcontroller.h index 4ec95e9e..539af0bd 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/mxstreamcontroller.h @@ -1,13 +1,23 @@ #ifndef MXSTREAMCONTROLLER_H #define MXSTREAMCONTROLLER_H +#include "decomp.h" #include "mxatomid.h" +#include "mxcriticalsection.h" #include "mxcore.h" +#include "mxdsobject.h" +#include "mxdsaction.h" +#include "mxstreamprovider.h" // VTABLE 0x100dc968 +// SIZE 0x64 class MxStreamController : public MxCore { public: + MxStreamController(); + + virtual ~MxStreamController() override; // vtable+0x0 + // OFFSET: LEGO1 0x100c0f10 inline virtual const char *ClassName() const override // vtable+0xc { @@ -21,16 +31,24 @@ class MxStreamController : public MxCore return !strcmp(name, MxStreamController::ClassName()) || MxCore::IsA(name); } - int m_unk08; - int m_unk0c; - int m_unk10; - int m_unk14; - int m_unk18; - int m_unk1c; - int m_unk20; + virtual MxResult Open(const char *p_filename); // vtable+0x14 + virtual MxResult vtable0x18(undefined4 p_unknown, undefined4 p_unknown2); //vtable+0x18 + virtual MxResult vtable0x1C(undefined4 p_unknown, undefined4 p_unknown2); //vtable+0x1c + virtual MxResult vtable0x20(MxDSAction* p_action); //vtable+0x20 + virtual MxResult vtable0x24(undefined4 p_unknown); //vtable+0x24 + virtual MxResult vtable0x28(); //vtable+0x28 + virtual MxResult vtable0x2c(MxDSAction* p_action, MxU32 p_bufferval); //vtable+0x2c + virtual MxResult vtable0x30(undefined4 p_unknown); //vtable+0x30 + + MxBool FUN_100c20d0(MxDSObject &p_obj); + + inline MxAtomId &GetAtom() { return atom; }; +protected: + MxCriticalSection m_criticalSection; MxAtomId atom; - int m_unk28; - int m_unk2c; + MxStreamProvider* m_provider; // MxStreamProvider* + undefined4 m_unk2c; + undefined m_unk30[0x34]; }; #endif // MXSTREAMCONTROLLER_H diff --git a/LEGO1/mxstreamer.cpp b/LEGO1/mxstreamer.cpp index 12f51f99..e95e4558 100644 --- a/LEGO1/mxstreamer.cpp +++ b/LEGO1/mxstreamer.cpp @@ -1,37 +1,180 @@ #include "mxstreamer.h" -// OFFSET: LEGO1 0x100b91d0 STUB -MxStreamer::~MxStreamer() +#include "legoomni.h" +#include "mxdiskstreamcontroller.h" +#include "mxramstreamcontroller.h" +#include "mxnotificationmanager.h" + +#include + +DECOMP_SIZE_ASSERT(MxStreamer, 0x2c); + +// OFFSET: LEGO1 0x100b8f00 +MxStreamer::MxStreamer() { - // TODO + NotificationManager()->Register(this); } -// OFFSET: LEGO1 0x100b92c0 STUB -MxStreamController *MxStreamer::Open(const char *name, MxU16 p) +// OFFSET: LEGO1 0x100b9190 +MxResult MxStreamer::Init() +{ + undefined *b = new undefined[m_subclass1.GetSize() * 0x5800]; + m_subclass1.SetBuffer(b); + if (b) { + b = new undefined[m_subclass2.GetSize() * 0x800]; + m_subclass2.SetBuffer(b); + if (b) { + return SUCCESS; + } + } + + return FAILURE; +} + +// OFFSET: LEGO1 0x100b91d0 +MxStreamer::~MxStreamer() +{ + while (!m_openStreams.empty()) { + MxStreamController *c = m_openStreams.front(); + m_openStreams.pop_front(); + delete c; + } + + NotificationManager()->Unregister(this); +} + +// OFFSET: LEGO1 0x100b92c0 +MxStreamController *MxStreamer::Open(const char *p_name, MxU16 p_lookupType) { // TODO + MxStreamController *stream = NULL; + + if (!GetOpenStream(p_name)) { + switch (p_lookupType) { + case e_DiskStream: + stream = new MxDiskStreamController(); + break; + case e_RAMStream: + stream = new MxRAMStreamController(); + break; + } + + if (!stream + || stream->Open(p_name) != SUCCESS + || AddStreamControllerToOpenList(stream) != SUCCESS) { + delete stream; + stream = NULL; + } + } + + return stream; +} + +// OFFSET: LEGO1 0x100b9570 +MxLong MxStreamer::Close(const char *p) +{ + MxDSAction ds; + + ds.SetUnknown24(-2); + + for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { + MxStreamController *c = *it; + + if (!p || !strcmp(p, c->GetAtom().GetInternal())) { + m_openStreams.erase(it); + + if (!c->FUN_100c20d0(ds)) { + MxStreamerNotification notif(MXSTREAMER_DELETE_NOTIFY, NULL, c); + + NotificationManager()->Send(this, ¬if); + } else { + delete c; + } + + return SUCCESS; + } + } + + return FAILURE; +} + +// OFFSET: LEGO1 0x100b9700 +MxNotificationParam *MxStreamerNotification::Clone() +{ + return new MxStreamerNotification(m_type, m_sender, m_controller); +} + +// OFFSET: LEGO1 0x100b9870 +MxStreamController *MxStreamer::GetOpenStream(const char *p_name) +{ + for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { + MxStreamController *c = *it; + MxAtomId &atom = c->GetAtom(); + if (p_name) { + if (!strcmp(atom.GetInternal(), p_name)) { + return *it; + } + } + } + return NULL; } -// OFFSET: LEGO1 0x100b9570 STUB -MxLong MxStreamer::Close(const char *p) +// OFFSET: LEGO1 0x100b9930 +MxResult MxStreamer::AddStreamControllerToOpenList(MxStreamController *stream) { - // TODO - return 0; + if (find(m_openStreams.begin(), m_openStreams.end(), stream) == m_openStreams.end()) { + m_openStreams.push_back(stream); + return SUCCESS; + } + + return FAILURE; } -// OFFSET: LEGO1 0x100b9b60 STUB +// OFFSET: LEGO1 0x100b99b0 +MxResult MxStreamer::Unknown100b99b0(MxDSAction* p_action) +{ + MxStreamController* controller; + if (p_action != NULL && p_action->GetAtomId().GetInternal() != NULL && p_action->GetObjectId() != -1) + { + controller = GetOpenStream(p_action->GetAtomId().GetInternal()); + if (controller == NULL) + { + return FAILURE; + } + return controller->vtable0x20(p_action); + } + return FAILURE; +} + +// OFFSET: LEGO1 0x100b9b60 MxLong MxStreamer::Notify(MxParam &p) { - // TODO + if (((MxNotificationParam&) p).GetType() == MXSTREAMER_DELETE_NOTIFY) { + MxDSAction ds; + + ds.SetUnknown24(-2); + + MxStreamController *c = static_cast(p).GetController(); + + if (!c->FUN_100c20d0(ds)) { + MxStreamerNotification notif(MXSTREAMER_DELETE_NOTIFY, NULL, c); + NotificationManager()->Send(this, ¬if); + } else { + delete c; + } + } return 0; } -// OFFSET: LEGO1 0x100b9190 STUB -MxResult MxStreamer::VTable0x14() +// No offset, function is always inlined +MxStreamerSubClass1::MxStreamerSubClass1(undefined4 size) { - // TODO - - return MxResult(); -} + m_buffer = NULL; + m_size = size; + undefined4 *ptr = &m_unk08; + for (int i = 0; i >= 0; i--) { + ptr[i] = 0; + } +} \ No newline at end of file diff --git a/LEGO1/mxstreamer.h b/LEGO1/mxstreamer.h index f14ac66d..529a564a 100644 --- a/LEGO1/mxstreamer.h +++ b/LEGO1/mxstreamer.h @@ -1,21 +1,107 @@ #ifndef MXSTREAMER_H #define MXSTREAMER_H +#include + +#include "decomp.h" #include "mxcore.h" +#include "mxnotificationparam.h" #include "mxstreamcontroller.h" #include "mxtypes.h" +// NOTE: This feels like some kind of templated class, maybe something from the +// STL. But I haven't figured out what yet (it's definitely not a vector). +class MxStreamerSubClass1 +{ +public: + inline MxStreamerSubClass1(undefined4 size); + + ~MxStreamerSubClass1() { delete [] m_buffer; } + + undefined4 GetSize() { return m_size; } + + void SetBuffer(undefined *p_buf) { m_buffer = p_buf; } + +private: + undefined *m_buffer; + undefined4 m_size; + undefined4 m_unk08; +}; + +class MxStreamerSubClass2 : public MxStreamerSubClass1 +{ +public: + inline MxStreamerSubClass2() : MxStreamerSubClass1(0x40) {} +}; + +class MxStreamerSubClass3 : public MxStreamerSubClass1 +{ +public: + inline MxStreamerSubClass3() : MxStreamerSubClass1(0x80) {} +}; + +class MxStreamerNotification : public MxNotificationParam +{ +public: + inline MxStreamerNotification(MxParamType p_type, MxCore *p_sender, MxStreamController *p_ctrlr) : MxNotificationParam(p_type, p_sender) + { + m_controller = p_ctrlr; + } + + virtual ~MxStreamerNotification() override {} + + virtual MxNotificationParam *Clone() override; + + MxStreamController *GetController() { return m_controller; } + +private: + MxStreamController *m_controller; +}; + // VTABLE 0x100dc710 +// SIZE 0x2c class MxStreamer : public MxCore { public: - virtual ~MxStreamer() override; + enum OpenMode + { + e_DiskStream, + e_RAMStream + }; - __declspec(dllexport) MxStreamController *Open(const char *name, MxU16 p); - __declspec(dllexport) MxLong Close(const char *p); + MxStreamer(); + virtual ~MxStreamer() override; // vtable+0x0 + + __declspec(dllexport) MxStreamController *Open(const char *p_name, MxU16 p_openMode); + __declspec(dllexport) MxLong Close(const char *p_name); virtual MxLong Notify(MxParam &p) override; // vtable+0x4 - virtual MxResult VTable0x14(); // vtable+0x14 + + // OFFSET: LEGO1 0x100b9000 + inline virtual const char *ClassName() const override // vtable+0x0c + { + // 0x1010210c + return "MxStreamer"; + } + + // OFFSET: LEGO1 0x100b9010 + inline virtual MxBool IsA(const char *p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxStreamer::ClassName()) || MxCore::IsA(p_name); + } + + virtual MxResult Init(); // vtable+0x14 + + MxStreamController *GetOpenStream(const char *p_name); + + MxResult AddStreamControllerToOpenList(MxStreamController *p_stream); + + MxResult MxStreamer::Unknown100b99b0(MxDSAction* p_action); + +private: + list m_openStreams; // 0x8 + MxStreamerSubClass2 m_subclass1; // 0x14 + MxStreamerSubClass3 m_subclass2; // 0x20 }; #endif // MXSTREAMER_H diff --git a/LEGO1/mxstreamprovider.cpp b/LEGO1/mxstreamprovider.cpp new file mode 100644 index 00000000..c9dab949 --- /dev/null +++ b/LEGO1/mxstreamprovider.cpp @@ -0,0 +1,17 @@ +#include "decomp.h" +#include "mxstreamprovider.h" + +DECOMP_SIZE_ASSERT(MxStreamProvider, 0x10); + +// OFFSET: LEGO1 0x100d07c0 +MxResult MxStreamProvider::SetResourceToGet(void* p_resource) +{ + m_pLookup = p_resource; + return SUCCESS; +} + +// OFFSET: LEGO1 0x100d07d0 +void MxStreamProvider::vtable0x20(undefined4 p_unknown1) +{ + +} diff --git a/LEGO1/mxstreamprovider.h b/LEGO1/mxstreamprovider.h index b70b6446..fb210f80 100644 --- a/LEGO1/mxstreamprovider.h +++ b/LEGO1/mxstreamprovider.h @@ -1,13 +1,17 @@ #ifndef MXSTREAMPROVIDER_H #define MXSTREAMPROVIDER_H +#include "decomp.h" #include "mxcore.h" #include "mxdsfile.h" // VTABLE 0x100dd100 +// SIZE 0x10 class MxStreamProvider : public MxCore { public: + inline MxStreamProvider() : m_pLookup(NULL), m_pFile(NULL) {} + // OFFSET: LEGO1 0x100d07e0 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -20,7 +24,14 @@ class MxStreamProvider : public MxCore return !strcmp(name, MxStreamProvider::ClassName()) || MxCore::IsA(name); } -private: + virtual MxResult SetResourceToGet(void* p_resource); //vtable+0x14 + virtual MxU32 GetFileSize() = 0; //vtable+0x18 + virtual MxU32 GetStreamBuffersNum() = 0; //vtable+0x1c + virtual void vtable0x20(undefined4 p_unknown1); //vtable+0x20 + virtual MxU32 GetLengthInDWords() = 0; //vtable+0x24 + virtual MxU32* GetBufferForDWords() = 0; //vtable+0x28 + +protected: void *m_pLookup; MxDSFile* m_pFile; }; diff --git a/LEGO1/mxstring.cpp b/LEGO1/mxstring.cpp index e2f24cab..fe221f94 100644 --- a/LEGO1/mxstring.cpp +++ b/LEGO1/mxstring.cpp @@ -1,7 +1,11 @@ #include "mxstring.h" +#include "decomp.h" + #include #include +DECOMP_SIZE_ASSERT(MxString, 0x10) + // OFFSET: LEGO1 0x100ae200 MxString::MxString() { @@ -52,14 +56,14 @@ void MxString::ToLowerCase() } // OFFSET: LEGO1 0x100ae4b0 -MxString &MxString::operator=(MxString *param) +MxString &MxString::operator=(MxString ¶m) { - if (this->m_data != param->m_data) + if (this->m_data != param.m_data) { delete[] this->m_data; - this->m_length = param->m_length; + this->m_length = param.m_length; this->m_data = new char[this->m_length + 1]; - strcpy(this->m_data, param->m_data); + strcpy(this->m_data, param.m_data); } return *this; diff --git a/LEGO1/mxstring.h b/LEGO1/mxstring.h index a24a0df1..ec20f879 100644 --- a/LEGO1/mxstring.h +++ b/LEGO1/mxstring.h @@ -15,7 +15,7 @@ class MxString : public MxCore MxString(const char *); void ToUpperCase(); void ToLowerCase(); - MxString& operator=(MxString *); + MxString& operator=(MxString &); MxString operator+(const char *); MxString& operator+=(const char *); diff --git a/LEGO1/mxstringlist.cpp b/LEGO1/mxstringlist.cpp new file mode 100644 index 00000000..8a0a2ddc --- /dev/null +++ b/LEGO1/mxstringlist.cpp @@ -0,0 +1,5 @@ +#include "mxstringlist.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxListEntry, 0x18) diff --git a/LEGO1/mxstringlist.h b/LEGO1/mxstringlist.h new file mode 100644 index 00000000..f92d2b7d --- /dev/null +++ b/LEGO1/mxstringlist.h @@ -0,0 +1,35 @@ +#ifndef MXSTRINGLIST_H +#define MXSTRINGLIST_H + +#include "mxlist.h" +#include "mxstring.h" + +// VTABLE 0x100dd040 +// SIZE 0x18 +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::OtherAppend + +// 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/mxthread.cpp b/LEGO1/mxthread.cpp index b63019ed..fed82eca 100644 --- a/LEGO1/mxthread.cpp +++ b/LEGO1/mxthread.cpp @@ -1,9 +1,10 @@ #include "mxthread.h" -#include - #include "mxomni.h" +#include "mxtimer.h" + +#include // OFFSET: LEGO1 0x100bf690 MxResult MxThread::Run() diff --git a/LEGO1/mxthread.h b/LEGO1/mxthread.h index 4537dc14..758205d7 100644 --- a/LEGO1/mxthread.h +++ b/LEGO1/mxthread.h @@ -24,6 +24,8 @@ class MxThread protected: MxThread(); + +public: virtual ~MxThread(); private: diff --git a/LEGO1/mxtransitionmanager.cpp b/LEGO1/mxtransitionmanager.cpp index 8af3f497..12d989c8 100644 --- a/LEGO1/mxtransitionmanager.cpp +++ b/LEGO1/mxtransitionmanager.cpp @@ -1,27 +1,406 @@ #include "mxtransitionmanager.h" -// OFFSET: LEGO1 0x1004b8d0 STUB +#include "legovideomanager.h" +#include "legoinputmanager.h" +#include "legoutil.h" +#include "legoworld.h" +#include "mxbackgroundaudiomanager.h" +#include "mxparam.h" +#include "mxticklemanager.h" + +DECOMP_SIZE_ASSERT(MxTransitionManager, 0x900); + +// 0x100f4378 +RECT g_fullScreenRect = {0, 0, 640, 480}; + +// OFFSET: LEGO1 0x1004b8d0 MxTransitionManager::MxTransitionManager() { - // TODO + m_animationTimer = 0; + m_transitionType = NOT_TRANSITIONING; + m_ddSurface = NULL; + m_waitIndicator = NULL; + m_copyBuffer = NULL; + m_copyFlags.bit0 = FALSE; + m_unk28.bit0 = FALSE; + m_unk24 = 0; } -// OFFSET: LEGO1 0x1004ba00 STUB +// OFFSET: LEGO1 0x1004ba00 MxTransitionManager::~MxTransitionManager() { - // TODO + delete[] m_copyBuffer; + + if (m_waitIndicator != NULL) { + delete m_waitIndicator->GetAction(); + delete m_waitIndicator; + } + + TickleManager()->UnregisterClient(this); } -// OFFSET: LEGO1 0x1004bac0 STUB -MxLong MxTransitionManager::Tickle() +// OFFSET: LEGO1 0x1004bac0 +MxResult MxTransitionManager::Tickle() { - // TODO + if (this->m_animationSpeed + this->m_systemTime > timeGetTime()) { + return SUCCESS; + } - return 0; + this->m_systemTime = timeGetTime(); + + switch (this->m_transitionType) { + case NO_ANIMATION: + Transition_None(); + break; + case DISSOLVE: + Transition_Dissolve(); + break; + case PIXELATION: + Transition_Pixelation(); + break; + case SCREEN_WIPE: + Transition_Wipe(); + break; + case WINDOWS: + Transition_Windows(); + break; + case BROKEN: + Transition_Broken(); + break; + } + return SUCCESS; } -// OFFSET: LEGO1 0x1004c470 STUB -void MxTransitionManager::SetWaitIndicator(MxVideoPresenter *videoPresenter) +// OFFSET: LEGO1 0x1004bc30 +void MxTransitionManager::EndTransition(MxBool p_notifyWorld) +{ + if (m_transitionType != NOT_TRANSITIONING) { + m_transitionType = NOT_TRANSITIONING; + + m_copyFlags.bit0 = FALSE; + + TickleManager()->UnregisterClient(this); + + if (p_notifyWorld) { + LegoWorld *world = GetCurrentWorld(); + + if (world) { + world->Notify(MxNotificationParam(MXTRANSITIONMANAGER_TRANSITIONENDED, this)); + } + } + } +} + +// OFFSET: LEGO1 0x1004bd10 +void MxTransitionManager::Transition_Dissolve() +{ + // If the animation is finished + if (m_animationTimer == 40) { + m_animationTimer = 0; + EndTransition(TRUE); + return; + } + + // If we are starting the animation + if (m_animationTimer == 0) { + // Generate the list of columns in order... + for (MxS32 i = 0; i < 640; i++) { + m_columnOrder[i] = i; + } + + // ...then shuffle the list (to ensure that we hit each column once) + for (i = 0; i < 640; i++) { + MxS32 swap = rand() % 640; + MxU16 t = m_columnOrder[i]; + m_columnOrder[i] = m_columnOrder[swap]; + m_columnOrder[swap] = t; + } + + // For each scanline, pick a random X offset + for (i = 0; i < 480; i++) { + m_randomShift[i] = rand() % 640; + } + } + + // Run one tick of the animation + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + HRESULT res = m_ddSurface->Lock(NULL, &ddsd, 1, NULL); + if (res == DDERR_SURFACELOST) { + m_ddSurface->Restore(); + res = m_ddSurface->Lock(NULL, &ddsd, 1, NULL); + } + + if (res == DD_OK) { + SubmitCopyRect(&ddsd); + + for (MxS32 i = 0; i < 640; i++) { + // Select 16 columns on each tick + if (m_animationTimer * 16 > m_columnOrder[i]) + continue; + + if (m_animationTimer * 16 + 15 < m_columnOrder[i]) + continue; + + for (MxS32 j = 0; j < 480; j++) { + // Shift the chosen column a different amount at each scanline. + // We use the same shift for that scanline each time. + // By the end, every pixel gets hit. + MxS32 ofs = (m_randomShift[j] + i) % 640; + + // Set the chosen pixel to black + if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) { + ((MxU8*)ddsd.lpSurface)[j * ddsd.lPitch + ofs] = 0; + } else { + ((MxU16*)ddsd.lpSurface)[j * ddsd.lPitch + ofs] = 0; + } + } + } + + SetupCopyRect(&ddsd); + m_ddSurface->Unlock(ddsd.lpSurface); + + if (VideoManager()->GetVideoParam().flags().GetFlipSurfaces()) { + LPDIRECTDRAWSURFACE surf = VideoManager()->GetDisplaySurface()->GetDirectDrawSurface1(); + surf->BltFast(NULL, NULL, m_ddSurface, &g_fullScreenRect, 0x10); + } + + m_animationTimer++; + } +} + +// OFFSET: LEGO1 0x1004baa0 +MxResult MxTransitionManager::GetDDrawSurfaceFromVideoManager() // vtable+0x14 +{ + LegoVideoManager *videoManager = VideoManager(); + this->m_ddSurface = videoManager->GetDisplaySurface()->GetDirectDrawSurface2(); + return SUCCESS; +} + +// OFFSET: LEGO1 0x1004bb70 +MxResult MxTransitionManager::StartTransition(TransitionType p_animationType, MxS32 p_speed, + MxBool p_doCopy, MxBool p_playMusicInAnim) +{ + if (this->m_transitionType == NOT_TRANSITIONING) { + if (!p_playMusicInAnim) { + MxBackgroundAudioManager *backgroundAudioManager = BackgroundAudioManager(); + backgroundAudioManager->Stop(); + } + + this->m_transitionType = p_animationType; + + m_copyFlags.bit0 = p_doCopy; + + if (m_copyFlags.bit0 && m_waitIndicator != NULL) { + m_waitIndicator->Enable(TRUE); + + MxDSAction *action = m_waitIndicator->GetAction(); + action->SetLoopCount(10000); + action->SetFlags(action->GetFlags() | MxDSAction::Flag_Bit9); + } + + MxU32 time = timeGetTime(); + this->m_systemTime = time; + + this->m_animationSpeed = p_speed; + + MxTickleManager *tickleManager = TickleManager(); + tickleManager->RegisterClient(this, p_speed); + + LegoInputManager *inputManager = InputManager(); + inputManager->m_unk0x88 = TRUE; + inputManager->m_unk0x336 = FALSE; + + LegoVideoManager *videoManager = VideoManager(); + videoManager->SetUnkE4(FALSE); + + SetAppCursor(1); + return SUCCESS; + } + return FAILURE; +} + +// OFFSET: LEGO1 0x1004bcf0 +void MxTransitionManager::Transition_None() +{ + LegoVideoManager *videoManager = VideoManager(); + videoManager->GetDisplaySurface()->FUN_100ba640(); + EndTransition(TRUE); +} + +// OFFSET: LEGO1 0x1004bed0 STUB +void MxTransitionManager::Transition_Pixelation() { // TODO } + + +// OFFSET: LEGO1 0x1004c270 STUB +void MxTransitionManager::Transition_Windows() +{ + // TODO +} + +// OFFSET: LEGO1 0x1004c3e0 STUB +void MxTransitionManager::Transition_Broken() +{ + // TODO +} + +// OFFSET: LEGO1 0x1004c170 +void MxTransitionManager::Transition_Wipe() +{ + // If the animation is finished + if (m_animationTimer == 240) { + m_animationTimer = 0; + EndTransition(TRUE); + return; + } + + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + HRESULT res = m_ddSurface->Lock(NULL, &ddsd, 1, NULL); + if (res == DDERR_SURFACELOST) { + m_ddSurface->Restore(); + res = m_ddSurface->Lock(NULL, &ddsd, 1, NULL); + } + + if (res == DD_OK) { + SubmitCopyRect(&ddsd); + + // For each of the 240 animation ticks, blank out two scanlines + // starting at the top of the screen. + // (dwRGBBitCount / 8) will tell how many bytes are used per pixel. + MxU8 *line = (MxU8*)ddsd.lpSurface + 2*ddsd.lPitch*m_animationTimer; + memset(line, 0, 640 * ddsd.ddpfPixelFormat.dwRGBBitCount / 8); + + line += ddsd.lPitch; + memset(line, 0, 640 * ddsd.ddpfPixelFormat.dwRGBBitCount / 8); + + SetupCopyRect(&ddsd); + m_ddSurface->Unlock(ddsd.lpSurface); + + m_animationTimer++; + } +} + +// OFFSET: LEGO1 0x1004c470 +void MxTransitionManager::SetWaitIndicator(MxVideoPresenter *p_waitIndicator) +{ + // End current wait indicator + if (m_waitIndicator != NULL) { + m_waitIndicator->GetAction()->SetFlags(m_waitIndicator->GetAction()->GetFlags() & ~MxDSAction::Flag_Parsed); + m_waitIndicator->EndAction(); + m_waitIndicator = NULL; + } + + // Check if we were given a new wait indicator + if (p_waitIndicator != NULL) { + // Setup the new wait indicator + m_waitIndicator = p_waitIndicator; + + LegoVideoManager *videoManager = VideoManager(); + videoManager->RemovePresenter(*m_waitIndicator); + + if (m_waitIndicator->GetCurrentTickleState() < MxPresenter::TickleState_Streaming) { + m_waitIndicator->Tickle(); + } + } else { + // Disable copy rect + m_copyFlags.bit0 = FALSE; + } +} + +// OFFSET: LEGO1 0x1004c4d0 +void MxTransitionManager::SubmitCopyRect(LPDDSURFACEDESC ddsc) +{ + // Check if the copy rect is setup + if (m_copyFlags.bit0 == FALSE || m_waitIndicator == NULL || m_copyBuffer == NULL) { + return; + } + + // Copy the copy rect onto the surface + MxU8 *dst; + + MxU32 bytesPerPixel = ddsc->ddpfPixelFormat.dwRGBBitCount / 8; + + const MxU8 *src = (const MxU8 *)m_copyBuffer; + + MxS32 copyPitch; + copyPitch = ((m_copyRect.right - m_copyRect.left) + 1) * bytesPerPixel; + + MxS32 y; + dst = (MxU8 *)ddsc->lpSurface + (ddsc->lPitch * m_copyRect.top) + (bytesPerPixel * m_copyRect.left); + + for (y = 0; y < m_copyRect.bottom - m_copyRect.top + 1; ++y) { + memcpy(dst, src, copyPitch); + src += copyPitch; + dst += ddsc->lPitch; + } + + // Free the copy buffer + delete[] m_copyBuffer; + m_copyBuffer = NULL; +} + +// OFFSET: LEGO1 0x1004c580 +void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC ddsc) +{ + // Check if the copy rect is setup + if (m_copyFlags.bit0 == FALSE || m_waitIndicator == NULL) { + return; + } + + // Tickle wait indicator + m_waitIndicator->Tickle(); + + // Check if wait indicator has started + if (m_waitIndicator->GetCurrentTickleState() >= MxPresenter::TickleState_Streaming) { + // Setup the copy rect + MxU32 copyPitch = (ddsc->ddpfPixelFormat.dwRGBBitCount / 8) * (m_copyRect.right - m_copyRect.left + 1); // This uses m_copyRect, seemingly erroneously + MxU32 bytesPerPixel = ddsc->ddpfPixelFormat.dwRGBBitCount / 8; + + m_copyRect.left = m_waitIndicator->GetLocationX(); + m_copyRect.top = m_waitIndicator->GetLocationY(); + + MxS32 height = m_waitIndicator->GetHeight(); + MxS32 width = m_waitIndicator->GetWidth(); + + m_copyRect.right = m_copyRect.left + width - 1; + m_copyRect.bottom = m_copyRect.top + height - 1; + + // Allocate the copy buffer + const MxU8 *src = (const MxU8*)ddsc->lpSurface + m_copyRect.top * ddsc->lPitch + bytesPerPixel * m_copyRect.left; + + m_copyBuffer = new MxU8[bytesPerPixel * width * height]; + if (!m_copyBuffer) + return; + + // Copy into the copy buffer + MxU8 *dst = m_copyBuffer; + + for (MxS32 i = 0; i < (m_copyRect.bottom - m_copyRect.top + 1); i++) + { + memcpy(dst, src, copyPitch); + src += ddsc->lPitch; + dst += copyPitch; + } + } + + // Setup display surface + if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::Flag_Bit5) != 0) + { + MxDisplaySurface *displaySurface = VideoManager()->GetDisplaySurface(); + MxBool unkbool = FALSE; + displaySurface->vtable2c(ddsc, m_waitIndicator->m_bitmap, 0, 0, m_waitIndicator->GetLocationX(), m_waitIndicator->GetLocationY(), m_waitIndicator->GetWidth(), m_waitIndicator->GetHeight(), unkbool); + } + else + { + MxDisplaySurface *displaySurface = VideoManager()->GetDisplaySurface(); + displaySurface->vtable24(ddsc, m_waitIndicator->m_bitmap, 0, 0, m_waitIndicator->GetLocationX(), m_waitIndicator->GetLocationY(), m_waitIndicator->GetWidth(), m_waitIndicator->GetHeight()); + } +} diff --git a/LEGO1/mxtransitionmanager.h b/LEGO1/mxtransitionmanager.h index c6cc28aa..58a8079e 100644 --- a/LEGO1/mxtransitionmanager.h +++ b/LEGO1/mxtransitionmanager.h @@ -2,19 +2,76 @@ #define MXTRANSITIONMANAGER_H #include "mxcore.h" +#include "mxvideopresenter.h" +#include "legoomni.h" -class MxVideoPresenter; +#include -// 0x100d7ea0 +// VTABLE 0x100d7ea0 class MxTransitionManager : public MxCore { public: MxTransitionManager(); virtual ~MxTransitionManager() override; // vtable+0x0 - __declspec(dllexport) void SetWaitIndicator(MxVideoPresenter *videoPresenter); + __declspec(dllexport) void SetWaitIndicator(MxVideoPresenter *p_waitIndicator); - virtual MxLong Tickle(); // vtable+0x8 + virtual MxResult Tickle(); // vtable+0x8 + + // OFFSET: LEGO1 0x1004b950 + inline virtual const char *ClassName() const override // vtable+0x0c + { + return "MxTransitionManager"; + } + + // OFFSET: LEGO1 0x1004b960 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, MxTransitionManager::ClassName()) || MxCore::IsA(name); + } + + virtual MxResult GetDDrawSurfaceFromVideoManager(); // vtable+0x14 + + enum TransitionType { + NOT_TRANSITIONING, + NO_ANIMATION, + DISSOLVE, + PIXELATION, + SCREEN_WIPE, + WINDOWS, + BROKEN // Unknown what this is supposed to be, it locks the game up + }; + + MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim); + + +private: + void EndTransition(MxBool p_notifyWorld); + void Transition_None(); + void Transition_Dissolve(); + void Transition_Pixelation(); + void Transition_Wipe(); + void Transition_Windows(); + void Transition_Broken(); + + void SubmitCopyRect(LPDDSURFACEDESC ddsc); + void SetupCopyRect(LPDDSURFACEDESC ddsc); + + MxVideoPresenter *m_waitIndicator; + RECT m_copyRect; + MxU8 *m_copyBuffer; + + flag_bitfield m_copyFlags; + undefined4 m_unk24; + flag_bitfield m_unk28; + + TransitionType m_transitionType; + LPDIRECTDRAWSURFACE m_ddSurface; + MxU16 m_animationTimer; + MxU16 m_columnOrder[640]; // 0x36 + MxU16 m_randomShift[480]; // 0x536 + MxULong m_systemTime; // 0x8f8 + MxS32 m_animationSpeed; // 0x8fc }; #endif // MXTRANSITIONMANAGER_H diff --git a/LEGO1/mxtypes.h b/LEGO1/mxtypes.h index fc8d47b5..75f19d4a 100644 --- a/LEGO1/mxtypes.h +++ b/LEGO1/mxtypes.h @@ -44,4 +44,19 @@ typedef MxU8 MxBool; #define TWOCC(a, b) (((a) << 0) | ((b) << 8)) #define FOURCC(a, b, c, d) (((a) << 0) | ((b) << 8) | ((c) << 16) | ((d) << 24)) +// Must be union with struct for match. +typedef union { + struct { + MxU8 bit0: 1; + MxU8 bit1: 1; + MxU8 bit2: 1; + MxU8 bit3: 1; + MxU8 bit4: 1; + MxU8 bit5: 1; + MxU8 bit6: 1; + MxU8 bit7: 1; + }; + // BYTE all; // ? +} flag_bitfield; + #endif // MXTYPE_H diff --git a/LEGO1/mxunklist.h b/LEGO1/mxunklist.h new file mode 100644 index 00000000..af59f47b --- /dev/null +++ b/LEGO1/mxunklist.h @@ -0,0 +1,37 @@ +#ifndef MXUNKLIST_H +#define MXUNKLIST_H + +#include "decomp.h" +#include "mxtypes.h" + +/* +* This is an as-of-yet unknown list-like data structure. +* The class hierarchy/structure isn't quite correct yet. +*/ + +struct MxUnkListNode { + MxUnkListNode *m_unk00; + MxUnkListNode *m_unk04; + undefined4 m_unk08; +}; + +class MxUnkList { +public: + inline MxUnkList() { + undefined unk; + this->m_unk00 = unk; + + MxUnkListNode *node = new MxUnkListNode(); + node->m_unk00 = node; + node->m_unk04 = node; + + this->m_head = node; + this->m_count = 0; + } + + undefined m_unk00; + MxUnkListNode *m_head; + MxU32 m_count; +}; + +#endif // MXUNKLIST_H \ No newline at end of file diff --git a/LEGO1/mxunknown100dc6e0.cpp b/LEGO1/mxunknown100dc6e0.cpp deleted file mode 100644 index b896e89b..00000000 --- a/LEGO1/mxunknown100dc6e0.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "mxunknown100dc6e0.h" - -// OFFSET: LEGO1 0x100b8d00 -MxUnknown100dc6e0::MxUnknown100dc6e0() -{ - Init(); -} - -// OFFSET: LEGO1 0x100b8d90 STUB -MxUnknown100dc6e0::~MxUnknown100dc6e0() -{ - // TODO -} - -// OFFSET: LEGO1 0x100b8df0 -void MxUnknown100dc6e0::Init() -{ - this->m_unk2c = 100; -} diff --git a/LEGO1/mxunknown100dc6e0.h b/LEGO1/mxunknown100dc6e0.h deleted file mode 100644 index 056e1fcd..00000000 --- a/LEGO1/mxunknown100dc6e0.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MXUNKNOWN100DC6E0_H -#define MXUNKNOWN100DC6E0_H - -#include "mxmediamanager.h" - -// VTABLE 0x100dc6e0 -class MxUnknown100dc6e0 : public MxMediaManager -{ -public: - MxUnknown100dc6e0(); - virtual ~MxUnknown100dc6e0() override; - -protected: - void Init(); - - int m_unk2c; -}; - -#endif // MXUNKNOWN100DC6E0_H diff --git a/LEGO1/mxvariable.cpp b/LEGO1/mxvariable.cpp index f18e6a94..0c9bf95a 100644 --- a/LEGO1/mxvariable.cpp +++ b/LEGO1/mxvariable.cpp @@ -1,5 +1,8 @@ #include "mxvariable.h" #include "mxstring.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxVariable, 0x24) // OFFSET: LEGO1 0x1003bea0 MxString *MxVariable::GetValue() diff --git a/LEGO1/mxvariable.h b/LEGO1/mxvariable.h index 6899dfac..83c83020 100644 --- a/LEGO1/mxvariable.h +++ b/LEGO1/mxvariable.h @@ -4,7 +4,8 @@ #include "mxstring.h" #include "mxcore.h" -//VTABLE: 0x100d74a8 +// VTABLE 0x100d7498 +// SIZE 0x24 class MxVariable { public: diff --git a/LEGO1/mxvector.cpp b/LEGO1/mxvector.cpp index a4053105..ad4060e0 100644 --- a/LEGO1/mxvector.cpp +++ b/LEGO1/mxvector.cpp @@ -371,7 +371,7 @@ float MxVector4::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]; + (p_a[1] * p_b[1] + p_a[3] * p_b[3]); } // OFFSET: LEGO1 0x10002a20 @@ -410,13 +410,14 @@ void MxVector4::EqualsScalar(float *p_value) m_data[3] = *p_value; } -// OFFSET: LEGO1 0x10002ae0 STUB -void MxVector4::unk1(MxVector4 *p_a, float *p_b) +// OFFSET: LEGO1 0x10002ae0 +void MxVector4::SetMatrixProduct(MxVector4 *p_a, float *p_b) { + SetMatrixProductImpl(p_a->m_data, p_b); } // OFFSET: LEGO1 0x10002a40 -void MxVector4::SetMatrixProduct(float *p_vec, float *p_mat) +void MxVector4::SetMatrixProductImpl(float *p_vec, float *p_mat) { m_data[0] = p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + @@ -453,8 +454,19 @@ MxResult MxVector4::NormalizeQuaternion() return FAILURE; } -// OFFSET: LEGO1 0x10002bf0 STUB +// OFFSET: LEGO1 0x10002bf0 void MxVector4::UnknownQuaternionOp(MxVector4 *p_a, MxVector4 *p_b) { + MxFloat *bDat = p_b->m_data; + MxFloat *aDat = p_a->m_data; -} \ No newline at end of file + 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]; + this->m_data[1] = aDat[2] * bDat[0] - bDat[2] * aDat[0]; + this->m_data[2] = bDat[1] * aDat[0] - aDat[1] * bDat[0]; + + + m_data[0] = p_b->m_data[3] * p_a->m_data[0] + p_a->m_data[3] * p_b->m_data[0] + m_data[0]; + m_data[1] = p_b->m_data[1] * p_a->m_data[3] + p_a->m_data[1] * p_b->m_data[3] + m_data[1]; + m_data[2] = p_b->m_data[2] * p_a->m_data[3] + p_a->m_data[2] * p_b->m_data[3] + m_data[2]; +} diff --git a/LEGO1/mxvector.h b/LEGO1/mxvector.h index ae58abd9..b2d0bf54 100644 --- a/LEGO1/mxvector.h +++ b/LEGO1/mxvector.h @@ -95,6 +95,8 @@ class MxVector3 : public MxVector2 virtual void EqualsCross(MxVector3 *p_a, float *p_b); virtual void EqualsCross(MxVector3 *p_a, MxVector3 *p_b); virtual void EqualsScalar(float *p_value); + + inline void Fill(float p_value) { EqualsScalar(&p_value); } }; // VTABLE 0x100d45a0 @@ -123,8 +125,8 @@ class MxVector4 : public MxVector3 void EqualsScalar(float *p_value); // vtable + 0x84 - virtual void unk1(MxVector4 *p_a, float *p_b); - virtual void SetMatrixProduct(float *p_vec, float *p_mat); + virtual void SetMatrixProduct(MxVector4 *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); }; diff --git a/LEGO1/mxvideomanager.cpp b/LEGO1/mxvideomanager.cpp index 7663743d..bab495fd 100644 --- a/LEGO1/mxvideomanager.cpp +++ b/LEGO1/mxvideomanager.cpp @@ -1,18 +1,6 @@ #include "mxvideomanager.h" - -// OFFSET: LEGO1 0x100be2a0 STUB -MxVideoManager::~MxVideoManager() -{ - // TODO -} - -// OFFSET: LEGO1 0x100bea90 STUB -MxLong MxVideoManager::Tickle() -{ - // TODO - - return 0; -} +#include "mxautolocker.h" +#include "mxpresenter.h" // OFFSET: LEGO1 0x100be1f0 MxVideoManager::MxVideoManager() @@ -20,16 +8,85 @@ MxVideoManager::MxVideoManager() Init(); } +// OFFSET: LEGO1 0x100be2a0 STUB +MxVideoManager::~MxVideoManager() +{ + // TODO +} + +// OFFSET: LEGO1 0x100bea90 +MxResult MxVideoManager::Tickle() +{ + MxAutoLocker lock(&this->m_criticalSection); + + SortPresenterList(); + + MxPresenter *presenter; + MxPresenterListCursor cursor(this->m_presenters); + + while (cursor.Next(presenter)) + presenter->Tickle(); + + cursor.Reset(); + + while (cursor.Next(presenter)) + presenter->PutData(); + + UpdateRegion(); + m_region->Reset(); + + return SUCCESS; +} + // OFFSET: LEGO1 0x100be320 -int MxVideoManager::Init() +MxResult MxVideoManager::Init() { this->m_pDirectDraw = NULL; - this->m_unk54 = NULL; + this->m_pDDSurface = NULL; this->m_displaySurface = NULL; - this->m_unk5c = 0; + this->m_region = NULL; this->m_videoParam.SetPalette(NULL); this->m_unk60 = FALSE; - return 0; + return SUCCESS; +} + +// OFFSET: LEGO1 0x100be440 +void MxVideoManager::SortPresenterList() +{ + if (this->m_presenters->GetCount() <= 1) + return; + + MxPresenterListCursor a(this->m_presenters); + MxPresenterListCursor b(this->m_presenters); + MxU32 count = this->m_presenters->GetCount() - 1; + MxBool finished; + + if (count != 0) { + do { + a.Reset(); + b.Head(); + + finished = TRUE; + for (MxU32 i = count; i != 0; i--) { + MxPresenter *p_a, *p_b; + + a.Next(p_a); + b.Next(p_b); + + if (p_a->GetDisplayZ() < p_b->GetDisplayZ()) { + a.SetValue(p_b); + b.SetValue(p_a); + finished = FALSE; + } + } + } while (!finished && --count != 0); + } +} + +// OFFSET: LEGO1 0x100be3e0 STUB +void MxVideoManager::UpdateRegion() +{ + // TODO } // OFFSET: LEGO1 0x100bea60 STUB @@ -54,3 +111,15 @@ MxLong MxVideoManager::RealizePalette(MxPalette *p_palette) this->m_criticalSection.Leave(); return 0; } + +// OFFSET: LEGO1 0x100be600 STUB +void MxVideoManager::vtable0x28() +{ + +} + +// OFFSET: LEGO1 0x100bebe0 STUB +MxResult MxVideoManager::vtable0x2c(MxVideoParam& p_videoParam, undefined4 p_unknown1, MxU8 p_unknown2) +{ + return FAILURE; +} diff --git a/LEGO1/mxvideomanager.h b/LEGO1/mxvideomanager.h index 03eac8aa..f6e1a726 100644 --- a/LEGO1/mxvideomanager.h +++ b/LEGO1/mxvideomanager.h @@ -2,6 +2,7 @@ #define MXVIDEOMANAGER_H #include "mxdisplaysurface.h" +#include "mxregion.h" #include "mxmediamanager.h" #include "mxvideoparam.h" @@ -12,23 +13,28 @@ class MxVideoManager : public MxMediaManager public: virtual ~MxVideoManager(); - virtual MxLong Tickle(); // vtable+0x8 + virtual MxResult Tickle() override; // vtable+0x8 + virtual void vtable0x28(); // vtable+0x28 (TODO ARGUMENTS) + virtual MxResult vtable0x2c(MxVideoParam& p_videoParam, undefined4 p_unknown1, MxU8 p_unknown2); // vtable+0x2c __declspec(dllexport) void InvalidateRect(MxRect32 &); __declspec(dllexport) virtual MxLong RealizePalette(MxPalette *); // vtable+0x30 MxVideoManager(); - int Init(); + MxResult Init(); + void SortPresenterList(); + void UpdateRegion(); inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } inline LPDIRECTDRAW GetDirectDraw() { return this->m_pDirectDraw; } -private: + inline MxDisplaySurface *GetDisplaySurface() { return this->m_displaySurface; } +protected: MxVideoParam m_videoParam; LPDIRECTDRAW m_pDirectDraw; - LPDIRECTDRAWSURFACE m_unk54; + LPDIRECTDRAWSURFACE m_pDDSurface; MxDisplaySurface *m_displaySurface; - int m_unk5c; + MxRegion *m_region; MxBool m_unk60; }; diff --git a/LEGO1/mxvideoparamflags.h b/LEGO1/mxvideoparamflags.h index f25ab4bd..8d1714ed 100644 --- a/LEGO1/mxvideoparamflags.h +++ b/LEGO1/mxvideoparamflags.h @@ -3,20 +3,7 @@ #include -// Must be union with struct for match. -typedef union { - struct { - BYTE bit0: 1; - BYTE bit1: 1; - BYTE bit2: 1; - BYTE bit3: 1; - BYTE bit4: 1; - BYTE bit5: 1; - BYTE bit6: 1; - BYTE bit7: 1; - }; - // BYTE all; // ? -} flag_bitfield; +#include "mxtypes.h" class MxVideoParamFlags { diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index 4e47e4a4..42dc34f3 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -2,8 +2,94 @@ DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64); +// OFFSET: LEGO1 0x1000c700 STUB +void MxVideoPresenter::VTable0x5c() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c710 +void MxVideoPresenter::VTable0x60() +{ + // Empty +} + +// OFFSET: LEGO1 0x1000c720 STUB +void MxVideoPresenter::VTable0x68() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c730 STUB +void MxVideoPresenter::VTable0x70() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c740 +MxVideoPresenter::~MxVideoPresenter() +{ + Destroy(TRUE); +} + +// OFFSET: LEGO1 0x1000c7a0 STUB +void MxVideoPresenter::InitVirtual() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c7b0 STUB +void MxVideoPresenter::VTable0x78() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c7c0 +MxBool MxVideoPresenter::VTable0x7c() +{ + return (m_bitmap != NULL) || (m_unk54 != NULL); +} + +// OFFSET: LEGO1 0x1000c7e0 +MxS32 MxVideoPresenter::GetWidth() +{ + return m_unk54 ? m_unk54->width + : m_bitmap->GetBmiHeader()->biWidth; +} + +// OFFSET: LEGO1 0x1000c800 +MxS32 MxVideoPresenter::GetHeight() +{ + return m_unk54 ? m_unk54->height + : m_bitmap->GetBmiHeader()->biHeight; +} + // OFFSET: LEGO1 0x100b2760 STUB void MxVideoPresenter::Init() { // TODO } + +// OFFSET: LEGO1 0x100b27b0 STUB +void MxVideoPresenter::Destroy(MxBool) +{ + // TODO +} + +// OFFSET: LEGO1 0x100b28b0 STUB +void MxVideoPresenter::VTable0x64() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b2a70 STUB +void MxVideoPresenter::VTable0x6c() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b3300 STUB +void MxVideoPresenter::VTable0x74() +{ + // TODO +} diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index 19c211c3..9c9a21a3 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -2,9 +2,11 @@ #define MXVIDEOPRESENTER_H #include "mxmediapresenter.h" +#include "mxbitmap.h" #include "decomp.h" +// VTABLE 0x100d4be8 class MxVideoPresenter : public MxMediaPresenter { public: @@ -13,6 +15,8 @@ class MxVideoPresenter : public MxMediaPresenter Init(); } + virtual ~MxVideoPresenter() override; // vtable+0x0 + // OFFSET: LEGO1 0x1000c820 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -27,12 +31,35 @@ class MxVideoPresenter : public MxMediaPresenter } void Init(); + void Destroy(MxBool); - undefined4 m_unk50; - undefined4 m_unk54; + virtual void InitVirtual() override; // vtable+0x38 + + virtual void VTable0x5c(); // vtable+0x5c + virtual void VTable0x60(); // vtable+0x60 + virtual void VTable0x64(); // vtable+0x64 + virtual void VTable0x68(); // vtable+0x68 + virtual void VTable0x6c(); // vtable+0x6c + virtual void VTable0x70(); // vtable+0x70 + virtual void VTable0x74(); // vtable+0x74 + virtual void VTable0x78(); // vtable+0x78 + virtual MxBool VTable0x7c(); // vtable+0x7c + virtual MxS32 GetWidth(); // vtable+0x80 + virtual MxS32 GetHeight(); // vtable+0x84 + + // TODO: Not sure what this is. Seems to have size of 12 bytes + // based on 0x100b9e9a. Values are copied from the bitmap header. + typedef struct { + undefined unk0[8]; + MxU16 width; + MxU16 height; + } unknown_meta_struct; + + MxBitmap *m_bitmap; + unknown_meta_struct *m_unk54; undefined4 m_unk58; undefined2 m_unk5c; - unsigned char m_flags; + unsigned char m_flags; // 0x5e undefined4 m_unk60; }; diff --git a/LEGO1/pizza.cpp b/LEGO1/pizza.cpp index 7e153b26..047e34bb 100644 --- a/LEGO1/pizza.cpp +++ b/LEGO1/pizza.cpp @@ -1,13 +1,11 @@ #include "pizza.h" -#include "decomp.h" - DECOMP_SIZE_ASSERT(Pizza, 0x9c); // OFFSET: LEGO1 0x10037ef0 Pizza::Pizza() { - // FIXME: This inherits from LegoActor, probably why this isn't matching + this->m_unk7c = 0; this->m_unk80 = 0; this->m_unk84 = 0; this->m_unk88 = 0; diff --git a/LEGO1/pizza.h b/LEGO1/pizza.h index 34d781c9..d6909810 100644 --- a/LEGO1/pizza.h +++ b/LEGO1/pizza.h @@ -1,6 +1,8 @@ #ifndef PIZZA_H #define PIZZA_H +#include "decomp.h" + #include "isleactor.h" #include "mxcore.h" #include "mxomni.h" @@ -29,16 +31,17 @@ class Pizza : public IsleActor { return !strcmp(name, Pizza::ClassName()) || IsleActor::IsA(name); } + private: - MxS32 m_unk78; - MxS32 m_unk7c; - MxS32 m_unk80; - MxS32 m_unk84; - MxS32 m_unk88; - MxS32 m_unk8c; - MxU32 m_unk90; - MxS32 m_unk94; - MxS32 m_unk98; + undefined4 m_unk78; + undefined4 m_unk7c; + undefined4 m_unk80; + undefined4 m_unk84; + undefined4 m_unk88; + undefined4 m_unk8c; + undefined4 m_unk90; + undefined4 m_unk94; + undefined m_unk98; }; #endif // PIZZA_H diff --git a/LEGO1/police.h b/LEGO1/police.h index 8ff6dff9..a11264da 100644 --- a/LEGO1/police.h +++ b/LEGO1/police.h @@ -13,7 +13,19 @@ class Police : public LegoWorld virtual ~Police() override; // vtable+0x0 virtual MxLong Notify(MxParam &p) override; // vtable+0x4 - + + // OFFSET: LEGO1 0x1005e1e0 + inline virtual const char *ClassName() const override // vtable+0xc + { + // 0x100f0450 + return "Police"; + } + + // OFFSET: LEGO1 0x1005e1f0 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, Police::ClassName()) || LegoWorld::IsA(name); + } }; #endif // POLICE_H diff --git a/LEGO1/policeentity.h b/LEGO1/policeentity.h index a23cced4..3a301016 100644 --- a/LEGO1/policeentity.h +++ b/LEGO1/policeentity.h @@ -7,7 +7,19 @@ // SIZE 0x68 class PoliceEntity : public BuildingEntity { +public: + // OFFSET: LEGO1 0x1000ed60 + inline virtual const char *ClassName() const override // vtable+0xc + { + // 0x100f0328 + return "PoliceEntity"; + } + // OFFSET: LEGO1 0x1000ed70 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, PoliceEntity::ClassName()) || BuildingEntity::IsA(name); + } }; #endif // POLICEENTITY_H diff --git a/LEGO1/racecar.cpp b/LEGO1/racecar.cpp index 59bb5146..4e4a4a21 100644 --- a/LEGO1/racecar.cpp +++ b/LEGO1/racecar.cpp @@ -1,9 +1,11 @@ #include "racecar.h" -// OFFSET: LEGO1 0x10028200 STUB +DECOMP_SIZE_ASSERT(RaceCar, 0x164); + +// OFFSET: LEGO1 0x10028200 RaceCar::RaceCar() { - // TODO + this->m_unk13c = 40.0; } // OFFSET: LEGO1 0x10028420 STUB diff --git a/LEGO1/racecar.h b/LEGO1/racecar.h index f8bd6ccf..f10d9b62 100644 --- a/LEGO1/racecar.h +++ b/LEGO1/racecar.h @@ -1,6 +1,7 @@ #ifndef RACECAR_H #define RACECAR_H +#include "decomp.h" #include "islepathactor.h" // VTABLE 0x100d6918 @@ -10,6 +11,22 @@ class RaceCar : public IslePathActor public: RaceCar(); virtual ~RaceCar() override; // vtable+0x0 + + // OFFSET: LEGO1 0x10028270 + inline virtual const char *ClassName() const override // vtable+0x0c + { + // 0x100f03e0 + return "RaceCar"; + } + + // OFFSET: LEGO1 0x10028280 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, RaceCar::ClassName()) || IslePathActor::IsA(name); + } +private: + // TODO: RaceCar fields + undefined m_unk160[4]; }; #endif // RACECAR_H diff --git a/LEGO1/skateboard.cpp b/LEGO1/skateboard.cpp index 42466206..b67e127e 100644 --- a/LEGO1/skateboard.cpp +++ b/LEGO1/skateboard.cpp @@ -1,7 +1,19 @@ #include "skateboard.h" -// OFFSET: LEGO1 0x1000fd40 STUB +#include "mxomni.h" +#include "mxnotificationmanager.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(SkateBoard, 0x168); + +// OFFSET: LEGO1 0x1000fd40 SkateBoard::SkateBoard() { - // TODO + this->m_unk160 = 0; + this->m_unk13c = 15.0; + this->m_unk150 = 3.5; + this->m_unk148 = 1; + + NotificationManager()->Register(this); } diff --git a/LEGO1/skateboard.h b/LEGO1/skateboard.h index f290dc7b..e7fb1fc8 100644 --- a/LEGO1/skateboard.h +++ b/LEGO1/skateboard.h @@ -1,6 +1,7 @@ #ifndef SKATEBOARD_H #define SKATEBOARD_H +#include "decomp.h" #include "islepathactor.h" // VTABLE 0x100d55f0 @@ -10,6 +11,22 @@ class SkateBoard : public IslePathActor public: SkateBoard(); + // OFFSET: LEGO1 0x1000fdd0 + inline virtual const char *ClassName() const override // vtable+0x0c + { + // 0x100f041c + return "SkateBoard"; + } + + // OFFSET: LEGO1 0x1000fde0 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, SkateBoard::ClassName()) || IslePathActor::IsA(name); + } +private: + // TODO: SkateBoard types + undefined m_unk160; + undefined m_unk161[0x7]; }; #endif // SKATEBOARD_H diff --git a/LEGO1/towtrack.cpp b/LEGO1/towtrack.cpp index 90d3d018..3b7a9264 100644 --- a/LEGO1/towtrack.cpp +++ b/LEGO1/towtrack.cpp @@ -1,7 +1,17 @@ #include "towtrack.h" -// OFFSET: LEGO1 0x1004c720 STUB +DECOMP_SIZE_ASSERT(TowTrack, 0x180); + +// OFFSET: LEGO1 0x1004c720 TowTrack::TowTrack() { - // TODO + this->m_unk168 = 0; + this->m_unk16a = -1; + this->m_unk164 = 0; + this->m_unk16c = 0; + this->m_unk170 = -1; + this->m_unk16e = 0; + this->m_unk174 = -1; + this->m_unk13c = 40.0; + this->m_unk178 = 1.0; } diff --git a/LEGO1/towtrack.h b/LEGO1/towtrack.h index 95e6885a..7263ab3a 100644 --- a/LEGO1/towtrack.h +++ b/LEGO1/towtrack.h @@ -1,6 +1,7 @@ #ifndef TOWTRACK_H #define TOWTRACK_H +#include "decomp.h" #include "islepathactor.h" // VTABLE 0x100d7ee0 @@ -10,6 +11,31 @@ class TowTrack : public IslePathActor public: TowTrack(); + // OFFSET: LEGO1 0x1004c7c0 + inline virtual const char *ClassName() const override // vtable+0x0c + { + // 0x100f03b8 + return "TowTrack"; + } + + // OFFSET: LEGO1 0x1004c7d0 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, TowTrack::ClassName()) || IslePathActor::IsA(name); + } + +private: + // TODO: TowTrack field types + undefined m_unk154[4]; + MxS32 m_unk164; + MxS16 m_unk168; + MxS16 m_unk16a; + MxS16 m_unk16c; + MxS16 m_unk16e; + MxS32 m_unk170; + MxS32 m_unk174; + MxFloat m_unk178; + undefined4 m_unk17c; }; diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index 1beec5dd..f26ab764 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -10,6 +10,7 @@ import os import sys import colorama +import html import re parser = argparse.ArgumentParser(allow_abbrev=False, @@ -43,7 +44,7 @@ verbose = int(args.verbose, 16) except ValueError: parser.error('invalid verbose argument') -html = args.html +html_path = args.html plain = args.no_color @@ -113,7 +114,7 @@ def __init__(self, unix_cwd): def get_wine_path(self, unix_fn: str) -> str: if unix_fn.startswith('./'): - return self.win_cmd + '\\' + unix_fn[2:].replace('/', '\\') + return self.win_cwd + '\\' + unix_fn[2:].replace('/', '\\') if unix_fn.startswith(self.unix_cwd): return self.win_cwd + '\\' + unix_fn.removeprefix(self.unix_cwd).replace('/', '\\').lstrip('\\') return self._call_winepath_unix2win(unix_fn) @@ -140,6 +141,7 @@ def get_file_in_script_dir(fn): class SymInfo: funcs = {} lines = {} + names = {} def __init__(self, pdb, file, wine_path_converter): call = [get_file_in_script_dir('cvdump.exe'), '-l', '-s'] @@ -183,6 +185,7 @@ def __init__(self, pdb, file, wine_path_converter): info.name = line[77:] + self.names[info.name] = info self.funcs[addr] = info elif current_section == 'LINES' and line.startswith(' ') and not line.startswith(' '): sourcepath = line.split()[0] @@ -238,6 +241,14 @@ def get_recompiled_address(self, filename, line): else: logger.error('Failed to find function symbol with filename and line: %s:%d', filename, line) + def get_recompiled_address_from_name(self, name): + logger.debug('Looking for %s', name) + + if name in self.names: + return self.names[name] + else: + logger.error('Failed to find function symbol with name: %s', name) + wine_path_converter = None if os.name != 'nt': wine_path_converter = WinePathConverter(source) @@ -419,14 +430,24 @@ def can_resolve_register_differences(original_asm, new_asm): else: continue - find_open_bracket = line - while '{' not in find_open_bracket: - find_open_bracket = srcfile.readline() - line_no += 1 + if line.endswith("TEMPLATE"): + line = srcfile.readline() + line_no += 1 + # Name comes after // comment + name = line[2:].strip() - recinfo = syminfo.get_recompiled_address(srcfilename, line_no) - if not recinfo: - continue + recinfo = syminfo.get_recompiled_address_from_name(name) + if not recinfo: + continue + else: + find_open_bracket = line + while '{' not in find_open_bracket: + find_open_bracket = srcfile.readline() + line_no += 1 + + recinfo = syminfo.get_recompiled_address(srcfilename, line_no) + if not recinfo: + continue # The effective_ratio is the ratio when ignoring differing register # allocation vs the ratio is the true ratio. @@ -463,11 +484,12 @@ def can_resolve_register_differences(original_asm, new_asm): else: percenttext += colorama.Fore.RED + "*" + colorama.Style.RESET_ALL + if args.print_rec_addr: + addrs = '%s / %s' % (hex(addr), hex(recinfo.addr)) + else: + addrs = hex(addr) + if not verbose: - if args.print_rec_addr: - addrs = '%s / %s' % (hex(addr), hex(recinfo.addr)) - else: - addrs = hex(addr) print(' %s (%s) is %s similar to the original' % (recinfo.name, addrs, percenttext)) function_count += 1 @@ -477,16 +499,16 @@ def can_resolve_register_differences(original_asm, new_asm): if recinfo.size: udiff = difflib.unified_diff(origasm, recompasm, n=10) - # If verbose, print the diff for that funciton to the output + # If verbose, print the diff for that function to the output if verbose: if effective_ratio == 1.0: ok_text = "OK!" if plain else (colorama.Fore.GREEN + "✨ OK! ✨" + colorama.Style.RESET_ALL) if ratio == 1.0: print("%s: %s 100%% match.\n\n%s\n\n" % - (hex(addr), recinfo.name, ok_text)) + (addrs, recinfo.name, ok_text)) else: print("%s: %s Effective 100%% match. (Differs in register allocation only)\n\n%s (still differs in register allocation)\n\n" % - (hex(addr), recinfo.name, ok_text)) + (addrs, recinfo.name, ok_text)) else: for line in udiff: if line.startswith("++") or line.startswith("@@") or line.startswith("--"): @@ -510,14 +532,14 @@ def can_resolve_register_differences(original_asm, new_asm): print("\n%s is only %s similar to the original, diff above" % (recinfo.name, percenttext)) # If html, record the diffs to an HTML file - if html: + if html_path: escaped = '\\n'.join(udiff).replace('"', '\\"').replace('\n', '\\n').replace('<', '<').replace('>', '>') - htmlinsert.append('{address: "%s", name: "%s", matching: %s, diff: "%s"}' % (hex(addr), recinfo.name, str(effective_ratio), escaped)) + htmlinsert.append('{address: "%s", name: "%s", matching: %s, diff: "%s"}' % (hex(addr), html.escape(recinfo.name), str(effective_ratio), escaped)) except UnicodeDecodeError: break -def gen_html(html, data): +def gen_html(html_path, data): templatefile = open(get_file_in_script_dir('template.html'), 'r') if not templatefile: print('Failed to find HTML template file, can\'t generate HTML summary') @@ -528,9 +550,9 @@ def gen_html(html, data): templatedata = templatedata.replace('/* INSERT DATA HERE */', ','.join(data), 1) - htmlfile = open(html, 'w') + htmlfile = open(html_path, 'w') if not htmlfile: - print('Failed to write to HTML file %s' % html) + print('Failed to write to HTML file %s' % html_path) return htmlfile.write(templatedata) @@ -579,8 +601,8 @@ def gen_svg(svg, name, icon, implemented_funcs, total_funcs, raw_accuracy): svgfile.write(templatedata) svgfile.close() -if html: - gen_html(html, htmlinsert) +if html_path: + gen_html(html_path, htmlinsert) if verbose: if not found_verbose_target: