diff --git a/ISLE/define.h b/ISLE/define.h index aac9f28d..3f92244b 100644 --- a/ISLE/define.h +++ b/ISLE/define.h @@ -8,9 +8,9 @@ class IsleApp; extern IsleApp* g_isle; extern int g_closed; -// GLOBAL: ISLE 0x4101c4 +// STRING: ISLE 0x4101c4 #define WNDCLASS_NAME "Lego Island MainNoM App" -// GLOBAL: ISLE 0x4101dc +// STRING: ISLE 0x4101dc #define WINDOW_TITLE "LEGO\xAE" extern unsigned char g_mousedown; extern unsigned char g_mousemoved; diff --git a/LEGO1/act1state.h b/LEGO1/act1state.h index e2e8d3e1..d0daec7d 100644 --- a/LEGO1/act1state.h +++ b/LEGO1/act1state.h @@ -12,7 +12,7 @@ class Act1State : public LegoState { // FUNCTION: LEGO1 0x100338a0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0154 + // STRING: LEGO1 0x100f0154 return "Act1State"; }; diff --git a/LEGO1/act2brick.h b/LEGO1/act2brick.h index de4f29b1..10665c40 100644 --- a/LEGO1/act2brick.h +++ b/LEGO1/act2brick.h @@ -16,7 +16,7 @@ class Act2Brick : public LegoPathActor { // FUNCTION: LEGO1 0x1007a360 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0438 + // STRING: LEGO1 0x100f0438 return "Act2Brick"; } diff --git a/LEGO1/act2policestation.h b/LEGO1/act2policestation.h index 2ca1a4e8..887ab542 100644 --- a/LEGO1/act2policestation.h +++ b/LEGO1/act2policestation.h @@ -12,7 +12,7 @@ class Act2PoliceStation : public LegoEntity { // FUNCTION: LEGO1 0x1000e200 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03fc + // STRING: LEGO1 0x100f03fc return "Act2PoliceStation"; } diff --git a/LEGO1/act3.h b/LEGO1/act3.h index cc4a2c3f..76c9722b 100644 --- a/LEGO1/act3.h +++ b/LEGO1/act3.h @@ -14,7 +14,7 @@ class Act3 : public LegoWorld { // FUNCTION: LEGO1 0x10072510 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f013c + // STRING: LEGO1 0x100f013c return "Act3"; } diff --git a/LEGO1/act3actor.h b/LEGO1/act3actor.h index ef756436..cd1e1fcd 100644 --- a/LEGO1/act3actor.h +++ b/LEGO1/act3actor.h @@ -3,12 +3,12 @@ // FIXME: Uncertain location. There are three vtables which eventually call this // class' ClassName() function, but none of them call it directly. -class Act3Actor { +class Act3Actor : public MxCore { public: // FUNCTION: LEGO1 0x100431b0 inline virtual const char* ClassName() override { - // GLOBAL: LEGO1 0x100f03ac + // STRING: LEGO1 0x100f03ac return "Act3Actor"; } }; diff --git a/LEGO1/act3shark.h b/LEGO1/act3shark.h index 63a4e7a6..611cbc38 100644 --- a/LEGO1/act3shark.h +++ b/LEGO1/act3shark.h @@ -9,7 +9,7 @@ class Act3Shark : public LegoAnimActor { // FUNCTION: LEGO1 0x100430c0 inline virtual const char* ClassName() const override { - // GLOBAL: LEGO1 0x100f03a0 + // STRING: LEGO1 0x100f03a0 return "Act3Shark"; } }; diff --git a/LEGO1/act3state.h b/LEGO1/act3state.h index 5da94fac..dca6c3ea 100644 --- a/LEGO1/act3state.h +++ b/LEGO1/act3state.h @@ -12,7 +12,7 @@ class Act3State : public LegoState { // FUNCTION: LEGO1 0x1000e300 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03f0 + // STRING: LEGO1 0x100f03f0 return "Act3State"; } diff --git a/LEGO1/ambulance.h b/LEGO1/ambulance.h index eb46a1ed..3bc80212 100644 --- a/LEGO1/ambulance.h +++ b/LEGO1/ambulance.h @@ -12,7 +12,7 @@ class Ambulance : public IslePathActor { // FUNCTION: LEGO1 0x10035fa0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03c4 + // STRING: LEGO1 0x100f03c4 return "Ambulance"; } diff --git a/LEGO1/ambulancemissionstate.h b/LEGO1/ambulancemissionstate.h index 05d09859..a09bf117 100644 --- a/LEGO1/ambulancemissionstate.h +++ b/LEGO1/ambulancemissionstate.h @@ -12,7 +12,7 @@ class AmbulanceMissionState : public LegoState { // FUNCTION: LEGO1 0x10037600 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00e8 + // STRING: LEGO1 0x100f00e8 return "AmbulanceMissionState"; } diff --git a/LEGO1/animstate.h b/LEGO1/animstate.h index 5e8fa4e5..c1098b6a 100644 --- a/LEGO1/animstate.h +++ b/LEGO1/animstate.h @@ -13,7 +13,7 @@ class AnimState : public LegoState { // FUNCTION: LEGO1 0x10065070 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0460 + // STRING: LEGO1 0x100f0460 return "AnimState"; } diff --git a/LEGO1/beachhouseentity.h b/LEGO1/beachhouseentity.h index cf6a8909..58aa3c68 100644 --- a/LEGO1/beachhouseentity.h +++ b/LEGO1/beachhouseentity.h @@ -12,7 +12,7 @@ class BeachHouseEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000ee80 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0314 + // STRING: LEGO1 0x100f0314 return "BeachHouseEntity"; } diff --git a/LEGO1/bike.h b/LEGO1/bike.h index f3d5c90d..899cfd21 100644 --- a/LEGO1/bike.h +++ b/LEGO1/bike.h @@ -13,7 +13,7 @@ class Bike : public IslePathActor { // FUNCTION: LEGO1 0x100766f0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03d0 + // STRING: LEGO1 0x100f03d0 return "Bike"; } diff --git a/LEGO1/buildingentity.h b/LEGO1/buildingentity.h index f0ba4c3c..7f2abe07 100644 --- a/LEGO1/buildingentity.h +++ b/LEGO1/buildingentity.h @@ -13,7 +13,7 @@ class BuildingEntity : public LegoEntity { // FUNCTION: LEGO1 0x10014f20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07e8 + // STRING: LEGO1 0x100f07e8 return "BuildingEntity"; } diff --git a/LEGO1/bumpbouy.h b/LEGO1/bumpbouy.h index 8399c7ef..a56526e4 100644 --- a/LEGO1/bumpbouy.h +++ b/LEGO1/bumpbouy.h @@ -10,7 +10,7 @@ class BumpBouy : public LegoAnimActor { // FUNCTION: LEGO1 0x100274e0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0394 + // STRING: LEGO1 0x100f0394 return "BumpBouy"; } diff --git a/LEGO1/carrace.cpp b/LEGO1/carrace.cpp index 6da96168..9fdb353f 100644 --- a/LEGO1/carrace.cpp +++ b/LEGO1/carrace.cpp @@ -1,7 +1,10 @@ #include "carrace.h" -// STUB: LEGO1 0x10016a90 +DECOMP_SIZE_ASSERT(CarRace, 0x154); + +// FUNCTION: LEGO1 0x10016a90 CarRace::CarRace() { - // TODO + this->m_unk0x150 = 0; + this->m_unk0x130 = MxRect32(0x16c, 0x154, 0x1ec, 0x15e); } diff --git a/LEGO1/carrace.h b/LEGO1/carrace.h index b876fd4d..767fa567 100644 --- a/LEGO1/carrace.h +++ b/LEGO1/carrace.h @@ -1,6 +1,7 @@ #ifndef CARRACE_H #define CARRACE_H +#include "decomp.h" #include "legorace.h" // VTABLE: LEGO1 0x100d5e50 @@ -12,7 +13,7 @@ class CarRace : public LegoRace { // FUNCTION: LEGO1 0x10016b20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0528 + // STRING: LEGO1 0x100f0528 return "CarRace"; } @@ -21,6 +22,10 @@ class CarRace : public LegoRace { { return !strcmp(p_name, CarRace::ClassName()) || LegoRace::IsA(p_name); } + +private: + undefined m_unk0x144[12]; // 0x144 + undefined4 m_unk0x150; // 0x150 }; #endif // CARRACE_H diff --git a/LEGO1/carracestate.h b/LEGO1/carracestate.h index c922354f..561f277b 100644 --- a/LEGO1/carracestate.h +++ b/LEGO1/carracestate.h @@ -10,7 +10,7 @@ class CarRaceState : public RaceState { // FUNCTION: LEGO1 0x1000dd30 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f009c + // STRING: LEGO1 0x100f009c return "CarRaceState"; } diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp index 31f1e521..acd811a8 100644 --- a/LEGO1/define.cpp +++ b/LEGO1/define.cpp @@ -19,6 +19,9 @@ const char* g_strWORLD = "WORLD"; // GLOBAL: LEGO1 0x10101f20 const char* g_strSOUND = "SOUND"; +// GLOBAL: LEGO1 0x10101f58 +const char* g_strOBJECT = "OBJECT"; + // GLOBAL: LEGO1 0x10102040 const char* g_strACTION = "ACTION"; diff --git a/LEGO1/define.h b/LEGO1/define.h index 82e93375..45a536a9 100644 --- a/LEGO1/define.h +++ b/LEGO1/define.h @@ -7,6 +7,7 @@ extern MxU32 g_mxcoreCount[101]; extern const char* g_parseExtraTokens; extern const char* g_strWORLD; extern const char* g_strSOUND; +extern const char* g_strOBJECT; extern const char* g_strACTION; extern const char* g_strVISIBILITY; diff --git a/LEGO1/doors.h b/LEGO1/doors.h index a2c142a4..feea0460 100644 --- a/LEGO1/doors.h +++ b/LEGO1/doors.h @@ -10,7 +10,7 @@ class Doors : public LegoPathActor { // FUNCTION: LEGO1 0x1000e430 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03e8 + // STRING: LEGO1 0x100f03e8 return "Doors"; } diff --git a/LEGO1/dunebuggy.h b/LEGO1/dunebuggy.h index 1accaa05..e45fe8fe 100644 --- a/LEGO1/dunebuggy.h +++ b/LEGO1/dunebuggy.h @@ -13,7 +13,7 @@ class DuneBuggy : public IslePathActor { // FUNCTION: LEGO1 0x10067c30 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0410 + // STRING: LEGO1 0x100f0410 return "DuneBuggy"; } diff --git a/LEGO1/elevatorbottom.h b/LEGO1/elevatorbottom.h index 2a0f2570..64b3f221 100644 --- a/LEGO1/elevatorbottom.h +++ b/LEGO1/elevatorbottom.h @@ -14,7 +14,7 @@ class ElevatorBottom : public LegoWorld { // FUNCTION: LEGO1 0x10017f20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04ac + // STRING: LEGO1 0x100f04ac return "ElevatorBottom"; } diff --git a/LEGO1/gasstation.h b/LEGO1/gasstation.h index d6761980..0617e161 100644 --- a/LEGO1/gasstation.h +++ b/LEGO1/gasstation.h @@ -17,7 +17,7 @@ class GasStation : public LegoWorld { // FUNCTION: LEGO1 0x10004780 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0168 + // STRING: LEGO1 0x100f0168 return "GasStation"; } diff --git a/LEGO1/gasstationentity.h b/LEGO1/gasstationentity.h index 17aa22cf..b4a27942 100644 --- a/LEGO1/gasstationentity.h +++ b/LEGO1/gasstationentity.h @@ -10,7 +10,7 @@ class GasStationEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000eb20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0348 + // STRING: LEGO1 0x100f0348 return "GasStationEntity"; } diff --git a/LEGO1/gasstationstate.h b/LEGO1/gasstationstate.h index 2fb7e512..e2768a98 100644 --- a/LEGO1/gasstationstate.h +++ b/LEGO1/gasstationstate.h @@ -12,7 +12,7 @@ class GasStationState : public LegoState { // FUNCTION: LEGO1 0x100061d0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0174 + // STRING: LEGO1 0x100f0174 return "GasStationState"; } diff --git a/LEGO1/helicopter.h b/LEGO1/helicopter.h index cc4f3b35..7c5be4ea 100644 --- a/LEGO1/helicopter.h +++ b/LEGO1/helicopter.h @@ -27,7 +27,7 @@ class Helicopter : public IslePathActor { // FUNCTION: LEGO1 0x10003070 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0130 + // STRING: LEGO1 0x100f0130 return "Helicopter"; } diff --git a/LEGO1/helicopterstate.h b/LEGO1/helicopterstate.h index 1c43b04f..2cb3b747 100644 --- a/LEGO1/helicopterstate.h +++ b/LEGO1/helicopterstate.h @@ -11,7 +11,7 @@ class HelicopterState : public LegoState { // FUNCTION: LEGO1 0x1000e0d0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0144 + // STRING: LEGO1 0x100f0144 return "HelicopterState"; } diff --git a/LEGO1/historybook.h b/LEGO1/historybook.h index 18154c79..80cc78b5 100644 --- a/LEGO1/historybook.h +++ b/LEGO1/historybook.h @@ -15,7 +15,7 @@ class HistoryBook : public LegoWorld { // FUNCTION: LEGO1 0x10082390 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04bc + // STRING: LEGO1 0x100f04bc return "HistoryBook"; } diff --git a/LEGO1/hospital.h b/LEGO1/hospital.h index 014c301d..627dc4cc 100644 --- a/LEGO1/hospital.h +++ b/LEGO1/hospital.h @@ -15,7 +15,7 @@ class Hospital : public LegoWorld { // FUNCTION: LEGO1 0x100746b0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0490 + // STRING: LEGO1 0x100f0490 return "Hospital"; } diff --git a/LEGO1/hospitalentity.h b/LEGO1/hospitalentity.h index 9dc597f1..f4f14b70 100644 --- a/LEGO1/hospitalentity.h +++ b/LEGO1/hospitalentity.h @@ -10,7 +10,7 @@ class HospitalEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000ec40 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0338 + // STRING: LEGO1 0x100f0338 return "HospitalEntity"; } diff --git a/LEGO1/hospitalstate.cpp b/LEGO1/hospitalstate.cpp index b1727b74..4f865128 100644 --- a/LEGO1/hospitalstate.cpp +++ b/LEGO1/hospitalstate.cpp @@ -1,7 +1,14 @@ #include "hospitalstate.h" -// STUB: LEGO1 0x10076370 +DECOMP_SIZE_ASSERT(HospitalState, 0x18) + +// FUNCTION: LEGO1 0x10076370 HospitalState::HospitalState() { - // TODO + this->m_unk0xc = 0; + this->m_unk0xe = 0; + this->m_unk0x10 = 0; + this->m_unk0x12 = 0; + this->m_unk0x14 = 0; + this->m_unk0x16 = 0; } diff --git a/LEGO1/hospitalstate.h b/LEGO1/hospitalstate.h index 795342b0..25c23d96 100644 --- a/LEGO1/hospitalstate.h +++ b/LEGO1/hospitalstate.h @@ -1,6 +1,7 @@ #ifndef HOSPITALSTATE_H #define HOSPITALSTATE_H +#include "decomp.h" #include "legostate.h" // VTABLE: LEGO1 0x100d97a0 @@ -12,7 +13,7 @@ class HospitalState : public LegoState { // FUNCTION: LEGO1 0x10076400 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0480 + // STRING: LEGO1 0x100f0480 return "HospitalState"; } @@ -21,6 +22,15 @@ class HospitalState : public LegoState { { return !strcmp(p_name, HospitalState::ClassName()) || LegoState::IsA(p_name); } + +private: + undefined m_unk0x8[4]; // 0x8 + undefined2 m_unk0xc; // 0xc + undefined2 m_unk0xe; // 0xe + undefined2 m_unk0x10; // 0x10 + undefined2 m_unk0x12; // 0x12 + undefined2 m_unk0x14; // 0x14 + undefined2 m_unk0x16; // 0x16 }; #endif // HOSPITALSTATE_H diff --git a/LEGO1/infocenter.h b/LEGO1/infocenter.h index 2b6de946..ec0be745 100644 --- a/LEGO1/infocenter.h +++ b/LEGO1/infocenter.h @@ -16,7 +16,7 @@ class Infocenter : public LegoWorld { // FUNCTION: LEGO1 0x1006eb40 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04ec + // STRING: LEGO1 0x100f04ec return "Infocenter"; } diff --git a/LEGO1/infocenterdoor.h b/LEGO1/infocenterdoor.h index 1586dbc8..5bc5e407 100644 --- a/LEGO1/infocenterdoor.h +++ b/LEGO1/infocenterdoor.h @@ -15,7 +15,7 @@ class InfocenterDoor : public LegoWorld { // FUNCTION: LEGO1 0x100377b0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f049c + // STRING: LEGO1 0x100f049c return "InfocenterDoor"; } diff --git a/LEGO1/infocenterentity.h b/LEGO1/infocenterentity.h index 44121ae2..e011aeb8 100644 --- a/LEGO1/infocenterentity.h +++ b/LEGO1/infocenterentity.h @@ -10,7 +10,7 @@ class InfoCenterEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000ea00 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f035c + // STRING: LEGO1 0x100f035c return "InfoCenterEntity"; } diff --git a/LEGO1/infocenterstate.h b/LEGO1/infocenterstate.h index 322e7bec..b1bce306 100644 --- a/LEGO1/infocenterstate.h +++ b/LEGO1/infocenterstate.h @@ -14,7 +14,7 @@ class InfocenterState : public LegoState { // FUNCTION: LEGO1 0x10071840 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04dc + // STRING: LEGO1 0x100f04dc return "InfocenterState"; } diff --git a/LEGO1/isle.h b/LEGO1/isle.h index 9f44eadd..c3579aec 100644 --- a/LEGO1/isle.h +++ b/LEGO1/isle.h @@ -30,7 +30,7 @@ class Isle : public LegoWorld { // FUNCTION: LEGO1 0x10030910 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0458 + // STRING: LEGO1 0x100f0458 return "Isle"; } diff --git a/LEGO1/isleactor.h b/LEGO1/isleactor.h index aa205483..8fd7d039 100644 --- a/LEGO1/isleactor.h +++ b/LEGO1/isleactor.h @@ -9,7 +9,7 @@ class IsleActor : public LegoActor { // FUNCTION: LEGO1 0x1000e660 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07dc + // STRING: LEGO1 0x100f07dc return "IsleActor"; } diff --git a/LEGO1/islepathactor.h b/LEGO1/islepathactor.h index 44f50475..d7a8ff60 100644 --- a/LEGO1/islepathactor.h +++ b/LEGO1/islepathactor.h @@ -18,7 +18,7 @@ class IslePathActor : public LegoPathActor { // FUNCTION: LEGO1 0x10002ea0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0104 + // STRING: LEGO1 0x100f0104 return "IslePathActor"; } diff --git a/LEGO1/jetski.h b/LEGO1/jetski.h index 8c669ca6..1a64a4b6 100644 --- a/LEGO1/jetski.h +++ b/LEGO1/jetski.h @@ -13,7 +13,7 @@ class Jetski : public IslePathActor { // FUNCTION: LEGO1 0x1007e430 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03d8 + // STRING: LEGO1 0x100f03d8 return "Jetski"; } diff --git a/LEGO1/jetskirace.h b/LEGO1/jetskirace.h index 9488ed04..9b16d9a7 100644 --- a/LEGO1/jetskirace.h +++ b/LEGO1/jetskirace.h @@ -10,7 +10,7 @@ class JetskiRace : public LegoRace { // FUNCTION: LEGO1 0x1000daf0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0530 + // STRING: LEGO1 0x100f0530 return "JetskiRace"; } diff --git a/LEGO1/jetskiracestate.h b/LEGO1/jetskiracestate.h index 9724e4a1..5610ac32 100644 --- a/LEGO1/jetskiracestate.h +++ b/LEGO1/jetskiracestate.h @@ -10,7 +10,7 @@ class JetskiRaceState : public RaceState { // FUNCTION: LEGO1 0x1000dc40 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00ac + // STRING: LEGO1 0x100f00ac return "JetskiRaceState"; } diff --git a/LEGO1/jukebox.h b/LEGO1/jukebox.h index 63b04520..59aee194 100644 --- a/LEGO1/jukebox.h +++ b/LEGO1/jukebox.h @@ -13,7 +13,7 @@ class JukeBox : public LegoWorld { // FUNCTION: LEGO1 0x1005d6f0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02cc + // STRING: LEGO1 0x100f02cc return "JukeBox"; } diff --git a/LEGO1/jukeboxentity.h b/LEGO1/jukeboxentity.h index 3e175568..c451787d 100644 --- a/LEGO1/jukeboxentity.h +++ b/LEGO1/jukeboxentity.h @@ -13,7 +13,7 @@ class JukeBoxEntity : public LegoEntity { // FUNCTION: LEGO1 0x10085cc0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02f0 + // STRING: LEGO1 0x100f02f0 return "JukeBoxEntity"; } diff --git a/LEGO1/jukeboxstate.h b/LEGO1/jukeboxstate.h index 8a481437..7a517bb0 100644 --- a/LEGO1/jukeboxstate.h +++ b/LEGO1/jukeboxstate.h @@ -10,7 +10,7 @@ class JukeBoxState : public LegoState { // FUNCTION: LEGO1 0x1000f310 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02bc + // STRING: LEGO1 0x100f02bc return "JukeBoxState"; } diff --git a/LEGO1/lego3dview.h b/LEGO1/lego3dview.h index cafca31a..b984ad0f 100644 --- a/LEGO1/lego3dview.h +++ b/LEGO1/lego3dview.h @@ -2,6 +2,7 @@ #define LEGO3DVIEW_H #include "mxtypes.h" +#include "tgl/d3drm/impl.h" #include "viewmanager/viewmanager.h" class LegoROI; @@ -9,11 +10,18 @@ class LegoROI; class Lego3DView { public: inline ViewManager* GetViewManager() { return this->m_viewManager; } + inline TglImpl::ViewImpl* GetViewPort() { return this->m_viewPort; } LegoROI* PickROI(MxLong p_a, MxLong p_b); private: - char m_pad[0x88]; - ViewManager* m_viewManager; + // TODO: all of these fields are in various base classes + undefined4 m_vtable; // 0x0 (TODO: remove once virtual function added) + undefined4 m_unk0x4; // 0x4 + TglImpl::RendererImpl* m_renderImpl; // 0x8 + TglImpl::DeviceImpl* m_deviceImpl; // 0xc + TglImpl::ViewImpl* m_viewPort; // 0x10 + char m_pad[0x78]; // 0x14 + ViewManager* m_viewManager; // 0x88 }; #endif // LEGO3DVIEW_H diff --git a/LEGO1/lego3dwavepresenter.h b/LEGO1/lego3dwavepresenter.h index a2363518..ed1942da 100644 --- a/LEGO1/lego3dwavepresenter.h +++ b/LEGO1/lego3dwavepresenter.h @@ -1,16 +1,16 @@ #ifndef LEGO3DWAVEPRESENTER_H #define LEGO3DWAVEPRESENTER_H -#include "legowavepresenter.h" +#include "mxwavepresenter.h" // VTABLE: LEGO1 0x100d52b0 // SIZE 0xa0 -class Lego3DWavePresenter : public LegoWavePresenter { +class Lego3DWavePresenter : public MxWavePresenter { public: // FUNCTION: LEGO1 0x1000d890 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f058c + // STRING: LEGO1 0x100f058c return "Lego3DWavePresenter"; } diff --git a/LEGO1/legoact2.h b/LEGO1/legoact2.h new file mode 100644 index 00000000..b504c11c --- /dev/null +++ b/LEGO1/legoact2.h @@ -0,0 +1,11 @@ +#ifndef LEGOACT2_H +#define LEGOACT2_H + +#include "legocarraceactor.h" +#include "legopathactor.h" + +// VTABLE: LEGO1 0x100d82e0 +// SIZE: 0x1154 +class LegoAct2 : public LegoWorld {}; + +#endif // LEGOACT2_H diff --git a/LEGO1/legoact2state.h b/LEGO1/legoact2state.h index a26cdd7d..38584769 100644 --- a/LEGO1/legoact2state.h +++ b/LEGO1/legoact2state.h @@ -10,7 +10,7 @@ class LegoAct2State : public LegoState { // FUNCTION: LEGO1 0x1000df80 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0428 + // STRING: LEGO1 0x100f0428 return "LegoAct2State"; } diff --git a/LEGO1/legoactioncontrolpresenter.h b/LEGO1/legoactioncontrolpresenter.h index 98815348..746300a6 100644 --- a/LEGO1/legoactioncontrolpresenter.h +++ b/LEGO1/legoactioncontrolpresenter.h @@ -15,7 +15,7 @@ class LegoActionControlPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000d0e0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f05bc + // STRING: LEGO1 0x100f05bc return "LegoActionControlPresenter"; } diff --git a/LEGO1/legoactor.h b/LEGO1/legoactor.h index c8380177..95c991df 100644 --- a/LEGO1/legoactor.h +++ b/LEGO1/legoactor.h @@ -13,7 +13,7 @@ class LegoActor : public LegoEntity { // FUNCTION: LEGO1 0x1002d210 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0124 + // STRING: LEGO1 0x100f0124 return "LegoActor"; } diff --git a/LEGO1/legoactorpresenter.h b/LEGO1/legoactorpresenter.h index 359960dc..a9709686 100644 --- a/LEGO1/legoactorpresenter.h +++ b/LEGO1/legoactorpresenter.h @@ -10,7 +10,7 @@ class LegoActorPresenter : public LegoEntityPresenter { // FUNCTION: LEGO1 0x1000cb10 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f06a4 + // STRING: LEGO1 0x100f06a4 return "LegoActorPresenter"; } diff --git a/LEGO1/legoanimationmanager.h b/LEGO1/legoanimationmanager.h index 0a647e8f..f943b062 100644 --- a/LEGO1/legoanimationmanager.h +++ b/LEGO1/legoanimationmanager.h @@ -16,7 +16,7 @@ class LegoAnimationManager : public MxCore { // FUNCTION: LEGO1 0x1005ec80 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f7508 + // STRING: LEGO1 0x100f7508 return "LegoAnimationManager"; } diff --git a/LEGO1/legoanimmmpresenter.h b/LEGO1/legoanimmmpresenter.h index 9fc9d19f..2e1ab918 100644 --- a/LEGO1/legoanimmmpresenter.h +++ b/LEGO1/legoanimmmpresenter.h @@ -12,7 +12,7 @@ class LegoAnimMMPresenter : public MxCompositePresenter { // FUNCTION: LEGO1 0x1004a950 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f046c + // STRING: LEGO1 0x100f046c return "LegoAnimMMPresenter"; } diff --git a/LEGO1/legoanimpresenter.h b/LEGO1/legoanimpresenter.h index 5961f74a..de8e91d9 100644 --- a/LEGO1/legoanimpresenter.h +++ b/LEGO1/legoanimpresenter.h @@ -11,7 +11,7 @@ class LegoAnimPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x10068530 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f071c + // STRING: LEGO1 0x100f071c return "LegoAnimPresenter"; } diff --git a/LEGO1/legobuildingmanager.h b/LEGO1/legobuildingmanager.h index 38c9cd57..bb9c96bb 100644 --- a/LEGO1/legobuildingmanager.h +++ b/LEGO1/legobuildingmanager.h @@ -13,7 +13,7 @@ class LegoBuildingManager : public MxCore { // FUNCTION: LEGO1 0x1002f930 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f37d0 + // STRING: LEGO1 0x100f37d0 return "LegoBuildingManager"; } diff --git a/LEGO1/legocachesound.h b/LEGO1/legocachesound.h index e045a719..6398c04e 100644 --- a/LEGO1/legocachesound.h +++ b/LEGO1/legocachesound.h @@ -13,7 +13,7 @@ class LegoCacheSound : public MxCore { // FUNCTION: LEGO1 0x10006580 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f01c4 + // STRING: LEGO1 0x100f01c4 return "LegoCacheSound"; } diff --git a/LEGO1/legocameracontroller.h b/LEGO1/legocameracontroller.h index 7fa9552d..09785df1 100644 --- a/LEGO1/legocameracontroller.h +++ b/LEGO1/legocameracontroller.h @@ -15,7 +15,7 @@ class LegoCameraController : public MxCore { // FUNCTION: LEGO1 0x10011ec0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0850 + // STRING: LEGO1 0x100f0850 return "LegoCameraController"; } diff --git a/LEGO1/legocarbuild.h b/LEGO1/legocarbuild.h index b4a93e7c..74d850d4 100644 --- a/LEGO1/legocarbuild.h +++ b/LEGO1/legocarbuild.h @@ -16,7 +16,7 @@ class LegoCarBuild : public LegoWorld { // FUNCTION: LEGO1 0x10022940 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0504 + // STRING: LEGO1 0x100f0504 return "LegoCarBuild"; } diff --git a/LEGO1/legocarbuildanimpresenter.h b/LEGO1/legocarbuildanimpresenter.h index 8be926f7..0440a0f3 100644 --- a/LEGO1/legocarbuildanimpresenter.h +++ b/LEGO1/legocarbuildanimpresenter.h @@ -13,7 +13,7 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { // FUNCTION: LEGO1 0x10078510 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f05ec + // STRING: LEGO1 0x100f05ec return "LegoCarBuildAnimPresenter"; } diff --git a/LEGO1/legocarraceactor.h b/LEGO1/legocarraceactor.h index d03b20eb..f00d900e 100644 --- a/LEGO1/legocarraceactor.h +++ b/LEGO1/legocarraceactor.h @@ -9,7 +9,7 @@ class LegoCarRaceActor : public LegoRaceActor { // FUNCTION: LEGO1 0x10081650 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0568 + // STRING: LEGO1 0x100f0568 return "LegoCarRaceActor"; } diff --git a/LEGO1/legocontrolmanager.h b/LEGO1/legocontrolmanager.h index 591effb6..7bc8dc0f 100644 --- a/LEGO1/legocontrolmanager.h +++ b/LEGO1/legocontrolmanager.h @@ -14,7 +14,7 @@ class LegoControlManager : public MxCore { // FUNCTION: LEGO1 0x10028cb0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f31b8 + // STRING: LEGO1 0x100f31b8 return "LegoControlManager"; } diff --git a/LEGO1/legoentity.cpp b/LEGO1/legoentity.cpp index 26f9daab..0f813029 100644 --- a/LEGO1/legoentity.cpp +++ b/LEGO1/legoentity.cpp @@ -76,6 +76,12 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) // TODO } +// STUB: LEGO1 0x100109b0 +void LegoEntity::SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool) +{ + // TODO +} + // STUB: LEGO1 0x10010c30 void LegoEntity::FUN_10010c30() { diff --git a/LEGO1/legoentity.h b/LEGO1/legoentity.h index cdee29c3..5a2eb715 100644 --- a/LEGO1/legoentity.h +++ b/LEGO1/legoentity.h @@ -22,7 +22,7 @@ class LegoEntity : public MxEntity { // FUNCTION: LEGO1 0x1000c2f0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0064 + // STRING: LEGO1 0x100f0064 return "LegoEntity"; } @@ -49,6 +49,7 @@ class LegoEntity : public MxEntity { virtual void VTable0x4c(); // vtable+0x4c void FUN_10010c30(); + void SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool); protected: void Init(); diff --git a/LEGO1/legoentitypresenter.cpp b/LEGO1/legoentitypresenter.cpp index dc1a44eb..7a586c80 100644 --- a/LEGO1/legoentitypresenter.cpp +++ b/LEGO1/legoentitypresenter.cpp @@ -1,5 +1,6 @@ #include "legoentitypresenter.h" +#include "islepathactor.h" #include "legoomni.h" #include "legovideomanager.h" @@ -14,7 +15,7 @@ LegoEntityPresenter::LegoEntityPresenter() // FUNCTION: LEGO1 0x100535c0 void LegoEntityPresenter::Init() { - m_unk0x4c = 0; + m_objectBackend = 0; } // FUNCTION: LEGO1 0x100535d0 @@ -24,9 +25,9 @@ LegoEntityPresenter::~LegoEntityPresenter() } // FUNCTION: LEGO1 0x10053630 -undefined4 LegoEntityPresenter::VTable0x6c(undefined4 p_unk0x4c) +undefined4 LegoEntityPresenter::SetBackend(LegoEntity* p_backend) { - m_unk0x4c = p_unk0x4c; + m_objectBackend = p_backend; return 0; } @@ -45,3 +46,60 @@ void LegoEntityPresenter::Destroy() { Destroy(FALSE); } + +// FUNCTION: LEGO1 0x10053680 +MxResult LegoEntityPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + MxResult result = MxCompositePresenter::StartAction(p_controller, p_action); + + if (VideoManager()) { + VideoManager()->AddPresenter(*this); + } + + return result; +} + +// FUNCTION: LEGO1 0x100536c0 +void LegoEntityPresenter::ReadyTickle() +{ + if (GetCurrentWorld()) { + m_objectBackend = (LegoEntity*) MxPresenter::CreateEntityBackend("LegoEntity"); + if (m_objectBackend) { + m_objectBackend->Create(*m_action); + m_objectBackend->SetLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), TRUE); + ParseExtra(); + } + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Starting; + } +} + +// FUNCTION: LEGO1 0x10053720 +void LegoEntityPresenter::RepeatingTickle() +{ + if (m_list.empty()) { + EndAction(); + } +} + +// FUNCTION: LEGO1 0x10053730 +void LegoEntityPresenter::SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up) +{ + if (m_objectBackend) { + m_objectBackend->SetLocation(p_location, p_direction, p_up, TRUE); + } +} + +// FUNCTION: LEGO1 0x10053750 +void LegoEntityPresenter::ParseExtra() +{ + char data[512]; + MxU16 len = m_action->GetExtraLength(); + if (len) { + memcpy(data, m_action->GetExtraData(), len); + data[len] = 0; + + len &= MAXWORD; + m_objectBackend->ParseAction(data); + } +} diff --git a/LEGO1/legoentitypresenter.h b/LEGO1/legoentitypresenter.h index 9e072498..72af0498 100644 --- a/LEGO1/legoentitypresenter.h +++ b/LEGO1/legoentitypresenter.h @@ -3,6 +3,8 @@ #include "mxcompositepresenter.h" +class LegoEntity; + // VTABLE: LEGO1 0x100d8398 // SIZE 0x50 class LegoEntityPresenter : public MxCompositePresenter { @@ -13,7 +15,7 @@ class LegoEntityPresenter : public MxCompositePresenter { // FUNCTION: LEGO1 0x100534b0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f06b8 + // STRING: LEGO1 0x100f06b8 return "LegoEntityPresenter"; } @@ -23,14 +25,21 @@ class LegoEntityPresenter : public MxCompositePresenter { return !strcmp(p_name, LegoEntityPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); } - virtual void Destroy() override; // vtable+0x38 - virtual void Init(); // vtable+0x68 - virtual undefined4 VTable0x6c(undefined4 p_unk0x4c); // vtable+0x6c + virtual void ReadyTickle() override; // vtable+0x18 + virtual void RepeatingTickle(); // vtable+0x24 + virtual void ParseExtra(); // vtable+0x30 + virtual void Destroy() override; // vtable+0x38 + virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + virtual void Init(); // vtable+0x68 + virtual undefined4 SetBackend(LegoEntity* p_unk0x4c); // vtable+0x6c + + void SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up); private: void Destroy(MxBool p_fromDestructor); - undefined4 m_unk0x4c; +protected: + LegoEntity* m_objectBackend; // 0x4c }; #endif // LEGOENTITYPRESENTER_H diff --git a/LEGO1/legoextraactor.h b/LEGO1/legoextraactor.h index 6b8a9198..c4c76cee 100644 --- a/LEGO1/legoextraactor.h +++ b/LEGO1/legoextraactor.h @@ -9,7 +9,7 @@ class LegoExtraActor : public LegoAnimActor { // FUNCTION: LEGO1 0x1002b7a0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f3204 + // STRING: LEGO1 0x100f3204 return "LegoExtraActor"; } diff --git a/LEGO1/legoflctexturepresenter.cpp b/LEGO1/legoflctexturepresenter.cpp index 29a49814..f96d2b47 100644 --- a/LEGO1/legoflctexturepresenter.cpp +++ b/LEGO1/legoflctexturepresenter.cpp @@ -1,7 +1,16 @@ #include "legoflctexturepresenter.h" -// STUB: LEGO1 0x1005de80 +DECOMP_SIZE_ASSERT(LegoFlcTexturePresenter, 0x70) + +// FUNCTION: LEGO1 0x1005de80 LegoFlcTexturePresenter::LegoFlcTexturePresenter() { - // TODO + Init(); +} + +// FUNCTION: LEGO1 0x1005df70 +void LegoFlcTexturePresenter::Init() +{ + this->m_unk0x68 = 0; + this->m_unk0x6c = 0; } diff --git a/LEGO1/legoflctexturepresenter.h b/LEGO1/legoflctexturepresenter.h index c68d045d..36d1fefc 100644 --- a/LEGO1/legoflctexturepresenter.h +++ b/LEGO1/legoflctexturepresenter.h @@ -1,6 +1,7 @@ #ifndef LEGOFLCTEXTUREPRESENTER_H #define LEGOFLCTEXTUREPRESENTER_H +#include "decomp.h" #include "mxflcpresenter.h" // VTABLE: LEGO1 0x100d89e0 @@ -12,9 +13,15 @@ class LegoFlcTexturePresenter : public MxFlcPresenter { // FUNCTION: LEGO1 0x1005def0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0634 + // STRING: LEGO1 0x100f0634 return "LegoFlcTexturePresenter"; } + +private: + void Init(); + + undefined4 m_unk0x68; // 0x68 + undefined4 m_unk0x6c; // 0x6c }; #endif // LEGOFLCTEXTUREPRESENTER_H diff --git a/LEGO1/legohideanimpresenter.h b/LEGO1/legohideanimpresenter.h index aca44424..f6e86c2e 100644 --- a/LEGO1/legohideanimpresenter.h +++ b/LEGO1/legohideanimpresenter.h @@ -12,7 +12,7 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { // FUNCTION: LEGO1 0x1006d880 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f06cc + // STRING: LEGO1 0x100f06cc return "LegoHideAnimPresenter"; } diff --git a/LEGO1/legojetski.h b/LEGO1/legojetski.h index b7909a46..09a9f8d1 100644 --- a/LEGO1/legojetski.h +++ b/LEGO1/legojetski.h @@ -9,7 +9,7 @@ class LegoJetski : public LegoJetskiRaceActor { // FUNCTION: LEGO1 0x10013e80 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f053c + // STRING: LEGO1 0x100f053c return "LegoJetski"; } diff --git a/LEGO1/legojetskiraceactor.h b/LEGO1/legojetskiraceactor.h index d2ab88d8..28d151e8 100644 --- a/LEGO1/legojetskiraceactor.h +++ b/LEGO1/legojetskiraceactor.h @@ -9,7 +9,7 @@ class LegoJetskiRaceActor : public LegoCarRaceActor { // FUNCTION: LEGO1 0x10081d80 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0554 + // STRING: LEGO1 0x100f0554 return "LegoJetskiRaceActor"; } diff --git a/LEGO1/legoloadcachesoundpresenter.h b/LEGO1/legoloadcachesoundpresenter.h index c9255b01..1c26cdec 100644 --- a/LEGO1/legoloadcachesoundpresenter.h +++ b/LEGO1/legoloadcachesoundpresenter.h @@ -14,7 +14,7 @@ class LegoLoadCacheSoundPresenter : public MxWavePresenter { // FUNCTION: LEGO1 0x10018450 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f05a0 + // STRING: LEGO1 0x100f05a0 return "LegoLoadCacheSoundPresenter"; } diff --git a/LEGO1/legolocomotionanimpresenter.h b/LEGO1/legolocomotionanimpresenter.h index e7d7af25..36facd1d 100644 --- a/LEGO1/legolocomotionanimpresenter.h +++ b/LEGO1/legolocomotionanimpresenter.h @@ -11,7 +11,7 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { // FUNCTION: LEGO1 0x1006ce50 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f06e4 + // STRING: LEGO1 0x100f06e4 return "LegoLocomotionAnimPresenter"; } diff --git a/LEGO1/legoloopinganimpresenter.h b/LEGO1/legoloopinganimpresenter.h index 7f033a98..a17c671c 100644 --- a/LEGO1/legoloopinganimpresenter.h +++ b/LEGO1/legoloopinganimpresenter.h @@ -10,7 +10,7 @@ class LegoLoopingAnimPresenter : public LegoAnimPresenter { // FUNCTION: LEGO1 0x1000c9a0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0700 + // STRING: LEGO1 0x100f0700 return "LegoLoopingAnimPresenter"; } diff --git a/LEGO1/legomodelpresenter.h b/LEGO1/legomodelpresenter.h index b529fede..b55372dd 100644 --- a/LEGO1/legomodelpresenter.h +++ b/LEGO1/legomodelpresenter.h @@ -12,14 +12,14 @@ class LegoModelPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x1000ccb0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f067c + // STRING: LEGO1 0x100f067c return "LegoModelPresenter"; } // FUNCTION: LEGO1 0x1000ccc0 inline MxBool IsA(const char* p_name) const override // vtable+0x10 { - return !strcmp(p_name, LegoModelPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); + return !strcmp(p_name, ClassName()) || MxVideoPresenter::IsA(p_name); } }; diff --git a/LEGO1/legonavcontroller.h b/LEGO1/legonavcontroller.h index ffaf99cb..c6505341 100644 --- a/LEGO1/legonavcontroller.h +++ b/LEGO1/legonavcontroller.h @@ -42,7 +42,7 @@ class LegoNavController : public MxCore { // FUNCTION: LEGO1 0x10054b80 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f66d8 + // STRING: LEGO1 0x100f66d8 return "LegoNavController"; } diff --git a/LEGO1/legoobjectfactory.cpp b/LEGO1/legoobjectfactory.cpp index 2c77c7a9..ff52bad1 100644 --- a/LEGO1/legoobjectfactory.cpp +++ b/LEGO1/legoobjectfactory.cpp @@ -1,7 +1,104 @@ #include "legoobjectfactory.h" +#include "carrace.h" #include "decomp.h" +#include "dunebuggy.h" +#include "elevatorbottom.h" +#include "gasstation.h" +#include "gasstationstate.h" +#include "helicopter.h" +#include "helicopterstate.h" +#include "historybook.h" +#include "hospital.h" +#include "hospitalstate.h" +#include "infocenter.h" +#include "infocenterdoor.h" #include "infocenterstate.h" +#include "isle.h" +#include "jetskirace.h" +#include "lego3dwavepresenter.h" +#include "legoact2.h" +#include "legoact2state.h" +#include "legoactioncontrolpresenter.h" +#include "legoactor.h" +#include "legoactorpresenter.h" +#include "legoanimactor.h" +#include "legoanimpresenter.h" +#include "legocarbuild.h" +#include "legocarbuildanimpresenter.h" +#include "legocarraceactor.h" +#include "legoentity.h" +#include "legoentitypresenter.h" +#include "legoflctexturepresenter.h" +#include "legohideanimpresenter.h" +#include "legojetski.h" +#include "legojetskiraceactor.h" +#include "legoloadcachesoundpresenter.h" +#include "legolocomotionanimpresenter.h" +#include "legoloopinganimpresenter.h" +#include "legomodelpresenter.h" +#include "legopalettepresenter.h" +#include "legopartpresenter.h" +#include "legopathactor.h" +#include "legopathpresenter.h" +#include "legophonemepresenter.h" +#include "legoracecar.h" +#include "legotexturepresenter.h" +#include "legoworld.h" +#include "legoworldpresenter.h" +#include "mxcontrolpresenter.h" +#include "mxvideopresenter.h" +#include "pizza.h" +#include "pizzamissionstate.h" +#include "police.h" +#include "policestate.h" +#include "registrationbook.h" +#include "score.h" +#include "scorestate.h" +#include "skateboard.h" +// #include "act2actor.h" +#include "act2brick.h" +// #include "act2genactor.h" +#include "act2policestation.h" +#include "act3.h" +#include "act3state.h" +#include "ambulance.h" +#include "ambulancemissionstate.h" +#include "bike.h" +#include "doors.h" +#include "jetski.h" +#include "legoanimmmpresenter.h" +#include "motorcycle.h" +#include "racecar.h" +#include "towtrack.h" +#include "towtrackmissionstate.h" +// #include "act3cop.h" +// #include "act3brickster.h" +#include "act1state.h" +#include "act3actor.h" +#include "act3shark.h" +#include "beachhouseentity.h" +#include "bumpbouy.h" +#include "carracestate.h" +#include "gasstationentity.h" +#include "hospitalentity.h" +#include "infocenterentity.h" +#include "jetskiracestate.h" +#include "jukeboxentity.h" +#include "pizzeria.h" +#include "pizzeriastate.h" +#include "policeentity.h" +#include "racestandsentity.h" +#include "radiostate.h" +// #include "caveentity.h" +// #include "jailentity.h" +#include "jukebox.h" +#include "jukeboxstate.h" +#include "mxcompositemediapresenter.h" +// #include "raceskel.h" +#include "animstate.h" + +// TODO: Before HospitalState, add all of the different LegoVehicleBuildState's // TODO: Uncomment once we have all the relevant types ready // DECOMP_SIZE_ASSERT(LegoObjectFactory, 0x1c8); diff --git a/LEGO1/legoobjectfactory.h b/LEGO1/legoobjectfactory.h index 82117d34..3a575c52 100644 --- a/LEGO1/legoobjectfactory.h +++ b/LEGO1/legoobjectfactory.h @@ -3,7 +3,103 @@ #include "mxobjectfactory.h" -#define FOR_LEGOOBJECTFACTORY_OBJECTS(X) X(InfocenterState) +#define FOR_LEGOOBJECTFACTORY_OBJECTS(X) \ + X(LegoModelPresenter) \ + X(LegoTexturePresenter) \ + X(LegoPhonemePresenter) \ + X(LegoFlcTexturePresenter) \ + X(LegoEntityPresenter) \ + X(LegoActorPresenter) \ + X(LegoWorldPresenter) \ + X(LegoWorld) \ + X(LegoPalettePresenter) \ + X(LegoPathPresenter) \ + X(LegoAnimPresenter) \ + X(LegoLoopingAnimPresenter) \ + X(LegoLocomotionAnimPresenter) \ + X(LegoHideAnimPresenter) \ + X(LegoPartPresenter) \ + X(LegoCarBuildAnimPresenter) \ + X(LegoActionControlPresenter) \ + X(MxVideoPresenter) \ + X(LegoLoadCacheSoundPresenter) \ + X(Lego3DWavePresenter) \ + X(LegoActor) \ + X(LegoPathActor) \ + X(LegoRaceCar) \ + X(LegoJetski) \ + /*X(JetskiRace) \*/ \ + X(LegoEntity) \ + X(LegoCarRaceActor) \ + X(LegoJetskiRaceActor) \ + X(LegoCarBuild) \ + X(Infocenter) \ + X(LegoAnimActor) \ + X(MxControlPresenter) \ + X(RegistrationBook) \ + X(HistoryBook) \ + X(ElevatorBottom) \ + X(InfocenterDoor) \ + X(Score) \ + X(ScoreState) \ + X(Hospital) \ + X(Isle) \ + X(Police) \ + X(GasStation) \ + X(LegoAct2) \ + X(LegoAct2State) \ + /*X(CarRace)*/ \ + X(HospitalState) \ + X(InfocenterState) \ + X(PoliceState) \ + X(GasStationState) \ + X(SkateBoard) \ + X(Helicopter) \ + X(HelicopterState) \ + X(DuneBuggy) \ + X(Pizza) \ + X(PizzaMissionState) \ + /*X(Act2Actor)*/ \ + /*X(Act2Brick)*/ \ + /*X(Act2GenActor)*/ \ + X(Act2PoliceStation) \ + X(Act3) \ + X(Act3State) \ + X(Doors) \ + X(LegoAnimMMPresenter) \ + X(RaceCar) \ + X(Jetski) \ + X(Bike) \ + X(Motorcycle) \ + X(Ambulance) \ + X(AmbulanceMissionState) \ + X(TowTrack) \ + X(TowTrackMissionState) \ + /*X(Act3Cop)*/ \ + /*X(Act3Brickster)*/ \ + X(Act3Shark) \ + X(BumpBouy) \ + X(Act3Actor) \ + X(JetskiRaceState) \ + X(CarRaceState) \ + X(Act1State) \ + X(Pizzeria) \ + X(PizzeriaState) \ + X(InfoCenterEntity) \ + X(HospitalEntity) \ + X(GasStationEntity) \ + X(PoliceEntity) \ + X(BeachHouseEntity) \ + X(RaceStandsEntity) \ + X(JukeBoxEntity) \ + X(RadioState) \ + /*X(CaveEntity)*/ \ + /*X(JailEntity)*/ \ + X(MxCompositeMediaPresenter) \ + X(JukeBox) \ + X(JukeBoxState) \ + /*X(RaceSkel)*/ \ + X(AnimState) // VTABLE: LEGO1 0x100d4768 class LegoObjectFactory : public MxObjectFactory { diff --git a/LEGO1/legoomni.cpp b/LEGO1/legoomni.cpp index cd3438a7..8c9e5905 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/legoomni.cpp @@ -568,6 +568,12 @@ LegoOmni* LegoOmni::GetInstance() return (LegoOmni*) MxOmni::GetInstance(); } +// FUNCTION: LEGO1 0x1005ad20 +void LegoOmni::AddWorld(LegoWorld* p_world) +{ + m_worldList->Append(p_world); +} + // STUB: LEGO1 0x1005af10 void LegoOmni::RemoveWorld(const MxAtomId&, MxLong) { diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index 69f6964a..f0ac8369 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -76,7 +76,7 @@ class LegoOmni : public MxOmni { // FUNCTION: LEGO1 0x10058aa0 inline virtual const char* ClassName() const override // vtable+0c { - // GLOBAL: LEGO1 0x100f671c + // STRING: LEGO1 0x100f671c return "LegoOmni"; } @@ -98,6 +98,7 @@ class LegoOmni : public MxOmni { virtual void StopTimer() override; // vtable+3c LegoEntity* FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid); + void AddWorld(LegoWorld* p_world); LegoVideoManager* GetVideoManager() { return (LegoVideoManager*) m_videoManager; } LegoSoundManager* GetSoundManager() { return (LegoSoundManager*) m_soundManager; } diff --git a/LEGO1/legopalettepresenter.cpp b/LEGO1/legopalettepresenter.cpp index 5ee9279f..f18a22c3 100644 --- a/LEGO1/legopalettepresenter.cpp +++ b/LEGO1/legopalettepresenter.cpp @@ -1,5 +1,10 @@ #include "legopalettepresenter.h" +#include "legoomni.h" +#include "legostream.h" +#include "legovideomanager.h" +#include "mxstreamchunk.h" + DECOMP_SIZE_ASSERT(LegoPalettePresenter, 0x68) // FUNCTION: LEGO1 0x10079e50 @@ -39,3 +44,48 @@ void LegoPalettePresenter::Destroy() { Destroy(FALSE); } + +// FUNCTION: LEGO1 0x1007a130 +MxResult LegoPalettePresenter::ParsePallete(MxStreamChunk* p_chunk) +{ + MxU8 buffer[40]; + RGBQUAD palleteData[256]; + MxResult result = FAILURE; + LegoMemoryStream stream((char*) p_chunk->GetData()); + if (stream.Read(buffer, 40) == SUCCESS) { + if (stream.Read(palleteData, sizeof(RGBQUAD) * 256) == SUCCESS) { + m_palette = new MxPalette(palleteData); + if (m_palette) { + result = SUCCESS; + } + } + } + + if (result != SUCCESS && m_palette) { + delete m_palette; + m_palette = NULL; + } + + return result; +} + +// FUNCTION: LEGO1 0x1007a230 +void LegoPalettePresenter::ReadyTickle() +{ + MxStreamChunk* chunk = m_subscriber->FUN_100b8360(); + if (chunk) { + if (chunk->GetTime() <= m_action->GetElapsedTime()) { + ParseExtra(); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Starting; + chunk = m_subscriber->FUN_100b8250(); + MxResult result = ParsePallete(chunk); + m_subscriber->FUN_100b8390(chunk); + + if (result == SUCCESS) { + VideoManager()->RealizePalette(m_palette); + } + EndAction(); + } + } +} diff --git a/LEGO1/legopalettepresenter.h b/LEGO1/legopalettepresenter.h index e29b5391..f725149d 100644 --- a/LEGO1/legopalettepresenter.h +++ b/LEGO1/legopalettepresenter.h @@ -15,7 +15,7 @@ class LegoPalettePresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x10079f30 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f061c + // STRING: LEGO1 0x100f061c return "LegoPalettePresenter"; } @@ -25,13 +25,16 @@ class LegoPalettePresenter : public MxVideoPresenter { return !strcmp(p_name, ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual void Destroy() override; // vtable+0x38 + virtual void ReadyTickle() override; // vtable+0x18 + virtual void Destroy() override; // vtable+0x38 + + MxResult ParsePallete(MxStreamChunk* p_chunk); private: void Init(); void Destroy(MxBool p_fromDestructor); - MxPalette* m_palette; + MxPalette* m_palette; // 0x64 }; #endif // LEGOPALETTEPRESENTER_H diff --git a/LEGO1/legopartpresenter.h b/LEGO1/legopartpresenter.h index 936d4876..6695a70b 100644 --- a/LEGO1/legopartpresenter.h +++ b/LEGO1/legopartpresenter.h @@ -10,7 +10,7 @@ class LegoPartPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000cf70 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f05d8 + // STRING: LEGO1 0x100f05d8 return "LegoPartPresenter"; } diff --git a/LEGO1/legopathactor.h b/LEGO1/legopathactor.h index f331e8ce..a3f5756c 100644 --- a/LEGO1/legopathactor.h +++ b/LEGO1/legopathactor.h @@ -15,7 +15,7 @@ class LegoPathActor : public LegoActor { // FUNCTION: LEGO1 0x1000c430 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0114 + // STRING: LEGO1 0x100f0114 return "LegoPathActor"; } diff --git a/LEGO1/legopathcontroller.h b/LEGO1/legopathcontroller.h index 7bb6d30d..f7278ca8 100644 --- a/LEGO1/legopathcontroller.h +++ b/LEGO1/legopathcontroller.h @@ -15,7 +15,7 @@ class LegoPathController : public MxCore { // FUNCTION: LEGO1 0x10045110 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f11b8 + // STRING: LEGO1 0x100f11b8 return "LegoPathController"; } diff --git a/LEGO1/legopathpresenter.h b/LEGO1/legopathpresenter.h index 8fe2d5ee..de7b14d1 100644 --- a/LEGO1/legopathpresenter.h +++ b/LEGO1/legopathpresenter.h @@ -12,7 +12,7 @@ class LegoPathPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x100449a0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0690 + // STRING: LEGO1 0x100f0690 return "LegoPathPresenter"; } diff --git a/LEGO1/legophonemepresenter.h b/LEGO1/legophonemepresenter.h index 7b620723..330b1c7a 100644 --- a/LEGO1/legophonemepresenter.h +++ b/LEGO1/legophonemepresenter.h @@ -16,7 +16,7 @@ class LegoPhonemePresenter : public MxFlcPresenter { // FUNCTION: LEGO1 0x1004e310 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f064c + // STRING: LEGO1 0x100f064c return "LegoPhonemePresenter"; } diff --git a/LEGO1/legoplantmanager.h b/LEGO1/legoplantmanager.h index 87a6ec79..7fd20746 100644 --- a/LEGO1/legoplantmanager.h +++ b/LEGO1/legoplantmanager.h @@ -15,7 +15,7 @@ class LegoPlantManager : public MxCore { // FUNCTION: LEGO1 0x10026290 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f318c + // STRING: LEGO1 0x100f318c return "LegoPlantManager"; } diff --git a/LEGO1/legorace.h b/LEGO1/legorace.h index 8ae52d8e..530c289c 100644 --- a/LEGO1/legorace.h +++ b/LEGO1/legorace.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "legoworld.h" +#include "mxrect32.h" #include "mxtypes.h" // VTABLE: LEGO1 0x100d5db0 @@ -17,7 +18,7 @@ class LegoRace : public LegoWorld { // FUNCTION: LEGO1 0x10015ba0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f07c4 + // STRING: LEGO1 0x100f07c4 return "LegoRace"; } @@ -38,22 +39,26 @@ class LegoRace : public LegoWorld { virtual void VTable0x7c(undefined4, undefined4); // vtable+0x7c private: - undefined4 m_unk0xf8; // 0xf8 - undefined4 m_unk0xfc; // 0xfc - undefined4 m_unk0x100; // 0x100 - undefined4 m_unk0x104; // 0x104 - undefined4 m_unk0x108; // 0x108 - undefined4 m_unk0x10c; // 0x10c - undefined4 m_unk0x110; // 0x110 - undefined4 m_unk0x114; // 0x114 - undefined4 m_unk0x118; // 0x118 - undefined4 m_unk0x11c; // 0x11c - undefined4 m_unk0x120; // 0x120 - this may be the current vehcle (function at 0x10015880) - undefined4 m_unk0x124; // 0x124 - something game state - undefined4 m_unk0x128; // 0x128 - undefined4 m_unk0x12c; // 0x12c - undefined4 m_unk0x130[4]; // unconfirmed bytes, ghidra claims these are integers - undefined4 m_unk0x140; + undefined4 m_unk0xf8; // 0xf8 + undefined4 m_unk0xfc; // 0xfc + undefined4 m_unk0x100; // 0x100 + undefined4 m_unk0x104; // 0x104 + undefined4 m_unk0x108; // 0x108 + undefined4 m_unk0x10c; // 0x10c + undefined4 m_unk0x110; // 0x110 + undefined4 m_unk0x114; // 0x114 + undefined4 m_unk0x118; // 0x118 + undefined4 m_unk0x11c; // 0x11c + undefined4 m_unk0x120; // 0x120 + undefined4 m_unk0x124; // 0x124 + undefined4 m_unk0x128; // 0x128 + undefined4 m_unk0x12c; // 0x12c + +protected: + MxRect32 m_unk0x130; // 0x130 + +private: + undefined4 m_unk0x140; // 0x140 }; #endif // LEGORACE_H diff --git a/LEGO1/legoraceactor.h b/LEGO1/legoraceactor.h index 9a4e34ec..eb459e81 100644 --- a/LEGO1/legoraceactor.h +++ b/LEGO1/legoraceactor.h @@ -9,7 +9,7 @@ class LegoRaceActor : public LegoAnimActor { // FUNCTION: LEGO1 0x10014af0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0bf4 + // STRING: LEGO1 0x100f0bf4 return "LegoRaceActor"; } diff --git a/LEGO1/legoracecar.h b/LEGO1/legoracecar.h new file mode 100644 index 00000000..d3800b5a --- /dev/null +++ b/LEGO1/legoracecar.h @@ -0,0 +1,25 @@ +#ifndef LEGOCARRACE_H +#define LEGOCARRACE_H + +#include "legocarraceactor.h" +#include "legopathactor.h" + +// VTABLE: LEGO1 0x100d58b8 +// SIZE: 0x200 +class LegoRaceCar : public LegoCarRaceActor { +public: + // FUNCTION: LEGO1 0x10014290 + inline const char* ClassName() const override // vtable+0xc + { + // STRING: LEGO1 0x100f0548 + return "LegoRaceCar"; + } + + // FUNCTION: LEGO1 0x100142b0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); + } +}; + +#endif // LEGOCARRACE_H diff --git a/LEGO1/legostate.h b/LEGO1/legostate.h index 55f0a1af..ba4403de 100644 --- a/LEGO1/legostate.h +++ b/LEGO1/legostate.h @@ -14,7 +14,7 @@ class LegoState : public MxCore { // FUNCTION: LEGO1 0x100060d0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f01b8 + // STRING: LEGO1 0x100f01b8 return "LegoState"; } diff --git a/LEGO1/legotexturepresenter.cpp b/LEGO1/legotexturepresenter.cpp index 36a7e243..6d0cbe8c 100644 --- a/LEGO1/legotexturepresenter.cpp +++ b/LEGO1/legotexturepresenter.cpp @@ -2,6 +2,7 @@ #include "legoomni.h" #include "legovideomanager.h" +#include "mxcompositepresenter.h" // FUNCTION: LEGO1 0x1004eb40 LegoTexturePresenter::~LegoTexturePresenter() @@ -15,3 +16,21 @@ MxResult LegoTexturePresenter::AddToManager() VideoManager()->AddPresenter(*this); return SUCCESS; } + +// STUB: LEGO1 0x1004fc60 +MxResult LegoTexturePresenter::PutData() +{ + // TODO + return FAILURE; +} + +// FUNCTION: LEGO1 0x1004fcb0 +void LegoTexturePresenter::DoneTickle() +{ + if (this->m_compositePresenter && !this->m_compositePresenter->VTable0x64(2)) { + SetTickleState(TickleState_Idle); + return; + } + + MxMediaPresenter::DoneTickle(); +} diff --git a/LEGO1/legotexturepresenter.h b/LEGO1/legotexturepresenter.h index 22a23500..0ac13926 100644 --- a/LEGO1/legotexturepresenter.h +++ b/LEGO1/legotexturepresenter.h @@ -12,7 +12,7 @@ class LegoTexturePresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000ce50 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0664 + // STRING: LEGO1 0x100f0664 return "LegoTexturePresenter"; } @@ -22,7 +22,9 @@ class LegoTexturePresenter : public MxMediaPresenter { return !strcmp(p_name, LegoTexturePresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } + virtual void DoneTickle() override; // vtable+0x2c virtual MxResult AddToManager() override; // vtable+0x34 + virtual MxResult PutData() override; // vtable+0x4c }; #endif // LEGOTEXTUREPRESENTER_H diff --git a/LEGO1/legovideomanager.cpp b/LEGO1/legovideomanager.cpp index 167b81a3..456b10f5 100644 --- a/LEGO1/legovideomanager.cpp +++ b/LEGO1/legovideomanager.cpp @@ -37,6 +37,13 @@ LegoVideoManager::~LegoVideoManager() delete m_palette; } +// STUB: LEGO1 0x1007ac40 +MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) +{ + // TODO + return MxVideoManager::Create(p_videoParam, p_frequencyMS, p_createThread); +} + // FUNCTION: LEGO1 0x1007b5e0 void LegoVideoManager::Destroy() { @@ -69,6 +76,31 @@ void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) m_cursorY = 463; } +// STUB: LEGO1 0x1007b770 +MxResult LegoVideoManager::Tickle() +{ + // TODO + return MxVideoManager::Tickle(); +} + +// STUB: LEGO1 0x1007c080 +void LegoVideoManager::VTable0x38(undefined4, undefined4) +{ + // TODO +} + +// FUNCTION: LEGO1 0x1007c290 +MxResult LegoVideoManager::RealizePalette(MxPalette* p_pallete) +{ + if (p_pallete && m_videoParam.GetPalette()) { + p_pallete->GetEntries(m_paletteEntries); + m_videoParam.GetPalette()->SetEntries(m_paletteEntries); + m_displaySurface->SetPalette(m_videoParam.GetPalette()); + } + + return SUCCESS; +} + // FUNCTION: LEGO1 0x1007c300 void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable) { @@ -135,9 +167,7 @@ void LegoVideoManager::SetSkyColor(float p_red, float p_green, float p_blue) colorStrucure.peFlags = -124; m_videoParam.GetPalette()->SetSkyColor(&colorStrucure); m_videoParam.GetPalette()->SetOverrideSkyColor(TRUE); - - // TODO 3d manager - // m_3dManager->m_pViewport->VTable0x1c(red, green, blue) + m_3dManager->GetLego3DView()->GetViewPort()->SetBackgroundColor(p_red, p_green, p_blue); } // FUNCTION: LEGO1 0x1007c4c0 @@ -146,6 +176,21 @@ void LegoVideoManager::OverrideSkyColor(MxBool p_shouldOverride) this->m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride); } +// FUNCTION: LEGO1 0x1007c4d0 +void LegoVideoManager::VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) +{ + if (p_width == 0) { + p_width = m_videoParam.GetRect().GetWidth(); + } + if (p_height == 0) { + p_height = m_videoParam.GetRect().GetHeight(); + } + + if (!m_initialized) { + m_3dManager->GetLego3DView()->GetViewPort()->ForceUpdate(p_x, p_y, p_width, p_height); + } +} + // STUB: LEGO1 0x1007c560 int LegoVideoManager::EnableRMDevice() { diff --git a/LEGO1/legovideomanager.h b/LEGO1/legovideomanager.h index 11501e2d..122505de 100644 --- a/LEGO1/legovideomanager.h +++ b/LEGO1/legovideomanager.h @@ -21,7 +21,15 @@ class LegoVideoManager : public MxVideoManager { __declspec(dllexport) void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale); __declspec(dllexport) void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY); - virtual void Destroy() override; // vtable+0x18 + virtual MxResult Tickle() override; // vtable+0x8 + virtual void Destroy() override; // vtable+0x18 + virtual MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) + override; // vtable+0x2c + virtual MxResult RealizePalette(MxPalette*) override; // vtable+0x30 + virtual void VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) override; // vtable+0x34 + virtual void VTable0x38(undefined4, undefined4); // vtable+0x38 + // FUNCTION: LGEO1 0x1007ab10 + virtual undefined4 VTable0x3c() { return m_unk0x4e8; } // vtable+0x3c void SetSkyColor(float p_red, float p_green, float p_blue); void OverrideSkyColor(MxBool p_shouldOverride); diff --git a/LEGO1/legoworld.h b/LEGO1/legoworld.h index 8b95fb24..eed5c6b0 100644 --- a/LEGO1/legoworld.h +++ b/LEGO1/legoworld.h @@ -23,7 +23,7 @@ class LegoWorld : public LegoEntity { // FUNCTION: LEGO1 0x1001d690 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0058 + // STRING: LEGO1 0x100f0058 return "LegoWorld"; } diff --git a/LEGO1/legoworldpresenter.cpp b/LEGO1/legoworldpresenter.cpp index 9cd12880..02578675 100644 --- a/LEGO1/legoworldpresenter.cpp +++ b/LEGO1/legoworldpresenter.cpp @@ -1,5 +1,16 @@ #include "legoworldpresenter.h" +#include "legoentity.h" +#include "legoomni.h" +#include "legovideomanager.h" +#include "mxactionnotificationparam.h" +#include "mxautolocker.h" +#include "mxdsactionlist.h" +#include "mxdsmultiaction.h" +#include "mxobjectfactory.h" +#include "mxpresenter.h" +#include "mxstl/stlcompat.h" + // GLOBAL: LEGO1 0x100f75d4 undefined4 g_legoWorldPresenterQuality = 1; @@ -20,3 +31,101 @@ LegoWorldPresenter::~LegoWorldPresenter() { // TODO } + +// FUNCTION: LEGO1 0x10066870 +MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + MxAutoLocker lock(&m_criticalSection); + + MxResult result = FAILURE; + MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList(); + MxObjectFactory* factory = ObjectFactory(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + if (MxPresenter::StartAction(p_controller, p_action) == SUCCESS) { + // The usual cursor.Next() loop doesn't match here, even though + // the logic is the same. It does match when "deconstructed" into + // the following Head(), Current() and NextFragment() calls, + // but this seems unlikely to be the original code. + // The alpha debug build also uses Next(). + cursor.Head(); + while (cursor.Current(action)) { + cursor.NextFragment(); + + MxBool success = FALSE; + + action->CopyFlags(m_action->GetFlags()); + + const char* presenterName = PresenterNameDispatch(*action); + MxPresenter* presenter = (MxPresenter*) factory->Create(presenterName); + + if (presenter && presenter->AddToManager() == SUCCESS) { + presenter->SetCompositePresenter(this); + if (presenter->StartAction(p_controller, action) == SUCCESS) { + presenter->SetTickleState(TickleState_Idle); + success = TRUE; + } + } + + if (success) { + action->SetOrigin(this); + m_list.push_back(presenter); + } + else if (presenter) + delete presenter; + } + + VideoManager()->AddPresenter(*this); + + result = SUCCESS; + } + + return result; +} + +// FUNCTION: LEGO1 0x10066a50 +void LegoWorldPresenter::ReadyTickle() +{ + m_objectBackend = (LegoEntity*) MxPresenter::CreateEntityBackend("LegoWorld"); + if (m_objectBackend) { + m_objectBackend->Create(*m_action); + Lego()->AddWorld((LegoWorld*) m_objectBackend); + SetBackendLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); + } + + ParseExtra(); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Starting; +} + +// FUNCTION: LEGO1 0x10066ac0 +void LegoWorldPresenter::StartingTickle() +{ + if (m_action->IsA("MxDSSerialAction")) { + MxPresenter* presenter = *m_list.begin(); + if (presenter->GetCurrentTickleState() == TickleState_Idle) { + presenter->SetTickleState(TickleState_Ready); + } + } + else { + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + if ((*it)->GetCurrentTickleState() == TickleState_Idle) { + (*it)->SetTickleState(TickleState_Ready); + } + } + } + + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Streaming; +} + +// STUB: LEGO1 0x10067a70 +void LegoWorldPresenter::VTable0x60(MxPresenter* p_presenter) +{ +} + +// STUB: LEGO1 0x10067b00 +void LegoWorldPresenter::ParseExtra() +{ +} diff --git a/LEGO1/legoworldpresenter.h b/LEGO1/legoworldpresenter.h index bcae2f5e..be18baca 100644 --- a/LEGO1/legoworldpresenter.h +++ b/LEGO1/legoworldpresenter.h @@ -15,7 +15,7 @@ class LegoWorldPresenter : public LegoEntityPresenter { // FUNCTION: LEGO1 0x10066630 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0608 + // STRING: LEGO1 0x100f0608 return "LegoWorldPresenter"; } @@ -25,6 +25,12 @@ class LegoWorldPresenter : public LegoEntityPresenter { return !strcmp(p_name, LegoWorldPresenter::ClassName()) || LegoEntityPresenter::IsA(p_name); } + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void ParseExtra() override; // vtable+0x30 + virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + virtual void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 + private: undefined4 m_unk0x50; }; diff --git a/LEGO1/motorcycle.h b/LEGO1/motorcycle.h index a698fcd8..af04b4ad 100644 --- a/LEGO1/motorcycle.h +++ b/LEGO1/motorcycle.h @@ -13,7 +13,7 @@ class Motorcycle : public IslePathActor { // FUNCTION: LEGO1 0x10035840 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f38e8 + // STRING: LEGO1 0x100f38e8 return "Motorcycle"; } diff --git a/LEGO1/mxaudiopresenter.h b/LEGO1/mxaudiopresenter.h index f1d207e1..73024aac 100644 --- a/LEGO1/mxaudiopresenter.h +++ b/LEGO1/mxaudiopresenter.h @@ -13,7 +13,7 @@ class MxAudioPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000d280 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f078c + // STRING: LEGO1 0x100f078c return "MxAudioPresenter"; } diff --git a/LEGO1/mxbackgroundaudiomanager.h b/LEGO1/mxbackgroundaudiomanager.h index cb03624c..9d47947f 100644 --- a/LEGO1/mxbackgroundaudiomanager.h +++ b/LEGO1/mxbackgroundaudiomanager.h @@ -21,7 +21,7 @@ class MxBackgroundAudioManager : public MxCore { // FUNCTION: LEGO1 0x1007eb70 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f7ac4 + // STRING: LEGO1 0x100f7ac4 return "MxBackgroundAudioManager"; } diff --git a/LEGO1/mxcompositemediapresenter.h b/LEGO1/mxcompositemediapresenter.h index 4f0efc76..ed6f1335 100644 --- a/LEGO1/mxcompositemediapresenter.h +++ b/LEGO1/mxcompositemediapresenter.h @@ -15,7 +15,7 @@ class MxCompositeMediaPresenter : public MxCompositePresenter { // FUNCTION: LEGO1 0x10073f10 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02d4 + // STRING: LEGO1 0x100f02d4 return "MxCompositeMediaPresenter"; } diff --git a/LEGO1/mxcompositepresenter.h b/LEGO1/mxcompositepresenter.h index f6929b6d..6f14e615 100644 --- a/LEGO1/mxcompositepresenter.h +++ b/LEGO1/mxcompositepresenter.h @@ -19,7 +19,7 @@ class MxCompositePresenter : public MxPresenter { // FUNCTION: LEGO1 0x100b6210 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0774 + // STRING: LEGO1 0x100f0774 return "MxCompositePresenter"; } diff --git a/LEGO1/mxcontrolpresenter.h b/LEGO1/mxcontrolpresenter.h index 515af808..9779e45f 100644 --- a/LEGO1/mxcontrolpresenter.h +++ b/LEGO1/mxcontrolpresenter.h @@ -14,7 +14,7 @@ class MxControlPresenter : public MxCompositePresenter { // FUNCTION: LEGO1 0x10044000 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0514 + // STRING: LEGO1 0x100f0514 return "MxControlPresenter"; } diff --git a/LEGO1/mxcore.h b/LEGO1/mxcore.h index 5792eaf2..db812bba 100644 --- a/LEGO1/mxcore.h +++ b/LEGO1/mxcore.h @@ -20,7 +20,7 @@ class MxCore { // FUNCTION: LEGO1 0x100144c0 inline virtual const char* ClassName() const // vtable+0c { - // GLOBAL: LEGO1 0x100f007c + // STRING: LEGO1 0x100f007c return "MxCore"; } diff --git a/LEGO1/mxdiskstreamcontroller.cpp b/LEGO1/mxdiskstreamcontroller.cpp index 1520ba3b..f992443d 100644 --- a/LEGO1/mxdiskstreamcontroller.cpp +++ b/LEGO1/mxdiskstreamcontroller.cpp @@ -15,10 +15,41 @@ MxDiskStreamController::MxDiskStreamController() m_unk0x8c = 0; } -// STUB: LEGO1 0x100c7530 +// FUNCTION: LEGO1 0x100c7530 MxDiskStreamController::~MxDiskStreamController() { - // TODO + MxAutoLocker lock(&this->m_criticalSection); + + m_unk0xc4 = FALSE; + m_unk0x70 = FALSE; + + if (m_provider) + m_provider->VTable0x20(&MxDSAction()); + + MxDSAction* action; + while (m_unk0x3c.PopFront(action)) + delete action; + + if (m_provider) { + delete m_provider; + m_provider = NULL; + } + + FUN_100c8720(); + + while (m_list0x80.PopFront(action)) + FUN_100c7cb0((MxDSStreamingAction*) action); + + while (m_list0x64.PopFront(action)) + FUN_100c7cb0((MxDSStreamingAction*) action); + + while (!m_list0x74.empty()) { + MxDSBuffer* buffer = m_list0x74.front(); + m_list0x74.pop_front(); + FUN_100c7ce0(buffer); + } + + TickleManager()->UnregisterClient(this); } // FUNCTION: LEGO1 0x100c7790 @@ -257,8 +288,8 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) else if (MxStreamController::VTable0x20(p_action) != SUCCESS) return FAILURE; - m_unk0x70 = 1; - m_unk0xc4 = 1; + m_unk0x70 = TRUE; + m_unk0xc4 = TRUE; return SUCCESS; } @@ -289,9 +320,9 @@ MxResult MxDiskStreamController::VTable0x24(MxDSAction* p_action) MxStreamController::VTable0x24(&action); } while (m_action0x60 != NULL); - if (m_unk0x3c.size() == 0) { - m_unk0x70 = 0; - m_unk0xc4 = 0; + if (m_unk0x3c.empty()) { + m_unk0x70 = FALSE; + m_unk0xc4 = FALSE; } return SUCCESS; @@ -389,7 +420,7 @@ void MxDiskStreamController::FUN_100c8720() MxAutoLocker lock(&this->m_critical9c); MxDSStreamingAction* action; - while (m_list0xb8.size() != 0) { + while (!m_list0xb8.empty()) { action = (MxDSStreamingAction*) m_list0xb8.front(); m_list0xb8.pop_front(); diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/mxdiskstreamcontroller.h index 703b3bf2..bc5cce61 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/mxdiskstreamcontroller.h @@ -17,19 +17,12 @@ class MxDiskStreamController : public MxStreamController { MxDiskStreamController(); virtual ~MxDiskStreamController() override; - virtual MxResult Tickle() override; // vtable+0x8 - virtual MxResult Open(const char* p_filename) override; // vtable+0x14 - virtual MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18 - virtual MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20 - virtual MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24 - virtual MxDSStreamingAction* VTable0x28() override; // vtable+0x28 - virtual MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30 - virtual MxResult VTable0x34(undefined4); // vtable+0x34 + virtual MxResult Tickle() override; // vtable+0x8 // FUNCTION: LEGO1 0x100c7360 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102144 + // STRING: LEGO1 0x10102144 return "MxDiskStreamController"; } @@ -39,6 +32,14 @@ class MxDiskStreamController : public MxStreamController { return !strcmp(p_name, MxDiskStreamController::ClassName()) || MxStreamController::IsA(p_name); } + virtual MxResult Open(const char* p_filename) override; // vtable+0x14 + virtual MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18 + virtual MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20 + virtual MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24 + virtual MxDSStreamingAction* VTable0x28() override; // vtable+0x28 + virtual MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30 + virtual MxResult VTable0x34(undefined4); // vtable+0x34 + inline MxBool GetUnk0xc4() const { return m_unk0xc4; } void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); @@ -48,7 +49,7 @@ class MxDiskStreamController : public MxStreamController { private: MxStreamListMxDSAction m_list0x64; // 0x64 - undefined m_unk0x70; // 0x70 + MxBool m_unk0x70; // 0x70 list m_list0x74; // 0x74 MxStreamListMxDSAction m_list0x80; // 0x80 undefined2 m_unk0x8c; // 0x8c diff --git a/LEGO1/mxdiskstreamprovider.cpp b/LEGO1/mxdiskstreamprovider.cpp index c7e311eb..b9ed63d0 100644 --- a/LEGO1/mxdiskstreamprovider.cpp +++ b/LEGO1/mxdiskstreamprovider.cpp @@ -40,10 +40,39 @@ MxDiskStreamProvider::MxDiskStreamProvider() this->m_unk0x35 = FALSE; } -// STUB: LEGO1 0x100d1240 +// FUNCTION: LEGO1 0x100d1240 MxDiskStreamProvider::~MxDiskStreamProvider() { - // TODO + MxDSStreamingAction* action; + m_unk0x35 = FALSE; + + do { + action = NULL; + + { + MxAutoLocker lock(&m_criticalSection); + m_list.PopFrontStreamingAction(action); + } + + if (!action) + break; + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + g_unk0x10102878--; + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + + if (m_remainingWork) { + m_remainingWork = FALSE; + m_busySemaphore.Release(1); + m_thread.Terminate(); + } + + if (m_pFile) + delete m_pFile; + + m_pFile = NULL; } // FUNCTION: LEGO1 0x100d13d0 @@ -77,10 +106,47 @@ MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource) return result; } -// STUB: LEGO1 0x100d15e0 +// FUNCTION: LEGO1 0x100d15e0 void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) { - // TODO + MxDSStreamingAction* action; + + if (p_action->GetObjectId() == -1) { + m_unk0x35 = FALSE; + + do { + action = NULL; + + { + MxAutoLocker lock(&m_criticalSection); + m_list.PopFrontStreamingAction(action); + } + + if (!action) + return; + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + g_unk0x10102878--; + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + } + else { + do { + { + MxAutoLocker lock(&m_criticalSection); + action = (MxDSStreamingAction*) m_list.Find(p_action, TRUE); + } + + if (!action) + return; + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + g_unk0x10102878--; + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + } } // FUNCTION: LEGO1 0x100d1750 diff --git a/LEGO1/mxdiskstreamprovider.h b/LEGO1/mxdiskstreamprovider.h index bc73c0e4..1314e3f9 100644 --- a/LEGO1/mxdiskstreamprovider.h +++ b/LEGO1/mxdiskstreamprovider.h @@ -32,7 +32,7 @@ class MxDiskStreamProvider : public MxStreamProvider { // FUNCTION: LEGO1 0x100d1160 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010287c + // STRING: LEGO1 0x1010287c return "MxDiskStreamProvider"; } diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index bc1d2078..de4d7006 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -5,6 +5,8 @@ DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); +MxU32 g_unk0x1010215c = 0; + // FUNCTION: LEGO1 0x100ba500 MxDisplaySurface::MxDisplaySurface() { @@ -248,9 +250,60 @@ undefined4 MxDisplaySurface::VTable0x34(undefined4, undefined4, undefined4, unde return 0; } -// STUB: LEGO1 0x100bba50 -void MxDisplaySurface::Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) +// FUNCTION: LEGO1 0x100bba50 +void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height) { + if (m_videoParam.Flags().GetF2bit1()) { + if (m_videoParam.Flags().GetFlipSurfaces()) { + if (g_unk0x1010215c < 2) { + g_unk0x1010215c++; + + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (m_ddSurface2->Lock(NULL, &ddsd, 1, NULL) == S_OK) { + MxU8* surface = (MxU8*) ddsd.lpSurface; + MxS32 height = m_videoParam.GetRect().GetHeight(); + + for (MxU32 i = 0; i < ddsd.dwHeight; i++) { + memset(surface, 0, ddsd.dwWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8); + surface += ddsd.lPitch; + } + + m_ddSurface2->Unlock(ddsd.lpSurface); + } + else { + OutputDebugString("MxDisplaySurface::Display error\n"); + } + } + m_ddSurface1->Flip(NULL, 1); + } + else { + POINT point = {0, 0}; + ClientToScreen(MxOmni::GetInstance()->GetWindowHandle(), &point); + + // TODO: Match + RECT rect1, rect2; + rect1.left = p_left2 + m_videoParam.GetRect().GetLeft() + point.x; + rect2.left = p_left; + rect1.top = p_top2 + m_videoParam.GetRect().GetTop() + point.y; + rect2.right = p_left + p_width; + rect2.top = p_top; + rect2.bottom = p_top + p_height; + rect1.right = rect1.left + p_width; + rect1.bottom = rect1.top + p_height; + + DDBLTFX data; + memset(&data, 0, sizeof(data)); + data.dwSize = sizeof(data); + data.dwDDFX = 8; + + if (m_ddSurface1->Blt(&rect1, m_ddSurface2, &rect2, 0, &data) == DDERR_SURFACELOST) { + m_ddSurface1->Restore(); + m_ddSurface1->Blt(&rect1, m_ddSurface2, &rect2, 0, &data); + } + } + } } // FUNCTION: LEGO1 0x100bbc10 diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index 3d386bb4..45714ce1 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -62,7 +62,7 @@ class MxDisplaySurface : public MxCore { MxBool ); virtual undefined4 VTable0x34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); - virtual void Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); + virtual void Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height); virtual void GetDC(HDC* p_hdc); virtual void ReleaseDC(HDC p_hdc); virtual LPDIRECTDRAWSURFACE VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4); diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index eb70b18f..c32dd4aa 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -33,7 +33,7 @@ class MxDSAction : public MxDSObject { // FUNCTION: LEGO1 0x100ad980 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101013f4 + // STRING: LEGO1 0x101013f4 return "MxDSAction"; } @@ -63,7 +63,9 @@ class MxDSAction : public MxDSObject { inline MxLong GetStartTime() const { return m_startTime; } inline MxS32 GetLoopCount() { return m_loopCount; } inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } - inline const Vector3Data& GetLocation() const { return m_location; } + inline Vector3Data& GetLocation() { return m_location; } + inline Vector3Data& GetDirection() { return m_direction; } + inline Vector3Data& GetUp() { return m_up; } inline MxCore* GetUnknown84() { return m_unk0x84; } inline void SetUnknown84(MxCore* p_unk0x84) { m_unk0x84 = p_unk0x84; } inline MxCore* GetOrigin() { return m_origin; } diff --git a/LEGO1/mxdsanim.h b/LEGO1/mxdsanim.h index ee206e6a..213fcf87 100644 --- a/LEGO1/mxdsanim.h +++ b/LEGO1/mxdsanim.h @@ -16,7 +16,7 @@ class MxDSAnim : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c9060 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025d8 + // STRING: LEGO1 0x101025d8 return "MxDSAnim"; } diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp index 261f00d3..da643c17 100644 --- a/LEGO1/mxdsbuffer.cpp +++ b/LEGO1/mxdsbuffer.cpp @@ -30,11 +30,45 @@ MxDSBuffer::MxDSBuffer() MxDSBuffer::~MxDSBuffer() { if (m_pBuffer != NULL) { - if (m_mode == MxDSBufferType_Chunk) { - // TODO - } - else if (m_mode == MxDSBufferType_Allocate || m_mode == MxDSBufferType_Unknown) { + switch (m_mode) { + case MxDSBufferType_Allocate: + case MxDSBufferType_Unknown: delete[] m_pBuffer; + break; + + case MxDSBufferType_Chunk: { + MxU32 offset = m_writeOffset / 1024; + MxStreamer* streamer = Streamer(); + + switch (offset) { + case 0x40: { + MxU32 a = + (m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10); + + MxU32 bit = 1 << ((MxU8) a & 0x1f); + MxU32 index = (a & ~0x18u) >> 3; + + if ((*(MxU32*) (&streamer->GetSubclass1().GetUnk08Ref()[index])) & bit) { + MxU32* ptr = (MxU32*) (&streamer->GetSubclass1().GetUnk08Ref()[index]); + *ptr = *ptr ^ bit; + } + break; + } + case 0x80: { + MxU32 a = + (m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10); + + MxU32 bit = 1 << ((MxU8) a & 0x1f); + MxU32 index = (a & ~0x18u) >> 3; + + if ((*(MxU32*) (&streamer->GetSubclass2().GetUnk08Ref()[index])) & bit) { + MxU32* ptr = (MxU32*) (&streamer->GetSubclass2().GetUnk08Ref()[index]); + *ptr = *ptr ^ bit; + } + break; + } + } + } } } @@ -246,7 +280,7 @@ MxResult MxDSBuffer::StartPresenterFromAction( return SUCCESS; } -// STUB: LEGO1 0x100c6a50 +// FUNCTION: LEGO1 0x100c6a50 MxResult MxDSBuffer::ParseChunk( MxStreamController* p_controller, MxU32* p_data, @@ -255,8 +289,83 @@ MxResult MxDSBuffer::ParseChunk( MxStreamChunk* p_header ) { - // TODO - return FAILURE; + MxResult result = SUCCESS; + + if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && m_unk0x30->GetUnknowna8() && p_header->GetTime() < 0) { + delete p_header; + return SUCCESS; + } + + p_header->SetTime(p_header->GetTime() + m_unk0x30->GetUnknowna8()); + + if (p_header->GetFlags() & MxDSChunk::Flag_Bit5) { + MxU32 length = p_header->GetLength() + MxDSChunk::ReturnE() + 8; + MxDSBuffer* buffer = new MxDSBuffer(); + + if (buffer && buffer->AllocateBuffer(length, MxDSBufferType_Allocate) == SUCCESS && + buffer->CalcBytesRemaining((MxU8*) p_data) == SUCCESS) { + *p_streamingAction = new MxDSStreamingAction((MxDSStreamingAction&) *p_action); + ; + + if (*p_streamingAction) { + MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer()); + *flags = p_header->GetFlags() & ~MxDSChunk::Flag_Bit5; + + delete p_header; + (*p_streamingAction)->SetUnknowna0(buffer); + goto done; + } + } + + if (buffer) + delete buffer; + + delete p_header; + return FAILURE; + } + else { + if (p_header->GetFlags() & MxDSChunk::Flag_Bit2) { + if (m_unk0x30->HasId(p_header->GetObjectId())) { + if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && + (m_unk0x30->GetLoopCount() > 1 || m_unk0x30->GetDuration() == -1)) { + + if (p_action->GetObjectId() == p_header->GetObjectId()) { + MxU32 val = p_controller->GetProvider()->GetBufferForDWords()[m_unk0x30->GetObjectId()]; + + m_unk0x30->SetUnknown94(val); + m_unk0x30->SetBufferOffset(m_writeOffset * (val / m_writeOffset)); + + MxNextActionDataStart* data = + p_controller->FindNextActionDataStartFromStreamingAction(m_unk0x30); + + if (data) + data->SetData(m_unk0x30->GetBufferOffset()); + + m_unk0x30->FUN_100cd2d0(); + } + + delete p_header; + p_header = NULL; + } + else { + if (p_action->GetObjectId() == p_header->GetObjectId() && + p_controller->VTable0x30(p_action) == SUCCESS) { + p_controller->GetProvider()->VTable0x20(p_action); + result = 1; + } + } + } + } + + if (p_header) { + if (p_header->SendChunk(p_controller->GetSubscriberList(), TRUE, p_action->GetUnknown24()) != SUCCESS) { + delete p_header; + } + } + } + +done: + return result; } // FUNCTION: LEGO1 0x100c6d00 @@ -343,11 +452,36 @@ void MxDSBuffer::AddRef(MxDSChunk* p_chunk) } } -// STUB: LEGO1 0x100c6ef0 +// FUNCTION: LEGO1 0x100c6ef0 MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) { - // TODO - return FAILURE; + MxResult result = FAILURE; + + if (m_mode == MxDSBufferType_Allocate && m_bytesRemaining != 0) { + MxU32 bytesRead; + MxU8* ptr; + + if (m_writeOffset == m_bytesRemaining) { + bytesRead = *(MxU32*) (p_data + 4) + 8; + ptr = p_data; + } + else { + ptr = &p_data[MxStreamChunk::ReturnE() + 8]; + bytesRead = (*(MxU32*) (p_data + 4)) - MxStreamChunk::ReturnE(); + } + + if (bytesRead <= m_bytesRemaining) { + memcpy(m_pBuffer + m_writeOffset - m_bytesRemaining, ptr, bytesRead); + + if (m_writeOffset == m_bytesRemaining) + *(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoPlus0x12(m_pBuffer) + MxStreamChunk::ReturnE(); + + m_bytesRemaining -= bytesRead; + result = SUCCESS; + } + } + + return result; } // FUNCTION: LEGO1 0x100c6f80 diff --git a/LEGO1/mxdsbuffer.h b/LEGO1/mxdsbuffer.h index e9fe2675..daa3263e 100644 --- a/LEGO1/mxdsbuffer.h +++ b/LEGO1/mxdsbuffer.h @@ -27,7 +27,7 @@ class MxDSBuffer : public MxCore { // FUNCTION: LEGO1 0x100c6500 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025b8 + // STRING: LEGO1 0x101025b8 return "MxDSBuffer"; } diff --git a/LEGO1/mxdschunk.cpp b/LEGO1/mxdschunk.cpp index b44bc475..bf7e08a6 100644 --- a/LEGO1/mxdschunk.cpp +++ b/LEGO1/mxdschunk.cpp @@ -19,3 +19,9 @@ MxDSChunk::~MxDSChunk() delete[] m_data; } } + +// FUNCTION: LEGO1 0x100be1e0 +MxU32 MxDSChunk::ReturnE() +{ + return 0xe; +} diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index 4cbb2fc9..9f2ac9b6 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/mxdschunk.h @@ -13,6 +13,8 @@ class MxDSChunk : public MxCore { Flag_Bit1 = 0x01, Flag_Bit2 = 0x02, Flag_Bit3 = 0x04, + Flag_Bit4 = 0x08, + Flag_Bit5 = 0x10, Flag_Bit8 = 0x80, Flag_Bit16 = 0x8000 }; @@ -23,7 +25,7 @@ class MxDSChunk : public MxCore { // FUNCTION: LEGO1 0x100be0c0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101e6c + // STRING: LEGO1 0x10101e6c return "MxDSChunk"; } @@ -33,6 +35,8 @@ class MxDSChunk : public MxCore { return !strcmp(p_name, MxDSChunk::ClassName()) || MxCore::IsA(p_name); } + static MxU32 ReturnE(); + inline void SetFlags(MxU16 p_flags) { m_flags = p_flags; } inline void SetObjectId(undefined4 p_objectid) { m_objectId = p_objectid; } inline void SetTime(MxLong p_time) { m_time = p_time; } @@ -52,11 +56,11 @@ class MxDSChunk : public MxCore { } protected: - MxU16 m_flags; // 0x8 - undefined4 m_objectId; // 0xc - MxLong m_time; // 0x10 - MxU32 m_length; // 0x14 - MxU8* m_data; // 0x18 + MxU16 m_flags; // 0x8 + MxU32 m_objectId; // 0xc + MxLong m_time; // 0x10 + MxU32 m_length; // 0x14 + MxU8* m_data; // 0x18 }; #endif // MXDSCHUNK_H diff --git a/LEGO1/mxdsevent.h b/LEGO1/mxdsevent.h index 8c6e825e..01cf1fa4 100644 --- a/LEGO1/mxdsevent.h +++ b/LEGO1/mxdsevent.h @@ -14,7 +14,7 @@ class MxDSEvent : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c9660 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025f0 + // STRING: LEGO1 0x101025f0 return "MxDSEvent"; } diff --git a/LEGO1/mxdsfile.h b/LEGO1/mxdsfile.h index e453cb9a..34afeccb 100644 --- a/LEGO1/mxdsfile.h +++ b/LEGO1/mxdsfile.h @@ -17,7 +17,7 @@ class MxDSFile : public MxDSSource { // FUNCTION: LEGO1 0x100c0120 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102594 + // STRING: LEGO1 0x10102594 return "MxDSFile"; } diff --git a/LEGO1/mxdsmediaaction.h b/LEGO1/mxdsmediaaction.h index 72fcf036..1f1b97d5 100644 --- a/LEGO1/mxdsmediaaction.h +++ b/LEGO1/mxdsmediaaction.h @@ -18,7 +18,7 @@ class MxDSMediaAction : public MxDSAction { // FUNCTION: LEGO1 0x100c8be0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f7624 + // STRING: LEGO1 0x100f7624 return "MxDSMediaAction"; } diff --git a/LEGO1/mxdsmultiaction.h b/LEGO1/mxdsmultiaction.h index 5003a378..a600b787 100644 --- a/LEGO1/mxdsmultiaction.h +++ b/LEGO1/mxdsmultiaction.h @@ -17,7 +17,7 @@ class MxDSMultiAction : public MxDSAction { // FUNCTION: LEGO1 0x100c9f50 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101dbc + // STRING: LEGO1 0x10101dbc return "MxDSMultiAction"; } diff --git a/LEGO1/mxdsobjectaction.h b/LEGO1/mxdsobjectaction.h index 3286f110..a31f6d6b 100644 --- a/LEGO1/mxdsobjectaction.h +++ b/LEGO1/mxdsobjectaction.h @@ -15,7 +15,7 @@ class MxDSObjectAction : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c88e0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025c4 + // STRING: LEGO1 0x101025c4 return "MxDSObjectAction"; } diff --git a/LEGO1/mxdsparallelaction.h b/LEGO1/mxdsparallelaction.h index 65028ce3..89fc1df0 100644 --- a/LEGO1/mxdsparallelaction.h +++ b/LEGO1/mxdsparallelaction.h @@ -16,7 +16,7 @@ class MxDSParallelAction : public MxDSMultiAction { // FUNCTION: LEGO1 0x100caf00 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102608 + // STRING: LEGO1 0x10102608 return "MxDSParallelAction"; } diff --git a/LEGO1/mxdsselectaction.h b/LEGO1/mxdsselectaction.h index 187e3a72..6b68bfc9 100644 --- a/LEGO1/mxdsselectaction.h +++ b/LEGO1/mxdsselectaction.h @@ -18,7 +18,7 @@ class MxDSSelectAction : public MxDSParallelAction { // FUNCTION: LEGO1 0x100cb6f0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010261c + // STRING: LEGO1 0x1010261c return "MxDSSelectAction"; } diff --git a/LEGO1/mxdsserialaction.h b/LEGO1/mxdsserialaction.h index ea758afa..c4fa18b3 100644 --- a/LEGO1/mxdsserialaction.h +++ b/LEGO1/mxdsserialaction.h @@ -17,7 +17,7 @@ class MxDSSerialAction : public MxDSMultiAction { // FUNCTION: LEGO1 0x100caad0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f75dc + // STRING: LEGO1 0x100f75dc return "MxDSSerialAction"; } diff --git a/LEGO1/mxdssound.h b/LEGO1/mxdssound.h index 45f93942..5dc6bbd7 100644 --- a/LEGO1/mxdssound.h +++ b/LEGO1/mxdssound.h @@ -16,7 +16,7 @@ class MxDSSound : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c9330 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025e4 + // STRING: LEGO1 0x101025e4 return "MxDSSound"; } diff --git a/LEGO1/mxdssource.h b/LEGO1/mxdssource.h index 711ba110..db009fb4 100644 --- a/LEGO1/mxdssource.h +++ b/LEGO1/mxdssource.h @@ -14,7 +14,7 @@ class MxDSSource : public MxCore { // FUNCTION: LEGO1 0x100c0010 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102588 + // STRING: LEGO1 0x10102588 return "MxDSSource"; } diff --git a/LEGO1/mxdsstill.h b/LEGO1/mxdsstill.h index 846f8293..268fe79f 100644 --- a/LEGO1/mxdsstill.h +++ b/LEGO1/mxdsstill.h @@ -16,7 +16,7 @@ class MxDSStill : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c9930 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025fc + // STRING: LEGO1 0x101025fc return "MxDSStill"; } diff --git a/LEGO1/mxdsstreamingaction.h b/LEGO1/mxdsstreamingaction.h index 7581b217..00cd13aa 100644 --- a/LEGO1/mxdsstreamingaction.h +++ b/LEGO1/mxdsstreamingaction.h @@ -35,6 +35,7 @@ class MxDSStreamingAction : public MxDSAction { inline MxS32 GetUnknown9c() { return m_unk0x9c; } inline MxDSBuffer* GetUnknowna0() { return m_unk0xa0; } inline MxDSBuffer* GetUnknowna4() { return m_unk0xa4; } + inline MxLong GetUnknowna8() { return m_unk0xa8; } inline MxDSAction* GetInternalAction() { return m_internalAction; } inline MxU32 GetBufferOffset() { return m_bufferOffset; } inline void SetUnknown94(MxU32 p_unk0x94) { m_unk0x94 = p_unk0x94; } diff --git a/LEGO1/mxdssubscriber.cpp b/LEGO1/mxdssubscriber.cpp index b4fa97a0..33ee11fc 100644 --- a/LEGO1/mxdssubscriber.cpp +++ b/LEGO1/mxdssubscriber.cpp @@ -17,7 +17,7 @@ MxDSSubscriber::MxDSSubscriber() MxDSSubscriber::~MxDSSubscriber() { if (m_controller) - m_controller->FUN_100c1620(this); + m_controller->RemoveSubscriber(this); DeleteChunks(); @@ -48,7 +48,7 @@ MxResult MxDSSubscriber::Create(MxStreamController* p_controller, MxU32 p_object if (!m_unk0x3c) return FAILURE; - m_controller->FUN_100c15d0(this); + m_controller->AddSubscriber(this); return SUCCESS; } diff --git a/LEGO1/mxdssubscriber.h b/LEGO1/mxdssubscriber.h index 13d62040..8187e354 100644 --- a/LEGO1/mxdssubscriber.h +++ b/LEGO1/mxdssubscriber.h @@ -19,7 +19,7 @@ class MxDSSubscriber : public MxCore { // FUNCTION: LEGO1 0x100b7d50 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101020f8 + // STRING: LEGO1 0x101020f8 return "MxDSSubscriber"; } diff --git a/LEGO1/mxentity.h b/LEGO1/mxentity.h index a83462cd..64a003ee 100644 --- a/LEGO1/mxentity.h +++ b/LEGO1/mxentity.h @@ -17,7 +17,7 @@ class MxEntity : public MxCore { // FUNCTION: LEGO1 0x1000c180 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0070 + // STRING: LEGO1 0x100f0070 return "MxEntity"; } diff --git a/LEGO1/mxeventpresenter.h b/LEGO1/mxeventpresenter.h index d022f609..201b15e5 100644 --- a/LEGO1/mxeventpresenter.h +++ b/LEGO1/mxeventpresenter.h @@ -14,7 +14,7 @@ class MxEventPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x100c2c30 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101dcc + // STRING: LEGO1 0x10101dcc return "MxEventPresenter"; } diff --git a/LEGO1/mxflcpresenter.h b/LEGO1/mxflcpresenter.h index 393e2810..0ad44de3 100644 --- a/LEGO1/mxflcpresenter.h +++ b/LEGO1/mxflcpresenter.h @@ -22,7 +22,7 @@ class MxFlcPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x100b33f0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f43c8 + // STRING: LEGO1 0x100f43c8 return "MxFlcPresenter"; } diff --git a/LEGO1/mxloopingflcpresenter.h b/LEGO1/mxloopingflcpresenter.h index e4f781c9..c05c3657 100644 --- a/LEGO1/mxloopingflcpresenter.h +++ b/LEGO1/mxloopingflcpresenter.h @@ -14,7 +14,7 @@ class MxLoopingFlcPresenter : public MxFlcPresenter { // FUNCTION: LEGO1 0x100b4380 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e20 + // STRING: LEGO1 0x10101e20 return "MxLoopingFlcPresenter"; } diff --git a/LEGO1/mxloopingmidipresenter.h b/LEGO1/mxloopingmidipresenter.h index 49df30f4..e47ef30d 100644 --- a/LEGO1/mxloopingmidipresenter.h +++ b/LEGO1/mxloopingmidipresenter.h @@ -10,7 +10,7 @@ class MxLoopingMIDIPresenter : public MxMIDIPresenter { // FUNCTION: LEGO1 0x100b1830 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101de0 + // STRING: LEGO1 0x10101de0 return "MxLoopingMIDIPresenter"; } diff --git a/LEGO1/mxloopingsmkpresenter.h b/LEGO1/mxloopingsmkpresenter.h index 2f20676e..9506de84 100644 --- a/LEGO1/mxloopingsmkpresenter.h +++ b/LEGO1/mxloopingsmkpresenter.h @@ -14,7 +14,7 @@ class MxLoopingSmkPresenter : public MxSmkPresenter { // FUNCTION: LEGO1 0x100b4920 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e08 + // STRING: LEGO1 0x10101e08 return "MxLoopingSmkPresenter"; } diff --git a/LEGO1/mxmediapresenter.h b/LEGO1/mxmediapresenter.h index 4a482a78..32c7b6d0 100644 --- a/LEGO1/mxmediapresenter.h +++ b/LEGO1/mxmediapresenter.h @@ -18,7 +18,7 @@ class MxMediaPresenter : public MxPresenter { // FUNCTION: LEGO1 0x1000c5c0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f074c + // STRING: LEGO1 0x100f074c return "MxMediaPresenter"; } diff --git a/LEGO1/mxmidipresenter.h b/LEGO1/mxmidipresenter.h index 09e11dde..2ec11b0b 100644 --- a/LEGO1/mxmidipresenter.h +++ b/LEGO1/mxmidipresenter.h @@ -14,7 +14,7 @@ class MxMIDIPresenter : public MxMusicPresenter { // FUNCTION: LEGO1 0x100c2650 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101df8 + // STRING: LEGO1 0x10101df8 return "MxMIDIPresenter"; } diff --git a/LEGO1/mxmusicpresenter.h b/LEGO1/mxmusicpresenter.h index 965c38df..bba2afb0 100644 --- a/LEGO1/mxmusicpresenter.h +++ b/LEGO1/mxmusicpresenter.h @@ -13,7 +13,7 @@ class MxMusicPresenter : public MxAudioPresenter { // FUNCTION: LEGO1 0x100c23a0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e48 + // STRING: LEGO1 0x10101e48 return "MxMusicPresenter"; } diff --git a/LEGO1/mxnextactiondatastart.h b/LEGO1/mxnextactiondatastart.h index c9534899..15e35b00 100644 --- a/LEGO1/mxnextactiondatastart.h +++ b/LEGO1/mxnextactiondatastart.h @@ -18,7 +18,7 @@ class MxNextActionDataStart : public MxCore { // FUNCTION: LEGO1 0x100c1900 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x101025a0 + // STRING: LEGO1 0x101025a0 return "MxNextActionDataStart"; } diff --git a/LEGO1/mxobjectfactory.h b/LEGO1/mxobjectfactory.h index cfc97308..3741bfa3 100644 --- a/LEGO1/mxobjectfactory.h +++ b/LEGO1/mxobjectfactory.h @@ -26,7 +26,7 @@ class MxObjectFactory : public MxCore { // FUNCTION: LEGO1 0x10008f70 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0730 + // STRING: LEGO1 0x100f0730 return "MxObjectFactory"; } diff --git a/LEGO1/mxpalette.cpp b/LEGO1/mxpalette.cpp index 6d4f0306..8431fb76 100644 --- a/LEGO1/mxpalette.cpp +++ b/LEGO1/mxpalette.cpp @@ -4,7 +4,6 @@ #include "mxvideomanager.h" // GLOBAL: LEGO1 0x10102188 -// SIZE 0x400 PALETTEENTRY g_defaultPaletteEntries[256] = { {0u, 0u, 0u, 0u}, {128u, 0u, 0u, 0u}, {0u, 128u, 0u, 0u}, {128u, 128u, 0u, 0u}, {0u, 0u, 128u, 0u}, {128u, 0u, 128u, 0u}, {0u, 128u, 128u, 0u}, {128u, 128u, 128u, 0u}, diff --git a/LEGO1/mxpresenter.cpp b/LEGO1/mxpresenter.cpp index 31279513..b2404439 100644 --- a/LEGO1/mxpresenter.cpp +++ b/LEGO1/mxpresenter.cpp @@ -2,12 +2,14 @@ #include "decomp.h" #include "define.h" +#include "legoobjectfactory.h" #include "legoomni.h" #include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxcompositepresenter.h" #include "mxdsanim.h" #include "mxdssound.h" +#include "mxentity.h" #include "mxnotificationmanager.h" #include "mxparam.h" #include "mxstreamer.h" @@ -304,6 +306,27 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) return name; } +// FUNCTION: LEGO1 0x100b5410 +MxEntity* MxPresenter::CreateEntityBackend(const char* p_name) +{ + char buffer[512]; + char buffer2[512]; + strcpy(buffer, p_name); + + MxU16 extraLen = m_action->GetExtraLength(); + + buffer[0] = extraLen; + buffer[1] = extraLen >> 8; + if (extraLen) { + extraLen &= MAXWORD; + memcpy(buffer2 + 2, m_action->GetExtraData(), extraLen); + buffer2[extraLen + 2] = 0; + KeyValueStringParse(buffer, g_strOBJECT, buffer2 + 2); + } + + return (MxEntity*) ObjectFactory()->Create(buffer); +} + // FUNCTION: LEGO1 0x100b54c0 MxBool MxPresenter::IsEnabled() { diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index 160329c1..bc327c1f 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -10,6 +10,7 @@ class MxCompositePresenter; class MxStreamController; +class MxEntity; // VTABLE: LEGO1 0x100d4d38 // SIZE 0x40 @@ -33,7 +34,7 @@ class MxPresenter : public MxCore { // FUNCTION: LEGO1 0x1000bfe0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0740 + // STRING: LEGO1 0x100f0740 return "MxPresenter"; } @@ -65,6 +66,7 @@ class MxPresenter : public MxCore { virtual MxBool IsHit(MxS32 p_x, MxS32 p_y); // vtable+0x50 __declspec(dllexport) virtual void Enable(MxBool p_enable); // vtable+0x54 + MxEntity* CreateEntityBackend(const char* p_name); MxBool IsEnabled(); inline MxS32 GetCurrentTickleState() const { return this->m_currentTickleState; } diff --git a/LEGO1/mxramstreamcontroller.cpp b/LEGO1/mxramstreamcontroller.cpp index 0a5e29cd..71ee1b92 100644 --- a/LEGO1/mxramstreamcontroller.cpp +++ b/LEGO1/mxramstreamcontroller.cpp @@ -11,7 +11,7 @@ undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize); // FUNCTION: LEGO1 0x100c6110 MxResult MxRAMStreamController::Open(const char* p_filename) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); if (MxStreamController::Open(p_filename) != SUCCESS) { return FAILURE; } @@ -39,7 +39,7 @@ MxResult MxRAMStreamController::Open(const char* p_filename) // FUNCTION: LEGO1 0x100c6210 MxResult MxRAMStreamController::VTable0x20(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxS32 unk0x24 = 0; MxResult result = FAILURE; @@ -83,7 +83,7 @@ MxResult MxRAMStreamController::VTable0x24(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c63c0 MxResult MxRAMStreamController::DeserializeObject(MxDSStreamingAction& p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result; MxDSStreamingAction* value = NULL; diff --git a/LEGO1/mxramstreamcontroller.h b/LEGO1/mxramstreamcontroller.h index 008fe458..aa70ec33 100644 --- a/LEGO1/mxramstreamcontroller.h +++ b/LEGO1/mxramstreamcontroller.h @@ -14,7 +14,7 @@ class MxRAMStreamController : public MxStreamController { // FUNCTION: LEGO1 0x100b9430 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10102118 + // STRING: LEGO1 0x10102118 return "MxRAMStreamController"; } diff --git a/LEGO1/mxramstreamprovider.h b/LEGO1/mxramstreamprovider.h index 112f6b71..16ed5a4c 100644 --- a/LEGO1/mxramstreamprovider.h +++ b/LEGO1/mxramstreamprovider.h @@ -12,7 +12,7 @@ class MxRAMStreamProvider : public MxStreamProvider { // FUNCTION: LEGO1 0x100d0970 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10102864 + // STRING: LEGO1 0x10102864 return "MxRAMStreamProvider"; } diff --git a/LEGO1/mxregion.h b/LEGO1/mxregion.h index be15a672..c7d7dd90 100644 --- a/LEGO1/mxregion.h +++ b/LEGO1/mxregion.h @@ -13,16 +13,16 @@ class MxRegion : public MxCore { MxRegion(); virtual ~MxRegion() override; - virtual void Reset(); - virtual void VTable0x18(MxRect32& p_rect); - virtual MxBool VTable0x1c(MxRect32& p_rect); - virtual MxBool VTable0x20(); + virtual void Reset(); // vtable+0x14 + virtual void VTable0x18(MxRect32& p_rect); // vtable+0x18 + virtual MxBool VTable0x1c(MxRect32& p_rect); // vtable+0x1c + virtual MxBool VTable0x20(); // vtable+0x20 inline MxRect32& GetRect() { return this->m_rect; } private: - MxRegionList* m_list; - MxRect32 m_rect; + MxRegionList* m_list; // 0x08 + MxRect32 m_rect; // 0x0c }; #endif // MXREGION_H diff --git a/LEGO1/mxsmkpresenter.h b/LEGO1/mxsmkpresenter.h index 95b6a201..4c3913cc 100644 --- a/LEGO1/mxsmkpresenter.h +++ b/LEGO1/mxsmkpresenter.h @@ -15,7 +15,7 @@ class MxSmkPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x100b3730 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e38 + // STRING: LEGO1 0x10101e38 return "MxSmkPresenter"; } diff --git a/LEGO1/mxsoundpresenter.h b/LEGO1/mxsoundpresenter.h index 1c4051ee..d61d8088 100644 --- a/LEGO1/mxsoundpresenter.h +++ b/LEGO1/mxsoundpresenter.h @@ -13,7 +13,7 @@ class MxSoundPresenter : public MxAudioPresenter { // FUNCTION: LEGO1 0x1000d4a0 inline virtual const char* ClassName() const // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07a0 + // STRING: LEGO1 0x100f07a0 return "MxSoundPresenter"; }; diff --git a/LEGO1/mxstillpresenter.h b/LEGO1/mxstillpresenter.h index e28ab84f..828f58b7 100644 --- a/LEGO1/mxstillpresenter.h +++ b/LEGO1/mxstillpresenter.h @@ -15,7 +15,7 @@ class MxStillPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x100435c0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0184 + // STRING: LEGO1 0x100f0184 return "MxStillPresenter"; } diff --git a/LEGO1/mxstreamchunk.cpp b/LEGO1/mxstreamchunk.cpp index 93e76a6c..8dd9ed67 100644 --- a/LEGO1/mxstreamchunk.cpp +++ b/LEGO1/mxstreamchunk.cpp @@ -2,6 +2,7 @@ #include "legoutil.h" #include "mxdsbuffer.h" +#include "mxstreamlist.h" // FUNCTION: LEGO1 0x100c2fe0 MxStreamChunk::~MxStreamChunk() @@ -48,8 +49,51 @@ MxU32 MxStreamChunk::ReadChunkHeader(MxU8* p_chunkData) return headersize; } +// FUNCTION: LEGO1 0x100c30e0 +MxResult MxStreamChunk::SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_append, MxS16 p_obj24val) +{ + for (MxStreamListMxDSSubscriber::iterator it = p_subscriberList.begin(); it != p_subscriberList.end(); it++) { + if ((*it)->GetObjectId() == m_objectId && (*it)->GetUnknown48() == p_obj24val) { + if (m_flags & MxDSChunk::Flag_Bit2 && m_buffer) { + m_buffer->ReleaseRef(this); + m_buffer = NULL; + } + + (*it)->AddChunk(this, p_append); + + return SUCCESS; + } + } + + return FAILURE; +} + // FUNCTION: LEGO1 0x100c3170 void MxStreamChunk::SetBuffer(MxDSBuffer* p_buffer) { m_buffer = p_buffer; } + +// FUNCTION: LEGO1 0x100c3180 +MxU16* MxStreamChunk::IntoFlags(MxU8* p_buffer) +{ + return (MxU16*) (p_buffer + 8); +} + +// FUNCTION: LEGO1 0x100c3190 +MxU32* MxStreamChunk::IntoPlus0xa(MxU8* p_buffer) +{ + return (MxU32*) (p_buffer + 0xa); +} + +// FUNCTION: LEGO1 0x100c31a0 +MxU32* MxStreamChunk::IntoPlus0xe(MxU8* p_buffer) +{ + return (MxU32*) (p_buffer + 0xe); +} + +// FUNCTION: LEGO1 0x100c31b0 +MxU32* MxStreamChunk::IntoPlus0x12(MxU8* p_buffer) +{ + return (MxU32*) (p_buffer + 0x12); +} diff --git a/LEGO1/mxstreamchunk.h b/LEGO1/mxstreamchunk.h index 53cbfc68..5b258603 100644 --- a/LEGO1/mxstreamchunk.h +++ b/LEGO1/mxstreamchunk.h @@ -2,8 +2,10 @@ #define MXSTREAMCHUNK_H #include "mxdschunk.h" +#include "mxdsobject.h" class MxDSBuffer; +class MxStreamListMxDSSubscriber; // VTABLE: LEGO1 0x100dc2a8 // SIZE 0x20 @@ -15,7 +17,7 @@ class MxStreamChunk : public MxDSChunk { // FUNCTION: LEGO1 0x100b1fe0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e5c + // STRING: LEGO1 0x10101e5c return "MxStreamChunk"; } @@ -29,8 +31,14 @@ class MxStreamChunk : public MxDSChunk { MxResult ReadChunk(MxDSBuffer* p_buffer, MxU8* p_chunkData); MxU32 ReadChunkHeader(MxU8* p_chunkData); + MxResult SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_append, MxS16 p_obj24val); void SetBuffer(MxDSBuffer* p_buffer); + static MxU16* IntoFlags(MxU8* p_buffer); + static MxU32* IntoPlus0x12(MxU8* p_buffer); + static MxU32* IntoPlus0xa(MxU8* p_buffer); + static MxU32* IntoPlus0xe(MxU8* p_buffer); + private: MxDSBuffer* m_buffer; // 0x1c }; diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp index c7d30cc4..f351582a 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/mxstreamcontroller.cpp @@ -3,6 +3,7 @@ #include "legoomni.h" #include "legoutil.h" #include "mxautolocker.h" +#include "mxdsmultiaction.h" #include "mxdsstreamingaction.h" #include "mxnextactiondatastart.h" #include "mxstl/stlcompat.h" @@ -71,29 +72,29 @@ MxStreamController::~MxStreamController() MxResult MxStreamController::Open(const char* p_filename) { char sourceName[256]; - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MakeSourceName(sourceName, p_filename); this->m_atom = MxAtomId(sourceName, LookupMode_LowerCase2); return SUCCESS; } -// STUB: LEGO1 0x100c15d0 -void MxStreamController::FUN_100c15d0(MxDSSubscriber* p_subscriber) +// FUNCTION: LEGO1 0x100c15d0 +void MxStreamController::AddSubscriber(MxDSSubscriber* p_subscriber) { - // TODO + m_subscriberList.push_back(p_subscriber); } -// STUB: LEGO1 0x100c1620 -void MxStreamController::FUN_100c1620(MxDSSubscriber* p_subscriber) +// FUNCTION: LEGO1 0x100c1620 +void MxStreamController::RemoveSubscriber(MxDSSubscriber* p_subscriber) { - // TODO + m_subscriberList.remove(p_subscriber); } // FUNCTION: LEGO1 0x100c1690 MxResult MxStreamController::VTable0x20(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result; MxU32 offset = 0; @@ -115,7 +116,7 @@ MxResult MxStreamController::VTable0x20(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1740 MxResult MxStreamController::VTable0x24(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); VTable0x30(p_action); m_action0x60 = m_unk0x54.Find(p_action, TRUE); if (m_action0x60 == NULL) { @@ -200,7 +201,7 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) // FUNCTION: LEGO1 0x100c1c10 MxResult MxStreamController::VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); if (FUN_100c1a00(p_action, p_bufferval) != SUCCESS) { return FAILURE; } @@ -210,11 +211,11 @@ MxResult MxStreamController::VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval) // FUNCTION: LEGO1 0x100c1ce0 MxResult MxStreamController::VTable0x30(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result = FAILURE; MxDSAction* action = m_unk0x3c.Find(p_action, TRUE); if (action != NULL) { - MxNextActionDataStart* data = m_nextActionList.Find(action->GetObjectId(), action->GetUnknown24()); + MxNextActionDataStart* data = m_nextActionList.FindAndErase(action->GetObjectId(), action->GetUnknown24()); delete action; delete data; result = SUCCESS; @@ -225,7 +226,7 @@ MxResult MxStreamController::VTable0x30(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1da0 MxResult MxStreamController::InsertActionToList54(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxDSAction* action = p_action->Clone(); if (action == NULL) { @@ -240,7 +241,7 @@ MxResult MxStreamController::InsertActionToList54(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1e70 MxPresenter* MxStreamController::FUN_100c1e70(MxDSAction& p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxPresenter* result = NULL; if (p_action.GetObjectId() != -1) { MxDSAction* action = m_unk0x3c.Find(&p_action, FALSE); @@ -252,16 +253,59 @@ MxPresenter* MxStreamController::FUN_100c1e70(MxDSAction& p_action) return result; } -// STUB: LEGO1 0x100c1f00 +// FUNCTION: LEGO1 0x100c1f00 MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) { - // TODO - return FAILURE; + MxAutoLocker lock(&m_criticalSection); + + MxU32 objectId = p_action->GetObjectId(); + MxStreamChunk* chunk = new MxStreamChunk; + + if (!chunk) + return FAILURE; + + chunk->SetFlags(MxDSChunk::Flag_Bit3); + chunk->SetObjectId(objectId); + + if (chunk->SendChunk(m_subscriberList, FALSE, p_action->GetUnknown24()) != SUCCESS) + delete chunk; + + if (p_action->IsA("MxDSMultiAction")) { + MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + while (cursor.Next(action)) { + if (FUN_100c1f00(action) != SUCCESS) + return FAILURE; + } + } + + return SUCCESS; } -// STUB: LEGO1 0x100c20d0 +// FUNCTION: LEGO1 0x100c20b0 +MxNextActionDataStart* MxStreamController::FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action) +{ + return m_nextActionList.Find(p_action->GetObjectId(), p_action->GetUnknown24()); +} + +// FUNCTION: LEGO1 0x100c20d0 MxBool MxStreamController::FUN_100c20d0(MxDSObject& p_obj) { - // TODO + if (m_subscriberList.Find(&p_obj)) + return FALSE; + + if (p_obj.IsA("MxDSMultiAction")) { + MxDSActionList* actions = ((MxDSMultiAction&) p_obj).GetActionList(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + while (cursor.Next(action)) { + if (!FUN_100c20d0(*action)) + return FALSE; + } + } + return TRUE; } diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/mxstreamcontroller.h index b8a5bfbd..bbd1eb3d 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/mxstreamcontroller.h @@ -24,7 +24,7 @@ class MxStreamController : public MxCore { // FUNCTION: LEGO1 0x100c0f10 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10102130 + // STRING: LEGO1 0x10102130 return "MxStreamController"; } @@ -43,18 +43,21 @@ class MxStreamController : public MxCore { virtual MxResult VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval); // vtable+0x2c virtual MxResult VTable0x30(MxDSAction* p_action); // vtable+0x30 - void FUN_100c15d0(MxDSSubscriber* p_subscriber); - void FUN_100c1620(MxDSSubscriber* p_subscriber); + void AddSubscriber(MxDSSubscriber* p_subscriber); + void RemoveSubscriber(MxDSSubscriber* p_subscriber); MxResult FUN_100c1800(MxDSAction* p_action, MxU32 p_val); MxResult FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset); MxPresenter* FUN_100c1e70(MxDSAction& p_action); MxResult FUN_100c1f00(MxDSAction* p_action); MxBool FUN_100c20d0(MxDSObject& p_obj); MxResult InsertActionToList54(MxDSAction* p_action); + MxNextActionDataStart* FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action); inline MxAtomId& GetAtom() { return m_atom; }; + inline MxStreamProvider* GetProvider() { return m_provider; }; inline MxStreamListMxDSAction& GetUnk0x3c() { return m_unk0x3c; }; inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; }; + inline MxStreamListMxDSSubscriber& GetSubscriberList() { return m_subscriberList; }; protected: MxCriticalSection m_criticalSection; // 0x8 diff --git a/LEGO1/mxstreamer.cpp b/LEGO1/mxstreamer.cpp index c35a4e8f..1688c1b8 100644 --- a/LEGO1/mxstreamer.cpp +++ b/LEGO1/mxstreamer.cpp @@ -142,7 +142,7 @@ MxResult MxStreamer::FUN_100b99b0(MxDSAction* p_action) return FAILURE; } -// STUB: LEGO1 0x100b99f0 +// FUNCTION: LEGO1 0x100b99f0 MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) { MxDSAction tempAction; @@ -156,8 +156,16 @@ MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) tempAction.SetUnknown24(p_dsAction->GetUnknown24()); } - // TODO: remove action from list - return FAILURE; + MxResult result = FAILURE; + for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { + const char* id = p_dsAction->GetAtomId().GetInternal(); + if (!id || id == (*it)->GetAtom().GetInternal()) { + tempAction.SetAtomId((*it)->GetAtom()); + result = (*it)->VTable0x24(&tempAction); + } + } + + return result; } // FUNCTION: LEGO1 0x100b9b30 diff --git a/LEGO1/mxstreamer.h b/LEGO1/mxstreamer.h index 8017e898..4d3684e9 100644 --- a/LEGO1/mxstreamer.h +++ b/LEGO1/mxstreamer.h @@ -78,7 +78,7 @@ class MxStreamer : public MxCore { // FUNCTION: LEGO1 0x100b9000 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010210c + // STRING: LEGO1 0x1010210c return "MxStreamer"; } diff --git a/LEGO1/mxstreamlist.cpp b/LEGO1/mxstreamlist.cpp index 1fa4dd48..729b0d7b 100644 --- a/LEGO1/mxstreamlist.cpp +++ b/LEGO1/mxstreamlist.cpp @@ -5,6 +5,20 @@ DECOMP_SIZE_ASSERT(MxStreamListMxDSAction, 0xc); DECOMP_SIZE_ASSERT(MxStreamListMxNextActionDataStart, 0xc); DECOMP_SIZE_ASSERT(MxStreamListMxDSSubscriber, 0xc); +// FUNCTION: LEGO1 0x100b8450 +MxDSSubscriber* MxStreamListMxDSSubscriber::Find(MxDSObject* p_object) +{ + for (iterator it = begin(); it != end(); it++) { + if (p_object->GetObjectId() == -1 || p_object->GetObjectId() == (*it)->GetObjectId()) { + if (p_object->GetUnknown24() == -2 || p_object->GetUnknown24() == (*it)->GetUnknown48()) { + return *it; + } + } + } + + return NULL; +} + // FUNCTION: LEGO1 0x100bfa80 MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) { @@ -30,8 +44,19 @@ MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) return found; } -// FUNCTION: LEGO1 0x100c2240 +// FUNCTION: LEGO1 0x100c21e0 MxNextActionDataStart* MxStreamListMxNextActionDataStart::Find(MxU32 p_id, MxS16 p_value) +{ + for (iterator it = begin(); it != end(); it++) { + if (p_id == (*it)->GetObjectId() && p_value == (*it)->GetUnknown24()) + return *it; + } + + return NULL; +} + +// FUNCTION: LEGO1 0x100c2240 +MxNextActionDataStart* MxStreamListMxNextActionDataStart::FindAndErase(MxU32 p_id, MxS16 p_value) { MxNextActionDataStart* match = NULL; diff --git a/LEGO1/mxstreamlist.h b/LEGO1/mxstreamlist.h index 6aa63de0..f9164bfb 100644 --- a/LEGO1/mxstreamlist.h +++ b/LEGO1/mxstreamlist.h @@ -41,10 +41,14 @@ class MxStreamListMxDSAction : public MxStreamList { // SIZE 0xc class MxStreamListMxNextActionDataStart : public MxStreamList { public: - MxNextActionDataStart* Find(MxU32, MxS16); + MxNextActionDataStart* Find(MxU32 p_id, MxS16 p_value); + MxNextActionDataStart* FindAndErase(MxU32 p_id, MxS16 p_value); }; // SIZE 0xc -class MxStreamListMxDSSubscriber : public MxStreamList {}; +class MxStreamListMxDSSubscriber : public MxStreamList { +public: + MxDSSubscriber* Find(MxDSObject* p_object); +}; #endif // MXSTREAMLIST_H diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index d25ecb2b..4c1bab5e 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -23,7 +23,7 @@ class MxVideoPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000c820 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0760 + // STRING: LEGO1 0x100f0760 return "MxVideoPresenter"; } diff --git a/LEGO1/mxwavepresenter.h b/LEGO1/mxwavepresenter.h index 4210a44e..cd09d486 100644 --- a/LEGO1/mxwavepresenter.h +++ b/LEGO1/mxwavepresenter.h @@ -16,7 +16,7 @@ class MxWavePresenter : public MxSoundPresenter { // FUNCTION: LEGO1 0x1000d6c0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07b4 + // STRING: LEGO1 0x100f07b4 return "MxWavePresenter"; } diff --git a/LEGO1/pizza.h b/LEGO1/pizza.h index f1ac9f45..11bf6814 100644 --- a/LEGO1/pizza.h +++ b/LEGO1/pizza.h @@ -20,7 +20,7 @@ class Pizza : public IsleActor { // FUNCTION: LEGO1 0x10037f90 inline const char* ClassName() const // vtable+0c { - // GLOBAL: LEGO1 0x100f038c + // STRING: LEGO1 0x100f038c return "Pizza"; } diff --git a/LEGO1/pizzamissionstate.h b/LEGO1/pizzamissionstate.h index a9231c81..85b8e4bb 100644 --- a/LEGO1/pizzamissionstate.h +++ b/LEGO1/pizzamissionstate.h @@ -18,7 +18,7 @@ class PizzaMissionState : public LegoState { // FUNCTION: LEGO1 0x10039290 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00d4 + // STRING: LEGO1 0x100f00d4 return "PizzaMissionState"; } diff --git a/LEGO1/pizzeria.h b/LEGO1/pizzeria.h index 65a3b195..0196d616 100644 --- a/LEGO1/pizzeria.h +++ b/LEGO1/pizzeria.h @@ -1,5 +1,5 @@ -#ifndef PIZZERIASTATE_H -#define PIZZERIASTATE_H +#ifndef PIZZERIA_H +#define PIZZERIA_H #include "isleactor.h" @@ -10,7 +10,7 @@ class Pizzeria : public IsleActor { // FUNCTION: LEGO1 0x1000e780 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0380 + // STRING: LEGO1 0x100f0380 return "Pizzeria"; } @@ -21,4 +21,4 @@ class Pizzeria : public IsleActor { } }; -#endif // PIZZERIASTATE_H +#endif // PIZZERIA_H diff --git a/LEGO1/pizzeriastate.h b/LEGO1/pizzeriastate.h index 53f4ddd5..c27fcef0 100644 --- a/LEGO1/pizzeriastate.h +++ b/LEGO1/pizzeriastate.h @@ -12,7 +12,7 @@ class PizzeriaState : public LegoState { // FUNCTION: LEGO1 0x10017c20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0370 + // STRING: LEGO1 0x100f0370 return "PizzeriaState"; } diff --git a/LEGO1/police.h b/LEGO1/police.h index 0da58828..829c7e66 100644 --- a/LEGO1/police.h +++ b/LEGO1/police.h @@ -16,7 +16,7 @@ class Police : public LegoWorld { // FUNCTION: LEGO1 0x1005e1e0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0450 + // STRING: LEGO1 0x100f0450 return "Police"; } diff --git a/LEGO1/policeentity.h b/LEGO1/policeentity.h index e2314dd3..735cf0bc 100644 --- a/LEGO1/policeentity.h +++ b/LEGO1/policeentity.h @@ -10,7 +10,7 @@ class PoliceEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000ed60 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0328 + // STRING: LEGO1 0x100f0328 return "PoliceEntity"; } diff --git a/LEGO1/policestate.h b/LEGO1/policestate.h index b3a732c9..2638a393 100644 --- a/LEGO1/policestate.h +++ b/LEGO1/policestate.h @@ -12,7 +12,7 @@ class PoliceState : public LegoState { // FUNCTION: LEGO1 0x1005e860 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0444 + // STRING: LEGO1 0x100f0444 return "PoliceState"; } diff --git a/LEGO1/racecar.h b/LEGO1/racecar.h index b0db77c5..b4a210e6 100644 --- a/LEGO1/racecar.h +++ b/LEGO1/racecar.h @@ -14,7 +14,7 @@ class RaceCar : public IslePathActor { // FUNCTION: LEGO1 0x10028270 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03e0 + // STRING: LEGO1 0x100f03e0 return "RaceCar"; } diff --git a/LEGO1/racestate.h b/LEGO1/racestate.h index 63a775d4..ef3cfa63 100644 --- a/LEGO1/racestate.h +++ b/LEGO1/racestate.h @@ -20,7 +20,7 @@ class RaceState : public LegoState { // FUNCTION: LEGO1 0x10016010 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07d0 + // STRING: LEGO1 0x100f07d0 return "RaceState"; } diff --git a/LEGO1/radio.h b/LEGO1/radio.h index 8d454483..54aef25b 100644 --- a/LEGO1/radio.h +++ b/LEGO1/radio.h @@ -13,7 +13,7 @@ class Radio : public MxCore { // FUNCTION: LEGO1 0x1002c8e0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f328c + // STRING: LEGO1 0x100f328c return "Radio"; } diff --git a/LEGO1/radiostate.h b/LEGO1/radiostate.h index dc2c8b8f..a5ea6035 100644 --- a/LEGO1/radiostate.h +++ b/LEGO1/radiostate.h @@ -12,7 +12,7 @@ class RadioState : public LegoState { // FUNCTION: LEGO1 0x1002cf60 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04f8 + // STRING: LEGO1 0x100f04f8 return "RadioState"; } diff --git a/LEGO1/realtime/matrix.cpp b/LEGO1/realtime/matrix.cpp index 852e14d0..61f7b1a9 100644 --- a/LEGO1/realtime/matrix.cpp +++ b/LEGO1/realtime/matrix.cpp @@ -138,7 +138,7 @@ void Matrix4Impl::ToQuaternion(Vector4Impl* p_outQuat) return; } - // GLOBAL: LEGO1 0x100d4090 + // ~GLOBAL: LEGO1 0x100d4090 static int rotateIndex[] = {1, 2, 0}; // Largest element along the trace diff --git a/LEGO1/registrationbook.h b/LEGO1/registrationbook.h index 4f19a8dc..3ae904c9 100644 --- a/LEGO1/registrationbook.h +++ b/LEGO1/registrationbook.h @@ -15,7 +15,7 @@ class RegistrationBook : public LegoWorld { // FUNCTION: LEGO1 0x10076e10 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04c8 + // STRING: LEGO1 0x100f04c8 return "RegistrationBook"; } diff --git a/LEGO1/score.h b/LEGO1/score.h index 89d9608d..c927863f 100644 --- a/LEGO1/score.h +++ b/LEGO1/score.h @@ -18,7 +18,7 @@ class Score : public LegoWorld { // FUNCTION: LEGO1 0x100010c0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0050 + // STRING: LEGO1 0x100f0050 return "Score"; } diff --git a/LEGO1/scorestate.h b/LEGO1/scorestate.h index 2797ad34..21be3493 100644 --- a/LEGO1/scorestate.h +++ b/LEGO1/scorestate.h @@ -10,7 +10,7 @@ class ScoreState : public LegoState { // FUNCTION: LEGO1 0x1000de40 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0084 + // STRING: LEGO1 0x100f0084 return "ScoreState"; }; diff --git a/LEGO1/skateboard.h b/LEGO1/skateboard.h index 671c7f86..171705c4 100644 --- a/LEGO1/skateboard.h +++ b/LEGO1/skateboard.h @@ -13,7 +13,7 @@ class SkateBoard : public IslePathActor { // FUNCTION: LEGO1 0x1000fdd0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f041c + // STRING: LEGO1 0x100f041c return "SkateBoard"; } diff --git a/LEGO1/tgl/d3drm/renderer.cpp b/LEGO1/tgl/d3drm/renderer.cpp index d098f7ff..bd9ed873 100644 --- a/LEGO1/tgl/d3drm/renderer.cpp +++ b/LEGO1/tgl/d3drm/renderer.cpp @@ -61,7 +61,7 @@ Device* RendererImpl::CreateDevice(const DeviceDirect3DCreateData& data) } // GLOBAL: LEGO1 0x10101040 -static int gSetBufferCount = 1; +static int g_SetBufferCount = 1; // FUNCTION: LEGO1 0x100a1900 Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data) @@ -73,7 +73,7 @@ Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data) data.m_pBackBuffer, &device->m_data ); - if (SUCCEEDED(result) && data.m_pBackBuffer && gSetBufferCount) { + if (SUCCEEDED(result) && data.m_pBackBuffer && g_SetBufferCount) { device->m_data->SetBufferCount(2); } if (!SUCCEEDED(result)) { diff --git a/LEGO1/towtrack.h b/LEGO1/towtrack.h index 2243f9a2..1cc7e6af 100644 --- a/LEGO1/towtrack.h +++ b/LEGO1/towtrack.h @@ -13,7 +13,7 @@ class TowTrack : public IslePathActor { // FUNCTION: LEGO1 0x1004c7c0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03b8 + // STRING: LEGO1 0x100f03b8 return "TowTrack"; } diff --git a/LEGO1/towtrackmissionstate.h b/LEGO1/towtrackmissionstate.h index 7537cb94..9dc7c587 100644 --- a/LEGO1/towtrackmissionstate.h +++ b/LEGO1/towtrackmissionstate.h @@ -12,7 +12,7 @@ class TowTrackMissionState : public LegoState { // FUNCTION: LEGO1 0x1004dfa0 inline virtual const char* ClassName() const // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00bc + // STRING: LEGO1 0x100f00bc return "TowTrackMissionState"; } diff --git a/tools/isledecomp/isledecomp/parser/error.py b/tools/isledecomp/isledecomp/parser/error.py index 638a806e..eb1aa7b8 100644 --- a/tools/isledecomp/isledecomp/parser/error.py +++ b/tools/isledecomp/isledecomp/parser/error.py @@ -39,6 +39,14 @@ class ParserError(Enum): # WARN: We found a marker to be referenced by name outside of a header file. BYNAME_FUNCTION_IN_CPP = 109 + # WARN: A GLOBAL marker appeared over a variable without the g_ prefix + GLOBAL_MISSING_PREFIX = 110 + + # WARN: GLOBAL marker points at something other than variable declaration. + # We can't match global variables based on position, but the goal here is + # to ignore things like string literal that are not variables. + GLOBAL_NOT_VARIABLE = 111 + # This code or higher is an error, not a warning DECOMP_ERROR_START = 200 @@ -50,13 +58,18 @@ class ParserError(Enum): # For example, a GLOBAL cannot follow FUNCTION/STUB INCOMPATIBLE_MARKER = 201 - # ERROR: The line following a synthetic marker was not a comment - BAD_SYNTHETIC = 202 + # ERROR: The line following an explicit by-name marker was not a comment + # We assume a syntax error here rather than try to use the next line + BAD_NAMEREF = 202 # ERROR: This function offset comes before the previous offset from the same module # This hopefully gives some hint about which functions need to be rearranged. FUNCTION_OUT_OF_ORDER = 203 + # ERROR: The line following an explicit by-name marker that does _not_ expect + # a comment -- i.e. VTABLE or GLOBAL -- could not extract the name + NO_SUITABLE_NAME = 204 + @dataclass class ParserAlert: diff --git a/tools/isledecomp/isledecomp/parser/marker.py b/tools/isledecomp/isledecomp/parser/marker.py new file mode 100644 index 00000000..d2e181dd --- /dev/null +++ b/tools/isledecomp/isledecomp/parser/marker.py @@ -0,0 +1,103 @@ +import re +from typing import Optional +from enum import Enum + + +class MarkerType(Enum): + UNKNOWN = -100 + FUNCTION = 1 + STUB = 2 + SYNTHETIC = 3 + TEMPLATE = 4 + GLOBAL = 5 + VTABLE = 6 + STRING = 7 + LIBRARY = 8 + + +markerRegex = re.compile( + r"\s*//\s*(?P\w+):\s*(?P\w+)\s+(?P0x[a-f0-9]+)", + flags=re.I, +) + + +markerExactRegex = re.compile( + r"\s*// (?P[A-Z]+): (?P[A-Z0-9]+) (?P0x[a-f0-9]+)$" +) + + +class DecompMarker: + def __init__(self, marker_type: str, module: str, offset: int) -> None: + try: + self._type = MarkerType[marker_type.upper()] + except KeyError: + self._type = MarkerType.UNKNOWN + + # Convert to upper here. A lot of other analysis depends on this name + # being consistent and predictable. If the name is _not_ capitalized + # we will emit a syntax error. + self._module: str = module.upper() + self._offset: int = offset + + @property + def type(self) -> MarkerType: + return self._type + + @property + def module(self) -> str: + return self._module + + @property + def offset(self) -> int: + return self._offset + + def is_regular_function(self) -> bool: + """Regular function, meaning: not an explicit byname lookup. FUNCTION + markers can be _implicit_ byname. + FUNCTION and STUB markers are (currently) the only heterogenous marker types that + can be lumped together, although the reasons for doing so are a little vague.""" + return self._type in (MarkerType.FUNCTION, MarkerType.STUB) + + def is_explicit_byname(self) -> bool: + return self._type in ( + MarkerType.SYNTHETIC, + MarkerType.TEMPLATE, + MarkerType.LIBRARY, + ) + + def is_variable(self) -> bool: + return self._type == MarkerType.GLOBAL + + def is_synthetic(self) -> bool: + return self._type == MarkerType.SYNTHETIC + + def is_template(self) -> bool: + return self._type == MarkerType.TEMPLATE + + def is_vtable(self) -> bool: + return self._type == MarkerType.VTABLE + + def is_library(self) -> bool: + return self._type == MarkerType.LIBRARY + + def is_string(self) -> bool: + return self._type == MarkerType.STRING + + def allowed_in_func(self) -> bool: + return self._type in (MarkerType.GLOBAL, MarkerType.STRING) + + +def match_marker(line: str) -> Optional[DecompMarker]: + match = markerRegex.match(line) + if match is None: + return None + + return DecompMarker( + marker_type=match.group("type"), + module=match.group("module"), + offset=int(match.group("offset"), 16), + ) + + +def is_marker_exact(line: str) -> bool: + return markerExactRegex.match(line) is not None diff --git a/tools/isledecomp/isledecomp/parser/node.py b/tools/isledecomp/isledecomp/parser/node.py index 721a24b9..b6561fd6 100644 --- a/tools/isledecomp/isledecomp/parser/node.py +++ b/tools/isledecomp/isledecomp/parser/node.py @@ -1,35 +1,57 @@ +from typing import Optional from dataclasses import dataclass +from .marker import MarkerType @dataclass -class ParserNode: +class ParserSymbol: + """Exported decomp marker with all information (except the code filename) required to + cross-reference with cvdump data.""" + + type: MarkerType line_number: int - - -@dataclass -class ParserSymbol(ParserNode): module: str offset: int + name: str + + # The parser doesn't (currently) know about the code filename, but if you + # wanted to set it here after the fact, here's the spot. + filename: Optional[str] = None + + def should_skip(self) -> bool: + """The default is to compare any symbols we have""" + return False + + def is_nameref(self) -> bool: + """All symbols default to name lookup""" + return True @dataclass class ParserFunction(ParserSymbol): - name: str + # We are able to detect the closing line of a function with some reliability. + # This isn't used for anything right now, but perhaps later it will be. + end_line: Optional[int] = None + + # All marker types are referenced by name except FUNCTION/STUB. These can also be + # referenced by name, but only if this flag is true. lookup_by_name: bool = False - is_stub: bool = False - is_synthetic: bool = False - is_template: bool = False - end_line: int = -1 + + def should_skip(self) -> bool: + return self.type == MarkerType.STUB + + def is_nameref(self) -> bool: + return ( + self.type in (MarkerType.SYNTHETIC, MarkerType.TEMPLATE, MarkerType.LIBRARY) + or self.lookup_by_name + ) @dataclass class ParserVariable(ParserSymbol): - name: str - size: int = -1 is_static: bool = False @dataclass class ParserVtable(ParserSymbol): - class_name: str - num_entries: int = -1 + pass diff --git a/tools/isledecomp/isledecomp/parser/parser.py b/tools/isledecomp/isledecomp/parser/parser.py index 336d4b0c..f9485e65 100644 --- a/tools/isledecomp/isledecomp/parser/parser.py +++ b/tools/isledecomp/isledecomp/parser/parser.py @@ -3,15 +3,19 @@ from typing import List, Iterable, Iterator from enum import Enum from .util import ( - DecompMarker, is_blank_or_comment, - match_marker, - is_marker_exact, get_class_name, + get_variable_name, get_synthetic_name, remove_trailing_comment, ) +from .marker import ( + DecompMarker, + match_marker, + is_marker_exact, +) from .node import ( + ParserSymbol, ParserFunction, ParserVariable, ParserVtable, @@ -28,44 +32,23 @@ class ReaderState(Enum): IN_GLOBAL = 5 IN_FUNC_GLOBAL = 6 IN_VTABLE = 7 + IN_SYNTHETIC = 8 + IN_LIBRARY = 9 DONE = 100 -def marker_is_stub(marker: DecompMarker) -> bool: - return marker.type.upper() == "STUB" - - -def marker_is_variable(marker: DecompMarker) -> bool: - return marker.type.upper() == "GLOBAL" - - -def marker_is_synthetic(marker: DecompMarker) -> bool: - return marker.type.upper() in ("SYNTHETIC", "TEMPLATE") - - -def marker_is_template(marker: DecompMarker) -> bool: - return marker.type.upper() == "TEMPLATE" - - -def marker_is_function(marker: DecompMarker) -> bool: - return marker.type.upper() in ("FUNCTION", "STUB") - - -def marker_is_vtable(marker: DecompMarker) -> bool: - return marker.type.upper() == "VTABLE" - - class MarkerDict: def __init__(self) -> None: self.markers: dict = {} def insert(self, marker: DecompMarker) -> bool: """Return True if this insert would overwrite""" - module = marker.module.upper() + module = marker.module if module in self.markers: return True - self.markers[module] = (marker.type, marker.offset) + # TODO: type converted back to string version here instead of using enum + self.markers[module] = (marker.type.name, marker.offset) return False def iter(self) -> Iterator[DecompMarker]: @@ -82,9 +65,7 @@ class DecompParser: # but not right now def __init__(self) -> None: # The lists to be populated as we parse - self.functions: List[ParserFunction] = [] - self.vtables: List[ParserVtable] = [] - self.variables: List[ParserVariable] = [] + self._symbols: List[ParserSymbol] = [] self.alerts: List[ParserAlert] = [] self.line_number: int = 0 @@ -113,9 +94,7 @@ def __init__(self) -> None: self.function_sig: str = "" def reset(self): - self.functions = [] - self.vtables = [] - self.variables = [] + self._symbols = [] self.alerts = [] self.line_number = 0 @@ -131,6 +110,18 @@ def reset(self): self.function_start = 0 self.function_sig = "" + @property + def functions(self) -> List[ParserSymbol]: + return [s for s in self._symbols if isinstance(s, ParserFunction)] + + @property + def vtables(self) -> List[ParserSymbol]: + return [s for s in self._symbols if isinstance(s, ParserVtable)] + + @property + def variables(self) -> List[ParserSymbol]: + return [s for s in self._symbols if isinstance(s, ParserVariable)] + def _recover(self): """We hit a syntax error and need to reset temp structures""" self.state = ReaderState.SEARCH @@ -159,10 +150,17 @@ def _function_marker(self, marker: DecompMarker): self._syntax_warning(ParserError.DUPLICATE_MODULE) self.state = ReaderState.WANT_SIG - def _synthetic_marker(self, marker: DecompMarker): + def _nameref_marker(self, marker: DecompMarker): + """Functions explicitly referenced by name are set here""" if self.fun_markers.insert(marker): self._syntax_warning(ParserError.DUPLICATE_MODULE) - self.state = ReaderState.IN_TEMPLATE + + if marker.is_template(): + self.state = ReaderState.IN_TEMPLATE + elif marker.is_synthetic(): + self.state = ReaderState.IN_SYNTHETIC + else: + self.state = ReaderState.IN_LIBRARY def _function_done(self, lookup_by_name: bool = False, unexpected: bool = False): end_line = self.line_number @@ -173,16 +171,14 @@ def _function_done(self, lookup_by_name: bool = False, unexpected: bool = False) end_line -= 1 for marker in self.fun_markers.iter(): - self.functions.append( + self._symbols.append( ParserFunction( + type=marker.type, line_number=self.function_start, module=marker.module, offset=marker.offset, - lookup_by_name=lookup_by_name, - is_stub=marker_is_stub(marker), - is_synthetic=marker_is_synthetic(marker), - is_template=marker_is_template(marker), name=self.function_sig, + lookup_by_name=lookup_by_name, end_line=end_line, ) ) @@ -202,12 +198,13 @@ def _vtable_done(self, class_name: str = None): class_name = self.last_line.strip() for marker in self.tbl_markers.iter(): - self.vtables.append( + self._symbols.append( ParserVtable( + type=marker.type, line_number=self.line_number, module=marker.module, offset=marker.offset, - class_name=class_name, + name=class_name, ) ) @@ -223,14 +220,19 @@ def _variable_marker(self, marker: DecompMarker): else: self.state = ReaderState.IN_GLOBAL - def _variable_done(self): + def _variable_done(self, name: str): + if not name.startswith("g_"): + self._syntax_warning(ParserError.GLOBAL_MISSING_PREFIX) + for marker in self.var_markers.iter(): - self.variables.append( + self._symbols.append( ParserVariable( + type=marker.type, line_number=self.line_number, module=marker.module, offset=marker.offset, - name=self.last_line.strip(), + name=name, + is_static=self.state == ReaderState.IN_FUNC_GLOBAL, ) ) @@ -246,12 +248,23 @@ def _handle_marker(self, marker: DecompMarker): self._syntax_error(ParserError.UNEXPECTED_MARKER) return + # If we are inside a function, the only markers we accept are: + # GLOBAL, indicating a static variable + # STRING, indicating a literal string. + # Otherwise we assume that the parser missed the end of the function + # and we have moved on to something else. + # This is unlikely to occur with well-formed code, but + # we can recover easily by just ending the function here. + if self.state == ReaderState.IN_FUNC and not marker.allowed_in_func(): + self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) + self._function_done(unexpected=True) + # TODO: How uncertain are we of detecting the end of a function # in a clang-formatted file? For now we assume we have missed the # end if we detect a non-GLOBAL marker while state is IN_FUNC. # Maybe these cases should be syntax errors instead - if marker_is_function(marker): + if marker.is_regular_function(): if self.state in ( ReaderState.SEARCH, ReaderState.WANT_SIG, @@ -259,29 +272,41 @@ def _handle_marker(self, marker: DecompMarker): # We will allow multiple offsets if we have just begun # the code block, but not after we hit the curly brace. self._function_marker(marker) - elif self.state == ReaderState.IN_FUNC: - # We hit another offset unexpectedly. - # We can recover easily by just ending the function here. - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(unexpected=True) - - # Start the next function right after so we can - # read the next line. - self._function_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_synthetic(marker): + elif marker.is_template(): if self.state in (ReaderState.SEARCH, ReaderState.IN_TEMPLATE): - self._synthetic_marker(marker) - elif self.state == ReaderState.IN_FUNC: - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(lookup_by_name=True, unexpected=True) - self._synthetic_marker(marker) + self._nameref_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_variable(marker): + elif marker.is_synthetic(): + if self.state in (ReaderState.SEARCH, ReaderState.IN_SYNTHETIC): + self._nameref_marker(marker) + else: + self._syntax_error(ParserError.INCOMPATIBLE_MARKER) + + elif marker.is_library(): + if self.state in (ReaderState.SEARCH, ReaderState.IN_LIBRARY): + self._nameref_marker(marker) + else: + self._syntax_error(ParserError.INCOMPATIBLE_MARKER) + + elif marker.is_string(): + # TODO: We are ignoring string markers for the moment. + # We already have a lot of them in the codebase, though, so we'll + # hang onto them for now in case we can use them later. + # To match up string constants, the strategy will be: + # 1. Use cvdump to find all string constants in the recomp + # 2. In the original binary, look at relocated vaddrs from .rdata + # 3. Try to match up string data from #1 with locations in #2 + + # Throw the syntax error we would throw if we were parsing these + if self.state not in (ReaderState.SEARCH, ReaderState.IN_FUNC): + self._syntax_error(ParserError.INCOMPATIBLE_MARKER) + + elif marker.is_variable(): if self.state in ( ReaderState.SEARCH, ReaderState.IN_GLOBAL, @@ -292,13 +317,9 @@ def _handle_marker(self, marker: DecompMarker): else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_vtable(marker): + elif marker.is_vtable(): if self.state in (ReaderState.SEARCH, ReaderState.IN_VTABLE): self._vtable_marker(marker) - elif self.state == ReaderState.IN_FUNC: - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(unexpected=True) - self._vtable_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) @@ -322,12 +343,16 @@ def read_line(self, line: str): return line_strip = line.strip() - if self.state == ReaderState.IN_TEMPLATE: - # TEMPLATE functions are a special case. The signature is - # given on the next line (in a // comment) + if self.state in ( + ReaderState.IN_SYNTHETIC, + ReaderState.IN_TEMPLATE, + ReaderState.IN_LIBRARY, + ): + # Explicit nameref functions provide the function name + # on the next line (in a // comment) name = get_synthetic_name(line) if name is None: - self._syntax_error(ParserError.BAD_SYNTHETIC) + self._syntax_error(ParserError.BAD_NAMEREF) else: self.function_sig = name self._function_starts_here() @@ -384,8 +409,28 @@ def read_line(self, line: str): self._function_done() elif self.state in (ReaderState.IN_GLOBAL, ReaderState.IN_FUNC_GLOBAL): - if not is_blank_or_comment(line): - self._variable_done() + # TODO: Known problem that an error here will cause us to abandon a + # function we have already parsed if state == IN_FUNC_GLOBAL. + # However, we are not tolerant of _any_ syntax problems in our + # CI actions, so the solution is to just fix the invalid marker. + if is_blank_or_comment(line): + self._syntax_error(ParserError.NO_SUITABLE_NAME) + return + + # We don't have a foolproof mechanism to tell what is and is not a variable. + # If the GLOBAL is being declared on a `return` statement, though, this is + # not correct. It is either a string literal (which will be handled differently) + # or it is not the variable declaration, which is incorrect decomp syntax. + if line.strip().startswith("return"): + self._syntax_error(ParserError.GLOBAL_NOT_VARIABLE) + return + + name = get_variable_name(line) + if name is None: + self._syntax_error(ParserError.NO_SUITABLE_NAME) + return + + self._variable_done(name) elif self.state == ReaderState.IN_VTABLE: vtable_class = get_class_name(line) diff --git a/tools/isledecomp/isledecomp/parser/util.py b/tools/isledecomp/isledecomp/parser/util.py index 99ab1c56..a106d841 100644 --- a/tools/isledecomp/isledecomp/parser/util.py +++ b/tools/isledecomp/isledecomp/parser/util.py @@ -1,17 +1,6 @@ # C++ Parser utility functions and data structures -from __future__ import annotations # python <3.10 compatibility import re -from collections import namedtuple - -DecompMarker = namedtuple("DecompMarker", ["type", "module", "offset"]) - - -markerRegex = re.compile( - r"\s*//\s*(\w+):\s*(\w+)\s+(0x[a-f0-9]+)", - flags=re.I, -) - -markerExactRegex = re.compile(r"\s*// ([A-Z]+): ([A-Z0-9]+) (0x[a-f0-9]+)$") +from typing import Optional # The goal here is to just read whatever is on the next line, so some # flexibility in the formatting seems OK @@ -23,7 +12,7 @@ trailingCommentRegex = re.compile(r"(\s*(?://|/\*).*)$") -def get_synthetic_name(line: str) -> str | None: +def get_synthetic_name(line: str) -> Optional[str]: """Synthetic names appear on a single line comment on the line after the marker. If that's not what we have, return None""" template_match = templateCommentRegex.match(line) @@ -51,20 +40,6 @@ def is_blank_or_comment(line: str) -> bool: ) -def match_marker(line: str) -> DecompMarker | None: - match = markerRegex.match(line) - if match is None: - return None - - return DecompMarker( - type=match.group(1), module=match.group(2), offset=int(match.group(3), 16) - ) - - -def is_marker_exact(line: str) -> bool: - return markerExactRegex.match(line) is not None - - template_class_decl_regex = re.compile( r"\s*(?:\/\/)?\s*(?:class|struct) (\w+)<([\w]+)\s*(\*+)?\s*>" ) @@ -73,7 +48,7 @@ def is_marker_exact(line: str) -> bool: class_decl_regex = re.compile(r"\s*(?:\/\/)?\s*(?:class|struct) (\w+)") -def get_class_name(line: str) -> str | None: +def get_class_name(line: str) -> Optional[str]: """For VTABLE markers, extract the class name from the code line or comment where it appears.""" @@ -93,3 +68,21 @@ def get_class_name(line: str) -> str | None: return match.group(1) return None + + +global_regex = re.compile(r"(?Pg_\w+)") +less_strict_global_regex = re.compile(r"(?P\w+)(?:\)\(|\[.*|\s*=.*|;)") + + +def get_variable_name(line: str) -> Optional[str]: + """Grab the name of the variable annotated with the GLOBAL marker. + Correct syntax would have the variable start with the prefix "g_" + but we will try to match regardless.""" + + if (match := global_regex.search(line)) is not None: + return match.group("name") + + if (match := less_strict_global_regex.search(line)) is not None: + return match.group("name") + + return None diff --git a/tools/isledecomp/tests/test_parser.py b/tools/isledecomp/tests/test_parser.py index c31602f1..853e773d 100644 --- a/tools/isledecomp/tests/test_parser.py +++ b/tools/isledecomp/tests/test_parser.py @@ -115,7 +115,7 @@ def test_different_markers_same_module(parser): # Use first marker declaration, don't replace assert len(parser.functions) == 1 - assert parser.functions[0].is_stub is False + assert parser.functions[0].should_skip() is False # Should alert to this assert len(parser.alerts) == 1 @@ -193,7 +193,7 @@ def test_multiple_vtables(parser): ) assert len(parser.alerts) == 0 assert len(parser.vtables) == 2 - assert parser.vtables[0].class_name == "MxString" + assert parser.vtables[0].name == "MxString" def test_multiple_vtables_same_module(parser): @@ -247,7 +247,7 @@ def test_synthetic_no_comment(parser): ) assert len(parser.functions) == 0 assert len(parser.alerts) == 1 - assert parser.alerts[0].code == ParserError.BAD_SYNTHETIC + assert parser.alerts[0].code == ParserError.BAD_NAMEREF assert parser.state == ReaderState.SEARCH @@ -375,3 +375,70 @@ def test_unexpected_eof(parser): assert len(parser.functions) == 1 assert len(parser.alerts) == 1 assert parser.alerts[0].code == ParserError.UNEXPECTED_END_OF_FILE + + +def test_global_variable_prefix(parser): + """Global and static variables should have the g_ prefix.""" + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + 'const char* g_msg = "hello";', + ] + ) + assert len(parser.variables) == 1 + assert len(parser.alerts) == 0 + + parser.read_lines( + [ + "// GLOBAL: TEXT 0x5555", + "int test = 5;", + ] + ) + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.GLOBAL_MISSING_PREFIX + # In spite of that, we should still grab the variable name. + assert parser.variables[1].name == "test" + + +def test_global_nomatch(parser): + """We do our best to grab the variable name, even without the g_ prefix + but this (by design) will not match everything.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "FunctionCall();", + ] + ) + assert len(parser.variables) == 0 + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.NO_SUITABLE_NAME + + +def test_static_variable(parser): + """We can detect whether a variable is a static function variable + based on the parser's state when we detect it. + Checking for the word `static` alone is not a good test. + Static class variables are filed as S_GDATA32, same as regular globals. + Only function statics are filed as S_LDATA32.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "int g_test = 1234;", + ] + ) + assert len(parser.variables) == 1 + assert parser.variables[0].is_static is False + + parser.read_lines( + [ + "// FUNCTION: TEST 0x5555", + "void test_function() {", + "// GLOBAL: TEST 0x8888", + "int g_internal = 0;", + "}", + ] + ) + assert len(parser.variables) == 2 + assert parser.variables[1].is_static is True diff --git a/tools/isledecomp/tests/test_parser_statechange.py b/tools/isledecomp/tests/test_parser_statechange.py index 8d18d547..cb54cf0a 100644 --- a/tools/isledecomp/tests/test_parser_statechange.py +++ b/tools/isledecomp/tests/test_parser_statechange.py @@ -11,9 +11,11 @@ (_rs.SEARCH, "FUNCTION", _rs.WANT_SIG, None), (_rs.SEARCH, "GLOBAL", _rs.IN_GLOBAL, None), (_rs.SEARCH, "STUB", _rs.WANT_SIG, None), - (_rs.SEARCH, "SYNTHETIC", _rs.IN_TEMPLATE, None), + (_rs.SEARCH, "SYNTHETIC", _rs.IN_SYNTHETIC, None), (_rs.SEARCH, "TEMPLATE", _rs.IN_TEMPLATE, None), (_rs.SEARCH, "VTABLE", _rs.IN_VTABLE, None), + (_rs.SEARCH, "LIBRARY", _rs.IN_LIBRARY, None), + (_rs.SEARCH, "STRING", _rs.SEARCH, None), (_rs.WANT_SIG, "FUNCTION", _rs.WANT_SIG, None), (_rs.WANT_SIG, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -21,20 +23,26 @@ (_rs.WANT_SIG, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_SIG, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_SIG, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.WANT_SIG, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.WANT_SIG, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC, "FUNCTION", _rs.WANT_SIG, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "GLOBAL", _rs.IN_FUNC_GLOBAL, None), (_rs.IN_FUNC, "STUB", _rs.WANT_SIG, _pe.MISSED_END_OF_FUNCTION), - (_rs.IN_FUNC, "SYNTHETIC", _rs.IN_TEMPLATE, _pe.MISSED_END_OF_FUNCTION), + (_rs.IN_FUNC, "SYNTHETIC", _rs.IN_SYNTHETIC, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "TEMPLATE", _rs.IN_TEMPLATE, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "VTABLE", _rs.IN_VTABLE, _pe.MISSED_END_OF_FUNCTION), + (_rs.IN_FUNC, "LIBRARY", _rs.IN_LIBRARY, _pe.MISSED_END_OF_FUNCTION), + (_rs.IN_FUNC, "STRING", _rs.IN_FUNC, None), (_rs.IN_TEMPLATE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), - (_rs.IN_TEMPLATE, "SYNTHETIC", _rs.IN_TEMPLATE, None), + (_rs.IN_TEMPLATE, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "TEMPLATE", _rs.IN_TEMPLATE, None), (_rs.IN_TEMPLATE, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_TEMPLATE, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_TEMPLATE, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_CURLY, "FUNCTION", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "GLOBAL", _rs.SEARCH, _pe.UNEXPECTED_MARKER), @@ -42,6 +50,8 @@ (_rs.WANT_CURLY, "SYNTHETIC", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "TEMPLATE", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "VTABLE", _rs.SEARCH, _pe.UNEXPECTED_MARKER), + (_rs.WANT_CURLY, "LIBRARY", _rs.SEARCH, _pe.UNEXPECTED_MARKER), + (_rs.WANT_CURLY, "STRING", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.IN_GLOBAL, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "GLOBAL", _rs.IN_GLOBAL, None), @@ -49,6 +59,8 @@ (_rs.IN_GLOBAL, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_GLOBAL, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_GLOBAL, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "GLOBAL", _rs.IN_FUNC_GLOBAL, None), @@ -56,6 +68,8 @@ (_rs.IN_FUNC_GLOBAL, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_FUNC_GLOBAL, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_FUNC_GLOBAL, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -63,6 +77,26 @@ (_rs.IN_VTABLE, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "VTABLE", _rs.IN_VTABLE, None), + (_rs.IN_VTABLE, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_VTABLE, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + + (_rs.IN_SYNTHETIC, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "SYNTHETIC", _rs.IN_SYNTHETIC, None), + (_rs.IN_SYNTHETIC, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + + (_rs.IN_LIBRARY, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "LIBRARY", _rs.IN_LIBRARY, None), + (_rs.IN_LIBRARY, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), ] # fmt: on @@ -105,47 +139,3 @@ def test_state_search_line(line: str): p.read_line(line) assert p.state == _rs.SEARCH assert len(p.alerts) == 0 - - -global_lines = [ - ("// A comment", _rs.IN_GLOBAL), - ("", _rs.IN_GLOBAL), - ("\t", _rs.IN_GLOBAL), - (" ", _rs.IN_GLOBAL), - # TODO: no check for "likely" variable declaration so these all count - ("void function()", _rs.SEARCH), - ("int x = 123;", _rs.SEARCH), - ("just some text", _rs.SEARCH), -] - - -@pytest.mark.parametrize("line, new_state", global_lines) -def test_state_global_line(line: str, new_state: _rs): - p = DecompParser() - p.read_line("// GLOBAL: TEST 0x1234") - assert p.state == _rs.IN_GLOBAL - p.read_line(line) - assert p.state == new_state - - -# mostly same as above -in_func_global_lines = [ - ("// A comment", _rs.IN_FUNC_GLOBAL), - ("", _rs.IN_FUNC_GLOBAL), - ("\t", _rs.IN_FUNC_GLOBAL), - (" ", _rs.IN_FUNC_GLOBAL), - # TODO: no check for "likely" variable declaration so these all count - ("void function()", _rs.IN_FUNC), - ("int x = 123;", _rs.IN_FUNC), - ("just some text", _rs.IN_FUNC), -] - - -@pytest.mark.parametrize("line, new_state", in_func_global_lines) -def test_state_in_func_global_line(line: str, new_state: _rs): - p = DecompParser() - p.state = _rs.IN_FUNC - p.read_line("// GLOBAL: TEST 0x1234") - assert p.state == _rs.IN_FUNC_GLOBAL - p.read_line(line) - assert p.state == new_state diff --git a/tools/isledecomp/tests/test_parser_util.py b/tools/isledecomp/tests/test_parser_util.py index 643abf3e..af102fc2 100644 --- a/tools/isledecomp/tests/test_parser_util.py +++ b/tools/isledecomp/tests/test_parser_util.py @@ -1,11 +1,15 @@ import pytest from isledecomp.parser.parser import MarkerDict -from isledecomp.parser.util import ( +from isledecomp.parser.marker import ( DecompMarker, - is_blank_or_comment, + MarkerType, match_marker, is_marker_exact, +) +from isledecomp.parser.util import ( + is_blank_or_comment, get_class_name, + get_variable_name, ) @@ -96,7 +100,7 @@ def test_marker_dict_type_replace(): d.insert(DecompMarker("STUB", "TEST", 0x1234)) markers = list(d.iter()) assert len(markers) == 1 - assert markers[0].type == "FUNCTION" + assert markers[0].type == MarkerType.FUNCTION class_name_match_cases = [ @@ -131,3 +135,26 @@ def test_get_class_name(line: str, class_name: str): @pytest.mark.parametrize("line", class_name_no_match_cases) def test_get_class_name_none(line: str): assert get_class_name(line) is None + + +variable_name_cases = [ + # with prefix for easy access + ("char* g_test;", "g_test"), + ("g_test;", "g_test"), + ("void (*g_test)(int);", "g_test"), + ("char g_test[50];", "g_test"), + ("char g_test[50] = {1234,", "g_test"), + ("int g_test = 500;", "g_test"), + # no prefix + ("char* hello;", "hello"), + ("hello;", "hello"), + ("void (*hello)(int);", "hello"), + ("char hello[50];", "hello"), + ("char hello[50] = {1234,", "hello"), + ("int hello = 500;", "hello"), +] + + +@pytest.mark.parametrize("line,name", variable_name_cases) +def test_get_variable_name(line: str, name: str): + assert get_variable_name(line) == name diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index 913154f5..c7db5e2c 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -316,7 +316,7 @@ def main(): parser.read_lines(srcfile) for fun in parser.functions: - if fun.is_stub: + if fun.should_skip(): continue if fun.module != basename: @@ -330,7 +330,7 @@ def main(): else: continue - if fun.lookup_by_name: + if fun.is_nameref(): recinfo = syminfo.get_recompiled_address_from_name(fun.name) if not recinfo: continue