From f7dcdf9894b03b7bacb60aac0d579e7e1a300f62 Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Wed, 29 Nov 2023 07:35:32 -0500 Subject: [PATCH] MxFlcPresenter vtable70, m_unk64 (#304) * MxFlcPresenter: vtable70 * begin work on MxFlcPresenter's m_unk64 * Add another function that makes use of the FLIC header * Remove space --------- Co-authored-by: Christian Semmler --- 3rdparty/flic/flic.h | 36 +++++++++++++++++++++++++++++++++ CMakeLists.txt | 1 + LEGO1/mxflcpresenter.cpp | 23 ++++++++++++++++++--- LEGO1/mxflcpresenter.h | 9 +++++++-- LEGO1/mxloopingflcpresenter.cpp | 18 +++++++++++++++++ LEGO1/mxloopingflcpresenter.h | 2 ++ 6 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 3rdparty/flic/flic.h diff --git a/3rdparty/flic/flic.h b/3rdparty/flic/flic.h new file mode 100644 index 00000000..6d8495f4 --- /dev/null +++ b/3rdparty/flic/flic.h @@ -0,0 +1,36 @@ +#ifndef FLIC_H +#define FLIC_H + +#include + +// A basic FLIC header structure from the "EGI" documentation. Source: https://www.compuphase.com/flic.htm#FLICHEADER +// This also goes over the FLIC structures: https://github.com/thinkbeforecoding/nomemalloc.handson/blob/master/flic.txt +typedef struct { + DWORD size; /* Size of FLIC including this header */ + WORD type; /* File type 0xAF11, 0xAF12, 0xAF30, 0xAF44, ... */ + WORD frames; /* Number of frames in first segment */ + WORD width; /* FLIC width in pixels */ + WORD height; /* FLIC height in pixels */ + WORD depth; /* Bits per pixel (usually 8) */ + WORD flags; /* Set to zero or to three */ + DWORD speed; /* Delay between frames */ + WORD reserved1; /* Set to zero */ + DWORD created; /* Date of FLIC creation (FLC only) */ + DWORD creator; /* Serial number or compiler id (FLC only) */ + DWORD updated; /* Date of FLIC update (FLC only) */ + DWORD updater; /* Serial number (FLC only), see creator */ + WORD aspect_dx; /* Width of square rectangle (FLC only) */ + WORD aspect_dy; /* Height of square rectangle (FLC only) */ + WORD ext_flags; /* EGI: flags for specific EGI extensions */ + WORD keyframes; /* EGI: key-image frequency */ + WORD totalframes; /* EGI: total number of frames (segments) */ + DWORD req_memory; /* EGI: maximum chunk size (uncompressed) */ + WORD max_regions; /* EGI: max. number of regions in a CHK_REGION chunk */ + WORD transp_num; /* EGI: number of transparent levels */ + BYTE reserved2[24]; /* Set to zero */ + DWORD oframe1; /* Offset to frame 1 (FLC only) */ + DWORD oframe2; /* Offset to frame 2 (FLC only) */ + BYTE reserved3[40]; /* Set to zero */ +} FLIC_HEADER; + +#endif FLIC_H // FLIC_H \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 392d4dbe..f6ff00b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,6 +221,7 @@ endif() # Additional include directories target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/3rdparty/vec") +target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/flic") target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/smk") if (ISLE_USE_SMARTHEAP) diff --git a/LEGO1/mxflcpresenter.cpp b/LEGO1/mxflcpresenter.cpp index 991e0bbe..08bd9e0f 100644 --- a/LEGO1/mxflcpresenter.cpp +++ b/LEGO1/mxflcpresenter.cpp @@ -11,7 +11,7 @@ DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); // OFFSET: LEGO1 0x100b3310 MxFlcPresenter::MxFlcPresenter() { - this->m_unk64 = 0; + this->m_flicHeader = NULL; this->m_flags &= 0xfd; this->m_flags &= 0xfb; } @@ -19,11 +19,28 @@ MxFlcPresenter::MxFlcPresenter() // OFFSET: LEGO1 0x100b3420 MxFlcPresenter::~MxFlcPresenter() { - if (this->m_unk64) { - delete this->m_unk64; + if (this->m_flicHeader) { + delete this->m_flicHeader; } } +// OFFSET: LEGO1 0x100b3490 +void MxFlcPresenter::LoadHeader(MxStreamChunk* p_chunk) +{ + m_flicHeader = (FLIC_HEADER*) new MxU8[p_chunk->GetLength()]; + memcpy(m_flicHeader, p_chunk->GetData(), p_chunk->GetLength()); +} + +// OFFSET: LEGO1 0x100b34d0 +void MxFlcPresenter::CreateBitmap() +{ + if (m_bitmap) + delete m_bitmap; + + m_bitmap = new MxBitmap; + m_bitmap->SetSize(m_flicHeader->width, m_flicHeader->height, NULL, FALSE); +} + // OFFSET: LEGO1 0x100b3620 void MxFlcPresenter::VTable0x70() { diff --git a/LEGO1/mxflcpresenter.h b/LEGO1/mxflcpresenter.h index 7cf6aa9d..9ed72140 100644 --- a/LEGO1/mxflcpresenter.h +++ b/LEGO1/mxflcpresenter.h @@ -4,6 +4,8 @@ #include "decomp.h" #include "mxvideopresenter.h" +#include + // VTABLE 0x100dc2c0 // SIZE 0x68 class MxFlcPresenter : public MxVideoPresenter { @@ -24,9 +26,12 @@ public: return "MxFlcPresenter"; } - virtual void VTable0x70() override; // vtable+0x70 + virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c + virtual void CreateBitmap() override; // vtable+0x60 + virtual void VTable0x70() override; // vtable+0x70 - undefined4* m_unk64; +protected: + FLIC_HEADER* m_flicHeader; }; #endif // MXFLCPRESENTER_H diff --git a/LEGO1/mxloopingflcpresenter.cpp b/LEGO1/mxloopingflcpresenter.cpp index 90135eb9..f54cb1e5 100644 --- a/LEGO1/mxloopingflcpresenter.cpp +++ b/LEGO1/mxloopingflcpresenter.cpp @@ -29,3 +29,21 @@ void MxLoopingFlcPresenter::Destroy(MxBool p_fromDestructor) { // TODO } + +// OFFSET: LEGO1 0x100b4470 +void MxLoopingFlcPresenter::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_unk68 += m_flicHeader->speed; + } + + m_subscriber->FUN_100b8390(chunk); +} diff --git a/LEGO1/mxloopingflcpresenter.h b/LEGO1/mxloopingflcpresenter.h index 2107731b..fa3f31de 100644 --- a/LEGO1/mxloopingflcpresenter.h +++ b/LEGO1/mxloopingflcpresenter.h @@ -18,6 +18,8 @@ public: return "MxLoopingFlcPresenter"; } + virtual void NextFrame() override; // vtable+0x64 + private: void Init(); void Destroy(MxBool p_fromDestructor);