Merge branch 'master' into mxdsselectaction

This commit is contained in:
Christian Semmler 2023-10-06 09:02:51 -04:00
commit 25022ec78d
26 changed files with 793 additions and 111 deletions

View File

@ -140,6 +140,7 @@ add_library(lego1 SHARED
LEGO1/mxmatrix.cpp
LEGO1/mxmediamanager.cpp
LEGO1/mxmediapresenter.cpp
LEGO1/mxmidimanager.cpp
LEGO1/mxmidipresenter.cpp
LEGO1/mxmusicpresenter.cpp
LEGO1/mxnotificationmanager.cpp
@ -273,4 +274,4 @@ if (MSVC)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/incremental:no")
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "/incremental:no /debug")
set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "/incremental:no")
endif()
endif()

View File

@ -27,8 +27,8 @@ LegoInputManager::LegoInputManager()
m_joyid = -1;
m_joystickIndex = -1;
m_useJoystick = FALSE;
m_unk0x335 = 0;
m_unk0x336 = 0;
m_unk0x335 = FALSE;
m_unk0x336 = FALSE;
m_unk0x74 = 0x19;
m_timeout = 1000;
}

View File

@ -312,3 +312,9 @@ MxBool LegoOmni::vtable40()
// FIXME: Stub
return 0;
}
// OFFSET: LEGO1 0x100157a0
LegoWorld *GetCurrentWorld()
{
return LegoOmni::GetInstance()->GetCurrentWorld();
}

View File

@ -75,12 +75,16 @@ class LegoOmni : public MxOmni
LegoGameState *GetGameState() { return m_gameState; }
LegoNavController *GetNavController() { return m_navController; }
MxTransitionManager *GetTransitionManager() { return m_transitionManager; }
LegoWorld *GetCurrentWorld() { return m_currentWorld; }
private:
int m_unk68;
int m_unk6c;
LegoInputManager *m_inputMgr; // 0x70
char m_unk74[0x10];
undefined4 m_unk74;
undefined4 m_unk78;
LegoWorld *m_currentWorld;
undefined4 m_unk80;
LegoNavController *m_navController; // 0x84
Isle* m_isle; // 0x88
char m_unk8c[0x4];
@ -115,5 +119,6 @@ LegoBuildingManager* BuildingManager();
Isle* GetIsle();
LegoPlantManager* PlantManager();
MxBool KeyValueStringParse(char *, const char *, const char *);
LegoWorld *GetCurrentWorld();
#endif // LEGOOMNI_H

View File

@ -20,7 +20,21 @@ MxAudioManager::~MxAudioManager()
// OFFSET: LEGO1 0x100b8df0
void MxAudioManager::Init()
{
this->m_unk2c = 100;
this->m_volume = 100;
}
// OFFSET: LEGO1 0x10029910
MxS32 MxAudioManager::GetVolume()
{
return this->m_volume;
}
// OFFSET: LEGO1 0x100b8ea0
void MxAudioManager::SetVolume(MxS32 p_volume)
{
this->m_criticalSection.Enter();
this->m_volume = p_volume;
this->m_criticalSection.Leave();
}
// OFFSET: LEGO1 0x100b8e00

View File

@ -11,18 +11,20 @@ class MxAudioManager : public MxMediaManager
MxAudioManager();
virtual ~MxAudioManager() override;
virtual MxResult InitPresenters(); // vtable+14
virtual void Destroy(); // vtable+18
virtual MxResult InitPresenters() override; // vtable+14
virtual void Destroy() override; // vtable+18
virtual MxS32 GetVolume(); // vtable+28
virtual void SetVolume(MxS32 p_volume); // vtable+2c
private:
void LockedReinitialize(MxBool);
void LockedReinitialize(MxBool p_skipDestroy);
static MxS32 g_unkCount;
protected:
void Init();
undefined4 m_unk2c;
MxS32 m_volume; // 0x2c
};
#endif // MXAUDIOMANAGER_H

View File

@ -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;
}
@ -230,3 +230,9 @@ undefined4 MxDisplaySurface::vtable44(undefined4, undefined4*, undefined4, undef
{
return 0;
}
// OFFSET: LEGO1 0x100ba640 STUB
void MxDisplaySurface::FUN_100ba640()
{
// TODO
}

View File

@ -19,13 +19,15 @@ class MxDisplaySurface : public MxCore
void Reset();
void FUN_100ba640();
virtual MxResult Init(MxVideoParam &p_videoParam, LPDIRECTDRAWSURFACE p_ddSurface1, LPDIRECTDRAWSURFACE p_ddSurface2, LPDIRECTDRAWCLIPPER p_ddClipper);
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);
@ -33,6 +35,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:

View File

@ -16,8 +16,10 @@ class MxDSAction : public MxDSObject
{
Flag_Looping = 0x01,
Flag_Bit3 = 0x04,
Flag_Bit5 = 0x10,
Flag_Enabled = 0x20,
Flag_Parsed = 0x80,
Flag_Bit9 = 0x200,
};
__declspec(dllexport) MxDSAction();
@ -52,16 +54,18 @@ class MxDSAction : public MxDSObject
void AppendData(MxU16 p_extraLength, const char *p_extraData);
inline MxU32 GetFlags() { return this->m_flags; }
inline void SetFlags(MxU32 m_flags) { this->m_flags = m_flags; }
inline MxU32 GetFlags() { return m_flags; }
inline void SetFlags(MxU32 p_flags) { m_flags = p_flags; }
inline char *GetExtraData() { return m_extraData; }
inline MxU16 GetExtraLength() const { return m_extraLength; }
inline MxLong GetStartTime() const { return m_startTime; }
inline MxS32 GetLoopCount() { return m_loopCount; }
inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; }
inline const MxVector3Data &GetLocation() const { return m_location; }
inline void SetOmni(MxOmni *p_omni) { m_omni = p_omni; }
inline MxBool IsLooping() const { return this->m_flags & Flag_Looping; }
inline MxBool IsBit3() const { return this->m_flags & Flag_Bit3; }
inline MxBool IsLooping() const { return m_flags & Flag_Looping; }
inline MxBool IsBit3() const { return m_flags & Flag_Bit3; }
private:
MxU32 m_sizeOnDisk;

View File

@ -4,20 +4,28 @@
DECOMP_SIZE_ASSERT(MxLoopingFlcPresenter, 0x6c);
// OFFSET: LEGO1 0x100b4310 STUB
// OFFSET: LEGO1 0x100b4310
MxLoopingFlcPresenter::MxLoopingFlcPresenter()
{
// TODO
Init();
}
// OFFSET: LEGO1 0x100b43b0 STUB
MxLoopingFlcPresenter::~MxLoopingFlcPresenter()
{
// TODO
Destroy(TRUE);
}
// OFFSET: LEGO1 0x100b4410 STUB
// OFFSET: LEGO1 0x100b4410
void MxLoopingFlcPresenter::Init()
{
// TODO
this->m_unk68 = 0;
this->m_flags &= 0xfd;
this->m_flags &= 0xfb;
}
// OFFSET: LEGO1 0x100b4432 STUB
void MxLoopingFlcPresenter::Destroy(MxBool p_param)
{
// TODO
}

View File

@ -22,6 +22,8 @@ class MxLoopingFlcPresenter : public MxFlcPresenter
private:
void Init();
void Destroy(MxBool);
undefined4 m_unk68;
};

View File

@ -10,14 +10,22 @@ MxLoopingSmkPresenter::MxLoopingSmkPresenter()
Init();
}
// OFFSET: LEGO1 0x100b4950 STUB
// OFFSET: LEGO1 0x100b4950
MxLoopingSmkPresenter::~MxLoopingSmkPresenter()
{
// TODO
Destroy(TRUE);
}
// OFFSET: LEGO1 0x100b49b0 STUB
// OFFSET: LEGO1 0x100b49b0
void MxLoopingSmkPresenter::Init()
{
// TODO
this->m_unk720 = 0;
this->m_flags &= 0xfd;
this->m_flags &= 0xfb;
}
// OFFSET: LEGO1 0x100b49d0 STUB
void MxLoopingSmkPresenter::Destroy(MxBool p_bool)
{
// TODO - theres a chain of destroy and free function calls here (FUN_100b4300 -> FUN_100b3900 -> FUN_100c5d40 -> function at 0x100b27b0)
}

View File

@ -22,6 +22,8 @@ class MxLoopingSmkPresenter : public MxSmkPresenter
private:
void Init();
void Destroy(MxBool);
undefined4 m_unk720;
};

View File

@ -17,3 +17,9 @@ void MxMediaPresenter::Init()
this->m_unk48 = NULL;
this->m_unk4c = NULL;
}
// OFFSET: LEGO1 0x100b5f10 STUB
void MxMediaPresenter::VTable0x58()
{
// TODO
}

View File

@ -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;

161
LEGO1/mxmidimanager.cpp Normal file
View File

@ -0,0 +1,161 @@
#include "mxmidimanager.h"
#include "mxomni.h"
#include <windows.h>
DECOMP_SIZE_ASSERT(MxMIDIManager, 0x58);
// OFFSET: LEGO1 0x100c05a0
MxMIDIManager::MxMIDIManager()
{
Init();
}
// OFFSET: LEGO1 0x100c0630
MxMIDIManager::~MxMIDIManager()
{
LockedReinitialize(TRUE);
}
// OFFSET: LEGO1 0x100c0b20
void MxMIDIManager::DeinitializeMIDI()
{
m_criticalSection.Enter();
if (this->m_MIDIInitialized)
{
this->m_MIDIInitialized = FALSE;
midiStreamStop(this->m_MIDIStreamH);
midiOutUnprepareHeader(this->m_MIDIStreamH, this->m_MIDIHdrP, sizeof(MIDIHDR));
midiOutSetVolume(this->m_MIDIStreamH, this->m_MIDIVolume);
midiStreamClose(this->m_MIDIStreamH);
delete this->m_MIDIHdrP;
this->InitData();
}
this->m_criticalSection.Leave();
}
// OFFSET: LEGO1 0x100c0690
void MxMIDIManager::Init()
{
this->m_multiplier = 100;
InitData();
}
// OFFSET: LEGO1 0x100c06a0
void MxMIDIManager::InitData()
{
this->m_MIDIStreamH = 0;
this->m_MIDIInitialized = FALSE;
this->m_unk38 = 0;
this->m_unk3c = 0;
this->m_unk40 = 0;
this->m_unk44 = 0;
this->m_unk48 = 0;
this->m_MIDIHdrP = NULL;
}
// OFFSET: LEGO1 0x100c06c0
void MxMIDIManager::LockedReinitialize(MxBool p_skipDestroy)
{
if (this->m_thread)
{
this->m_thread->Terminate();
if (this->m_thread)
{
delete m_thread;
}
}
else
{
TickleManager()->UnregisterClient(this);
}
this->m_criticalSection.Enter();
DeinitializeMIDI();
Init();
this->m_criticalSection.Leave();
if (!p_skipDestroy)
{
MxAudioManager::Destroy();
}
}
// OFFSET: LEGO1 0x100c0930
void MxMIDIManager::Destroy()
{
LockedReinitialize(FALSE);
}
// OFFSET: LEGO1 0x100c09a0
MxS32 MxMIDIManager::CalculateVolume(MxS32 p_volume)
{
MxS32 result = (p_volume * 0xffff) / 100;
return (result << 0x10) | result;
}
// OFFSET: LEGO1 0x100c07f0
void MxMIDIManager::SetMIDIVolume()
{
MxS32 result = (this->m_volume * this->m_multiplier) / 0x64;
HMIDISTRM streamHandle = this->m_MIDIStreamH;
if (streamHandle)
{
MxS32 volume = CalculateVolume(result);
midiOutSetVolume(streamHandle, volume);
}
}
// OFFSET: LEGO1 0x100c0940
void MxMIDIManager::SetVolume(MxS32 p_volume)
{
MxAudioManager::SetVolume(p_volume);
this->m_criticalSection.Enter();
SetMIDIVolume();
this->m_criticalSection.Leave();
}
// OFFSET: LEGO1 0x100c0840
MxResult MxMIDIManager::StartMIDIThread(MxU32 p_frequencyMS, MxBool p_noRegister)
{
MxResult status = FAILURE;
MxBool locked = FALSE;
MxResult result = MxAudioManager::InitPresenters();
if (result == SUCCESS)
{
if (p_noRegister)
{
this->m_criticalSection.Enter();
locked = TRUE;
this->m_thread = new MxTickleThread(this, p_frequencyMS);
if (this->m_thread)
{
if (this->m_thread->Start(0, 0) == SUCCESS)
{
status = SUCCESS;
}
}
}
else
{
TickleManager()->RegisterClient(this, p_frequencyMS);
status = SUCCESS;
}
}
if (status != SUCCESS)
{
Destroy();
}
if (locked)
{
this->m_criticalSection.Leave();
}
return status;
}

42
LEGO1/mxmidimanager.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef MXMIDIMANAGER_H
#define MXMIDIMANAGER_H
#include "decomp.h"
#include "mxaudiomanager.h"
// VTABLE 0x100dc930
// SIZE 0x58
class MxMIDIManager : public MxAudioManager
{
public:
MxMIDIManager();
virtual ~MxMIDIManager() override;
virtual void Destroy() override; // vtable+18
virtual void SetVolume(MxS32 p_volume) override; // vtable+2c
virtual MxResult StartMIDIThread(MxU32 p_frequencyMS, MxU8 p_noRegister); // vtable+30
private:
void LockedReinitialize(MxBool p_skipDestroy);
void DeinitializeMIDI();
MxS32 CalculateVolume(MxS32 p_volume);
void SetMIDIVolume();
HMIDISTRM m_MIDIStreamH; // 0x30
MxBool m_MIDIInitialized; // 0x34
undefined4 m_unk38; // 0x38
undefined4 m_unk3c; // 0x3c
undefined4 m_unk40; // 0x40
undefined4 m_unk44; // 0x44
undefined4 m_unk48; // 0x48
MIDIHDR *m_MIDIHdrP; // 0x4c
MxS32 m_multiplier; // 0x50
DWORD m_MIDIVolume; // 0x54
protected:
void Init();
void InitData();
};
#endif // MXMIDIMANAGER_H

View File

@ -68,7 +68,10 @@ 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; }
protected:
__declspec(dllexport) void Init();

View File

@ -1,21 +1,49 @@
#include "mxsoundmanager.h"
#include "mxomni.h"
DECOMP_SIZE_ASSERT(MxSoundManager, 0x3c);
// OFFSET: LEGO1 0x100ae740
MxSoundManager::MxSoundManager()
{
Init();
}
// OFFSET: LEGO1 0x100ae7d0 STUB
// OFFSET: LEGO1 0x100ae7d0
MxSoundManager::~MxSoundManager()
{
// TODO
Destroy(TRUE);
}
// OFFSET: LEGO1 0x100ae830
void MxSoundManager::Init()
{
m_unk30 = 0;
m_unk34 = 0;
m_dsBuffer = NULL;
}
// OFFSET: LEGO1 0x100ae840
void MxSoundManager::Destroy(MxBool p_param)
{
if (this->m_thread) {
this->m_thread->Terminate();
delete this->m_thread;
}
else {
TickleManager()->UnregisterClient(this);
}
this->m_criticalSection.Enter();
if (this->m_dsBuffer) {
this->m_dsBuffer->Release();
}
Init();
this->m_criticalSection.Leave();
if (!p_param) {
MxAudioManager::Destroy();
}
}

View File

@ -1,11 +1,13 @@
#ifndef MXSOUNDMANAGER_H
#define MXSOUNDMANAGER_H
#include "decomp.h"
#include "mxaudiomanager.h"
#include <dsound.h>
// VTABLE 0x100dc128
// SIZE 0x3c
// Base vtables are: MxCore -> 0x100dc6b0 -> MxAudioManager -> MxSoundManager
class MxSoundManager : public MxAudioManager
{
public:
@ -14,8 +16,11 @@ class MxSoundManager : public MxAudioManager
private:
void Init();
int m_unk30;
int m_unk34;
void Destroy(MxBool);
undefined4 m_unk30;
LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x34
undefined m_unk35[4];
};
#endif // MXSOUNDMANAGER_H

View File

@ -24,6 +24,8 @@ class MxThread
protected:
MxThread();
public:
virtual ~MxThread();
private:

View File

@ -4,15 +4,18 @@
DECOMP_SIZE_ASSERT(MxTransitionManager, 0x900);
// 0x100f4378
RECT g_fullScreenRect = {0, 0, 640, 480};
// OFFSET: LEGO1 0x1004b8d0
MxTransitionManager::MxTransitionManager()
{
m_animationTimer = 0;
m_transitionType = NOT_TRANSITIONING;
m_ddSurface = NULL;
m_unk08 = 0;
m_unk1c = 0;
m_unk20.bit0 = FALSE;
m_waitIndicator = NULL;
m_copyBuffer = NULL;
m_copyFlags.bit0 = FALSE;
m_unk28.bit0 = FALSE;
m_unk24 = 0;
}
@ -20,28 +23,146 @@ MxTransitionManager::MxTransitionManager()
// OFFSET: LEGO1 0x1004ba00
MxTransitionManager::~MxTransitionManager()
{
free(m_unk1c);
free(m_copyBuffer);
if (m_unk08 != NULL) {
delete m_unk08->m_unk1c;
delete m_unk08;
if (m_waitIndicator != NULL) {
delete m_waitIndicator->GetAction();
delete m_waitIndicator;
}
TickleManager()->UnregisterClient(this);
}
// OFFSET: LEGO1 0x1004bac0 STUB
// OFFSET: LEGO1 0x1004bac0
MxResult MxTransitionManager::Tickle()
{
// TODO
if (this->m_animationSpeed + this->m_systemTime > timeGetTime()) {
return SUCCESS;
}
return 0;
this->m_systemTime = timeGetTime();
switch (this->m_transitionType) {
case NO_ANIMATION:
Transition_None();
break;
case DISSOLVE:
Transition_Dissolve();
break;
case PIXELATION:
Transition_Pixelation();
break;
case SCREEN_WIPE:
Transition_Wipe();
break;
case WINDOWS:
Transition_Windows();
break;
case BROKEN:
Transition_Broken();
break;
}
return SUCCESS;
}
// OFFSET: LEGO1 0x1004c470 STUB
void MxTransitionManager::SetWaitIndicator(MxVideoPresenter *videoPresenter)
// OFFSET: LEGO1 0x1004bc30
void MxTransitionManager::EndTransition(MxBool p_notifyWorld)
{
// TODO
if (m_transitionType != NOT_TRANSITIONING) {
m_transitionType = NOT_TRANSITIONING;
m_copyFlags.bit0 = FALSE;
TickleManager()->UnregisterClient(this);
if (p_notifyWorld) {
LegoWorld *world = GetCurrentWorld();
if (world) {
world->Notify(MxParam(0x18, this));
}
}
}
}
// 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) {
SubmitCopyRect(&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;
}
}
}
SetupCopyRect(&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 0x1004baa0
@ -54,7 +175,7 @@ MxResult MxTransitionManager::GetDDrawSurfaceFromVideoManager() // vtable+0x14
// OFFSET: LEGO1 0x1004bb70
MxResult MxTransitionManager::StartTransition(TransitionType p_animationType, MxS32 p_speed,
MxBool p_unk, MxBool p_playMusicInAnim)
MxBool p_doCopy, MxBool p_playMusicInAnim)
{
if (this->m_transitionType == NOT_TRANSITIONING) {
if (!p_playMusicInAnim) {
@ -64,14 +185,14 @@ MxResult MxTransitionManager::StartTransition(TransitionType p_animationType, Mx
this->m_transitionType = p_animationType;
m_unk20.bit0 = p_unk;
m_copyFlags.bit0 = p_doCopy;
if (m_unk20.bit0 && m_unk08 != NULL) {
m_unk08->vtable54(1);
if (m_copyFlags.bit0 && m_waitIndicator != NULL) {
m_waitIndicator->Enable(TRUE);
MxTransitionManagerUnknownSubclass2 *iVar2 = m_unk08->m_unk1c;
iVar2->m_unk3c = 10000;
iVar2->m_unk30 |= 0x200;
MxDSAction *action = m_waitIndicator->GetAction();
action->SetLoopCount(10000);
action->SetFlags(action->GetFlags() | MxDSAction::Flag_Bit9);
}
MxU32 time = timeGetTime();
@ -94,3 +215,186 @@ MxResult MxTransitionManager::StartTransition(TransitionType p_animationType, Mx
}
return FAILURE;
}
// OFFSET: LEGO1 0x1004bcf0
void MxTransitionManager::Transition_None()
{
LegoVideoManager *videoManager = VideoManager();
videoManager->GetDisplaySurface()->FUN_100ba640();
EndTransition(TRUE);
}
// OFFSET: LEGO1 0x1004bed0 STUB
void MxTransitionManager::Transition_Pixelation()
{
// TODO
}
// OFFSET: LEGO1 0x1004c270 STUB
void MxTransitionManager::Transition_Windows()
{
// TODO
}
// OFFSET: LEGO1 0x1004c3e0 STUB
void MxTransitionManager::Transition_Broken()
{
// TODO
}
// 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++;
}
}
// OFFSET: LEGO1 0x1004c470
void MxTransitionManager::SetWaitIndicator(MxVideoPresenter *p_waitIndicator)
{
// 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(LPDDSURFACEDESC 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
void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC ddsc)
{
// 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());
}
}

View File

@ -5,52 +5,6 @@
#include "mxvideopresenter.h"
#include "legoomni.h"
class MxTransitionManagerUnknownSubclass2
{
public:
virtual ~MxTransitionManagerUnknownSubclass2(){}
undefined m_unk04[0x2c];
undefined4 m_unk30;
undefined4 m_unk34;
undefined4 m_unk38;
undefined4 m_unk3c;
};
// TODO: Don't know what this is yet
class MxTransitionManagerUnknownSubclass1
{
public:
virtual ~MxTransitionManagerUnknownSubclass1(){}
virtual void vtable04();
virtual void vtable08();
virtual void vtable0c();
virtual void vtable10();
virtual void vtable14();
virtual void vtable18();
virtual void vtable1c();
virtual void vtable20();
virtual void vtable24();
virtual void vtable28();
virtual void vtable2c();
virtual void vtable30();
virtual void vtable34();
virtual void vtable38();
virtual void vtable3c();
virtual void vtable40();
virtual void vtable44();
virtual void vtable48();
virtual void vtable4c();
virtual void vtable50();
virtual void vtable54(undefined4 p_unk1);
undefined m_unk04[0x18];
MxTransitionManagerUnknownSubclass2 *m_unk1c;
};
// VTABLE 0x100d7ea0
class MxTransitionManager : public MxCore
{
@ -58,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
@ -86,25 +40,36 @@ class MxTransitionManager : public MxCore
BROKEN // Unknown what this is supposed to be, it locks the game up
};
MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_unk, MxBool p_playMusicInAnim);
MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim);
private:
MxTransitionManagerUnknownSubclass1 *m_unk08;
undefined4 m_unk0c;
undefined4 m_unk10;
undefined4 m_unk14;
undefined4 m_unk18;
void *m_unk1c;
flag_bitfield m_unk20;
void EndTransition(MxBool p_notifyWorld);
void Transition_None();
void Transition_Dissolve();
void Transition_Pixelation();
void Transition_Wipe();
void Transition_Windows();
void Transition_Broken();
void SubmitCopyRect(LPDDSURFACEDESC ddsc);
void SetupCopyRect(LPDDSURFACEDESC ddsc);
MxVideoPresenter *m_waitIndicator;
RECT m_copyRect;
void *m_copyBuffer;
flag_bitfield m_copyFlags;
undefined4 m_unk24;
flag_bitfield m_unk28;
TransitionType m_transitionType;
LPDIRECTDRAWSURFACE m_ddSurface;
MxU16 m_animationTimer;
undefined m_pad36[0x8c2];
MxULong m_systemTime;
MxS32 m_animationSpeed;
MxU16 m_columnOrder[640]; // 0x36
MxU16 m_randomShift[480]; // 0x536
MxULong m_systemTime; // 0x8f8
MxS32 m_animationSpeed; // 0x8fc
};
#endif // MXTRANSITIONMANAGER_H

View File

@ -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
}

View File

@ -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;

View File

@ -114,7 +114,7 @@ def __init__(self, unix_cwd):
def get_wine_path(self, unix_fn: str) -> str:
if unix_fn.startswith('./'):
return self.win_cmd + '\\' + unix_fn[2:].replace('/', '\\')
return self.win_cwd + '\\' + unix_fn[2:].replace('/', '\\')
if unix_fn.startswith(self.unix_cwd):
return self.win_cwd + '\\' + unix_fn.removeprefix(self.unix_cwd).replace('/', '\\').lstrip('\\')
return self._call_winepath_unix2win(unix_fn)