diff --git a/3rdparty/flic/flic.h b/3rdparty/flic/flic.h index 42969e5c..c828b2f4 100644 --- a/3rdparty/flic/flic.h +++ b/3rdparty/flic/flic.h @@ -6,31 +6,42 @@ // 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 */ + 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; +extern "C" +{ + void DecodeFLCFrame( + LPBITMAPINFOHEADER bitmapHeader, + void* pixelData, + FLIC_HEADER* flcHeader, + void* flcFrame, + unsigned char* decodedColorMap + ); +} + #endif // FLIC_H diff --git a/3rdparty/flic/flic.lib b/3rdparty/flic/flic.lib new file mode 100644 index 00000000..5d3c86c2 Binary files /dev/null and b/3rdparty/flic/flic.lib differ diff --git a/CMakeLists.txt b/CMakeLists.txt index 61a8d165..34b67e0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -278,9 +278,10 @@ if (ISLE_USE_DX5) endif() target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/smacker") +target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/flic") # Link libraries -target_link_libraries(lego1 PRIVATE ddraw dsound dinput dxguid winmm d3drm smack) +target_link_libraries(lego1 PRIVATE ddraw dsound dinput dxguid winmm d3drm smack flic) # Make sure filenames are ALL CAPS set_property(TARGET lego1 PROPERTY OUTPUT_NAME LEGO1) diff --git a/LEGO1/omni/include/mxflcpresenter.h b/LEGO1/omni/include/mxflcpresenter.h index d883d106..c8f9854d 100644 --- a/LEGO1/omni/include/mxflcpresenter.h +++ b/LEGO1/omni/include/mxflcpresenter.h @@ -28,13 +28,14 @@ class MxFlcPresenter : public MxVideoPresenter { virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c virtual void CreateBitmap() override; // vtable+0x60 + virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 virtual void RealizePalette() override; // vtable+0x70 // SYNTHETIC: LEGO1 0x100b3400 // MxFlcPresenter::`scalar deleting destructor' protected: - FLIC_HEADER* m_flicHeader; + FLIC_HEADER* m_flcHeader; // 0x64 }; #endif // MXFLCPRESENTER_H diff --git a/LEGO1/omni/src/video/mxflcpresenter.cpp b/LEGO1/omni/src/video/mxflcpresenter.cpp index de334852..b61c04a0 100644 --- a/LEGO1/omni/src/video/mxflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxflcpresenter.cpp @@ -2,6 +2,7 @@ #include "decomp.h" #include "mxbitmap.h" +#include "mxdsmediaaction.h" #include "mxomni.h" #include "mxpalette.h" #include "mxvideomanager.h" @@ -11,7 +12,7 @@ DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); // FUNCTION: LEGO1 0x100b3310 MxFlcPresenter::MxFlcPresenter() { - this->m_flicHeader = NULL; + this->m_flcHeader = NULL; this->m_flags &= ~c_bit2; this->m_flags &= ~c_bit3; } @@ -19,16 +20,16 @@ MxFlcPresenter::MxFlcPresenter() // FUNCTION: LEGO1 0x100b3420 MxFlcPresenter::~MxFlcPresenter() { - if (this->m_flicHeader) { - delete this->m_flicHeader; + if (this->m_flcHeader) { + delete this->m_flcHeader; } } // FUNCTION: 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()); + m_flcHeader = (FLIC_HEADER*) new MxU8[p_chunk->GetLength()]; + memcpy(m_flcHeader, p_chunk->GetData(), p_chunk->GetLength()); } // FUNCTION: LEGO1 0x100b34d0 @@ -38,7 +39,39 @@ void MxFlcPresenter::CreateBitmap() delete m_bitmap; m_bitmap = new MxBitmap; - m_bitmap->SetSize(m_flicHeader->width, m_flicHeader->height, NULL, FALSE); + m_bitmap->SetSize(m_flcHeader->width, m_flcHeader->height, NULL, FALSE); +} + +// FUNCTION: LEGO1 0x100b3570 +void MxFlcPresenter::LoadFrame(MxStreamChunk* p_chunk) +{ + MxU32* dat = (MxU32*) p_chunk->GetData() + 4; + MxU32 offset = *(MxU32*) p_chunk->GetData(); + MxBool decodedColorMap; + + DecodeFLCFrame( + &m_bitmap->GetBitmapInfo()->m_bmiHeader, + m_bitmap->GetBitmapData(), + m_flcHeader, + &dat[offset], + //&(p_chunk->GetData() + 4)[*(MxU32*) p_chunk->GetData()], + &decodedColorMap + ); + + if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && decodedColorMap) + RealizePalette(); + + while (offset > 0) { + dat += 4; + MxRect32 rect( + dat[-4] + m_location.GetX(), + dat[-3] + m_location.GetY(), + dat[-2] + m_location.GetX(), + dat[-1] + m_location.GetY() + ); + MVideoManager()->InvalidateRect(rect); + offset--; + } } // FUNCTION: LEGO1 0x100b3620 diff --git a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp index dcdeba96..b8d9bd45 100644 --- a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp @@ -45,7 +45,7 @@ void MxLoopingFlcPresenter::NextFrame() else { LoadFrame(chunk); LoopChunk(chunk); - m_unk0x68 += m_flicHeader->speed; + m_unk0x68 += m_flcHeader->speed; } m_subscriber->DestroyChunk(chunk);