2023-06-29 04:10:08 -04:00
|
|
|
#include "mxtransitionmanager.h"
|
2023-10-07 11:30:04 -04:00
|
|
|
|
|
|
|
#include "legoinputmanager.h"
|
2024-03-09 15:07:52 -05:00
|
|
|
#include "legoutils.h"
|
2023-10-24 19:38:27 -04:00
|
|
|
#include "legovideomanager.h"
|
2023-10-07 11:30:04 -04:00
|
|
|
#include "legoworld.h"
|
2024-03-09 15:07:52 -05:00
|
|
|
#include "misc.h"
|
2023-10-07 11:30:04 -04:00
|
|
|
#include "mxbackgroundaudiomanager.h"
|
2024-05-03 12:19:12 -04:00
|
|
|
#include "mxdisplaysurface.h"
|
2024-03-09 15:07:52 -05:00
|
|
|
#include "mxmisc.h"
|
2023-10-07 11:30:04 -04:00
|
|
|
#include "mxparam.h"
|
|
|
|
#include "mxticklemanager.h"
|
2024-03-09 15:07:52 -05:00
|
|
|
#include "mxvideopresenter.h"
|
2023-09-29 12:09:46 -04:00
|
|
|
|
2024-03-22 21:30:58 -04:00
|
|
|
DECOMP_SIZE_ASSERT(MxTransitionManager, 0x900)
|
2023-06-29 04:10:08 -04:00
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// GLOBAL: LEGO1 0x100f4378
|
2023-10-03 18:03:10 -04:00
|
|
|
RECT g_fullScreenRect = {0, 0, 640, 480};
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004b8d0
|
2023-06-29 04:10:08 -04:00
|
|
|
MxTransitionManager::MxTransitionManager()
|
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
m_animationTimer = 0;
|
2024-11-01 12:21:15 -04:00
|
|
|
m_mode = e_idle;
|
2023-10-24 19:38:27 -04:00
|
|
|
m_ddSurface = NULL;
|
|
|
|
m_waitIndicator = NULL;
|
|
|
|
m_copyBuffer = NULL;
|
2023-12-13 05:48:14 -05:00
|
|
|
m_copyFlags.m_bit0 = FALSE;
|
|
|
|
m_unk0x28.m_bit0 = FALSE;
|
|
|
|
m_unk0x24 = 0;
|
2023-06-29 04:10:08 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004ba00
|
2023-06-29 04:10:08 -04:00
|
|
|
MxTransitionManager::~MxTransitionManager()
|
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
delete[] m_copyBuffer;
|
2023-10-01 20:18:16 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
if (m_waitIndicator != NULL) {
|
|
|
|
delete m_waitIndicator->GetAction();
|
|
|
|
delete m_waitIndicator;
|
|
|
|
}
|
2023-10-01 20:18:16 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
TickleManager()->UnregisterClient(this);
|
2023-06-29 04:10:08 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004baa0
|
2023-11-21 03:44:45 -05:00
|
|
|
MxResult MxTransitionManager::GetDDrawSurfaceFromVideoManager() // vtable+0x14
|
|
|
|
{
|
|
|
|
LegoVideoManager* videoManager = VideoManager();
|
2024-11-01 12:21:15 -04:00
|
|
|
m_ddSurface = videoManager->GetDisplaySurface()->GetDirectDrawSurface2();
|
2023-11-21 03:44:45 -05:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004bac0
|
2023-09-21 14:51:24 -04:00
|
|
|
MxResult MxTransitionManager::Tickle()
|
2023-06-29 04:10:08 -04:00
|
|
|
{
|
2024-11-01 12:21:15 -04:00
|
|
|
if (m_animationSpeed + m_systemTime > timeGetTime()) {
|
2023-10-24 19:38:27 -04:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2024-11-01 12:21:15 -04:00
|
|
|
m_systemTime = timeGetTime();
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-11-01 12:21:15 -04:00
|
|
|
switch (m_mode) {
|
2024-01-17 11:53:53 -05:00
|
|
|
case e_noAnimation:
|
2024-03-11 21:23:31 -04:00
|
|
|
NoTransition();
|
2023-10-24 19:38:27 -04:00
|
|
|
break;
|
2024-01-17 11:53:53 -05:00
|
|
|
case e_dissolve:
|
2024-03-11 04:57:58 -04:00
|
|
|
DissolveTransition();
|
2023-10-24 19:38:27 -04:00
|
|
|
break;
|
2024-03-11 04:57:58 -04:00
|
|
|
case e_mosaic:
|
|
|
|
MosaicTransition();
|
2023-10-24 19:38:27 -04:00
|
|
|
break;
|
2024-03-11 04:57:58 -04:00
|
|
|
case e_wipeDown:
|
|
|
|
WipeDownTransition();
|
2023-10-24 19:38:27 -04:00
|
|
|
break;
|
2024-01-17 11:53:53 -05:00
|
|
|
case e_windows:
|
2024-03-11 04:57:58 -04:00
|
|
|
WindowsTransition();
|
2023-10-24 19:38:27 -04:00
|
|
|
break;
|
2024-01-17 11:53:53 -05:00
|
|
|
case e_broken:
|
2024-03-11 04:57:58 -04:00
|
|
|
BrokenTransition();
|
2023-10-24 19:38:27 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
2023-06-29 04:10:08 -04:00
|
|
|
}
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004bb70
|
2024-11-01 12:21:15 -04:00
|
|
|
// FUNCTION: BETA10 0x100ec4c1
|
2023-11-21 03:44:45 -05:00
|
|
|
MxResult MxTransitionManager::StartTransition(
|
|
|
|
TransitionType p_animationType,
|
|
|
|
MxS32 p_speed,
|
|
|
|
MxBool p_doCopy,
|
|
|
|
MxBool p_playMusicInAnim
|
|
|
|
)
|
|
|
|
{
|
2024-11-01 12:21:15 -04:00
|
|
|
assert(m_mode == e_idle);
|
|
|
|
|
|
|
|
if (m_mode == e_idle) {
|
2023-11-21 03:44:45 -05:00
|
|
|
if (!p_playMusicInAnim) {
|
|
|
|
MxBackgroundAudioManager* backgroundAudioManager = BackgroundAudioManager();
|
|
|
|
backgroundAudioManager->Stop();
|
|
|
|
}
|
|
|
|
|
2024-11-01 12:21:15 -04:00
|
|
|
m_mode = p_animationType;
|
2023-11-21 03:44:45 -05:00
|
|
|
|
2023-12-13 05:48:14 -05:00
|
|
|
m_copyFlags.m_bit0 = p_doCopy;
|
2023-11-21 03:44:45 -05:00
|
|
|
|
2023-12-13 05:48:14 -05:00
|
|
|
if (m_copyFlags.m_bit0 && m_waitIndicator != NULL) {
|
2023-11-21 03:44:45 -05:00
|
|
|
m_waitIndicator->Enable(TRUE);
|
|
|
|
|
|
|
|
MxDSAction* action = m_waitIndicator->GetAction();
|
|
|
|
action->SetLoopCount(10000);
|
2024-01-17 11:53:53 -05:00
|
|
|
action->SetFlags(action->GetFlags() | MxDSAction::c_bit10);
|
2023-11-21 03:44:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
MxU32 time = timeGetTime();
|
2024-11-01 12:21:15 -04:00
|
|
|
m_systemTime = time;
|
2023-11-21 03:44:45 -05:00
|
|
|
|
2024-11-01 12:21:15 -04:00
|
|
|
m_animationSpeed = p_speed;
|
2023-11-21 03:44:45 -05:00
|
|
|
|
|
|
|
MxTickleManager* tickleManager = TickleManager();
|
|
|
|
tickleManager->RegisterClient(this, p_speed);
|
|
|
|
|
|
|
|
LegoInputManager* inputManager = InputManager();
|
2024-01-14 16:58:00 -05:00
|
|
|
inputManager->SetUnknown88(TRUE);
|
|
|
|
inputManager->SetUnknown336(FALSE);
|
2023-11-21 03:44:45 -05:00
|
|
|
|
|
|
|
LegoVideoManager* videoManager = VideoManager();
|
2024-01-10 13:45:52 -05:00
|
|
|
videoManager->SetRender3D(FALSE);
|
2023-11-21 03:44:45 -05:00
|
|
|
|
2024-06-01 10:07:58 -04:00
|
|
|
SetAppCursor(e_cursorBusy);
|
2023-11-21 03:44:45 -05:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004bc30
|
2023-10-04 02:56:16 -04:00
|
|
|
void MxTransitionManager::EndTransition(MxBool p_notifyWorld)
|
2023-10-03 18:03:10 -04:00
|
|
|
{
|
2024-11-01 12:21:15 -04:00
|
|
|
if (m_mode != e_idle) {
|
|
|
|
m_mode = e_idle;
|
2023-10-04 02:56:16 -04:00
|
|
|
|
2023-12-13 05:48:14 -05:00
|
|
|
m_copyFlags.m_bit0 = FALSE;
|
2023-10-04 02:56:16 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
TickleManager()->UnregisterClient(this);
|
2023-10-04 02:56:16 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
if (p_notifyWorld) {
|
2024-02-02 12:18:46 -05:00
|
|
|
LegoWorld* world = CurrentWorld();
|
2023-10-04 02:56:16 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
if (world) {
|
2024-01-07 12:30:45 -05:00
|
|
|
#ifdef COMPAT_MODE
|
|
|
|
{
|
2024-01-17 11:53:53 -05:00
|
|
|
MxNotificationParam param(c_notificationTransitioned, this);
|
2024-01-07 12:30:45 -05:00
|
|
|
world->Notify(param);
|
|
|
|
}
|
|
|
|
#else
|
2024-01-17 11:53:53 -05:00
|
|
|
world->Notify(MxNotificationParam(c_notificationTransitioned, this));
|
2024-01-07 12:30:45 -05:00
|
|
|
#endif
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-03 18:03:10 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004bcf0
|
2024-03-11 21:23:31 -04:00
|
|
|
void MxTransitionManager::NoTransition()
|
2023-11-21 03:44:45 -05:00
|
|
|
{
|
|
|
|
LegoVideoManager* videoManager = VideoManager();
|
2024-01-17 11:53:53 -05:00
|
|
|
videoManager->GetDisplaySurface()->ClearScreen();
|
2023-11-21 03:44:45 -05:00
|
|
|
EndTransition(TRUE);
|
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004bd10
|
2024-03-11 04:57:58 -04:00
|
|
|
void MxTransitionManager::DissolveTransition()
|
2023-10-03 18:03:10 -04:00
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
// 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...
|
|
|
|
MxS32 i;
|
|
|
|
for (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, DDLOCK_WAIT, NULL);
|
|
|
|
if (res == DDERR_SURFACELOST) {
|
|
|
|
m_ddSurface->Restore();
|
|
|
|
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res == DD_OK) {
|
|
|
|
SubmitCopyRect(&ddsd);
|
|
|
|
|
|
|
|
for (MxS32 col = 0; col < 640; col++) {
|
|
|
|
// Select 16 columns on each tick
|
2024-02-01 15:42:10 -05:00
|
|
|
if (m_animationTimer * 16 > m_columnOrder[col]) {
|
2023-10-24 19:38:27 -04:00
|
|
|
continue;
|
2024-02-01 15:42:10 -05:00
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-02-01 15:42:10 -05:00
|
|
|
if (m_animationTimer * 16 + 15 < m_columnOrder[col]) {
|
2023-10-24 19:38:27 -04:00
|
|
|
continue;
|
2024-02-01 15:42:10 -05:00
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
|
|
|
for (MxS32 row = 0; row < 480; row++) {
|
|
|
|
// 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.
|
2023-12-13 05:48:14 -05:00
|
|
|
MxS32 xShift = (m_randomShift[row] + col) % 640;
|
2023-10-24 19:38:27 -04:00
|
|
|
|
|
|
|
// Set the chosen pixel to black
|
|
|
|
if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) {
|
2024-01-31 17:39:50 -05:00
|
|
|
MxU8* surf = (MxU8*) ddsd.lpSurface + ddsd.lPitch * row + xShift;
|
|
|
|
*surf = 0;
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
|
|
|
else {
|
2024-01-31 17:39:50 -05:00
|
|
|
MxU8* surf = (MxU8*) ddsd.lpSurface + ddsd.lPitch * row + xShift * 2;
|
|
|
|
*(MxU16*) surf = 0;
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetupCopyRect(&ddsd);
|
|
|
|
m_ddSurface->Unlock(ddsd.lpSurface);
|
|
|
|
|
2023-12-13 05:48:14 -05:00
|
|
|
if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) {
|
2023-10-24 19:38:27 -04:00
|
|
|
LPDIRECTDRAWSURFACE surf = VideoManager()->GetDisplaySurface()->GetDirectDrawSurface1();
|
2024-01-06 12:56:15 -05:00
|
|
|
surf->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT);
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
m_animationTimer++;
|
|
|
|
}
|
2023-10-03 18:03:10 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004bed0
|
2024-03-11 04:57:58 -04:00
|
|
|
void MxTransitionManager::MosaicTransition()
|
2023-10-05 18:51:34 -04:00
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
if (m_animationTimer == 16) {
|
|
|
|
m_animationTimer = 0;
|
|
|
|
EndTransition(TRUE);
|
|
|
|
return;
|
|
|
|
}
|
2024-03-11 17:33:43 -04:00
|
|
|
else {
|
|
|
|
if (m_animationTimer == 0) {
|
|
|
|
|
|
|
|
// Same init/shuffle steps as the dissolve transition, except that
|
|
|
|
// we are using big blocky pixels and only need 64 columns.
|
|
|
|
MxS32 i;
|
|
|
|
for (i = 0; i < 64; i++) {
|
|
|
|
m_columnOrder[i] = i;
|
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
for (i = 0; i < 64; i++) {
|
|
|
|
MxS32 swap = rand() % 64;
|
|
|
|
MxU16 t = m_columnOrder[i];
|
|
|
|
m_columnOrder[i] = m_columnOrder[swap];
|
|
|
|
m_columnOrder[swap] = t;
|
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
// The same is true here. We only need 48 rows.
|
|
|
|
for (i = 0; i < 48; i++) {
|
|
|
|
m_randomShift[i] = rand() % 64;
|
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
// Run one tick of the animation
|
|
|
|
DDSURFACEDESC ddsd;
|
|
|
|
memset(&ddsd, 0, sizeof(ddsd));
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, 1, NULL);
|
|
|
|
if (res == DDERR_SURFACELOST) {
|
|
|
|
m_ddSurface->Restore();
|
|
|
|
res = m_ddSurface->Lock(NULL, &ddsd, 1, NULL);
|
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
if (res == DD_OK) {
|
|
|
|
SubmitCopyRect(&ddsd);
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
for (MxS32 col = 0; col < 64; col++) {
|
|
|
|
// Select 4 columns on each tick
|
|
|
|
if (m_animationTimer * 4 > m_columnOrder[col]) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
if (m_animationTimer * 4 + 3 < m_columnOrder[col]) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
for (MxS32 row = 0; row < 48; row++) {
|
|
|
|
// To do the mosaic effect, we subdivide the 640x480 surface into
|
|
|
|
// 10x10 pixel blocks. At the chosen block, we sample the top-leftmost
|
|
|
|
// color and set the other 99 pixels to that value.
|
2024-01-31 17:39:50 -05:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
// First, get the offset of the 10x10 block that we will sample for this row.
|
|
|
|
MxS32 xShift = 10 * ((m_randomShift[row] + col) % 64);
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
// Combine xShift with this value to target the correct location in the buffer.
|
|
|
|
MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
// Seek to the sample position.
|
|
|
|
MxU8* source = (MxU8*) ddsd.lpSurface + 10 * row * ddsd.lPitch + bytesPerPixel * xShift;
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
// Sample byte or word depending on display mode.
|
|
|
|
MxU32 sample = bytesPerPixel == 1 ? *source : *(MxU16*) source;
|
2024-01-31 17:39:50 -05:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
// For each of the 10 rows in the 10x10 square:
|
|
|
|
for (MxS32 k = 10 * row; k < 10 * row + 10; k++) {
|
|
|
|
if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) {
|
|
|
|
// Optimization: If the pixel is only one byte, we can use memset
|
2024-03-11 17:37:45 -04:00
|
|
|
MxU8* pos = ((MxU8*) ddsd.lpSurface + k * ddsd.lPitch + xShift);
|
2024-03-11 17:33:43 -04:00
|
|
|
memset(pos, sample, 10);
|
2024-01-31 17:39:50 -05:00
|
|
|
}
|
2024-03-11 17:33:43 -04:00
|
|
|
else {
|
|
|
|
// Need to double xShift because it measures pixels not bytes
|
|
|
|
MxU16* pos = (MxU16*) ((MxU8*) ddsd.lpSurface + k * ddsd.lPitch + 2 * xShift);
|
2024-01-31 17:39:50 -05:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
for (MxS32 tt = 0; tt < 10; tt++) {
|
|
|
|
pos[tt] = sample;
|
|
|
|
}
|
2024-01-31 17:39:50 -05:00
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
SetupCopyRect(&ddsd);
|
|
|
|
m_ddSurface->Unlock(ddsd.lpSurface);
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) {
|
|
|
|
LPDIRECTDRAWSURFACE surf = VideoManager()->GetDisplaySurface()->GetDirectDrawSurface1();
|
|
|
|
surf->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT);
|
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-03-11 17:33:43 -04:00
|
|
|
m_animationTimer++;
|
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
2023-10-05 18:51:34 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004c170
|
2024-03-11 04:57:58 -04:00
|
|
|
void MxTransitionManager::WipeDownTransition()
|
2023-11-21 03:44:45 -05:00
|
|
|
{
|
|
|
|
// 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, DDLOCK_WAIT, NULL);
|
|
|
|
if (res == DDERR_SURFACELOST) {
|
|
|
|
m_ddSurface->Restore();
|
|
|
|
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, 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-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004c270
|
2024-03-11 04:57:58 -04:00
|
|
|
void MxTransitionManager::WindowsTransition()
|
2023-10-05 18:51:34 -04:00
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
if (m_animationTimer == 240) {
|
|
|
|
m_animationTimer = 0;
|
|
|
|
EndTransition(TRUE);
|
|
|
|
return;
|
|
|
|
}
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
DDSURFACEDESC ddsd;
|
|
|
|
memset(&ddsd, 0, sizeof(ddsd));
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
|
|
|
if (res == DDERR_SURFACELOST) {
|
|
|
|
m_ddSurface->Restore();
|
|
|
|
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
|
|
|
}
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
if (res == DD_OK) {
|
|
|
|
SubmitCopyRect(&ddsd);
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
MxU8* line = (MxU8*) ddsd.lpSurface + m_animationTimer * ddsd.lPitch;
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
|
|
|
|
MxS32 bytesPerLine = bytesPerPixel * 640;
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
memset(line, 0, bytesPerLine);
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
for (MxS32 i = m_animationTimer + 1; i < 480 - m_animationTimer; i++) {
|
|
|
|
line += ddsd.lPitch;
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
memset(line + m_animationTimer * bytesPerPixel, 0, bytesPerPixel);
|
|
|
|
memset(line + 640 + (-1 - m_animationTimer) * bytesPerPixel, 0, bytesPerPixel);
|
|
|
|
}
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
line += ddsd.lPitch;
|
|
|
|
memset(line, 0, bytesPerLine);
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
SetupCopyRect(&ddsd);
|
|
|
|
m_ddSurface->Unlock(ddsd.lpSurface);
|
2023-10-15 19:41:05 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
m_animationTimer++;
|
|
|
|
}
|
2023-10-05 18:51:34 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004c3e0
|
2024-03-11 04:57:58 -04:00
|
|
|
void MxTransitionManager::BrokenTransition()
|
2023-10-05 18:51:34 -04:00
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
// This function has no actual animation logic.
|
|
|
|
// It also never calls EndTransition to
|
|
|
|
// properly terminate the transition, so
|
|
|
|
// the game just hangs forever.
|
|
|
|
|
|
|
|
DDSURFACEDESC ddsd;
|
|
|
|
memset(&ddsd, 0, sizeof(ddsd));
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
|
|
|
|
|
|
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
|
|
|
if (res == DDERR_SURFACELOST) {
|
|
|
|
m_ddSurface->Restore();
|
|
|
|
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res == DD_OK) {
|
|
|
|
SubmitCopyRect(&ddsd);
|
|
|
|
SetupCopyRect(&ddsd);
|
|
|
|
m_ddSurface->Unlock(ddsd.lpSurface);
|
|
|
|
}
|
2023-10-05 18:51:34 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004c470
|
2023-10-24 19:38:27 -04:00
|
|
|
void MxTransitionManager::SetWaitIndicator(MxVideoPresenter* p_waitIndicator)
|
2023-10-04 09:43:34 -04:00
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
// End current wait indicator
|
|
|
|
if (m_waitIndicator != NULL) {
|
2024-01-17 11:53:53 -05:00
|
|
|
m_waitIndicator->GetAction()->SetFlags(m_waitIndicator->GetAction()->GetFlags() & ~MxDSAction::c_world);
|
2023-10-24 19:38:27 -04:00
|
|
|
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();
|
2024-01-14 16:49:11 -05:00
|
|
|
videoManager->UnregisterPresenter(*m_waitIndicator);
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2024-01-17 11:53:53 -05:00
|
|
|
if (m_waitIndicator->GetCurrentTickleState() < MxPresenter::e_streaming) {
|
2023-10-24 19:38:27 -04:00
|
|
|
m_waitIndicator->Tickle();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Disable copy rect
|
2023-12-13 05:48:14 -05:00
|
|
|
m_copyFlags.m_bit0 = FALSE;
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
2023-10-04 09:43:34 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004c4d0
|
2023-12-13 05:48:14 -05:00
|
|
|
void MxTransitionManager::SubmitCopyRect(LPDDSURFACEDESC p_ddsc)
|
2023-10-04 09:43:34 -04:00
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
// Check if the copy rect is setup
|
2023-12-13 05:48:14 -05:00
|
|
|
if (m_copyFlags.m_bit0 == FALSE || m_waitIndicator == NULL || m_copyBuffer == NULL) {
|
2023-10-24 19:38:27 -04:00
|
|
|
return;
|
|
|
|
}
|
2023-10-04 09:43:34 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
// Copy the copy rect onto the surface
|
|
|
|
MxU8* dst;
|
2023-10-04 09:43:34 -04:00
|
|
|
|
2023-12-13 05:48:14 -05:00
|
|
|
MxU32 bytesPerPixel = p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8;
|
2023-10-04 09:43:34 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
const MxU8* src = (const MxU8*) m_copyBuffer;
|
2023-10-04 09:43:34 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
MxS32 copyPitch;
|
|
|
|
copyPitch = ((m_copyRect.right - m_copyRect.left) + 1) * bytesPerPixel;
|
2023-10-04 09:43:34 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
MxS32 y;
|
2023-12-13 05:48:14 -05:00
|
|
|
dst = (MxU8*) p_ddsc->lpSurface + (p_ddsc->lPitch * m_copyRect.top) + (bytesPerPixel * m_copyRect.left);
|
2023-10-04 09:43:34 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
for (y = 0; y < m_copyRect.bottom - m_copyRect.top + 1; ++y) {
|
|
|
|
memcpy(dst, src, copyPitch);
|
|
|
|
src += copyPitch;
|
2023-12-13 05:48:14 -05:00
|
|
|
dst += p_ddsc->lPitch;
|
2023-10-24 19:38:27 -04:00
|
|
|
}
|
2023-10-04 09:43:34 -04:00
|
|
|
|
2023-10-24 19:38:27 -04:00
|
|
|
// Free the copy buffer
|
|
|
|
delete[] m_copyBuffer;
|
|
|
|
m_copyBuffer = NULL;
|
2023-10-04 09:43:34 -04:00
|
|
|
}
|
|
|
|
|
2023-12-06 07:10:45 -05:00
|
|
|
// FUNCTION: LEGO1 0x1004c580
|
2023-12-13 05:48:14 -05:00
|
|
|
void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc)
|
2023-10-04 09:43:34 -04:00
|
|
|
{
|
2023-10-24 19:38:27 -04:00
|
|
|
// Check if the copy rect is setup
|
2023-12-13 05:48:14 -05:00
|
|
|
if (m_copyFlags.m_bit0 == FALSE || m_waitIndicator == NULL) {
|
2023-10-24 19:38:27 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tickle wait indicator
|
|
|
|
m_waitIndicator->Tickle();
|
|
|
|
|
|
|
|
// Check if wait indicator has started
|
2024-01-17 11:53:53 -05:00
|
|
|
if (m_waitIndicator->GetCurrentTickleState() >= MxPresenter::e_streaming) {
|
2023-10-24 19:38:27 -04:00
|
|
|
// Setup the copy rect
|
2023-12-13 05:48:14 -05:00
|
|
|
MxU32 copyPitch = (p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8) *
|
2023-10-24 19:38:27 -04:00
|
|
|
(m_copyRect.right - m_copyRect.left + 1); // This uses m_copyRect, seemingly erroneously
|
2023-12-13 05:48:14 -05:00
|
|
|
MxU32 bytesPerPixel = p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8;
|
2023-10-24 19:38:27 -04:00
|
|
|
|
2023-12-21 10:52:42 -05:00
|
|
|
m_copyRect.left = m_waitIndicator->GetLocation().GetX();
|
|
|
|
m_copyRect.top = m_waitIndicator->GetLocation().GetY();
|
2023-10-24 19:38:27 -04:00
|
|
|
|
|
|
|
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 MxU8* src =
|
2023-12-13 05:48:14 -05:00
|
|
|
(const MxU8*) p_ddsc->lpSurface + m_copyRect.top * p_ddsc->lPitch + bytesPerPixel * m_copyRect.left;
|
2023-10-24 19:38:27 -04:00
|
|
|
|
|
|
|
m_copyBuffer = new MxU8[bytesPerPixel * width * height];
|
2024-02-01 15:42:10 -05:00
|
|
|
if (!m_copyBuffer) {
|
2023-10-24 19:38:27 -04:00
|
|
|
return;
|
2024-02-01 15:42:10 -05:00
|
|
|
}
|
2023-10-24 19:38:27 -04:00
|
|
|
|
|
|
|
// Copy into the copy buffer
|
|
|
|
MxU8* dst = m_copyBuffer;
|
|
|
|
|
|
|
|
for (MxS32 i = 0; i < (m_copyRect.bottom - m_copyRect.top + 1); i++) {
|
|
|
|
memcpy(dst, src, copyPitch);
|
2023-12-13 05:48:14 -05:00
|
|
|
src += p_ddsc->lPitch;
|
2023-10-24 19:38:27 -04:00
|
|
|
dst += copyPitch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup display surface
|
2024-01-17 11:53:53 -05:00
|
|
|
if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::c_bit5) != 0) {
|
2023-10-24 19:38:27 -04:00
|
|
|
MxDisplaySurface* displaySurface = VideoManager()->GetDisplaySurface();
|
2023-12-13 05:48:14 -05:00
|
|
|
MxBool und = FALSE;
|
|
|
|
displaySurface->VTable0x2c(
|
|
|
|
p_ddsc,
|
2023-11-25 14:08:10 -05:00
|
|
|
m_waitIndicator->GetBitmap(),
|
2023-10-24 19:38:27 -04:00
|
|
|
0,
|
|
|
|
0,
|
2023-12-21 10:52:42 -05:00
|
|
|
m_waitIndicator->GetLocation().GetX(),
|
|
|
|
m_waitIndicator->GetLocation().GetY(),
|
2023-10-24 19:38:27 -04:00
|
|
|
m_waitIndicator->GetWidth(),
|
|
|
|
m_waitIndicator->GetHeight(),
|
2023-12-13 05:48:14 -05:00
|
|
|
und
|
2023-10-24 19:38:27 -04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
MxDisplaySurface* displaySurface = VideoManager()->GetDisplaySurface();
|
2023-12-13 05:48:14 -05:00
|
|
|
displaySurface->VTable0x24(
|
|
|
|
p_ddsc,
|
2023-11-25 14:08:10 -05:00
|
|
|
m_waitIndicator->GetBitmap(),
|
2023-10-24 19:38:27 -04:00
|
|
|
0,
|
|
|
|
0,
|
2023-12-21 10:52:42 -05:00
|
|
|
m_waitIndicator->GetLocation().GetX(),
|
|
|
|
m_waitIndicator->GetLocation().GetY(),
|
2023-10-24 19:38:27 -04:00
|
|
|
m_waitIndicator->GetWidth(),
|
|
|
|
m_waitIndicator->GetHeight()
|
|
|
|
);
|
|
|
|
}
|
2023-10-04 09:43:34 -04:00
|
|
|
}
|