From 20a9a2b4c33528f24c52e3aaf988ec5b470d4987 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Thu, 21 Dec 2023 10:44:54 -0500 Subject: [PATCH 1/6] implement EnableFullScreenMovie and FUN_100ba640 (#346) * implement EnableFullScreenMovie and FUN_100ba640 * Match MxDisplaySurface::FUN_100ba640 * Match LegoVideoManager::EnableFullScreenMovie --------- Co-authored-by: Christian Semmler --- LEGO1/legovideomanager.cpp | 53 ++++++++++++++++++++++++++++++++++++-- LEGO1/legovideomanager.h | 15 ++++------- LEGO1/mxdisplaysurface.cpp | 41 +++++++++++++++++++++++++++-- LEGO1/mxdisplaysurface.h | 1 + LEGO1/mxpalette.h | 1 + 5 files changed, 97 insertions(+), 14 deletions(-) diff --git a/LEGO1/legovideomanager.cpp b/LEGO1/legovideomanager.cpp index 92440dd4..167b81a3 100644 --- a/LEGO1/legovideomanager.cpp +++ b/LEGO1/legovideomanager.cpp @@ -75,10 +75,53 @@ void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable) EnableFullScreenMovie(p_enable, TRUE); } -// STUB: LEGO1 0x1007c310 +// FUNCTION: LEGO1 0x1007c310 void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) { - // TODO + if (m_isFullscreenMovie != p_enable) { + m_isFullscreenMovie = p_enable; + + if (p_enable) { + m_palette = m_videoParam.GetPalette()->Clone(); + OverrideSkyColor(FALSE); + + m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); + + m_unk0xe4 = FALSE; + m_unk0x500 = TRUE; + } + else { + m_displaySurface->FUN_100ba640(); + m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); + + // restore previous pallete + RealizePalette(m_palette); + delete m_palette; + m_palette = NULL; + + // update region where video used to be + MxRect32 rect( + 0, + 0, + m_videoParam.GetRect().GetRight() - m_videoParam.GetRect().GetLeft(), + m_videoParam.GetRect().GetBottom() - m_videoParam.GetRect().GetTop() + ); + + InvalidateRect(rect); + UpdateRegion(); + OverrideSkyColor(TRUE); + + m_unk0xe4 = TRUE; + m_unk0x500 = FALSE; + } + } + + if (p_enable) { + m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); + } + else { + m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); + } } // FUNCTION: LEGO1 0x1007c440 @@ -97,6 +140,12 @@ void LegoVideoManager::SetSkyColor(float p_red, float p_green, float p_blue) // m_3dManager->m_pViewport->VTable0x1c(red, green, blue) } +// FUNCTION: LEGO1 0x1007c4c0 +void LegoVideoManager::OverrideSkyColor(MxBool p_shouldOverride) +{ + this->m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride); +} + // STUB: LEGO1 0x1007c560 int LegoVideoManager::EnableRMDevice() { diff --git a/LEGO1/legovideomanager.h b/LEGO1/legovideomanager.h index 02558785..11501e2d 100644 --- a/LEGO1/legovideomanager.h +++ b/LEGO1/legovideomanager.h @@ -21,20 +21,15 @@ class LegoVideoManager : public MxVideoManager { __declspec(dllexport) void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale); __declspec(dllexport) void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY); - inline Lego3DManager* Get3DManager() { return this->m_3dManager; } - inline MxDirect3D* GetDirect3D() { return this->m_direct3d; } + virtual void Destroy() override; // vtable+0x18 void SetSkyColor(float p_red, float p_green, float p_blue); + void OverrideSkyColor(MxBool p_shouldOverride); + + inline Lego3DManager* Get3DManager() { return this->m_3dManager; } + inline MxDirect3D* GetDirect3D() { return this->m_direct3d; } inline void SetUnkE4(MxBool p_unk0xe4) { this->m_unk0xe4 = p_unk0xe4; } - // FUNCTION: LEGO1 0x1007c4c0 - void OverrideSkyColor(MxBool p_shouldOverride) - { - this->m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride); - } - - virtual void Destroy() override; // vtable+0x18 - private: undefined4 m_unk0x64; Lego3DManager* m_3dManager; // 0x68 diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index 957bc568..bc1d2078 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -28,10 +28,47 @@ void MxDisplaySurface::Reset() memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); } -// STUB: LEGO1 0x100ba640 +// FUNCTION: LEGO1 0x100ba640 void MxDisplaySurface::FUN_100ba640() { - // TODO + MxS32 backBuffers; + DDSURFACEDESC desc; + HRESULT hr; + + if (!m_videoParam.Flags().GetFlipSurfaces()) { + backBuffers = 1; + } + else { + backBuffers = m_videoParam.GetBackBuffers() + 1; + } + + for (MxS32 i = 0; i < backBuffers; i++) { + memset(&desc, 0, sizeof(DDSURFACEDESC)); + + desc.dwSize = sizeof(DDSURFACEDESC); + hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + m_ddSurface2->Restore(); + hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL); + } + + if (hr != S_OK) { + return; + } + + MxU8* surface = (MxU8*) desc.lpSurface; + MxS32 height = m_videoParam.GetRect().GetHeight(); + + while (height--) { + memset(surface, 0, m_videoParam.GetRect().GetWidth() * desc.ddpfPixelFormat.dwRGBBitCount / 8); + surface += desc.lPitch; + } + + m_ddSurface2->Unlock(desc.lpSurface); + if (m_videoParam.Flags().GetFlipSurfaces()) { + m_ddSurface1->Flip(NULL, 1); + } + } } // FUNCTION: LEGO1 0x100ba790 diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index 280100f4..3d386bb4 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -69,6 +69,7 @@ class MxDisplaySurface : public MxCore { inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } inline LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return this->m_ddSurface2; } + inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } private: MxVideoParam m_videoParam; diff --git a/LEGO1/mxpalette.h b/LEGO1/mxpalette.h index d63b061c..90ffa605 100644 --- a/LEGO1/mxpalette.h +++ b/LEGO1/mxpalette.h @@ -25,6 +25,7 @@ class MxPalette : public MxCore { MxResult SetSkyColor(LPPALETTEENTRY p_skyColor); void Reset(MxBool p_ignoreSkyColor); LPDIRECTDRAWPALETTE CreateNativePalette(); + inline void SetOverrideSkyColor(MxBool p_value) { this->m_overrideSkyColor = p_value; } private: From 71ed20bf11374930ce6e9159ac37e7247aae9481 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 21 Dec 2023 10:52:42 -0500 Subject: [PATCH 2/6] Implement/match rest of MxSmkPresenter (#345) * Implement/match rest of MxSmkPresenter * Fix include guard * Update mxregion.cpp * Match MxRegion::VTable0x18 * Fix * Fix matches * Remove class name --- LEGO1/mxbitmap.h | 1 + LEGO1/mxpoint32.h | 13 ++++++ LEGO1/mxpresenter.h | 2 - LEGO1/mxrect32.h | 76 ++++++++++++++++++++++--------- LEGO1/mxrectlist.h | 86 +++++++++++++++++++++++++++++++++++ LEGO1/mxregion.cpp | 11 ++--- LEGO1/mxsize32.h | 4 ++ LEGO1/mxsmack.cpp | 13 ++++++ LEGO1/mxsmack.h | 10 ++++ LEGO1/mxsmkpresenter.cpp | 27 ++++++++++- LEGO1/mxstillpresenter.cpp | 18 ++++---- LEGO1/mxtransitionmanager.cpp | 12 ++--- LEGO1/mxvideomanager.cpp | 4 +- LEGO1/mxvideopresenter.cpp | 20 ++++---- 14 files changed, 239 insertions(+), 58 deletions(-) create mode 100644 LEGO1/mxrectlist.h diff --git a/LEGO1/mxbitmap.h b/LEGO1/mxbitmap.h index 766c86dd..b87bcdcf 100644 --- a/LEGO1/mxbitmap.h +++ b/LEGO1/mxbitmap.h @@ -65,6 +65,7 @@ class MxBitmap : public MxCore { return m_bmiHeader->biHeight > 0 ? m_bmiHeader->biHeight : -m_bmiHeader->biHeight; } inline MxU8* GetBitmapData() const { return m_data; } + inline MxBITMAPINFO* GetBitmapInfo() const { return m_info; } private: MxResult ImportColorsToPalette(RGBQUAD*, MxPalette*); diff --git a/LEGO1/mxpoint32.h b/LEGO1/mxpoint32.h index 6e066af5..d041e894 100755 --- a/LEGO1/mxpoint32.h +++ b/LEGO1/mxpoint32.h @@ -12,6 +12,19 @@ class MxPoint32 { this->m_y = p_y; } + MxPoint32(const MxPoint32& p_point) + { + this->m_x = p_point.m_x; + this->m_y = p_point.m_y; + } + + inline MxS32 GetX() const { return m_x; } + inline MxS32 GetY() const { return m_y; } + + inline void SetX(MxS32 p_x) { m_x = p_x; } + inline void SetY(MxS32 p_y) { m_y = p_y; } + +private: MxS32 m_x; MxS32 m_y; }; diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index fae7021a..160329c1 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -69,8 +69,6 @@ class MxPresenter : public MxCore { inline MxS32 GetCurrentTickleState() const { return this->m_currentTickleState; } inline MxPoint32 GetLocation() const { return this->m_location; } - inline MxS32 GetLocationX() const { return this->m_location.m_x; } - inline MxS32 GetLocationY() const { return this->m_location.m_y; } inline MxS32 GetDisplayZ() const { return this->m_displayZ; } inline MxDSAction* GetAction() const { return this->m_action; } diff --git a/LEGO1/mxrect32.h b/LEGO1/mxrect32.h index 6deb5095..b54a9d92 100644 --- a/LEGO1/mxrect32.h +++ b/LEGO1/mxrect32.h @@ -18,10 +18,10 @@ class MxRect32 { MxRect32(const MxPoint32& p_point, const MxSize32& p_size) { - this->m_left = p_point.m_x; - this->m_top = p_point.m_y; - this->m_right = p_size.m_width; - this->m_bottom = p_size.m_height; + this->m_left = p_point.GetX(); + this->m_top = p_point.GetY(); + this->m_right = p_size.GetWidth(); + this->m_bottom = p_size.GetHeight(); } MxRect32(const MxRect32& p_a, const MxRect32& p_b) @@ -32,22 +32,40 @@ class MxRect32 { m_bottom = Min(p_a.m_bottom, p_b.m_bottom); } + MxRect32(const MxRect32& p_rect) { CopyFrom(p_rect); } + + MxRect32& operator=(const MxRect32& p_rect) + { + CopyFrom(p_rect); + return *this; + } + + inline void Intersect(const MxRect32& p_rect) + { + m_left = Max(p_rect.m_left, m_left); + m_top = Max(p_rect.m_top, m_top); + m_right = Min(p_rect.m_right, m_right); + m_bottom = Min(p_rect.m_bottom, m_bottom); + } + inline void SetPoint(const MxPoint32& p_point) { - this->m_left = p_point.m_x; - this->m_top = p_point.m_y; + this->m_left = p_point.GetX(); + this->m_top = p_point.GetY(); + } + + inline void AddPoint(const MxPoint32& p_point) + { + this->m_left += p_point.GetX(); + this->m_top += p_point.GetY(); + this->m_right += p_point.GetX(); + this->m_bottom += p_point.GetY(); } inline void SetSize(const MxSize32& p_size) { - this->m_right = p_size.m_width; - this->m_bottom = p_size.m_height; - } - - inline MxBool IsValid() { return m_left < m_right && m_top < m_bottom; } - inline MxBool IntersectsWith(const MxRect32& p_rect) - { - return m_left < p_rect.m_right && p_rect.m_left < m_right && m_top < p_rect.m_bottom && p_rect.m_top < m_bottom; + this->m_right = p_size.GetWidth(); + this->m_bottom = p_size.GetHeight(); } inline void UpdateBounds(const MxRect32& p_rect) @@ -58,16 +76,22 @@ class MxRect32 { m_bottom = Max(m_bottom, p_rect.m_bottom); } - inline MxS32 GetWidth() { return (m_right - m_left) + 1; } - inline MxS32 GetHeight() { return (m_bottom - m_top) + 1; } + inline MxBool IsValid() const { return m_left < m_right && m_top < m_bottom; } + inline MxBool IntersectsWith(const MxRect32& p_rect) const + { + return m_left < p_rect.m_right && p_rect.m_left < m_right && m_top < p_rect.m_bottom && p_rect.m_top < m_bottom; + } - inline MxPoint32 GetPoint() { return MxPoint32(this->m_left, this->m_top); } - inline MxSize32 GetSize() { return MxSize32(this->m_right, this->m_bottom); } + inline MxS32 GetWidth() const { return (m_right - m_left) + 1; } + inline MxS32 GetHeight() const { return (m_bottom - m_top) + 1; } - inline MxS32 GetLeft() { return m_left; } - inline MxS32 GetTop() { return m_top; } - inline MxS32 GetRight() { return m_right; } - inline MxS32 GetBottom() { return m_bottom; } + inline MxPoint32 GetPoint() const { return MxPoint32(this->m_left, this->m_top); } + inline MxSize32 GetSize() const { return MxSize32(this->m_right, this->m_bottom); } + + inline MxS32 GetLeft() const { return m_left; } + inline MxS32 GetTop() const { return m_top; } + inline MxS32 GetRight() const { return m_right; } + inline MxS32 GetBottom() const { return m_bottom; } inline void SetLeft(MxS32 p_left) { m_left = p_left; } inline void SetTop(MxS32 p_top) { m_top = p_top; } @@ -75,6 +99,14 @@ class MxRect32 { inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; } private: + inline void CopyFrom(const MxRect32& p_rect) + { + this->m_left = p_rect.m_left; + this->m_top = p_rect.m_top; + this->m_right = p_rect.m_right; + this->m_bottom = p_rect.m_bottom; + } + inline static MxS32 Min(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_a : p_b; }; inline static MxS32 Max(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_b : p_a; }; diff --git a/LEGO1/mxrectlist.h b/LEGO1/mxrectlist.h new file mode 100644 index 00000000..c0527f01 --- /dev/null +++ b/LEGO1/mxrectlist.h @@ -0,0 +1,86 @@ +#ifndef MXRECTLIST_H +#define MXRECTLIST_H + +#include "mxlist.h" +#include "mxrect32.h" + +// VTABLE: LEGO1 0x100dc3f0 +// SIZE 0x18 +class MxRectList : public MxPtrList { +public: + MxRectList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} +}; + +// VTABLE: LEGO1 0x100dc438 +// class MxListCursor + +// VTABLE: LEGO1 0x100dc408 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100dc420 +class MxRectListCursor : public MxPtrListCursor { +public: + MxRectListCursor(MxRectList* p_list) : MxPtrListCursor(p_list){}; +}; + +// VTABLE: LEGO1 0x100dc3d8 +// class MxPtrList + +// VTABLE: LEGO1 0x100dc450 +// class MxList + +// VTABLE: LEGO1 0x100dc468 +// class MxCollection + +// TEMPLATE: LEGO1 0x100b3c00 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x100b3c10 +// MxCollection::MxCollection + +// TEMPLATE: LEGO1 0x100b3c80 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x100b3cd0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x100b3ce0 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x100b3d70 +// MxPtrList::Destroy + +// SYNTHETIC: LEGO1 0x100b3d80 +// MxRectList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100b3e40 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100b3eb0 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100b3f60 +// MxPtrList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x100b3fd0 +// MxRectList::~MxRectList + +// SYNTHETIC: LEGO1 0x100b4020 +// MxRectListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x100b4090 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x100b40e0 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100b4150 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x100b41c0 +// MxListCursor::~MxListCursor + +// TEMPLATE: LEGO1 0x100b4210 +// MxRectListCursor::~MxRectListCursor + +#endif // MXRECTLIST_H diff --git a/LEGO1/mxregion.cpp b/LEGO1/mxregion.cpp index 0c698413..f003aceb 100644 --- a/LEGO1/mxregion.cpp +++ b/LEGO1/mxregion.cpp @@ -10,8 +10,7 @@ DECOMP_SIZE_ASSERT(MxRegionLeftRight, 0x08); MxRegion::MxRegion() { m_list = new MxRegionList; - m_rect.SetPoint(MxPoint32(INT_MAX, INT_MAX)); - m_rect.SetSize(MxSize32(-1, -1)); + m_rect = MxRect32(INT_MAX, INT_MAX, -1, -1); } // FUNCTION: LEGO1 0x100c3660 @@ -31,14 +30,14 @@ MxRegion::~MxRegion() void MxRegion::Reset() { m_list->DeleteAll(); - m_rect.SetPoint(MxPoint32(INT_MAX, INT_MAX)); - m_rect.SetSize(MxSize32(-1, -1)); + m_rect = MxRect32(INT_MAX, INT_MAX, -1, -1); } // FUNCTION: LEGO1 0x100c3750 void MxRegion::VTable0x18(MxRect32& p_rect) { - MxRect32 rect(p_rect.GetPoint(), MxSize32(p_rect.GetRight(), p_rect.GetBottom())); + MxRect32 rect(p_rect); + MxRect32 newRect; MxRegionListCursor cursor(m_list); MxRegionTopBottom* topBottom; @@ -50,7 +49,7 @@ void MxRegion::VTable0x18(MxRect32& p_rect) } else if (rect.GetTop() < topBottom->GetBottom()) { if (rect.GetTop() < topBottom->GetTop()) { - MxRect32 newRect(rect); + newRect = rect; newRect.SetBottom(topBottom->GetTop()); MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(newRect); cursor.Prepend(newTopBottom); diff --git a/LEGO1/mxsize32.h b/LEGO1/mxsize32.h index a55326cc..a8b30368 100644 --- a/LEGO1/mxsize32.h +++ b/LEGO1/mxsize32.h @@ -12,6 +12,10 @@ class MxSize32 { this->m_height = p_height; } + inline MxS32 GetWidth() const { return m_width; } + inline MxS32 GetHeight() const { return m_height; } + +private: MxS32 m_width; MxS32 m_height; }; diff --git a/LEGO1/mxsmack.cpp b/LEGO1/mxsmack.cpp index f0d320da..63fa361d 100644 --- a/LEGO1/mxsmack.cpp +++ b/LEGO1/mxsmack.cpp @@ -139,3 +139,16 @@ void MxSmack::Destroy(MxSmack* p_mxSmack) if (p_mxSmack->m_unk0x6b4) delete[] p_mxSmack->m_unk0x6b4; } + +// STUB: LEGO1 0x100c5db0 +void MxSmack::FUN_100c5db0( + MxBITMAPINFO* p_bitmapInfo, + MxU8* p_bitmapData, + MxSmack* p_mxSmack, + MxU8* p_chunkData, + MxBool p_und, + MxRectList* p_list +) +{ + // TODO +} diff --git a/LEGO1/mxsmack.h b/LEGO1/mxsmack.h index b7e00c2a..b89195d8 100644 --- a/LEGO1/mxsmack.h +++ b/LEGO1/mxsmack.h @@ -2,6 +2,8 @@ #define MXSMACK_H #include "decomp.h" +#include "mxbitmap.h" +#include "mxrectlist.h" #include "mxtypes.h" #include @@ -40,6 +42,14 @@ struct MxSmack { static MxResult LoadHeaderAndTrees(MxU8* p_data, MxSmack* p_mxSmack); static void Destroy(MxSmack* p_mxSmack); + static void FUN_100c5db0( + MxBITMAPINFO* p_bitmapInfo, + MxU8* p_bitmapData, + MxSmack* p_mxSmack, + MxU8* p_chunkData, + MxBool p_und, + MxRectList* p_list + ); }; #endif // MXSMACK_H diff --git a/LEGO1/mxsmkpresenter.cpp b/LEGO1/mxsmkpresenter.cpp index f517f41d..613d7050 100644 --- a/LEGO1/mxsmkpresenter.cpp +++ b/LEGO1/mxsmkpresenter.cpp @@ -1,6 +1,7 @@ #include "mxsmkpresenter.h" #include "decomp.h" +#include "mxdsmediaaction.h" #include "mxvideomanager.h" DECOMP_SIZE_ASSERT(MxSmkPresenter, 0x720); @@ -57,10 +58,32 @@ void MxSmkPresenter::CreateBitmap() m_bitmap->SetSize(m_mxSmack.m_smackTag.Width, m_mxSmack.m_smackTag.Height, NULL, FALSE); } -// STUB: LEGO1 0x100b3a00 +// FUNCTION: LEGO1 0x100b3a00 void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk) { - // TODO + MxBITMAPINFO* bitmapInfo = m_bitmap->GetBitmapInfo(); + MxU8* bitmapData = m_bitmap->GetBitmapData(); + MxU8* chunkData = p_chunk->GetData(); + + MxBool und = m_mxSmack.m_frameTypes[m_unk0x71c] & 1; + m_unk0x71c++; + VTable0x88(); + + MxRectList list(TRUE); + MxSmack::FUN_100c5db0(bitmapInfo, bitmapData, &m_mxSmack, chunkData, und, &list); + + if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && und) + RealizePalette(); + + MxRect32 invalidateRect; + MxRectListCursor cursor(&list); + MxRect32* rect; + + while (cursor.Next(rect)) { + invalidateRect = *rect; + invalidateRect.AddPoint(GetLocation()); + MVideoManager()->InvalidateRect(invalidateRect); + } } // FUNCTION: LEGO1 0x100b4260 diff --git a/LEGO1/mxstillpresenter.cpp b/LEGO1/mxstillpresenter.cpp index 285e2cd4..5474f8e3 100644 --- a/LEGO1/mxstillpresenter.cpp +++ b/LEGO1/mxstillpresenter.cpp @@ -73,8 +73,8 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) MxS32 height = GetHeight() - 1; MxS32 width = GetWidth() - 1; - MxS32 x = m_location.m_x; - MxS32 y = m_location.m_y; + MxS32 x = m_location.GetX(); + MxS32 y = m_location.GetY(); MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); @@ -148,17 +148,17 @@ void MxStillPresenter::RepeatingTickle() // FUNCTION: LEGO1 0x100ba040 void MxStillPresenter::VTable0x88(MxS32 p_x, MxS32 p_y) { - MxS32 x = m_location.m_x; - MxS32 y = m_location.m_y; - m_location.m_x = p_x; - m_location.m_y = p_y; + MxS32 x = m_location.GetX(); + MxS32 y = m_location.GetY(); + m_location.SetX(p_x); + m_location.SetY(p_y); if (IsEnabled()) { MxS32 height = GetHeight() - 1; MxS32 width = GetWidth() - 1; MxRect32 rectA(x, y, width + x, height + y); - MxRect32 rectB(m_location.m_x, m_location.m_y, width + m_location.m_x, height + m_location.m_y); + MxRect32 rectB(m_location.GetX(), m_location.GetY(), width + m_location.GetX(), height + m_location.GetY()); MVideoManager()->InvalidateRect(rectA); MVideoManager()->VTable0x34(rectA.GetLeft(), rectA.GetTop(), rectA.GetWidth(), rectA.GetHeight()); @@ -176,8 +176,8 @@ void MxStillPresenter::Enable(MxBool p_enable) if (MVideoManager() && (m_alpha || m_bitmap)) { MxS32 height = GetHeight(); MxS32 width = GetWidth(); - MxS32 x = m_location.m_x; - MxS32 y = m_location.m_y; + MxS32 x = m_location.GetX(); + MxS32 y = m_location.GetY(); MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); diff --git a/LEGO1/mxtransitionmanager.cpp b/LEGO1/mxtransitionmanager.cpp index b319e6c9..b10ac7c1 100644 --- a/LEGO1/mxtransitionmanager.cpp +++ b/LEGO1/mxtransitionmanager.cpp @@ -541,8 +541,8 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) (m_copyRect.right - m_copyRect.left + 1); // This uses m_copyRect, seemingly erroneously MxU32 bytesPerPixel = p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8; - m_copyRect.left = m_waitIndicator->GetLocationX(); - m_copyRect.top = m_waitIndicator->GetLocationY(); + m_copyRect.left = m_waitIndicator->GetLocation().GetX(); + m_copyRect.top = m_waitIndicator->GetLocation().GetY(); MxS32 height = m_waitIndicator->GetHeight(); MxS32 width = m_waitIndicator->GetWidth(); @@ -577,8 +577,8 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) m_waitIndicator->GetBitmap(), 0, 0, - m_waitIndicator->GetLocationX(), - m_waitIndicator->GetLocationY(), + m_waitIndicator->GetLocation().GetX(), + m_waitIndicator->GetLocation().GetY(), m_waitIndicator->GetWidth(), m_waitIndicator->GetHeight(), und @@ -591,8 +591,8 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) m_waitIndicator->GetBitmap(), 0, 0, - m_waitIndicator->GetLocationX(), - m_waitIndicator->GetLocationY(), + m_waitIndicator->GetLocation().GetX(), + m_waitIndicator->GetLocation().GetY(), m_waitIndicator->GetWidth(), m_waitIndicator->GetHeight() ); diff --git a/LEGO1/mxvideomanager.cpp b/LEGO1/mxvideomanager.cpp index bd4965b9..aa2158f0 100644 --- a/LEGO1/mxvideomanager.cpp +++ b/LEGO1/mxvideomanager.cpp @@ -75,7 +75,9 @@ void MxVideoManager::Destroy(MxBool p_fromDestructor) void MxVideoManager::UpdateRegion() { if (m_region->VTable0x20() == FALSE) { - MxRect32 rect(m_region->GetRect(), m_videoParam.GetRect()); + MxRect32 rect(m_region->GetRect()); + rect.Intersect(m_videoParam.GetRect()); + m_displaySurface ->Display(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); } diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index 3c3f7530..259d8651 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -217,8 +217,8 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) MxS32 height = GetHeight(); MxS32 width = GetWidth(); - MxS32 x = GetLocationX(); - MxS32 y = GetLocationY(); + MxS32 x = m_location.GetX(); + MxS32 y = m_location.GetY(); MxRect32 rect(x, y, x + width, y + height); MVideoManager()->InvalidateRect(rect); @@ -259,12 +259,12 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) return FALSE; if (!m_bitmap) - return m_alpha->IsHit(p_x - GetLocationX(), p_y - GetLocationY()); + return m_alpha->IsHit(p_x - m_location.GetX(), p_y - m_location.GetY()); MxLong heightAbs = m_bitmap->GetBmiHeightAbs(); - MxLong minX = GetLocationX(); - MxLong minY = GetLocationY(); + MxLong minX = m_location.GetX(); + MxLong minY = m_location.GetY(); MxLong maxY = minY + heightAbs; MxLong maxX = minX + m_bitmap->GetBmiWidth(); @@ -285,13 +285,13 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) // the MxPresenter location x and y coordinates. if (biCompression == BI_RGB) { if (biCompression == BI_RGB_TOPDOWN || height < 0) { - seekRow = p_y - GetLocationY(); + seekRow = p_y - m_location.GetY(); } else { height = height > 0 ? height : -height; - seekRow = height - p_y - 1 + GetLocationY(); + seekRow = height - p_y - 1 + m_location.GetY(); } - pixel = m_bitmap->GetBmiStride() * seekRow + m_bitmap->GetBitmapData() - GetLocationX() + p_x; + pixel = m_bitmap->GetBmiStride() * seekRow + m_bitmap->GetBitmapData() - m_location.GetX() + p_x; } else if (biCompression == BI_RGB_TOPDOWN) { pixel = m_bitmap->GetBitmapData(); @@ -466,8 +466,8 @@ void MxVideoPresenter::EndAction() if (m_bitmap) { MxLong height = m_bitmap->GetBmiHeightAbs(); MxLong width = m_bitmap->GetBmiWidth(); - MxS32 x = m_location.m_x; - MxS32 y = m_location.m_y; + MxS32 x = m_location.GetX(); + MxS32 y = m_location.GetY(); MxRect32 rect(x, y, x + width, y + height); From 2c018c117c1968cb933927046108e0067adeb7fb Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Thu, 21 Dec 2023 10:59:26 -0500 Subject: [PATCH 3/6] Implement Helicopter subclass (#336) * Implement Helicopter subclass * Minor fixes --------- Co-authored-by: Christian Semmler --- LEGO1/helicopter.cpp | 48 ++++++++++++++++++++++++++++++++++++++--- LEGO1/realtime/vector.h | 4 +++- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/LEGO1/helicopter.cpp b/LEGO1/helicopter.cpp index 2d13e011..87ee1dcb 100644 --- a/LEGO1/helicopter.cpp +++ b/LEGO1/helicopter.cpp @@ -233,7 +233,7 @@ MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) Matrix4 mat2 = mat.GetMatrix(); float s = sin(0.5235987901687622); // PI / 6, 30 deg float c = cos(0.5235987901687622); // PI / 6, 30 deg - for (int i = 0; i < 4; i++) { + for (MxS32 i = 0; i < 4; i++) { mat.GetMatrix()[i][1] = mat2[i][1] * c - mat2[i][2] * s; mat.GetMatrix()[i][2] = mat2[i][2] * c + mat2[i][1] * s; } @@ -321,8 +321,50 @@ void Helicopter::VTable0x70(float p_float) } } -// STUB: LEGO1 0x100040a0 +// FUNCTION: LEGO1 0x100040a0 MxResult HelicopterSubclass::FUN_100040a0(Vector4Impl& p_v, float p_f) { - return SUCCESS; + MxU32 state = m_unk0x30; + if (state == 1) { + p_v.EqualsImpl(m_unk0x0.GetVector().elements); + p_v[3] = acos(p_v[3]) * (1 - p_f) * 2.0; + return p_v.NormalizeQuaternion(); + } + else if (state == 2) { + p_v.EqualsImpl(m_unk0x18.GetVector().elements); + p_v[3] = acos(p_v[3]) * p_f * 2.0; + p_v.NormalizeQuaternion(); + return p_v.NormalizeQuaternion(); + } + else if (state == 3) { + double d1 = p_v.Dot(&m_unk0x0, &m_unk0x18), d2; + if (d1 + 1 > 0.00001) { + if (1 - d1 > 0.00001) { + double d = acos(d1); + sin(d); + d1 = sin((1 - p_f) * d) / sin(d); + d2 = sin(p_f * d) / sin(d); + } + else { + d1 = 1 - p_f; + d2 = p_f; + } + for (MxS32 i = 0; i < 4; i++) { + p_v[i] = m_unk0x18[i] * d2 + m_unk0x0[i] * d1; + } + return SUCCESS; + } + p_v[0] = -m_unk0x0[1]; + p_v[1] = m_unk0x0[1]; + p_v[2] = -m_unk0x0[3]; + p_v[3] = m_unk0x0[2]; + d1 = sin((1 - p_f) * 1.570796326794895); + d2 = sin(p_f * 1.570796326794895); + for (MxS32 i = 0; i < 3; i++) { + p_v[i] = m_unk0x0[i] * d1 + p_v[i] * d2; + } + return SUCCESS; + } + else + return FAILURE; } diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 3f61fb9a..5c31f24e 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -174,11 +174,13 @@ class Vector4Impl : public Vector3Impl { void EqualsScalar(float* p_value); - // vtable + 0x84 + // vtable + 0x88 virtual void SetMatrixProduct(Vector4Impl* p_a, float* p_b); virtual void SetMatrixProductImpl(float* p_vec, float* p_mat); virtual int NormalizeQuaternion(); virtual void UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b); + + inline Vector4& GetVector() { return *((Vector4*) m_data); } }; // VTABLE: LEGO1 0x100d4488 From 6d0d308c37e4b2d3bb304cd6a874a8e5facb1f6f Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Thu, 21 Dec 2023 13:21:56 -0500 Subject: [PATCH 4/6] Add unknown render class stub (#347) * Add mxrender manager class stub * fix format * rename the class * Update MxUnknown100dbdbc.cpp * rename class * fix clang format * Remove accidently committed code * Update LEGO1/legoomni.cpp Co-authored-by: Joshua Peisach * fix * fix 2 --------- Co-authored-by: Joshua Peisach --- CMakeLists.txt | 1 + LEGO1/legoomni.cpp | 14 ++++++++------ LEGO1/legoomni.h | 3 ++- LEGO1/mxunknown100dbdbc.cpp | 11 +++++++++++ LEGO1/mxunknown100dbdbc.h | 17 +++++++++++++++++ 5 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 LEGO1/mxunknown100dbdbc.cpp create mode 100644 LEGO1/mxunknown100dbdbc.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d70c0626..3650c718 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,7 @@ add_library(lego1 SHARED LEGO1/mxtimer.cpp LEGO1/mxtransitionmanager.cpp LEGO1/mxtype17notificationparam.cpp + LEGO1/mxunknown100dbdbc.cpp LEGO1/mxvariable.cpp LEGO1/mxvariabletable.cpp LEGO1/mxvideomanager.cpp diff --git a/LEGO1/legoomni.cpp b/LEGO1/legoomni.cpp index 53bb07ef..cd3438a7 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/legoomni.cpp @@ -21,6 +21,7 @@ #include "mxomnicreateparam.h" #include "mxticklemanager.h" #include "mxtransitionmanager.h" +#include "mxunknown100dbdbc.h" DECOMP_SIZE_ASSERT(LegoWorldList, 0x18); @@ -385,7 +386,7 @@ void LegoOmni::Init() MxOmni::Init(); m_unk0x68 = 0; m_inputMgr = NULL; - m_unk0x6c = 0; + m_renderMgr = NULL; m_gifManager = NULL; m_worldList = NULL; m_currentWorld = NULL; @@ -443,9 +444,9 @@ void LegoOmni::Destroy() m_gifManager = NULL; } - if (m_unk0x6c) { - // delete m_unk0x6c; // TODO - m_unk0x6c = NULL; + if (m_renderMgr) { + delete m_renderMgr; + m_renderMgr = NULL; } if (m_inputMgr) { @@ -523,15 +524,16 @@ MxResult LegoOmni::Create(MxOmniCreateParam& p_param) } } - // TODO: there are a few more classes here + m_renderMgr = new MxUnknown100dbdbc(); m_gifManager = new GifManager(); + // TODO: there is another class here m_plantManager = new LegoPlantManager(); m_animationManager = new LegoAnimationManager(); m_buildingManager = new LegoBuildingManager(); m_gameState = new LegoGameState(); m_worldList = new LegoWorldList(TRUE); - if (m_unk0x6c && m_gifManager && m_worldList && m_plantManager && m_animationManager && m_buildingManager) { + if (m_renderMgr && m_gifManager && m_worldList && m_plantManager && m_animationManager && m_buildingManager) { // TODO: initialize a bunch of MxVariables RegisterScripts(); FUN_1001a700(); diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index 4edaeb35..69f6964a 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -27,6 +27,7 @@ class MxAtomId; class MxBackgroundAudioManager; class MxDSFile; class MxTransitionManager; +class MxUnknown100dbdbc; extern MxAtomId* g_copterScript; extern MxAtomId* g_dunecarScript; @@ -116,7 +117,7 @@ class LegoOmni : public MxOmni { private: undefined4* m_unk0x68; // 0x68 - undefined4 m_unk0x6c; // 0x6c + MxUnknown100dbdbc* m_renderMgr; // 0x6c LegoInputManager* m_inputMgr; // 0x70 GifManager* m_gifManager; // 0x74 LegoWorldList* m_worldList; // 0x78 diff --git a/LEGO1/mxunknown100dbdbc.cpp b/LEGO1/mxunknown100dbdbc.cpp new file mode 100644 index 00000000..a420454a --- /dev/null +++ b/LEGO1/mxunknown100dbdbc.cpp @@ -0,0 +1,11 @@ +#include "mxunknown100dbdbc.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxUnknown100dbdbc, 0x14) + +// STUB: LEGO1 0x100a6fd0 +MxUnknown100dbdbc::MxUnknown100dbdbc() +{ + // TODO +} diff --git a/LEGO1/mxunknown100dbdbc.h b/LEGO1/mxunknown100dbdbc.h new file mode 100644 index 00000000..157058a7 --- /dev/null +++ b/LEGO1/mxunknown100dbdbc.h @@ -0,0 +1,17 @@ +#ifndef MXUNKNOWN100DBDBC_H +#define MXUNKNOWN100DBDBC_H + +#include "decomp.h" +#include "mxtypes.h" + +// VTABLE: LEGO1 0x100dbdbc +// SIZE 0x14 +class MxUnknown100dbdbc { +public: + MxUnknown100dbdbc(); + +private: + undefined m_unk0x4[0x14]; // TODO: change to 0x10 once scalar deconstructor is added +}; + +#endif // MXUNKNOWN100DBDBC_H From c51aed256bab6d9001102625810eaac02a93fca6 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 21 Dec 2023 21:11:14 -0500 Subject: [PATCH 5/6] Implement/match MxSmack::LoadFrame (#348) --- LEGO1/mxsmack.cpp | 88 ++++++++++++++++++++++++++++++++++++---- LEGO1/mxsmack.h | 10 +++-- LEGO1/mxsmkpresenter.cpp | 10 ++--- 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/LEGO1/mxsmack.cpp b/LEGO1/mxsmack.cpp index 63fa361d..8a1c8fde 100644 --- a/LEGO1/mxsmack.cpp +++ b/LEGO1/mxsmack.cpp @@ -6,7 +6,7 @@ DECOMP_SIZE_ASSERT(SmackTag, 0x390); DECOMP_SIZE_ASSERT(MxSmack, 0x6b8); // FUNCTION: LEGO1 0x100c5a90 -MxResult MxSmack::LoadHeaderAndTrees(MxU8* p_data, MxSmack* p_mxSmack) +MxResult MxSmack::LoadHeader(MxU8* p_data, MxSmack* p_mxSmack) { // Macros for readability #define FRAME_COUNT(mxSmack) (p_mxSmack->m_smackTag.Frames + (p_mxSmack->m_smackTag.SmackerType & 1)) @@ -82,8 +82,7 @@ MxResult MxSmack::LoadHeaderAndTrees(MxU8* p_data, MxSmack* p_mxSmack) p_mxSmack->m_smackTag.typesize ); - MxU32 size = - ::SmackGetSizeDeltas(p_mxSmack->m_smackTag.Width, p_mxSmack->m_smackTag.Height) + 32; + MxU32 size = SmackGetSizeDeltas(p_mxSmack->m_smackTag.Width, p_mxSmack->m_smackTag.Height) + 32; p_mxSmack->m_unk0x6b4 = new MxU8[size]; memset(p_mxSmack->m_unk0x6b4, 0, size); @@ -92,7 +91,7 @@ MxResult MxSmack::LoadHeaderAndTrees(MxU8* p_data, MxSmack* p_mxSmack) *data = 1; data++; - *data = 0; + *data = NULL; // MxU8* bitmapData data++; *data = p_mxSmack->m_smackTag.Width / 4; data++; @@ -140,15 +139,88 @@ void MxSmack::Destroy(MxSmack* p_mxSmack) delete[] p_mxSmack->m_unk0x6b4; } -// STUB: LEGO1 0x100c5db0 -void MxSmack::FUN_100c5db0( +// This should be refactored to somewhere else +inline MxLong AbsFlipped(MxLong p_value) +{ + return p_value > 0 ? p_value : -p_value; +} + +// FUNCTION: LEGO1 0x100c5db0 +MxResult MxSmack::LoadFrame( MxBITMAPINFO* p_bitmapInfo, MxU8* p_bitmapData, MxSmack* p_mxSmack, MxU8* p_chunkData, - MxBool p_und, + MxBool p_paletteChanged, MxRectList* p_list ) { - // TODO + p_bitmapInfo->m_bmiHeader.biHeight = -AbsFlipped(p_bitmapInfo->m_bmiHeader.biHeight); + *(MxU8**) (p_mxSmack->m_unk0x6b4 + 4) = p_bitmapData; + + // Reference: https://wiki.multimedia.cx/index.php/Smacker#Palette_Chunk + if (p_paletteChanged) { + MxU8 palette[772]; + + MxU8* intoChunk = p_chunkData + 1; + MxU8* intoPalette = palette; + MxU16 paletteIndex = 0; + // TODO: struct incorrect, Palette at wrong offset? + MxU8* currentPalette = &p_mxSmack->m_smackTag.Palette[4]; + + do { + if (*intoChunk & 0x80) { + MxU8 length = (*intoChunk & 0x7f) + 1; + memcpy(intoPalette, ¤tPalette[paletteIndex * 3], length * 3); + intoPalette += length * 3; + paletteIndex += length; + intoChunk++; + } + else { + if (*intoChunk & 0x40) { + MxU8 length = (*intoChunk & 0x3f) + 1; + memcpy(intoPalette, ¤tPalette[*(intoChunk + 1) * 3], length * 3); + intoPalette += length * 3; + paletteIndex += length; + intoChunk += 2; + } + else { + *(MxU32*) intoPalette = *(MxU32*) intoChunk; + intoPalette += 3; + paletteIndex++; + intoChunk += 3; + } + } + } while (paletteIndex < 256); + + for (MxU32 i = 0; i < 256; i++) { + memcpy(currentPalette, &palette[i * 3], 3); + currentPalette += 3; + p_bitmapInfo->m_bmiColors[i].rgbBlue = palette[i * 3 + 2] * 4; + p_bitmapInfo->m_bmiColors[i].rgbGreen = palette[i * 3 + 1] * 4; + p_bitmapInfo->m_bmiColors[i].rgbRed = palette[i * 3] * 4; + } + + p_chunkData += *p_chunkData * 4; + } + + SmackDoFrameToBuffer(p_chunkData, p_mxSmack->m_huffmanTables, p_mxSmack->m_unk0x6b4); + + MxS16 und1 = 1; + MxU32 und2[4]; + MxRect32 rect; + + while (FUN_100c6050(p_mxSmack->m_unk0x6b4, &und1, und2, &rect)) { + MxRect32* newRect = new MxRect32(rect); + p_list->Append(newRect); + } + + return SUCCESS; +} + +// STUB: LEGO1 0x100c6050 +MxBool MxSmack::FUN_100c6050(MxU8* p_unk0x6b4, MxS16* p_und1, MxU32* p_und2, MxRect32* p_rect) +{ + // TODO + return TRUE; } diff --git a/LEGO1/mxsmack.h b/LEGO1/mxsmack.h index b89195d8..b5e34781 100644 --- a/LEGO1/mxsmack.h +++ b/LEGO1/mxsmack.h @@ -25,6 +25,9 @@ extern "C" u32 p_typeSize ); + // (SMACK.LIB) FUNCTION: LEGO1 0x100cda83 + void SmackDoFrameToBuffer(u8* p_source, u8* p_huffmanTables, u8* p_unk0x6b4); + // (SMACK.LIB) FUNCTION: LEGO1 0x100d052c u32 SmackGetSizeDeltas(u32 p_width, u32 p_height); } @@ -40,16 +43,17 @@ struct MxSmack { MxU32 m_maxFrameSize; // 0x6b0 MxU8* m_unk0x6b4; // 0x6b4 - static MxResult LoadHeaderAndTrees(MxU8* p_data, MxSmack* p_mxSmack); + static MxResult LoadHeader(MxU8* p_data, MxSmack* p_mxSmack); static void Destroy(MxSmack* p_mxSmack); - static void FUN_100c5db0( + static MxResult LoadFrame( MxBITMAPINFO* p_bitmapInfo, MxU8* p_bitmapData, MxSmack* p_mxSmack, MxU8* p_chunkData, - MxBool p_und, + MxBool p_paletteChanged, MxRectList* p_list ); + static MxBool FUN_100c6050(MxU8* p_unk0x6b4, MxS16* p_und1, MxU32* p_und2, MxRect32* p_rect); }; #endif // MXSMACK_H diff --git a/LEGO1/mxsmkpresenter.cpp b/LEGO1/mxsmkpresenter.cpp index 613d7050..442e59a7 100644 --- a/LEGO1/mxsmkpresenter.cpp +++ b/LEGO1/mxsmkpresenter.cpp @@ -45,7 +45,7 @@ void MxSmkPresenter::Destroy(MxBool p_fromDestructor) // FUNCTION: LEGO1 0x100b3940 void MxSmkPresenter::LoadHeader(MxStreamChunk* p_chunk) { - MxSmack::LoadHeaderAndTrees(p_chunk->GetData(), &m_mxSmack); + MxSmack::LoadHeader(p_chunk->GetData(), &m_mxSmack); } // FUNCTION: LEGO1 0x100b3960 @@ -65,14 +65,14 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk) MxU8* bitmapData = m_bitmap->GetBitmapData(); MxU8* chunkData = p_chunk->GetData(); - MxBool und = m_mxSmack.m_frameTypes[m_unk0x71c] & 1; + MxBool paletteChanged = m_mxSmack.m_frameTypes[m_unk0x71c] & 1; m_unk0x71c++; VTable0x88(); MxRectList list(TRUE); - MxSmack::FUN_100c5db0(bitmapInfo, bitmapData, &m_mxSmack, chunkData, und, &list); + MxSmack::LoadFrame(bitmapInfo, bitmapData, &m_mxSmack, chunkData, paletteChanged, &list); - if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && und) + if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && paletteChanged) RealizePalette(); MxRect32 invalidateRect; @@ -98,7 +98,7 @@ void MxSmkPresenter::VTable0x88() if (m_mxSmack.m_smackTag.Frames == m_unk0x71c) { m_unk0x71c = 0; // TODO: struct incorrect, Palette at wrong offset? - memset(m_mxSmack.m_smackTag.Palette, 0, sizeof(m_mxSmack.m_smackTag.Palette)); + memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette)); } } } From acdaf4ed4c1c9f13c4db734405a2f4e4ba591886 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 22 Dec 2023 07:26:54 -0500 Subject: [PATCH 6/6] Finish implementation of MxSmack (#349) * Finish implementation of MxSmack * Fix var name --- LEGO1/mxsmack.cpp | 38 ++++++++++++++++++++++++++++++++------ LEGO1/mxsmack.h | 5 ++++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/LEGO1/mxsmack.cpp b/LEGO1/mxsmack.cpp index 8a1c8fde..551b87c9 100644 --- a/LEGO1/mxsmack.cpp +++ b/LEGO1/mxsmack.cpp @@ -206,11 +206,11 @@ MxResult MxSmack::LoadFrame( SmackDoFrameToBuffer(p_chunkData, p_mxSmack->m_huffmanTables, p_mxSmack->m_unk0x6b4); - MxS16 und1 = 1; - MxU32 und2[4]; + MxU16 und = 1; + u32 smackRect[4]; MxRect32 rect; - while (FUN_100c6050(p_mxSmack->m_unk0x6b4, &und1, und2, &rect)) { + while (GetRect(p_mxSmack->m_unk0x6b4, &und, smackRect, &rect)) { MxRect32* newRect = new MxRect32(rect); p_list->Append(newRect); } @@ -218,9 +218,35 @@ MxResult MxSmack::LoadFrame( return SUCCESS; } -// STUB: LEGO1 0x100c6050 -MxBool MxSmack::FUN_100c6050(MxU8* p_unk0x6b4, MxS16* p_und1, MxU32* p_und2, MxRect32* p_rect) +// FUNCTION: LEGO1 0x100c6050 +MxBool MxSmack::GetRect(MxU8* p_unk0x6b4, MxU16* p_und, u32* p_smackRect, MxRect32* p_rect) { - // TODO + u32 left, bottom, top, right; + + if (!*p_und) + return FALSE; + + if (*p_und == 1) { + if (!SmackGetRect(p_unk0x6b4, p_smackRect)) + return FALSE; + *p_und = 2; + } + + left = p_smackRect[0]; + top = p_smackRect[1]; + right = p_smackRect[2] + p_smackRect[0]; + bottom = p_smackRect[3] + p_smackRect[1]; + + while (SmackGetRect(p_unk0x6b4, p_smackRect)) { + if (left > p_smackRect[0]) + left = p_smackRect[0]; + if (right < p_smackRect[0] + p_smackRect[2]) + right = p_smackRect[0] + p_smackRect[2]; + + bottom = p_smackRect[1] + p_smackRect[3]; + } + + *p_und = 0; + *p_rect = MxRect32(left, top, right, bottom); return TRUE; } diff --git a/LEGO1/mxsmack.h b/LEGO1/mxsmack.h index b5e34781..e0f8c76e 100644 --- a/LEGO1/mxsmack.h +++ b/LEGO1/mxsmack.h @@ -30,6 +30,9 @@ extern "C" // (SMACK.LIB) FUNCTION: LEGO1 0x100d052c u32 SmackGetSizeDeltas(u32 p_width, u32 p_height); + + // (SMACK.LIB) FUNCTION: LEGO1 0x100d0543 + u8 SmackGetRect(u8* p_unk0x6b4, u32* p_rect); } // SIZE 0x6b8 @@ -53,7 +56,7 @@ struct MxSmack { MxBool p_paletteChanged, MxRectList* p_list ); - static MxBool FUN_100c6050(MxU8* p_unk0x6b4, MxS16* p_und1, MxU32* p_und2, MxRect32* p_rect); + static MxBool GetRect(MxU8* p_unk0x6b4, MxU16* p_und, u32* p_smackRect, MxRect32* p_rect); }; #endif // MXSMACK_H