From 6da1bc0a0dec95f31b81cd2ec1f35e1a417a461b Mon Sep 17 00:00:00 2001 From: disinvite Date: Mon, 23 Oct 2023 23:31:49 -0400 Subject: [PATCH] MxVideoPresenter::IsHit --- LEGO1/mxbitmap.h | 1 + LEGO1/mxdsaction.h | 2 ++ LEGO1/mxvideopresenter.cpp | 73 ++++++++++++++++++++++++++++++++++++-- LEGO1/mxvideopresenter.h | 5 +-- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/LEGO1/mxbitmap.h b/LEGO1/mxbitmap.h index 6bb1c5fd..a5fba524 100644 --- a/LEGO1/mxbitmap.h +++ b/LEGO1/mxbitmap.h @@ -51,6 +51,7 @@ class MxBitmap : public MxCore inline BITMAPINFOHEADER *GetBmiHeader() const { return m_bmiHeader; } inline MxLong GetBmiWidth() const { return m_bmiHeader->biWidth; } + inline MxLong GetBmiStride() const { return ((m_bmiHeader->biWidth + 3) & -4); } inline MxLong GetBmiHeight() const { return m_bmiHeader->biHeight; } inline MxLong GetBmiHeightAbs() const { return m_bmiHeader->biHeight > 0 ? m_bmiHeader->biHeight : -m_bmiHeader->biHeight; } inline MxU8 *GetBitmapData() const { return m_data; } diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index 868ae002..8878223d 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -16,10 +16,12 @@ class MxDSAction : public MxDSObject { Flag_Looping = 0x01, Flag_Bit3 = 0x04, + Flag_Bit4 = 0x08, Flag_Bit5 = 0x10, Flag_Enabled = 0x20, Flag_Parsed = 0x80, Flag_Bit9 = 0x200, + Flag_Bit10 = 0x400, }; __declspec(dllexport) MxDSAction(); diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index f48a0f8b..760cb023 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -115,14 +115,14 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap &p_bitmap) // TODO: would prefer not to use goto if we can figure this structure out seek_to_last_row: - bitmap_src_ptr = ((p_bitmap.GetBmiWidth()+3)&-4) * rows_before_top + p_bitmap.GetBitmapData(); + bitmap_src_ptr = p_bitmap.GetBmiStride() * rows_before_top + p_bitmap.GetBitmapData(); } // How many bytes are there for each row of the bitmap? // (i.e. the image stride) // If this is a bottom-up DIB, we will walk it in reverse. // TODO: Same rounding trick as in MxBitmap - MxS32 row_seek = ((m_height+3)&-4); + MxS32 row_seek = ((m_width+3)&-4); if (p_bitmap.GetBmiHeight() < 0) row_seek = -row_seek; @@ -166,6 +166,16 @@ MxVideoPresenter::AlphaMask::~AlphaMask() delete[] m_bitmask; } +// OFFSET: LEGO1 0x100b26f0 +MxS32 MxVideoPresenter::AlphaMask::IsHit(MxU32 p_x, MxU32 p_y) +{ + if (p_x >= m_width || p_y >= m_height) + return 0; + + MxS32 pos = p_y * m_width + p_x; + return m_bitmask[pos / 8] & (1 << abs(abs(pos) & 7)) ? 1 : 0; +} + // OFFSET: LEGO1 0x100b2760 void MxVideoPresenter::Init() { @@ -226,6 +236,65 @@ void MxVideoPresenter::VTable0x64() // TODO } +// OFFSET: LEGO1 0x100b2900 +MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) +{ + MxDSAction *action = GetAction(); + if ((action == NULL) || (((action->GetFlags() & MxDSAction::Flag_Bit10) == 0) && !IsEnabled()) + || (!m_bitmap && !m_alpha)) + return FALSE; + + if (m_bitmap) + return m_alpha->IsHit(p_x - GetLocationX(), p_y - GetLocationY()); + + MxLong heightAbs = m_bitmap->GetBmiHeightAbs(); + + MxLong min_x = GetLocationX(); + MxLong min_y = GetLocationY(); + + MxLong max_y = min_y + heightAbs; + MxLong max_x = min_x + m_bitmap->GetBmiWidth(); + + if (p_x < min_x || p_x >= max_x || p_y < min_y || p_y >= max_y) + return FALSE; + + MxU8 *pixel; + + MxLong biCompression = m_bitmap->GetBmiHeader()->biCompression; + MxLong height = m_bitmap->GetBmiHeight(); + MxLong seek_row; + + // DECOMP: Same basic layout as AlphaMask constructor + // The idea here is to again seek to the correct place in the bitmap's + // m_data buffer. The x,y args are (most likely) screen x and y, so we + // need to shift that to coordinates local to the bitmap by removing + // the MxPresenter location x and y coordinates. + if (biCompression == BI_RGB) { + if (biCompression == BI_RGB_TOPDOWN || height < 0) { + seek_row = p_y - GetLocationY(); + } else { + height = height > 0 ? height : -height; + seek_row = height - p_y - 1 + GetLocationY(); + } + pixel = m_bitmap->GetBmiStride() * seek_row + m_bitmap->GetBitmapData() - GetLocationX() + p_x; + } else if (biCompression == BI_RGB_TOPDOWN) { + pixel = m_bitmap->GetBitmapData(); + } else { + height = height > 0 ? height : -height; + height--; + pixel = m_bitmap->GetBmiStride() * height + m_bitmap->GetBitmapData(); + } + + // DECOMP: m_flags is 1 byte, so no enum here + if (m_flags & 0x10) + return (MxBool) *pixel; + + if ((GetAction()->GetFlags() & MxDSAction::Flag_Bit4) && *pixel == 0) + return FALSE; + + return TRUE; +} + // OFFSET: LEGO1 0x100b2a70 STUB void MxVideoPresenter::VTable0x6c() { diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index 61a1027c..7ae3f796 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -35,6 +35,7 @@ class MxVideoPresenter : public MxMediaPresenter virtual void Destroy() override; // vtable+0x38 + virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) override; //vtable+0x50 virtual void VTable0x5c(undefined4 p_unknown1); // vtable+0x5c virtual void VTable0x60(); // vtable+0x60 virtual void VTable0x64(); // vtable+0x64 @@ -47,8 +48,6 @@ class MxVideoPresenter : public MxMediaPresenter virtual MxS32 GetWidth(); // vtable+0x80 virtual MxS32 GetHeight(); // vtable+0x84 - // TODO: Not sure what this is. Seems to have size of 12 bytes - // based on 0x100b9e9a. Values are copied from the bitmap header. // SIZE 0xc struct AlphaMask { MxU8 *m_bitmask; @@ -58,6 +57,8 @@ class MxVideoPresenter : public MxMediaPresenter AlphaMask(const MxBitmap &); AlphaMask(const AlphaMask &); virtual ~AlphaMask(); + + MxS32 IsHit(MxU32 p_x, MxU32 p_y); }; MxBitmap *m_bitmap;