mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-24 16:51:15 +00:00
Merge branch 'master' into animpresenter-destroy
This commit is contained in:
commit
d0cf3976ee
@ -12,10 +12,26 @@ const char* g_strANIMATION = "ANIMATION";
|
||||
// STRING: LEGO1 0x10102024
|
||||
const char* g_strATTACH_CAMERA = "ATTACH_CAMERA";
|
||||
|
||||
// GLOBAL: LEGO1 0x10102080
|
||||
// STRING: LEGO1 0x100f4368
|
||||
const char* g_strFROM_PARENT = "FROM_PARENT";
|
||||
|
||||
// GLOBAL: LEGO1 0x10102084
|
||||
// STRING: LEGO1 0x10101fa4
|
||||
const char* g_strHIDE_ON_STOP = "HIDE_ON_STOP";
|
||||
|
||||
// GLOBAL: LEGO1 0x10102098
|
||||
// STRING: LEGO1 0x10101f60
|
||||
const char* g_strMUST_SUCCEED = "MUST_SUCCEED";
|
||||
|
||||
// GLOBAL: LEGO1 0x1010209c
|
||||
// STRING: LEGO1 0x10101f58
|
||||
const char* g_strOBJECT = "OBJECT";
|
||||
|
||||
// GLOBAL: LEGO1 0x101020a8
|
||||
// STRING: LEGO1 0x10101f38
|
||||
const char* g_strPTATCAM = "PTATCAM";
|
||||
|
||||
// GLOBAL: LEGO1 0x101020b0
|
||||
// STRING: LEGO1 0x10101f20
|
||||
const char* g_strSOUND = "SOUND";
|
||||
@ -28,6 +44,10 @@ const char* g_strMUTE = "MUTE";
|
||||
// STRING: LEGO1 0x100f09cc
|
||||
const char* g_strSPEED = "SPEED";
|
||||
|
||||
// GLOBAL: LEGO1 0x101020bc
|
||||
// STRING: LEGO1 0x10101f10
|
||||
const char* g_strSUBST = "SUBST";
|
||||
|
||||
// GLOBAL: LEGO1 0x101020cc
|
||||
// STRING: LEGO1 0x100f3808
|
||||
const char* g_strVISIBILITY = "VISIBILITY";
|
||||
|
||||
@ -14,5 +14,10 @@ extern const char* g_strSPEED;
|
||||
extern const char* g_strATTACH_CAMERA;
|
||||
extern const char* g_strMUTE;
|
||||
extern const char* g_strANIMMAN_ID;
|
||||
extern const char* g_strFROM_PARENT;
|
||||
extern const char* g_strHIDE_ON_STOP;
|
||||
extern const char* g_strMUST_SUCCEED;
|
||||
extern const char* g_strSUBST;
|
||||
extern const char* g_strPTATCAM;
|
||||
|
||||
#endif // DEFINE_H
|
||||
|
||||
@ -8,6 +8,9 @@
|
||||
#include "legotraninfolist.h"
|
||||
#include "mxcore.h"
|
||||
|
||||
class LegoAnimPresenter;
|
||||
class LegoROIList;
|
||||
|
||||
// SIZE 0x18
|
||||
struct Character {
|
||||
char* m_name; // 0x00
|
||||
@ -92,6 +95,8 @@ class LegoAnimationManager : public MxCore {
|
||||
void FUN_10062770();
|
||||
void FUN_100627d0(MxBool);
|
||||
void FUN_100629b0(MxU32, MxBool);
|
||||
void FUN_10063270(LegoROIList*, LegoAnimPresenter*);
|
||||
void FUN_10063780(LegoROIList*);
|
||||
void FUN_10064670(MxBool);
|
||||
void FUN_10064740(MxBool);
|
||||
|
||||
|
||||
@ -10,11 +10,16 @@
|
||||
class LegoWorld;
|
||||
class LegoAnimClass;
|
||||
class LegoAnimActor;
|
||||
class LegoPathBoundary;
|
||||
|
||||
struct LegoAnimStructComparator {
|
||||
MxBool operator()(const char* const& p_a, const char* const& p_b) const { return strcmp(p_a, p_b) < 0; }
|
||||
};
|
||||
|
||||
struct LegoAnimSubstComparator {
|
||||
MxBool operator()(const char* const& p_a, const char* const& p_b) const { return strcmp(p_a, p_b) < 0; }
|
||||
};
|
||||
|
||||
// SIZE 0x08
|
||||
struct LegoAnimStruct {
|
||||
LegoROI* m_roi; // 0x00
|
||||
@ -22,14 +27,15 @@ struct LegoAnimStruct {
|
||||
};
|
||||
|
||||
typedef map<const char*, LegoAnimStruct, LegoAnimStructComparator> LegoAnimPresenterMap;
|
||||
typedef map<const char*, const char*, LegoAnimSubstComparator> LegoAnimSubstMap;
|
||||
|
||||
// VTABLE: LEGO1 0x100d90c8
|
||||
// SIZE 0xbc
|
||||
class LegoAnimPresenter : public MxVideoPresenter {
|
||||
public:
|
||||
enum {
|
||||
c_bit1 = 0x01,
|
||||
c_bit2 = 0x02
|
||||
c_hideOnStop = 0x01,
|
||||
c_mustSucceed = 0x02
|
||||
};
|
||||
|
||||
LegoAnimPresenter();
|
||||
@ -62,7 +68,7 @@ class LegoAnimPresenter : public MxVideoPresenter {
|
||||
virtual void VTable0x8c(); // vtable+0x8c
|
||||
virtual void VTable0x90(); // vtable+0x90
|
||||
virtual MxResult VTable0x94(Vector3&, Vector3&, float, float, Vector3&); // vtable+0x94
|
||||
virtual void VTable0x98(); // vtable+0x98
|
||||
virtual MxResult VTable0x98(LegoPathBoundary* p_boundary); // vtable+0x98
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c990
|
||||
virtual LegoROI** GetROIMap(MxU32& p_roiMapSize)
|
||||
@ -71,16 +77,14 @@ class LegoAnimPresenter : public MxVideoPresenter {
|
||||
return m_roiMap;
|
||||
} // vtable+0x9c
|
||||
|
||||
virtual void VTable0xa0(Matrix4*); // vtable+0xa0
|
||||
virtual void VTable0xa0(Matrix4& p_matrix); // vtable+0xa0
|
||||
|
||||
MxResult FUN_1006afc0(MxMatrix*&, undefined4);
|
||||
MxResult FUN_1006afc0(MxMatrix*& p_matrix, float p_und);
|
||||
MxResult FUN_1006b140(LegoROI* p_roi);
|
||||
void FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value);
|
||||
const char* GetActionObjectName();
|
||||
|
||||
inline LegoAnim* GetAnimation() { return m_anim; }
|
||||
|
||||
const char* GetActionObjectName();
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
void Destroy(MxBool p_fromDestructor);
|
||||
@ -98,36 +102,52 @@ class LegoAnimPresenter : public MxVideoPresenter {
|
||||
LegoBool FUN_1006aba0();
|
||||
MxBool FUN_1006abb0(LegoTreeNode* p_node, LegoROI* p_roi);
|
||||
void FUN_1006ac90();
|
||||
void FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix);
|
||||
void FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix);
|
||||
void FUN_1006c8a0(MxBool p_bool);
|
||||
|
||||
LegoAnim* m_anim; // 0x64
|
||||
LegoROI** m_roiMap; // 0x68
|
||||
MxU32 m_roiMapSize; // 0x6c
|
||||
LegoROIList* m_unk0x70; // 0x70
|
||||
LegoROIList* m_unk0x74; // 0x74
|
||||
MxMatrix* m_unk0x78; // 0x78
|
||||
MxU32 m_flags; // 0x7c
|
||||
LegoWorld* m_currentWorld; // 0x80
|
||||
MxAtomId m_animAtom; // 0x84
|
||||
undefined4 m_unk0x88; // 0x88
|
||||
LegoROI** m_unk0x8c; // 0x8c
|
||||
char** m_unk0x90; // 0x90
|
||||
MxU8 m_unk0x94; // 0x94
|
||||
undefined m_unk0x95; // 0x95
|
||||
MxBool m_unk0x96; // 0x96
|
||||
undefined m_unk0x97; // 0x97
|
||||
undefined4 m_unk0x98; // 0x98
|
||||
MxS16 m_unk0x9c; // 0x9c
|
||||
undefined4* m_unk0xa0; // 0xa0
|
||||
undefined4 m_unk0xa4; // 0xa4
|
||||
Mx3DPointFloat m_unk0xa8; // 0xa8
|
||||
LegoAnim* m_anim; // 0x64
|
||||
LegoROI** m_roiMap; // 0x68
|
||||
MxU32 m_roiMapSize; // 0x6c
|
||||
LegoROIList* m_unk0x70; // 0x70
|
||||
LegoROIList* m_unk0x74; // 0x74
|
||||
MxMatrix* m_unk0x78; // 0x78
|
||||
MxU32 m_flags; // 0x7c
|
||||
LegoWorld* m_currentWorld; // 0x80
|
||||
MxAtomId m_worldAtom; // 0x84
|
||||
MxS32 m_worldId; // 0x88
|
||||
LegoROI** m_unk0x8c; // 0x8c
|
||||
char** m_unk0x90; // 0x90
|
||||
MxU8 m_unk0x94; // 0x94
|
||||
undefined m_unk0x95; // 0x95
|
||||
MxBool m_unk0x96; // 0x96
|
||||
undefined m_unk0x97; // 0x97
|
||||
LegoAnimSubstMap* m_substMap; // 0x98
|
||||
MxS16 m_unk0x9c; // 0x9c
|
||||
undefined4* m_unk0xa0; // 0xa0
|
||||
undefined4 m_unk0xa4; // 0xa4
|
||||
Mx3DPointFloat m_unk0xa8; // 0xa8
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
// SYNTHETIC: LEGO1 0x10068650
|
||||
// LegoAnimPresenter::`scalar deleting destructor'
|
||||
|
||||
// TEMPLATE: LEGO1 0x100689c0
|
||||
// map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >::~map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >
|
||||
|
||||
// TEMPLATE: LEGO1 0x10068a10
|
||||
// _Tree<char const *,pair<char const * const,char const *>,map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >::_Kfn,LegoAnimSubstComparator,allocator<char const *> >::~_Tree<char const *,pair<char const * const,char const *>,map
|
||||
|
||||
// TEMPLATE: LEGO1 0x10068ae0
|
||||
// _Tree<char const *,pair<char const * const,char const *>,map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >::_Kfn,LegoAnimSubstComparator,allocator<char const *> >::iterator::_Inc
|
||||
|
||||
// TEMPLATE: LEGO1 0x10068b20
|
||||
// _Tree<char const *,pair<char const * const,char const *>,map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >::_Kfn,LegoAnimSubstComparator,allocator<char const *> >::erase
|
||||
|
||||
// TEMPLATE: LEGO1 0x10068f70
|
||||
// _Tree<char const *,pair<char const * const,char const *>,map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >::_Kfn,LegoAnimSubstComparator,allocator<char const *> >::_Erase
|
||||
|
||||
// TEMPLATE: LEGO1 0x10069d80
|
||||
// _Tree<char const *,pair<char const * const,LegoAnimStruct>,map<char const *,LegoAnimStruct,LegoAnimStructComparator,allocator<LegoAnimStruct> >::_Kfn,LegoAnimStructComparator,allocator<LegoAnimStruct> >::~_Tree<char const *,pair<char const * const,LegoAni
|
||||
|
||||
@ -152,6 +172,21 @@ class LegoAnimPresenter : public MxVideoPresenter {
|
||||
// TEMPLATE: LEGO1 0x1006a7a0
|
||||
// _Tree<char const *,pair<char const * const,LegoAnimStruct>,map<char const *,LegoAnimStruct,LegoAnimStructComparator,allocator<LegoAnimStruct> >::_Kfn,LegoAnimStructComparator,allocator<LegoAnimStruct> >::_Insert
|
||||
|
||||
// TEMPLATE: LEGO1 0x1006c1b0
|
||||
// _Tree<char const *,pair<char const * const,char const *>,map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >::_Kfn,LegoAnimSubstComparator,allocator<char const *> >::iterator::_Dec
|
||||
|
||||
// TEMPLATE: LEGO1 0x1006c200
|
||||
// _Tree<char const *,pair<char const * const,char const *>,map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >::_Kfn,LegoAnimSubstComparator,allocator<char const *> >::_Insert
|
||||
|
||||
// TEMPLATE: LEGO1 0x1006c4b0
|
||||
// list<char *,allocator<char *> >::~list<char *,allocator<char *> >
|
||||
|
||||
// TEMPLATE: LEGO1 0x1006c520
|
||||
// List<char *>::~List<char *>
|
||||
|
||||
// GLOBAL: LEGO1 0x100f7680
|
||||
// _Tree<char const *,pair<char const * const,char const *>,map<char const *,char const *,LegoAnimSubstComparator,allocator<char const *> >::_Kfn,LegoAnimSubstComparator,allocator<char const *> >::_Nil
|
||||
|
||||
// GLOBAL: LEGO1 0x100f7688
|
||||
// _Tree<char const *,pair<char const * const,LegoAnimStruct>,map<char const *,LegoAnimStruct,LegoAnimStructComparator,allocator<LegoAnimStruct> >::_Kfn,LegoAnimStructComparator,allocator<LegoAnimStruct> >::_Nil
|
||||
// clang-format on
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
#define LEGOEXTRAACTOR_H
|
||||
|
||||
#include "legoanimactor.h"
|
||||
#include "legoanimpresenter.h"
|
||||
|
||||
// VTABLE: LEGO1 0x100d6c00 LegoAnimActor
|
||||
// VTABLE: LEGO1 0x100d6c10 LegoPathActor
|
||||
|
||||
@ -35,6 +35,8 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter {
|
||||
// SYNTHETIC: LEGO1 0x1006cfe0
|
||||
// LegoLocomotionAnimPresenter::`scalar deleting destructor'
|
||||
|
||||
void FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value);
|
||||
|
||||
inline void DecrementUnknown0xd4()
|
||||
{
|
||||
if (m_unk0xd4) {
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
|
||||
#include "geom/legounkown100db7f4.h"
|
||||
#include "legoactor.h"
|
||||
#include "legopathboundary.h"
|
||||
#include "misc/legounknown.h"
|
||||
#include "mxtypes.h"
|
||||
#include "realtime/matrix.h"
|
||||
|
||||
class LegoPathBoundary;
|
||||
class LegoPathController;
|
||||
|
||||
// VTABLE: LEGO1 0x100d6e28
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "legopathactor.h"
|
||||
#include "mxcore.h"
|
||||
|
||||
class LegoAnimPresenter;
|
||||
class LegoPathBoundary;
|
||||
class LegoWorld;
|
||||
|
||||
@ -41,6 +42,8 @@ class LegoPathController : public MxCore {
|
||||
virtual void Destroy(); // vtable+0x18
|
||||
|
||||
undefined4 FUN_10046770(LegoPathActor* p_actor);
|
||||
void FUN_100468f0(LegoAnimPresenter* p_presenter);
|
||||
void FUN_10046930(LegoAnimPresenter* p_presenter);
|
||||
MxResult FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value);
|
||||
void Enable(MxBool p_enable);
|
||||
void FUN_10046bb0(LegoWorld* p_world);
|
||||
|
||||
@ -12,12 +12,14 @@
|
||||
// class MxList<LegoPhoneme *>
|
||||
|
||||
// VTABLE: LEGO1 0x100d9d00
|
||||
// VTABLE: BETA10 0x101bef58
|
||||
// SIZE 0x18
|
||||
class LegoPhonemeList : public MxList<LegoPhoneme*> {
|
||||
public:
|
||||
LegoPhonemeList() { SetDestroy(Destroy); }
|
||||
|
||||
// FUNCTION: LEGO1 0x1007b210
|
||||
// FUNCTION: BETA10 0x100d8340
|
||||
MxS8 Compare(LegoPhoneme* p_a, LegoPhoneme* p_b) override
|
||||
{
|
||||
MxString a(p_a->GetName());
|
||||
|
||||
@ -75,6 +75,7 @@ class LegoWorld : public LegoEntity {
|
||||
);
|
||||
void FUN_1001fc80(IslePathActor* p_actor);
|
||||
void FUN_1001fda0(LegoAnimPresenter* p_presenter);
|
||||
void FUN_1001fe90(LegoAnimPresenter* p_presenter);
|
||||
void AddPath(LegoPathController* p_controller);
|
||||
MxResult GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value);
|
||||
MxCore* Find(const char* p_class, const char* p_name);
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legonavcontroller.h"
|
||||
#include "legopathboundary.h"
|
||||
#include "legoutils.h"
|
||||
#include "misc.h"
|
||||
#include "mxnotificationparam.h"
|
||||
|
||||
@ -621,6 +621,18 @@ void LegoAnimationManager::FUN_100629b0(MxU32, MxBool)
|
||||
// TODO
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10063270
|
||||
void LegoAnimationManager::FUN_10063270(LegoROIList*, LegoAnimPresenter*)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10063780
|
||||
void LegoAnimationManager::FUN_10063780(LegoROIList*)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10064670
|
||||
void LegoAnimationManager::FUN_10064670(MxBool)
|
||||
{
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "define.h"
|
||||
#include "islepathactor.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legoanimpresenter.h"
|
||||
#include "legotraninfo.h"
|
||||
#include "legovideomanager.h"
|
||||
#include "legoworld.h"
|
||||
@ -149,7 +150,7 @@ void LegoAnimMMPresenter::ReadyTickle()
|
||||
}
|
||||
|
||||
if (m_tranInfo != NULL && m_tranInfo->m_unk0x0c != NULL) {
|
||||
m_presenter->VTable0xa0(m_tranInfo->m_unk0x0c);
|
||||
m_presenter->VTable0xa0(*m_tranInfo->m_unk0x0c);
|
||||
}
|
||||
|
||||
if (m_presenter != NULL) {
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "act1state.h"
|
||||
#include "islepathactor.h"
|
||||
#include "legoanimpresenter.h"
|
||||
#include "legogamestate.h"
|
||||
#include "legoinputmanager.h"
|
||||
#include "legonamedtexture.h"
|
||||
|
||||
@ -68,12 +68,13 @@ const char* g_nick = "Nick";
|
||||
const char* g_laura = "Laura";
|
||||
|
||||
// FUNCTION: LEGO1 0x10037d00
|
||||
// FUNCTION: BETA10 0x100d5620
|
||||
void VisibilityVariable::SetValue(const char* p_value)
|
||||
{
|
||||
MxVariable::SetValue(p_value);
|
||||
|
||||
if (p_value) {
|
||||
char* instruction = strtok(m_value.GetDataPtr(), g_delimiter2);
|
||||
char* instruction = strtok(m_value.GetData(), g_delimiter2);
|
||||
char* name = strtok(NULL, g_delimiter2);
|
||||
MxBool show;
|
||||
|
||||
|
||||
@ -299,10 +299,28 @@ void LegoWorld::FUN_1001fc80(IslePathActor* p_actor)
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1001fda0
|
||||
// FUNCTION: LEGO1 0x1001fda0
|
||||
// FUNCTION: BETA10 0x100da621
|
||||
void LegoWorld::FUN_1001fda0(LegoAnimPresenter* p_presenter)
|
||||
{
|
||||
// TODO
|
||||
LegoPathControllerListCursor cursor(&m_list0x68);
|
||||
LegoPathController* controller;
|
||||
|
||||
while (cursor.Next(controller)) {
|
||||
controller->FUN_100468f0(p_presenter);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1001fe90
|
||||
// FUNCTION: BETA10 0x100da6b5
|
||||
void LegoWorld::FUN_1001fe90(LegoAnimPresenter* p_presenter)
|
||||
{
|
||||
LegoPathControllerListCursor cursor(&m_list0x68);
|
||||
LegoPathController* controller;
|
||||
|
||||
while (cursor.Next(controller)) {
|
||||
controller->FUN_10046930(p_presenter);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1001ff80
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
#include "legoanimactor.h"
|
||||
|
||||
#include "define.h"
|
||||
#include "legoanimpresenter.h"
|
||||
#include "legolocomotionanimpresenter.h"
|
||||
#include "legopathboundary.h"
|
||||
#include "legoworld.h"
|
||||
#include "misc.h"
|
||||
#include "mxutilities.h"
|
||||
@ -200,7 +201,8 @@ void LegoAnimActor::ParseAction(char* p_extra)
|
||||
char* token = strtok(value, g_parseExtraTokens);
|
||||
|
||||
while (token) {
|
||||
LegoAnimPresenter* presenter = (LegoAnimPresenter*) world->Find("LegoAnimPresenter", token);
|
||||
LegoLocomotionAnimPresenter* presenter =
|
||||
(LegoLocomotionAnimPresenter*) world->Find("LegoAnimPresenter", token);
|
||||
|
||||
if (presenter != NULL) {
|
||||
token = strtok(NULL, g_parseExtraTokens);
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "legoextraactor.h"
|
||||
|
||||
#include "legolocomotionanimpresenter.h"
|
||||
#include "legopathboundary.h"
|
||||
#include "legosoundmanager.h"
|
||||
#include "misc.h"
|
||||
#include "mxmisc.h"
|
||||
@ -11,10 +13,10 @@ DECOMP_SIZE_ASSERT(LegoExtraActor, 0x1dc)
|
||||
LegoWorld* g_unk0x100f31d0 = NULL;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f31d4
|
||||
LegoAnimPresenter* m_assAnimP = NULL;
|
||||
LegoLocomotionAnimPresenter* m_assAnimP = NULL;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f31d8
|
||||
LegoAnimPresenter* m_disAnimP = NULL;
|
||||
LegoLocomotionAnimPresenter* m_disAnimP = NULL;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f31dc
|
||||
MxS32 g_unk0x100f31dc = 0;
|
||||
@ -156,8 +158,8 @@ inline void LegoExtraActor::FUN_1002ad8a()
|
||||
|
||||
if (g_unk0x100f31d0 != w) {
|
||||
g_unk0x100f31d0 = w;
|
||||
m_assAnimP = (LegoAnimPresenter*) w->Find("LegoAnimPresenter", "BNsAss01");
|
||||
m_disAnimP = (LegoAnimPresenter*) w->Find("LegoAnimPresenter", "BNsDis01");
|
||||
m_assAnimP = (LegoLocomotionAnimPresenter*) w->Find("LegoAnimPresenter", "BNsAss01");
|
||||
m_disAnimP = (LegoLocomotionAnimPresenter*) w->Find("LegoAnimPresenter", "BNsDis01");
|
||||
}
|
||||
|
||||
if (!m_assAnim) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "legopathactor.h"
|
||||
|
||||
#include "legonavcontroller.h"
|
||||
#include "legopathboundary.h"
|
||||
#include "legosoundmanager.h"
|
||||
#include "misc.h"
|
||||
#include "mxmisc.h"
|
||||
|
||||
@ -33,6 +33,18 @@ undefined4 LegoPathController::FUN_10046770(LegoPathActor* p_actor)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100468f0
|
||||
// FUNCTION: BETA10 0x100b72f7
|
||||
void LegoPathController::FUN_100468f0(LegoAnimPresenter* p_presenter)
|
||||
{
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10046930
|
||||
// FUNCTION: BETA10 0x100b737b
|
||||
void LegoPathController::FUN_10046930(LegoAnimPresenter* p_presenter)
|
||||
{
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10046b30
|
||||
MxResult LegoPathController::FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value)
|
||||
{
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
#include "legoanimpresenter.h"
|
||||
|
||||
#include "define.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legoanimmmpresenter.h"
|
||||
#include "legocharactermanager.h"
|
||||
#include "legopathboundary.h"
|
||||
#include "legovideomanager.h"
|
||||
#include "legoworld.h"
|
||||
#include "misc.h"
|
||||
@ -13,6 +16,7 @@
|
||||
#include "mxstreamchunk.h"
|
||||
#include "mxtimer.h"
|
||||
#include "mxtype18notificationparam.h"
|
||||
#include "mxutilities.h"
|
||||
#include "mxvideomanager.h"
|
||||
#include "realtime/realtime.h"
|
||||
|
||||
@ -44,9 +48,9 @@ void LegoAnimPresenter::Init()
|
||||
m_unk0xa4 = 0;
|
||||
m_currentWorld = NULL;
|
||||
m_unk0x95 = 0;
|
||||
m_unk0x88 = -1;
|
||||
m_unk0x98 = 0;
|
||||
m_animAtom.Clear();
|
||||
m_worldId = -1;
|
||||
m_substMap = NULL;
|
||||
m_worldAtom.Clear();
|
||||
m_unk0x9c = 0;
|
||||
m_unk0x8c = NULL;
|
||||
m_unk0x90 = NULL;
|
||||
@ -505,10 +509,15 @@ void LegoAnimPresenter::FUN_1006aa60()
|
||||
// TODO
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1006ab70
|
||||
// FUNCTION: LEGO1 0x1006ab70
|
||||
void LegoAnimPresenter::FUN_1006ab70()
|
||||
{
|
||||
// TODO
|
||||
if (m_unk0x96) {
|
||||
AnimationManager()->FUN_10063270(m_unk0x74, this);
|
||||
}
|
||||
else {
|
||||
AnimationManager()->FUN_10063780(m_unk0x74);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1006aba0
|
||||
@ -627,11 +636,32 @@ void LegoAnimPresenter::PutFrame()
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1006afc0
|
||||
// FUNCTION: LEGO1 0x1006afc0
|
||||
// FUNCTION: BETA10 0x1005059a
|
||||
MxResult LegoAnimPresenter::FUN_1006afc0(MxMatrix*&, undefined4)
|
||||
MxResult LegoAnimPresenter::FUN_1006afc0(MxMatrix*& p_matrix, float p_und)
|
||||
{
|
||||
// TODO
|
||||
MxU32 length = m_roiMapSize + 1;
|
||||
p_matrix = new MxMatrix[length];
|
||||
|
||||
MxS32 i;
|
||||
for (i = 1; i < length; i++) {
|
||||
if (m_roiMap[i] != NULL) {
|
||||
p_matrix[i] = m_roiMap[i]->GetLocal2World();
|
||||
}
|
||||
}
|
||||
|
||||
FUN_1006b900(m_anim, p_und, m_unk0x78);
|
||||
|
||||
for (i = 1; i < length; i++) {
|
||||
MxMatrix mat;
|
||||
|
||||
if (m_roiMap[i] != NULL) {
|
||||
mat = p_matrix[i];
|
||||
p_matrix[i] = m_roiMap[i]->GetLocal2World();
|
||||
m_roiMap[i]->FUN_100a58f0(mat);
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -674,7 +704,7 @@ void LegoAnimPresenter::StartingTickle()
|
||||
FUN_100692b0();
|
||||
FUN_100695c0();
|
||||
|
||||
if (m_flags & c_bit2 && !FUN_1006aba0()) {
|
||||
if (m_flags & c_mustSucceed && !FUN_1006aba0()) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -770,6 +800,31 @@ const char* LegoAnimPresenter::GetActionObjectName()
|
||||
return m_action->GetObjectName();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1006b900
|
||||
// FUNCTION: BETA10 0x100510d8
|
||||
void LegoAnimPresenter::FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix)
|
||||
{
|
||||
LegoTreeNode* root = p_anim->GetRoot();
|
||||
MxMatrix mat;
|
||||
LegoAnimNodeData* data = (LegoAnimNodeData*) root->GetData();
|
||||
|
||||
if (p_matrix != NULL) {
|
||||
mat = *p_matrix;
|
||||
}
|
||||
else {
|
||||
LegoROI* roi = m_roiMap[data->GetUnknown0x20()];
|
||||
|
||||
if (roi != NULL) {
|
||||
mat = roi->GetLocal2World();
|
||||
}
|
||||
else {
|
||||
mat.SetIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
LegoROI::FUN_100a8fd0(root, mat, p_time, m_roiMap);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1006b9a0
|
||||
void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix)
|
||||
{
|
||||
@ -803,16 +858,117 @@ void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p
|
||||
LegoROI::FUN_100a8e80(root, mat, p_time, m_roiMap);
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1006bac0
|
||||
// FUNCTION: LEGO1 0x1006bac0
|
||||
// FUNCTION: BETA10 0x100512e1
|
||||
void LegoAnimPresenter::ParseExtra()
|
||||
{
|
||||
// TODO
|
||||
MxU16 extraLength;
|
||||
char* extraData;
|
||||
m_action->GetExtra(extraLength, extraData);
|
||||
|
||||
if (extraLength & MAXWORD) {
|
||||
char extraCopy[256];
|
||||
memcpy(extraCopy, extraData, extraLength & MAXWORD);
|
||||
extraCopy[extraLength & MAXWORD] = '\0';
|
||||
|
||||
char output[256];
|
||||
if (KeyValueStringParse(NULL, g_strFROM_PARENT, extraCopy) && m_compositePresenter != NULL) {
|
||||
m_compositePresenter->GetAction()->GetExtra(extraLength, extraData);
|
||||
|
||||
if (extraLength & MAXWORD) {
|
||||
memcpy(extraCopy, extraData, extraLength & MAXWORD);
|
||||
extraCopy[extraLength & MAXWORD] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (KeyValueStringParse(output, g_strHIDE_ON_STOP, extraCopy)) {
|
||||
m_flags |= c_hideOnStop;
|
||||
}
|
||||
|
||||
if (KeyValueStringParse(output, g_strMUST_SUCCEED, extraCopy)) {
|
||||
m_flags |= c_mustSucceed;
|
||||
}
|
||||
|
||||
if (KeyValueStringParse(output, g_strSUBST, extraCopy)) {
|
||||
m_substMap = new LegoAnimSubstMap();
|
||||
|
||||
char* substToken = output;
|
||||
char *key, *value;
|
||||
|
||||
while ((key = strtok(substToken, g_parseExtraTokens))) {
|
||||
substToken = NULL;
|
||||
|
||||
if ((value = strtok(NULL, g_parseExtraTokens))) {
|
||||
char* keyCopy = new char[strlen(key) + 1];
|
||||
strcpy(keyCopy, key);
|
||||
char* valueCopy = new char[strlen(value) + 1];
|
||||
strcpy(valueCopy, value);
|
||||
(*m_substMap)[keyCopy] = valueCopy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (KeyValueStringParse(output, g_strWORLD, extraCopy)) {
|
||||
char* token = strtok(output, g_parseExtraTokens);
|
||||
m_worldAtom = MxAtomId(token, e_lowerCase2);
|
||||
|
||||
token = strtok(NULL, g_parseExtraTokens);
|
||||
m_worldId = atoi(token);
|
||||
}
|
||||
|
||||
if (KeyValueStringParse(output, g_strPTATCAM, extraCopy)) {
|
||||
list<char*> tmp;
|
||||
|
||||
if (m_unk0x90 != NULL) {
|
||||
for (MxS32 i = 0; i < m_unk0x94; i++) {
|
||||
if (m_unk0x90[i] != NULL) {
|
||||
// (modernization) critical bug: wrong free
|
||||
delete[] m_unk0x90;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] m_unk0x90;
|
||||
m_unk0x90 = NULL;
|
||||
}
|
||||
|
||||
if (m_unk0x8c != NULL) {
|
||||
delete[] m_unk0x8c;
|
||||
m_unk0x8c = NULL;
|
||||
}
|
||||
|
||||
char* token = strtok(output, g_parseExtraTokens);
|
||||
while (token != NULL) {
|
||||
char* valueCopy = new char[strlen(token) + 1];
|
||||
strcpy(valueCopy, token);
|
||||
tmp.push_back(valueCopy);
|
||||
token = strtok(NULL, g_parseExtraTokens);
|
||||
}
|
||||
|
||||
m_unk0x94 = tmp.size();
|
||||
if (m_unk0x94 != 0) {
|
||||
m_unk0x8c = new LegoROI*[m_unk0x94];
|
||||
m_unk0x90 = new char*[m_unk0x94];
|
||||
memset(m_unk0x8c, 0, sizeof(*m_unk0x8c) * m_unk0x94);
|
||||
memset(m_unk0x90, 0, sizeof(*m_unk0x90) * m_unk0x94);
|
||||
|
||||
MxS32 i = 0;
|
||||
for (list<char*>::iterator it = tmp.begin(); it != tmp.end(); it++, i++) {
|
||||
m_unk0x90[i] = *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1006c570
|
||||
void LegoAnimPresenter::VTable0xa0(Matrix4*)
|
||||
// FUNCTION: LEGO1 0x1006c570
|
||||
// FUNCTION: BETA10 0x10051ab3
|
||||
void LegoAnimPresenter::VTable0xa0(Matrix4& p_matrix)
|
||||
{
|
||||
// TODO
|
||||
if (m_unk0x78 != NULL) {
|
||||
delete m_unk0x78;
|
||||
}
|
||||
|
||||
m_unk0x78 = new MxMatrix(p_matrix);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1006c620
|
||||
@ -844,7 +1000,7 @@ void LegoAnimPresenter::EndAction()
|
||||
FUN_1006b9a0(m_anim, m_anim->GetDuration(), m_unk0x78);
|
||||
}
|
||||
|
||||
if (m_roiMapSize != 0 && m_roiMap != NULL && m_roiMap[1] != NULL && m_flags & c_bit1) {
|
||||
if (m_roiMapSize != 0 && m_roiMap != NULL && m_roiMap[1] != NULL && m_flags & c_hideOnStop) {
|
||||
for (MxS16 i = 1; i <= m_roiMapSize; i++) {
|
||||
if (m_roiMap[i] != NULL) {
|
||||
m_roiMap[i]->SetVisibility(FALSE);
|
||||
@ -864,6 +1020,7 @@ void LegoAnimPresenter::EndAction()
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1006c7d0
|
||||
// FUNCTION: BETA10 0x10051e07
|
||||
void LegoAnimPresenter::VTable0x8c()
|
||||
{
|
||||
if (m_unk0x78) {
|
||||
@ -874,7 +1031,7 @@ void LegoAnimPresenter::VTable0x8c()
|
||||
}
|
||||
|
||||
if (m_currentWorld == NULL) {
|
||||
m_currentWorld = m_unk0x88 != -1 ? FindWorld(m_animAtom, m_unk0x88) : CurrentWorld();
|
||||
m_currentWorld = m_worldId != -1 ? FindWorld(m_worldAtom, m_worldId) : CurrentWorld();
|
||||
}
|
||||
|
||||
if (m_currentWorld) {
|
||||
@ -885,10 +1042,19 @@ void LegoAnimPresenter::VTable0x8c()
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1006c860
|
||||
// FUNCTION: LEGO1 0x1006c860
|
||||
// FUNCTION: BETA10 0x10051f45
|
||||
void LegoAnimPresenter::VTable0x90()
|
||||
{
|
||||
// TODO
|
||||
if (m_currentWorld != NULL) {
|
||||
m_currentWorld->FUN_1001fe90(this);
|
||||
|
||||
if (m_compositePresenter != NULL && m_compositePresenter->IsA("LegoAnimMMPresenter")) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentWorld->Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1006c8a0
|
||||
@ -917,14 +1083,17 @@ MxResult LegoAnimPresenter::VTable0x94(Vector3&, Vector3&, float, float, Vector3
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1006ca50
|
||||
void LegoAnimPresenter::VTable0x98()
|
||||
// FUNCTION: LEGO1 0x1006ca50
|
||||
// FUNCTION: BETA10 0x100521d0
|
||||
MxResult LegoAnimPresenter::VTable0x98(LegoPathBoundary* p_boundary)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
for (MxU32 i = 1; i <= m_roiMapSize; i++) {
|
||||
LegoEntity* entity = m_roiMap[i]->GetEntity();
|
||||
|
||||
// STUB: LEGO1 0x1006d680
|
||||
void LegoAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value)
|
||||
{
|
||||
// TODO
|
||||
if (entity != NULL) {
|
||||
p_boundary->AddActor((LegoPathActor*) entity);
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -113,3 +113,9 @@ void LegoLocomotionAnimPresenter::EndAction()
|
||||
MxVideoPresenter::EndAction();
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x1006d680
|
||||
void LegoLocomotionAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
@ -405,14 +405,14 @@ LegoResult LegoROI::FUN_100a8da0(LegoTreeNode* p_node, const Matrix4& p_matrix,
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a8e80
|
||||
void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_rois)
|
||||
void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap)
|
||||
{
|
||||
MxMatrix mat;
|
||||
|
||||
LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData();
|
||||
FUN_100a8cb0(data, p_time, mat);
|
||||
|
||||
LegoROI* roi = p_rois[data->GetUnknown0x20()];
|
||||
LegoROI* roi = p_roiMap[data->GetUnknown0x20()];
|
||||
if (roi != NULL) {
|
||||
roi->m_local2world.Product(mat, p_matrix);
|
||||
roi->VTable0x1c();
|
||||
@ -421,7 +421,7 @@ void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t
|
||||
roi->SetVisibility(und);
|
||||
|
||||
for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) {
|
||||
FUN_100a8e80(p_node->GetChild(i), roi->m_local2world, p_time, p_rois);
|
||||
FUN_100a8e80(p_node->GetChild(i), roi->m_local2world, p_time, p_roiMap);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -429,7 +429,34 @@ void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t
|
||||
local2world.Product(mat, p_matrix);
|
||||
|
||||
for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) {
|
||||
FUN_100a8e80(p_node->GetChild(i), local2world, p_time, p_rois);
|
||||
FUN_100a8e80(p_node->GetChild(i), local2world, p_time, p_roiMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a8fd0
|
||||
// FUNCTION: BETA10 0x1018ac81
|
||||
void LegoROI::FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap)
|
||||
{
|
||||
MxMatrix mat;
|
||||
|
||||
LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData();
|
||||
FUN_100a8cb0(data, p_time, mat);
|
||||
|
||||
LegoROI* roi = p_roiMap[data->GetUnknown0x20()];
|
||||
if (roi != NULL) {
|
||||
roi->m_local2world.Product(mat, p_matrix);
|
||||
|
||||
for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) {
|
||||
FUN_100a8fd0(p_node->GetChild(i), roi->m_local2world, p_time, p_roiMap);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MxMatrix local2world;
|
||||
local2world.Product(mat, p_matrix);
|
||||
|
||||
for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) {
|
||||
FUN_100a8fd0(p_node->GetChild(i), local2world, p_time, p_roiMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,8 @@ class LegoROI : public ViewROI {
|
||||
);
|
||||
LegoROI* FindChildROI(const LegoChar* p_name, LegoROI* p_roi);
|
||||
LegoResult FUN_100a8da0(LegoTreeNode* p_node, const Matrix4& p_matrix, LegoTime p_time, LegoROI* p_roi);
|
||||
static void FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_rois);
|
||||
static void FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap);
|
||||
static void FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap);
|
||||
LegoResult SetFrame(LegoAnim* p_anim, LegoTime p_time);
|
||||
LegoResult FUN_100a9170(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha);
|
||||
LegoResult FUN_100a9210(LegoTextureInfo* p_textureInfo);
|
||||
|
||||
@ -58,7 +58,7 @@ MxResult ModelDbPart::Read(FILE* p_file)
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// Critical bug: buffer overrun
|
||||
// (modernization) critical bug: buffer overrun
|
||||
if (fread(buff, len, 1, p_file) != 1) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
// SIZE 0x48
|
||||
class MxMatrix : public Matrix4 {
|
||||
public:
|
||||
// FUNCTION: LEGO1 0x1006b120
|
||||
inline MxMatrix() : Matrix4(m_elements) {}
|
||||
|
||||
// FUNCTION: LEGO1 0x10032770
|
||||
@ -26,7 +27,7 @@ class MxMatrix : public Matrix4 {
|
||||
virtual void operator=(const MxMatrix& p_matrix) { Equals(p_matrix); } // vtable+0x48
|
||||
|
||||
private:
|
||||
float m_elements[4][4];
|
||||
float m_elements[4][4]; // 0x08
|
||||
};
|
||||
|
||||
#endif // MXMATRIX_H
|
||||
|
||||
@ -4,28 +4,42 @@
|
||||
#include "mxcore.h"
|
||||
|
||||
// VTABLE: LEGO1 0x100dc110
|
||||
// VTABLE: BETA10 0x101c1be0
|
||||
// SIZE 0x10
|
||||
class MxString : public MxCore {
|
||||
public:
|
||||
MxString(const MxString& p_str);
|
||||
~MxString() override;
|
||||
const MxString& operator=(const char* p_data);
|
||||
|
||||
MxString();
|
||||
MxString(const char*);
|
||||
MxString(const MxString& p_str);
|
||||
MxString(const char* p_str);
|
||||
MxString(const char* p_str, MxU16 p_maxlen);
|
||||
~MxString() override;
|
||||
|
||||
void Reverse();
|
||||
void ToUpperCase();
|
||||
void ToLowerCase();
|
||||
|
||||
MxString& operator=(const MxString& p_str);
|
||||
MxString operator+(const char* p_str);
|
||||
const MxString& operator=(const char* p_str);
|
||||
MxString operator+(const MxString& p_str) const;
|
||||
MxString operator+(const char* p_str) const;
|
||||
MxString& operator+=(const char* p_str);
|
||||
|
||||
inline MxS8 Compare(const MxString& p_str) const { return strcmp(m_data, p_str.m_data); }
|
||||
inline MxBool Equal(const MxString& p_str) const { return strcmp(m_data, p_str.m_data) == 0; }
|
||||
inline const char* GetData() const { return m_data; }
|
||||
inline char* GetDataPtr() const { return m_data; }
|
||||
static void CharSwap(char* p_a, char* p_b);
|
||||
|
||||
// FUNCTION: BETA10 0x10017c50
|
||||
inline char* GetData() const { return m_data; }
|
||||
|
||||
// FUNCTION: BETA10 0x10067630
|
||||
inline const MxU16 GetLength() const { return m_length; }
|
||||
|
||||
// FUNCTION: BETA10 0x100d8a30
|
||||
inline MxBool Equal(const MxString& p_str) const { return strcmp(m_data, p_str.m_data) == 0; }
|
||||
|
||||
// FUNCTION: BETA10 0x1012a810
|
||||
inline MxS8 Compare(const MxString& p_str) const { return strcmp(m_data, p_str.m_data); }
|
||||
|
||||
// SYNTHETIC: LEGO1 0x100ae280
|
||||
// SYNTHETIC: BETA10 0x1012c9d0
|
||||
// MxString::`scalar deleting destructor'
|
||||
|
||||
private:
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
DECOMP_SIZE_ASSERT(MxString, 0x10)
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae200
|
||||
// FUNCTION: BETA10 0x1012c110
|
||||
MxString::MxString()
|
||||
{
|
||||
// Set string to one char in length and set that char to null terminator
|
||||
@ -17,6 +18,7 @@ MxString::MxString()
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae2a0
|
||||
// FUNCTION: BETA10 0x1012c1a1
|
||||
MxString::MxString(const MxString& p_str)
|
||||
{
|
||||
this->m_length = p_str.m_length;
|
||||
@ -25,6 +27,7 @@ MxString::MxString(const MxString& p_str)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae350
|
||||
// FUNCTION: BETA10 0x1012c24f
|
||||
MxString::MxString(const char* p_str)
|
||||
{
|
||||
if (p_str) {
|
||||
@ -39,25 +42,65 @@ MxString::MxString(const char* p_str)
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x1012c330
|
||||
MxString::MxString(const char* p_str, MxU16 p_maxlen)
|
||||
{
|
||||
if (p_str) {
|
||||
if (strlen(p_str) <= p_maxlen) {
|
||||
this->m_length = strlen(p_str);
|
||||
}
|
||||
else {
|
||||
this->m_length = p_maxlen;
|
||||
}
|
||||
|
||||
// Basically strncpy
|
||||
this->m_data = new char[this->m_length + 1];
|
||||
memcpy(this->m_data, p_str, this->m_length);
|
||||
this->m_data[this->m_length] = '\0';
|
||||
}
|
||||
else {
|
||||
this->m_data = new char[1];
|
||||
this->m_data[0] = 0;
|
||||
this->m_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae420
|
||||
// FUNCTION: BETA10 0x1012c45b
|
||||
MxString::~MxString()
|
||||
{
|
||||
delete[] this->m_data;
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x1012c4de
|
||||
void MxString::Reverse()
|
||||
{
|
||||
char* start = this->m_data;
|
||||
char* end = this->m_data + this->m_length - 1;
|
||||
|
||||
while (start < end) {
|
||||
CharSwap(start, end);
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae490
|
||||
// FUNCTION: BETA10 0x1012c537
|
||||
void MxString::ToUpperCase()
|
||||
{
|
||||
strupr(this->m_data);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae4a0
|
||||
// FUNCTION: BETA10 0x1012c55c
|
||||
void MxString::ToLowerCase()
|
||||
{
|
||||
strlwr(this->m_data);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae4b0
|
||||
// FUNCTION: BETA10 0x1012c581
|
||||
MxString& MxString::operator=(const MxString& p_str)
|
||||
{
|
||||
if (this->m_data != p_str.m_data) {
|
||||
@ -71,22 +114,39 @@ MxString& MxString::operator=(const MxString& p_str)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae510
|
||||
const MxString& MxString::operator=(const char* p_data)
|
||||
// FUNCTION: BETA10 0x1012c606
|
||||
const MxString& MxString::operator=(const char* p_str)
|
||||
{
|
||||
if (this->m_data != p_data) {
|
||||
if (this->m_data != p_str) {
|
||||
delete[] this->m_data;
|
||||
this->m_length = strlen(p_data);
|
||||
this->m_length = strlen(p_str);
|
||||
this->m_data = new char[this->m_length + 1];
|
||||
strcpy(this->m_data, p_data);
|
||||
strcpy(this->m_data, p_str);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x1012c68a
|
||||
MxString MxString::operator+(const MxString& p_str) const
|
||||
{
|
||||
MxString tmp;
|
||||
delete[] tmp.m_data;
|
||||
|
||||
tmp.m_length = p_str.m_length + this->m_length;
|
||||
tmp.m_data = new char[tmp.m_length + 1];
|
||||
|
||||
strcpy(tmp.m_data, this->m_data);
|
||||
strcpy(tmp.m_data + this->m_length, p_str.m_data);
|
||||
|
||||
return MxString(tmp);
|
||||
}
|
||||
|
||||
// Return type is intentionally just MxString, not MxString&.
|
||||
// This forces MSVC to add $ReturnUdt$ to the stack for 100% match.
|
||||
// FUNCTION: LEGO1 0x100ae580
|
||||
MxString MxString::operator+(const char* p_str)
|
||||
// FUNCTION: BETA10 0x1012c78d
|
||||
MxString MxString::operator+(const char* p_str) const
|
||||
{
|
||||
// MxString constructor allocates 1 byte for m_data, so free that first
|
||||
MxString tmp;
|
||||
@ -102,6 +162,7 @@ MxString MxString::operator+(const char* p_str)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae690
|
||||
// FUNCTION: BETA10 0x1012c92f
|
||||
MxString& MxString::operator+=(const char* p_str)
|
||||
{
|
||||
int newlen = this->m_length + strlen(p_str);
|
||||
@ -111,8 +172,16 @@ MxString& MxString::operator+=(const char* p_str)
|
||||
strcpy(tmp + this->m_length, p_str);
|
||||
|
||||
delete[] this->m_data;
|
||||
this->m_length = newlen;
|
||||
this->m_data = tmp;
|
||||
this->m_length = newlen;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x1012ca10
|
||||
void MxString::CharSwap(char* p_a, char* p_b)
|
||||
{
|
||||
char t = *p_a;
|
||||
*p_a = *p_b;
|
||||
*p_b = t;
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ class ParseAsm:
|
||||
def __init__(
|
||||
self,
|
||||
relocate_lookup: Optional[Callable[[int], bool]] = None,
|
||||
name_lookup: Optional[Callable[[int], str]] = None,
|
||||
name_lookup: Optional[Callable[[int, bool], str]] = None,
|
||||
bin_lookup: Optional[Callable[[int, int], Optional[bytes]]] = None,
|
||||
) -> None:
|
||||
self.relocate_lookup = relocate_lookup
|
||||
@ -86,13 +86,15 @@ def float_replace(self, addr: int, data_size: int) -> Optional[str]:
|
||||
|
||||
return None
|
||||
|
||||
def lookup(self, addr: int, use_cache: bool = True) -> Optional[str]:
|
||||
def lookup(
|
||||
self, addr: int, use_cache: bool = True, exact: bool = False
|
||||
) -> Optional[str]:
|
||||
"""Return a replacement name for this address if we find one."""
|
||||
if use_cache and (cached := self.replacements.get(addr, None)) is not None:
|
||||
return cached
|
||||
|
||||
if callable(self.name_lookup):
|
||||
if (name := self.name_lookup(addr)) is not None:
|
||||
if (name := self.name_lookup(addr, exact)) is not None:
|
||||
if use_cache:
|
||||
self.replacements[addr] = name
|
||||
|
||||
@ -210,7 +212,7 @@ def sanitize(self, inst: DisasmLiteInst) -> Tuple[str, str]:
|
||||
# If we have a name for this address, use it. If not,
|
||||
# do not create a new placeholder. We will instead
|
||||
# fall through to generic jump handling below.
|
||||
potential_name = self.lookup(op_str_address)
|
||||
potential_name = self.lookup(op_str_address, exact=True)
|
||||
if potential_name is not None:
|
||||
return (inst.mnemonic, potential_name)
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
import logging
|
||||
import difflib
|
||||
import struct
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, Iterable, List, Optional
|
||||
from isledecomp.bin import Bin as IsleBin, InvalidVirtualAddressError
|
||||
@ -71,6 +72,9 @@ def __init__(
|
||||
self.recomp_bin = recomp_bin
|
||||
self.pdb_file = pdb_file
|
||||
self.code_dir = code_dir
|
||||
# Controls whether we dump the asm output to a file
|
||||
self.debug: bool = False
|
||||
self.runid: str = uuid.uuid4().hex[:8]
|
||||
|
||||
self._lines_db = LinesDb(code_dir)
|
||||
self._db = CompareDb()
|
||||
@ -452,6 +456,16 @@ def _find_vtordisp(self):
|
||||
)
|
||||
self._db.set_function_pair(orig_addr, recomp_addr)
|
||||
|
||||
def _dump_asm(self, orig_combined, recomp_combined):
|
||||
"""Append the provided assembly output to the debug files"""
|
||||
with open(f"orig-{self.runid}.txt", "a", encoding="utf-8") as f:
|
||||
for addr, line in orig_combined:
|
||||
f.write(f"{addr}: {line}\n")
|
||||
|
||||
with open(f"recomp-{self.runid}.txt", "a", encoding="utf-8") as f:
|
||||
for addr, line in recomp_combined:
|
||||
f.write(f"{addr}: {line}\n")
|
||||
|
||||
def _compare_function(self, match: MatchInfo) -> DiffReport:
|
||||
# Detect when the recomp function size would cause us to read
|
||||
# enough bytes from the original function that we cross into
|
||||
@ -478,19 +492,33 @@ def _compare_function(self, match: MatchInfo) -> DiffReport:
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
def orig_lookup(addr: int) -> Optional[str]:
|
||||
m = self._db.get_by_orig(addr)
|
||||
def orig_lookup(addr: int, exact: bool) -> Optional[str]:
|
||||
m = self._db.get_by_orig(addr, exact)
|
||||
if m is None:
|
||||
return None
|
||||
|
||||
return m.match_name()
|
||||
if m.orig_addr == addr:
|
||||
return m.match_name()
|
||||
|
||||
def recomp_lookup(addr: int) -> Optional[str]:
|
||||
m = self._db.get_by_recomp(addr)
|
||||
offset = addr - m.orig_addr
|
||||
if m.compare_type != SymbolType.DATA or offset >= m.size:
|
||||
return None
|
||||
|
||||
return m.offset_name(offset)
|
||||
|
||||
def recomp_lookup(addr: int, exact: bool) -> Optional[str]:
|
||||
m = self._db.get_by_recomp(addr, exact)
|
||||
if m is None:
|
||||
return None
|
||||
|
||||
return m.match_name()
|
||||
if m.recomp_addr == addr:
|
||||
return m.match_name()
|
||||
|
||||
offset = addr - m.recomp_addr
|
||||
if m.compare_type != SymbolType.DATA or offset >= m.size:
|
||||
return None
|
||||
|
||||
return m.offset_name(offset)
|
||||
|
||||
orig_should_replace = create_reloc_lookup(self.orig_bin)
|
||||
recomp_should_replace = create_reloc_lookup(self.recomp_bin)
|
||||
@ -512,6 +540,9 @@ def recomp_lookup(addr: int) -> Optional[str]:
|
||||
orig_combined = orig_parse.parse_asm(orig_raw, match.orig_addr)
|
||||
recomp_combined = recomp_parse.parse_asm(recomp_raw, match.recomp_addr)
|
||||
|
||||
if self.debug:
|
||||
self._dump_asm(orig_combined, recomp_combined)
|
||||
|
||||
# Detach addresses from asm lines for the text diff.
|
||||
orig_asm = [x[1] for x in orig_combined]
|
||||
recomp_asm = [x[1] for x in recomp_combined]
|
||||
|
||||
@ -53,7 +53,7 @@ def __init__(
|
||||
self.name = name
|
||||
self.size = size
|
||||
|
||||
def match_name(self) -> str:
|
||||
def match_name(self) -> Optional[str]:
|
||||
"""Combination of the name and compare type.
|
||||
Intended for name substitution in the diff. If there is a diff,
|
||||
it will be more obvious what this symbol indicates."""
|
||||
@ -64,6 +64,12 @@ def match_name(self) -> str:
|
||||
name = repr(self.name) if ctype == "STRING" else self.name
|
||||
return f"{name} ({ctype})"
|
||||
|
||||
def offset_name(self, ofs: int) -> Optional[str]:
|
||||
if self.name is None:
|
||||
return None
|
||||
|
||||
return f"{self.name}+{ofs} (OFFSET)"
|
||||
|
||||
|
||||
def matchinfo_factory(_, row):
|
||||
return MatchInfo(*row)
|
||||
@ -135,7 +141,32 @@ def get_one_match(self, addr: int) -> Optional[MatchInfo]:
|
||||
cur.row_factory = matchinfo_factory
|
||||
return cur.fetchone()
|
||||
|
||||
def get_by_orig(self, addr: int) -> Optional[MatchInfo]:
|
||||
def _get_closest_orig(self, addr: int) -> Optional[int]:
|
||||
value = self._db.execute(
|
||||
"""SELECT max(orig_addr) FROM `symbols`
|
||||
WHERE ? >= orig_addr
|
||||
LIMIT 1
|
||||
""",
|
||||
(addr,),
|
||||
).fetchone()
|
||||
return value[0] if value is not None else None
|
||||
|
||||
def _get_closest_recomp(self, addr: int) -> Optional[int]:
|
||||
value = self._db.execute(
|
||||
"""SELECT max(recomp_addr) FROM `symbols`
|
||||
WHERE ? >= recomp_addr
|
||||
LIMIT 1
|
||||
""",
|
||||
(addr,),
|
||||
).fetchone()
|
||||
return value[0] if value is not None else None
|
||||
|
||||
def get_by_orig(self, addr: int, exact: bool = True) -> Optional[MatchInfo]:
|
||||
if not exact and not self._orig_used(addr):
|
||||
addr = self._get_closest_orig(addr)
|
||||
if addr is None:
|
||||
return None
|
||||
|
||||
cur = self._db.execute(
|
||||
"""SELECT * FROM `match_info`
|
||||
WHERE orig_addr = ?
|
||||
@ -145,7 +176,12 @@ def get_by_orig(self, addr: int) -> Optional[MatchInfo]:
|
||||
cur.row_factory = matchinfo_factory
|
||||
return cur.fetchone()
|
||||
|
||||
def get_by_recomp(self, addr: int) -> Optional[MatchInfo]:
|
||||
def get_by_recomp(self, addr: int, exact: bool = True) -> Optional[MatchInfo]:
|
||||
if not exact and not self._recomp_used(addr):
|
||||
addr = self._get_closest_recomp(addr)
|
||||
if addr is None:
|
||||
return None
|
||||
|
||||
cur = self._db.execute(
|
||||
"""SELECT * FROM `match_info`
|
||||
WHERE recomp_addr = ?
|
||||
|
||||
@ -113,7 +113,7 @@ def relocate_lookup(addr: int) -> bool:
|
||||
def test_name_replace(start, end):
|
||||
"""Make sure the name lookup function is called if present"""
|
||||
|
||||
def substitute(_: int) -> str:
|
||||
def substitute(_: int, __: bool) -> str:
|
||||
return "_substitute_"
|
||||
|
||||
p = ParseAsm(name_lookup=substitute)
|
||||
@ -137,7 +137,7 @@ def test_replacement_numbering():
|
||||
"""If we can use the name lookup for the first address but not the second,
|
||||
the second replacement should be <OFFSET2> not <OFFSET1>."""
|
||||
|
||||
def substitute_1234(addr: int) -> Optional[str]:
|
||||
def substitute_1234(addr: int, _: bool) -> Optional[str]:
|
||||
return "_substitute_" if addr == 0x1234 else None
|
||||
|
||||
p = ParseAsm(name_lookup=substitute_1234)
|
||||
@ -171,7 +171,7 @@ def test_jump_to_function():
|
||||
assume this is the case for all jumps. Only replace the jump with a name
|
||||
if we can find it using our lookup."""
|
||||
|
||||
def substitute_1234(addr: int) -> Optional[str]:
|
||||
def substitute_1234(addr: int, _: bool) -> Optional[str]:
|
||||
return "_substitute_" if addr == 0x1234 else None
|
||||
|
||||
p = ParseAsm(name_lookup=substitute_1234)
|
||||
@ -212,7 +212,7 @@ def test_float_variable():
|
||||
"""If there is a variable at the address referenced by a float instruction,
|
||||
use the name instead of calling into the float replacement handler."""
|
||||
|
||||
def name_lookup(addr: int) -> Optional[str]:
|
||||
def name_lookup(addr: int, _: bool) -> Optional[str]:
|
||||
return "g_myFloatVariable" if addr == 0x1234 else None
|
||||
|
||||
p = ParseAsm(name_lookup=name_lookup)
|
||||
@ -234,7 +234,7 @@ def relocate_lookup(addr: int) -> bool:
|
||||
return addr in (0x1234, 0x5555)
|
||||
|
||||
# Only 0x5555 is a "known" address
|
||||
def name_lookup(addr: int) -> Optional[str]:
|
||||
def name_lookup(addr: int, _: bool) -> Optional[str]:
|
||||
return "hello" if addr == 0x5555 else None
|
||||
|
||||
p = ParseAsm(relocate_lookup=relocate_lookup, name_lookup=name_lookup)
|
||||
@ -263,7 +263,7 @@ def test_absolute_indirect():
|
||||
we have it, but there are some circumstances where we want to replace
|
||||
with the pointer's name (i.e. an import function)."""
|
||||
|
||||
def name_lookup(addr: int) -> Optional[str]:
|
||||
def name_lookup(addr: int, _: bool) -> Optional[str]:
|
||||
return {
|
||||
0x1234: "Hello",
|
||||
0x4321: "xyz",
|
||||
|
||||
@ -241,6 +241,9 @@ def main():
|
||||
|
||||
isle_compare = IsleCompare(origfile, recompfile, args.pdb, args.decomp_dir)
|
||||
|
||||
if args.loglevel == logging.DEBUG:
|
||||
isle_compare.debug = True
|
||||
|
||||
print()
|
||||
|
||||
### Compare one or none.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user