From 129e8d6373ff8167b4549a855132e1411dc449c1 Mon Sep 17 00:00:00 2001 From: MS Date: Tue, 3 Oct 2023 18:03:10 -0400 Subject: [PATCH] MxTransitionManager::Dissolve (#155) * MxTransitionManager::Dissolve * Some comments and better names * use refs instead of pointers * slightly improved name for rect * Use MxS32 instead of int --- LEGO1/mxdisplaysurface.h | 1 + LEGO1/mxtransitionmanager.cpp | 101 ++++++++++++++++++++++++++++++++++ LEGO1/mxtransitionmanager.h | 8 ++- 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index 4c2c3866..9bbc44bc 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -33,6 +33,7 @@ class MxDisplaySurface : public MxCore virtual void ReleaseDC(HDC p_hdc); virtual undefined4 vtable44(undefined4, undefined4*, undefined4, undefined4); + inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } inline LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return this->m_ddSurface2; } private: diff --git a/LEGO1/mxtransitionmanager.cpp b/LEGO1/mxtransitionmanager.cpp index c3dfb035..61283718 100644 --- a/LEGO1/mxtransitionmanager.cpp +++ b/LEGO1/mxtransitionmanager.cpp @@ -4,6 +4,9 @@ DECOMP_SIZE_ASSERT(MxTransitionManager, 0x900); +// 0x100f4378 +RECT g_fullScreenRect = {0, 0, 640, 480}; + // OFFSET: LEGO1 0x1004b8d0 MxTransitionManager::MxTransitionManager() { @@ -38,12 +41,110 @@ MxResult MxTransitionManager::Tickle() return 0; } +// OFFSET: LEGO1 0x1004bc30 STUB +void MxTransitionManager::EndTransition(MxBool) +{ + // TODO +} + +// OFFSET: LEGO1 0x1004bd10 +void MxTransitionManager::Transition_Dissolve() +{ + // If the animation is finished + if (m_animationTimer == 40) { + m_animationTimer = 0; + EndTransition(TRUE); + return; + } + + // If we are starting the animation + if (m_animationTimer == 0) { + // Generate the list of columns in order... + for (MxS32 i = 0; i < 640; i++) { + m_columnOrder[i] = i; + } + + // ...then shuffle the list (to ensure that we hit each column once) + for (i = 0; i < 640; i++) { + MxS32 swap = rand() % 640; + MxU16 t = m_columnOrder[i]; + m_columnOrder[i] = m_columnOrder[swap]; + m_columnOrder[swap] = t; + } + + // For each scanline, pick a random X offset + for (i = 0; i < 480; i++) { + m_randomShift[i] = rand() % 640; + } + } + + // Run one tick of the animation + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + HRESULT res = m_ddSurface->Lock(NULL, &ddsd, 1, NULL); + if (res == DDERR_SURFACELOST) { + m_ddSurface->Restore(); + res = m_ddSurface->Lock(NULL, &ddsd, 1, NULL); + } + + if (res == DD_OK) { + FUN_1004c4d0(ddsd); + + for (MxS32 i = 0; i < 640; i++) { + // Select 16 columns on each tick + if (m_animationTimer * 16 > m_columnOrder[i]) + continue; + + if (m_animationTimer * 16 + 15 < m_columnOrder[i]) + continue; + + for (MxS32 j = 0; j < 480; j++) { + // Shift the chosen column a different amount at each scanline. + // We use the same shift for that scanline each time. + // By the end, every pixel gets hit. + MxS32 ofs = (m_randomShift[j] + i) % 640; + + // Set the chosen pixel to black + if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) { + ((MxU8*)ddsd.lpSurface)[j * ddsd.lPitch + ofs] = 0; + } else { + ((MxU16*)ddsd.lpSurface)[j * ddsd.lPitch + ofs] = 0; + } + } + } + + FUN_1004c580(ddsd); + m_ddSurface->Unlock(ddsd.lpSurface); + + if (VideoManager()->GetVideoParam().flags().GetFlipSurfaces()) { + LPDIRECTDRAWSURFACE surf = VideoManager()->GetDisplaySurface()->GetDirectDrawSurface1(); + surf->BltFast(NULL, NULL, m_ddSurface, &g_fullScreenRect, 0x10); + } + + m_animationTimer++; + } +} + // OFFSET: LEGO1 0x1004c470 STUB void MxTransitionManager::SetWaitIndicator(MxVideoPresenter *videoPresenter) { // TODO } +// OFFSET: LEGO1 0x1004c4d0 STUB +void MxTransitionManager::FUN_1004c4d0(DDSURFACEDESC &ddsc) +{ + // TODO +} + +// OFFSET: LEGO1 0x1004c580 STUB +void MxTransitionManager::FUN_1004c580(DDSURFACEDESC &ddsc) +{ + // TODO +} + // OFFSET: LEGO1 0x1004baa0 MxResult MxTransitionManager::GetDDrawSurfaceFromVideoManager() // vtable+0x14 { diff --git a/LEGO1/mxtransitionmanager.h b/LEGO1/mxtransitionmanager.h index 723366c1..09d3e622 100644 --- a/LEGO1/mxtransitionmanager.h +++ b/LEGO1/mxtransitionmanager.h @@ -89,6 +89,11 @@ class MxTransitionManager : public MxCore MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_unk, MxBool p_playMusicInAnim); private: + void EndTransition(MxBool); + void Transition_Dissolve(); + void FUN_1004c4d0(DDSURFACEDESC &); + void FUN_1004c580(DDSURFACEDESC &); + MxTransitionManagerUnknownSubclass1 *m_unk08; undefined4 m_unk0c; undefined4 m_unk10; @@ -102,7 +107,8 @@ class MxTransitionManager : public MxCore TransitionType m_transitionType; LPDIRECTDRAWSURFACE m_ddSurface; MxU16 m_animationTimer; - undefined m_pad36[0x8c2]; + MxU16 m_columnOrder[640]; // 0x36 + MxU16 m_randomShift[480]; // 0x536 MxULong m_systemTime; MxS32 m_animationSpeed; };