diff --git a/CMakeLists.txt b/CMakeLists.txt index f1c5f499..baa5011f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,7 @@ option(ISLE_BUILD_APP "Build ISLE.EXE application" ON) cmake_dependent_option(ISLE_BUILD_CONFIG "Build CONFIG.EXE application" ON "NOT MINGW" OFF) option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" ${NOT_MINGW}) cmake_dependent_option(ISLE_D3DRM_FROM_WINE "Use d3drm from wine" "${MINGW}" "NOT ISLE_USE_DX5" OFF) +option(ISLE_DECOMP_ASSERT "Assert struct size" ${MSVC_FOR_DECOMP}) message(STATUS "Using internal DirectX5 SDK: ${ISLE_USE_DX5}") message(STATUS "Using d3drm from wine: ${ISLE_D3DRM_FROM_WINE}") @@ -174,6 +175,7 @@ add_library(mxdirectx STATIC LEGO1/mxdirectx/mxdirect3d.cpp LEGO1/mxdirectx/mxdirectdraw.cpp LEGO1/mxdirectx/mxdirectxinfo.cpp + LEGO1/mxdirectx/legodxinfo.cpp ) register_lego1_target(mxdirectx) set_property(TARGET mxdirectx PROPERTY ARCHIVE_OUTPUT_NAME "MxDirectX$<$:d>") @@ -327,7 +329,7 @@ add_library(lego1 SHARED LEGO1/define.cpp LEGO1/lego/legoomni/src/actors/act2actor.cpp LEGO1/lego/legoomni/src/actors/act2genactor.cpp - LEGO1/lego/legoomni/src/actors/act3actor.cpp + LEGO1/lego/legoomni/src/actors/act3actors.cpp LEGO1/lego/legoomni/src/actors/act3brickster.cpp LEGO1/lego/legoomni/src/actors/act3cop.cpp LEGO1/lego/legoomni/src/actors/act3shark.cpp @@ -412,7 +414,7 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/race/jetskirace.cpp LEGO1/lego/legoomni/src/race/legorace.cpp LEGO1/lego/legoomni/src/race/legoraceactor.cpp - LEGO1/lego/legoomni/src/race/legoracecar.cpp + LEGO1/lego/legoomni/src/race/legoracers.cpp LEGO1/lego/legoomni/src/race/legoracemap.cpp LEGO1/lego/legoomni/src/race/raceskel.cpp LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -511,6 +513,7 @@ endif() if (ISLE_BUILD_CONFIG) add_executable(config WIN32 LEGO1/mxdirectx/mxdirectxinfo.cpp + LEGO1/mxdirectx/legodxinfo.cpp CONFIG/config.cpp CONFIG/ConfigCommandLineInfo.cpp CONFIG/AboutDlg.cpp @@ -561,7 +564,8 @@ if(MSVC) target_link_options(lego1 PRIVATE "/SAFESEH:NO") endif() -if (MSVC_FOR_DECOMP) +if (ISLE_DECOMP_ASSERT) + message(STATUS "Decomp asserts enabled") foreach(tgt IN LISTS lego1_targets) target_compile_definitions(${tgt} PRIVATE "ENABLE_DECOMP_ASSERTS") endforeach() diff --git a/CONFIG/MainDlg.cpp b/CONFIG/MainDlg.cpp index da0b5d17..7ae5393e 100644 --- a/CONFIG/MainDlg.cpp +++ b/CONFIG/MainDlg.cpp @@ -4,7 +4,7 @@ #include "config.h" #include "res/resource.h" -#include +#include DECOMP_SIZE_ASSERT(CDialog, 0x60) DECOMP_SIZE_ASSERT(CMainDialog, 0x70) @@ -57,7 +57,7 @@ BOOL CMainDialog::OnInitDialog() } SendMessage(WM_SETICON, ICON_BIG, (LPARAM) m_icon); SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) m_icon); - MxDeviceEnumerate* enumerator = currentConfigApp->m_device_enumerator; + LegoDeviceEnumerate* enumerator = currentConfigApp->m_device_enumerator; enumerator->FUN_1009d210(); m_modified = currentConfigApp->ReadRegisterSettings(); CWnd* list_3d_devices = GetDlgItem(IDC_LIST_3DDEVICES); @@ -131,7 +131,7 @@ HCURSOR CMainDialog::OnQueryDragIcon() // FUNCTION: CONFIG 0x00404240 void CMainDialog::OnList3DevicesSelectionChanged() { - MxDeviceEnumerate* device_enumerator = currentConfigApp->m_device_enumerator; + LegoDeviceEnumerate* device_enumerator = currentConfigApp->m_device_enumerator; int selected = ::SendMessage(GetDlgItem(IDC_LIST_3DDEVICES)->m_hWnd, LB_GETCURSEL, 0, 0); device_enumerator->GetDevice(selected, currentConfigApp->m_driver, currentConfigApp->m_device); if (currentConfigApp->GetHardwareDeviceColorModel()) { diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp index 59c03332..d4457b55 100644 --- a/CONFIG/config.cpp +++ b/CONFIG/config.cpp @@ -5,6 +5,7 @@ #include "detectdx5.h" #include // _chdir +#include #include #include // _spawnl diff --git a/LEGO1/lego/legoomni/include/act3actor.h b/LEGO1/lego/legoomni/include/act3actors.h similarity index 78% rename from LEGO1/lego/legoomni/include/act3actor.h rename to LEGO1/lego/legoomni/include/act3actors.h index b71939e0..ac955816 100644 --- a/LEGO1/lego/legoomni/include/act3actor.h +++ b/LEGO1/lego/legoomni/include/act3actors.h @@ -1,10 +1,13 @@ -#ifndef ACT3ACTOR_H -#define ACT3ACTOR_H +#ifndef ACT3ACTORS_H +#define ACT3ACTORS_H #include "legoanimactor.h" +// File name verified by multiple assertions, e.g. BETA10 0x10018391 + // VTABLE: LEGO1 0x100d7668 LegoPathActor // VTABLE: LEGO1 0x100d7738 LegoAnimActor +// VTABLE: BETA10 0x101b8a98 LegoPathActor // SIZE 0x178 class Act3Actor : public LegoAnimActor { public: @@ -30,4 +33,4 @@ class Act3Actor : public LegoAnimActor { undefined4 m_unk0x1c; // 0x1c }; -#endif // ACT3ACTOR_H +#endif // ACT3ACTORS_H diff --git a/LEGO1/lego/legoomni/include/act3brickster.h b/LEGO1/lego/legoomni/include/act3brickster.h index f9066d3c..c84b8dd7 100644 --- a/LEGO1/lego/legoomni/include/act3brickster.h +++ b/LEGO1/lego/legoomni/include/act3brickster.h @@ -1,7 +1,7 @@ #ifndef ACT3BRICKSTER_H #define ACT3BRICKSTER_H -#include "act3actor.h" +#include "act3actors.h" // VTABLE: LEGO1 0x100d7838 LegoPathActor // VTABLE: LEGO1 0x100d7908 LegoAnimActor diff --git a/LEGO1/lego/legoomni/include/act3cop.h b/LEGO1/lego/legoomni/include/act3cop.h index 29ac65b6..a720b84c 100644 --- a/LEGO1/lego/legoomni/include/act3cop.h +++ b/LEGO1/lego/legoomni/include/act3cop.h @@ -1,7 +1,7 @@ #ifndef ACT3COP_H #define ACT3COP_H -#include "act3actor.h" +#include "act3actors.h" // VTABLE: LEGO1 0x100d7750 LegoPathActor // VTABLE: LEGO1 0x100d7820 LegoAnimActor diff --git a/LEGO1/lego/legoomni/include/carrace.h b/LEGO1/lego/legoomni/include/carrace.h index fd33c536..5a43f420 100644 --- a/LEGO1/lego/legoomni/include/carrace.h +++ b/LEGO1/lego/legoomni/include/carrace.h @@ -52,6 +52,9 @@ class CarRace : public LegoRace { MxLong HandleEndAction(MxEndActionNotificationParam&) override; // vtable+0x74 MxLong HandleType0Notification(MxNotificationParam&) override; // vtable+0x78 + // FUNCTION: BETA10 0x100cd060 + undefined4 GetUnk0x150() { return m_unk0x150; } + // SYNTHETIC: LEGO1 0x10016c70 // CarRace::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/dunebuggy.h b/LEGO1/lego/legoomni/include/dunebuggy.h index 81b7bfe5..7302e0ce 100644 --- a/LEGO1/lego/legoomni/include/dunebuggy.h +++ b/LEGO1/lego/legoomni/include/dunebuggy.h @@ -32,12 +32,12 @@ class DuneBuggy : public IslePathActor { void ActivateSceneActions(); + static MxS32 GetColorOffset(const char* p_variable); + // SYNTHETIC: LEGO1 0x10067dc0 // DuneBuggy::`scalar deleting destructor' private: - static MxS32 GetDashboardOffset(const char* p_variable); - MxS16 m_dashboard; // 0x160 MxFloat m_fuel; // 0x164 MxFloat m_time; // 0x168 diff --git a/LEGO1/lego/legoomni/include/jetski.h b/LEGO1/lego/legoomni/include/jetski.h index 70102eac..e81824be 100644 --- a/LEGO1/lego/legoomni/include/jetski.h +++ b/LEGO1/lego/legoomni/include/jetski.h @@ -26,12 +26,12 @@ class Jetski : public IslePathActor { } MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x70(float p_time) override; // vtable+0x70 MxLong HandleClick() override; // vtable+0xcc MxLong HandleControl(LegoControlManagerNotificationParam&) override; // vtable+0xd4 void Exit() override; // vtable+0xe4 - void FUN_1007e990(); + void ActivateSceneActions(); MxS16 GetUnknown0x160() { return m_unk0x160; } @@ -39,9 +39,9 @@ class Jetski : public IslePathActor { // Jetski::`scalar deleting destructor' private: - // TODO: Jetski fields - MxS16 m_unk0x160; // 0x160 - undefined m_unk0x162[2]; // 0x162 + void RemoveFromWorld(); + + MxS16 m_unk0x160; // 0x160 }; #endif // JETSKI_H diff --git a/LEGO1/lego/legoomni/include/legoanimactor.h b/LEGO1/lego/legoomni/include/legoanimactor.h index e2843c3d..72f6bc1c 100644 --- a/LEGO1/lego/legoomni/include/legoanimactor.h +++ b/LEGO1/lego/legoomni/include/legoanimactor.h @@ -15,6 +15,10 @@ struct LegoAnimActorStruct { float GetUnknown0x00() { return m_unk0x00; } + // FUNCTION: BETA10 0x10012210 + LegoAnim* GetAnimTreePtr() { return m_AnimTreePtr; } + + // TODO: Possibly private float m_unk0x00; // 0x00 LegoAnim* m_AnimTreePtr; // 0x04 LegoROI** m_roiMap; // 0x08 diff --git a/LEGO1/lego/legoomni/include/legocarraceactor.h b/LEGO1/lego/legoomni/include/legocarraceactor.h index 35c099d2..6f1c72f4 100644 --- a/LEGO1/lego/legoomni/include/legocarraceactor.h +++ b/LEGO1/lego/legoomni/include/legocarraceactor.h @@ -38,7 +38,7 @@ class LegoCarRaceActor : public virtual LegoRaceActor { override; // vtable+0x98 MxResult VTable0x9c() override; // vtable+0x9c - virtual void FUN_10080590(); + virtual void FUN_10080590(float); // FUNCTION: LEGO1 0x10012bb0 virtual void FUN_10012bb0(float p_unk0x14) { m_unk0x14 = p_unk0x14; } @@ -60,6 +60,9 @@ class LegoCarRaceActor : public virtual LegoRaceActor { virtual void VTable0x1c(); // vtable+0x1c + // SYNTHETIC: LEGO1 0x10012c30 + // LegoCarRaceActor::`vbase destructor' + // SYNTHETIC: LEGO1 0x10081620 // LegoCarRaceActor::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index b5b4e880..115ed813 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -62,6 +62,7 @@ class LegoEntity : public MxEntity { virtual void ResetWorldTransform(MxBool p_cameraFlag); // vtable+0x2c // FUNCTION: LEGO1 0x10001090 + // FUNCTION: BETA10 0x10013260 virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 virtual void ClickSound(MxBool p_und); // vtable+0x34 @@ -83,7 +84,10 @@ class LegoEntity : public MxEntity { MxBool GetFlagsIsSet(MxU8 p_flag) { return m_flags & p_flag; } MxU8 GetFlags() { return m_flags; } MxFloat GetWorldSpeed() { return m_worldSpeed; } + + // FUNCTION: BETA10 0x1000f2f0 LegoROI* GetROI() { return m_roi; } + MxU8 GetType() { return m_type; } MxBool GetCameraFlag() { return m_cameraFlag; } diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index 70ee6950..5110c8ee 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -13,6 +13,8 @@ struct LegoPathEdgeContainer; struct LegoUnknown100db7f4; class LegoWEEdge; +extern MxLong g_unk0x100f3308; + // VTABLE: LEGO1 0x100d6e28 // SIZE 0x154 class LegoPathActor : public LegoActor { @@ -124,12 +126,18 @@ class LegoPathActor : public LegoActor { virtual void VTable0xc8(MxU8 p_unk0x148) { m_unk0x148 = p_unk0x148; } // vtable+0xc8 LegoPathBoundary* GetBoundary() { return m_boundary; } + + // FUNCTION: BETA10 0x1001c860 MxU32 GetState() { return m_state; } + LegoPathController* GetController() { return m_controller; } MxBool GetCollideBox() { return m_collideBox; } void SetBoundary(LegoPathBoundary* p_boundary) { m_boundary = p_boundary; } + + // FUNCTION: BETA10 0x10013430 void SetState(MxU32 p_state) { m_state = p_state; } + void SetController(LegoPathController* p_controller) { m_controller = p_controller; } // SYNTHETIC: LEGO1 0x1002d800 diff --git a/LEGO1/lego/legoomni/include/legoraceactor.h b/LEGO1/lego/legoomni/include/legoraceactor.h index 50d4a016..57325256 100644 --- a/LEGO1/lego/legoomni/include/legoraceactor.h +++ b/LEGO1/lego/legoomni/include/legoraceactor.h @@ -33,6 +33,9 @@ class LegoRaceActor : public virtual LegoAnimActor { // FUNCTION: LEGO1 0x10014aa0 virtual MxResult FUN_10014aa0() { return SUCCESS; } + // SYNTHETIC: LEGO1 0x10012c10 + // LegoRaceActor::`vbase destructor' + // SYNTHETIC: LEGO1 0x10014ac0 // LegoRaceActor::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoracecar.h b/LEGO1/lego/legoomni/include/legoracecar.h deleted file mode 100644 index d85e7d7b..00000000 --- a/LEGO1/lego/legoomni/include/legoracecar.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef LEGORACECAR_H -#define LEGORACECAR_H - -#include "legocarraceactor.h" -#include "legoracemap.h" - -// SIZE 0x08 -struct EdgeReference { - const char* m_name; // 0x00 - LegoPathBoundary* m_data; // 0x04 -}; - -// VTABLE: LEGO1 0x100d58a0 LegoRaceActor -// VTABLE: LEGO1 0x100d58a8 LegoAnimActor -// VTABLE: LEGO1 0x100d58b8 LegoPathActor -// VTABLE: LEGO1 0x100d5984 LegoRaceMap -// VTABLE: LEGO1 0x100d5988 LegoCarRaceActor -// SIZE 0x200 -class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { -public: - LegoRaceCar(); - ~LegoRaceCar() override; - - MxLong Notify(MxParam& p_param) override; // vtable+0x04 - - // FUNCTION: LEGO1 0x100142a0 - const char* ClassName() const override // vtable+0x0c - { - // STRING: LEGO1 0x100f0548 - return "LegoRaceCar"; - } - - // FUNCTION: LEGO1 0x100142c0 - MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoRaceCar::ClassName()) || LegoCarRaceActor::IsA(p_name); - } - - void ParseAction(char*) override; // vtable+0x20 - void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - MxU32 VTable0x6c( - LegoPathBoundary* p_boundary, - Vector3& p_v1, - Vector3& p_v2, - float p_f1, - float p_f2, - Vector3& p_v3 - ) override; // vtable+0x6c - void VTable0x70(float p_float) override; // vtable+0x70 - MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 - void SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4) - override; // vtable+0x98 - MxResult VTable0x9c() override; // vtable+0x9c - - virtual void SetMaxLinearVelocity(float p_maxLinearVelocity); - virtual void FUN_10012ff0(float); - virtual MxBool FUN_10013130(float); - - // SYNTHETIC: LEGO1 0x10014240 - // LegoRaceCar::`scalar deleting destructor' - -private: - undefined m_unk0x54; // 0x54 - undefined4 m_unk0x58; // 0x58 - Mx3DPointFloat m_unk0x5c; // 0x5c - LegoAnimActorStruct* m_unk0x70; // 0x70 - LegoAnimActorStruct* m_unk0x74; // 0x74 - LegoPathBoundary* m_unk0x78; // 0x78 - LegoPathBoundary* m_unk0x7c; // 0x7c - - static EdgeReference g_edgeReferences[]; - static const EdgeReference* g_pEdgeReferences; -}; - -#endif // LEGORACECAR_H diff --git a/LEGO1/lego/legoomni/include/legoracemap.h b/LEGO1/lego/legoomni/include/legoracemap.h index 99625dd9..3cbd7739 100644 --- a/LEGO1/lego/legoomni/include/legoracemap.h +++ b/LEGO1/lego/legoomni/include/legoracemap.h @@ -21,6 +21,9 @@ class LegoRaceMap : public virtual LegoRaceActor { // LegoRaceMap vtable virtual void FUN_1005d4b0(); // vtable+0x00 + // SYNTHETIC: LEGO1 0x10012c50 + // LegoRaceMap::`vbase destructor' + // SYNTHETIC: LEGO1 0x1005d5d0 // LegoRaceMap::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoracers.h b/LEGO1/lego/legoomni/include/legoracers.h new file mode 100644 index 00000000..d20de8a7 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoracers.h @@ -0,0 +1,117 @@ +#ifndef LEGORACERS_H +#define LEGORACERS_H + +#include "legocarraceactor.h" +#include "legoracemap.h" + +#define LEGORACECAR_UNKNOWN_0 0 +#define LEGORACECAR_UNKNOWN_1 1 +#define LEGORACECAR_KICK1 2 // name guessed +#define LEGORACECAR_KICK2 4 // name validated by BETA10 0x100cb659 + +// SIZE 0x08 +struct EdgeReference { + const char* m_name; // 0x00 + // name verified by BETA10 0x100cbee6 + LegoPathBoundary* m_b; // 0x04 +}; + +// SIZE 0x10 +struct SkeletonKickPhase { + EdgeReference* m_edgeRef; // 0x00 + float m_lower; // 0x04 + float m_upper; // 0x08 + MxU8 m_userState; // 0x0c +}; + +// VTABLE: LEGO1 0x100d58a0 LegoRaceActor +// VTABLE: LEGO1 0x100d58a8 LegoAnimActor +// VTABLE: LEGO1 0x100d58b8 LegoPathActor +// VTABLE: LEGO1 0x100d5984 LegoRaceMap +// VTABLE: LEGO1 0x100d5988 LegoCarRaceActor +// VTABLE: BETA10 0x101be6ec LegoRaceActor +// VTABLE: BETA10 0x101be6f0 LegoAnimActor +// VTABLE: BETA10 0x101be708 LegoPathActor +// VTABLE: BETA10 0x101be7f8 LegoRaceMap +// VTABLE: BETA10 0x101be800 LegoCarRaceActor +// SIZE 0x200 +class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { +public: + LegoRaceCar(); + ~LegoRaceCar() override; + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x100142a0 + const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0548 + return "LegoRaceCar"; + } + + // FUNCTION: LEGO1 0x100142c0 + MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoRaceCar::ClassName()) || LegoCarRaceActor::IsA(p_name); + } + + void ParseAction(char* p_extra) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + MxU32 VTable0x6c( + LegoPathBoundary* p_boundary, + Vector3& p_v1, + Vector3& p_v2, + float p_f1, + float p_f2, + Vector3& p_v3 + ) override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 + void SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4) + override; // vtable+0x98 + MxResult VTable0x9c() override; // vtable+0x9c + + virtual void SetMaxLinearVelocity(float p_maxLinearVelocity); + virtual void FUN_10012ff0(float p_param); + virtual MxU32 HandleSkeletonKicks(float p_param1); + + // SYNTHETIC: LEGO1 0x10014240 + // LegoRaceCar::`scalar deleting destructor' + +private: + undefined m_userState; // 0x54 + float m_unk0x58; // 0x58 + Mx3DPointFloat m_unk0x5c; // 0x5c + + // Names verified by BETA10 0x100cb4a9 + LegoAnimActorStruct* m_skelKick1Anim; // 0x70 + LegoAnimActorStruct* m_skelKick2Anim; // 0x74 + + // Name verified by BETA10 0x100cb4f0 + LegoPathBoundary* m_kick1B; // 0x78 + + // Name verified by BETA10 0x100cb537 + LegoPathBoundary* m_kick2B; // 0x7c + + // name verified by BETA10 0x100cbee6 + static EdgeReference g_skBMap[]; + + static const SkeletonKickPhase g_skeletonKickPhases[]; + static const char* g_strSpeed; + static const char* g_srtsl18to29[]; + static const char* g_srtsl6to10[]; + static const char* g_emptySoundKeyList[]; + static const char* g_srtrh[]; + static const char* g_srt001ra; + static const char* g_soundSkel3; + static MxU32 g_srtsl18to29Index; + static MxU32 g_srtsl6to10Index; + static MxU32 g_emptySoundKeyListIndex; + static MxU32 g_srtrhIndex; + static MxLong g_timeLastSoundPlayed; + static MxS32 g_unk0x100f0b88; + static MxBool g_unk0x100f0b8c; + static Mx3DPointFloat g_unk0x10102af0; +}; + +#endif // LEGORACERS_H diff --git a/LEGO1/lego/legoomni/include/legovariables.h b/LEGO1/lego/legoomni/include/legovariables.h index 1901a254..1b5cd93b 100644 --- a/LEGO1/lego/legoomni/include/legovariables.h +++ b/LEGO1/lego/legoomni/include/legovariables.h @@ -3,12 +3,15 @@ #include "mxvariable.h" +extern const char* g_varJETSPEED; +extern const char* g_varJETFUEL; extern const char* g_varDUNESPEED; extern const char* g_varDUNEFUEL; extern const char* g_varMOTOSPEED; extern const char* g_varMOTOFUEL; extern const char* g_varAMBULSPEED; extern const char* g_varAMBULFUEL; +extern const char* g_varTOWSPEED; extern const char* g_varTOWFUEL; extern const char* g_varVISIBILITY; extern const char* g_varCAMERALOCATION; diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 8cec279c..d248ab5b 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -97,7 +97,9 @@ class LegoWorld : public LegoEntity { MxCore* Find(const char* p_class, const char* p_name); MxCore* Find(const MxAtomId& p_atom, MxS32 p_entityId); + // FUNCTION: BETA10 0x1002b4f0 LegoCameraController* GetCamera() { return m_cameraController; } + LegoEntityList* GetEntityList() { return m_entityList; } MxS32 GetWorldId() { return m_worldId; } MxBool GetUnknown0xd0Empty() { return m_set0xd0.empty(); } diff --git a/LEGO1/lego/legoomni/include/raceskel.h b/LEGO1/lego/legoomni/include/raceskel.h index 6d9a270b..fca57dde 100644 --- a/LEGO1/lego/legoomni/include/raceskel.h +++ b/LEGO1/lego/legoomni/include/raceskel.h @@ -12,8 +12,10 @@ class RaceSkel : public LegoAnimActor { public: RaceSkel(); + void GetCurrentAnimData(float* p_outCurAnimPosition, float* p_outCurAnimDuration); + private: - undefined4 m_unk0x1c; // 0x1c + float m_animPosition; // 0x1c }; #endif // RACESKEL_H diff --git a/LEGO1/lego/legoomni/include/towtrack.h b/LEGO1/lego/legoomni/include/towtrack.h index ebcefb54..3d9c7a1a 100644 --- a/LEGO1/lego/legoomni/include/towtrack.h +++ b/LEGO1/lego/legoomni/include/towtrack.h @@ -48,8 +48,8 @@ class TowTrackMissionState : public LegoState { // TowTrackMissionState::`scalar deleting destructor' undefined4 m_unk0x08; // 0x08 - undefined4 m_unk0x0c; // 0x0c - MxU8 m_unk0x10; // 0x10 + MxS32 m_unk0x0c; // 0x0c + MxBool m_unk0x10; // 0x10 MxS16 m_unk0x12; // 0x12 MxS16 m_unk0x14; // 0x14 MxS16 m_unk0x16; // 0x16 @@ -84,7 +84,7 @@ class TowTrack : public IslePathActor { MxLong Notify(MxParam& p_param) override; // vtable+0x04 MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x70(float p_time) override; // vtable+0x70 MxLong HandleClick() override; // vtable+0xcc MxLong HandleControl(LegoControlManagerNotificationParam& p_param) override; // vtable+0xd4 MxLong HandleEndAnim(LegoEndAnimNotificationParam& p_param) override; // vtable+0xd8 @@ -101,6 +101,8 @@ class TowTrack : public IslePathActor { // TowTrack::`scalar deleting destructor' private: + void FUN_1004dcf0(IsleScript::Script); + undefined4 m_unk0x160; // 0x160 TowTrackMissionState* m_state; // 0x164 MxS16 m_unk0x168; // 0x168 @@ -109,7 +111,7 @@ class TowTrack : public IslePathActor { MxS16 m_unk0x16e; // 0x16e MxS32 m_unk0x170; // 0x170 MxS32 m_unk0x174; // 0x174 - MxFloat m_unk0x178; // 0x178 + MxFloat m_fuel; // 0x178 MxFloat m_time; // 0x17c }; diff --git a/LEGO1/lego/legoomni/src/actors/act3actor.cpp b/LEGO1/lego/legoomni/src/actors/act3actors.cpp similarity index 92% rename from LEGO1/lego/legoomni/src/actors/act3actor.cpp rename to LEGO1/lego/legoomni/src/actors/act3actors.cpp index 5ae24f14..01359090 100644 --- a/LEGO1/lego/legoomni/src/actors/act3actor.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3actors.cpp @@ -1,4 +1,4 @@ -#include "act3actor.h" +#include "act3actors.h" DECOMP_SIZE_ASSERT(Act3Actor, 0x178) diff --git a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp index 30aff459..a4504310 100644 --- a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp +++ b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp @@ -102,7 +102,7 @@ MxLong DuneBuggy::HandleClick() } m_time = Timer()->GetTime(); - m_dashboard = IsleScript::c_DuneCarSpeedMeter + GetDashboardOffset(g_varDBFRFNY4); + m_dashboard = IsleScript::c_DuneCarSpeedMeter + GetColorOffset(g_varDBFRFNY4); InvokeAction(Extra::ActionType::e_start, *g_isleScript, m_dashboard, NULL); InvokeAction(Extra::ActionType::e_start, *g_isleScript, IsleScript::c_DuneCarDashboard, NULL); @@ -157,30 +157,30 @@ MxLong DuneBuggy::HandlePathStruct(LegoPathStructNotificationParam& p_param) } // FUNCTION: LEGO1 0x10068290 -MxS32 DuneBuggy::GetDashboardOffset(const char* p_variable) +MxS32 DuneBuggy::GetColorOffset(const char* p_variable) { - MxS32 color = 1; + MxS32 offset = 1; const char* colorName = VariableTable()->GetVariable(p_variable); if (strcmpi(colorName, "lego green")) { if (!strcmpi(colorName, "lego red")) { - color = 2; + offset = 2; } else if (!strcmpi(colorName, "lego yellow")) { - color = 3; + offset = 3; } else if (!strcmpi(colorName, "lego black")) { - color = 4; + offset = 4; } else if (!strcmpi(colorName, "lego blue")) { - color = 5; + offset = 5; } else if (!strcmpi(colorName, "lego white")) { - color = 6; + offset = 6; } } - return color; + return offset; } // FUNCTION: LEGO1 0x10068350 diff --git a/LEGO1/lego/legoomni/src/actors/jetski.cpp b/LEGO1/lego/legoomni/src/actors/jetski.cpp index a65268ac..158df471 100644 --- a/LEGO1/lego/legoomni/src/actors/jetski.cpp +++ b/LEGO1/lego/legoomni/src/actors/jetski.cpp @@ -1,50 +1,163 @@ #include "jetski.h" +#include "dunebuggy.h" +#include "isle.h" +#include "isle_actions.h" +#include "jukebox_actions.h" +#include "legoanimationmanager.h" +#include "legocontrolmanager.h" +#include "legonavcontroller.h" +#include "legoutils.h" +#include "legovariables.h" +#include "legoworld.h" +#include "misc.h" +#include "mxmisc.h" +#include "mxtransitionmanager.h" +#include "mxvariabletable.h" +#include "scripts.h" + DECOMP_SIZE_ASSERT(Jetski, 0x164) +// GLOBAL: LEGO1 0x100f7ab8 +// STRING: LEGO1 0x100f3ce0 +const char* g_varJSFRNTY5 = "c_jsfrnty5"; + +// GLOBAL: LEGO1 0x100f7abc +// STRING: LEGO1 0x100f3ca4 +const char* g_varJSWNSHY5 = "c_jswnshy5"; + // FUNCTION: LEGO1 0x1007e3b0 Jetski::Jetski() { - this->m_maxLinearVel = 25.0; - this->m_unk0x150 = 2.0; - this->m_unk0x148 = 1; + m_maxLinearVel = 25.0; + m_unk0x150 = 2.0; + m_unk0x148 = 1; } -// STUB: LEGO1 0x1007e630 +// FUNCTION: LEGO1 0x1007e630 MxResult Jetski::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = IslePathActor::Create(p_dsAction); + m_world = CurrentWorld(); + + if (m_world) { + m_world->Add(this); + } + + VariableTable()->SetVariable(g_varJETFUEL, "0.8"); + return result; } -// STUB: LEGO1 0x1007e680 -void Jetski::VTable0x70(float p_float) +// FUNCTION: LEGO1 0x1007e680 +void Jetski::VTable0x70(float p_time) { - // TODO + IslePathActor::VTable0x70(p_time); + + char buf[200]; + float speed = abs(m_worldSpeed); + float maxLinearVel = NavController()->GetMaxLinearVel(); + + sprintf(buf, "%g", speed / maxLinearVel); + VariableTable()->SetVariable(g_varJETSPEED, buf); } -// STUB: LEGO1 0x1007e6f0 +// FUNCTION: LEGO1 0x1007e6f0 void Jetski::Exit() { - // TODO + SpawnPlayer(LegoGameState::e_unk45, FALSE, c_spawnBit1 | c_playMusic | c_spawnBit3); + IslePathActor::Exit(); + GameState()->m_currentArea = LegoGameState::e_jetski; + RemoveFromWorld(); + EnableAnimations(TRUE); + SetIsWorldActive(TRUE); + ControlManager()->Unregister(this); } -// STUB: LEGO1 0x1007e750 +// FUNCTION: LEGO1 0x1007e750 +// FUNCTION: BETA10 0x10037621 MxLong Jetski::HandleClick() { - // TODO - return 0; + if (!FUN_1003ef60()) { + return 1; + } + + FUN_10015820(TRUE, 0); + + ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::Area::e_jetski); + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, TRUE); + + if (GameState()->GetActorId() != UserActor()->GetActorId()) { + ((IslePathActor*) UserActor())->Exit(); + } + + // TODO: Match + m_unk0x160 = ((DuneBuggy::GetColorOffset(g_varJSWNSHY5) * 5 + 15) * 2); + m_unk0x160 += DuneBuggy::GetColorOffset(g_varJSFRNTY5); + + InvokeAction(Extra::ActionType::e_start, *g_isleScript, m_unk0x160, NULL); + InvokeAction(Extra::ActionType::e_start, *g_isleScript, IsleScript::c_JetskiDashboard, NULL); + GetCurrentAction().SetObjectId(-1); + + AnimationManager()->FUN_1005f6d0(FALSE); + AnimationManager()->FUN_10064670(NULL); + Enter(); + ControlManager()->Register(this); + return 1; } -// STUB: LEGO1 0x1007e8e0 +// FUNCTION: LEGO1 0x1007e880 +void Jetski::RemoveFromWorld() +{ + RemoveFromCurrentWorld(*g_isleScript, m_unk0x160); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_JetskiArms_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_JetskiInfo_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_JetskiSpeedMeter); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_JetskiFuelMeter); +} + +// FUNCTION: LEGO1 0x1007e8e0 MxLong Jetski::HandleControl(LegoControlManagerNotificationParam& p_param) { - // TODO + if (p_param.GetUnknown0x28() == 1 && CurrentWorld()->IsA("Isle")) { + switch (p_param.GetClickedObjectId()) { + case IsleScript::c_JetskiArms_Ctl: + Exit(); + ((IslePathActor*) UserActor()) + ->SpawnPlayer(LegoGameState::e_jetraceExterior, TRUE, c_spawnBit1 | c_playMusic | c_spawnBit3); + GameState()->m_currentArea = LegoGameState::e_unk66; + return 1; + case IsleScript::c_JetskiInfo_Ctl: + ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain); + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + Exit(); + return 1; + } + } + return 0; } -// STUB: LEGO1 0x1007e990 -void Jetski::FUN_1007e990() +// FUNCTION: LEGO1 0x1007e990 +void Jetski::ActivateSceneActions() { - // TODO + PlayMusic(JukeboxScript::c_JetskiRace_Music); + + Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); + if (!act1state->m_unk0x018) { + if (act1state->m_unk0x022) { + PlayCamAnim(this, FALSE, 68, TRUE); + } + else { + act1state->m_unk0x022 = TRUE; + + LegoPathActor* user = UserActor(); + if (user != NULL) { + MxMatrix mat(user->GetROI()->GetLocal2World()); + mat.TranslateBy(mat[2][0] * 2.5, mat[2][1] + 0.6, mat[2][2] * 2.5); + + AnimationManager() + ->FUN_10060dc0(IsleScript::c_sjs007in_RunAnim, &mat, TRUE, FALSE, NULL, FALSE, TRUE, TRUE, TRUE); + } + } + } } diff --git a/LEGO1/lego/legoomni/src/actors/towtrack.cpp b/LEGO1/lego/legoomni/src/actors/towtrack.cpp index 05cf5fcb..dd9a0d9b 100644 --- a/LEGO1/lego/legoomni/src/actors/towtrack.cpp +++ b/LEGO1/lego/legoomni/src/actors/towtrack.cpp @@ -1,7 +1,9 @@ #include "towtrack.h" +#include "isle_actions.h" #include "legocontrolmanager.h" #include "legogamestate.h" +#include "legonavcontroller.h" #include "legovariables.h" #include "legoworld.h" #include "misc.h" @@ -23,7 +25,7 @@ TowTrack::TowTrack() m_unk0x16e = 0; m_unk0x174 = -1; m_maxLinearVel = 40.0; - m_unk0x178 = 1.0; + m_fuel = 1.0; } // FUNCTION: LEGO1 0x1004c970 @@ -54,15 +56,39 @@ MxResult TowTrack::Create(MxDSAction& p_dsAction) } VariableTable()->SetVariable(g_varTOWFUEL, "1.0"); - m_unk0x178 = 1.0; + m_fuel = 1.0; m_time = Timer()->GetTime(); return result; } -// STUB: LEGO1 0x1004cb10 -void TowTrack::VTable0x70(float p_float) +// FUNCTION: LEGO1 0x1004cb10 +void TowTrack::VTable0x70(float p_time) { - // TODO + IslePathActor::VTable0x70(p_time); + + if (UserActor() == this) { + char buf[200]; + float speed = abs(m_worldSpeed); + float maxLinearVel = NavController()->GetMaxLinearVel(); + + sprintf(buf, "%g", speed / maxLinearVel); + VariableTable()->SetVariable(g_varTOWSPEED, buf); + + m_fuel += (p_time - m_time) * -3.333333333e-06f; + if (m_fuel < 0) { + m_fuel = 0; + } + + m_time = p_time; + + sprintf(buf, "%g", m_fuel); + VariableTable()->SetVariable(g_varTOWFUEL, buf); + + if (p_time - m_state->m_unk0x0c > 100000.0f && m_state->m_unk0x08 == 1 && !m_state->m_unk0x10) { + FUN_1004dcf0(IsleScript::c_Avo909In_PlayWav); + m_state->m_unk0x10 = TRUE; + } + } } // FUNCTION: LEGO1 0x1004cc40 @@ -139,6 +165,12 @@ void TowTrack::FUN_1004dbe0() // TODO } +// STUB: LEGO1 0x1004dcf0 +void TowTrack::FUN_1004dcf0(IsleScript::Script) +{ + // TODO +} + // FUNCTION: LEGO1 0x1004dd30 TowTrackMissionState::TowTrackMissionState() { @@ -149,7 +181,7 @@ TowTrackMissionState::TowTrackMissionState() m_unk0x18 = 0; m_unk0x0c = 0; m_unk0x1a = 0; - m_unk0x10 = 0; + m_unk0x10 = FALSE; m_score1 = 0; m_score2 = 0; m_score3 = 0; diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index fa136321..fb8b39d0 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -1220,7 +1220,7 @@ void LegoAnimationManager::FUN_10061010(MxBool p_und) if (tranInfo->m_presenter->GetPresenter() != NULL && (anim = tranInfo->m_presenter->GetPresenter()->GetAnimation()) != NULL && - anim->GetScene() != NULL) { + anim->GetCamAnim() != NULL) { if (flags & LegoTranInfo::c_bit2) { BackgroundAudioManager()->RaiseVolume(); tranInfo->m_flags &= ~LegoTranInfo::c_bit2; diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp index fca0c0cb..6bbae1fa 100644 --- a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp +++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp @@ -5,7 +5,7 @@ #include "act2genactor.h" #include "act2policestation.h" #include "act3.h" -#include "act3actor.h" +#include "act3actors.h" #include "act3brickster.h" #include "act3cop.h" #include "act3shark.h" @@ -57,7 +57,7 @@ #include "legopathactor.h" #include "legopathpresenter.h" #include "legophonemepresenter.h" -#include "legoracecar.h" +#include "legoracers.h" #include "legotexturepresenter.h" #include "legoworld.h" #include "legoworldpresenter.h" diff --git a/LEGO1/lego/legoomni/src/common/legovariables.cpp b/LEGO1/lego/legoomni/src/common/legovariables.cpp index fcb4b975..da6b30fd 100644 --- a/LEGO1/lego/legoomni/src/common/legovariables.cpp +++ b/LEGO1/lego/legoomni/src/common/legovariables.cpp @@ -16,6 +16,14 @@ DECOMP_SIZE_ASSERT(CursorVariable, 0x24) DECOMP_SIZE_ASSERT(WhoAmIVariable, 0x24) DECOMP_SIZE_ASSERT(CustomizeAnimFileVariable, 0x24) +// GLOBAL: LEGO1 0x100f7ab0 +// STRING: LEGO1 0x100f09c0 +const char* g_varJETSPEED = "jetSPEED"; + +// GLOBAL: LEGO1 0x100f7ab4 +// STRING: LEGO1 0x100f7aa8 +const char* g_varJETFUEL = "jetFUEL"; + // GLOBAL: LEGO1 0x100f7658 // STRING: LEGO1 0x100f764c const char* g_varDUNESPEED = "duneSPEED"; @@ -40,6 +48,10 @@ const char* g_varAMBULSPEED = "ambulSPEED"; // STRING: LEGO1 0x100f39a0 const char* g_varAMBULFUEL = "ambulFUEL"; +// GLOBAL: LEGO1 0x100f43b0 +// STRING: LEGO1 0x100f43a4 +const char* g_varTOWSPEED = "towSPEED"; + // GLOBAL: LEGO1 0x100f43b4 // STRING: LEGO1 0x100f439c const char* g_varTOWFUEL = "towFUEL"; diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 29cc4cd6..6d879aa1 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -73,8 +73,10 @@ LegoPathActor* UserActor() } // FUNCTION: LEGO1 0x100157a0 +// FUNCTION: BETA10 0x100e4a46 LegoWorld* CurrentWorld() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetCurrentWorld(); } diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp index 3db91002..bd757bd5 100644 --- a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -140,6 +140,7 @@ void LegoCameraController::FUN_10012320(float p_angle) } // FUNCTION: LEGO1 0x100123e0 +// FUNCTION: BETA10 0x10068cb2 void LegoCameraController::FUN_100123e0(const Matrix4& p_transform, MxU32 p_und) { if (m_lego3DView != NULL) { diff --git a/LEGO1/lego/legoomni/src/entity/legocarraceactor.cpp b/LEGO1/lego/legoomni/src/entity/legocarraceactor.cpp index c36040b9..b74a652b 100644 --- a/LEGO1/lego/legoomni/src/entity/legocarraceactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocarraceactor.cpp @@ -28,7 +28,7 @@ LegoCarRaceActor::LegoCarRaceActor() } // STUB: LEGO1 0x10080590 -void LegoCarRaceActor::FUN_10080590() +void LegoCarRaceActor::FUN_10080590(float) { } diff --git a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp index 70c73fe2..eaad8ba9 100644 --- a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp @@ -29,8 +29,10 @@ LegoAnimActorStruct::~LegoAnimActorStruct() } // FUNCTION: LEGO1 0x1001c130 +// FUNCTION: BETA10 0x1003df5f float LegoAnimActorStruct::GetDuration() { + assert(m_AnimTreePtr); return m_AnimTreePtr->GetDuration(); } diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index c374ab5e..239f704f 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -33,6 +33,7 @@ DECOMP_SIZE_ASSERT(LegoPathEdgeContainer, 0x3c) const char* g_strHIT_WALL_SOUND = "HIT_WALL_SOUND"; // GLOBAL: LEGO1 0x100f3308 +// GLOBAL: BETA10 0x101f1e1c MxLong g_unk0x100f3308 = 0; // FUNCTION: LEGO1 0x1002d700 diff --git a/LEGO1/lego/legoomni/src/race/legoracecar.cpp b/LEGO1/lego/legoomni/src/race/legoracecar.cpp deleted file mode 100644 index 2a2b2a7e..00000000 --- a/LEGO1/lego/legoomni/src/race/legoracecar.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include "legoracecar.h" - -#include "define.h" -#include "legorace.h" -#include "misc.h" -#include "mxmisc.h" -#include "mxnotificationmanager.h" -#include "mxutilities.h" - -DECOMP_SIZE_ASSERT(EdgeReference, 0x08) -DECOMP_SIZE_ASSERT(LegoRaceCar, 0x200) - -// GLOBAL: LEGO1 0x100f0a20 -EdgeReference LegoRaceCar::g_edgeReferences[] = { - {// STRING: LEGO1 0x100f0a10 - "EDG03_772", - NULL - }, - {// STRING: LEGO1 0x100f0a04 - "EDG03_773", - NULL - }, - {// STRING: LEGO1 0x100f09f8 - "EDG03_774", - NULL - }, - {// STRING: LEGO1 0x100f09ec - "EDG03_775", - NULL - }, - {// STRING: LEGO1 0x100f09e0 - "EDG03_776", - NULL - }, - {// STRING: LEGO1 0x100f09d4 - "EDG03_777", - NULL - } -}; - -// GLOBAL: LEGO1 0x100f0a50 -const EdgeReference* LegoRaceCar::g_pEdgeReferences = g_edgeReferences; - -// FUNCTION: LEGO1 0x10012950 -LegoRaceCar::LegoRaceCar() -{ - m_unk0x54 = 0; - m_unk0x70 = 0; - m_unk0x74 = 0; - m_unk0x5c.Clear(); - m_unk0x58 = 0; - m_unk0x78 = 0; - m_unk0x7c = 0; - NotificationManager()->Register(this); -} - -// FUNCTION: LEGO1 0x10012c80 -LegoRaceCar::~LegoRaceCar() -{ - NotificationManager()->Unregister(this); -} - -// FUNCTION: LEGO1 0x10012d90 -MxLong LegoRaceCar::Notify(MxParam& p_param) -{ - return LegoRaceMap::Notify(p_param); -} - -// FUNCTION: LEGO1 0x10012e60 -void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed) -{ - if (!m_userNavFlag) { - if (!LegoCarRaceActor::m_unk0x0c) { - m_maxLinearVel = p_worldSpeed; - } - LegoAnimActor::SetWorldSpeed(p_worldSpeed); - } - else { - m_worldSpeed = p_worldSpeed; - } -} - -// FUNCTION: LEGO1 0x10012ea0 -void LegoRaceCar::SetMaxLinearVelocity(float p_maxLinearVelocity) -{ - if (p_maxLinearVelocity < 0) { - LegoCarRaceActor::m_unk0x0c = 2; - m_maxLinearVel = 0; - SetWorldSpeed(0); - } - else { - m_maxLinearVel = p_maxLinearVelocity; - } -} - -// FUNCTION: LEGO1 0x10012ef0 -void LegoRaceCar::ParseAction(char* p_extra) -{ - char buffer[256]; - - LegoAnimActor::ParseAction(p_extra); - LegoRaceMap::ParseAction(p_extra); - LegoRace* currentWorld = (LegoRace*) CurrentWorld(); - - if (KeyValueStringParse(buffer, g_strCOMP, p_extra) && currentWorld) { - currentWorld->VTable0x7c(this, atoi(buffer)); - } - - if (m_userNavFlag) { - for (MxU32 i = 0; i < m_animMaps.size(); i++) { - LegoAnimActorStruct* animMap = m_animMaps[i]; - - if (animMap->m_unk0x00 == -1.0f) { - m_unk0x70 = animMap; - } - else if (animMap->m_unk0x00 == -2.0f) { - m_unk0x74 = animMap; - } - } - - // STRING: LEGO1 0x100f0bc4 - const char* edge0344 = "EDG03_44"; - m_unk0x78 = currentWorld->FindPathBoundary(edge0344); - // STRING: LEGO1 0x100f0bb8 - const char* edge0354 = "EDG03_54"; - m_unk0x7c = currentWorld->FindPathBoundary(edge0354); - - for (MxS32 j = 0; j < sizeOfArray(g_edgeReferences); j++) { - g_edgeReferences[j].m_data = currentWorld->FindPathBoundary(g_edgeReferences[j].m_name); - } - } -} - -// STUB: LEGO1 0x10012ff0 -void LegoRaceCar::FUN_10012ff0(float) -{ - // TODO -} - -// STUB: LEGO1 0x10013130 -MxBool LegoRaceCar::FUN_10013130(float) -{ - // TODO - return TRUE; -} - -// STUB: LEGO1 0x100131f0 -void LegoRaceCar::VTable0x70(float p_float) -{ - // TODO -} - -// STUB: LEGO1 0x100133c0 -MxResult LegoRaceCar::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) -{ - // TODO - return 0; -} - -// STUB: LEGO1 0x10013600 -MxResult LegoRaceCar::VTable0x9c() -{ - // TODO - return SUCCESS; -} - -// STUB: LEGO1 0x10014500 -MxU32 LegoRaceCar::VTable0x6c( - LegoPathBoundary* p_boundary, - Vector3& p_v1, - Vector3& p_v2, - float p_f1, - float p_f2, - Vector3& p_v3 -) -{ - // TODO - return 0; -} - -// STUB: LEGO1 0x10014560 -void LegoRaceCar::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4) -{ - // TODO -} diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp new file mode 100644 index 00000000..5bebe2da --- /dev/null +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -0,0 +1,535 @@ +#include "legoracers.h" + +#include "anim/legoanim.h" +#include "carrace.h" +#include "define.h" +#include "legocachesoundmanager.h" +#include "legocameracontroller.h" +#include "legonavcontroller.h" +#include "legorace.h" +#include "legosoundmanager.h" +#include "misc.h" +#include "mxdebug.h" +#include "mxmisc.h" +#include "mxnotificationmanager.h" +#include "mxtimer.h" +#include "mxutilities.h" +#include "mxvariabletable.h" +#include "raceskel.h" + +DECOMP_SIZE_ASSERT(EdgeReference, 0x08) +DECOMP_SIZE_ASSERT(SkeletonKickPhase, 0x10) +DECOMP_SIZE_ASSERT(LegoRaceCar, 0x200) + +// GLOBAL: LEGO1 0x100f0a20 +// GLOBAL: BETA10 0x101f5e34 +EdgeReference LegoRaceCar::g_skBMap[] = { + {// STRING: LEGO1 0x100f0a10 + "EDG03_772", + NULL + }, + {// STRING: LEGO1 0x100f0a04 + "EDG03_773", + NULL + }, + {// STRING: LEGO1 0x100f09f8 + "EDG03_774", + NULL + }, + {// STRING: LEGO1 0x100f09ec + "EDG03_775", + NULL + }, + {// STRING: LEGO1 0x100f09e0 + "EDG03_776", + NULL + }, + {// STRING: LEGO1 0x100f09d4 + "EDG03_777", + NULL + } +}; + +// GLOBAL: LEGO1 0x100f0a50 +// GLOBAL: BETA10 0x101f5e60 +const SkeletonKickPhase LegoRaceCar::g_skeletonKickPhases[] = { + {&LegoRaceCar::g_skBMap[0], 0.1, 0.2, LEGORACECAR_KICK2}, + {&LegoRaceCar::g_skBMap[1], 0.2, 0.3, LEGORACECAR_KICK2}, + {&LegoRaceCar::g_skBMap[2], 0.3, 0.4, LEGORACECAR_KICK2}, + {&LegoRaceCar::g_skBMap[2], 0.6, 0.7, LEGORACECAR_KICK1}, + {&LegoRaceCar::g_skBMap[1], 0.7, 0.8, LEGORACECAR_KICK1}, + {&LegoRaceCar::g_skBMap[0], 0.8, 0.9, LEGORACECAR_KICK1}, + {&LegoRaceCar::g_skBMap[3], 0.1, 0.2, LEGORACECAR_KICK1}, + {&LegoRaceCar::g_skBMap[4], 0.2, 0.3, LEGORACECAR_KICK1}, + {&LegoRaceCar::g_skBMap[5], 0.3, 0.4, LEGORACECAR_KICK1}, + {&LegoRaceCar::g_skBMap[5], 0.6, 0.7, LEGORACECAR_KICK2}, + {&LegoRaceCar::g_skBMap[4], 0.7, 0.8, LEGORACECAR_KICK2}, + {&LegoRaceCar::g_skBMap[3], 0.8, 0.9, LEGORACECAR_KICK2}, +}; + +// GLOBAL: LEGO1 0x100f0b10 +// STRING: LEGO1 0x100f09cc +const char* LegoRaceCar::g_strSpeed = "SPEED"; + +// GLOBAL: LEGO1 0x100f0b18 +// GLOBAL: BETA10 0x101f5f28 +const char* LegoRaceCar::g_srtsl18to29[] = { + "srt018sl", + "srt019sl", + "srt020sl", + "srt021sl", + "srt022sl", + "srt023sl", + "srt024sl", + "srt025sl", + "srt026sl", + "srt027sl", + "srt028sl", + "srt029sl" +}; + +// GLOBAL: LEGO1 0x100f0b48 +// GLOBAL: BETA10 0x101f5f58 +const char* LegoRaceCar::g_srtsl6to10[] = {"srt006sl", "srt007sl", "srt008sl", "srt009sl", "srt010sl"}; + +// GLOBAL: LEGO1 0x100f0b5c +// GLOBAL: BETA10 0x101f5f6c +const char* LegoRaceCar::g_emptySoundKeyList[] = {NULL}; + +// GLOBAL: LEGO1 0x100f0b60 +// GLOBAL: BETA10 0x101f5f70 +const char* LegoRaceCar::g_srtrh[] = {"srt004rh", "srt005rh", "srt006rh"}; + +// GLOBAL: LEGO1 0x100f0b6c +// STRING: LEGO1 0x100f08c4 +const char* LegoRaceCar::g_srt001ra = "srt001ra"; + +// GLOBAL: LEGO1 0x100f0b70 +// STRING: LEGO1 0x100f08bc +const char* LegoRaceCar::g_soundSkel3 = "skel3"; + +// GLOBAL: LEGO1 0x100f0b74 +// GLOBAL: BETA10 0x101f5f80 +MxU32 LegoRaceCar::g_srtsl18to29Index = 0; + +// GLOBAL: LEGO1 0x100f0b78 +// GLOBAL: BETA10 0x101f5f84 +MxU32 LegoRaceCar::g_srtsl6to10Index = 0; + +// GLOBAL: LEGO1 0x100f0b7c +// GLOBAL: BETA10 0x101f5f88 +MxU32 LegoRaceCar::g_emptySoundKeyListIndex = 0; + +// GLOBAL: LEGO1 0x100f0b80 +// GLOBAL: BETA10 0x101f5f8c +MxU32 LegoRaceCar::g_srtrhIndex = 0; + +// GLOBAL: LEGO1 0x100f0b84 +// GLOBAL: BETA10 0x101f5f90 +MxLong LegoRaceCar::g_timeLastSoundPlayed = 0; + +// GLOBAL: LEGO1 0x100f0b88 +// GLOBAL: BETA10 0x101f5f94 +MxS32 LegoRaceCar::g_unk0x100f0b88 = 0; + +// GLOBAL: LEGO1 0x100f0b8c +// GLOBAL: BETA10 0x101f5f98 +MxBool LegoRaceCar::g_unk0x100f0b8c = TRUE; + +// Initialized at LEGO1 0x10012db0 +// GLOBAL: LEGO1 0x10102af0 +// GLOBAL: BETA10 0x102114c0 +Mx3DPointFloat LegoRaceCar::g_unk0x10102af0 = Mx3DPointFloat(0.0f, 2.0f, 0.0f); + +// FUNCTION: LEGO1 0x10012950 +LegoRaceCar::LegoRaceCar() +{ + m_userState = 0; + m_skelKick1Anim = 0; + m_skelKick2Anim = 0; + m_unk0x5c.Clear(); + m_unk0x58 = 0; + m_kick1B = 0; + m_kick2B = 0; + NotificationManager()->Register(this); +} + +// FUNCTION: LEGO1 0x10012c80 +LegoRaceCar::~LegoRaceCar() +{ + NotificationManager()->Unregister(this); +} + +// FUNCTION: LEGO1 0x10012d90 +MxLong LegoRaceCar::Notify(MxParam& p_param) +{ + return LegoRaceMap::Notify(p_param); +} + +// FUNCTION: LEGO1 0x10012e60 +// FUNCTION: BETA10 0x100cb191 +void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed) +{ + if (!m_userNavFlag) { + if (!LegoCarRaceActor::m_unk0x0c) { + m_maxLinearVel = p_worldSpeed; + } + LegoAnimActor::SetWorldSpeed(p_worldSpeed); + } + else { + LegoEntity::SetWorldSpeed(p_worldSpeed); + } +} + +// FUNCTION: LEGO1 0x10012ea0 +// FUNCTION: BETA10 0x100cb220 +void LegoRaceCar::SetMaxLinearVelocity(float p_maxLinearVelocity) +{ + if (p_maxLinearVelocity < 0) { + LegoCarRaceActor::m_unk0x0c = 2; + m_maxLinearVel = 0; + SetWorldSpeed(0); + } + else { + m_maxLinearVel = p_maxLinearVelocity; + } +} + +// FUNCTION: LEGO1 0x10012ef0 +// FUNCTION: BETA10 0x100cb2aa +void LegoRaceCar::ParseAction(char* p_extra) +{ + char buffer[256]; + + LegoAnimActor::ParseAction(p_extra); + LegoRaceMap::ParseAction(p_extra); + LegoRace* currentWorld = (LegoRace*) CurrentWorld(); + + if (KeyValueStringParse(buffer, g_strCOMP, p_extra) && currentWorld) { + currentWorld->VTable0x7c(this, atoi(buffer)); + } + + if (m_userNavFlag) { + MxS32 i; + + for (i = 0; i < m_animMaps.size(); i++) { + // It appears that the implementation in BETA10 does not use this variable + LegoAnimActorStruct* animMap = m_animMaps[i]; + + if (animMap->m_unk0x00 == -1.0f) { + m_skelKick1Anim = animMap; + } + else if (animMap->m_unk0x00 == -2.0f) { + m_skelKick2Anim = animMap; + } + } + + assert(m_skelKick1Anim && m_skelKick2Anim); + + // STRING: LEGO1 0x100f0bc4 + const char* edge0344 = "EDG03_44"; + m_kick1B = currentWorld->FindPathBoundary(edge0344); + assert(m_kick1B); + + // STRING: LEGO1 0x100f0bb8 + const char* edge0354 = "EDG03_54"; + m_kick2B = currentWorld->FindPathBoundary(edge0354); + assert(m_kick2B); + + for (i = 0; i < sizeOfArray(g_skBMap); i++) { + assert(g_skBMap[i].m_name); + g_skBMap[i].m_b = currentWorld->FindPathBoundary(g_skBMap[i].m_name); + assert(g_skBMap[i].m_b); + } + } +} + +// FUNCTION: LEGO1 0x10012ff0 +// FUNCTION: BETA10 0x100cb60e +void LegoRaceCar::FUN_10012ff0(float p_param) +{ + LegoAnimActorStruct* a; // called `a` in BETA10 + float deltaTime; + + if (m_userState == LEGORACECAR_KICK1) { + a = m_skelKick1Anim; + } + else { + assert(m_userState == LEGORACECAR_KICK2); + a = m_skelKick2Anim; + } + + assert(a && a->GetAnimTreePtr() && a->GetAnimTreePtr()->GetCamAnim()); + + if (a->GetAnimTreePtr()) { + deltaTime = p_param - m_unk0x58; + + if (a->GetDuration() <= deltaTime || deltaTime < 0.0) { + if (m_userState == LEGORACECAR_KICK1) { + LegoEdge** edges = m_kick1B->GetEdges(); + m_destEdge = (LegoUnknown100db7f4*) (edges[2]); + m_boundary = m_kick1B; + } + else { + LegoEdge** edges = m_kick1B->GetEdges(); + m_destEdge = (LegoUnknown100db7f4*) (edges[1]); + m_boundary = m_kick2B; + } + + m_userState = LEGORACECAR_UNKNOWN_0; + } + else if (a->GetAnimTreePtr()->GetCamAnim()) { + MxMatrix transformationMatrix; + + LegoWorld* r = CurrentWorld(); // called `r` in BETA10 + assert(r); + + transformationMatrix.SetIdentity(); + + // Possible bug in the original code: The first argument is not initialized + a->GetAnimTreePtr()->GetCamAnim()->FUN_1009f490(deltaTime, transformationMatrix); + + if (r->GetCamera()) { + r->GetCamera()->FUN_100123e0(transformationMatrix, 0); + } + + m_roi->FUN_100a58f0(transformationMatrix); + } + } +} + +// FUNCTION: LEGO1 0x10013130 +// FUNCTION: BETA10 0x100cce50 +MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1) +{ + const SkeletonKickPhase* current = g_skeletonKickPhases; + + // TODO: Type is guesswork so far + CarRace* r = (CarRace*) CurrentWorld(); // called `r` in BETA10 + assert(r); + + RaceSkel* s = (RaceSkel*) r->GetUnk0x150(); // called `s` in BETA10 + assert(s); + + float skeletonCurAnimPosition; + float skeletonCurAnimDuration; + + s->GetCurrentAnimData(&skeletonCurAnimPosition, &skeletonCurAnimDuration); + + float skeletonCurAnimPhase = skeletonCurAnimPosition / skeletonCurAnimDuration; + + for (MxS32 i = 0; i < sizeOfArray(g_skeletonKickPhases); i++) { + if (m_boundary == current->m_edgeRef->m_b && current->m_lower <= skeletonCurAnimPhase && + skeletonCurAnimPhase <= current->m_upper) { + m_userState = current->m_userState; + } + current = ¤t[1]; + } + + if (m_userState != LEGORACECAR_KICK1 && m_userState != LEGORACECAR_KICK2) { + MxTrace( + // STRING: BETA10 0x101f64c8 + "Got kicked in boundary %s %d %g:%g %g\n", + m_boundary->GetName(), + skeletonCurAnimPosition, + skeletonCurAnimDuration, + skeletonCurAnimPhase + ); + return FALSE; + } + + m_unk0x58 = p_param1; + SoundManager()->GetCacheSoundManager()->Play(g_soundSkel3, NULL, FALSE); + + return TRUE; +} + +// FUNCTION: LEGO1 0x100131f0 +// FUNCTION: BETA10 0x100cb88a +void LegoRaceCar::VTable0x70(float p_float) +{ + if (m_userNavFlag && (m_userState == LEGORACECAR_KICK1 || m_userState == LEGORACECAR_KICK2)) { + FUN_10012ff0(p_float); + return; + } + + LegoCarRaceActor::VTable0x70(p_float); + + if (m_userNavFlag && m_userState == LEGORACECAR_UNKNOWN_1) { + if (HandleSkeletonKicks(p_float)) { + return; + } + } + + if (LegoCarRaceActor::m_unk0x0c == 1) { + FUN_1005d4b0(); + + if (!m_userNavFlag) { + FUN_10080590(p_float); + return; + } + + float absoluteSpeed = abs(m_worldSpeed); + float maximumSpeed = NavController()->GetMaxLinearVel(); + char buffer[200]; + + sprintf(buffer, "%g", absoluteSpeed / maximumSpeed); + + VariableTable()->SetVariable(g_strSpeed, buffer); + + if (m_sound) { + // pitches up the engine sound based on the velocity + if (absoluteSpeed > 0.83 * maximumSpeed) { + m_frequencyFactor = 1.9f; + } + else { + // this value seems to simulate RPM based on the gear + MxS32 gearRpmFactor = (MxS32) (6.0 * absoluteSpeed) % 100; + m_frequencyFactor = gearRpmFactor / 80.0 + 0.7; + } + } + + if (absoluteSpeed != 0.0f) { + g_unk0x100f0b88 = p_float; + g_unk0x100f0b8c = FALSE; + } + + if (p_float - g_unk0x100f0b88 > 5000.0f && !g_unk0x100f0b8c) { + SoundManager()->GetCacheSoundManager()->Play(g_srt001ra, NULL, 0); + g_unk0x100f0b8c = TRUE; + } + } +} + +// FUNCTION: LEGO1 0x100133c0 +// FUNCTION: BETA10 0x100cbb84 +MxResult LegoRaceCar::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) +{ + if (!p_actor->GetUserNavFlag()) { + if (p_actor->GetState()) { + return FAILURE; + } + + if (p_bool) { + LegoROI* roi = p_actor->GetROI(); // name verified by BETA10 0x100cbbf5 + assert(roi); + MxMatrix matr; + matr = roi->GetLocal2World(); + + Vector3(matr[3]).Add(g_unk0x10102af0); + roi->FUN_100a58f0(matr); + + p_actor->SetState(2); + } + + if (m_userNavFlag) { + MxBool actorIsStuds = strcmpi(p_actor->GetROI()->GetName(), "studs") == 0; + MxBool actorIsRhoda = strcmpi(p_actor->GetROI()->GetName(), "rhoda") == 0; + MxLong time = Timer()->GetTime(); + + const char* soundKey = NULL; + MxLong timeElapsed = time - g_timeLastSoundPlayed; + + if (timeElapsed > 3000) { + if (p_bool) { + if (actorIsStuds) { + soundKey = g_srtsl18to29[g_srtsl18to29Index++]; + if (g_srtsl18to29Index >= sizeOfArray(g_srtsl18to29)) { + g_srtsl18to29Index = 0; + } + } + else if (actorIsRhoda) { + soundKey = g_emptySoundKeyList[g_emptySoundKeyListIndex++]; + if (g_emptySoundKeyListIndex >= sizeOfArray(g_emptySoundKeyList)) { + g_emptySoundKeyListIndex = 0; + } + } + } + else { + if (actorIsStuds) { + soundKey = g_srtsl6to10[g_srtsl6to10Index++]; + if (g_srtsl6to10Index >= sizeOfArray(g_srtsl6to10)) { + g_srtsl6to10Index = 0; + } + } + else if (actorIsRhoda) { + soundKey = g_srtrh[g_srtrhIndex++]; + if (g_srtrhIndex >= sizeOfArray(g_srtrh)) { + g_srtrhIndex = 0; + } + } + } + + if (soundKey) { + SoundManager()->GetCacheSoundManager()->Play(soundKey, NULL, FALSE); + g_timeLastSoundPlayed = g_unk0x100f3308 = time; + } + } + + if (p_bool && m_worldSpeed != 0) { + return SUCCESS; + } + + return FAILURE; + } + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10013600 +// FUNCTION: BETA10 0x100cbe60 +MxResult LegoRaceCar::VTable0x9c() +{ + MxResult result; + + if (m_userNavFlag) { + result = LegoCarRaceActor::VTable0x9c(); + + if (m_boundary) { + MxS32 bVar2 = 0; + + for (MxS32 i = 0; i < sizeOfArray(g_skBMap); i++) { + assert(g_skBMap[i].m_b); + if (m_boundary == g_skBMap[i].m_b) { + bVar2 = 1; + break; + } + } + + if (m_userState == LEGORACECAR_UNKNOWN_1) { + if (!bVar2) { + m_userState = LEGORACECAR_UNKNOWN_0; + } + } + else { + m_userState = LEGORACECAR_UNKNOWN_1; + } + } + } + else { + result = LegoCarRaceActor::VTable0x9c(); + } + + return result; +} + +// FUNCTION: LEGO1 0x10014500 +// FUNCTION: BETA10 0x100cd5e0 +MxU32 LegoRaceCar::VTable0x6c( + LegoPathBoundary* p_boundary, + Vector3& p_v1, + Vector3& p_v2, + float p_f1, + float p_f2, + Vector3& p_v3 +) +{ + return LegoCarRaceActor::VTable0x6c(p_boundary, p_v1, p_v2, p_f1, p_f2, p_v3); +} + +// FUNCTION: LEGO1 0x10014560 +// FUNCTION: BETA10 0x100cd660 +void LegoRaceCar::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4) +{ + LegoCarRaceActor::SwitchBoundary(p_boundary, p_edge, p_unk0xe4); +} diff --git a/LEGO1/lego/legoomni/src/race/raceskel.cpp b/LEGO1/lego/legoomni/src/race/raceskel.cpp index 5ef950e2..dd7e87f3 100644 --- a/LEGO1/lego/legoomni/src/race/raceskel.cpp +++ b/LEGO1/lego/legoomni/src/race/raceskel.cpp @@ -1,5 +1,7 @@ #include "raceskel.h" +#include + DECOMP_SIZE_ASSERT(RaceSkel, 0x178) // STUB: LEGO1 0x100719b0 @@ -7,3 +9,13 @@ RaceSkel::RaceSkel() { // TODO } + +// FUNCTION: LEGO1 0x10071cb0 +// FUNCTION: BETA10 0x100f158b +void RaceSkel::GetCurrentAnimData(float* p_outCurAnimPosition, float* p_outCurAnimDuration) +{ + *p_outCurAnimPosition = m_animPosition; + + assert(m_curAnim >= 0); + *p_outCurAnimDuration = m_animMaps[m_curAnim]->GetDuration(); +} diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 723a1a30..faebd3d4 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -922,9 +922,9 @@ void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p } } - if (p_anim->GetScene() != NULL) { + if (p_anim->GetCamAnim() != NULL) { MxMatrix transform(mat); - p_anim->GetScene()->FUN_1009f490(p_time, transform); + p_anim->GetCamAnim()->FUN_1009f490(p_time, transform); if (m_currentWorld != NULL && m_currentWorld->GetCamera() != NULL) { m_currentWorld->GetCamera()->FUN_100123e0(transform, 0); diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 0eae0878..21147b1f 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -4,6 +4,7 @@ #include "legoinputmanager.h" #include "legomain.h" #include "misc.h" +#include "mxdirectx/legodxinfo.h" #include "mxdirectx/mxdirect3d.h" #include "mxdirectx/mxstopwatch.h" #include "mxdisplaysurface.h" diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index d7cabb7b..fa9f9c5f 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -1044,7 +1044,7 @@ MxLong Isle::HandleTransitionEnd() FUN_10032d30((IsleScript::Script) m_jetski->GetUnknown0x160(), JukeboxScript::c_MusicTheme1, NULL, TRUE); if (!m_act1state->m_unk0x01f) { - m_jetski->FUN_1007e990(); + m_jetski->ActivateSceneActions(); } break; default: diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp index 45844ca9..77801f61 100644 --- a/LEGO1/lego/sources/anim/legoanim.cpp +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -785,7 +785,7 @@ LegoAnim::LegoAnim() m_duration = 0; m_actors = NULL; m_numActors = 0; - m_scene = NULL; + m_camAnim = NULL; } // FUNCTION: LEGO1 0x100a0bc0 @@ -799,8 +799,8 @@ LegoAnim::~LegoAnim() delete[] m_actors; } - if (m_scene != NULL) { - delete m_scene; + if (m_camAnim != NULL) { + delete m_camAnim; } } @@ -845,9 +845,9 @@ LegoResult LegoAnim::Read(LegoStorage* p_storage, LegoS32 p_parseScene) } if (p_parseScene) { - m_scene = new LegoAnimScene(); + m_camAnim = new LegoAnimScene(); - result = m_scene->Read(p_storage); + result = m_camAnim->Read(p_storage); if (result != SUCCESS) { goto done; diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index a7f7ee72..1a861eb6 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -208,6 +208,7 @@ struct LegoAnimActorEntry { undefined4 m_unk0x04; // 0x04 }; +// TODO: Possibly called `LegoCameraAnim(ation)`? // SIZE 0x24 class LegoAnimScene { public: @@ -242,7 +243,10 @@ class LegoAnim : public LegoTree { public: LegoAnim(); ~LegoAnim() override; + + // FUNCTION: BETA10 0x100284c0 LegoTime GetDuration() { return m_duration; } + LegoU32 GetNumActors() { return m_numActors; } LegoResult Write(LegoStorage* p_storage) override; // vtable+0x08 virtual LegoResult Read(LegoStorage* p_storage, LegoS32 p_parseScene); // vtable+0x10 @@ -250,7 +254,8 @@ class LegoAnim : public LegoTree { const LegoChar* GetActorName(LegoU32 p_index); undefined4 GetActorUnknown0x04(LegoU32 p_index); - LegoAnimScene* GetScene() { return m_scene; } + // FUNCTION: BETA10 0x1005abf0 + LegoAnimScene* GetCamAnim() { return m_camAnim; } // SYNTHETIC: LEGO1 0x100a0ba0 // LegoAnim::`scalar deleting destructor' @@ -259,7 +264,7 @@ class LegoAnim : public LegoTree { LegoTime m_duration; // 0x08 LegoAnimActorEntry* m_actors; // 0x0c LegoU32 m_numActors; // 0x10 - LegoAnimScene* m_scene; // 0x14 + LegoAnimScene* m_camAnim; // 0x14 // FUNCTION: LEGO1 0x100a1040 LegoTreeNodeData* CreateData() override { return new LegoAnimNodeData(); } // vtable+0x0c diff --git a/LEGO1/lego/sources/geom/legoweedge.h b/LEGO1/lego/sources/geom/legoweedge.h index c5a8b83d..74dc6a45 100644 --- a/LEGO1/lego/sources/geom/legoweedge.h +++ b/LEGO1/lego/sources/geom/legoweedge.h @@ -16,7 +16,10 @@ class LegoWEEdge { virtual LegoResult VTable0x04(); // vtable+0x04 LegoU8 GetNumEdges() { return m_numEdges; } + + // FUNCTION: BETA10 0x1001cc30 LegoEdge** GetEdges() { return m_edges; } + LegoU32 IsEqual(LegoWEEdge& p_other) { return this == &p_other; } void SetEdges(LegoEdge** p_edges, LegoU8 p_numEdges) diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index 716f830f..23bdf340 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -43,6 +43,8 @@ class LegoWEGEdge : public LegoWEEdge { LegoU32 GetFlag0x10() { return m_flags & c_bit5 ? FALSE : TRUE; } Mx4DPointFloat* GetUnknown0x14() { return &m_unk0x14; } Mx4DPointFloat* GetEdgeNormal(int index) { return &m_edgeNormals[index]; } + + // FUNCTION: BETA10 0x1001c9b0 LegoChar* GetName() { return m_name; } void SetFlag0x10(LegoU32 p_disable) diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index ef01fddf..d570ac56 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -60,7 +60,9 @@ class LegoROI : public ViewROI { ); static LegoBool FUN_100a9cf0(const LegoChar* p_param, unsigned char* paletteEntries, LegoU32 p_numEntries); + // FUNCTION: BETA10 0x1000f320 const LegoChar* GetName() const { return m_name; } + LegoEntity* GetEntity() { return m_entity; } void SetEntity(LegoEntity* p_entity) { m_entity = p_entity; } diff --git a/LEGO1/mxdirectx/legodxinfo.cpp b/LEGO1/mxdirectx/legodxinfo.cpp new file mode 100644 index 00000000..d24d42db --- /dev/null +++ b/LEGO1/mxdirectx/legodxinfo.cpp @@ -0,0 +1,379 @@ +#include "legodxinfo.h" + +#include +#include // for vsprintf + +// File name validated by BETA10 0x1011cba3; directory unknown + +// FUNCTION: CONFIG 0x00402560 +// FUNCTION: LEGO1 0x1009ce60 +// FUNCTION: BETA10 0x1011c7e0 +int LegoDeviceEnumerate::ParseDeviceName(const char* p_deviceId) +{ + if (!IsInitialized()) { + return -1; + } + + int unknown = -1; + int num = -1; + int hex[4]; + + if (sscanf(p_deviceId, "%d 0x%x 0x%x 0x%x 0x%x", &num, &hex[0], &hex[1], &hex[2], &hex[3]) != 5) { + return -1; + } + + if (num < 0) { + return -1; + } + + GUID guid; + memcpy(&guid, hex, sizeof(guid)); + + int result = ProcessDeviceBytes(num, guid); + + if (result < 0) { + result = ProcessDeviceBytes(-1, guid); + } + + return result; +} + +// FUNCTION: CONFIG 0x00402620 +// FUNCTION: LEGO1 0x1009cf20 +// FUNCTION: BETA10 0x1011c8b3 +int LegoDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) +{ + if (!IsInitialized()) { + return -1; + } + + int i = 0; + int j = 0; + + static_assert(sizeof(GUID4) == sizeof(GUID), "Equal size"); + + GUID4 deviceGuid; + memcpy(&deviceGuid, &p_guid, sizeof(GUID4)); + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { + if (p_deviceNum >= 0 && p_deviceNum < i) { + return -1; + } + + GUID4 compareGuid; + MxDriver& driver = *it; + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + Direct3DDeviceInfo& md3d = *it2; + assert(md3d.m_guid); + + memcpy(&compareGuid, md3d.m_guid, sizeof(GUID4)); + + if (GUID4::Compare(compareGuid, deviceGuid) && i == p_deviceNum) { + return j; + } + + j++; + } + } + + return -1; +} + +// FUNCTION: CONFIG 0x00402730 +// FUNCTION: LEGO1 0x1009d030 +// FUNCTION: BETA10 0x1011ca54 +int LegoDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device) +{ + if (p_deviceNum < 0 || !IsInitialized()) { + return -1; + } + + int i = 0; + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { + p_driver = &*it; + + for (list::iterator it2 = p_driver->m_devices.begin(); it2 != p_driver->m_devices.end(); + it2++) { + if (i == p_deviceNum) { + p_device = &*it2; + return 0; + } + i++; + } + } + + return -1; +} + +// FUNCTION: CONFIG 0x004027d0 +// FUNCTION: BETA10 0x1011cb70 +int LegoDeviceEnumerate::FormatDeviceName(char* p_buffer, const MxDriver* p_ddInfo, const Direct3DDeviceInfo* p_d3dInfo) + const +{ + int number = 0; + assert(p_ddInfo && p_d3dInfo); + + for (list::const_iterator it = m_list.begin(); it != m_list.end(); it++, number++) { + if (&(*it) == p_ddInfo) { + GUID4 guid; + memcpy(&guid, p_d3dInfo->m_guid, sizeof(GUID4)); + + sprintf(p_buffer, "%d 0x%x 0x%x 0x%x 0x%x", number, guid.m_data1, guid.m_data2, guid.m_data3, guid.m_data4); + return 0; + } + } + + return -1; +} + +// FUNCTION: BETA10 0x1011cc65 +int LegoDeviceEnumerate::BETA_1011cc65(int p_idx, char* p_buffer) +{ + if (p_idx < 0 || !IsInitialized()) { + return -1; + } + + int i = 0; + int j = 0; + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { + MxDriver& driver = *it; + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + + if (j == p_idx) { + GUID4 guid; + memcpy(&guid, &((Direct3DDeviceInfo&) *it2).m_guid, sizeof(GUID4)); + sprintf(p_buffer, "%d 0x%x 0x%x 0x%x 0x%x", i, guid.m_data1, guid.m_data2, guid.m_data3, guid.m_data4); + return 0; + } + + j++; + } + } + + return -1; +} + +// FUNCTION: CONFIG 0x00402860 +// FUNCTION: LEGO1 0x1009d0d0 +// FUNCTION: BETA10 0x1011cdb4 +int LegoDeviceEnumerate::FUN_1009d0d0() +{ + if (!IsInitialized()) { + return -1; + } + + if (m_list.size() == 0) { + return -1; + } + + int i = 0; + int j = 0; + int k = -1; + int cpu_mmx = SupportsMMX(); + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { + + MxDriver& driver = *it; + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + if ((*it2).m_HWDesc.dcmColorModel) { + return j; + } + else { + if (cpu_mmx && (*it2).m_HELDesc.dcmColorModel == D3DCOLOR_RGB && i == 0) { + k = j; + } + else if ((*it2).m_HELDesc.dcmColorModel == D3DCOLOR_MONO && i == 0 && k < 0) { + k = j; + } + } + + j++; + } + } + + return k; +} + +// FUNCTION: CONFIG 0x00402930 +// FUNCTION: LEGO1 0x1009d1a0 +// FUNCTION: BETA10 0x1011cf54 +int LegoDeviceEnumerate::SupportsMMX() +{ + if (!SupportsCPUID()) { + return 0; + } + int supports_mmx; +#ifdef _MSC_VER +#if defined(_M_IX86) + __asm { + mov eax, 0x0 ; EAX=0: Highest Function Parameter and Manufacturer ID +#if _MSC_VER > 1100 + cpuid ; Run CPUID +#else + __emit 0x0f + __emit 0xa2 +#endif + mov eax, 0x1 ; EAX=1: Processor Info and Feature Bits (unused) +#if _MSC_VER > 1100 + cpuid ; Run CPUID +#else + __emit 0x0f + __emit 0xa2 +#endif + xor eax, eax ; Zero EAX register + bt edx, 0x17 ; Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) + adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF + mov supports_mmx, eax ; Save eax into C variable + } +#elif defined(_M_IX64) + supports_mmx = 1; +#else + supports_mmx = 0; +#endif +#else + __asm__("movl $0x0, %%eax\n\t" // EAX=0: Highest Function Parameter and Manufacturer ID + "cpuid\n\t" // Run CPUID\n" + "mov $0x1, %%eax\n\t" // EAX=1: Processor Info and Feature Bits (unused) + "cpuid\n\t" // Run CPUID + "xorl %%eax, %%eax\n\t" // Zero EAX register + "btl $0x15, %%edx\n\t" // Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) + "adc %%eax, %%eax" // Add with carry: EAX = EAX + EAX + CF = CF + : "=a"(supports_mmx) // supports_mmx == EAX + ); +#endif + return supports_mmx; +} + +// FUNCTION: CONFIG 0x00402970 +// FUNCTION: LEGO1 0x1009d1e0 +// FUNCTION: BETA10 0x1011cf97 +int LegoDeviceEnumerate::SupportsCPUID() +{ + int has_cpuid; +#ifdef _MSC_VER +#if defined(_M_IX86) + __asm { + xor eax, eax ; Zero EAX register + pushfd ; Push EFLAGS register value on the stack + or dword ptr[esp], 0x200000 ; Set bit 0x200000: Able to use CPUID instruction (Pentium+) + popfd ; Write the updated value into the EFLAGS register + pushfd ; Push EFLAGS register value on the stack (again) + btr dword ptr[esp], 0x15 ; Test bit 0x15 (21) and reset (set CF) + adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF + popfd ; Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) + mov has_cpuid, eax ; Save eax into C variable + } +#elif defined(_M_X64) + has_cpuid = 1; +#else + has_cpuid = 0; +#endif +#else +#if defined(__i386__) + __asm__("xorl %%eax, %%eax\n\t" // Zero EAX register + "pushfl\n\t" // Push EFLAGS register value on the stack + "orl $0x200000, (%%esp)\n\t" // Set bit 0x200000: Able to use CPUID instruction (Pentium+) + "popfl\n\t" // Write the updated value into the EFLAGS register + "pushfl\n\t" // Push EFLAGS register value on the stack (again) + "btrl $0x15, (%%esp)\n\t" // Test bit 0x15 (21) and reset (set CF) + "adc %%eax, %%eax\n\t" // Add with carry: EAX = EAX + EAX + CF = CF + "popfl" // Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) + : "=a"(has_cpuid) // has_cpuid == EAX + ); +#elif defined(__x86_64__) || defined(__amd64__) + has_cpuid = 1; +#else + has_cpuid = 0; +#endif +#endif + return has_cpuid; +} + +// FUNCTION: CONFIG 0x004029a0 +// FUNCTION: LEGO1 0x1009d210 +// FUNCTION: BETA10 0x1011cfc4 +int LegoDeviceEnumerate::FUN_1009d210() +{ + if (!IsInitialized()) { + return -1; + } + + for (list::iterator it = m_list.begin(); it != m_list.end();) { + if (!DriverSupportsRequiredDisplayMode(*it)) { + m_list.erase(it++); + continue; + } + + MxDriver& driver = *it; + + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end();) { + if (!FUN_1009d3d0(*it2)) { + driver.m_devices.erase(it2++); + } + else { + it2++; + } + } + + if (!driver.m_devices.size()) { + m_list.erase(it++); + } + else { + it++; + } + } + + if (!m_list.size()) { + return -1; + } + + return 0; +} + +// FUNCTION: CONFIG 0x00402b00 +// FUNCTION: LEGO1 0x1009d370 +// FUNCTION: BETA10 0x1011d176 +unsigned char LegoDeviceEnumerate::DriverSupportsRequiredDisplayMode(MxDriver& p_driver) +{ + for (list::iterator it = p_driver.m_displayModes.begin(); it != p_driver.m_displayModes.end(); + it++) { + if ((*it).m_width == 640 && (*it).m_height == 480) { + if ((*it).m_bitsPerPixel == 8 || (*it).m_bitsPerPixel == 16) { + return TRUE; + } + } + } + + return FALSE; +} + +// FUNCTION: CONFIG 0x00402b60 +// FUNCTION: LEGO1 0x1009d3d0 +// FUNCTION: BETA10 0x1011d235 +unsigned char LegoDeviceEnumerate::FUN_1009d3d0(Direct3DDeviceInfo& p_device) +{ + if (m_list.size() <= 0) { + return FALSE; + } + + if (p_device.m_HWDesc.dcmColorModel) { + if (p_device.m_HWDesc.dwDeviceZBufferBitDepth & DDBD_16 && + p_device.m_HWDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { + return TRUE; + } + else { + return FALSE; + } + } + + MxDriver& front = m_list.front(); + for (list::iterator it = front.m_devices.begin(); it != front.m_devices.end(); it++) { + if ((&*it) == &p_device) { + return TRUE; + } + } + + return FALSE; +} diff --git a/LEGO1/mxdirectx/legodxinfo.h b/LEGO1/mxdirectx/legodxinfo.h new file mode 100644 index 00000000..2888c02c --- /dev/null +++ b/LEGO1/mxdirectx/legodxinfo.h @@ -0,0 +1,32 @@ +#ifndef LEGODXINFO_H +#define LEGODXINFO_H + +#include "mxdirectxinfo.h" + +// VTABLE: CONFIG 0x4060e4 +// VTABLE: LEGO1 0x100d9cc8 +// VTABLE: BETA10 0x101befb4 +// SIZE 0x14 +class LegoDeviceEnumerate : public MxDeviceEnumerate { +public: + int ParseDeviceName(const char* p_deviceId); + int ProcessDeviceBytes(int p_deviceNum, GUID& p_guid); + int GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device); + int FormatDeviceName(char* p_buffer, const MxDriver* p_ddInfo, const Direct3DDeviceInfo* p_d3dInfo) const; + int BETA_1011cc65(int p_idx, char* p_buffer); + int FUN_1009d0d0(); + static int SupportsMMX(); + static int SupportsCPUID(); + int FUN_1009d210(); + unsigned char DriverSupportsRequiredDisplayMode(MxDriver& p_driver); + unsigned char FUN_1009d3d0(Direct3DDeviceInfo& p_device); + + // SYNTHETIC: BETA10 0x100d8d10 + // LegoDeviceEnumerate::LegoDeviceEnumerate + + // SYNTHETIC: LEGO1 0x1007b590 + // SYNTHETIC: BETA10 0x100d8da0 + // LegoDeviceEnumerate::~LegoDeviceEnumerate +}; + +#endif // LEGODXINFO_H diff --git a/LEGO1/mxdirectx/mxdirectxinfo.cpp b/LEGO1/mxdirectx/mxdirectxinfo.cpp index 69936c6e..4d2950e3 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.cpp +++ b/LEGO1/mxdirectx/mxdirectxinfo.cpp @@ -570,379 +570,6 @@ const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) } } -// FUNCTION: CONFIG 0x00402560 -// FUNCTION: LEGO1 0x1009ce60 -// FUNCTION: BETA10 0x1011c7e0 -int MxDeviceEnumerate::ParseDeviceName(const char* p_deviceId) -{ - if (!IsInitialized()) { - return -1; - } - - int unknown = -1; - int num = -1; - int hex[4]; - - if (sscanf(p_deviceId, "%d 0x%x 0x%x 0x%x 0x%x", &num, &hex[0], &hex[1], &hex[2], &hex[3]) != 5) { - return -1; - } - - if (num < 0) { - return -1; - } - - GUID guid; - memcpy(&guid, hex, sizeof(guid)); - - int result = ProcessDeviceBytes(num, guid); - - if (result < 0) { - result = ProcessDeviceBytes(-1, guid); - } - - return result; -} - -// FUNCTION: CONFIG 0x00402620 -// FUNCTION: LEGO1 0x1009cf20 -// FUNCTION: BETA10 0x1011c8b3 -int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) -{ - if (!IsInitialized()) { - return -1; - } - - int i = 0; - int j = 0; - - static_assert(sizeof(GUID4) == sizeof(GUID), "Equal size"); - - GUID4 deviceGuid; - memcpy(&deviceGuid, &p_guid, sizeof(GUID4)); - - for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { - if (p_deviceNum >= 0 && p_deviceNum < i) { - return -1; - } - - GUID4 compareGuid; - MxDriver& driver = *it; - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { - Direct3DDeviceInfo& md3d = *it2; - assert(md3d.m_guid); - - memcpy(&compareGuid, md3d.m_guid, sizeof(GUID4)); - - if (GUID4::Compare(compareGuid, deviceGuid) && i == p_deviceNum) { - return j; - } - - j++; - } - } - - return -1; -} - -// FUNCTION: CONFIG 0x00402730 -// FUNCTION: LEGO1 0x1009d030 -// FUNCTION: BETA10 0x1011ca54 -int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device) -{ - if (p_deviceNum < 0 || !IsInitialized()) { - return -1; - } - - int i = 0; - - for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { - p_driver = &*it; - - for (list::iterator it2 = p_driver->m_devices.begin(); it2 != p_driver->m_devices.end(); - it2++) { - if (i == p_deviceNum) { - p_device = &*it2; - return 0; - } - i++; - } - } - - return -1; -} - -// FUNCTION: CONFIG 0x004027d0 -// FUNCTION: BETA10 0x1011cb70 -int MxDeviceEnumerate::FormatDeviceName(char* p_buffer, const MxDriver* p_ddInfo, const Direct3DDeviceInfo* p_d3dInfo) - const -{ - int number = 0; - assert(p_ddInfo && p_d3dInfo); - - for (list::const_iterator it = m_list.begin(); it != m_list.end(); it++, number++) { - if (&(*it) == p_ddInfo) { - GUID4 guid; - memcpy(&guid, p_d3dInfo->m_guid, sizeof(GUID4)); - - sprintf(p_buffer, "%d 0x%x 0x%x 0x%x 0x%x", number, guid.m_data1, guid.m_data2, guid.m_data3, guid.m_data4); - return 0; - } - } - - return -1; -} - -// FUNCTION: BETA10 0x1011cc65 -int MxDeviceEnumerate::BETA_1011cc65(int p_idx, char* p_buffer) -{ - if (p_idx < 0 || !IsInitialized()) { - return -1; - } - - int i = 0; - int j = 0; - - for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { - MxDriver& driver = *it; - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { - - if (j == p_idx) { - GUID4 guid; - memcpy(&guid, &((Direct3DDeviceInfo&) *it2).m_guid, sizeof(GUID4)); - sprintf(p_buffer, "%d 0x%x 0x%x 0x%x 0x%x", i, guid.m_data1, guid.m_data2, guid.m_data3, guid.m_data4); - return 0; - } - - j++; - } - } - - return -1; -} - -// FUNCTION: CONFIG 0x00402860 -// FUNCTION: LEGO1 0x1009d0d0 -// FUNCTION: BETA10 0x1011cdb4 -int MxDeviceEnumerate::FUN_1009d0d0() -{ - if (!IsInitialized()) { - return -1; - } - - if (m_list.size() == 0) { - return -1; - } - - int i = 0; - int j = 0; - int k = -1; - int cpu_mmx = SupportsMMX(); - - for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { - - MxDriver& driver = *it; - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { - if ((*it2).m_HWDesc.dcmColorModel) { - return j; - } - else { - if (cpu_mmx && (*it2).m_HELDesc.dcmColorModel == D3DCOLOR_RGB && i == 0) { - k = j; - } - else if ((*it2).m_HELDesc.dcmColorModel == D3DCOLOR_MONO && i == 0 && k < 0) { - k = j; - } - } - - j++; - } - } - - return k; -} - -// FUNCTION: CONFIG 0x00402930 -// FUNCTION: LEGO1 0x1009d1a0 -// FUNCTION: BETA10 0x1011cf54 -int MxDeviceEnumerate::SupportsMMX() -{ - if (!SupportsCPUID()) { - return 0; - } - int supports_mmx; -#ifdef _MSC_VER -#if defined(_M_IX86) - __asm { - mov eax, 0x0 ; EAX=0: Highest Function Parameter and Manufacturer ID -#if _MSC_VER > 1100 - cpuid ; Run CPUID -#else - __emit 0x0f - __emit 0xa2 -#endif - mov eax, 0x1 ; EAX=1: Processor Info and Feature Bits (unused) -#if _MSC_VER > 1100 - cpuid ; Run CPUID -#else - __emit 0x0f - __emit 0xa2 -#endif - xor eax, eax ; Zero EAX register - bt edx, 0x17 ; Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) - adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF - mov supports_mmx, eax ; Save eax into C variable - } -#elif defined(_M_IX64) - supports_mmx = 1; -#else - supports_mmx = 0; -#endif -#else - __asm__("movl $0x0, %%eax\n\t" // EAX=0: Highest Function Parameter and Manufacturer ID - "cpuid\n\t" // Run CPUID\n" - "mov $0x1, %%eax\n\t" // EAX=1: Processor Info and Feature Bits (unused) - "cpuid\n\t" // Run CPUID - "xorl %%eax, %%eax\n\t" // Zero EAX register - "btl $0x15, %%edx\n\t" // Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) - "adc %%eax, %%eax" // Add with carry: EAX = EAX + EAX + CF = CF - : "=a"(supports_mmx) // supports_mmx == EAX - ); -#endif - return supports_mmx; -} - -// FUNCTION: CONFIG 0x00402970 -// FUNCTION: LEGO1 0x1009d1e0 -// FUNCTION: BETA10 0x1011cf97 -int MxDeviceEnumerate::SupportsCPUID() -{ - int has_cpuid; -#ifdef _MSC_VER -#if defined(_M_IX86) - __asm { - xor eax, eax ; Zero EAX register - pushfd ; Push EFLAGS register value on the stack - or dword ptr[esp], 0x200000 ; Set bit 0x200000: Able to use CPUID instruction (Pentium+) - popfd ; Write the updated value into the EFLAGS register - pushfd ; Push EFLAGS register value on the stack (again) - btr dword ptr[esp], 0x15 ; Test bit 0x15 (21) and reset (set CF) - adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF - popfd ; Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) - mov has_cpuid, eax ; Save eax into C variable - } -#elif defined(_M_X64) - has_cpuid = 1; -#else - has_cpuid = 0; -#endif -#else -#if defined(__i386__) - __asm__("xorl %%eax, %%eax\n\t" // Zero EAX register - "pushfl\n\t" // Push EFLAGS register value on the stack - "orl $0x200000, (%%esp)\n\t" // Set bit 0x200000: Able to use CPUID instruction (Pentium+) - "popfl\n\t" // Write the updated value into the EFLAGS register - "pushfl\n\t" // Push EFLAGS register value on the stack (again) - "btrl $0x15, (%%esp)\n\t" // Test bit 0x15 (21) and reset (set CF) - "adc %%eax, %%eax\n\t" // Add with carry: EAX = EAX + EAX + CF = CF - "popfl" // Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) - : "=a"(has_cpuid) // has_cpuid == EAX - ); -#elif defined(__x86_64__) || defined(__amd64__) - has_cpuid = 1; -#else - has_cpuid = 0; -#endif -#endif - return has_cpuid; -} - -// FUNCTION: CONFIG 0x004029a0 -// FUNCTION: LEGO1 0x1009d210 -// FUNCTION: BETA10 0x1011cfc4 -int MxDeviceEnumerate::FUN_1009d210() -{ - if (!IsInitialized()) { - return -1; - } - - for (list::iterator it = m_list.begin(); it != m_list.end();) { - if (!DriverSupportsRequiredDisplayMode(*it)) { - m_list.erase(it++); - continue; - } - - MxDriver& driver = *it; - - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end();) { - if (!FUN_1009d3d0(*it2)) { - driver.m_devices.erase(it2++); - } - else { - it2++; - } - } - - if (!driver.m_devices.size()) { - m_list.erase(it++); - } - else { - it++; - } - } - - if (!m_list.size()) { - return -1; - } - - return 0; -} - -// FUNCTION: CONFIG 0x00402b00 -// FUNCTION: LEGO1 0x1009d370 -// FUNCTION: BETA10 0x1011d176 -unsigned char MxDeviceEnumerate::DriverSupportsRequiredDisplayMode(MxDriver& p_driver) -{ - for (list::iterator it = p_driver.m_displayModes.begin(); it != p_driver.m_displayModes.end(); - it++) { - if ((*it).m_width == 640 && (*it).m_height == 480) { - if ((*it).m_bitsPerPixel == 8 || (*it).m_bitsPerPixel == 16) { - return TRUE; - } - } - } - - return FALSE; -} - -// FUNCTION: CONFIG 0x00402b60 -// FUNCTION: LEGO1 0x1009d3d0 -// FUNCTION: BETA10 0x1011d235 -unsigned char MxDeviceEnumerate::FUN_1009d3d0(Direct3DDeviceInfo& p_device) -{ - if (m_list.size() <= 0) { - return FALSE; - } - - if (p_device.m_HWDesc.dcmColorModel) { - if (p_device.m_HWDesc.dwDeviceZBufferBitDepth & DDBD_16 && - p_device.m_HWDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { - return TRUE; - } - else { - return FALSE; - } - } - - MxDriver& front = m_list.front(); - for (list::iterator it = front.m_devices.begin(); it != front.m_devices.end(); it++) { - if ((&*it) == &p_device) { - return TRUE; - } - } - - return FALSE; -} - // FUNCTION: LEGO1 0x1009efb0 // FUNCTION: BETA10 0x10122ee2 DeviceModesInfo::DeviceModesInfo() diff --git a/LEGO1/mxdirectx/mxdirectxinfo.h b/LEGO1/mxdirectx/mxdirectxinfo.h index e585cd1e..0371b276 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.h +++ b/LEGO1/mxdirectx/mxdirectxinfo.h @@ -203,17 +203,6 @@ class MxDeviceEnumerate { LPD3DDEVICEDESC p_HELDesc ); const char* EnumerateErrorToString(HRESULT p_error); - int ParseDeviceName(const char* p_deviceId); - int ProcessDeviceBytes(int p_deviceNum, GUID& p_guid); - int GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device); - int FormatDeviceName(char* p_buffer, const MxDriver* p_ddInfo, const Direct3DDeviceInfo* p_d3dInfo) const; - int BETA_1011cc65(int p_idx, char* p_buffer); - - int FUN_1009d0d0(); - int FUN_1009d210(); - unsigned char DriverSupportsRequiredDisplayMode(MxDriver& p_driver); - unsigned char FUN_1009d3d0(Direct3DDeviceInfo& p_device); - static void BuildErrorString(const char*, ...); static BOOL CALLBACK DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context); @@ -226,8 +215,6 @@ class MxDeviceEnumerate { LPD3DDEVICEDESC p_HELDesc, LPVOID p_context ); - static int SupportsMMX(); - static int SupportsCPUID(); friend class MxDirect3D; @@ -251,24 +238,11 @@ class MxDeviceEnumerate { // FUNCTION: BETA10 0x1011d320 unsigned char IsInitialized() const { return m_initialized; } -private: +protected: list m_list; // 0x04 unsigned char m_initialized; // 0x10 }; -// VTABLE: CONFIG 0x4060e4 -// VTABLE: LEGO1 0x100d9cc8 -// VTABLE: BETA10 0x101befb4 -// SIZE 0x14 -class LegoDeviceEnumerate : public MxDeviceEnumerate {}; - -// SYNTHETIC: BETA10 0x100d8d10 -// LegoDeviceEnumerate::LegoDeviceEnumerate - -// SYNTHETIC: LEGO1 0x1007b590 -// SYNTHETIC: BETA10 0x100d8da0 -// LegoDeviceEnumerate::~LegoDeviceEnumerate - // TEMPLATE: BETA10 0x1011c1b0 // list >::iterator::operator* diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h index a33d92b9..5f471a8d 100644 --- a/LEGO1/mxgeometry/mxmatrix.h +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -4,6 +4,7 @@ #include "realtime/matrix.h" // VTABLE: LEGO1 0x100d4300 +// VTABLE: BETA10 0x101b82e0 // SIZE 0x48 class MxMatrix : public Matrix4 { public: @@ -15,7 +16,9 @@ class MxMatrix : public Matrix4 { MxMatrix(const Matrix4& p_matrix) : Matrix4(m_elements) { Equals(p_matrix); } + // FUNCTION: BETA10 0x10010860 float* operator[](int idx) { return m_data[idx]; } + const float* operator[](int idx) const { return m_data[idx]; } // FUNCTION: LEGO1 0x10002850 diff --git a/LEGO1/omni/include/mxtimer.h b/LEGO1/omni/include/mxtimer.h index 1e33d548..034b1565 100644 --- a/LEGO1/omni/include/mxtimer.h +++ b/LEGO1/omni/include/mxtimer.h @@ -14,8 +14,10 @@ class MxTimer : public MxCore { MxLong GetRealTime(); + // FUNCTION: BETA10 0x10017810 MxLong GetTime() { + // Note that the BETA10 implementation differs - it only consists of the second branch of this `if` call if (this->m_isRunning) { return g_lastTimeTimerStarted; } diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index a63b69d6..92c7ac7d 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -13,6 +13,7 @@ struct UnknownMatrixType { // The class needs to undergo a very careful refactoring to fix that (no matches should break). // VTABLE: LEGO1 0x100d4350 +// VTABLE: BETA10 0x101b8340 // SIZE 0x08 class Matrix4 { public: diff --git a/LEGO1/realtime/orientableroi.cpp b/LEGO1/realtime/orientableroi.cpp index 21a6b75a..451df324 100644 --- a/LEGO1/realtime/orientableroi.cpp +++ b/LEGO1/realtime/orientableroi.cpp @@ -98,6 +98,7 @@ void OrientableROI::GetLocalTransform(Matrix4& p_transform) } // FUNCTION: LEGO1 0x100a58f0 +// FUNCTION: BETA10 0x10167b77 void OrientableROI::FUN_100a58f0(const Matrix4& p_transform) { m_local2world = p_transform; diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index b707bbe3..54059f20 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -39,7 +39,9 @@ class OrientableROI : public ROI { void FUN_100a58f0(const Matrix4& p_transform); void FUN_100a5a30(const Vector3& p_world_velocity); + // FUNCTION: BETA10 0x1000fbf0 const Matrix4& GetLocal2World() const { return m_local2world; } + const float* GetWorldPosition() const { return m_local2world[3]; } const float* GetWorldDirection() const { return m_local2world[2]; } const float* GetWorldUp() const { return m_local2world[1]; } @@ -47,6 +49,7 @@ class OrientableROI : public ROI { void SetParentROI(OrientableROI* p_parentROI) { m_parentROI = p_parentROI; } + // FUNCTION: BETA10 0x10168800 void ToggleUnknown0xd8(BOOL p_enable) { if (p_enable) {