mirror of
https://github.com/isledecomp/isle.git
synced 2025-10-23 00:14:22 +00:00
Move some classes to LegoOmni (#417)
This commit is contained in:

committed by
GitHub

parent
c47206617d
commit
091ecd5935
@@ -140,15 +140,12 @@ private:
|
||||
};
|
||||
|
||||
__declspec(dllexport) MxBackgroundAudioManager* BackgroundAudioManager();
|
||||
__declspec(dllexport) MxDSObject* CreateStreamObject(MxDSFile*, MxS16);
|
||||
__declspec(dllexport) LegoGameState* GameState();
|
||||
__declspec(dllexport) const char* GetNoCD_SourceName();
|
||||
__declspec(dllexport) LegoInputManager* InputManager();
|
||||
__declspec(dllexport) LegoOmni* Lego();
|
||||
__declspec(dllexport) void MakeSourceName(char*, const char*);
|
||||
__declspec(dllexport) LegoEntity* PickEntity(MxLong, MxLong);
|
||||
__declspec(dllexport) LegoROI* PickROI(MxLong, MxLong);
|
||||
__declspec(dllexport) void SetOmniUserMessage(void (*)(const char*, int));
|
||||
__declspec(dllexport) LegoSoundManager* SoundManager();
|
||||
__declspec(dllexport) MxResult Start(MxDSAction*);
|
||||
__declspec(dllexport) MxTransitionManager* TransitionManager();
|
||||
@@ -159,26 +156,12 @@ LegoBuildingManager* BuildingManager();
|
||||
LegoControlManager* ControlManager();
|
||||
IslePathActor* GetCurrentVehicle();
|
||||
LegoPlantManager* PlantManager();
|
||||
MxBool KeyValueStringParse(char*, const char*, const char*);
|
||||
LegoWorld* GetCurrentWorld();
|
||||
GifManager* GetGifManager();
|
||||
void FUN_10015820(MxU32, MxU32);
|
||||
LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid);
|
||||
MxDSAction& GetCurrentAction();
|
||||
|
||||
MxBool FUN_100b6e10(
|
||||
MxS32 p_bitmapWidth,
|
||||
MxS32 p_bitmapHeight,
|
||||
MxS32 p_videoParamWidth,
|
||||
MxS32 p_videoParamHeight,
|
||||
MxS32* p_left,
|
||||
MxS32* p_top,
|
||||
MxS32* p_right,
|
||||
MxS32* p_bottom,
|
||||
MxS32* p_width,
|
||||
MxS32* p_height
|
||||
);
|
||||
|
||||
void PlayMusic(MxU32 p_index);
|
||||
void SetIsWorldActive(MxBool p_isWorldActive);
|
||||
void RegisterScripts();
|
||||
|
@@ -2,58 +2,13 @@
|
||||
#define LEGOUTIL_H
|
||||
|
||||
#include "extra.h"
|
||||
#include "legoentity.h"
|
||||
#include "mxatomid.h"
|
||||
#include "mxtypes.h"
|
||||
#include "mxutil.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
template <class T>
|
||||
inline T Abs(T p_t)
|
||||
{
|
||||
return p_t < 0 ? -p_t : p_t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T Min(T p_t1, T p_t2)
|
||||
{
|
||||
return p_t1 < p_t2 ? p_t1 : p_t2;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T Max(T p_t1, T p_t2)
|
||||
{
|
||||
return p_t1 > p_t2 ? p_t1 : p_t2;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void GetScalar(MxU8** p_source, T& p_dest)
|
||||
{
|
||||
p_dest = *(T*) *p_source;
|
||||
*p_source += sizeof(T);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T GetScalar(T** p_source)
|
||||
{
|
||||
T val = **p_source;
|
||||
*p_source += 1;
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void GetDouble(MxU8** p_source, T& p_dest)
|
||||
{
|
||||
p_dest = *(double*) *p_source;
|
||||
*p_source += sizeof(double);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void GetString(MxU8** p_source, char** p_dest, T* p_obj, void (T::*p_setter)(const char*))
|
||||
{
|
||||
(p_obj->*p_setter)((char*) *p_source);
|
||||
*p_source += strlen(*p_dest) + 1;
|
||||
}
|
||||
class MxAtomId;
|
||||
class LegoEntity;
|
||||
|
||||
ExtraActionType MatchActionString(const char*);
|
||||
void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender);
|
||||
|
66
LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h
Normal file
66
LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef MXBACKGROUNDAUDIOMANAGER_H
|
||||
#define MXBACKGROUNDAUDIOMANAGER_H
|
||||
|
||||
#include "mxaudiopresenter.h"
|
||||
#include "mxcore.h"
|
||||
#include "mxdsaction.h"
|
||||
#include "mxnotificationmanager.h"
|
||||
#include "mxpresenter.h"
|
||||
#include "mxtypes.h"
|
||||
|
||||
// VTABLE: LEGO1 0x100d9fe8
|
||||
// SIZE 0x150
|
||||
class MxBackgroundAudioManager : public MxCore {
|
||||
public:
|
||||
MxBackgroundAudioManager();
|
||||
virtual ~MxBackgroundAudioManager() override;
|
||||
|
||||
virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04
|
||||
virtual MxResult Tickle() override; // vtable+0x08
|
||||
|
||||
// FUNCTION: LEGO1 0x1007eb70
|
||||
inline virtual const char* ClassName() const override // vtable+0x0c
|
||||
{
|
||||
// STRING: LEGO1 0x100f7ac4
|
||||
return "MxBackgroundAudioManager";
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007eb80
|
||||
inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10
|
||||
{
|
||||
return !strcmp(p_name, MxBackgroundAudioManager::ClassName()) || MxCore::IsA(p_name);
|
||||
}
|
||||
|
||||
void StartAction(MxParam& p_param);
|
||||
void StopAction(MxParam& p_param);
|
||||
MxResult PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, undefined4 p_unk0x13c);
|
||||
|
||||
void FUN_1007ee70();
|
||||
void FUN_1007ef40();
|
||||
void FadeInOrFadeOut();
|
||||
|
||||
__declspec(dllexport) void Enable(MxBool p_enable);
|
||||
virtual MxResult Create(MxAtomId& p_script, MxU32 p_frequencyMS);
|
||||
|
||||
void Stop();
|
||||
void LowerVolume();
|
||||
void RaiseVolume();
|
||||
|
||||
private:
|
||||
void Init();
|
||||
MxResult OpenMusic(MxAtomId& p_script);
|
||||
void DestroyMusic();
|
||||
|
||||
MxBool m_musicEnabled; // 0x8
|
||||
MxDSAction m_action1; // 0xc
|
||||
MxAudioPresenter* m_unk0xa0;
|
||||
MxDSAction m_action2; // 0xa4
|
||||
MxAudioPresenter* m_unk0x138;
|
||||
MxS32 m_unk0x13c;
|
||||
MxS32 m_unk0x140;
|
||||
MxS32 m_targetVolume;
|
||||
MxS16 m_unk0x148;
|
||||
MxAtomId m_script;
|
||||
};
|
||||
|
||||
#endif // MXBACKGROUNDAUDIOMANAGER_H
|
40
LEGO1/lego/legoomni/include/mxcompositemediapresenter.h
Normal file
40
LEGO1/lego/legoomni/include/mxcompositemediapresenter.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef MXCOMPOSITEMEDIAPRESENTER_H
|
||||
#define MXCOMPOSITEMEDIAPRESENTER_H
|
||||
|
||||
#include "mxcompositepresenter.h"
|
||||
|
||||
// VTABLE: LEGO1 0x100d96b0
|
||||
// SIZE 0x50
|
||||
class MxCompositeMediaPresenter : public MxCompositePresenter {
|
||||
public:
|
||||
MxCompositeMediaPresenter();
|
||||
virtual ~MxCompositeMediaPresenter() override;
|
||||
|
||||
virtual MxResult Tickle() override; // vtable+0x08
|
||||
|
||||
// FUNCTION: LEGO1 0x10073f10
|
||||
inline virtual const char* ClassName() const override // vtable+0x0c
|
||||
{
|
||||
// STRING: LEGO1 0x100f02d4
|
||||
return "MxCompositeMediaPresenter";
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10073f20
|
||||
inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10
|
||||
{
|
||||
return !strcmp(p_name, MxCompositeMediaPresenter::ClassName()) || MxCompositePresenter::IsA(p_name);
|
||||
}
|
||||
|
||||
virtual void StartingTickle() override; // vtable+0x1c
|
||||
virtual MxResult StartAction(MxStreamController*, MxDSAction* p_action) override; // vtable+0x3c
|
||||
virtual MxResult PutData() override; // vtable+0x4c
|
||||
|
||||
private:
|
||||
MxS16 m_unk0x4c; // 0x4c
|
||||
MxBool m_unk0x4e; // 0x4e
|
||||
};
|
||||
|
||||
// SYNTHETIC: LEGO1 0x10074000
|
||||
// MxCompositeMediaPresenter::`scalar deleting destructor'
|
||||
|
||||
#endif // MXCOMPOSITEMEDIAPRESENTER_H
|
75
LEGO1/lego/legoomni/include/mxtransitionmanager.h
Normal file
75
LEGO1/lego/legoomni/include/mxtransitionmanager.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef MXTRANSITIONMANAGER_H
|
||||
#define MXTRANSITIONMANAGER_H
|
||||
|
||||
#include "legoomni.h"
|
||||
#include "mxcore.h"
|
||||
#include "mxvideopresenter.h"
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
// VTABLE: LEGO1 0x100d7ea0
|
||||
class MxTransitionManager : public MxCore {
|
||||
public:
|
||||
MxTransitionManager();
|
||||
virtual ~MxTransitionManager() override; // vtable+0x0
|
||||
|
||||
__declspec(dllexport) void SetWaitIndicator(MxVideoPresenter* p_waitIndicator);
|
||||
|
||||
virtual MxResult Tickle(); // vtable+0x8
|
||||
|
||||
// FUNCTION: LEGO1 0x1004b950
|
||||
inline virtual const char* ClassName() const override // vtable+0x0c
|
||||
{
|
||||
return "MxTransitionManager";
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004b960
|
||||
inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10
|
||||
{
|
||||
return !strcmp(p_name, MxTransitionManager::ClassName()) || MxCore::IsA(p_name);
|
||||
}
|
||||
|
||||
virtual MxResult GetDDrawSurfaceFromVideoManager(); // vtable+0x14
|
||||
|
||||
enum TransitionType {
|
||||
NOT_TRANSITIONING,
|
||||
NO_ANIMATION,
|
||||
DISSOLVE,
|
||||
PIXELATION,
|
||||
SCREEN_WIPE,
|
||||
WINDOWS,
|
||||
BROKEN // Unknown what this is supposed to be, it locks the game up
|
||||
};
|
||||
|
||||
MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim);
|
||||
|
||||
inline TransitionType GetTransitionType() { return m_transitionType; }
|
||||
|
||||
private:
|
||||
void EndTransition(MxBool p_notifyWorld);
|
||||
void TransitionNone();
|
||||
void TransitionDissolve();
|
||||
void TransitionPixelation();
|
||||
void TransitionWipe();
|
||||
void TransitionWindows();
|
||||
void TransitionBroken();
|
||||
|
||||
void SubmitCopyRect(LPDDSURFACEDESC p_ddsc);
|
||||
void SetupCopyRect(LPDDSURFACEDESC p_ddsc);
|
||||
|
||||
MxVideoPresenter* m_waitIndicator; // 0x08
|
||||
RECT m_copyRect; // 0x0c
|
||||
MxU8* m_copyBuffer; // 0x1c
|
||||
FlagBitfield m_copyFlags; // 0x20
|
||||
undefined4 m_unk0x24; // 0x24
|
||||
FlagBitfield m_unk0x28; // 0x28
|
||||
TransitionType m_transitionType; // 0x2c
|
||||
LPDIRECTDRAWSURFACE m_ddSurface; // 0x30
|
||||
MxU16 m_animationTimer; // 0x34
|
||||
MxU16 m_columnOrder[640]; // 0x36
|
||||
MxU16 m_randomShift[480]; // 0x536
|
||||
MxULong m_systemTime; // 0x8f8
|
||||
MxS32 m_animationSpeed; // 0x8fc
|
||||
};
|
||||
|
||||
#endif // MXTRANSITIONMANAGER_H
|
326
LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp
Normal file
326
LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
#include "mxbackgroundaudiomanager.h"
|
||||
|
||||
#include "legoomni.h"
|
||||
#include "mxcompositepresenter.h"
|
||||
#include "mxdssound.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxpresenter.h"
|
||||
#include "mxstreamer.h"
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxBackgroundAudioManager, 0x150)
|
||||
|
||||
// FUNCTION: LEGO1 0x1007ea90
|
||||
MxBackgroundAudioManager::MxBackgroundAudioManager()
|
||||
{
|
||||
NotificationManager()->Register(this);
|
||||
m_unk0xa0 = 0;
|
||||
m_unk0x138 = 0;
|
||||
m_unk0x13c = 0;
|
||||
m_unk0x140 = 0;
|
||||
m_targetVolume = 0;
|
||||
m_unk0x148 = 0;
|
||||
m_musicEnabled = FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007ec20
|
||||
MxBackgroundAudioManager::~MxBackgroundAudioManager()
|
||||
{
|
||||
TickleManager()->UnregisterClient(this);
|
||||
NotificationManager()->Unregister(this);
|
||||
DestroyMusic();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007ece0
|
||||
MxResult MxBackgroundAudioManager::Create(MxAtomId& p_script, MxU32 p_frequencyMS)
|
||||
{
|
||||
MxResult result = OpenMusic(p_script);
|
||||
|
||||
if (result == SUCCESS) {
|
||||
TickleManager()->RegisterClient(this, p_frequencyMS);
|
||||
m_musicEnabled = TRUE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007ed20
|
||||
MxResult MxBackgroundAudioManager::OpenMusic(MxAtomId& p_script)
|
||||
{
|
||||
if (m_script.GetInternal())
|
||||
DestroyMusic();
|
||||
|
||||
MxResult result = FAILURE;
|
||||
|
||||
if (Streamer()->Open(p_script.GetInternal(), 0)) {
|
||||
m_script = p_script;
|
||||
result = SUCCESS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007ed70
|
||||
void MxBackgroundAudioManager::DestroyMusic()
|
||||
{
|
||||
if (m_script.GetInternal()) {
|
||||
MxDSAction ds;
|
||||
ds.SetAtomId(m_script);
|
||||
ds.SetUnknown24(-2);
|
||||
DeleteObject(ds);
|
||||
Streamer()->Close(m_script.GetInternal());
|
||||
m_musicEnabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007ee40
|
||||
MxResult MxBackgroundAudioManager::Tickle()
|
||||
{
|
||||
switch (m_unk0x13c) {
|
||||
case MxPresenter::TickleState_Starting:
|
||||
FadeInOrFadeOut();
|
||||
return SUCCESS;
|
||||
case MxPresenter::TickleState_Streaming:
|
||||
FUN_1007ee70();
|
||||
return SUCCESS;
|
||||
case MxPresenter::TickleState_Repeating:
|
||||
FUN_1007ef40();
|
||||
return SUCCESS;
|
||||
default:
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007ee70
|
||||
void MxBackgroundAudioManager::FUN_1007ee70()
|
||||
{
|
||||
if (m_unk0xa0 && m_unk0xa0->GetAction()) {
|
||||
DeleteObject(*m_unk0x138->GetAction());
|
||||
}
|
||||
|
||||
if (m_unk0x138) {
|
||||
m_unk0xa0 = m_unk0x138;
|
||||
m_action1 = m_action2;
|
||||
m_unk0x138 = NULL;
|
||||
m_action2.SetObjectId(-1);
|
||||
m_action2.SetAtomId(MxAtomId());
|
||||
m_unk0x13c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007ef40
|
||||
void MxBackgroundAudioManager::FUN_1007ef40()
|
||||
{
|
||||
MxU32 compare;
|
||||
MxU32 volume;
|
||||
if (m_unk0xa0 == NULL) {
|
||||
if (m_unk0x138) {
|
||||
compare = 30;
|
||||
if (m_unk0x148 == 0) {
|
||||
compare = m_unk0x148;
|
||||
}
|
||||
volume = m_unk0x138->GetVolume();
|
||||
if (volume < compare) {
|
||||
if (m_unk0x140 + m_unk0x138->GetVolume() <= compare) {
|
||||
compare = m_unk0x140 + compare;
|
||||
}
|
||||
m_unk0x138->SetVolume(compare);
|
||||
}
|
||||
else {
|
||||
m_unk0x138->SetVolume(compare);
|
||||
m_unk0xa0 = m_unk0x138;
|
||||
m_action1 = m_action2;
|
||||
m_unk0x138 = NULL;
|
||||
m_action2.SetObjectId(-1);
|
||||
m_action2.SetAtomId(MxAtomId());
|
||||
m_unk0x13c = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_unk0xa0->GetAction() != NULL) {
|
||||
if (m_unk0xa0->GetVolume() == 0) {
|
||||
DeleteObject(*m_unk0xa0->GetAction());
|
||||
}
|
||||
else {
|
||||
compare = m_unk0xa0->GetVolume();
|
||||
volume = 0;
|
||||
if (compare != m_unk0x140 && -1 < compare - m_unk0x140) {
|
||||
volume = m_unk0xa0->GetVolume() - m_unk0x140;
|
||||
}
|
||||
m_unk0x138->SetVolume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f0e0
|
||||
void MxBackgroundAudioManager::FadeInOrFadeOut()
|
||||
{
|
||||
// This function probably is the fade in/out routine
|
||||
if (m_unk0xa0 != NULL) {
|
||||
undefined4 volume = m_unk0xa0->GetVolume();
|
||||
MxU32 compare = 30;
|
||||
if (m_unk0x148 == 0) {
|
||||
compare = m_targetVolume;
|
||||
}
|
||||
|
||||
if (volume < compare) {
|
||||
volume = m_unk0x140 + volume;
|
||||
if (compare <= volume) {
|
||||
volume = compare;
|
||||
}
|
||||
m_unk0xa0->SetVolume(volume);
|
||||
}
|
||||
else if (compare < volume) {
|
||||
volume = volume - m_unk0x140;
|
||||
if (volume <= compare) {
|
||||
volume = compare;
|
||||
}
|
||||
m_unk0xa0->SetVolume(volume);
|
||||
}
|
||||
else {
|
||||
m_unk0xa0->SetVolume(volume);
|
||||
m_unk0x13c = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_unk0x13c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f170
|
||||
MxLong MxBackgroundAudioManager::Notify(MxParam& p_param)
|
||||
{
|
||||
switch (((MxNotificationParam&) p_param).GetNotification()) {
|
||||
case c_notificationStartAction:
|
||||
StartAction(p_param);
|
||||
return 1;
|
||||
case c_notificationEndAction:
|
||||
StopAction(p_param);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f1b0
|
||||
void MxBackgroundAudioManager::StartAction(MxParam& p_param)
|
||||
{
|
||||
// TODO: the sender is most likely a MxAudioPresenter?
|
||||
m_unk0x138 = (MxAudioPresenter*) ((MxNotificationParam&) p_param).GetSender();
|
||||
m_action2.SetAtomId(m_unk0x138->GetAction()->GetAtomId());
|
||||
m_action2.SetObjectId(m_unk0x138->GetAction()->GetObjectId());
|
||||
m_targetVolume = ((MxDSSound*) (m_unk0x138->GetAction()))->GetVolume();
|
||||
m_unk0x138->SetVolume(0);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f200
|
||||
void MxBackgroundAudioManager::StopAction(MxParam& p_param)
|
||||
{
|
||||
if (((MxNotificationParam&) p_param).GetSender() == m_unk0xa0) {
|
||||
m_unk0xa0 = NULL;
|
||||
m_action1.SetAtomId(MxAtomId());
|
||||
m_action1.SetObjectId(-1);
|
||||
}
|
||||
else if (((MxNotificationParam&) p_param).GetSender() == m_unk0x138) {
|
||||
m_unk0x138 = NULL;
|
||||
m_action2.SetAtomId(MxAtomId());
|
||||
m_action2.SetObjectId(-1);
|
||||
}
|
||||
|
||||
Lego()->HandleActionEnd(p_param);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f2f0
|
||||
MxResult MxBackgroundAudioManager::PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, undefined4 p_unk0x13c)
|
||||
{
|
||||
if (!m_musicEnabled) {
|
||||
return SUCCESS;
|
||||
}
|
||||
if (m_action2.GetObjectId() == -1 && m_action1.GetObjectId() != p_action.GetObjectId()) {
|
||||
MxDSAction action;
|
||||
action.SetAtomId(GetCurrentAction().GetAtomId());
|
||||
action.SetObjectId(GetCurrentAction().GetObjectId());
|
||||
action.SetUnknown24(GetCurrentAction().GetUnknown24());
|
||||
|
||||
m_action2.SetAtomId(p_action.GetAtomId());
|
||||
m_action2.SetObjectId(p_action.GetObjectId());
|
||||
m_action2.SetUnknown84(this);
|
||||
m_action2.SetOrigin(this);
|
||||
|
||||
MxResult result = Start(&m_action2);
|
||||
|
||||
GetCurrentAction().SetAtomId(action.GetAtomId());
|
||||
GetCurrentAction().SetObjectId(action.GetObjectId());
|
||||
GetCurrentAction().SetUnknown24(action.GetUnknown24());
|
||||
|
||||
if (result == SUCCESS) {
|
||||
m_unk0x13c = p_unk0x13c;
|
||||
m_unk0x140 = p_unk0x140;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f470
|
||||
void MxBackgroundAudioManager::Stop()
|
||||
{
|
||||
if (m_action2.GetObjectId() != -1)
|
||||
DeleteObject(m_action2);
|
||||
|
||||
m_unk0x138 = 0;
|
||||
m_action2.SetAtomId(MxAtomId());
|
||||
m_action2.SetObjectId(-1);
|
||||
|
||||
if (m_action1.GetObjectId() != -1)
|
||||
DeleteObject(m_action1);
|
||||
|
||||
m_unk0xa0 = 0;
|
||||
m_action1.SetAtomId(MxAtomId());
|
||||
m_unk0x148 = 0;
|
||||
m_action1.SetObjectId(-1);
|
||||
m_unk0x13c = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f570
|
||||
void MxBackgroundAudioManager::LowerVolume()
|
||||
{
|
||||
if (m_unk0x148 == 0) {
|
||||
if (m_unk0x13c == 0) {
|
||||
m_unk0x13c = 2;
|
||||
}
|
||||
m_unk0x140 = 20;
|
||||
}
|
||||
m_unk0x148++;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f5b0
|
||||
void MxBackgroundAudioManager::RaiseVolume()
|
||||
{
|
||||
if (m_unk0x148 != 0) {
|
||||
m_unk0x148--;
|
||||
if (m_unk0x148 == 0) {
|
||||
if (m_unk0x13c == 0) {
|
||||
m_unk0x13c = 2;
|
||||
}
|
||||
m_unk0x140 = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f5f0
|
||||
void MxBackgroundAudioManager::Enable(MxBool p_enable)
|
||||
{
|
||||
if (this->m_musicEnabled != p_enable) {
|
||||
this->m_musicEnabled = p_enable;
|
||||
if (!p_enable) {
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f650
|
||||
void MxBackgroundAudioManager::Init()
|
||||
{
|
||||
this->m_unk0xa0 = 0;
|
||||
this->m_unk0x13c = 0;
|
||||
}
|
172
LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp
Normal file
172
LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "mxcompositemediapresenter.h"
|
||||
|
||||
#include "legoomni.h"
|
||||
#include "legosoundmanager.h"
|
||||
#include "legovideomanager.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdsmultiaction.h"
|
||||
#include "mxmediapresenter.h"
|
||||
#include "mxobjectfactory.h"
|
||||
#include "mxtimer.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxCompositeMediaPresenter, 0x50)
|
||||
|
||||
// FUNCTION: LEGO1 0x10073ea0
|
||||
MxCompositeMediaPresenter::MxCompositeMediaPresenter()
|
||||
{
|
||||
m_unk0x4c = 0;
|
||||
m_unk0x4e = FALSE;
|
||||
VideoManager()->AddPresenter(*this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10074020
|
||||
MxCompositeMediaPresenter::~MxCompositeMediaPresenter()
|
||||
{
|
||||
VideoManager()->RemovePresenter(*this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10074090
|
||||
MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxResult result = FAILURE;
|
||||
MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList();
|
||||
MxDSActionListCursor cursor(actions);
|
||||
MxDSAction* action;
|
||||
|
||||
if (MxPresenter::StartAction(p_controller, p_action) == SUCCESS) {
|
||||
// The usual cursor.Next() loop doesn't match here, even though
|
||||
// the logic is the same. It does match when "deconstructed" into
|
||||
// the following Head(), Current() and NextFragment() calls,
|
||||
// but this seems unlikely to be the original code.
|
||||
// The alpha debug build also uses Next().
|
||||
// cursor.Head();
|
||||
// while (cursor.Current(action)) {
|
||||
// cursor.NextFragment();
|
||||
while (cursor.Next(action)) {
|
||||
MxBool success = FALSE;
|
||||
|
||||
action->CopyFlags(m_action->GetFlags());
|
||||
|
||||
const char* presenterName = PresenterNameDispatch(*action);
|
||||
MxPresenter* presenter = (MxPresenter*) ObjectFactory()->Create(presenterName);
|
||||
|
||||
if (presenter && presenter->AddToManager() == SUCCESS) {
|
||||
presenter->SetCompositePresenter(this);
|
||||
if (presenter->StartAction(p_controller, action) == SUCCESS) {
|
||||
presenter->SetTickleState(TickleState_Idle);
|
||||
|
||||
if (presenter->IsA("MxVideoPresenter"))
|
||||
VideoManager()->RemovePresenter(*presenter);
|
||||
else if (presenter->IsA("MxAudioPresenter"))
|
||||
SoundManager()->RemovePresenter(*presenter);
|
||||
|
||||
success = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
action->SetOrigin(this);
|
||||
m_list.push_back(presenter);
|
||||
}
|
||||
else if (presenter)
|
||||
delete presenter;
|
||||
}
|
||||
|
||||
if (!m_compositePresenter) {
|
||||
SetTickleState(TickleState_Ready);
|
||||
MxLong time = Timer()->GetTime();
|
||||
m_action->SetUnknown90(time);
|
||||
}
|
||||
|
||||
result = SUCCESS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100742e0
|
||||
void MxCompositeMediaPresenter::StartingTickle()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (!m_unk0x4e) {
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||
if ((*it)->GetCurrentTickleState() < TickleState_Streaming) {
|
||||
(*it)->Tickle();
|
||||
|
||||
if ((*it)->GetCurrentTickleState() == TickleState_Streaming ||
|
||||
((*it)->GetAction() && (*it)->GetAction()->GetStartTime()))
|
||||
m_unk0x4c++;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_list.size() == m_unk0x4c) {
|
||||
m_unk0x4e = TRUE;
|
||||
m_unk0x4c = 0;
|
||||
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||
if (!(*it)->GetAction()->GetStartTime())
|
||||
m_unk0x4c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||
if (!(*it)->GetAction()->GetStartTime() && ((MxMediaPresenter*) *it)->FUN_100b5650() &&
|
||||
!((*it)->GetAction()->GetFlags() & MxDSAction::Flag_Bit9)) {
|
||||
(*it)->Tickle();
|
||||
(*it)->GetAction()->SetFlags((*it)->GetAction()->GetFlags() | MxDSAction::Flag_Bit9);
|
||||
m_unk0x4c--;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_unk0x4c) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Streaming;
|
||||
MxLong time = Timer()->GetTime();
|
||||
m_action->SetUnknown90(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10074470
|
||||
MxResult MxCompositeMediaPresenter::Tickle()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
switch (m_currentTickleState) {
|
||||
case TickleState_Ready:
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Starting;
|
||||
case TickleState_Starting:
|
||||
StartingTickle();
|
||||
break;
|
||||
case TickleState_Streaming:
|
||||
case TickleState_Repeating:
|
||||
case TickleState_unk5:
|
||||
case TickleState_Done: {
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++)
|
||||
(*it)->Tickle();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10074540
|
||||
MxResult MxCompositeMediaPresenter::PutData()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_Done) {
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++)
|
||||
(*it)->PutData();
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
@@ -111,9 +111,6 @@ MxAtomId* g_nocdSourceName = NULL;
|
||||
// GLOBAL: LEGO1 0x100f6718
|
||||
const char* g_current = "current";
|
||||
|
||||
// GLOBAL: LEGO1 0x101020e8
|
||||
void (*g_omniUserMessage)(const char*, int);
|
||||
|
||||
// GLOBAL: LEGO1 0x100f4c58
|
||||
MxBool g_isWorldActive = TRUE;
|
||||
|
||||
@@ -694,144 +691,3 @@ MxResult Start(MxDSAction* p_dsAction)
|
||||
{
|
||||
return MxOmni::GetInstance()->Start(p_dsAction);
|
||||
}
|
||||
|
||||
// Probably should be somewhere else
|
||||
// FUNCTION: LEGO1 0x100b6e10
|
||||
MxBool FUN_100b6e10(
|
||||
MxS32 p_bitmapWidth,
|
||||
MxS32 p_bitmapHeight,
|
||||
MxS32 p_videoParamWidth,
|
||||
MxS32 p_videoParamHeight,
|
||||
MxS32* p_left,
|
||||
MxS32* p_top,
|
||||
MxS32* p_right,
|
||||
MxS32* p_bottom,
|
||||
MxS32* p_width,
|
||||
MxS32* p_height
|
||||
)
|
||||
{
|
||||
MxPoint32 topLeft(*p_left, *p_top);
|
||||
MxRect32 bitmapRect(MxPoint32(0, 0), MxSize32(p_bitmapWidth, p_bitmapHeight));
|
||||
|
||||
MxPoint32 bottomRight(*p_right, *p_bottom);
|
||||
MxRect32 videoParamRect(MxPoint32(0, 0), MxSize32(p_videoParamWidth, p_videoParamHeight));
|
||||
|
||||
MxRect32 rect(0, 0, *p_width, *p_height);
|
||||
rect.AddPoint(topLeft);
|
||||
|
||||
if (!rect.IntersectsWith(bitmapRect))
|
||||
return FALSE;
|
||||
|
||||
rect.Intersect(bitmapRect);
|
||||
rect.SubtractPoint(topLeft);
|
||||
rect.AddPoint(bottomRight);
|
||||
|
||||
if (!rect.IntersectsWith(videoParamRect))
|
||||
return FALSE;
|
||||
|
||||
rect.Intersect(videoParamRect);
|
||||
rect.SubtractPoint(bottomRight);
|
||||
|
||||
*p_left += rect.GetLeft();
|
||||
*p_top += rect.GetTop();
|
||||
*p_right += rect.GetLeft();
|
||||
*p_bottom += rect.GetTop();
|
||||
*p_width = rect.GetWidth();
|
||||
*p_height = rect.GetHeight();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6ff0
|
||||
void MakeSourceName(char* p_output, const char* p_input)
|
||||
{
|
||||
const char* cln = strchr(p_input, ':');
|
||||
if (cln) {
|
||||
p_input = cln + 1;
|
||||
}
|
||||
|
||||
strcpy(p_output, p_input);
|
||||
|
||||
strlwr(p_output);
|
||||
|
||||
char* extLoc = strstr(p_output, ".si");
|
||||
if (extLoc) {
|
||||
*extLoc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b7050
|
||||
MxBool KeyValueStringParse(char* p_outputValue, const char* p_key, const char* p_source)
|
||||
{
|
||||
MxBool didMatch = FALSE;
|
||||
|
||||
MxS16 len = strlen(p_source);
|
||||
char* temp = new char[len + 1];
|
||||
strcpy(temp, p_source);
|
||||
|
||||
char* token = strtok(temp, ", \t\r\n:");
|
||||
while (token) {
|
||||
len -= (strlen(token) + 1);
|
||||
|
||||
if (strcmpi(token, p_key) == 0) {
|
||||
if (p_outputValue && len > 0) {
|
||||
char* cur = &token[strlen(p_key)];
|
||||
cur++;
|
||||
while (*cur != ',') {
|
||||
if (*cur == ' ' || *cur == '\0' || *cur == '\t' || *cur == '\n' || *cur == '\r')
|
||||
break;
|
||||
*p_outputValue++ = *cur++;
|
||||
}
|
||||
*p_outputValue = '\0';
|
||||
}
|
||||
|
||||
didMatch = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
token = strtok(NULL, ", \t\r\n:");
|
||||
}
|
||||
|
||||
delete[] temp;
|
||||
return didMatch;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b7210
|
||||
void SetOmniUserMessage(void (*p_userMsg)(const char*, int))
|
||||
{
|
||||
g_omniUserMessage = p_userMsg;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0280
|
||||
MxDSObject* CreateStreamObject(MxDSFile* p_file, MxS16 p_ofs)
|
||||
{
|
||||
MxU8* buf;
|
||||
_MMCKINFO tmpChunk;
|
||||
|
||||
if (p_file->Seek(((MxLong*) p_file->GetBuffer())[p_ofs], 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p_file->Read((MxU8*) &tmpChunk.ckid, 8) == 0 && tmpChunk.ckid == FOURCC('M', 'x', 'S', 't')) {
|
||||
if (p_file->Read((MxU8*) &tmpChunk.ckid, 8) == 0 && tmpChunk.ckid == FOURCC('M', 'x', 'O', 'b')) {
|
||||
|
||||
buf = new MxU8[tmpChunk.cksize];
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p_file->Read(buf, tmpChunk.cksize) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Save a copy so we can clean up properly, because
|
||||
// this function will alter the pointer value.
|
||||
MxU8* copy = buf;
|
||||
MxDSObject* obj = DeserializeDSObjectDispatch(&buf, -1);
|
||||
delete[] copy;
|
||||
return obj;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
607
LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp
Normal file
607
LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp
Normal file
@@ -0,0 +1,607 @@
|
||||
#include "mxtransitionmanager.h"
|
||||
|
||||
#include "legoinputmanager.h"
|
||||
#include "legoutil.h"
|
||||
#include "legovideomanager.h"
|
||||
#include "legoworld.h"
|
||||
#include "mxbackgroundaudiomanager.h"
|
||||
#include "mxparam.h"
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxTransitionManager, 0x900);
|
||||
|
||||
// GLOBAL: LEGO1 0x100f4378
|
||||
RECT g_fullScreenRect = {0, 0, 640, 480};
|
||||
|
||||
// FUNCTION: LEGO1 0x1004b8d0
|
||||
MxTransitionManager::MxTransitionManager()
|
||||
{
|
||||
m_animationTimer = 0;
|
||||
m_transitionType = NOT_TRANSITIONING;
|
||||
m_ddSurface = NULL;
|
||||
m_waitIndicator = NULL;
|
||||
m_copyBuffer = NULL;
|
||||
m_copyFlags.m_bit0 = FALSE;
|
||||
m_unk0x28.m_bit0 = FALSE;
|
||||
m_unk0x24 = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004ba00
|
||||
MxTransitionManager::~MxTransitionManager()
|
||||
{
|
||||
delete[] m_copyBuffer;
|
||||
|
||||
if (m_waitIndicator != NULL) {
|
||||
delete m_waitIndicator->GetAction();
|
||||
delete m_waitIndicator;
|
||||
}
|
||||
|
||||
TickleManager()->UnregisterClient(this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004baa0
|
||||
MxResult MxTransitionManager::GetDDrawSurfaceFromVideoManager() // vtable+0x14
|
||||
{
|
||||
LegoVideoManager* videoManager = VideoManager();
|
||||
this->m_ddSurface = videoManager->GetDisplaySurface()->GetDirectDrawSurface2();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004bac0
|
||||
MxResult MxTransitionManager::Tickle()
|
||||
{
|
||||
if (this->m_animationSpeed + this->m_systemTime > timeGetTime()) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
this->m_systemTime = timeGetTime();
|
||||
|
||||
switch (this->m_transitionType) {
|
||||
case NO_ANIMATION:
|
||||
TransitionNone();
|
||||
break;
|
||||
case DISSOLVE:
|
||||
TransitionDissolve();
|
||||
break;
|
||||
case PIXELATION:
|
||||
TransitionPixelation();
|
||||
break;
|
||||
case SCREEN_WIPE:
|
||||
TransitionWipe();
|
||||
break;
|
||||
case WINDOWS:
|
||||
TransitionWindows();
|
||||
break;
|
||||
case BROKEN:
|
||||
TransitionBroken();
|
||||
break;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004bb70
|
||||
MxResult MxTransitionManager::StartTransition(
|
||||
TransitionType p_animationType,
|
||||
MxS32 p_speed,
|
||||
MxBool p_doCopy,
|
||||
MxBool p_playMusicInAnim
|
||||
)
|
||||
{
|
||||
if (this->m_transitionType == NOT_TRANSITIONING) {
|
||||
if (!p_playMusicInAnim) {
|
||||
MxBackgroundAudioManager* backgroundAudioManager = BackgroundAudioManager();
|
||||
backgroundAudioManager->Stop();
|
||||
}
|
||||
|
||||
this->m_transitionType = p_animationType;
|
||||
|
||||
m_copyFlags.m_bit0 = p_doCopy;
|
||||
|
||||
if (m_copyFlags.m_bit0 && m_waitIndicator != NULL) {
|
||||
m_waitIndicator->Enable(TRUE);
|
||||
|
||||
MxDSAction* action = m_waitIndicator->GetAction();
|
||||
action->SetLoopCount(10000);
|
||||
action->SetFlags(action->GetFlags() | MxDSAction::Flag_Bit10);
|
||||
}
|
||||
|
||||
MxU32 time = timeGetTime();
|
||||
this->m_systemTime = time;
|
||||
|
||||
this->m_animationSpeed = p_speed;
|
||||
|
||||
MxTickleManager* tickleManager = TickleManager();
|
||||
tickleManager->RegisterClient(this, p_speed);
|
||||
|
||||
LegoInputManager* inputManager = InputManager();
|
||||
inputManager->m_unk0x88 = TRUE;
|
||||
inputManager->m_unk0x336 = FALSE;
|
||||
|
||||
LegoVideoManager* videoManager = VideoManager();
|
||||
videoManager->SetUnkE4(FALSE);
|
||||
|
||||
SetAppCursor(1);
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004bc30
|
||||
void MxTransitionManager::EndTransition(MxBool p_notifyWorld)
|
||||
{
|
||||
if (m_transitionType != NOT_TRANSITIONING) {
|
||||
m_transitionType = NOT_TRANSITIONING;
|
||||
|
||||
m_copyFlags.m_bit0 = FALSE;
|
||||
|
||||
TickleManager()->UnregisterClient(this);
|
||||
|
||||
if (p_notifyWorld) {
|
||||
LegoWorld* world = GetCurrentWorld();
|
||||
|
||||
if (world) {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxNotificationParam param(MXTRANSITIONMANAGER_TRANSITIONENDED, this);
|
||||
world->Notify(param);
|
||||
}
|
||||
#else
|
||||
world->Notify(MxNotificationParam(MXTRANSITIONMANAGER_TRANSITIONENDED, this));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004bcf0
|
||||
void MxTransitionManager::TransitionNone()
|
||||
{
|
||||
LegoVideoManager* videoManager = VideoManager();
|
||||
videoManager->GetDisplaySurface()->FUN_100ba640();
|
||||
EndTransition(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004bd10
|
||||
void MxTransitionManager::TransitionDissolve()
|
||||
{
|
||||
// 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
|
||||
if (m_animationTimer * 16 > m_columnOrder[col])
|
||||
continue;
|
||||
|
||||
if (m_animationTimer * 16 + 15 < m_columnOrder[col])
|
||||
continue;
|
||||
|
||||
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.
|
||||
MxS32 xShift = (m_randomShift[row] + col) % 640;
|
||||
|
||||
// Set the chosen pixel to black
|
||||
if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) {
|
||||
((MxU8*) ddsd.lpSurface)[row * ddsd.lPitch + xShift] = 0;
|
||||
}
|
||||
else {
|
||||
((MxU16*) ddsd.lpSurface)[row * ddsd.lPitch + xShift] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetupCopyRect(&ddsd);
|
||||
m_ddSurface->Unlock(ddsd.lpSurface);
|
||||
|
||||
if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) {
|
||||
LPDIRECTDRAWSURFACE surf = VideoManager()->GetDisplaySurface()->GetDirectDrawSurface1();
|
||||
surf->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT);
|
||||
}
|
||||
|
||||
m_animationTimer++;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004bed0
|
||||
void MxTransitionManager::TransitionPixelation()
|
||||
{
|
||||
if (m_animationTimer == 16) {
|
||||
m_animationTimer = 0;
|
||||
EndTransition(TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// The same is true here. We only need 48 rows.
|
||||
for (i = 0; i < 48; i++) {
|
||||
m_randomShift[i] = rand() % 64;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 col = 0; col < 64; col++) {
|
||||
// Select 4 columns on each tick
|
||||
if (m_animationTimer * 4 > m_columnOrder[col])
|
||||
continue;
|
||||
|
||||
if (m_animationTimer * 4 + 3 < m_columnOrder[col])
|
||||
continue;
|
||||
|
||||
for (MxS32 row = 0; row < 48; row++) {
|
||||
MxS32 xShift = 10 * ((m_randomShift[row] + col) % 64);
|
||||
|
||||
// To do the pixelation, 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.
|
||||
|
||||
// Find the pixel to sample
|
||||
MxS32 sampleOfs = 10 * row * ddsd.lPitch + xShift;
|
||||
MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
|
||||
// Save this cast from void* to save time.
|
||||
// Seems to help accuracy doing it this way.
|
||||
MxU8* surface = (MxU8*) ddsd.lpSurface;
|
||||
MxU8* source = surface + sampleOfs * bytesPerPixel;
|
||||
|
||||
MxU32 sample = bytesPerPixel == 1 ? *source : *(MxU16*) source;
|
||||
|
||||
for (MxS32 k = 10 * row; k < 10 * row + 10; k++) {
|
||||
if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) {
|
||||
// TODO: This block and the next don't match, but they are
|
||||
// hopefully correct in principle.
|
||||
MxU16 colorWord = MAKEWORD(LOBYTE(sample), LOBYTE(sample));
|
||||
MxU32 newColor = MAKELONG(colorWord, colorWord);
|
||||
|
||||
MxU8* pos = surface + k * ddsd.lPitch + xShift;
|
||||
MxU32* dest = (MxU32*) pos;
|
||||
|
||||
// Sets 10 pixels (10 bytes)
|
||||
dest[0] = newColor;
|
||||
dest[1] = newColor;
|
||||
MxU16* half = (MxU16*) (dest + 2);
|
||||
*half = newColor;
|
||||
}
|
||||
else {
|
||||
MxU32 newColor = MAKELONG(sample, sample);
|
||||
|
||||
// You might expect a cast to MxU16* instead, but lPitch is
|
||||
// bytes/scanline, not pixels/scanline. Therefore, we just
|
||||
// need to double the xShift to get to the right spot.
|
||||
MxU8* pos = surface + k * ddsd.lPitch + 2 * xShift;
|
||||
MxU32* dest = (MxU32*) pos;
|
||||
// Sets 10 pixels (20 bytes)
|
||||
dest[0] = newColor;
|
||||
dest[1] = newColor;
|
||||
dest[2] = newColor;
|
||||
dest[3] = newColor;
|
||||
dest[4] = newColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetupCopyRect(&ddsd);
|
||||
m_ddSurface->Unlock(ddsd.lpSurface);
|
||||
|
||||
if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) {
|
||||
LPDIRECTDRAWSURFACE surf = VideoManager()->GetDisplaySurface()->GetDirectDrawSurface1();
|
||||
surf->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT);
|
||||
}
|
||||
|
||||
m_animationTimer++;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004c170
|
||||
void MxTransitionManager::TransitionWipe()
|
||||
{
|
||||
// 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++;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004c270
|
||||
void MxTransitionManager::TransitionWindows()
|
||||
{
|
||||
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);
|
||||
|
||||
MxU8* line = (MxU8*) ddsd.lpSurface + m_animationTimer * ddsd.lPitch;
|
||||
|
||||
MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
MxS32 bytesPerLine = bytesPerPixel * 640;
|
||||
|
||||
memset(line, 0, bytesPerLine);
|
||||
|
||||
for (MxS32 i = m_animationTimer + 1; i < 480 - m_animationTimer; i++) {
|
||||
line += ddsd.lPitch;
|
||||
|
||||
memset(line + m_animationTimer * bytesPerPixel, 0, bytesPerPixel);
|
||||
memset(line + 640 + (-1 - m_animationTimer) * bytesPerPixel, 0, bytesPerPixel);
|
||||
}
|
||||
|
||||
line += ddsd.lPitch;
|
||||
memset(line, 0, bytesPerLine);
|
||||
|
||||
SetupCopyRect(&ddsd);
|
||||
m_ddSurface->Unlock(ddsd.lpSurface);
|
||||
|
||||
m_animationTimer++;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004c3e0
|
||||
void MxTransitionManager::TransitionBroken()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: 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_World);
|
||||
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.m_bit0 = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004c4d0
|
||||
void MxTransitionManager::SubmitCopyRect(LPDDSURFACEDESC p_ddsc)
|
||||
{
|
||||
// Check if the copy rect is setup
|
||||
if (m_copyFlags.m_bit0 == FALSE || m_waitIndicator == NULL || m_copyBuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the copy rect onto the surface
|
||||
MxU8* dst;
|
||||
|
||||
MxU32 bytesPerPixel = p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
|
||||
const MxU8* src = (const MxU8*) m_copyBuffer;
|
||||
|
||||
MxS32 copyPitch;
|
||||
copyPitch = ((m_copyRect.right - m_copyRect.left) + 1) * bytesPerPixel;
|
||||
|
||||
MxS32 y;
|
||||
dst = (MxU8*) p_ddsc->lpSurface + (p_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 += p_ddsc->lPitch;
|
||||
}
|
||||
|
||||
// Free the copy buffer
|
||||
delete[] m_copyBuffer;
|
||||
m_copyBuffer = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1004c580
|
||||
void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc)
|
||||
{
|
||||
// Check if the copy rect is setup
|
||||
if (m_copyFlags.m_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
|
||||
MxU32 copyPitch = (p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8) *
|
||||
(m_copyRect.right - m_copyRect.left + 1); // This uses m_copyRect, seemingly erroneously
|
||||
MxU32 bytesPerPixel = p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
|
||||
m_copyRect.left = m_waitIndicator->GetLocation().GetX();
|
||||
m_copyRect.top = m_waitIndicator->GetLocation().GetY();
|
||||
|
||||
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 =
|
||||
(const MxU8*) p_ddsc->lpSurface + m_copyRect.top * p_ddsc->lPitch + bytesPerPixel * m_copyRect.left;
|
||||
|
||||
m_copyBuffer = new MxU8[bytesPerPixel * width * height];
|
||||
if (!m_copyBuffer)
|
||||
return;
|
||||
|
||||
// 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);
|
||||
src += p_ddsc->lPitch;
|
||||
dst += copyPitch;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup display surface
|
||||
if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::Flag_Bit5) != 0) {
|
||||
MxDisplaySurface* displaySurface = VideoManager()->GetDisplaySurface();
|
||||
MxBool und = FALSE;
|
||||
displaySurface->VTable0x2c(
|
||||
p_ddsc,
|
||||
m_waitIndicator->GetBitmap(),
|
||||
0,
|
||||
0,
|
||||
m_waitIndicator->GetLocation().GetX(),
|
||||
m_waitIndicator->GetLocation().GetY(),
|
||||
m_waitIndicator->GetWidth(),
|
||||
m_waitIndicator->GetHeight(),
|
||||
und
|
||||
);
|
||||
}
|
||||
else {
|
||||
MxDisplaySurface* displaySurface = VideoManager()->GetDisplaySurface();
|
||||
displaySurface->VTable0x24(
|
||||
p_ddsc,
|
||||
m_waitIndicator->GetBitmap(),
|
||||
0,
|
||||
0,
|
||||
m_waitIndicator->GetLocation().GetX(),
|
||||
m_waitIndicator->GetLocation().GetY(),
|
||||
m_waitIndicator->GetWidth(),
|
||||
m_waitIndicator->GetHeight()
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user