From d5658efe02c3ddf9e39beb5e61603a5c1b50b4d7 Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Fri, 19 Jan 2024 09:38:06 -0500 Subject: [PATCH] Finish Bitmap (#458) * Finish Bitmap * Add missing vtable annotations * Fixes --------- Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/infocenterstate.h | 2 +- LEGO1/omni/include/mxbitmap.h | 42 +++++++++- LEGO1/omni/include/mxutil.h | 18 ++-- LEGO1/omni/src/common/mxutil.cpp | 50 +++++------ LEGO1/omni/src/video/mxbitmap.cpp | 83 ++++++++++++++++++- LEGO1/omni/src/video/mxdisplaysurface.cpp | 2 +- 6 files changed, 154 insertions(+), 43 deletions(-) diff --git a/LEGO1/lego/legoomni/include/infocenterstate.h b/LEGO1/lego/legoomni/include/infocenterstate.h index 4f92b508..8314529f 100644 --- a/LEGO1/lego/legoomni/include/infocenterstate.h +++ b/LEGO1/lego/legoomni/include/infocenterstate.h @@ -3,7 +3,7 @@ #include "decomp.h" #include "legostate.h" -#include "mxstillpresenter.h"; +#include "mxstillpresenter.h" // VTABLE: LEGO1 0x100d93a8 // SIZE 0x94 diff --git a/LEGO1/omni/include/mxbitmap.h b/LEGO1/omni/include/mxbitmap.h index b88a1976..f17ddb4b 100644 --- a/LEGO1/omni/include/mxbitmap.h +++ b/LEGO1/omni/include/mxbitmap.h @@ -44,10 +44,26 @@ class MxBitmap : public MxCore { __declspec(dllexport) virtual MxLong Read(const char* p_filename); // vtable+24 // FUNCTION: LEGO1 0x1004e0d0 - virtual int VTable0x28(int) { return -1; }; + virtual int VTable0x28(int) { return -1; }; // vtable+28 - virtual void VTable0x2c(int, int, int, int, int, int, int); - virtual void VTable0x30(int, int, int, int, int, int, int); + virtual void BitBlt( + MxBitmap* p_src, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height + ); // vtable+2c + virtual void BitBltTransparent( + MxBitmap* p_src, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height + ); // vtable+30 __declspec(dllexport) virtual MxPalette* CreatePalette(); // vtable+34 virtual void ImportPalette(MxPalette* p_palette); // vtable+38 virtual MxResult SetBitDepth(MxBool); // vtable+3c @@ -92,6 +108,26 @@ class MxBitmap : public MxCore { return -GetBmiStride(); } + inline MxLong GetLine(MxS32 p_top) + { + MxS32 height; + if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) + height = p_top; + else + height = GetBmiHeightAbs() - p_top - 1; + return GetBmiStride() * height; + } + + inline MxU8* GetStart(MxS32 p_left, MxS32 p_top) + { + if (m_bmiHeader->biCompression == BI_RGB) + return GetLine(p_top) + m_data + p_left; + else if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) + return m_data; + else + return GetLine(0) + m_data; + } + // SYNTHETIC: LEGO1 0x100bc9f0 // MxBitmap::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxutil.h b/LEGO1/omni/include/mxutil.h index bd0247fd..5eb0a984 100644 --- a/LEGO1/omni/include/mxutil.h +++ b/LEGO1/omni/include/mxutil.h @@ -56,15 +56,15 @@ inline void GetString(MxU8** p_source, char** p_dest, T* p_obj, void (T::*p_sett *p_source += strlen(*p_dest) + 1; } -MxBool FUN_100b6e10( - MxS32 p_bitmapWidth, - MxS32 p_bitmapHeight, - MxS32 p_videoParamWidth, - MxS32 p_videoParamHeight, - MxS32* p_left, - MxS32* p_top, - MxS32* p_right, - MxS32* p_bottom, +MxBool GetRectIntersection( + MxS32 p_rect1Width, + MxS32 p_rect1Height, + MxS32 p_rect2Width, + MxS32 p_rect2Height, + MxS32* p_rect1Left, + MxS32* p_rect1Top, + MxS32* p_rect2Left, + MxS32* p_rect2Top, MxS32* p_width, MxS32* p_height ); diff --git a/LEGO1/omni/src/common/mxutil.cpp b/LEGO1/omni/src/common/mxutil.cpp index ababdc02..29b71863 100644 --- a/LEGO1/omni/src/common/mxutil.cpp +++ b/LEGO1/omni/src/common/mxutil.cpp @@ -11,45 +11,45 @@ void (*g_omniUserMessage)(const char*, int); // FUNCTION: LEGO1 0x100b6e10 -MxBool FUN_100b6e10( - MxS32 p_bitmapWidth, - MxS32 p_bitmapHeight, - MxS32 p_videoParamWidth, - MxS32 p_videoParamHeight, - MxS32* p_left, - MxS32* p_top, - MxS32* p_right, - MxS32* p_bottom, +MxBool GetRectIntersection( + MxS32 p_rect1Width, + MxS32 p_rect1Height, + MxS32 p_rect2Width, + MxS32 p_rect2Height, + MxS32* p_rect1Left, + MxS32* p_rect1Top, + MxS32* p_rect2Left, + MxS32* p_rect2Top, MxS32* p_width, MxS32* p_height ) { - MxPoint32 topLeft(*p_left, *p_top); - MxRect32 bitmapRect(MxPoint32(0, 0), MxSize32(p_bitmapWidth, p_bitmapHeight)); + MxPoint32 rect1Origin(*p_rect1Left, *p_rect1Top); + MxRect32 rect1(MxPoint32(0, 0), MxSize32(p_rect1Width, p_rect1Height)); - MxPoint32 bottomRight(*p_right, *p_bottom); - MxRect32 videoParamRect(MxPoint32(0, 0), MxSize32(p_videoParamWidth, p_videoParamHeight)); + MxPoint32 rect2Origin(*p_rect2Left, *p_rect2Top); + MxRect32 rect2(MxPoint32(0, 0), MxSize32(p_rect2Width, p_rect2Height)); MxRect32 rect(0, 0, *p_width, *p_height); - rect.AddPoint(topLeft); + rect.AddPoint(rect1Origin); - if (!rect.IntersectsWith(bitmapRect)) + if (!rect.IntersectsWith(rect1)) return FALSE; - rect.Intersect(bitmapRect); - rect.SubtractPoint(topLeft); - rect.AddPoint(bottomRight); + rect.Intersect(rect1); + rect.SubtractPoint(rect1Origin); + rect.AddPoint(rect2Origin); - if (!rect.IntersectsWith(videoParamRect)) + if (!rect.IntersectsWith(rect2)) return FALSE; - rect.Intersect(videoParamRect); - rect.SubtractPoint(bottomRight); + rect.Intersect(rect2); + rect.SubtractPoint(rect2Origin); - *p_left += rect.GetLeft(); - *p_top += rect.GetTop(); - *p_right += rect.GetLeft(); - *p_bottom += rect.GetTop(); + *p_rect1Left += rect.GetLeft(); + *p_rect1Top += rect.GetTop(); + *p_rect2Left += rect.GetLeft(); + *p_rect2Top += rect.GetTop(); *p_width = rect.GetWidth(); *p_height = rect.GetHeight(); return TRUE; diff --git a/LEGO1/omni/src/video/mxbitmap.cpp b/LEGO1/omni/src/video/mxbitmap.cpp index 9e21e449..0d83bba2 100644 --- a/LEGO1/omni/src/video/mxbitmap.cpp +++ b/LEGO1/omni/src/video/mxbitmap.cpp @@ -1,6 +1,7 @@ #include "mxbitmap.h" #include "decomp.h" +#include "mxutil.h" DECOMP_SIZE_ASSERT(MxBitmap, 0x20); DECOMP_SIZE_ASSERT(MxBITMAPINFO, 0x428); @@ -207,14 +208,88 @@ MxResult MxBitmap::LoadFile(HANDLE p_handle) return result; } -// STUB: LEGO1 0x100bce70 -void MxBitmap::VTable0x2c(int, int, int, int, int, int, int) +// FUNCTION: LEGO1 0x100bce70 +void MxBitmap::BitBlt( + MxBitmap* p_src, + MxS32 p_srcLeft, + MxS32 p_srcTop, + MxS32 p_dstLeft, + MxS32 p_dstTop, + MxS32 p_width, + MxS32 p_height +) { + MxLong dstHeight = GetBmiHeightAbs(); + MxLong srcHeight = p_src->GetBmiHeightAbs(); + + if (GetRectIntersection( + p_src->GetBmiWidth(), + srcHeight, + GetBmiWidth(), + dstHeight, + &p_srcLeft, + &p_srcTop, + &p_dstLeft, + &p_dstTop, + &p_width, + &p_height + )) { + MxU8* srcStart = p_src->GetStart(p_srcLeft, p_srcTop); + MxU8* dstStart = GetStart(p_dstLeft, p_dstTop); + MxLong srcStride = p_src->GetAdjustedStride(); + MxLong dstStride = GetAdjustedStride(); + + while (p_height--) { + memcpy(dstStart, srcStart, p_width); + dstStart += dstStride; + srcStart += srcStride; + } + } } -// STUB: LEGO1 0x100bd020 -void MxBitmap::VTable0x30(int, int, int, int, int, int, int) +// FUNCTION: LEGO1 0x100bd020 +void MxBitmap::BitBltTransparent( + MxBitmap* p_src, + MxS32 p_srcLeft, + MxS32 p_srcTop, + MxS32 p_dstLeft, + MxS32 p_dstTop, + MxS32 p_width, + MxS32 p_height +) { + MxLong dstHeight = GetBmiHeightAbs(); + MxLong srcHeight = p_src->GetBmiHeightAbs(); + + if (GetRectIntersection( + p_src->GetBmiWidth(), + srcHeight, + GetBmiWidth(), + dstHeight, + &p_srcLeft, + &p_srcTop, + &p_dstLeft, + &p_dstTop, + &p_width, + &p_height + )) { + MxU8* srcStart = p_src->GetStart(p_srcLeft, p_srcTop); + MxU8* dstStart = GetStart(p_dstLeft, p_dstTop); + MxLong srcStride = p_src->GetAdjustedStride() - p_width; + MxLong dstStride = GetAdjustedStride() - p_width; + + for (MxS32 h = 0; h < p_height; h++) { + for (MxS32 w = 0; w < p_width; w++) { + if (*srcStart) + *dstStart = *srcStart; + srcStart++; + dstStart++; + } + + srcStart += srcStride; + dstStart += dstStride; + } + } } // FUNCTION: LEGO1 0x100bd1c0 diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index d744accd..c1b45963 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -305,7 +305,7 @@ void MxDisplaySurface::VTable0x28( MxS32 p_height ) { - if (FUN_100b6e10( + if (GetRectIntersection( p_bitmap->GetBmiWidth(), p_bitmap->GetBmiHeightAbs(), m_videoParam.GetRect().GetWidth(),