Implement/match MxLoopingSmkPresenter (#351)

* Implement/match MxLoopingSmkPresenter

* Rename variable

* Rename variable
This commit is contained in:
Christian Semmler 2023-12-22 14:05:42 -05:00 committed by GitHub
parent e22ad6031c
commit cdc7b43db2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 156 additions and 14 deletions

View file

@ -33,6 +33,7 @@ public:
void CopyMediaSrcPath(const char* p_mediaSrcPath);
inline MxS32 GetFramesPerSecond() const { return this->m_framesPerSecond; }
inline MxS32 GetMediaFormat() const { return this->m_mediaFormat; }
inline MxS32 GetPaletteManagement() const { return this->m_paletteManagement; }
inline MxLong GetSustainTime() const { return this->m_sustainTime; }

View file

@ -92,6 +92,8 @@ public:
void Destroy();
MxBool Next(T& p_obj);
MxBool Current(T& p_obj);
MxBool First(T& p_obj);
MxBool Last(T& p_obj);
MxBool Advance();
MxBool HasMatch() { return m_match != NULL; }
void SetValue(T p_obj);
@ -229,6 +231,26 @@ inline MxBool MxListCursor<T>::Current(T& p_obj)
return m_match != NULL;
}
template <class T>
inline MxBool MxListCursor<T>::First(T& p_obj)
{
m_match = m_list->m_first;
if (m_match)
p_obj = m_match->GetValue();
return m_match != NULL;
}
template <class T>
inline MxBool MxListCursor<T>::Last(T& p_obj)
{
m_match = m_list->m_last;
if (m_match)
p_obj = m_match->GetValue();
return m_match != NULL;
}
template <class T>
inline MxBool MxListCursor<T>::Advance()
{

View file

@ -1,6 +1,7 @@
#include "mxloopingsmkpresenter.h"
#include "decomp.h"
#include "mxautolocker.h"
#include "mxdsmediaaction.h"
DECOMP_SIZE_ASSERT(MxLoopingSmkPresenter, 0x724);
@ -19,12 +20,112 @@ MxLoopingSmkPresenter::~MxLoopingSmkPresenter()
// FUNCTION: LEGO1 0x100b49b0
void MxLoopingSmkPresenter::Init()
{
this->m_unk0x720 = 0;
this->m_elapsedDuration = 0;
this->m_flags &= 0xfd;
this->m_flags &= 0xfb;
}
// STUB: LEGO1 0x100b49d0
// FUNCTION: LEGO1 0x100b49d0
void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor)
{
m_criticalSection.Enter();
Init();
m_criticalSection.Leave();
if (!p_fromDestructor)
MxSmkPresenter::Destroy();
}
// FUNCTION: LEGO1 0x100b4a00
void MxLoopingSmkPresenter::VTable0x88()
{
if (m_mxSmack.m_smackTag.Frames == m_currentFrame) {
m_currentFrame = 0;
// TODO: struct incorrect, Palette at wrong offset?
memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette));
}
}
// FUNCTION: LEGO1 0x100b4a30
void MxLoopingSmkPresenter::NextFrame()
{
MxStreamChunk* chunk = NextChunk();
if (chunk->GetFlags() & MxStreamChunk::Flag_Bit2) {
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
m_currentTickleState = TickleState_Repeating;
}
else {
LoadFrame(chunk);
AppendChunk(chunk);
m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
}
m_subscriber->FUN_100b8390(chunk);
}
// FUNCTION: LEGO1 0x100b4a90
void MxLoopingSmkPresenter::VTable0x8c()
{
if (m_action->GetDuration() < m_elapsedDuration) {
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
m_currentTickleState = TickleState_unk5;
}
else {
MxStreamChunk* chunk;
m_cursor->Current(chunk);
LoadFrame(chunk);
m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
}
}
// FUNCTION: LEGO1 0x100b4b00
void MxLoopingSmkPresenter::RepeatingTickle()
{
for (MxS16 i = 0; i < m_unk0x5c; i++) {
if (!m_cursor->HasMatch()) {
MxStreamChunk* chunk;
MxStreamChunkListCursor cursor(m_chunks);
cursor.Last(chunk);
MxLong time = chunk->GetTime();
cursor.First(chunk);
time -= chunk->GetTime();
time += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
cursor.Reset();
while (cursor.Next(chunk))
chunk->SetTime(chunk->GetTime() + time);
m_cursor->Advance();
}
MxStreamChunk* chunk;
m_cursor->Current(chunk);
if (m_action->GetElapsedTime() < chunk->GetTime())
break;
VTable0x8c();
m_cursor->Next(chunk);
if (m_currentTickleState != TickleState_Repeating)
break;
}
}
// FUNCTION: LEGO1 0x100b4cd0
MxResult MxLoopingSmkPresenter::AddToManager()
{
MxAutoLocker lock(&m_criticalSection);
return MxSmkPresenter::AddToManager();
}
// FUNCTION: LEGO1 0x100b4d40
void MxLoopingSmkPresenter::Destroy()
{
Destroy(FALSE);
}

View file

@ -18,11 +18,21 @@ public:
return "MxLoopingSmkPresenter";
}
virtual void RepeatingTickle() override; // vtable+0x24
virtual MxResult AddToManager() override; // vtable+0x34
virtual void Destroy() override; // vtable+0x38
virtual void NextFrame() override; // vtable+0x64
virtual void VTable0x88() override; // vtable+0x88
virtual void VTable0x8c(); // vtable+0x8c
private:
void Init();
void Destroy(MxBool p_fromDestructor);
undefined4 m_unk0x720;
MxLong m_elapsedDuration; // 0x720
};
// SYNTHETIC: LEGO1 0x100b4930
// MxLoopingSmkPresenter::`scalar deleting destructor'
#endif // MXLOOPINGSMKPRESENTER_H

View file

@ -21,7 +21,7 @@ MxSmkPresenter::~MxSmkPresenter()
// FUNCTION: LEGO1 0x100b38d0
void MxSmkPresenter::Init()
{
m_unk0x71c = 0;
m_currentFrame = 0;
memset(&m_mxSmack, 0, sizeof(m_mxSmack));
m_flags &= 0xfd;
m_flags &= 0xfb;
@ -65,8 +65,8 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk)
MxU8* bitmapData = m_bitmap->GetBitmapData();
MxU8* chunkData = p_chunk->GetData();
MxBool paletteChanged = m_mxSmack.m_frameTypes[m_unk0x71c] & 1;
m_unk0x71c++;
MxBool paletteChanged = m_mxSmack.m_frameTypes[m_currentFrame] & 1;
m_currentFrame++;
VTable0x88();
MxRectList list(TRUE);
@ -90,13 +90,13 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk)
void MxSmkPresenter::VTable0x88()
{
if ((m_mxSmack.m_smackTag.SmackerType & 1) != 0) {
MxU32 und = (m_unk0x71c % m_mxSmack.m_smackTag.Frames);
if (1 < m_unk0x71c && und == 1)
m_unk0x71c = 1;
MxU32 und = (m_currentFrame % m_mxSmack.m_smackTag.Frames);
if (1 < m_currentFrame && und == 1)
m_currentFrame = 1;
}
else {
if (m_mxSmack.m_smackTag.Frames == m_unk0x71c) {
m_unk0x71c = 0;
if (m_mxSmack.m_smackTag.Frames == m_currentFrame) {
m_currentFrame = 0;
// TODO: struct incorrect, Palette at wrong offset?
memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette));
}
@ -111,6 +111,12 @@ void MxSmkPresenter::RealizePalette()
delete palette;
}
// FUNCTION: LEGO1 0x100b42f0
MxResult MxSmkPresenter::AddToManager()
{
return MxVideoPresenter::AddToManager();
}
// FUNCTION: LEGO1 0x100b4300
void MxSmkPresenter::Destroy()
{

View file

@ -25,6 +25,7 @@ public:
return !strcmp(p_name, MxSmkPresenter::ClassName()) || MxVideoPresenter::IsA(p_name);
}
virtual MxResult AddToManager() override; // vtable+0x34
virtual void Destroy() override; // vtable+0x38
virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c
virtual void CreateBitmap() override; // vtable+0x60
@ -36,8 +37,9 @@ private:
void Init();
void Destroy(MxBool p_fromDestructor);
MxSmack m_mxSmack; // 0x64
undefined4 m_unk0x71c; // 0x71c
protected:
MxSmack m_mxSmack; // 0x64
MxU32 m_currentFrame; // 0x71c
};
#endif // MXSMKPRESENTER_H