2023-06-29 04:10:08 -04:00
|
|
|
#include "mxtransitionmanager.h"
|
2023-09-29 12:42:15 -04:00
|
|
|
#include "legoutil.h"
|
2023-09-29 12:09:46 -04:00
|
|
|
#include "legovideomanager.h"
|
|
|
|
|
|
|
|
DECOMP_SIZE_ASSERT(MxTransitionManager, 0x900);
|
2023-06-29 04:10:08 -04:00
|
|
|
|
2023-10-03 18:03:10 -04:00
|
|
|
// 0x100f4378
|
|
|
|
RECT g_fullScreenRect = {0, 0, 640, 480};
|
|
|
|
|
2023-10-01 20:18:16 -04:00
|
|
|
// OFFSET: LEGO1 0x1004b8d0
|
2023-06-29 04:10:08 -04:00
|
|
|
MxTransitionManager::MxTransitionManager()
|
|
|
|
{
|
2023-10-01 20:18:16 -04:00
|
|
|
m_animationTimer = 0;
|
|
|
|
m_transitionType = NOT_TRANSITIONING;
|
|
|
|
m_ddSurface = NULL;
|
2023-10-04 09:43:34 -04:00
|
|
|
m_waitIndicator = NULL;
|
|
|
|
m_copyBuffer = NULL;
|
|
|
|
m_copyFlags.bit0 = FALSE;
|
2023-10-01 20:18:16 -04:00
|
|
|
m_unk28.bit0 = FALSE;
|
|
|
|
m_unk24 = 0;
|
2023-06-29 04:10:08 -04:00
|
|
|
}
|
|
|
|
|
2023-10-01 20:18:16 -04:00
|
|
|
// OFFSET: LEGO1 0x1004ba00
|
2023-06-29 04:10:08 -04:00
|
|
|
MxTransitionManager::~MxTransitionManager()
|
|
|
|
{
|
2023-10-04 09:43:34 -04:00
|
|
|
free(m_copyBuffer);
|
2023-10-01 20:18:16 -04:00
|
|
|
|
2023-10-04 09:43:34 -04:00
|
|
|
if (m_waitIndicator != NULL) {
|
|
|
|
delete m_waitIndicator->GetAction();
|
|
|
|
delete m_waitIndicator;
|
2023-10-01 20:18:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
TickleManager()->UnregisterClient(this);
|
2023-06-29 04:10:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// OFFSET: LEGO1 0x1004bac0 STUB
|
2023-09-21 14:51:24 -04:00
|
|
|
MxResult MxTransitionManager::Tickle()
|
2023-06-29 04:10:08 -04:00
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-10-04 02:56:16 -04:00
|
|
|
// OFFSET: LEGO1 0x1004bc30
|
|
|
|
void MxTransitionManager::EndTransition(MxBool p_notifyWorld)
|
2023-10-03 18:03:10 -04:00
|
|
|
{
|
2023-10-04 02:56:16 -04:00
|
|
|
if (m_transitionType != NOT_TRANSITIONING) {
|
|
|
|
m_transitionType = NOT_TRANSITIONING;
|
|
|
|
|
2023-10-04 09:43:34 -04:00
|
|
|
m_copyFlags.bit0 = FALSE;
|
2023-10-04 02:56:16 -04:00
|
|
|
|
|
|
|
TickleManager()->UnregisterClient(this);
|
|
|
|
|
|
|
|
if (p_notifyWorld) {
|
|
|
|
LegoWorld *world = GetCurrentWorld();
|
|
|
|
|
|
|
|
if (world) {
|
|
|
|
world->Notify(MxParam(0x18, this));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-03 18:03:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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) {
|
2023-10-04 09:43:34 -04:00
|
|
|
SubmitCopyRect(ddsd);
|
2023-10-03 18:03:10 -04:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-04 09:43:34 -04:00
|
|
|
SetupCopyRect(ddsd);
|
2023-10-03 18:03:10 -04:00
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-29 12:09:46 -04:00
|
|
|
// OFFSET: LEGO1 0x1004baa0
|
|
|
|
MxResult MxTransitionManager::GetDDrawSurfaceFromVideoManager() // vtable+0x14
|
|
|
|
{
|
|
|
|
LegoVideoManager *videoManager = VideoManager();
|
|
|
|
this->m_ddSurface = videoManager->GetDisplaySurface()->GetDirectDrawSurface2();
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// OFFSET: LEGO1 0x1004bb70
|
|
|
|
MxResult MxTransitionManager::StartTransition(TransitionType p_animationType, MxS32 p_speed,
|
2023-10-04 09:43:34 -04:00
|
|
|
MxBool p_doCopy, MxBool p_playMusicInAnim)
|
2023-09-29 12:09:46 -04:00
|
|
|
{
|
|
|
|
if (this->m_transitionType == NOT_TRANSITIONING) {
|
|
|
|
if (!p_playMusicInAnim) {
|
|
|
|
MxBackgroundAudioManager *backgroundAudioManager = BackgroundAudioManager();
|
|
|
|
backgroundAudioManager->Stop();
|
|
|
|
}
|
|
|
|
|
2023-10-01 20:18:16 -04:00
|
|
|
this->m_transitionType = p_animationType;
|
2023-09-29 12:09:46 -04:00
|
|
|
|
2023-10-04 09:43:34 -04:00
|
|
|
m_copyFlags.bit0 = p_doCopy;
|
2023-09-29 12:09:46 -04:00
|
|
|
|
2023-10-04 09:43:34 -04:00
|
|
|
if (m_copyFlags.bit0 && m_waitIndicator != NULL) {
|
|
|
|
m_waitIndicator->Enable(TRUE);
|
2023-09-29 12:09:46 -04:00
|
|
|
|
2023-10-04 09:43:34 -04:00
|
|
|
MxDSAction *action = m_waitIndicator->GetAction();
|
|
|
|
action->SetLoopCount(10000);
|
|
|
|
action->SetFlags(action->GetFlags() | MxDSAction::Flag_Bit9);
|
2023-10-01 20:18:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
MxU32 time = timeGetTime();
|
|
|
|
this->m_systemTime = time;
|
|
|
|
|
|
|
|
this->m_animationSpeed = p_speed;
|
2023-09-29 12:09:46 -04:00
|
|
|
|
2023-10-01 20:18:16 -04:00
|
|
|
MxTickleManager *tickleManager = TickleManager();
|
|
|
|
tickleManager->RegisterClient(this, p_speed);
|
2023-09-29 12:09:46 -04:00
|
|
|
|
2023-10-01 20:18:16 -04:00
|
|
|
LegoInputManager *inputManager = InputManager();
|
2023-10-03 13:53:22 -04:00
|
|
|
inputManager->m_unk0x88 = TRUE;
|
|
|
|
inputManager->m_unk0x336 = FALSE;
|
2023-09-29 12:09:46 -04:00
|
|
|
|
2023-10-01 20:18:16 -04:00
|
|
|
LegoVideoManager *videoManager = VideoManager();
|
|
|
|
videoManager->SetUnkE4(FALSE);
|
|
|
|
|
|
|
|
SetAppCursor(1);
|
|
|
|
return SUCCESS;
|
2023-09-29 12:09:46 -04:00
|
|
|
}
|
|
|
|
return FAILURE;
|
2023-10-01 20:18:16 -04:00
|
|
|
}
|
2023-10-04 09:43:34 -04:00
|
|
|
|
2023-10-04 11:48:25 -04:00
|
|
|
// OFFSET: LEGO1 0x1004c170
|
|
|
|
void MxTransitionManager::Transition_Wipe()
|
|
|
|
{
|
|
|
|
// If the animation is finished
|
|
|
|
if (m_animationTimer == 240) {
|
|
|
|
m_animationTimer = 0;
|
|
|
|
EndTransition(TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
SubmitCopyRect(ddsd);
|
|
|
|
|
|
|
|
// For each of the 240 animation ticks, blank out two scanlines
|
|
|
|
// starting at the top of the screen.
|
|
|
|
// (dwRGBBitCount / 8) will tell how many bytes are used per pixel.
|
|
|
|
MxU8 *line = (MxU8*)ddsd.lpSurface + 2*ddsd.lPitch*m_animationTimer;
|
|
|
|
memset(line, 0, 640 * ddsd.ddpfPixelFormat.dwRGBBitCount / 8);
|
|
|
|
|
|
|
|
line += ddsd.lPitch;
|
|
|
|
memset(line, 0, 640 * ddsd.ddpfPixelFormat.dwRGBBitCount / 8);
|
|
|
|
|
|
|
|
SetupCopyRect(ddsd);
|
|
|
|
m_ddSurface->Unlock(ddsd.lpSurface);
|
|
|
|
|
|
|
|
m_animationTimer++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-04 09:43:34 -04:00
|
|
|
// OFFSET: LEGO1 0x1004c470 STUB
|
|
|
|
void MxTransitionManager::SetWaitIndicator(MxVideoPresenter *videoPresenter)
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
// OFFSET: LEGO1 0x1004c4d0
|
|
|
|
void MxTransitionManager::SubmitCopyRect(DDSURFACEDESC &ddsc)
|
|
|
|
{
|
|
|
|
// Check if the copy rect is setup
|
|
|
|
if (m_copyFlags.bit0 == FALSE || m_waitIndicator == NULL || m_copyBuffer == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy the copy rect onto the surface
|
|
|
|
char *dst;
|
|
|
|
|
|
|
|
DWORD bytesPerPixel = ddsc.ddpfPixelFormat.dwRGBBitCount / 8;
|
|
|
|
|
|
|
|
const char *src = (const char *)m_copyBuffer;
|
|
|
|
|
|
|
|
LONG copyPitch;
|
|
|
|
copyPitch = ((m_copyRect.right - m_copyRect.left) + 1) * bytesPerPixel;
|
|
|
|
|
|
|
|
LONG y;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free the copy buffer
|
|
|
|
free(m_copyBuffer);
|
|
|
|
m_copyBuffer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// OFFSET: LEGO1 0x1004c580 STUB
|
|
|
|
void MxTransitionManager::SetupCopyRect(DDSURFACEDESC &ddsc)
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
}
|