From c46bc985c272ceeff9d6fee2ff88a3f24ef0154b Mon Sep 17 00:00:00 2001 From: Regan Green Date: Thu, 5 Oct 2023 06:31:20 -0400 Subject: [PATCH] Implement MxTransitionManager SetWaitIndicator and SetupCopyRect (#165) * Implement MxTransitionManager SetWaitIndicator and SetupCopyRect * More accurate SetupCopyRect * Add MxDSAction::Flag_Bit5 * SetupCopyRect PR Amends * Correct braces formatting * Stub MxVideoPresenter::Destroy --- LEGO1/mxdisplaysurface.cpp | 4 +- LEGO1/mxdisplaysurface.h | 4 +- LEGO1/mxdsaction.h | 1 + LEGO1/mxmediapresenter.cpp | 6 ++ LEGO1/mxmediapresenter.h | 2 + LEGO1/mxpresenter.h | 2 + LEGO1/mxtransitionmanager.cpp | 101 +++++++++++++++++++++++++++++----- LEGO1/mxtransitionmanager.h | 6 +- LEGO1/mxvideopresenter.cpp | 86 +++++++++++++++++++++++++++++ LEGO1/mxvideopresenter.h | 17 ++++++ 10 files changed, 208 insertions(+), 21 deletions(-) diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index 4f02aeb6..619f5eef 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -174,7 +174,7 @@ void MxDisplaySurface::SetPalette(MxPalette *p_palette) } // OFFSET: LEGO1 0x100bc200 STUB -void MxDisplaySurface::vtable24(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) +void MxDisplaySurface::vtable24(LPDDSURFACEDESC, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) { } @@ -186,7 +186,7 @@ MxBool MxDisplaySurface::vtable28(undefined4, undefined4, undefined4, undefined4 } // OFFSET: LEGO1 0x100bc630 STUB -MxBool MxDisplaySurface::vtable2c(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool) +MxBool MxDisplaySurface::vtable2c(LPDDSURFACEDESC, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool) { return 0; } diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index 9bbc44bc..af484716 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -23,9 +23,9 @@ class MxDisplaySurface : public MxCore virtual MxResult Create(MxVideoParam &p_videoParam); virtual void Clear(); virtual void SetPalette(MxPalette *p_palette); - virtual void vtable24(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); + virtual void vtable24(LPDDSURFACEDESC, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); virtual MxBool vtable28(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); - virtual MxBool vtable2c(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool); + virtual MxBool vtable2c(LPDDSURFACEDESC, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool); virtual MxBool vtable30(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool); virtual undefined4 vtable34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); virtual void Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index eb7afb99..9881f3e2 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -16,6 +16,7 @@ class MxDSAction : public MxDSObject { Flag_Looping = 0x01, Flag_Bit3 = 0x04, + Flag_Bit5 = 0x10, Flag_Enabled = 0x20, Flag_Parsed = 0x80, Flag_Bit9 = 0x200, diff --git a/LEGO1/mxmediapresenter.cpp b/LEGO1/mxmediapresenter.cpp index 6a59a0ec..f36ecbdc 100644 --- a/LEGO1/mxmediapresenter.cpp +++ b/LEGO1/mxmediapresenter.cpp @@ -17,3 +17,9 @@ void MxMediaPresenter::Init() this->m_unk48 = NULL; this->m_unk4c = NULL; } + +// OFFSET: LEGO1 0x100b5f10 STUB +void MxMediaPresenter::VTable0x58() +{ + // TODO +} diff --git a/LEGO1/mxmediapresenter.h b/LEGO1/mxmediapresenter.h index 741ab49f..824dd399 100644 --- a/LEGO1/mxmediapresenter.h +++ b/LEGO1/mxmediapresenter.h @@ -29,6 +29,8 @@ class MxMediaPresenter : public MxPresenter return !strcmp(name, MxMediaPresenter::ClassName()) || MxPresenter::IsA(name); } + virtual void VTable0x58(); // vtable+0x58 + undefined4 m_unk40; undefined4 m_unk44; undefined4 m_unk48; diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index c0757665..81ea14ad 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -68,6 +68,8 @@ class MxPresenter : public MxCore MxBool IsEnabled(); + inline MxS32 GetCurrentTickleState() { return this->m_currentTickleState; } + inline MxPoint32 GetLocation() { return this->m_location; } inline MxS32 GetDisplayZ() { return this->m_displayZ; } inline MxDSAction *GetAction() { return this->m_action; } diff --git a/LEGO1/mxtransitionmanager.cpp b/LEGO1/mxtransitionmanager.cpp index f66f4bae..efb90604 100644 --- a/LEGO1/mxtransitionmanager.cpp +++ b/LEGO1/mxtransitionmanager.cpp @@ -104,7 +104,7 @@ void MxTransitionManager::Transition_Dissolve() } if (res == DD_OK) { - SubmitCopyRect(ddsd); + SubmitCopyRect(&ddsd); for (MxS32 i = 0; i < 640; i++) { // Select 16 columns on each tick @@ -129,7 +129,7 @@ void MxTransitionManager::Transition_Dissolve() } } - SetupCopyRect(ddsd); + SetupCopyRect(&ddsd); m_ddSurface->Unlock(ddsd.lpSurface); if (VideoManager()->GetVideoParam().flags().GetFlipSurfaces()) { @@ -213,7 +213,7 @@ void MxTransitionManager::Transition_Wipe() } if (res == DD_OK) { - SubmitCopyRect(ddsd); + SubmitCopyRect(&ddsd); // For each of the 240 animation ticks, blank out two scanlines // starting at the top of the screen. @@ -224,21 +224,42 @@ void MxTransitionManager::Transition_Wipe() line += ddsd.lPitch; memset(line, 0, 640 * ddsd.ddpfPixelFormat.dwRGBBitCount / 8); - SetupCopyRect(ddsd); + SetupCopyRect(&ddsd); m_ddSurface->Unlock(ddsd.lpSurface); m_animationTimer++; } } -// OFFSET: LEGO1 0x1004c470 STUB -void MxTransitionManager::SetWaitIndicator(MxVideoPresenter *videoPresenter) +// OFFSET: LEGO1 0x1004c470 +void MxTransitionManager::SetWaitIndicator(MxVideoPresenter *p_waitIndicator) { - // TODO + // End current wait indicator + if (m_waitIndicator != NULL) { + m_waitIndicator->GetAction()->SetFlags(m_waitIndicator->GetAction()->GetFlags() & ~MxDSAction::Flag_Parsed); + m_waitIndicator->EndAction(); + m_waitIndicator = NULL; + } + + // Check if we were given a new wait indicator + if (p_waitIndicator != NULL) { + // Setup the new wait indicator + m_waitIndicator = p_waitIndicator; + + LegoVideoManager *videoManager = VideoManager(); + videoManager->RemovePresenter(*m_waitIndicator); + + if (m_waitIndicator->GetCurrentTickleState() < MxPresenter::TickleState_Streaming) { + m_waitIndicator->Tickle(); + } + } else { + // Disable copy rect + m_copyFlags.bit0 = FALSE; + } } // OFFSET: LEGO1 0x1004c4d0 -void MxTransitionManager::SubmitCopyRect(DDSURFACEDESC &ddsc) +void MxTransitionManager::SubmitCopyRect(LPDDSURFACEDESC ddsc) { // Check if the copy rect is setup if (m_copyFlags.bit0 == FALSE || m_waitIndicator == NULL || m_copyBuffer == NULL) { @@ -248,7 +269,7 @@ void MxTransitionManager::SubmitCopyRect(DDSURFACEDESC &ddsc) // Copy the copy rect onto the surface char *dst; - DWORD bytesPerPixel = ddsc.ddpfPixelFormat.dwRGBBitCount / 8; + DWORD bytesPerPixel = ddsc->ddpfPixelFormat.dwRGBBitCount / 8; const char *src = (const char *)m_copyBuffer; @@ -256,12 +277,12 @@ void MxTransitionManager::SubmitCopyRect(DDSURFACEDESC &ddsc) copyPitch = ((m_copyRect.right - m_copyRect.left) + 1) * bytesPerPixel; LONG y; - dst = (char *)ddsc.lpSurface + (ddsc.lPitch * m_copyRect.top) + (bytesPerPixel * m_copyRect.left); + dst = (char *)ddsc->lpSurface + (ddsc->lPitch * m_copyRect.top) + (bytesPerPixel * m_copyRect.left); for (y = 0; y < m_copyRect.bottom - m_copyRect.top + 1; ++y) { memcpy(dst, src, copyPitch); src += copyPitch; - dst += ddsc.lPitch; + dst += ddsc->lPitch; } // Free the copy buffer @@ -269,8 +290,60 @@ void MxTransitionManager::SubmitCopyRect(DDSURFACEDESC &ddsc) m_copyBuffer = NULL; } -// OFFSET: LEGO1 0x1004c580 STUB -void MxTransitionManager::SetupCopyRect(DDSURFACEDESC &ddsc) +// OFFSET: LEGO1 0x1004c580 +void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC ddsc) { - // TODO + // Check if the copy rect is setup + if (m_copyFlags.bit0 == FALSE || m_waitIndicator == NULL) { + return; + } + + // Tickle wait indicator + m_waitIndicator->Tickle(); + + // Check if wait indicator has started + if (m_waitIndicator->GetCurrentTickleState() >= MxPresenter::TickleState_Streaming) { + // Setup the copy rect + DWORD copyPitch = (ddsc->ddpfPixelFormat.dwRGBBitCount / 8) * (m_copyRect.right - m_copyRect.left + 1); // This uses m_copyRect, seemingly erroneously + DWORD bytesPerPixel = ddsc->ddpfPixelFormat.dwRGBBitCount / 8; + + m_copyRect.left = m_waitIndicator->GetLocation().m_x; + m_copyRect.top = m_waitIndicator->GetLocation().m_y; + + MxS32 height = m_waitIndicator->GetHeight(); + MxS32 width = m_waitIndicator->GetWidth(); + + m_copyRect.right = m_copyRect.left + width - 1; + m_copyRect.bottom = m_copyRect.top + height - 1; + + // Allocate the copy buffer + const char *src = (const char*)ddsc->lpSurface + m_copyRect.top * ddsc->lPitch + bytesPerPixel * m_copyRect.left; + + m_copyBuffer = malloc(bytesPerPixel * width * height); + if (!m_copyBuffer) + return; + + // Copy into the copy buffer + char *dst = (char*)m_copyBuffer; + + for (MxS32 i = 0; i < (m_copyRect.bottom - m_copyRect.top + 1); i++) + { + memcpy(dst, src, copyPitch); + src += ddsc->lPitch; + dst += copyPitch; + } + } + + // Setup display surface + if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::Flag_Bit5) != 0) + { + MxDisplaySurface *displaySurface = VideoManager()->GetDisplaySurface(); + MxBool unkbool = FALSE; + displaySurface->vtable2c(ddsc, m_waitIndicator->m_unk50, 0, 0, m_waitIndicator->GetLocation().m_x, m_waitIndicator->GetLocation().m_y, m_waitIndicator->GetWidth(), m_waitIndicator->GetHeight(), unkbool); + } + else + { + MxDisplaySurface *displaySurface = VideoManager()->GetDisplaySurface(); + displaySurface->vtable24(ddsc, m_waitIndicator->m_unk50, 0, 0, m_waitIndicator->GetLocation().m_x, m_waitIndicator->GetLocation().m_y, m_waitIndicator->GetWidth(), m_waitIndicator->GetHeight()); + } } diff --git a/LEGO1/mxtransitionmanager.h b/LEGO1/mxtransitionmanager.h index cc5bd678..4ed82229 100644 --- a/LEGO1/mxtransitionmanager.h +++ b/LEGO1/mxtransitionmanager.h @@ -12,7 +12,7 @@ class MxTransitionManager : public MxCore MxTransitionManager(); virtual ~MxTransitionManager() override; // vtable+0x0 - __declspec(dllexport) void SetWaitIndicator(MxVideoPresenter *videoPresenter); + __declspec(dllexport) void SetWaitIndicator(MxVideoPresenter *p_waitIndicator); virtual MxResult Tickle(); // vtable+0x8 @@ -46,8 +46,8 @@ class MxTransitionManager : public MxCore void EndTransition(MxBool p_notifyWorld); void Transition_Dissolve(); void Transition_Wipe(); - void SubmitCopyRect(DDSURFACEDESC &); - void SetupCopyRect(DDSURFACEDESC &); + void SubmitCopyRect(LPDDSURFACEDESC ddsc); + void SetupCopyRect(LPDDSURFACEDESC ddsc); MxVideoPresenter *m_waitIndicator; RECT m_copyRect; diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index 4e47e4a4..fe83a2dc 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -2,8 +2,94 @@ DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64); +// OFFSET: LEGO1 0x1000c700 STUB +void MxVideoPresenter::VTable0x5c() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c710 STUB +void MxVideoPresenter::VTable0x60() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c720 STUB +void MxVideoPresenter::VTable0x68() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c730 STUB +void MxVideoPresenter::VTable0x70() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c740 +MxVideoPresenter::~MxVideoPresenter() +{ + Destroy(TRUE); +} + +// OFFSET: LEGO1 0x1000c7a0 STUB +void MxVideoPresenter::InitVirtual() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c7b0 STUB +void MxVideoPresenter::VTable0x78() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c7c0 STUB +void MxVideoPresenter::VTable0x7c() +{ + // TODO +} + +// OFFSET: LEGO1 0x1000c7e0 STUB +MxS32 MxVideoPresenter::GetWidth() +{ + // TODO + return 0; +} + +// OFFSET: LEGO1 0x1000c800 STUB +MxS32 MxVideoPresenter::GetHeight() +{ + // TODO + return 0; +} + // OFFSET: LEGO1 0x100b2760 STUB void MxVideoPresenter::Init() { // TODO } + +// OFFSET: LEGO1 0x100b27b0 STUB +void MxVideoPresenter::Destroy(MxBool) +{ + // TODO +} + +// OFFSET: LEGO1 0x100b28b0 STUB +void MxVideoPresenter::VTable0x64() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b2a70 STUB +void MxVideoPresenter::VTable0x6c() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b3300 STUB +void MxVideoPresenter::VTable0x74() +{ + // TODO +} diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index bc5fac5c..84822f71 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -13,6 +13,8 @@ class MxVideoPresenter : public MxMediaPresenter Init(); } + virtual ~MxVideoPresenter() override; // vtable+0x0 + // OFFSET: LEGO1 0x1000c820 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -27,6 +29,21 @@ class MxVideoPresenter : public MxMediaPresenter } void Init(); + void Destroy(MxBool); + + virtual void InitVirtual() override; // vtable+0x38 + + virtual void VTable0x5c(); // vtable+0x5c + virtual void VTable0x60(); // vtable+0x60 + virtual void VTable0x64(); // vtable+0x64 + virtual void VTable0x68(); // vtable+0x68 + virtual void VTable0x6c(); // vtable+0x6c + virtual void VTable0x70(); // vtable+0x70 + virtual void VTable0x74(); // vtable+0x74 + virtual void VTable0x78(); // vtable+0x78 + virtual void VTable0x7c(); // vtable+0x7c + virtual MxS32 GetWidth(); // vtable+0x80 + virtual MxS32 GetHeight(); // vtable+0x84 undefined4 m_unk50; undefined4 m_unk54;