Clean up Destroy pattern everywhere, fix missing overrides (#202)

* Rename MxMusicPresenter function vtable38

* Rename MxMusicPresenter function vtable38

* MxMediaPresenter, MxMusicManager and MxMusicPresenter
* Refactoring Destroy functions

* MxMediaManager & MxMusicPresenter

* Fix some vtable declarations, more renames

* Fix MxEventManager

* More rename fixes

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
This commit is contained in:
DmitriLeon2000
2023-10-14 01:43:45 +09:00
committed by GitHub
parent 91c3ed3e70
commit 34e09c2bb3
24 changed files with 104 additions and 115 deletions

View File

@@ -46,7 +46,7 @@ MxResult LegoEntity::InitFromMxDSObject(MxDSObject& p_object)
} }
// OFFSET: LEGO1 0x10010810 STUB // OFFSET: LEGO1 0x10010810 STUB
void LegoEntity::Destroy(MxBool) void LegoEntity::Destroy(MxBool p_fromDestructor)
{ {
if (m_unk54) { if (m_unk54) {
// TODO // TODO

View File

@@ -36,7 +36,7 @@ public:
} }
virtual MxResult InitFromMxDSObject(MxDSObject& p_object); // vtable+0x18 virtual MxResult InitFromMxDSObject(MxDSObject& p_object); // vtable+0x18
virtual void Destroy(MxBool); // vtable+0x1c virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c
virtual void ParseAction(char *); // vtable+0x20 virtual void ParseAction(char *); // vtable+0x20
protected: protected:

View File

@@ -14,7 +14,7 @@ MxAudioManager::MxAudioManager()
// OFFSET: LEGO1 0x100b8d90 // OFFSET: LEGO1 0x100b8d90
MxAudioManager::~MxAudioManager() MxAudioManager::~MxAudioManager()
{ {
LockedReinitialize(TRUE); Destroy(TRUE);
} }
// OFFSET: LEGO1 0x100b8df0 // OFFSET: LEGO1 0x100b8df0
@@ -38,14 +38,14 @@ void MxAudioManager::SetVolume(MxS32 p_volume)
} }
// OFFSET: LEGO1 0x100b8e00 // OFFSET: LEGO1 0x100b8e00
void MxAudioManager::LockedReinitialize(MxBool p_skipDestroy) void MxAudioManager::Destroy(MxBool p_fromDestructor)
{ {
this->m_criticalSection.Enter(); this->m_criticalSection.Enter();
g_unkCount--; g_unkCount--;
Init(); Init();
this->m_criticalSection.Leave(); this->m_criticalSection.Leave();
if (!p_skipDestroy) if (!p_fromDestructor)
MxMediaManager::Destroy(); MxMediaManager::Destroy();
} }
@@ -74,5 +74,5 @@ MxResult MxAudioManager::InitPresenters()
// OFFSET: LEGO1 0x100b8e90 // OFFSET: LEGO1 0x100b8e90
void MxAudioManager::Destroy() void MxAudioManager::Destroy()
{ {
LockedReinitialize(FALSE); Destroy(FALSE);
} }

View File

@@ -17,7 +17,7 @@ public:
virtual void SetVolume(MxS32 p_volume); // vtable+2c virtual void SetVolume(MxS32 p_volume); // vtable+2c
private: private:
void LockedReinitialize(MxBool p_skipDestroy); void Destroy(MxBool p_fromDestructor);
static MxS32 g_unkCount; static MxS32 g_unkCount;

View File

@@ -13,7 +13,7 @@ MxEventManager::MxEventManager()
// OFFSET: LEGO1 0x100c03f0 // OFFSET: LEGO1 0x100c03f0
MxEventManager::~MxEventManager() MxEventManager::~MxEventManager()
{ {
TerminateThread(TRUE); Destroy(TRUE);
} }
// OFFSET: LEGO1 0x100c0450 // OFFSET: LEGO1 0x100c0450
@@ -22,6 +22,20 @@ void MxEventManager::Init()
// This is intentionally left blank // This is intentionally left blank
} }
// OFFSET: LEGO1 0x100c0460
void MxEventManager::Destroy(MxBool p_fromDestructor)
{
if (m_thread != NULL) {
m_thread->Terminate();
delete m_thread;
}
else
TickleManager()->UnregisterClient(this);
if (!p_fromDestructor)
MxMediaManager::Destroy();
}
// OFFSET: LEGO1 0x100c04a0 // OFFSET: LEGO1 0x100c04a0
MxResult MxEventManager::CreateEventThread(MxU32 p_frequencyMS, MxBool p_noRegister) MxResult MxEventManager::CreateEventThread(MxU32 p_frequencyMS, MxBool p_noRegister)
{ {
@@ -29,38 +43,34 @@ MxResult MxEventManager::CreateEventThread(MxU32 p_frequencyMS, MxBool p_noRegis
MxBool locked = FALSE; MxBool locked = FALSE;
MxResult result = MxMediaManager::InitPresenters(); MxResult result = MxMediaManager::InitPresenters();
if (result == SUCCESS) if (result == SUCCESS) {
{ if (p_noRegister) {
if (p_noRegister)
{
this->m_criticalSection.Enter(); this->m_criticalSection.Enter();
locked = TRUE; locked = TRUE;
this->m_thread = new MxTickleThread(this, p_frequencyMS); this->m_thread = new MxTickleThread(this, p_frequencyMS);
if (this->m_thread) if (this->m_thread) {
{
if (this->m_thread->Start(0, 0) == SUCCESS) if (this->m_thread->Start(0, 0) == SUCCESS)
{
status = SUCCESS; status = SUCCESS;
}
} }
} }
else else {
{
TickleManager()->RegisterClient(this, p_frequencyMS); TickleManager()->RegisterClient(this, p_frequencyMS);
status = SUCCESS; status = SUCCESS;
} }
} }
if (status != SUCCESS) if (status != SUCCESS)
{
Destroy(); Destroy();
}
if (locked) if (locked)
{
this->m_criticalSection.Leave(); this->m_criticalSection.Leave();
}
return status; return status;
} }
// OFFSET: LEGO1 0x100c0590
void MxEventManager::Destroy()
{
Destroy(FALSE);
}

View File

@@ -11,9 +11,13 @@ class MxEventManager : public MxMediaManager
public: public:
MxEventManager(); MxEventManager();
virtual ~MxEventManager() override; virtual ~MxEventManager() override;
virtual void Destroy() override; // vtable+18
virtual MxResult CreateEventThread(MxU32 p_frequencyMS, MxBool p_noRegister); // vtable+28 virtual MxResult CreateEventThread(MxU32 p_frequencyMS, MxBool p_noRegister); // vtable+28
private: private:
void Init(); void Init();
void Destroy(MxBool p_fromDestructor);
}; };
#endif // MXEVENTMANAGER_H #endif // MXEVENTMANAGER_H

View File

@@ -25,7 +25,7 @@ void MxLoopingFlcPresenter::Init()
} }
// OFFSET: LEGO1 0x100b4432 STUB // OFFSET: LEGO1 0x100b4432 STUB
void MxLoopingFlcPresenter::Destroy(MxBool p_param) void MxLoopingFlcPresenter::Destroy(MxBool p_fromDestructor)
{ {
// TODO // TODO
} }

View File

@@ -22,7 +22,7 @@ public:
private: private:
void Init(); void Init();
void Destroy(MxBool); void Destroy(MxBool p_fromDestructor);
undefined4 m_unk68; undefined4 m_unk68;
}; };

View File

@@ -25,7 +25,6 @@ void MxLoopingSmkPresenter::Init()
} }
// OFFSET: LEGO1 0x100b49d0 STUB // OFFSET: LEGO1 0x100b49d0 STUB
void MxLoopingSmkPresenter::Destroy(MxBool p_bool) void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor)
{ {
// TODO - theres a chain of destroy and free function calls here (FUN_100b4300 -> FUN_100b3900 -> FUN_100c5d40 -> function at 0x100b27b0)
} }

View File

@@ -22,7 +22,7 @@ public:
private: private:
void Init(); void Init();
void Destroy(MxBool); void Destroy(MxBool p_fromDestructor);
undefined4 m_unk720; undefined4 m_unk720;
}; };

View File

@@ -99,22 +99,3 @@ void MxMediaManager::StopPresenters()
while (cursor.Next(presenter)) while (cursor.Next(presenter))
presenter->EndAction(); presenter->EndAction();
} }
// OFFSET: LEGO1 0x100c0460
void MxMediaManager::TerminateThread(MxBool p_reinit)
{
if(m_thread != NULL)
{
m_thread->Terminate();
delete m_thread;
}
else
{
TickleManager()->UnregisterClient(this);
}
if(!p_reinit)
{
MxMediaManager::Destroy();
}
}

View File

@@ -23,7 +23,6 @@ public:
virtual void StopPresenters(); // vtable+24 virtual void StopPresenters(); // vtable+24
MxResult Init(); MxResult Init();
void TerminateThread(MxBool p_reinit);
protected: protected:
MxPresenterList *m_presenters; MxPresenterList *m_presenters;

View File

@@ -25,7 +25,7 @@ void MxMediaPresenter::Init()
} }
// OFFSET: LEGO1 0x100b54f0 STUB // OFFSET: LEGO1 0x100b54f0 STUB
void MxMediaPresenter::Destroy(MxBool p_destroy) void MxMediaPresenter::Destroy(MxBool p_fromDestructor)
{ {
// TODO // TODO
} }
@@ -57,7 +57,7 @@ void MxMediaPresenter::Enable(MxBool p_enable)
} }
// OFFSET: LEGO1 0x1000c5b0 // OFFSET: LEGO1 0x1000c5b0
void MxMediaPresenter::InitVirtual() void MxMediaPresenter::Destroy()
{ {
Destroy(FALSE); Destroy(FALSE);
} }

View File

@@ -33,7 +33,7 @@ public:
virtual void StreamingTickle() override; virtual void StreamingTickle() override;
virtual void RepeatingTickle() override; virtual void RepeatingTickle() override;
virtual void DoneTickle() override; virtual void DoneTickle() override;
virtual void InitVirtual() override; virtual void Destroy() override;
virtual MxLong StartAction(MxStreamController *, MxDSAction *) override; virtual MxLong StartAction(MxStreamController *, MxDSAction *) override;
virtual void EndAction() override; virtual void EndAction() override;
virtual void Enable(MxBool p_enable) override; virtual void Enable(MxBool p_enable) override;
@@ -43,10 +43,10 @@ public:
undefined4 m_unk44; undefined4 m_unk44;
undefined4 m_unk48; undefined4 m_unk48;
undefined4 m_unk4c; undefined4 m_unk4c;
protected:
void Destroy(MxBool);
private: private:
void Init(); void Init();
protected:
void Destroy(MxBool p_fromDestructor);
}; };

View File

@@ -15,7 +15,7 @@ MxMusicManager::MxMusicManager()
// OFFSET: LEGO1 0x100c0630 // OFFSET: LEGO1 0x100c0630
MxMusicManager::~MxMusicManager() MxMusicManager::~MxMusicManager()
{ {
LockedReinitialize(TRUE); Destroy(TRUE);
} }
// OFFSET: LEGO1 0x100c0b20 // OFFSET: LEGO1 0x100c0b20
@@ -23,47 +23,47 @@ void MxMusicManager::DeinitializeMIDI()
{ {
m_criticalSection.Enter(); m_criticalSection.Enter();
if (this->m_MIDIInitialized) if (m_MIDIInitialized)
{ {
this->m_MIDIInitialized = FALSE; m_MIDIInitialized = FALSE;
midiStreamStop(this->m_MIDIStreamH); midiStreamStop(m_MIDIStreamH);
midiOutUnprepareHeader(this->m_MIDIStreamH, this->m_MIDIHdrP, sizeof(MIDIHDR)); midiOutUnprepareHeader(m_MIDIStreamH, m_MIDIHdrP, sizeof(MIDIHDR));
midiOutSetVolume(this->m_MIDIStreamH, this->m_MIDIVolume); midiOutSetVolume(m_MIDIStreamH, m_MIDIVolume);
midiStreamClose(this->m_MIDIStreamH); midiStreamClose(m_MIDIStreamH);
delete this->m_MIDIHdrP; delete m_MIDIHdrP;
this->InitData(); InitData();
} }
this->m_criticalSection.Leave(); m_criticalSection.Leave();
} }
// OFFSET: LEGO1 0x100c0690 // OFFSET: LEGO1 0x100c0690
void MxMusicManager::Init() void MxMusicManager::Init()
{ {
this->m_multiplier = 100; m_multiplier = 100;
InitData(); InitData();
} }
// OFFSET: LEGO1 0x100c06a0 // OFFSET: LEGO1 0x100c06a0
void MxMusicManager::InitData() void MxMusicManager::InitData()
{ {
this->m_MIDIStreamH = 0; m_MIDIStreamH = 0;
this->m_MIDIInitialized = FALSE; m_MIDIInitialized = FALSE;
this->m_unk38 = 0; m_unk38 = 0;
this->m_unk3c = 0; m_unk3c = 0;
this->m_unk40 = 0; m_unk40 = 0;
this->m_unk44 = 0; m_unk44 = 0;
this->m_unk48 = 0; m_unk48 = 0;
this->m_MIDIHdrP = NULL; m_MIDIHdrP = NULL;
} }
// OFFSET: LEGO1 0x100c06c0 // OFFSET: LEGO1 0x100c06c0
void MxMusicManager::LockedReinitialize(MxBool p_skipDestroy) void MxMusicManager::Destroy(MxBool p_fromDestructor)
{ {
if (this->m_thread) if (m_thread)
{ {
this->m_thread->Terminate(); m_thread->Terminate();
if (this->m_thread) if (m_thread)
{ {
delete m_thread; delete m_thread;
} }
@@ -73,12 +73,12 @@ void MxMusicManager::LockedReinitialize(MxBool p_skipDestroy)
TickleManager()->UnregisterClient(this); TickleManager()->UnregisterClient(this);
} }
this->m_criticalSection.Enter(); m_criticalSection.Enter();
DeinitializeMIDI(); DeinitializeMIDI();
Init(); Init();
this->m_criticalSection.Leave(); m_criticalSection.Leave();
if (!p_skipDestroy) if (!p_fromDestructor)
{ {
MxAudioManager::Destroy(); MxAudioManager::Destroy();
} }
@@ -87,7 +87,7 @@ void MxMusicManager::LockedReinitialize(MxBool p_skipDestroy)
// OFFSET: LEGO1 0x100c0930 // OFFSET: LEGO1 0x100c0930
void MxMusicManager::Destroy() void MxMusicManager::Destroy()
{ {
LockedReinitialize(FALSE); Destroy(FALSE);
} }
// OFFSET: LEGO1 0x100c09a0 // OFFSET: LEGO1 0x100c09a0
@@ -100,8 +100,8 @@ MxS32 MxMusicManager::CalculateVolume(MxS32 p_volume)
// OFFSET: LEGO1 0x100c07f0 // OFFSET: LEGO1 0x100c07f0
void MxMusicManager::SetMIDIVolume() void MxMusicManager::SetMIDIVolume()
{ {
MxS32 result = (this->m_volume * this->m_multiplier) / 0x64; MxS32 result = (m_volume * m_multiplier) / 0x64;
HMIDISTRM streamHandle = this->m_MIDIStreamH; HMIDISTRM streamHandle = m_MIDIStreamH;
if (streamHandle) if (streamHandle)
{ {
@@ -114,9 +114,9 @@ void MxMusicManager::SetMIDIVolume()
void MxMusicManager::SetVolume(MxS32 p_volume) void MxMusicManager::SetVolume(MxS32 p_volume)
{ {
MxAudioManager::SetVolume(p_volume); MxAudioManager::SetVolume(p_volume);
this->m_criticalSection.Enter(); m_criticalSection.Enter();
SetMIDIVolume(); SetMIDIVolume();
this->m_criticalSection.Leave(); m_criticalSection.Leave();
} }
// OFFSET: LEGO1 0x100c0840 // OFFSET: LEGO1 0x100c0840
@@ -130,13 +130,13 @@ MxResult MxMusicManager::StartMIDIThread(MxU32 p_frequencyMS, MxBool p_noRegiste
{ {
if (p_noRegister) if (p_noRegister)
{ {
this->m_criticalSection.Enter(); m_criticalSection.Enter();
locked = TRUE; locked = TRUE;
this->m_thread = new MxTickleThread(this, p_frequencyMS); m_thread = new MxTickleThread(this, p_frequencyMS);
if (this->m_thread) if (m_thread)
{ {
if (this->m_thread->Start(0, 0) == SUCCESS) if (m_thread->Start(0, 0) == SUCCESS)
{ {
status = SUCCESS; status = SUCCESS;
} }
@@ -156,7 +156,7 @@ MxResult MxMusicManager::StartMIDIThread(MxU32 p_frequencyMS, MxBool p_noRegiste
if (locked) if (locked)
{ {
this->m_criticalSection.Leave(); m_criticalSection.Leave();
} }
return status; return status;

View File

@@ -17,7 +17,7 @@ public:
virtual MxResult StartMIDIThread(MxU32 p_frequencyMS, MxU8 p_noRegister); // vtable+30 virtual MxResult StartMIDIThread(MxU32 p_frequencyMS, MxU8 p_noRegister); // vtable+30
private: private:
void LockedReinitialize(MxBool p_skipDestroy); void Destroy(MxBool p_fromDestructor);
void DeinitializeMIDI(); void DeinitializeMIDI();
MxS32 CalculateVolume(MxS32 p_volume); MxS32 CalculateVolume(MxS32 p_volume);

View File

@@ -24,7 +24,7 @@ void MxMusicPresenter::Init()
} }
// OFFSET: LEGO1 0x100c2550 // OFFSET: LEGO1 0x100c2550
void MxMusicPresenter::Destroy(MxBool p_reinit) void MxMusicPresenter::Destroy(MxBool p_fromDestructor)
{ {
if (MusicManager()) { if (MusicManager()) {
MusicManager()->RemovePresenter(*this); MusicManager()->RemovePresenter(*this);
@@ -32,13 +32,13 @@ void MxMusicPresenter::Destroy(MxBool p_reinit)
m_criticalSection.Enter(); m_criticalSection.Enter();
Init(); Init();
m_criticalSection.Leave(); m_criticalSection.Leave();
if (!p_reinit) { if (!p_fromDestructor) {
MxMediaPresenter::Destroy(FALSE); MxMediaPresenter::Destroy(FALSE);
} }
} }
// OFFSET: LEGO1 0x100c25a0 // OFFSET: LEGO1 0x100c25a0
MxResult MxMusicPresenter::AddToMusicManager() MxResult MxMusicPresenter::AddToManager()
{ {
MxResult result = FAILURE; MxResult result = FAILURE;
if (MusicManager()) { if (MusicManager()) {
@@ -49,8 +49,7 @@ MxResult MxMusicPresenter::AddToMusicManager()
} }
// OFFSET: LEGO1 0x100c25d0 // OFFSET: LEGO1 0x100c25d0
void MxMusicPresenter::vtable38() void MxMusicPresenter::Destroy()
{ {
// TODO: Name this function when we know what the argument to Destroy does
Destroy(FALSE); Destroy(FALSE);
} }

View File

@@ -24,12 +24,12 @@ public:
MxMusicPresenter(); MxMusicPresenter();
virtual ~MxMusicPresenter() override; virtual ~MxMusicPresenter() override;
virtual MxResult AddToMusicManager(); // vtable+0x34 virtual MxResult AddToManager() override; // vtable+0x34
virtual void vtable38(); // vtable+0x38 virtual void Destroy() override; // vtable+0x38
private: private:
void Init(); void Init();
void Destroy(MxBool p_reinit); void Destroy(MxBool p_fromDestructor);
}; };
#endif // MXMUSICPRESENTER_H #endif // MXMUSICPRESENTER_H

View File

@@ -29,7 +29,6 @@ void MxPresenter::Init()
// OFFSET: LEGO1 0x100b4fc0 // OFFSET: LEGO1 0x100b4fc0
void MxPresenter::ParseExtra() void MxPresenter::ParseExtra()
{ {
MxAutoLocker lock(&m_criticalSection); MxAutoLocker lock(&m_criticalSection);
MxU32 len = m_action->GetExtraLength(); MxU32 len = m_action->GetExtraLength();
char *extraData = m_action->GetExtraData(); char *extraData = m_action->GetExtraData();
@@ -47,15 +46,13 @@ void MxPresenter::ParseExtra()
strcpy(t_token, token); strcpy(t_token, token);
token = strtok(NULL, g_parseExtraTokens); token = strtok(NULL, g_parseExtraTokens);
int val = token ? atoi(token) : 0; MxS32 val = token ? atoi(token) : 0;
MxS32 result = MxOmni::GetInstance()->vtable0x30(t_token, val, this);
int result = MxOmni::GetInstance()->vtable0x30(t_token, val, this);
m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Parsed); m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Parsed);
if (result) if (result)
SendTo_unkPresenter(MxOmni::GetInstance()); SendTo_unkPresenter(MxOmni::GetInstance());
} }
} }
} }
@@ -279,13 +276,13 @@ void MxPresenter::DoneTickle()
} }
// OFFSET: LEGO1 0x1000bf70 // OFFSET: LEGO1 0x1000bf70
undefined4 MxPresenter::VTable0x34() MxResult MxPresenter::AddToManager()
{ {
return 0; return SUCCESS;
} }
// OFFSET: LEGO1 0x1000bf80 // OFFSET: LEGO1 0x1000bf80
void MxPresenter::InitVirtual() void MxPresenter::Destroy()
{ {
Init(); Init();
} }

View File

@@ -56,8 +56,8 @@ protected:
__declspec(dllexport) virtual void ParseExtra(); // vtable+0x30 __declspec(dllexport) virtual void ParseExtra(); // vtable+0x30
public: public:
virtual undefined4 VTable0x34(); // vtable+0x34 virtual MxResult AddToManager(); // vtable+0x34
virtual void InitVirtual(); // vtable+0x38 virtual void Destroy(); // vtable+0x38
__declspec(dllexport) virtual MxLong StartAction(MxStreamController *, MxDSAction *); // vtable+0x3c __declspec(dllexport) virtual MxLong StartAction(MxStreamController *, MxDSAction *); // vtable+0x3c
__declspec(dllexport) virtual void EndAction(); // vtable+0x40 __declspec(dllexport) virtual void EndAction(); // vtable+0x40
virtual void SetTickleState(TickleState p_tickleState); // vtable+0x44 virtual void SetTickleState(TickleState p_tickleState); // vtable+0x44

View File

@@ -24,7 +24,7 @@ void MxSoundManager::Init()
} }
// OFFSET: LEGO1 0x100ae840 // OFFSET: LEGO1 0x100ae840
void MxSoundManager::Destroy(MxBool p_param) void MxSoundManager::Destroy(MxBool p_fromDestructor)
{ {
if (this->m_thread) { if (this->m_thread) {
this->m_thread->Terminate(); this->m_thread->Terminate();
@@ -43,7 +43,7 @@ void MxSoundManager::Destroy(MxBool p_param)
Init(); Init();
this->m_criticalSection.Leave(); this->m_criticalSection.Leave();
if (!p_param) { if (!p_fromDestructor) {
MxAudioManager::Destroy(); MxAudioManager::Destroy();
} }
} }

View File

@@ -20,7 +20,7 @@ public:
private: private:
void Init(); void Init();
void Destroy(MxBool); void Destroy(MxBool p_fromDestructor);
undefined4 m_unk30; undefined4 m_unk30;
LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x34 LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x34

View File

@@ -33,7 +33,7 @@ MxVideoPresenter::~MxVideoPresenter()
} }
// OFFSET: LEGO1 0x1000c7a0 STUB // OFFSET: LEGO1 0x1000c7a0 STUB
void MxVideoPresenter::InitVirtual() void MxVideoPresenter::Destroy()
{ {
// TODO // TODO
} }
@@ -71,7 +71,7 @@ void MxVideoPresenter::Init()
} }
// OFFSET: LEGO1 0x100b27b0 STUB // OFFSET: LEGO1 0x100b27b0 STUB
void MxVideoPresenter::Destroy(MxBool) void MxVideoPresenter::Destroy(MxBool p_fromDestructor)
{ {
// TODO // TODO
} }

View File

@@ -31,9 +31,9 @@ public:
} }
void Init(); void Init();
void Destroy(MxBool); void Destroy(MxBool p_fromDestructor);
virtual void InitVirtual() override; // vtable+0x38 virtual void Destroy() override; // vtable+0x38
virtual void VTable0x5c(); // vtable+0x5c virtual void VTable0x5c(); // vtable+0x5c
virtual void VTable0x60(); // vtable+0x60 virtual void VTable0x60(); // vtable+0x60