mirror of
https://github.com/isledecomp/isle.git
synced 2025-10-24 17:04:17 +00:00
Reorganize sources and files (#414)
* Reorganize sources * Refactor * Remove relative paths * Renames * Fix gitignore * Remove stuff * Try fixing format script * Fix format * Fix format * Fix naming script * Test format * Fix format
This commit is contained in:
committed by
GitHub
parent
6a85e62406
commit
c47206617d
231
LEGO1/omni/src/action/mxdsaction.cpp
Normal file
231
LEGO1/omni/src/action/mxdsaction.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
#include "mxdsaction.h"
|
||||
|
||||
#include "legoutil.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxtimer.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSAction, 0x94)
|
||||
|
||||
// GLOBAL: LEGO1 0x10101410
|
||||
MxU16 g_sep = TWOCC(',', ' ');
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad810
|
||||
MxDSAction::MxDSAction()
|
||||
{
|
||||
this->m_flags = MxDSAction::Flag_Enabled;
|
||||
this->m_startTime = INT_MIN;
|
||||
this->m_extraData = NULL;
|
||||
this->m_extraLength = 0;
|
||||
this->m_duration = INT_MIN;
|
||||
this->m_loopCount = -1;
|
||||
|
||||
this->SetType(MxDSType_Action);
|
||||
this->m_location.Fill(FLT_MAX);
|
||||
this->m_direction.Fill(FLT_MAX);
|
||||
this->m_up.Fill(FLT_MAX);
|
||||
this->m_unk0x84 = NULL;
|
||||
this->m_unk0x88 = 0;
|
||||
this->m_origin = NULL;
|
||||
this->m_unk0x90 = INT_MIN;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad940
|
||||
MxLong MxDSAction::GetDuration()
|
||||
{
|
||||
return this->m_duration;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad950
|
||||
void MxDSAction::SetDuration(MxLong p_duration)
|
||||
{
|
||||
this->m_duration = p_duration;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad960
|
||||
MxBool MxDSAction::HasId(MxU32 p_objectId)
|
||||
{
|
||||
return this->GetObjectId() == p_objectId;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ada40
|
||||
void MxDSAction::SetUnknown90(MxLong p_unk0x90)
|
||||
{
|
||||
this->m_unk0x90 = p_unk0x90;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ada50
|
||||
MxLong MxDSAction::GetUnknown90()
|
||||
{
|
||||
return this->m_unk0x90;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ada80
|
||||
MxDSAction::~MxDSAction()
|
||||
{
|
||||
delete[] this->m_extraData;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100adaf0
|
||||
void MxDSAction::CopyFrom(MxDSAction& p_dsAction)
|
||||
{
|
||||
this->SetObjectId(p_dsAction.GetObjectId());
|
||||
this->m_flags = p_dsAction.m_flags;
|
||||
this->m_startTime = p_dsAction.m_startTime;
|
||||
this->m_duration = p_dsAction.m_duration;
|
||||
this->m_loopCount = p_dsAction.m_loopCount;
|
||||
|
||||
this->m_location.CopyFrom(p_dsAction.m_location);
|
||||
this->m_direction.CopyFrom(p_dsAction.m_direction);
|
||||
this->m_up.CopyFrom(p_dsAction.m_up);
|
||||
|
||||
AppendData(p_dsAction.m_extraLength, p_dsAction.m_extraData);
|
||||
this->m_unk0x84 = p_dsAction.m_unk0x84;
|
||||
this->m_unk0x88 = p_dsAction.m_unk0x88;
|
||||
this->m_origin = p_dsAction.m_origin;
|
||||
this->m_unk0x90 = p_dsAction.m_unk0x90;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100adbe0
|
||||
MxU32 MxDSAction::GetSizeOnDisk()
|
||||
{
|
||||
MxU32 totalSizeOnDisk;
|
||||
|
||||
totalSizeOnDisk = MxDSObject::GetSizeOnDisk() + 90 + this->m_extraLength;
|
||||
this->m_sizeOnDisk = totalSizeOnDisk - MxDSObject::GetSizeOnDisk();
|
||||
|
||||
return totalSizeOnDisk;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100adc10
|
||||
MxDSAction& MxDSAction::operator=(MxDSAction& p_dsAction)
|
||||
{
|
||||
if (this == &p_dsAction)
|
||||
return *this;
|
||||
|
||||
MxDSObject::operator=(p_dsAction);
|
||||
this->CopyFrom(p_dsAction);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100adc40
|
||||
MxDSAction* MxDSAction::Clone()
|
||||
{
|
||||
MxDSAction* clone = new MxDSAction();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100adcd0
|
||||
MxLong MxDSAction::GetElapsedTime()
|
||||
{
|
||||
return Timer()->GetTime() - this->m_unk0x90;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100add00
|
||||
void MxDSAction::MergeFrom(MxDSAction& p_dsAction)
|
||||
{
|
||||
if (p_dsAction.m_startTime != INT_MIN)
|
||||
this->m_startTime = p_dsAction.m_startTime;
|
||||
|
||||
if (p_dsAction.GetDuration() != INT_MIN)
|
||||
this->m_duration = p_dsAction.GetDuration();
|
||||
|
||||
if (p_dsAction.m_loopCount != -1)
|
||||
this->m_loopCount = p_dsAction.m_loopCount;
|
||||
|
||||
if (p_dsAction.m_location[0] != FLT_MAX)
|
||||
this->m_location[0] = p_dsAction.m_location[0];
|
||||
if (p_dsAction.m_location[1] != FLT_MAX)
|
||||
this->m_location[1] = p_dsAction.m_location[1];
|
||||
if (p_dsAction.m_location[2] != FLT_MAX)
|
||||
this->m_location[2] = p_dsAction.m_location[2];
|
||||
|
||||
if (p_dsAction.m_direction[0] != FLT_MAX)
|
||||
this->m_direction[0] = p_dsAction.m_direction[0];
|
||||
if (p_dsAction.m_direction[1] != FLT_MAX)
|
||||
this->m_direction[1] = p_dsAction.m_direction[1];
|
||||
if (p_dsAction.m_direction[2] != FLT_MAX)
|
||||
this->m_direction[2] = p_dsAction.m_up[2]; // This is correct
|
||||
|
||||
if (p_dsAction.m_up[0] != FLT_MAX)
|
||||
this->m_up[0] = p_dsAction.m_up[0];
|
||||
if (p_dsAction.m_up[1] != FLT_MAX)
|
||||
this->m_up[1] = p_dsAction.m_up[1];
|
||||
if (p_dsAction.m_up[2] != FLT_MAX)
|
||||
this->m_up[2] = p_dsAction.m_up[2];
|
||||
|
||||
MxU16 extraLength = p_dsAction.m_extraLength;
|
||||
char* extraData = p_dsAction.m_extraData;
|
||||
|
||||
// Taking those references forces the compiler to move the values onto the stack.
|
||||
// The original code most likely looked different, but this yields a 100% match.
|
||||
MxU16& extraLengthRef = extraLength;
|
||||
char*& extraDataRef = extraData;
|
||||
if (extraLength && extraData) {
|
||||
if (!this->m_extraData || !strncmp("XXX", this->m_extraData, 3)) {
|
||||
delete[] this->m_extraData;
|
||||
this->m_extraLength = 0;
|
||||
AppendData(extraLength, extraData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ade60
|
||||
void MxDSAction::AppendData(MxU16 p_extraLength, const char* p_extraData)
|
||||
{
|
||||
if (this->m_extraData == p_extraData || !p_extraData)
|
||||
return;
|
||||
|
||||
if (this->m_extraLength) {
|
||||
char* concat = new char[p_extraLength + this->m_extraLength + sizeof(g_sep)];
|
||||
memcpy(concat, this->m_extraData, this->m_extraLength);
|
||||
|
||||
*(MxU16*) &concat[this->m_extraLength] = g_sep;
|
||||
memcpy(&concat[this->m_extraLength + sizeof(g_sep)], p_extraData, p_extraLength);
|
||||
|
||||
this->m_extraLength += p_extraLength + sizeof(g_sep);
|
||||
delete[] this->m_extraData;
|
||||
this->m_extraData = concat;
|
||||
}
|
||||
else {
|
||||
char* copy = new char[p_extraLength];
|
||||
this->m_extraData = copy;
|
||||
|
||||
if (copy) {
|
||||
this->m_extraLength = p_extraLength;
|
||||
memcpy(copy, p_extraData, p_extraLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100adf70
|
||||
void MxDSAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24)
|
||||
{
|
||||
MxDSObject::Deserialize(p_source, p_unk0x24);
|
||||
|
||||
GetScalar(p_source, this->m_flags);
|
||||
GetScalar(p_source, this->m_startTime);
|
||||
GetScalar(p_source, this->m_duration);
|
||||
GetScalar(p_source, this->m_loopCount);
|
||||
GetDouble(p_source, this->m_location[0]);
|
||||
GetDouble(p_source, this->m_location[1]);
|
||||
GetDouble(p_source, this->m_location[2]);
|
||||
GetDouble(p_source, this->m_direction[0]);
|
||||
GetDouble(p_source, this->m_direction[1]);
|
||||
GetDouble(p_source, this->m_direction[2]);
|
||||
GetDouble(p_source, this->m_up[0]);
|
||||
GetDouble(p_source, this->m_up[1]);
|
||||
GetDouble(p_source, this->m_up[2]);
|
||||
|
||||
MxU16 extraLength = GetScalar((MxU16**) p_source);
|
||||
if (extraLength) {
|
||||
AppendData(extraLength, (char*) *p_source);
|
||||
*p_source += extraLength;
|
||||
}
|
||||
}
|
||||
41
LEGO1/omni/src/action/mxdsanim.cpp
Normal file
41
LEGO1/omni/src/action/mxdsanim.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "mxdsanim.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSAnim, 0xb8)
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8ff0
|
||||
MxDSAnim::MxDSAnim()
|
||||
{
|
||||
this->SetType(MxDSType_Anim);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c91a0
|
||||
MxDSAnim::~MxDSAnim()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c91f0
|
||||
void MxDSAnim::CopyFrom(MxDSAnim& p_dsAnim)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9200
|
||||
MxDSAnim& MxDSAnim::operator=(MxDSAnim& p_dsAnim)
|
||||
{
|
||||
if (this == &p_dsAnim)
|
||||
return *this;
|
||||
|
||||
MxDSMediaAction::operator=(p_dsAnim);
|
||||
this->CopyFrom(p_dsAnim);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9230
|
||||
MxDSAction* MxDSAnim::Clone()
|
||||
{
|
||||
MxDSAnim* clone = new MxDSAnim();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
41
LEGO1/omni/src/action/mxdsevent.cpp
Normal file
41
LEGO1/omni/src/action/mxdsevent.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "mxdsevent.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSEvent, 0xb8)
|
||||
|
||||
// FUNCTION: LEGO1 0x100c95f0
|
||||
MxDSEvent::MxDSEvent()
|
||||
{
|
||||
this->SetType(MxDSType_Event);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c97a0
|
||||
MxDSEvent::~MxDSEvent()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c97f0
|
||||
void MxDSEvent::CopyFrom(MxDSEvent& p_dsEvent)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9800
|
||||
MxDSEvent& MxDSEvent::operator=(MxDSEvent& p_dsEvent)
|
||||
{
|
||||
if (this == &p_dsEvent)
|
||||
return *this;
|
||||
|
||||
MxDSMediaAction::operator=(p_dsEvent);
|
||||
this->CopyFrom(p_dsEvent);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9830
|
||||
MxDSAction* MxDSEvent::Clone()
|
||||
{
|
||||
MxDSEvent* clone = new MxDSEvent();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
94
LEGO1/omni/src/action/mxdsmediaaction.cpp
Normal file
94
LEGO1/omni/src/action/mxdsmediaaction.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "mxdsmediaaction.h"
|
||||
|
||||
#include "legoutil.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSMediaAction, 0xb8)
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8b40
|
||||
MxDSMediaAction::MxDSMediaAction()
|
||||
{
|
||||
this->m_mediaSrcPath = NULL;
|
||||
this->m_unk0x9c.m_unk0x00 = 0;
|
||||
this->m_unk0x9c.m_unk0x04 = 0;
|
||||
this->m_framesPerSecond = 0;
|
||||
this->m_mediaFormat = 0;
|
||||
this->m_paletteManagement = 1;
|
||||
this->m_unk0xb4 = -1;
|
||||
this->m_sustainTime = 0;
|
||||
this->SetType(MxDSType_MediaAction);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8cf0
|
||||
MxDSMediaAction::~MxDSMediaAction()
|
||||
{
|
||||
delete[] this->m_mediaSrcPath;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8d60
|
||||
void MxDSMediaAction::CopyFrom(MxDSMediaAction& p_dsMediaAction)
|
||||
{
|
||||
CopyMediaSrcPath(p_dsMediaAction.m_mediaSrcPath);
|
||||
|
||||
this->m_unk0x9c = p_dsMediaAction.m_unk0x9c;
|
||||
this->m_framesPerSecond = p_dsMediaAction.m_framesPerSecond;
|
||||
this->m_mediaFormat = p_dsMediaAction.m_mediaFormat;
|
||||
this->m_paletteManagement = p_dsMediaAction.m_paletteManagement;
|
||||
this->m_sustainTime = p_dsMediaAction.m_sustainTime;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8dc0
|
||||
MxDSMediaAction& MxDSMediaAction::operator=(MxDSMediaAction& p_dsMediaAction)
|
||||
{
|
||||
if (this == &p_dsMediaAction)
|
||||
return *this;
|
||||
|
||||
MxDSAction::operator=(p_dsMediaAction);
|
||||
this->CopyFrom(p_dsMediaAction);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8e80
|
||||
void MxDSMediaAction::CopyMediaSrcPath(const char* p_mediaSrcPath)
|
||||
{
|
||||
if (this->m_mediaSrcPath == p_mediaSrcPath)
|
||||
return;
|
||||
|
||||
delete[] this->m_mediaSrcPath;
|
||||
|
||||
if (p_mediaSrcPath) {
|
||||
this->m_mediaSrcPath = new char[strlen(p_mediaSrcPath) + 1];
|
||||
if (this->m_mediaSrcPath)
|
||||
strcpy(this->m_mediaSrcPath, p_mediaSrcPath);
|
||||
}
|
||||
else
|
||||
this->m_mediaSrcPath = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8f10
|
||||
MxU32 MxDSMediaAction::GetSizeOnDisk()
|
||||
{
|
||||
MxU32 totalSizeOnDisk = MxDSAction::GetSizeOnDisk();
|
||||
|
||||
if (this->m_mediaSrcPath)
|
||||
totalSizeOnDisk += strlen(this->m_mediaSrcPath) + 1;
|
||||
else
|
||||
totalSizeOnDisk++;
|
||||
|
||||
totalSizeOnDisk += 24;
|
||||
this->m_sizeOnDisk = totalSizeOnDisk - MxDSAction::GetSizeOnDisk();
|
||||
return totalSizeOnDisk;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8f60
|
||||
void MxDSMediaAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24)
|
||||
{
|
||||
MxDSAction::Deserialize(p_source, p_unk0x24);
|
||||
|
||||
GetString(p_source, &this->m_mediaSrcPath, this, &MxDSMediaAction::CopyMediaSrcPath);
|
||||
GetScalar(p_source, this->m_unk0x9c.m_unk0x00);
|
||||
GetScalar(p_source, this->m_unk0x9c.m_unk0x04);
|
||||
GetScalar(p_source, this->m_framesPerSecond);
|
||||
GetScalar(p_source, this->m_mediaFormat);
|
||||
GetScalar(p_source, this->m_paletteManagement);
|
||||
GetScalar(p_source, this->m_sustainTime);
|
||||
}
|
||||
156
LEGO1/omni/src/action/mxdsmultiaction.cpp
Normal file
156
LEGO1/omni/src/action/mxdsmultiaction.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "mxdsmultiaction.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSMultiAction, 0x9c)
|
||||
DECOMP_SIZE_ASSERT(MxDSActionList, 0x1c);
|
||||
DECOMP_SIZE_ASSERT(MxDSActionListCursor, 0x10);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9b90
|
||||
MxDSMultiAction::MxDSMultiAction()
|
||||
{
|
||||
this->SetType(MxDSType_MultiAction);
|
||||
this->m_actions = new MxDSActionList;
|
||||
this->m_actions->SetDestroy(MxDSActionList::Destroy);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca060
|
||||
MxDSMultiAction::~MxDSMultiAction()
|
||||
{
|
||||
if (this->m_actions)
|
||||
delete this->m_actions;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca0d0
|
||||
void MxDSMultiAction::CopyFrom(MxDSMultiAction& p_dsMultiAction)
|
||||
{
|
||||
this->m_actions->DeleteAll();
|
||||
|
||||
MxDSActionListCursor cursor(p_dsMultiAction.m_actions);
|
||||
MxDSAction* action;
|
||||
while (cursor.Next(action))
|
||||
this->m_actions->Append(action->Clone());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca260
|
||||
MxDSMultiAction& MxDSMultiAction::operator=(MxDSMultiAction& p_dsMultiAction)
|
||||
{
|
||||
if (this == &p_dsMultiAction)
|
||||
return *this;
|
||||
|
||||
MxDSAction::operator=(p_dsMultiAction);
|
||||
this->CopyFrom(p_dsMultiAction);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca290
|
||||
void MxDSMultiAction::SetUnknown90(MxLong p_unk0x90)
|
||||
{
|
||||
this->m_unk0x90 = p_unk0x90;
|
||||
|
||||
MxDSActionListCursor cursor(this->m_actions);
|
||||
MxDSAction* action;
|
||||
while (cursor.Next(action))
|
||||
action->SetUnknown90(p_unk0x90);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca370
|
||||
void MxDSMultiAction::MergeFrom(MxDSAction& p_dsMultiAction)
|
||||
{
|
||||
MxDSAction::MergeFrom(p_dsMultiAction);
|
||||
|
||||
MxDSActionListCursor cursor(this->m_actions);
|
||||
MxDSAction* action;
|
||||
while (cursor.Next(action))
|
||||
action->MergeFrom(p_dsMultiAction);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca450
|
||||
MxBool MxDSMultiAction::HasId(MxU32 p_objectId)
|
||||
{
|
||||
if (this->GetObjectId() == p_objectId)
|
||||
return TRUE;
|
||||
|
||||
MxDSActionListCursor cursor(this->m_actions);
|
||||
MxDSAction* action;
|
||||
while (cursor.Next(action)) {
|
||||
if (action->HasId(p_objectId))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca550
|
||||
MxDSAction* MxDSMultiAction::Clone()
|
||||
{
|
||||
MxDSMultiAction* clone = new MxDSMultiAction();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca5e0
|
||||
undefined4 MxDSMultiAction::VTable0x14()
|
||||
{
|
||||
undefined4 result = MxDSAction::VTable0x14();
|
||||
|
||||
MxDSActionListCursor cursor(this->m_actions);
|
||||
MxDSAction* action;
|
||||
while (cursor.Next(action))
|
||||
result += action->VTable0x14();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca6c0
|
||||
MxU32 MxDSMultiAction::GetSizeOnDisk()
|
||||
{
|
||||
MxU32 totalSizeOnDisk = MxDSAction::GetSizeOnDisk() + 16;
|
||||
|
||||
MxDSActionListCursor cursor(this->m_actions);
|
||||
MxDSAction* action;
|
||||
while (cursor.Next(action))
|
||||
totalSizeOnDisk += action->GetSizeOnDisk();
|
||||
|
||||
this->m_sizeOnDisk = totalSizeOnDisk - MxDSAction::GetSizeOnDisk();
|
||||
|
||||
return totalSizeOnDisk;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca7b0
|
||||
void MxDSMultiAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24)
|
||||
{
|
||||
MxDSAction::Deserialize(p_source, p_unk0x24);
|
||||
|
||||
MxU32 extraFlag = *(MxU32*) (*p_source + 4) & 1;
|
||||
*p_source += 12;
|
||||
|
||||
MxU32 count = *(MxU32*) *p_source;
|
||||
*p_source += sizeof(count);
|
||||
|
||||
if (count) {
|
||||
while (count--) {
|
||||
MxU32 extraFlag = *(MxU32*) (*p_source + 4) & 1;
|
||||
*p_source += 8;
|
||||
|
||||
MxDSAction* action = (MxDSAction*) DeserializeDSObjectDispatch(p_source, p_unk0x24);
|
||||
*p_source += extraFlag;
|
||||
|
||||
this->m_actions->Append(action);
|
||||
}
|
||||
}
|
||||
|
||||
*p_source += extraFlag;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca8c0
|
||||
void MxDSMultiAction::SetAtomId(MxAtomId p_atomId)
|
||||
{
|
||||
MxDSAction::SetAtomId(p_atomId);
|
||||
|
||||
MxDSActionListCursor cursor(this->m_actions);
|
||||
MxDSAction* action;
|
||||
while (cursor.Next(action))
|
||||
action->SetAtomId(p_atomId);
|
||||
}
|
||||
194
LEGO1/omni/src/action/mxdsobject.cpp
Normal file
194
LEGO1/omni/src/action/mxdsobject.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
#include "mxdsobject.h"
|
||||
|
||||
#include "legoutil.h"
|
||||
#include "mxdsaction.h"
|
||||
#include "mxdsanim.h"
|
||||
#include "mxdsevent.h"
|
||||
#include "mxdsmediaaction.h"
|
||||
#include "mxdsmultiaction.h"
|
||||
#include "mxdsobjectaction.h"
|
||||
#include "mxdsparallelaction.h"
|
||||
#include "mxdsselectaction.h"
|
||||
#include "mxdsserialaction.h"
|
||||
#include "mxdssound.h"
|
||||
#include "mxdsstill.h"
|
||||
#include "mxdstypes.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSObject, 0x2c);
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf6a0
|
||||
MxDSObject::MxDSObject()
|
||||
{
|
||||
this->SetType(MxDSType_Object);
|
||||
this->m_sourceName = NULL;
|
||||
this->m_unk0x14 = 0;
|
||||
this->m_objectName = NULL;
|
||||
this->m_unk0x24 = -1;
|
||||
this->m_objectId = -1;
|
||||
this->m_unk0x28 = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf7e0
|
||||
MxDSObject::~MxDSObject()
|
||||
{
|
||||
delete[] m_objectName;
|
||||
delete[] m_sourceName;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf870
|
||||
void MxDSObject::CopyFrom(MxDSObject& p_dsObject)
|
||||
{
|
||||
this->SetSourceName(p_dsObject.m_sourceName);
|
||||
this->m_unk0x14 = p_dsObject.m_unk0x14;
|
||||
this->SetObjectName(p_dsObject.m_objectName);
|
||||
this->m_objectId = p_dsObject.m_objectId;
|
||||
this->m_unk0x24 = p_dsObject.m_unk0x24;
|
||||
this->m_atomId = p_dsObject.m_atomId;
|
||||
this->m_unk0x28 = p_dsObject.m_unk0x28;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf8c0
|
||||
MxDSObject& MxDSObject::operator=(MxDSObject& p_dsObject)
|
||||
{
|
||||
if (this == &p_dsObject)
|
||||
return *this;
|
||||
|
||||
this->CopyFrom(p_dsObject);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf8e0
|
||||
void MxDSObject::SetObjectName(const char* p_objectName)
|
||||
{
|
||||
if (p_objectName != this->m_objectName) {
|
||||
delete[] this->m_objectName;
|
||||
|
||||
if (p_objectName) {
|
||||
this->m_objectName = new char[strlen(p_objectName) + 1];
|
||||
|
||||
if (this->m_objectName) {
|
||||
strcpy(this->m_objectName, p_objectName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->m_objectName = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf950
|
||||
void MxDSObject::SetSourceName(const char* p_sourceName)
|
||||
{
|
||||
if (p_sourceName != this->m_sourceName) {
|
||||
delete[] this->m_sourceName;
|
||||
|
||||
if (p_sourceName) {
|
||||
this->m_sourceName = new char[strlen(p_sourceName) + 1];
|
||||
|
||||
if (this->m_sourceName) {
|
||||
strcpy(this->m_sourceName, p_sourceName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->m_sourceName = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf9c0
|
||||
undefined4 MxDSObject::VTable0x14()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf9d0
|
||||
MxU32 MxDSObject::GetSizeOnDisk()
|
||||
{
|
||||
MxU32 sizeOnDisk;
|
||||
|
||||
if (this->m_sourceName)
|
||||
sizeOnDisk = strlen(this->m_sourceName) + 3;
|
||||
else
|
||||
sizeOnDisk = 3;
|
||||
|
||||
sizeOnDisk += 4;
|
||||
|
||||
if (this->m_objectName)
|
||||
sizeOnDisk += strlen(this->m_objectName) + 1;
|
||||
else
|
||||
sizeOnDisk++;
|
||||
|
||||
sizeOnDisk += 4;
|
||||
this->m_sizeOnDisk = sizeOnDisk;
|
||||
return sizeOnDisk;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bfa20
|
||||
void MxDSObject::Deserialize(MxU8** p_source, MxS16 p_unk0x24)
|
||||
{
|
||||
GetString(p_source, &this->m_sourceName, this, &MxDSObject::SetSourceName);
|
||||
GetScalar(p_source, this->m_unk0x14);
|
||||
GetString(p_source, &this->m_objectName, this, &MxDSObject::SetObjectName);
|
||||
GetScalar(p_source, this->m_objectId);
|
||||
|
||||
this->m_unk0x24 = p_unk0x24;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bfb30
|
||||
MxDSObject* DeserializeDSObjectDispatch(MxU8** p_source, MxS16 p_flags)
|
||||
{
|
||||
MxU16 type = *(MxU16*) *p_source;
|
||||
*p_source += 2;
|
||||
|
||||
MxDSObject* obj = NULL;
|
||||
|
||||
switch (type) {
|
||||
default:
|
||||
return NULL;
|
||||
case MxDSType_Object:
|
||||
obj = new MxDSObject();
|
||||
break;
|
||||
case MxDSType_Action:
|
||||
obj = new MxDSAction();
|
||||
break;
|
||||
case MxDSType_MediaAction:
|
||||
obj = new MxDSMediaAction();
|
||||
break;
|
||||
case MxDSType_Anim:
|
||||
obj = new MxDSAnim();
|
||||
break;
|
||||
case MxDSType_Sound:
|
||||
obj = new MxDSSound();
|
||||
break;
|
||||
case MxDSType_MultiAction:
|
||||
obj = new MxDSMultiAction();
|
||||
break;
|
||||
case MxDSType_SerialAction:
|
||||
obj = new MxDSSerialAction();
|
||||
break;
|
||||
case MxDSType_ParallelAction:
|
||||
obj = new MxDSParallelAction();
|
||||
break;
|
||||
case MxDSType_Event:
|
||||
obj = new MxDSEvent();
|
||||
break;
|
||||
case MxDSType_SelectAction:
|
||||
obj = new MxDSSelectAction();
|
||||
break;
|
||||
case MxDSType_Still:
|
||||
obj = new MxDSStill();
|
||||
break;
|
||||
case MxDSType_ObjectAction:
|
||||
obj = new MxDSObjectAction();
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
obj->Deserialize(p_source, p_flags);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
41
LEGO1/omni/src/action/mxdsobjectaction.cpp
Normal file
41
LEGO1/omni/src/action/mxdsobjectaction.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "mxdsobjectaction.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSObjectAction, 0xb8)
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8870
|
||||
MxDSObjectAction::MxDSObjectAction()
|
||||
{
|
||||
this->SetType(MxDSType_ObjectAction);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8a20
|
||||
MxDSObjectAction::~MxDSObjectAction()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8a70
|
||||
void MxDSObjectAction::CopyFrom(MxDSObjectAction& p_dsObjectAction)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8a80
|
||||
MxDSObjectAction& MxDSObjectAction::operator=(MxDSObjectAction& p_dsObjectAction)
|
||||
{
|
||||
if (this == &p_dsObjectAction)
|
||||
return *this;
|
||||
|
||||
MxDSMediaAction::operator=(p_dsObjectAction);
|
||||
this->CopyFrom(p_dsObjectAction);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8ab0
|
||||
MxDSAction* MxDSObjectAction::Clone()
|
||||
{
|
||||
MxDSObjectAction* clone = new MxDSObjectAction();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
87
LEGO1/omni/src/action/mxdsparallelaction.cpp
Normal file
87
LEGO1/omni/src/action/mxdsparallelaction.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "mxdsparallelaction.h"
|
||||
|
||||
#include "mxdsmediaaction.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSParallelAction, 0x9c)
|
||||
|
||||
// FUNCTION: LEGO1 0x100cae80
|
||||
MxDSParallelAction::MxDSParallelAction()
|
||||
{
|
||||
this->SetType(MxDSType_ParallelAction);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cb040
|
||||
MxDSParallelAction::~MxDSParallelAction()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cb090
|
||||
void MxDSParallelAction::CopyFrom(MxDSParallelAction& p_dsParallelAction)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cb0a0
|
||||
MxDSParallelAction& MxDSParallelAction::operator=(MxDSParallelAction& p_dsParallelAction)
|
||||
{
|
||||
if (this == &p_dsParallelAction)
|
||||
return *this;
|
||||
|
||||
MxDSMultiAction::operator=(p_dsParallelAction);
|
||||
this->CopyFrom(p_dsParallelAction);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cb0d0
|
||||
MxDSAction* MxDSParallelAction::Clone()
|
||||
{
|
||||
MxDSParallelAction* clone = new MxDSParallelAction();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cb160
|
||||
MxLong MxDSParallelAction::GetDuration()
|
||||
{
|
||||
if (this->m_duration)
|
||||
return this->m_duration;
|
||||
|
||||
MxDSActionListCursor cursor(this->m_actions);
|
||||
MxDSAction* action;
|
||||
|
||||
while (cursor.Next(action)) {
|
||||
if (!action)
|
||||
continue;
|
||||
|
||||
MxLong duration = action->GetDuration();
|
||||
if (duration == -1) {
|
||||
this->m_duration = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
duration += action->GetStartTime();
|
||||
if (action->IsA("MxDSMediaAction")) {
|
||||
MxLong sustainTime = ((MxDSMediaAction*) action)->GetSustainTime();
|
||||
|
||||
if (sustainTime == -1)
|
||||
duration = -1;
|
||||
else if (sustainTime)
|
||||
duration += sustainTime;
|
||||
}
|
||||
|
||||
if (duration == -1) {
|
||||
this->m_duration = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->m_duration < duration)
|
||||
this->m_duration = duration;
|
||||
}
|
||||
|
||||
if (this->IsBit3())
|
||||
this->m_duration *= this->m_loopCount;
|
||||
|
||||
return this->m_duration;
|
||||
}
|
||||
133
LEGO1/omni/src/action/mxdsselectaction.cpp
Normal file
133
LEGO1/omni/src/action/mxdsselectaction.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "mxdsselectaction.h"
|
||||
|
||||
#include "mxomni.h"
|
||||
#include "mxtimer.h"
|
||||
#include "mxvariabletable.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSSelectAction, 0xb0)
|
||||
DECOMP_SIZE_ASSERT(MxListEntry<MxString>, 0x18)
|
||||
|
||||
// FUNCTION: LEGO1 0x100cb2b0
|
||||
MxDSSelectAction::MxDSSelectAction()
|
||||
{
|
||||
this->SetType(MxDSType_SelectAction);
|
||||
this->m_unk0xac = new MxStringList;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cb8d0
|
||||
MxDSSelectAction::~MxDSSelectAction()
|
||||
{
|
||||
if (this->m_unk0xac)
|
||||
delete this->m_unk0xac;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cb950
|
||||
void MxDSSelectAction::CopyFrom(MxDSSelectAction& p_dsSelectAction)
|
||||
{
|
||||
this->m_unk0x9c = p_dsSelectAction.m_unk0x9c;
|
||||
|
||||
this->m_unk0xac->DeleteAll();
|
||||
|
||||
MxStringListCursor cursor(p_dsSelectAction.m_unk0xac);
|
||||
MxString string;
|
||||
while (cursor.Next(string))
|
||||
this->m_unk0xac->Append(string);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cbd50
|
||||
MxDSSelectAction& MxDSSelectAction::operator=(MxDSSelectAction& p_dsSelectAction)
|
||||
{
|
||||
if (this != &p_dsSelectAction) {
|
||||
MxDSParallelAction::operator=(p_dsSelectAction);
|
||||
this->CopyFrom(p_dsSelectAction);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cbd80
|
||||
MxDSAction* MxDSSelectAction::Clone()
|
||||
{
|
||||
MxDSSelectAction* clone = new MxDSSelectAction();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cbe10
|
||||
MxU32 MxDSSelectAction::GetSizeOnDisk()
|
||||
{
|
||||
MxU32 totalSizeOnDisk = MxDSParallelAction::GetSizeOnDisk();
|
||||
|
||||
totalSizeOnDisk += strlen(this->m_unk0x9c.GetData()) + 1;
|
||||
|
||||
MxStringListCursor cursor(this->m_unk0xac);
|
||||
MxString string;
|
||||
while (cursor.Next(string))
|
||||
totalSizeOnDisk += strlen(string.GetData()) + 1;
|
||||
|
||||
// Note: unlike the other classes, MxDSSelectAction does not have its own
|
||||
// sizeOnDisk member. Instead, it overrides the one from MxDSMultiAction.
|
||||
this->m_sizeOnDisk = totalSizeOnDisk;
|
||||
|
||||
return totalSizeOnDisk;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cbf60
|
||||
void MxDSSelectAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24)
|
||||
{
|
||||
MxString string;
|
||||
MxDSAction::Deserialize(p_source, p_unk0x24);
|
||||
|
||||
MxU32 extraFlag = *(MxU32*) (*p_source + 4) & 1;
|
||||
*p_source += 12;
|
||||
|
||||
this->m_unk0x9c = (char*) *p_source;
|
||||
|
||||
if (!strnicmp(this->m_unk0x9c.GetData(), "RANDOM_", strlen("RANDOM_"))) {
|
||||
char buffer[10];
|
||||
MxS16 value = atoi(&this->m_unk0x9c.GetData()[strlen("RANDOM_")]);
|
||||
|
||||
srand(Timer()->GetTime());
|
||||
MxS32 random = rand() % value;
|
||||
string = itoa((MxS16) random, buffer, 10);
|
||||
}
|
||||
else
|
||||
string = VariableTable()->GetVariable((char*) *p_source);
|
||||
|
||||
*p_source += strlen((char*) *p_source) + 1;
|
||||
|
||||
MxU32 count = *(MxU32*) *p_source;
|
||||
*p_source += sizeof(MxU32);
|
||||
|
||||
if (count) {
|
||||
MxS32 index = -1;
|
||||
this->m_unk0xac->DeleteAll();
|
||||
|
||||
MxU32 i;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!strcmp(string.GetData(), (char*) *p_source))
|
||||
index = i;
|
||||
|
||||
this->m_unk0xac->Append((char*) *p_source);
|
||||
*p_source += strlen((char*) *p_source) + 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
MxU32 extraFlag = *(MxU32*) (*p_source + 4) & 1;
|
||||
*p_source += 8;
|
||||
|
||||
MxDSAction* action = (MxDSAction*) DeserializeDSObjectDispatch(p_source, p_unk0x24);
|
||||
|
||||
if (index == i)
|
||||
this->m_actions->Append(action);
|
||||
else
|
||||
delete action;
|
||||
|
||||
*p_source += extraFlag;
|
||||
}
|
||||
}
|
||||
|
||||
*p_source += extraFlag;
|
||||
}
|
||||
81
LEGO1/omni/src/action/mxdsserialaction.cpp
Normal file
81
LEGO1/omni/src/action/mxdsserialaction.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "mxdsserialaction.h"
|
||||
|
||||
#include "mxdsmediaaction.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSSerialAction, 0xa8)
|
||||
|
||||
// FUNCTION: LEGO1 0x100ca9d0
|
||||
MxDSSerialAction::MxDSSerialAction()
|
||||
{
|
||||
this->SetType(MxDSType_SerialAction);
|
||||
this->m_cursor = new MxDSActionListCursor(this->m_actions);
|
||||
this->m_unk0xa0 = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100caac0
|
||||
void MxDSSerialAction::SetDuration(MxLong p_duration)
|
||||
{
|
||||
this->m_duration = p_duration;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cac10
|
||||
MxDSSerialAction::~MxDSSerialAction()
|
||||
{
|
||||
if (this->m_cursor)
|
||||
delete this->m_cursor;
|
||||
|
||||
this->m_cursor = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cac90
|
||||
void MxDSSerialAction::CopyFrom(MxDSSerialAction& p_dsSerialAction)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100caca0
|
||||
MxDSSerialAction& MxDSSerialAction::operator=(MxDSSerialAction& p_dsSerialAction)
|
||||
{
|
||||
if (this == &p_dsSerialAction)
|
||||
return *this;
|
||||
|
||||
MxDSMultiAction::operator=(p_dsSerialAction);
|
||||
this->CopyFrom(p_dsSerialAction);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cacd0
|
||||
MxDSAction* MxDSSerialAction::Clone()
|
||||
{
|
||||
MxDSSerialAction* clone = new MxDSSerialAction();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cad60
|
||||
MxLong MxDSSerialAction::GetDuration()
|
||||
{
|
||||
if (this->m_duration)
|
||||
return this->m_duration;
|
||||
|
||||
MxDSActionListCursor cursor(this->m_actions);
|
||||
MxDSAction* action;
|
||||
|
||||
while (cursor.Next(action)) {
|
||||
if (!action)
|
||||
continue;
|
||||
|
||||
this->m_duration += action->GetDuration() + action->GetStartTime();
|
||||
|
||||
if (action->IsA("MxDSMediaAction")) {
|
||||
MxLong sustainTime = ((MxDSMediaAction*) action)->GetSustainTime();
|
||||
|
||||
if (sustainTime && sustainTime != -1)
|
||||
this->m_duration += sustainTime;
|
||||
}
|
||||
}
|
||||
|
||||
return this->m_duration;
|
||||
}
|
||||
63
LEGO1/omni/src/action/mxdssound.cpp
Normal file
63
LEGO1/omni/src/action/mxdssound.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "mxdssound.h"
|
||||
|
||||
#include "legoutil.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSSound, 0xc0)
|
||||
|
||||
// FUNCTION: LEGO1 0x100c92c0
|
||||
MxDSSound::MxDSSound()
|
||||
{
|
||||
this->m_volume = 0x4f;
|
||||
this->SetType(MxDSType_Sound);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9470
|
||||
MxDSSound::~MxDSSound()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c94c0
|
||||
void MxDSSound::CopyFrom(MxDSSound& p_dsSound)
|
||||
{
|
||||
this->SetType(p_dsSound.GetType());
|
||||
this->m_volume = p_dsSound.m_volume;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c94e0
|
||||
MxDSSound& MxDSSound::operator=(MxDSSound& p_dsSound)
|
||||
{
|
||||
if (this == &p_dsSound)
|
||||
return *this;
|
||||
|
||||
MxDSMediaAction::operator=(p_dsSound);
|
||||
this->CopyFrom(p_dsSound);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9510
|
||||
MxDSAction* MxDSSound::Clone()
|
||||
{
|
||||
MxDSSound* clone = new MxDSSound();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c95a0
|
||||
void MxDSSound::Deserialize(MxU8** p_source, MxS16 p_unk0x24)
|
||||
{
|
||||
MxDSMediaAction::Deserialize(p_source, p_unk0x24);
|
||||
|
||||
GetScalar(p_source, this->m_volume);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c95d0
|
||||
MxU32 MxDSSound::GetSizeOnDisk()
|
||||
{
|
||||
MxU32 totalSizeOnDisk = MxDSMediaAction::GetSizeOnDisk();
|
||||
|
||||
this->m_sizeOnDisk = sizeof(this->m_volume);
|
||||
return totalSizeOnDisk + 4;
|
||||
}
|
||||
41
LEGO1/omni/src/action/mxdsstill.cpp
Normal file
41
LEGO1/omni/src/action/mxdsstill.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "mxdsstill.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSStill, 0xb8)
|
||||
|
||||
// FUNCTION: LEGO1 0x100c98c0
|
||||
MxDSStill::MxDSStill()
|
||||
{
|
||||
this->SetType(MxDSType_Still);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9a70
|
||||
MxDSStill::~MxDSStill()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9ac0
|
||||
void MxDSStill::CopyFrom(MxDSStill& p_dsStill)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9ad0
|
||||
MxDSStill& MxDSStill::operator=(MxDSStill& p_dsStill)
|
||||
{
|
||||
if (this == &p_dsStill)
|
||||
return *this;
|
||||
|
||||
MxDSMediaAction::operator=(p_dsStill);
|
||||
this->CopyFrom(p_dsStill);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c9b00
|
||||
MxDSAction* MxDSStill::Clone()
|
||||
{
|
||||
MxDSStill* clone = new MxDSStill();
|
||||
|
||||
if (clone)
|
||||
*clone = *this;
|
||||
|
||||
return clone;
|
||||
}
|
||||
92
LEGO1/omni/src/action/mxdsstreamingaction.cpp
Normal file
92
LEGO1/omni/src/action/mxdsstreamingaction.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "mxdsstreamingaction.h"
|
||||
|
||||
#include "mxdsbuffer.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSStreamingAction, 0xb4)
|
||||
|
||||
// FUNCTION: LEGO1 0x100cd010
|
||||
MxDSStreamingAction::MxDSStreamingAction(MxDSAction& p_dsAction, MxU32 p_offset)
|
||||
{
|
||||
Init();
|
||||
|
||||
*this = p_dsAction;
|
||||
this->m_unk0x94 = p_offset;
|
||||
this->m_bufferOffset = p_offset;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cd090
|
||||
MxBool MxDSStreamingAction::HasId(MxU32 p_objectId)
|
||||
{
|
||||
if (this->m_internalAction)
|
||||
return this->m_internalAction->HasId(p_objectId);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cd0d0
|
||||
MxDSStreamingAction::MxDSStreamingAction(MxDSStreamingAction& p_dsStreamingAction)
|
||||
{
|
||||
Init();
|
||||
CopyFrom(p_dsStreamingAction);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cd150
|
||||
MxDSStreamingAction::~MxDSStreamingAction()
|
||||
{
|
||||
if (this->m_unk0xa0)
|
||||
delete this->m_unk0xa0;
|
||||
if (this->m_unk0xa4)
|
||||
delete this->m_unk0xa4;
|
||||
if (this->m_internalAction)
|
||||
delete this->m_internalAction;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cd1e0
|
||||
MxResult MxDSStreamingAction::Init()
|
||||
{
|
||||
this->m_unk0x94 = 0;
|
||||
this->m_bufferOffset = 0;
|
||||
this->m_unk0x9c = 0;
|
||||
this->m_unk0xa0 = NULL;
|
||||
this->m_unk0xa4 = NULL;
|
||||
this->m_unk0xa8 = 0;
|
||||
this->m_unk0xac = 2;
|
||||
this->m_internalAction = NULL;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cd220
|
||||
MxDSStreamingAction* MxDSStreamingAction::CopyFrom(MxDSStreamingAction& p_dsStreamingAction)
|
||||
{
|
||||
*this = p_dsStreamingAction;
|
||||
this->m_unk0x94 = p_dsStreamingAction.m_unk0x94;
|
||||
this->m_bufferOffset = p_dsStreamingAction.m_bufferOffset;
|
||||
this->m_unk0x9c = p_dsStreamingAction.m_unk0x9c;
|
||||
this->m_unk0xa0 = NULL;
|
||||
this->m_unk0xa4 = NULL;
|
||||
this->m_unk0xac = p_dsStreamingAction.m_unk0xac;
|
||||
this->m_unk0xa8 = p_dsStreamingAction.m_unk0xa8;
|
||||
SetInternalAction(p_dsStreamingAction.m_internalAction ? p_dsStreamingAction.m_internalAction->Clone() : NULL);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cd2a0
|
||||
void MxDSStreamingAction::SetInternalAction(MxDSAction* p_dsAction)
|
||||
{
|
||||
if (this->m_internalAction)
|
||||
delete this->m_internalAction;
|
||||
this->m_internalAction = p_dsAction;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cd2d0
|
||||
void MxDSStreamingAction::FUN_100cd2d0()
|
||||
{
|
||||
if (this->m_duration == -1)
|
||||
return;
|
||||
|
||||
MxLong duration = this->m_duration / this->m_loopCount;
|
||||
this->m_loopCount--;
|
||||
|
||||
this->m_duration -= duration;
|
||||
this->m_unk0xa8 += duration;
|
||||
}
|
||||
78
LEGO1/omni/src/audio/mxaudiomanager.cpp
Normal file
78
LEGO1/omni/src/audio/mxaudiomanager.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "mxaudiomanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxAudioManager, 0x30);
|
||||
|
||||
// GLOBAL: LEGO1 0x10102108
|
||||
MxS32 MxAudioManager::g_count = 0;
|
||||
|
||||
// FUNCTION: LEGO1 0x10029910
|
||||
MxS32 MxAudioManager::GetVolume()
|
||||
{
|
||||
return this->m_volume;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8d00
|
||||
MxAudioManager::MxAudioManager()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8d90
|
||||
MxAudioManager::~MxAudioManager()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8df0
|
||||
void MxAudioManager::Init()
|
||||
{
|
||||
this->m_volume = 100;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8e00
|
||||
void MxAudioManager::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
this->m_criticalSection.Enter();
|
||||
g_count--;
|
||||
Init();
|
||||
this->m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxMediaManager::Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8e40
|
||||
MxResult MxAudioManager::InitPresenters()
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
MxBool success = FALSE;
|
||||
|
||||
if (MxMediaManager::InitPresenters() == SUCCESS) {
|
||||
this->m_criticalSection.Enter();
|
||||
success = TRUE;
|
||||
result = SUCCESS;
|
||||
g_count++;
|
||||
}
|
||||
|
||||
if (result)
|
||||
Destroy();
|
||||
|
||||
if (success)
|
||||
this->m_criticalSection.Leave();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8e90
|
||||
void MxAudioManager::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8ea0
|
||||
void MxAudioManager::SetVolume(MxS32 p_volume)
|
||||
{
|
||||
this->m_criticalSection.Enter();
|
||||
this->m_volume = p_volume;
|
||||
this->m_criticalSection.Leave();
|
||||
}
|
||||
17
LEGO1/omni/src/audio/mxaudiopresenter.cpp
Normal file
17
LEGO1/omni/src/audio/mxaudiopresenter.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "mxaudiopresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxAudioPresenter, 0x54);
|
||||
|
||||
// FUNCTION: LEGO1 0x1000d260
|
||||
MxS32 MxAudioPresenter::GetVolume()
|
||||
{
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000d270
|
||||
void MxAudioPresenter::SetVolume(MxS32 p_volume)
|
||||
{
|
||||
m_volume = p_volume;
|
||||
}
|
||||
326
LEGO1/omni/src/audio/mxbackgroundaudiomanager.cpp
Normal file
326
LEGO1/omni/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;
|
||||
}
|
||||
50
LEGO1/omni/src/audio/mxloopingmidipresenter.cpp
Normal file
50
LEGO1/omni/src/audio/mxloopingmidipresenter.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "mxloopingmidipresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxdssound.h"
|
||||
#include "mxmusicmanager.h"
|
||||
#include "mxomni.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxLoopingMIDIPresenter, 0x58);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2a80
|
||||
void MxLoopingMIDIPresenter::StreamingTickle()
|
||||
{
|
||||
if (m_action->GetLoopCount()) {
|
||||
MxMIDIPresenter::StreamingTickle();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_chunk) {
|
||||
m_chunk = NextChunk();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_chunk->GetTime() + m_action->GetDuration() <= m_action->GetElapsedTime()) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Done;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2ae0
|
||||
void MxLoopingMIDIPresenter::DoneTickle()
|
||||
{
|
||||
if (m_action->GetLoopCount())
|
||||
MxMIDIPresenter::DoneTickle();
|
||||
else
|
||||
EndAction();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2b00
|
||||
MxResult MxLoopingMIDIPresenter::PutData()
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
|
||||
if (m_currentTickleState == TickleState_Streaming && m_chunk && !MusicManager()->GetMIDIInitialized()) {
|
||||
SetVolume(((MxDSSound*) m_action)->GetVolume());
|
||||
MusicManager()->FUN_100c09c0(m_chunk->GetData(), !m_action->GetLoopCount() ? -1 : m_action->GetLoopCount());
|
||||
}
|
||||
|
||||
m_criticalSection.Leave();
|
||||
return SUCCESS;
|
||||
}
|
||||
128
LEGO1/omni/src/audio/mxmidipresenter.cpp
Normal file
128
LEGO1/omni/src/audio/mxmidipresenter.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
#include "mxmidipresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "legoomni.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdssound.h"
|
||||
#include "mxmusicmanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxMIDIPresenter, 0x58);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c25e0
|
||||
MxMIDIPresenter::MxMIDIPresenter()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c27c0
|
||||
MxMIDIPresenter::~MxMIDIPresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2820
|
||||
void MxMIDIPresenter::Init()
|
||||
{
|
||||
m_chunk = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2830
|
||||
void MxMIDIPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
if (MusicManager()) {
|
||||
MusicManager()->DeinitializeMIDI();
|
||||
}
|
||||
|
||||
m_criticalSection.Enter();
|
||||
|
||||
if (m_subscriber && m_chunk)
|
||||
m_subscriber->FUN_100b8390(m_chunk);
|
||||
Init();
|
||||
|
||||
m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxMusicPresenter::Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2890
|
||||
void MxMIDIPresenter::ReadyTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk) {
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
ParseExtra();
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Starting;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c28d0
|
||||
void MxMIDIPresenter::StartingTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = FUN_100b5650();
|
||||
|
||||
if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Streaming;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2910
|
||||
void MxMIDIPresenter::StreamingTickle()
|
||||
{
|
||||
if (m_chunk) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Done;
|
||||
}
|
||||
else
|
||||
m_chunk = NextChunk();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2940
|
||||
void MxMIDIPresenter::DoneTickle()
|
||||
{
|
||||
if (!MusicManager()->GetMIDIInitialized())
|
||||
EndAction();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2960
|
||||
void MxMIDIPresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2970
|
||||
MxResult MxMIDIPresenter::PutData()
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
|
||||
if (m_currentTickleState == TickleState_Streaming && m_chunk && !MusicManager()->GetMIDIInitialized()) {
|
||||
SetVolume(((MxDSSound*) m_action)->GetVolume());
|
||||
|
||||
if (MusicManager()->FUN_100c09c0(m_chunk->GetData(), 1))
|
||||
EndAction();
|
||||
}
|
||||
|
||||
m_criticalSection.Leave();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c29e0
|
||||
void MxMIDIPresenter::EndAction()
|
||||
{
|
||||
if (m_action) {
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxMediaPresenter::EndAction();
|
||||
MusicManager()->DeinitializeMIDI();
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2a60
|
||||
void MxMIDIPresenter::SetVolume(MxS32 p_volume)
|
||||
{
|
||||
m_volume = p_volume;
|
||||
MusicManager()->SetMultiplier(p_volume);
|
||||
}
|
||||
162
LEGO1/omni/src/audio/mxmusicmanager.cpp
Normal file
162
LEGO1/omni/src/audio/mxmusicmanager.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "mxmusicmanager.h"
|
||||
|
||||
#include "mxomni.h"
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxMusicManager, 0x58);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c05a0
|
||||
MxMusicManager::MxMusicManager()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0630
|
||||
MxMusicManager::~MxMusicManager()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0690
|
||||
void MxMusicManager::Init()
|
||||
{
|
||||
m_multiplier = 100;
|
||||
InitData();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c06a0
|
||||
void MxMusicManager::InitData()
|
||||
{
|
||||
m_midiStreamH = 0;
|
||||
m_midiInitialized = FALSE;
|
||||
m_unk0x38 = 0;
|
||||
m_unk0x3c = 0;
|
||||
m_unk0x40 = 0;
|
||||
m_unk0x44 = 0;
|
||||
m_unk0x48 = 0;
|
||||
m_midiHdrP = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c06c0
|
||||
void MxMusicManager::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
if (m_thread) {
|
||||
m_thread->Terminate();
|
||||
if (m_thread) {
|
||||
delete m_thread;
|
||||
}
|
||||
}
|
||||
else {
|
||||
TickleManager()->UnregisterClient(this);
|
||||
}
|
||||
|
||||
m_criticalSection.Enter();
|
||||
DeinitializeMIDI();
|
||||
Init();
|
||||
m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor) {
|
||||
MxAudioManager::Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c07f0
|
||||
void MxMusicManager::SetMIDIVolume()
|
||||
{
|
||||
MxS32 result = (m_volume * m_multiplier) / 0x64;
|
||||
HMIDISTRM streamHandle = m_midiStreamH;
|
||||
|
||||
if (streamHandle) {
|
||||
MxS32 volume = CalculateVolume(result);
|
||||
midiOutSetVolume((HMIDIOUT) streamHandle, volume);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0840
|
||||
MxResult MxMusicManager::Create(MxU32 p_frequencyMS, MxBool p_createThread)
|
||||
{
|
||||
MxResult status = FAILURE;
|
||||
MxBool locked = FALSE;
|
||||
|
||||
if (MxAudioManager::InitPresenters() == SUCCESS) {
|
||||
if (p_createThread) {
|
||||
m_criticalSection.Enter();
|
||||
locked = TRUE;
|
||||
m_thread = new MxTickleThread(this, p_frequencyMS);
|
||||
|
||||
if (!m_thread || m_thread->Start(0, 0) != SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
TickleManager()->RegisterClient(this, p_frequencyMS);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
|
||||
done:
|
||||
if (status != SUCCESS)
|
||||
Destroy();
|
||||
|
||||
if (locked)
|
||||
m_criticalSection.Leave();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0930
|
||||
void MxMusicManager::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0940
|
||||
void MxMusicManager::SetVolume(MxS32 p_volume)
|
||||
{
|
||||
MxAudioManager::SetVolume(p_volume);
|
||||
m_criticalSection.Enter();
|
||||
SetMIDIVolume();
|
||||
m_criticalSection.Leave();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0970
|
||||
void MxMusicManager::SetMultiplier(MxS32 p_multiplier)
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
m_multiplier = p_multiplier;
|
||||
SetMIDIVolume();
|
||||
m_criticalSection.Leave();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c09a0
|
||||
MxS32 MxMusicManager::CalculateVolume(MxS32 p_volume)
|
||||
{
|
||||
MxS32 result = (p_volume * 0xffff) / 100;
|
||||
return (result << 0x10) | result;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100c09c0
|
||||
undefined4 MxMusicManager::FUN_100c09c0(MxU8* p_data, MxS32 p_loopCount)
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0b20
|
||||
void MxMusicManager::DeinitializeMIDI()
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
|
||||
if (m_midiInitialized) {
|
||||
m_midiInitialized = FALSE;
|
||||
midiStreamStop(m_midiStreamH);
|
||||
midiOutUnprepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP, sizeof(MIDIHDR));
|
||||
midiOutSetVolume((HMIDIOUT) m_midiStreamH, m_midiVolume);
|
||||
midiStreamClose(m_midiStreamH);
|
||||
delete m_midiHdrP;
|
||||
InitData();
|
||||
}
|
||||
|
||||
m_criticalSection.Leave();
|
||||
}
|
||||
59
LEGO1/omni/src/audio/mxmusicpresenter.cpp
Normal file
59
LEGO1/omni/src/audio/mxmusicpresenter.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "mxmusicpresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxmusicmanager.h"
|
||||
#include "mxomni.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxMusicPresenter, 0x54);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c22c0
|
||||
MxMusicPresenter::MxMusicPresenter()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c24e0
|
||||
MxMusicPresenter::~MxMusicPresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2540
|
||||
void MxMusicPresenter::Init()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2550
|
||||
void MxMusicPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
if (MusicManager()) {
|
||||
MusicManager()->RemovePresenter(*this);
|
||||
}
|
||||
|
||||
m_criticalSection.Enter();
|
||||
Init();
|
||||
m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor) {
|
||||
MxMediaPresenter::Destroy(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c25a0
|
||||
MxResult MxMusicPresenter::AddToManager()
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
if (MusicManager()) {
|
||||
result = SUCCESS;
|
||||
MusicManager()->AddPresenter(*this);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c25d0
|
||||
void MxMusicPresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
202
LEGO1/omni/src/audio/mxsoundmanager.cpp
Normal file
202
LEGO1/omni/src/audio/mxsoundmanager.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
#include "mxsoundmanager.h"
|
||||
|
||||
#include "define.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxpresenter.h"
|
||||
#include "mxticklemanager.h"
|
||||
#include "mxwavepresenter.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxSoundManager, 0x3c);
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae740
|
||||
MxSoundManager::MxSoundManager()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae7d0
|
||||
MxSoundManager::~MxSoundManager()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae830
|
||||
void MxSoundManager::Init()
|
||||
{
|
||||
m_directSound = NULL;
|
||||
m_dsBuffer = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae840
|
||||
void MxSoundManager::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
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_fromDestructor) {
|
||||
MxAudioManager::Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae8b0
|
||||
MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread)
|
||||
{
|
||||
MxResult status = FAILURE;
|
||||
MxBool locked = FALSE;
|
||||
|
||||
if (MxAudioManager::InitPresenters() != SUCCESS)
|
||||
goto done;
|
||||
|
||||
m_criticalSection.Enter();
|
||||
locked = TRUE;
|
||||
|
||||
if (DirectSoundCreate(NULL, &m_directSound, NULL) != DS_OK)
|
||||
goto done;
|
||||
|
||||
if (m_directSound->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DSSCL_PRIORITY) != DS_OK)
|
||||
goto done;
|
||||
|
||||
DSBUFFERDESC desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
if (MxOmni::IsSound3D())
|
||||
desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
|
||||
else
|
||||
desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
|
||||
|
||||
if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) {
|
||||
if (!MxOmni::IsSound3D())
|
||||
goto done;
|
||||
|
||||
MxOmni::SetSound3D(FALSE);
|
||||
desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
|
||||
|
||||
if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK)
|
||||
goto done;
|
||||
}
|
||||
|
||||
WAVEFORMATEX format;
|
||||
|
||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
|
||||
if (MxOmni::IsSound3D())
|
||||
format.nChannels = 2;
|
||||
else
|
||||
format.nChannels = 1;
|
||||
|
||||
format.nSamplesPerSec = 11025; // KHz
|
||||
format.wBitsPerSample = 16;
|
||||
format.nBlockAlign = format.nChannels * 2;
|
||||
format.nAvgBytesPerSec = format.nBlockAlign * 11025;
|
||||
format.cbSize = 0;
|
||||
|
||||
status = m_dsBuffer->SetFormat(&format);
|
||||
|
||||
if (p_createThread) {
|
||||
m_thread = new MxTickleThread(this, p_frequencyMS);
|
||||
|
||||
if (!m_thread || m_thread->Start(0, 0) != SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
TickleManager()->RegisterClient(this, p_frequencyMS);
|
||||
|
||||
status = SUCCESS;
|
||||
|
||||
done:
|
||||
if (status != SUCCESS)
|
||||
Destroy();
|
||||
|
||||
if (locked)
|
||||
m_criticalSection.Leave();
|
||||
return status;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aeab0
|
||||
void MxSoundManager::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aeac0
|
||||
void MxSoundManager::SetVolume(MxS32 p_volume)
|
||||
{
|
||||
MxAudioManager::SetVolume(p_volume);
|
||||
|
||||
m_criticalSection.Enter();
|
||||
|
||||
MxPresenter* presenter;
|
||||
MxPresenterListCursor cursor(m_presenters);
|
||||
|
||||
while (cursor.Next(presenter))
|
||||
((MxAudioPresenter*) presenter)->SetVolume(((MxAudioPresenter*) presenter)->GetVolume());
|
||||
|
||||
m_criticalSection.Leave();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aebd0
|
||||
MxPresenter* MxSoundManager::FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_objectId)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxPresenter* presenter;
|
||||
MxPresenterListCursor cursor(m_presenters);
|
||||
|
||||
while (cursor.Next(presenter)) {
|
||||
if (presenter->GetAction()->GetAtomId().GetInternal() == p_atomId.GetInternal() &&
|
||||
presenter->GetAction()->GetObjectId() == p_objectId)
|
||||
return presenter;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aecf0
|
||||
MxS32 MxSoundManager::FUN_100aecf0(MxU32 p_undefined)
|
||||
{
|
||||
if (!p_undefined)
|
||||
return -10000;
|
||||
return g_mxcoreCount[p_undefined];
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aed10
|
||||
void MxSoundManager::Pause()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxPresenter* presenter;
|
||||
MxPresenterListCursor cursor(m_presenters);
|
||||
|
||||
while (cursor.Next(presenter))
|
||||
if (presenter->IsA("MxWavePresenter"))
|
||||
((MxWavePresenter*) presenter)->Pause();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aee10
|
||||
void MxSoundManager::Resume()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxPresenter* presenter;
|
||||
MxPresenterListCursor cursor(m_presenters);
|
||||
|
||||
while (cursor.Next(presenter))
|
||||
if (presenter->IsA("MxWavePresenter"))
|
||||
((MxWavePresenter*) presenter)->Resume();
|
||||
}
|
||||
45
LEGO1/omni/src/audio/mxsoundpresenter.cpp
Normal file
45
LEGO1/omni/src/audio/mxsoundpresenter.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "mxsoundpresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxsoundmanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxSoundPresenter, 0x54)
|
||||
|
||||
// FUNCTION: LEGO1 0x1000d430
|
||||
MxSoundPresenter::~MxSoundPresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000d490
|
||||
void MxSoundPresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1a50
|
||||
void MxSoundPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
if (MSoundManager())
|
||||
MSoundManager()->RemovePresenter(*this);
|
||||
|
||||
this->m_criticalSection.Enter();
|
||||
MxMediaPresenter::Init();
|
||||
this->m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxMediaPresenter::Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1aa0
|
||||
MxResult MxSoundPresenter::AddToManager()
|
||||
{
|
||||
MxResult ret = FAILURE;
|
||||
|
||||
if (MSoundManager()) {
|
||||
ret = SUCCESS;
|
||||
MSoundManager()->AddPresenter(*this);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
375
LEGO1/omni/src/audio/mxwavepresenter.cpp
Normal file
375
LEGO1/omni/src/audio/mxwavepresenter.cpp
Normal file
@@ -0,0 +1,375 @@
|
||||
#include "mxwavepresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "define.h"
|
||||
#include "legoomni.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdssound.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxsoundmanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxWavePresenter, 0x6c);
|
||||
DECOMP_SIZE_ASSERT(MxWavePresenter::WaveFormat, 0x1c);
|
||||
|
||||
// FUNCTION: LEGO1 0x1000d640
|
||||
MxWavePresenter::~MxWavePresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000d6a0
|
||||
void MxWavePresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000d6b0
|
||||
MxBool MxWavePresenter::IsPaused()
|
||||
{
|
||||
return m_paused;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1ad0
|
||||
void MxWavePresenter::Init()
|
||||
{
|
||||
m_waveFormat = NULL;
|
||||
m_dsBuffer = NULL;
|
||||
m_chunkLength = 0;
|
||||
m_lockSize = 0;
|
||||
m_writtenChunks = 0;
|
||||
m_started = FALSE;
|
||||
m_unk0x66 = FALSE;
|
||||
m_paused = FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1af0
|
||||
MxResult MxWavePresenter::AddToManager()
|
||||
{
|
||||
MxResult result = MxSoundPresenter::AddToManager();
|
||||
Init();
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1b10
|
||||
void MxWavePresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
if (m_dsBuffer) {
|
||||
m_dsBuffer->Stop();
|
||||
m_dsBuffer->Release();
|
||||
}
|
||||
|
||||
if (m_waveFormat)
|
||||
delete[] ((MxU8*) m_waveFormat);
|
||||
|
||||
Init();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxSoundPresenter::Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1b60
|
||||
MxS8 MxWavePresenter::GetPlayedChunks()
|
||||
{
|
||||
DWORD dwCurrentPlayCursor, dwCurrentWriteCursor;
|
||||
MxS8 playedChunks = -1;
|
||||
|
||||
if (m_dsBuffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor) == DS_OK)
|
||||
playedChunks = dwCurrentPlayCursor / m_chunkLength;
|
||||
|
||||
return playedChunks;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1ba0
|
||||
MxBool MxWavePresenter::FUN_100b1ba0()
|
||||
{
|
||||
return !m_started || GetPlayedChunks() != m_writtenChunks;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1bd0
|
||||
void MxWavePresenter::WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length)
|
||||
{
|
||||
DWORD dwStatus;
|
||||
LPVOID pvAudioPtr1;
|
||||
DWORD dwOffset;
|
||||
LPVOID pvAudioPtr2;
|
||||
DWORD dwAudioBytes1;
|
||||
DWORD dwAudioBytes2;
|
||||
|
||||
dwOffset = m_chunkLength * m_writtenChunks;
|
||||
m_dsBuffer->GetStatus(&dwStatus);
|
||||
|
||||
if (dwStatus == DSBSTATUS_BUFFERLOST) {
|
||||
m_dsBuffer->Restore();
|
||||
m_dsBuffer->GetStatus(&dwStatus);
|
||||
}
|
||||
|
||||
if (dwStatus != DSBSTATUS_BUFFERLOST) {
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Looping) {
|
||||
m_writtenChunks++;
|
||||
m_lockSize = p_length;
|
||||
}
|
||||
else {
|
||||
m_writtenChunks = 1 - m_writtenChunks;
|
||||
m_lockSize = m_chunkLength;
|
||||
}
|
||||
|
||||
if (m_dsBuffer->Lock(dwOffset, m_lockSize, &pvAudioPtr1, &dwAudioBytes1, &pvAudioPtr2, &dwAudioBytes2, 0) ==
|
||||
DS_OK) {
|
||||
memcpy(pvAudioPtr1, p_audioPtr, p_length);
|
||||
|
||||
if (m_lockSize > p_length && !(m_action->GetFlags() & MxDSAction::Flag_Looping)) {
|
||||
memset((MxU8*) pvAudioPtr1 + p_length, m_silenceData, m_lockSize - p_length);
|
||||
}
|
||||
|
||||
m_dsBuffer->Unlock(pvAudioPtr1, m_lockSize, pvAudioPtr2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1cf0
|
||||
void MxWavePresenter::ReadyTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk) {
|
||||
m_waveFormat = (WaveFormat*) new MxU8[chunk->GetLength()];
|
||||
memcpy(m_waveFormat, chunk->GetData(), chunk->GetLength());
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
ParseExtra();
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Starting;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1d50
|
||||
void MxWavePresenter::StartingTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) {
|
||||
MxU32 length = chunk->GetLength();
|
||||
WAVEFORMATEX waveFormatEx;
|
||||
|
||||
m_chunkLength = length;
|
||||
memset(&waveFormatEx, 0, sizeof(waveFormatEx));
|
||||
|
||||
waveFormatEx.wFormatTag = m_waveFormat->m_waveFormatEx.wFormatTag;
|
||||
waveFormatEx.nChannels = m_waveFormat->m_waveFormatEx.nChannels;
|
||||
waveFormatEx.nSamplesPerSec = m_waveFormat->m_waveFormatEx.nSamplesPerSec;
|
||||
waveFormatEx.nAvgBytesPerSec = m_waveFormat->m_waveFormatEx.nAvgBytesPerSec;
|
||||
waveFormatEx.nBlockAlign = m_waveFormat->m_waveFormatEx.nBlockAlign;
|
||||
waveFormatEx.wBitsPerSample = m_waveFormat->m_waveFormatEx.wBitsPerSample;
|
||||
|
||||
if (waveFormatEx.wBitsPerSample == 8)
|
||||
m_silenceData = 0x7F;
|
||||
|
||||
if (waveFormatEx.wBitsPerSample == 16)
|
||||
m_silenceData = 0;
|
||||
|
||||
DSBUFFERDESC desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
|
||||
if (m_unk0x66)
|
||||
desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME;
|
||||
else
|
||||
desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME;
|
||||
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Looping)
|
||||
desc.dwBufferBytes = m_waveFormat->m_waveFormatEx.nAvgBytesPerSec *
|
||||
(m_action->GetDuration() / m_action->GetLoopCount()) / 1000;
|
||||
else
|
||||
desc.dwBufferBytes = 2 * length;
|
||||
|
||||
desc.lpwfxFormat = &waveFormatEx;
|
||||
|
||||
if (MSoundManager()->GetDirectSound()->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) {
|
||||
EndAction();
|
||||
}
|
||||
else {
|
||||
SetVolume(((MxDSSound*) m_action)->GetVolume());
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Streaming;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1ea0
|
||||
void MxWavePresenter::StreamingTickle()
|
||||
{
|
||||
if (!m_currentChunk) {
|
||||
if (!(m_action->GetFlags() & MxDSAction::Flag_Looping)) {
|
||||
MxStreamChunk* chunk = FUN_100b5650();
|
||||
|
||||
if (chunk && chunk->GetFlags() & MxDSChunk::Flag_End && !(chunk->GetFlags() & MxDSChunk::Flag_Bit16)) {
|
||||
chunk->SetFlags(chunk->GetFlags() | MxDSChunk::Flag_Bit16);
|
||||
|
||||
m_currentChunk = new MxStreamChunk;
|
||||
MxU8* data = new MxU8[m_chunkLength];
|
||||
|
||||
memset(data, m_silenceData, m_chunkLength);
|
||||
|
||||
m_currentChunk->SetLength(m_chunkLength);
|
||||
m_currentChunk->SetData(data);
|
||||
m_currentChunk->SetTime(chunk->GetTime() + 1000);
|
||||
m_currentChunk->SetFlags(MxDSChunk::Flag_Bit1);
|
||||
}
|
||||
}
|
||||
|
||||
MxMediaPresenter::StreamingTickle();
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b20c0
|
||||
void MxWavePresenter::DoneTickle()
|
||||
{
|
||||
if (m_dsBuffer) {
|
||||
DWORD dwCurrentPlayCursor, dwCurrentWriteCursor;
|
||||
m_dsBuffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor);
|
||||
|
||||
MxS8 playedChunks = dwCurrentPlayCursor / m_chunkLength;
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Bit7 || m_action->GetFlags() & MxDSAction::Flag_Looping ||
|
||||
m_writtenChunks != playedChunks || m_lockSize + (m_chunkLength * playedChunks) <= dwCurrentPlayCursor)
|
||||
MxMediaPresenter::DoneTickle();
|
||||
}
|
||||
else
|
||||
MxMediaPresenter::DoneTickle();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2130
|
||||
void MxWavePresenter::AppendChunk(MxStreamChunk* p_chunk)
|
||||
{
|
||||
WriteToSoundBuffer(p_chunk->GetData(), p_chunk->GetLength());
|
||||
if (IsEnabled())
|
||||
m_subscriber->FUN_100b8390(p_chunk);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2160
|
||||
MxResult MxWavePresenter::PutData()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (IsEnabled()) {
|
||||
switch (m_currentTickleState) {
|
||||
case TickleState_Streaming:
|
||||
if (m_currentChunk && FUN_100b1ba0()) {
|
||||
WriteToSoundBuffer(m_currentChunk->GetData(), m_currentChunk->GetLength());
|
||||
m_subscriber->FUN_100b8390(m_currentChunk);
|
||||
m_currentChunk = NULL;
|
||||
}
|
||||
|
||||
if (!m_started) {
|
||||
m_dsBuffer->SetCurrentPosition(0);
|
||||
|
||||
if (m_dsBuffer->Play(0, 0, DSBPLAY_LOOPING) == DS_OK)
|
||||
m_started = TRUE;
|
||||
}
|
||||
break;
|
||||
case TickleState_Repeating:
|
||||
if (m_started)
|
||||
break;
|
||||
|
||||
m_dsBuffer->SetCurrentPosition(0);
|
||||
|
||||
if (m_dsBuffer->Play(0, 0, m_action->GetLoopCount() > 1) == DS_OK)
|
||||
m_started = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2280
|
||||
void MxWavePresenter::EndAction()
|
||||
{
|
||||
if (m_action) {
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
MxMediaPresenter::EndAction();
|
||||
|
||||
if (m_dsBuffer)
|
||||
m_dsBuffer->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2300
|
||||
void MxWavePresenter::SetVolume(MxS32 p_volume)
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
|
||||
m_volume = p_volume;
|
||||
if (m_dsBuffer != NULL) {
|
||||
MxS32 volume = p_volume * MxOmni::GetInstance()->GetSoundManager()->GetVolume() / 100;
|
||||
MxS32 otherVolume = MxOmni::GetInstance()->GetSoundManager()->FUN_100aecf0(volume);
|
||||
m_dsBuffer->SetVolume(otherVolume);
|
||||
}
|
||||
|
||||
m_criticalSection.Leave();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2360
|
||||
void MxWavePresenter::Enable(MxBool p_enable)
|
||||
{
|
||||
if (IsEnabled() != p_enable) {
|
||||
MxSoundPresenter::Enable(p_enable);
|
||||
|
||||
if (p_enable) {
|
||||
m_writtenChunks = 0;
|
||||
m_started = FALSE;
|
||||
}
|
||||
else if (m_dsBuffer)
|
||||
m_dsBuffer->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b23a0
|
||||
void MxWavePresenter::ParseExtra()
|
||||
{
|
||||
char extraCopy[512];
|
||||
|
||||
MxSoundPresenter::ParseExtra();
|
||||
*((MxU16*) &extraCopy[0]) = m_action->GetExtraLength();
|
||||
char* extraData = m_action->GetExtraData();
|
||||
|
||||
if (*((MxU16*) &extraCopy[0])) {
|
||||
MxU16 len = *((MxU16*) &extraCopy[0]);
|
||||
memcpy(extraCopy, extraData, len);
|
||||
extraCopy[len] = '\0';
|
||||
|
||||
char soundValue[512];
|
||||
if (KeyValueStringParse(soundValue, g_strSOUND, extraCopy)) {
|
||||
if (!strcmpi(soundValue, "FALSE"))
|
||||
Enable(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2440
|
||||
void MxWavePresenter::Pause()
|
||||
{
|
||||
if (!m_paused && m_started) {
|
||||
if (m_dsBuffer)
|
||||
m_dsBuffer->Stop();
|
||||
m_paused = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2470
|
||||
void MxWavePresenter::Resume()
|
||||
{
|
||||
if (m_paused) {
|
||||
if (m_dsBuffer && m_started) {
|
||||
switch (m_currentTickleState) {
|
||||
case TickleState_Streaming:
|
||||
m_dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||
break;
|
||||
case TickleState_Repeating:
|
||||
m_dsBuffer->Play(0, 0, m_action->GetLoopCount() > 1);
|
||||
break;
|
||||
case TickleState_Done:
|
||||
m_dsBuffer->Play(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
m_paused = FALSE;
|
||||
}
|
||||
}
|
||||
103
LEGO1/omni/src/common/mxatomid.cpp
Normal file
103
LEGO1/omni/src/common/mxatomid.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "mxatomid.h"
|
||||
|
||||
#include "mxomni.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100acf90
|
||||
MxAtomId::MxAtomId(const char* p_str, LookupMode p_mode)
|
||||
{
|
||||
if (!MxOmni::GetInstance())
|
||||
return;
|
||||
|
||||
if (!AtomIdCounterSet())
|
||||
return;
|
||||
|
||||
MxAtomIdCounter* counter = GetCounter(p_str, p_mode);
|
||||
m_internal = counter->GetKey()->GetData();
|
||||
counter->Inc();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acfd0
|
||||
MxAtomId::~MxAtomId()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acfe0
|
||||
void MxAtomId::Destroy()
|
||||
{
|
||||
if (!m_internal)
|
||||
return;
|
||||
|
||||
if (!MxOmni::GetInstance())
|
||||
return;
|
||||
|
||||
if (!AtomIdCounterSet())
|
||||
return;
|
||||
|
||||
#ifdef COMPAT_MODE
|
||||
MxAtomIdCounterSet::iterator it;
|
||||
{
|
||||
MxAtomIdCounter id_counter(m_internal);
|
||||
it = AtomIdCounterSet()->find(&id_counter);
|
||||
}
|
||||
#else
|
||||
MxAtomIdCounterSet::iterator it = AtomIdCounterSet()->find(&MxAtomIdCounter(m_internal));
|
||||
#endif
|
||||
|
||||
MxAtomIdCounter* counter = (MxAtomIdCounter*) (*it);
|
||||
counter->Dec();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad1c0
|
||||
MxAtomId& MxAtomId::operator=(const MxAtomId& p_atomId)
|
||||
{
|
||||
if (m_internal)
|
||||
Destroy();
|
||||
|
||||
if (p_atomId.m_internal && MxOmni::GetInstance() && AtomIdCounterSet()) {
|
||||
MxAtomIdCounter* counter = GetCounter(p_atomId.m_internal, LookupMode_Exact);
|
||||
counter->Inc();
|
||||
}
|
||||
|
||||
m_internal = p_atomId.m_internal;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad210
|
||||
MxAtomIdCounter* MxAtomId::GetCounter(const char* p_str, LookupMode p_mode)
|
||||
{
|
||||
MxAtomId unused;
|
||||
MxAtomIdCounter* counter = new MxAtomIdCounter(p_str);
|
||||
|
||||
switch (p_mode) {
|
||||
case LookupMode_LowerCase:
|
||||
case LookupMode_LowerCase2:
|
||||
counter->GetKey()->ToLowerCase();
|
||||
break;
|
||||
case LookupMode_UpperCase:
|
||||
counter->GetKey()->ToUpperCase();
|
||||
break;
|
||||
}
|
||||
|
||||
MxAtomIdCounterSet::iterator it = AtomIdCounterSet()->find(counter);
|
||||
if (it != AtomIdCounterSet()->end()) {
|
||||
// Counter already in the set. Delete temp value and return it.
|
||||
delete counter;
|
||||
counter = *it;
|
||||
}
|
||||
else {
|
||||
// Counter is not in the set. Add it.
|
||||
AtomIdCounterSet()->insert(counter);
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad7e0
|
||||
void MxAtomId::Clear()
|
||||
{
|
||||
// Reset but do not delete MxAtomId object.
|
||||
Destroy();
|
||||
m_internal = NULL;
|
||||
}
|
||||
19
LEGO1/omni/src/common/mxatomidcounter.cpp
Normal file
19
LEGO1/omni/src/common/mxatomidcounter.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "mxatomidcounter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxAtomIdCounter, 0x14);
|
||||
DECOMP_SIZE_ASSERT(MxAtomIdCounterSet, 0x10);
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad7f0
|
||||
void MxAtomIdCounter::Inc()
|
||||
{
|
||||
m_value++;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ad800
|
||||
void MxAtomIdCounter::Dec()
|
||||
{
|
||||
if (m_value)
|
||||
m_value--;
|
||||
}
|
||||
172
LEGO1/omni/src/common/mxcompositemediapresenter.cpp
Normal file
172
LEGO1/omni/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;
|
||||
}
|
||||
265
LEGO1/omni/src/common/mxcompositepresenter.cpp
Normal file
265
LEGO1/omni/src/common/mxcompositepresenter.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
#include "mxcompositepresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdsmultiaction.h"
|
||||
#include "mxnotificationmanager.h"
|
||||
#include "mxobjectfactory.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxCompositePresenter, 0x4c);
|
||||
|
||||
// FUNCTION: LEGO1 0x1000caf0
|
||||
MxBool MxCompositePresenter::VTable0x64(undefined4 p_undefined)
|
||||
{
|
||||
if (m_compositePresenter)
|
||||
return m_compositePresenter->VTable0x64(p_undefined);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b60b0
|
||||
MxCompositePresenter::MxCompositePresenter()
|
||||
{
|
||||
NotificationManager()->Register(this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6390
|
||||
MxCompositePresenter::~MxCompositePresenter()
|
||||
{
|
||||
NotificationManager()->Unregister(this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6410
|
||||
MxResult MxCompositePresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxResult result = FAILURE;
|
||||
MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList();
|
||||
MxObjectFactory* factory = ObjectFactory();
|
||||
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();
|
||||
|
||||
MxBool success = FALSE;
|
||||
|
||||
action->CopyFlags(m_action->GetFlags());
|
||||
|
||||
const char* presenterName = PresenterNameDispatch(*action);
|
||||
MxPresenter* presenter = (MxPresenter*) factory->Create(presenterName);
|
||||
|
||||
if (presenter && presenter->AddToManager() == SUCCESS) {
|
||||
presenter->SetCompositePresenter(this);
|
||||
if (presenter->StartAction(p_controller, action) == SUCCESS)
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
action->SetOrigin(this);
|
||||
m_list.push_back(presenter);
|
||||
}
|
||||
else if (presenter)
|
||||
delete presenter;
|
||||
}
|
||||
|
||||
result = SUCCESS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b65e0
|
||||
void MxCompositePresenter::EndAction()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (!m_action)
|
||||
return;
|
||||
|
||||
((MxDSMultiAction*) m_action)->GetActionList()->DeleteAll(FALSE);
|
||||
|
||||
while (!m_list.empty()) {
|
||||
MxPresenter* presenter = m_list.front();
|
||||
m_list.pop_front();
|
||||
presenter->SetCompositePresenter(NULL);
|
||||
presenter->EndAction();
|
||||
}
|
||||
|
||||
MxDSAction* action = m_action;
|
||||
MxPresenter::EndAction();
|
||||
|
||||
if (action && action->GetOrigin()) {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxEndActionNotificationParam param(c_notificationEndAction, this, action, FALSE);
|
||||
NotificationManager()->Send(action->GetOrigin(), ¶m);
|
||||
}
|
||||
#else
|
||||
NotificationManager()->Send(
|
||||
action->GetOrigin(),
|
||||
&MxEndActionNotificationParam(c_notificationEndAction, this, action, FALSE)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6760
|
||||
MxLong MxCompositePresenter::Notify(MxParam& p_param)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
switch (((MxNotificationParam&) p_param).GetNotification()) {
|
||||
case c_notificationEndAction:
|
||||
VTable0x58((MxEndActionNotificationParam&) p_param);
|
||||
break;
|
||||
case MXPRESENTER_NOTIFICATION:
|
||||
VTable0x5c((MxNotificationParam&) p_param);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b67f0
|
||||
void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param)
|
||||
{
|
||||
MxPresenter* presenter = (MxPresenter*) p_param.GetSender();
|
||||
MxDSAction* action = p_param.GetAction();
|
||||
MxCompositePresenterList::iterator it;
|
||||
|
||||
if (!m_list.empty()) {
|
||||
for (it = m_list.begin(); it != m_list.end(); it++) {
|
||||
if (*it == presenter) {
|
||||
m_list.erase(it++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_action) {
|
||||
MxDSActionList* actions = ((MxDSMultiAction*) m_action)->GetActionList();
|
||||
MxDSActionListCursor cursor(actions);
|
||||
|
||||
if (cursor.Find(action))
|
||||
cursor.Detach();
|
||||
}
|
||||
|
||||
if (presenter)
|
||||
delete presenter;
|
||||
|
||||
if (action)
|
||||
delete action;
|
||||
|
||||
if (m_list.empty()) {
|
||||
EndAction();
|
||||
}
|
||||
else {
|
||||
if (m_action->IsA("MxDSSerialAction") && it != m_list.end()) {
|
||||
MxPresenter* presenter = *it;
|
||||
if (presenter->GetCurrentTickleState() == TickleState_Idle)
|
||||
presenter->SetTickleState(TickleState_Ready);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b69b0
|
||||
void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param)
|
||||
{
|
||||
if (!m_list.empty()) {
|
||||
MxPresenter* presenter = (MxPresenter*) p_param.GetSender();
|
||||
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||
if (*it == presenter) {
|
||||
m_list.erase(it++);
|
||||
|
||||
if (presenter->GetCurrentTickleState() == TickleState_Idle)
|
||||
presenter->SetTickleState(TickleState_Ready);
|
||||
|
||||
MxDSActionList* actions = ((MxDSMultiAction*) m_action)->GetActionList();
|
||||
MxDSActionListCursor cursor(actions);
|
||||
|
||||
if (cursor.Find(presenter->GetAction()))
|
||||
cursor.Detach();
|
||||
|
||||
if (m_list.empty()) {
|
||||
EndAction();
|
||||
}
|
||||
else {
|
||||
if (m_action->IsA("MxDSSerialAction")) {
|
||||
MxPresenter* presenter = *it;
|
||||
if (presenter->GetCurrentTickleState() == TickleState_Idle)
|
||||
presenter->SetTickleState(TickleState_Ready);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NotificationManager()->Send(this, &p_param);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6b40
|
||||
void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter)
|
||||
{
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||
if (*it == p_presenter) {
|
||||
if (++it == m_list.end()) {
|
||||
if (m_compositePresenter)
|
||||
m_compositePresenter->VTable0x60(this);
|
||||
}
|
||||
else if (m_action->IsA("MxDSSerialAction")) {
|
||||
MxPresenter* presenter = *it;
|
||||
if (presenter->GetCurrentTickleState() == TickleState_Idle)
|
||||
presenter->SetTickleState(TickleState_Ready);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6bc0
|
||||
void MxCompositePresenter::SetTickleState(TickleState p_tickleState)
|
||||
{
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = p_tickleState;
|
||||
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||
MxPresenter* presenter = *it;
|
||||
presenter->SetTickleState(p_tickleState);
|
||||
|
||||
if (m_action->IsA("MxDSSerialAction") && p_tickleState == TickleState_Ready)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6c30
|
||||
void MxCompositePresenter::Enable(MxBool p_enable)
|
||||
{
|
||||
MxPresenter::Enable(p_enable);
|
||||
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||
MxPresenter* presenter = *it;
|
||||
presenter->Enable(p_enable);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6c80
|
||||
MxBool MxCompositePresenter::HasTickleStatePassed(TickleState p_tickleState)
|
||||
{
|
||||
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
|
||||
MxPresenter* presenter = *it;
|
||||
if (!presenter->HasTickleStatePassed(p_tickleState))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
27
LEGO1/omni/src/common/mxcore.cpp
Normal file
27
LEGO1/omni/src/common/mxcore.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "mxcore.h"
|
||||
|
||||
#include "define.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x10001f70
|
||||
MxResult MxCore::Tickle()
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae1a0
|
||||
MxCore::MxCore()
|
||||
{
|
||||
m_id = (MxU32) g_mxcoreCount[0];
|
||||
g_mxcoreCount[0]++;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae1e0
|
||||
MxCore::~MxCore()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae1f0
|
||||
MxLong MxCore::Notify(MxParam& p_param)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
104
LEGO1/omni/src/common/mxmediamanager.cpp
Normal file
104
LEGO1/omni/src/common/mxmediamanager.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "mxmediamanager.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxpresenter.h"
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxMediaManager, 0x2c);
|
||||
DECOMP_SIZE_ASSERT(MxPresenterList, 0x18);
|
||||
DECOMP_SIZE_ASSERT(MxPresenterListCursor, 0x10);
|
||||
|
||||
// FUNCTION: LEGO1 0x100b84c0
|
||||
MxMediaManager::MxMediaManager()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8560
|
||||
MxMediaManager::~MxMediaManager()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b85d0
|
||||
MxResult MxMediaManager::Init()
|
||||
{
|
||||
this->m_presenters = NULL;
|
||||
this->m_thread = NULL;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b85e0
|
||||
MxResult MxMediaManager::InitPresenters()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
this->m_presenters = new MxPresenterList;
|
||||
|
||||
if (!this->m_presenters) {
|
||||
this->Destroy();
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8710
|
||||
void MxMediaManager::Destroy()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
if (this->m_presenters)
|
||||
delete this->m_presenters;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8790
|
||||
MxResult MxMediaManager::Tickle()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxPresenter* presenter;
|
||||
MxPresenterListCursor cursor(this->m_presenters);
|
||||
|
||||
while (cursor.Next(presenter))
|
||||
presenter->Tickle();
|
||||
|
||||
cursor.Reset();
|
||||
|
||||
while (cursor.Next(presenter))
|
||||
presenter->PutData();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b88c0
|
||||
void MxMediaManager::AddPresenter(MxPresenter& p_presenter)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
this->m_presenters->Append(&p_presenter);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8980
|
||||
void MxMediaManager::RemovePresenter(MxPresenter& p_presenter)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxPresenterListCursor cursor(this->m_presenters);
|
||||
|
||||
if (cursor.Find(&p_presenter))
|
||||
cursor.Detach();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8ac0
|
||||
void MxMediaManager::StopPresenters()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxPresenter* presenter;
|
||||
MxPresenterListCursor cursor(this->m_presenters);
|
||||
|
||||
while (cursor.Next(presenter))
|
||||
presenter->EndAction();
|
||||
}
|
||||
277
LEGO1/omni/src/common/mxmediapresenter.cpp
Normal file
277
LEGO1/omni/src/common/mxmediapresenter.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
#include "mxmediapresenter.h"
|
||||
|
||||
#include "mxactionnotificationparam.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxcompositepresenter.h"
|
||||
#include "mxnotificationmanager.h"
|
||||
#include "mxstreamchunk.h"
|
||||
#include "mxtimer.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxMediaPresenter, 0x50);
|
||||
DECOMP_SIZE_ASSERT(MxStreamChunkList, 0x18);
|
||||
DECOMP_SIZE_ASSERT(MxStreamChunkListCursor, 0x10);
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c550
|
||||
MxMediaPresenter::~MxMediaPresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c5b0
|
||||
void MxMediaPresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b54e0
|
||||
void MxMediaPresenter::Init()
|
||||
{
|
||||
this->m_subscriber = NULL;
|
||||
this->m_chunks = NULL;
|
||||
this->m_cursor = NULL;
|
||||
this->m_currentChunk = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b54f0
|
||||
void MxMediaPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (m_currentChunk && m_subscriber)
|
||||
m_subscriber->FUN_100b8390(m_currentChunk);
|
||||
|
||||
if (m_subscriber)
|
||||
delete m_subscriber;
|
||||
|
||||
if (m_cursor)
|
||||
delete m_cursor;
|
||||
|
||||
if (m_chunks) {
|
||||
MxStreamChunkListCursor cursor(m_chunks);
|
||||
MxStreamChunk* chunk;
|
||||
|
||||
while (cursor.Next(chunk))
|
||||
chunk->Release();
|
||||
|
||||
delete m_chunks;
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxPresenter::Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5650
|
||||
MxStreamChunk* MxMediaPresenter::FUN_100b5650()
|
||||
{
|
||||
MxStreamChunk* result = NULL;
|
||||
|
||||
if (m_subscriber) {
|
||||
result = m_subscriber->FUN_100b8360();
|
||||
|
||||
if (result && result->GetFlags() & MxDSChunk::Flag_Bit3) {
|
||||
m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7);
|
||||
m_subscriber->FUN_100b8250();
|
||||
m_subscriber->FUN_100b8390(result);
|
||||
result = NULL;
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Done;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b56b0
|
||||
MxStreamChunk* MxMediaPresenter::NextChunk()
|
||||
{
|
||||
MxStreamChunk* result = NULL;
|
||||
|
||||
if (m_subscriber) {
|
||||
result = m_subscriber->FUN_100b8250();
|
||||
|
||||
if (result && result->GetFlags() & MxDSChunk::Flag_Bit3) {
|
||||
m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7);
|
||||
m_subscriber->FUN_100b8390(result);
|
||||
result = NULL;
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Done;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5700
|
||||
MxResult MxMediaPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (MxPresenter::StartAction(p_controller, p_action) == SUCCESS) {
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Looping) {
|
||||
m_chunks = new MxStreamChunkList;
|
||||
m_cursor = new MxStreamChunkListCursor(m_chunks);
|
||||
|
||||
if (!m_chunks && !m_cursor)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_controller) {
|
||||
m_subscriber = new MxDSSubscriber;
|
||||
|
||||
if (!m_subscriber ||
|
||||
m_subscriber->Create(p_controller, p_action->GetObjectId(), p_action->GetUnknown24()) != SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = SUCCESS;
|
||||
}
|
||||
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5bc0
|
||||
void MxMediaPresenter::EndAction()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (!m_action)
|
||||
return;
|
||||
|
||||
m_currentChunk = NULL;
|
||||
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_World &&
|
||||
(!m_compositePresenter || !m_compositePresenter->VTable0x64(2))) {
|
||||
MxPresenter::Enable(FALSE);
|
||||
SetTickleState(TickleState_Idle);
|
||||
}
|
||||
else {
|
||||
MxDSAction* action = m_action;
|
||||
MxPresenter::EndAction();
|
||||
|
||||
if (m_subscriber) {
|
||||
delete m_subscriber;
|
||||
m_subscriber = NULL;
|
||||
}
|
||||
|
||||
if (action && action->GetOrigin()) {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxEndActionNotificationParam param(c_notificationEndAction, this, action, FALSE);
|
||||
NotificationManager()->Send(action->GetOrigin(), ¶m);
|
||||
}
|
||||
#else
|
||||
NotificationManager()->Send(
|
||||
action->GetOrigin(),
|
||||
&MxEndActionNotificationParam(c_notificationEndAction, this, action, FALSE)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5d10
|
||||
MxResult MxMediaPresenter::Tickle()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
FUN_100b5650();
|
||||
|
||||
return MxPresenter::Tickle();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5d90
|
||||
void MxMediaPresenter::StreamingTickle()
|
||||
{
|
||||
if (!m_currentChunk) {
|
||||
m_currentChunk = NextChunk();
|
||||
|
||||
if (m_currentChunk) {
|
||||
if (m_currentChunk->GetFlags() & MxDSChunk::Flag_End) {
|
||||
m_subscriber->FUN_100b8390(m_currentChunk);
|
||||
m_currentChunk = NULL;
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Repeating;
|
||||
}
|
||||
else if (m_action->GetFlags() & MxDSAction::Flag_Looping) {
|
||||
AppendChunk(m_currentChunk);
|
||||
|
||||
if (!IsEnabled()) {
|
||||
m_subscriber->FUN_100b8390(m_currentChunk);
|
||||
m_currentChunk = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5e10
|
||||
void MxMediaPresenter::RepeatingTickle()
|
||||
{
|
||||
if (IsEnabled() && !m_currentChunk) {
|
||||
if (m_cursor)
|
||||
if (!m_cursor->Next(m_currentChunk))
|
||||
m_cursor->Next(m_currentChunk);
|
||||
|
||||
if (m_currentChunk) {
|
||||
MxLong time = m_currentChunk->GetTime();
|
||||
if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_unk5;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m_action->GetElapsedTime() <= m_action->GetStartTime() + m_action->GetDuration()) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_unk5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5ef0
|
||||
void MxMediaPresenter::DoneTickle()
|
||||
{
|
||||
m_previousTickleStates |= 1 << m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Idle;
|
||||
EndAction();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5f10
|
||||
void MxMediaPresenter::AppendChunk(MxStreamChunk* p_chunk)
|
||||
{
|
||||
MxStreamChunk* chunk = new MxStreamChunk;
|
||||
|
||||
MxU32 length = p_chunk->GetLength();
|
||||
chunk->SetLength(length);
|
||||
chunk->SetData(new MxU8[length]);
|
||||
chunk->SetTime(p_chunk->GetTime());
|
||||
|
||||
memcpy(chunk->GetData(), p_chunk->GetData(), chunk->GetLength());
|
||||
m_chunks->Append(chunk);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6030
|
||||
void MxMediaPresenter::Enable(MxBool p_enable)
|
||||
{
|
||||
if (IsEnabled() != p_enable) {
|
||||
MxPresenter::Enable(p_enable);
|
||||
|
||||
if (p_enable) {
|
||||
MxLong time = Timer()->GetTime();
|
||||
m_action->SetUnknown90(time);
|
||||
SetTickleState(TickleState_Repeating);
|
||||
}
|
||||
else {
|
||||
if (m_cursor)
|
||||
m_cursor->Reset();
|
||||
m_currentChunk = NULL;
|
||||
SetTickleState(TickleState_Done);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
LEGO1/omni/src/common/mxobjectfactory.cpp
Normal file
49
LEGO1/omni/src/common/mxobjectfactory.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "mxobjectfactory.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxcompositepresenter.h"
|
||||
#include "mxeventpresenter.h"
|
||||
#include "mxflcpresenter.h"
|
||||
#include "mxloopingflcpresenter.h"
|
||||
#include "mxloopingmidipresenter.h"
|
||||
#include "mxloopingsmkpresenter.h"
|
||||
#include "mxmidipresenter.h"
|
||||
#include "mxpresenter.h"
|
||||
#include "mxsmkpresenter.h"
|
||||
#include "mxstillpresenter.h"
|
||||
#include "mxvideopresenter.h"
|
||||
#include "mxwavepresenter.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxObjectFactory, 0x38); // 100af1db
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0d80
|
||||
MxObjectFactory::MxObjectFactory()
|
||||
{
|
||||
#define X(V) this->m_id##V = MxAtomId(#V, LookupMode_Exact);
|
||||
FOR_MXOBJECTFACTORY_OBJECTS(X)
|
||||
#undef X
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b12c0
|
||||
MxCore* MxObjectFactory::Create(const char* p_name)
|
||||
{
|
||||
MxCore* object = NULL;
|
||||
MxAtomId atom(p_name, LookupMode_Exact);
|
||||
|
||||
if (0) {
|
||||
}
|
||||
#define X(V) \
|
||||
else if (this->m_id##V == atom) \
|
||||
{ \
|
||||
object = new V; \
|
||||
}
|
||||
FOR_MXOBJECTFACTORY_OBJECTS(X)
|
||||
#undef X
|
||||
return object;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b1a30
|
||||
void MxObjectFactory::Destroy(MxCore* p_object)
|
||||
{
|
||||
delete p_object;
|
||||
}
|
||||
348
LEGO1/omni/src/common/mxpresenter.cpp
Normal file
348
LEGO1/omni/src/common/mxpresenter.cpp
Normal file
@@ -0,0 +1,348 @@
|
||||
#include "mxpresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "define.h"
|
||||
#include "legoobjectfactory.h"
|
||||
#include "legoomni.h"
|
||||
#include "mxactionnotificationparam.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxcompositepresenter.h"
|
||||
#include "mxdsanim.h"
|
||||
#include "mxdssound.h"
|
||||
#include "mxentity.h"
|
||||
#include "mxnotificationmanager.h"
|
||||
#include "mxparam.h"
|
||||
#include "mxstreamer.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxPresenter, 0x40);
|
||||
|
||||
// FUNCTION: LEGO1 0x1000be30
|
||||
void MxPresenter::VTable0x14()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000be40
|
||||
void MxPresenter::ReadyTickle()
|
||||
{
|
||||
ParseExtra();
|
||||
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Starting;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000be60
|
||||
void MxPresenter::StartingTickle()
|
||||
{
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Streaming;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000be80
|
||||
void MxPresenter::StreamingTickle()
|
||||
{
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Repeating;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bea0
|
||||
void MxPresenter::RepeatingTickle()
|
||||
{
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_unk5;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bec0
|
||||
void MxPresenter::Unk5Tickle()
|
||||
{
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Done;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bee0
|
||||
void MxPresenter::DoneTickle()
|
||||
{
|
||||
m_previousTickleStates |= 1 << m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Idle;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bf00
|
||||
MxPresenter::~MxPresenter()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bf70
|
||||
MxResult MxPresenter::AddToManager()
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bf80
|
||||
void MxPresenter::Destroy()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bf90
|
||||
void MxPresenter::SetTickleState(TickleState p_tickleState)
|
||||
{
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = p_tickleState;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bfb0
|
||||
MxBool MxPresenter::HasTickleStatePassed(TickleState p_tickleState)
|
||||
{
|
||||
return m_previousTickleStates & (1 << (unsigned char) p_tickleState);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bfc0
|
||||
MxResult MxPresenter::PutData()
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000bfd0
|
||||
MxBool MxPresenter::IsHit(MxS32 p_x, MxS32 p_y)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4d50
|
||||
void MxPresenter::Init()
|
||||
{
|
||||
m_currentTickleState = TickleState_Idle;
|
||||
m_action = NULL;
|
||||
m_location = MxPoint32(0, 0);
|
||||
m_displayZ = 0;
|
||||
m_compositePresenter = NULL;
|
||||
m_previousTickleStates = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4d80
|
||||
MxResult MxPresenter::StartAction(MxStreamController*, MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
this->m_action = p_action;
|
||||
|
||||
const Vector3Data& location = this->m_action->GetLocation();
|
||||
MxS32 previousTickleState = this->m_currentTickleState;
|
||||
|
||||
this->m_location = MxPoint32(this->m_action->GetLocation()[0], this->m_action->GetLocation()[1]);
|
||||
this->m_displayZ = this->m_action->GetLocation()[2];
|
||||
this->m_previousTickleStates |= 1 << (unsigned char) previousTickleState;
|
||||
this->m_currentTickleState = TickleState_Ready;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4e40
|
||||
void MxPresenter::EndAction()
|
||||
{
|
||||
if (this->m_action == NULL)
|
||||
return;
|
||||
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
if (!this->m_compositePresenter) {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxEndActionNotificationParam param(c_notificationEndAction, NULL, this->m_action, TRUE);
|
||||
MxOmni::GetInstance()->NotifyCurrentEntity(¶m);
|
||||
}
|
||||
#else
|
||||
MxOmni::GetInstance()->NotifyCurrentEntity(
|
||||
&MxEndActionNotificationParam(c_notificationEndAction, NULL, this->m_action, TRUE)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
this->m_action = NULL;
|
||||
MxS32 previousTickleState = 1 << m_currentTickleState;
|
||||
this->m_previousTickleStates |= previousTickleState;
|
||||
this->m_currentTickleState = TickleState_Idle;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4fc0
|
||||
void MxPresenter::ParseExtra()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
MxU16 len = m_action->GetExtraLength();
|
||||
char* extraData = m_action->GetExtraData();
|
||||
|
||||
if (len) {
|
||||
// len &= MAXWORD;
|
||||
char extraCopy[512];
|
||||
memcpy(extraCopy, extraData, len);
|
||||
extraCopy[len] = '\0';
|
||||
|
||||
char worldValue[512];
|
||||
if (KeyValueStringParse(worldValue, g_strWORLD, extraCopy)) {
|
||||
char* token = strtok(worldValue, g_parseExtraTokens);
|
||||
char buf[256];
|
||||
strcpy(buf, token);
|
||||
|
||||
token = strtok(NULL, g_parseExtraTokens);
|
||||
MxS32 val = token ? atoi(token) : 0;
|
||||
MxEntity* result = MxOmni::GetInstance()->FindWorld(buf, val, this);
|
||||
|
||||
m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_World);
|
||||
|
||||
if (result)
|
||||
SendToCompositePresenter(MxOmni::GetInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5120
|
||||
void MxPresenter::SendToCompositePresenter(MxOmni* p_omni)
|
||||
{
|
||||
if (m_compositePresenter) {
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxNotificationParam param(MXPRESENTER_NOTIFICATION, this);
|
||||
NotificationManager()->Send(m_compositePresenter, ¶m);
|
||||
}
|
||||
#else
|
||||
NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(MXPRESENTER_NOTIFICATION, this));
|
||||
#endif
|
||||
|
||||
m_action->SetOrigin(p_omni ? p_omni : MxOmni::GetInstance());
|
||||
m_compositePresenter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5200
|
||||
MxResult MxPresenter::Tickle()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
switch (this->m_currentTickleState) {
|
||||
case TickleState_Ready:
|
||||
this->ReadyTickle();
|
||||
|
||||
if (m_currentTickleState != TickleState_Starting)
|
||||
break;
|
||||
case TickleState_Starting:
|
||||
this->StartingTickle();
|
||||
|
||||
if (m_currentTickleState != TickleState_Streaming)
|
||||
break;
|
||||
case TickleState_Streaming:
|
||||
this->StreamingTickle();
|
||||
|
||||
if (m_currentTickleState != TickleState_Repeating)
|
||||
break;
|
||||
case TickleState_Repeating:
|
||||
this->RepeatingTickle();
|
||||
|
||||
if (m_currentTickleState != TickleState_unk5)
|
||||
break;
|
||||
case TickleState_unk5:
|
||||
this->Unk5Tickle();
|
||||
|
||||
if (m_currentTickleState != TickleState_Done)
|
||||
break;
|
||||
case TickleState_Done:
|
||||
this->DoneTickle();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b52d0
|
||||
void MxPresenter::Enable(MxBool p_enable)
|
||||
{
|
||||
if (this->m_action && this->IsEnabled() != p_enable) {
|
||||
MxU32 flags = this->m_action->GetFlags();
|
||||
|
||||
if (p_enable)
|
||||
this->m_action->SetFlags(flags | MxDSAction::Flag_Enabled);
|
||||
else
|
||||
this->m_action->SetFlags(flags & ~MxDSAction::Flag_Enabled);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5310
|
||||
const char* PresenterNameDispatch(const MxDSAction& p_action)
|
||||
{
|
||||
const char* name = p_action.GetSourceName();
|
||||
MxS32 format;
|
||||
|
||||
if (!name || strlen(name) == 0) {
|
||||
switch (p_action.GetType()) {
|
||||
case MxDSType_Anim:
|
||||
format = ((MxDSAnim&) p_action).GetMediaFormat();
|
||||
switch (format) {
|
||||
case FOURCC(' ', 'F', 'L', 'C'):
|
||||
name = !p_action.IsLooping() ? "MxFlcPresenter" : "MxLoopingFlcPresenter";
|
||||
break;
|
||||
case FOURCC(' ', 'S', 'M', 'K'):
|
||||
name = !p_action.IsLooping() ? "MxSmkPresenter" : "MxLoopingSmkPresenter";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MxDSType_Sound:
|
||||
format = ((MxDSSound&) p_action).GetMediaFormat();
|
||||
switch (format) {
|
||||
case FOURCC(' ', 'M', 'I', 'D'):
|
||||
name = !p_action.IsLooping() ? "MxMIDIPresenter" : "MxLoopingMIDIPresenter";
|
||||
break;
|
||||
case FOURCC(' ', 'W', 'A', 'V'):
|
||||
name = "MxWavePresenter";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MxDSType_SerialAction:
|
||||
case MxDSType_ParallelAction:
|
||||
case MxDSType_SelectAction:
|
||||
name = "MxCompositePresenter";
|
||||
break;
|
||||
|
||||
case MxDSType_Event:
|
||||
name = "MxEventPresenter";
|
||||
break;
|
||||
|
||||
case MxDSType_Still:
|
||||
name = "MxStillPresenter";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b5410
|
||||
MxEntity* MxPresenter::CreateEntityBackend(const char* p_name)
|
||||
{
|
||||
char buffer[512];
|
||||
char buffer2[512];
|
||||
strcpy(buffer, p_name);
|
||||
|
||||
MxU16 extraLen = m_action->GetExtraLength();
|
||||
|
||||
buffer[0] = extraLen;
|
||||
buffer[1] = extraLen >> 8;
|
||||
if (extraLen) {
|
||||
extraLen &= MAXWORD;
|
||||
memcpy(buffer2 + 2, m_action->GetExtraData(), extraLen);
|
||||
buffer2[extraLen + 2] = 0;
|
||||
KeyValueStringParse(buffer, g_strOBJECT, buffer2 + 2);
|
||||
}
|
||||
|
||||
return (MxEntity*) ObjectFactory()->Create(buffer);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b54c0
|
||||
MxBool MxPresenter::IsEnabled()
|
||||
{
|
||||
return this->m_action && this->m_action->GetFlags() & MxDSAction::Flag_Enabled;
|
||||
}
|
||||
118
LEGO1/omni/src/common/mxstring.cpp
Normal file
118
LEGO1/omni/src/common/mxstring.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "mxstring.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxString, 0x10)
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae200
|
||||
MxString::MxString()
|
||||
{
|
||||
// Set string to one char in length and set that char to null terminator
|
||||
this->m_data = new char[1];
|
||||
this->m_data[0] = 0;
|
||||
this->m_length = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae2a0
|
||||
MxString::MxString(const MxString& p_str)
|
||||
{
|
||||
this->m_length = p_str.m_length;
|
||||
this->m_data = new char[this->m_length + 1];
|
||||
strcpy(this->m_data, p_str.m_data);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae350
|
||||
MxString::MxString(const char* p_str)
|
||||
{
|
||||
if (p_str) {
|
||||
this->m_length = strlen(p_str);
|
||||
this->m_data = new char[this->m_length + 1];
|
||||
strcpy(this->m_data, p_str);
|
||||
}
|
||||
else {
|
||||
this->m_data = new char[1];
|
||||
this->m_data[0] = 0;
|
||||
this->m_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae420
|
||||
MxString::~MxString()
|
||||
{
|
||||
delete[] this->m_data;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae490
|
||||
void MxString::ToUpperCase()
|
||||
{
|
||||
strupr(this->m_data);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae4a0
|
||||
void MxString::ToLowerCase()
|
||||
{
|
||||
strlwr(this->m_data);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae4b0
|
||||
MxString& MxString::operator=(const MxString& p_str)
|
||||
{
|
||||
if (this->m_data != p_str.m_data) {
|
||||
delete[] this->m_data;
|
||||
this->m_length = p_str.m_length;
|
||||
this->m_data = new char[this->m_length + 1];
|
||||
strcpy(this->m_data, p_str.m_data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae510
|
||||
const MxString& MxString::operator=(const char* p_data)
|
||||
{
|
||||
if (this->m_data != p_data) {
|
||||
delete[] this->m_data;
|
||||
this->m_length = strlen(p_data);
|
||||
this->m_data = new char[this->m_length + 1];
|
||||
strcpy(this->m_data, p_data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return type is intentionally just MxString, not MxString&.
|
||||
// This forces MSVC to add $ReturnUdt$ to the stack for 100% match.
|
||||
// FUNCTION: LEGO1 0x100ae580
|
||||
MxString MxString::operator+(const char* p_str)
|
||||
{
|
||||
// MxString constructor allocates 1 byte for m_data, so free that first
|
||||
MxString tmp;
|
||||
delete[] tmp.m_data;
|
||||
|
||||
tmp.m_length = strlen(p_str) + this->m_length;
|
||||
tmp.m_data = new char[tmp.m_length + 1];
|
||||
|
||||
strcpy(tmp.m_data, this->m_data);
|
||||
strcpy(tmp.m_data + this->m_length, p_str);
|
||||
|
||||
return MxString(tmp);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae690
|
||||
MxString& MxString::operator+=(const char* p_str)
|
||||
{
|
||||
int newlen = this->m_length + strlen(p_str);
|
||||
|
||||
char* tmp = new char[newlen + 1];
|
||||
strcpy(tmp, this->m_data);
|
||||
strcpy(tmp + this->m_length, p_str);
|
||||
|
||||
delete[] this->m_data;
|
||||
this->m_length = newlen;
|
||||
this->m_data = tmp;
|
||||
|
||||
return *this;
|
||||
}
|
||||
112
LEGO1/omni/src/common/mxticklemanager.cpp
Normal file
112
LEGO1/omni/src/common/mxticklemanager.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxtimer.h"
|
||||
#include "mxtypes.h"
|
||||
|
||||
#define TICKLE_MANAGER_FLAG_DESTROY 0x1
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxTickleClient, 0x10);
|
||||
DECOMP_SIZE_ASSERT(MxTickleManager, 0x14);
|
||||
|
||||
// FUNCTION: LEGO1 0x100bdd10
|
||||
MxTickleClient::MxTickleClient(MxCore* p_client, MxTime p_interval)
|
||||
{
|
||||
m_flags = 0;
|
||||
m_client = p_client;
|
||||
m_interval = p_interval;
|
||||
m_lastUpdateTime = -m_interval;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bdd30
|
||||
MxTickleManager::~MxTickleManager()
|
||||
{
|
||||
while (m_clients.size() != 0) {
|
||||
MxTickleClient* client = m_clients.front();
|
||||
m_clients.pop_front();
|
||||
delete client;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bdde0
|
||||
MxResult MxTickleManager::Tickle()
|
||||
{
|
||||
MxTime time = Timer()->GetTime();
|
||||
|
||||
for (MxTickleClientPtrList::iterator it = m_clients.begin(); it != m_clients.end();) {
|
||||
MxTickleClient* client = *it;
|
||||
|
||||
// TODO: Match.
|
||||
if ((MxU8) client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) {
|
||||
m_clients.erase(it++);
|
||||
delete client;
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
|
||||
if (client->GetLastUpdateTime() > time)
|
||||
client->SetLastUpdateTime(-client->GetTickleInterval());
|
||||
|
||||
if ((client->GetTickleInterval() + client->GetLastUpdateTime()) < time) {
|
||||
client->GetClient()->Tickle();
|
||||
client->SetLastUpdateTime(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bde80
|
||||
void MxTickleManager::RegisterClient(MxCore* p_client, MxTime p_interval)
|
||||
{
|
||||
MxTime interval = GetClientTickleInterval(p_client);
|
||||
if (interval == TICKLE_MANAGER_NOT_FOUND) {
|
||||
MxTickleClient* client = new MxTickleClient(p_client, p_interval);
|
||||
if (client != NULL)
|
||||
m_clients.push_back(client);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bdf60
|
||||
void MxTickleManager::UnregisterClient(MxCore* p_client)
|
||||
{
|
||||
MxTickleClientPtrList::iterator it = m_clients.begin();
|
||||
while (it != m_clients.end()) {
|
||||
MxTickleClient* client = *it;
|
||||
if (client->GetClient() == p_client) {
|
||||
client->SetFlags(client->GetFlags() | TICKLE_MANAGER_FLAG_DESTROY);
|
||||
return;
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bdfa0
|
||||
void MxTickleManager::SetClientTickleInterval(MxCore* p_client, MxTime p_interval)
|
||||
{
|
||||
for (MxTickleClientPtrList::iterator it = m_clients.begin(); it != m_clients.end(); it++) {
|
||||
MxTickleClient* client = *it;
|
||||
if ((client->GetClient() == p_client) && ((client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) == 0)) {
|
||||
client->SetTickleInterval(p_interval);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be000
|
||||
MxTime MxTickleManager::GetClientTickleInterval(MxCore* p_client)
|
||||
{
|
||||
MxTickleClientPtrList::iterator it = m_clients.begin();
|
||||
while (it != m_clients.end()) {
|
||||
MxTickleClient* client = *it;
|
||||
if ((client->GetClient() == p_client) && ((client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) == 0))
|
||||
return client->GetTickleInterval();
|
||||
|
||||
it++;
|
||||
}
|
||||
|
||||
return TICKLE_MANAGER_NOT_FOUND;
|
||||
}
|
||||
42
LEGO1/omni/src/common/mxtimer.cpp
Normal file
42
LEGO1/omni/src/common/mxtimer.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "mxtimer.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// GLOBAL: LEGO1 0x10101414
|
||||
MxLong MxTimer::g_lastTimeCalculated = 0;
|
||||
|
||||
// GLOBAL: LEGO1 0x10101418
|
||||
MxLong MxTimer::g_lastTimeTimerStarted = 0;
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae060
|
||||
MxTimer::MxTimer()
|
||||
{
|
||||
this->m_isRunning = FALSE;
|
||||
m_startTime = timeGetTime();
|
||||
// yeah this is somehow what the asm is
|
||||
g_lastTimeCalculated = m_startTime;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae140
|
||||
MxLong MxTimer::GetRealTime()
|
||||
{
|
||||
MxTimer::g_lastTimeCalculated = timeGetTime();
|
||||
return MxTimer::g_lastTimeCalculated - this->m_startTime;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae160
|
||||
void MxTimer::Start()
|
||||
{
|
||||
g_lastTimeTimerStarted = this->GetRealTime();
|
||||
this->m_isRunning = TRUE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ae180
|
||||
void MxTimer::Stop()
|
||||
{
|
||||
MxLong elapsed = this->GetRealTime();
|
||||
MxLong startTime = elapsed - MxTimer::g_lastTimeTimerStarted;
|
||||
this->m_isRunning = FALSE;
|
||||
// this feels very stupid but it's what the assembly does
|
||||
this->m_startTime = this->m_startTime + startTime - 5;
|
||||
}
|
||||
24
LEGO1/omni/src/common/mxvariable.cpp
Normal file
24
LEGO1/omni/src/common/mxvariable.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "mxvariable.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxstring.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxVariable, 0x24)
|
||||
|
||||
// FUNCTION: LEGO1 0x1003bea0
|
||||
MxString* MxVariable::GetValue()
|
||||
{
|
||||
return &m_value;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1003beb0
|
||||
void MxVariable::SetValue(const char* p_value)
|
||||
{
|
||||
m_value = p_value;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1003bec0
|
||||
void MxVariable::Destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
66
LEGO1/omni/src/common/mxvariabletable.cpp
Normal file
66
LEGO1/omni/src/common/mxvariabletable.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "mxvariabletable.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100b7330
|
||||
MxS8 MxVariableTable::Compare(MxVariable* p_var0, MxVariable* p_var1)
|
||||
{
|
||||
return p_var0->GetKey()->Compare(*p_var1->GetKey());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b7370
|
||||
MxU32 MxVariableTable::Hash(MxVariable* p_var)
|
||||
{
|
||||
const char* str = p_var->GetKey()->GetData();
|
||||
MxU32 value = 0;
|
||||
|
||||
for (int i = 0; str[i]; i++) {
|
||||
value += str[i];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b73a0
|
||||
void MxVariableTable::SetVariable(const char* p_key, const char* p_value)
|
||||
{
|
||||
MxHashTableCursor<MxVariable*> cursor(this);
|
||||
MxVariable* var = new MxVariable(p_key, p_value);
|
||||
|
||||
if (cursor.Find(var)) {
|
||||
delete var;
|
||||
cursor.Current(var);
|
||||
var->SetValue(p_value);
|
||||
}
|
||||
else {
|
||||
MxHashTable<MxVariable*>::Add(var);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b7740
|
||||
void MxVariableTable::SetVariable(MxVariable* p_var)
|
||||
{
|
||||
MxHashTableCursor<MxVariable*> cursor(this);
|
||||
MxBool found = cursor.Find(p_var);
|
||||
|
||||
if (found)
|
||||
cursor.DeleteMatch();
|
||||
|
||||
MxHashTable<MxVariable*>::Add(p_var);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b78f0
|
||||
const char* MxVariableTable::GetVariable(const char* p_key)
|
||||
{
|
||||
const char* value = "";
|
||||
MxHashTableCursor<MxVariable*> cursor(this);
|
||||
MxVariable* var = new MxVariable(p_key);
|
||||
|
||||
MxBool found = cursor.Find(var);
|
||||
delete var;
|
||||
|
||||
if (found) {
|
||||
cursor.Current(var);
|
||||
value = var->GetValue()->GetData();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
114
LEGO1/omni/src/control/mxcontrolpresenter.cpp
Normal file
114
LEGO1/omni/src/control/mxcontrolpresenter.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "mxcontrolpresenter.h"
|
||||
|
||||
#include "legoomni.h"
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c)
|
||||
|
||||
// FUNCTION: LEGO1 0x10043f50
|
||||
MxControlPresenter::MxControlPresenter()
|
||||
{
|
||||
this->m_unk0x4c = 0;
|
||||
this->m_unk0x4e = -1;
|
||||
this->m_unk0x50 = FALSE;
|
||||
this->m_unk0x52 = 0;
|
||||
this->m_unk0x58 = 0;
|
||||
this->m_unk0x54 = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10043fd0
|
||||
void MxControlPresenter::RepeatingTickle()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10043fe0
|
||||
MxBool MxControlPresenter::VTable0x64(undefined4 p_undefined)
|
||||
{
|
||||
return m_unk0x50;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10043ff0
|
||||
void MxControlPresenter::VTable0x68(MxBool p_undefined)
|
||||
{
|
||||
m_unk0x50 = p_undefined;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10044110
|
||||
MxControlPresenter::~MxControlPresenter()
|
||||
{
|
||||
if (m_unk0x58)
|
||||
delete m_unk0x58;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10044180
|
||||
MxResult MxControlPresenter::AddToManager()
|
||||
{
|
||||
m_unk0x4e = 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10044190
|
||||
MxResult MxControlPresenter::StartAction(MxStreamController*, MxDSAction*)
|
||||
{
|
||||
// TODO
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10044260
|
||||
void MxControlPresenter::EndAction()
|
||||
{
|
||||
if (m_action) {
|
||||
m_unk0x50 = TRUE;
|
||||
MxCompositePresenter::EndAction();
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10044270
|
||||
MxBool MxControlPresenter::FUN_10044270(undefined4, undefined4, undefined4*)
|
||||
{
|
||||
// TODO
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10044480
|
||||
MxBool MxControlPresenter::FUN_10044480(undefined4, undefined4*)
|
||||
{
|
||||
// TODO
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10044540
|
||||
void MxControlPresenter::FUN_10044540(undefined2)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10044610
|
||||
void MxControlPresenter::ReadyTickle()
|
||||
{
|
||||
MxPresenter::ParseExtra();
|
||||
TickleManager()->UnregisterClient(this);
|
||||
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Repeating;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10044640
|
||||
void MxControlPresenter::ParseExtra()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x10044820
|
||||
void MxControlPresenter::Enable(MxBool p_enable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100448a0
|
||||
MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState)
|
||||
{
|
||||
// TODO
|
||||
return TRUE;
|
||||
}
|
||||
22
LEGO1/omni/src/entity/mxentity.cpp
Normal file
22
LEGO1/omni/src/entity/mxentity.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "mxentity.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxEntity, 0x10)
|
||||
|
||||
// FUNCTION: LEGO1 0x10001070
|
||||
MxResult MxEntity::Create(MxS32 p_id, const MxAtomId& p_atom)
|
||||
{
|
||||
this->m_mxEntityId = p_id;
|
||||
this->m_atom = p_atom;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c110
|
||||
MxEntity::~MxEntity()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1001d190
|
||||
MxEntity::MxEntity()
|
||||
{
|
||||
this->m_mxEntityId = -1;
|
||||
}
|
||||
76
LEGO1/omni/src/event/mxeventmanager.cpp
Normal file
76
LEGO1/omni/src/event/mxeventmanager.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "mxeventmanager.h"
|
||||
|
||||
#include "mxcriticalsection.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxthread.h"
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0360
|
||||
MxEventManager::MxEventManager()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c03f0
|
||||
MxEventManager::~MxEventManager()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0450
|
||||
void MxEventManager::Init()
|
||||
{
|
||||
// This is intentionally left blank
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0460
|
||||
void MxEventManager::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
if (m_thread != NULL) {
|
||||
m_thread->Terminate();
|
||||
delete m_thread;
|
||||
}
|
||||
else
|
||||
TickleManager()->UnregisterClient(this);
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxMediaManager::Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c04a0
|
||||
MxResult MxEventManager::Create(MxU32 p_frequencyMS, MxBool p_createThread)
|
||||
{
|
||||
MxResult status = FAILURE;
|
||||
MxBool locked = FALSE;
|
||||
|
||||
MxResult result = MxMediaManager::InitPresenters();
|
||||
if (result == SUCCESS) {
|
||||
if (p_createThread) {
|
||||
this->m_criticalSection.Enter();
|
||||
locked = TRUE;
|
||||
this->m_thread = new MxTickleThread(this, p_frequencyMS);
|
||||
|
||||
if (!this->m_thread || this->m_thread->Start(0, 0) != SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
TickleManager()->RegisterClient(this, p_frequencyMS);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
|
||||
done:
|
||||
if (status != SUCCESS)
|
||||
Destroy();
|
||||
|
||||
if (locked)
|
||||
this->m_criticalSection.Leave();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0590
|
||||
void MxEventManager::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
117
LEGO1/omni/src/event/mxeventpresenter.cpp
Normal file
117
LEGO1/omni/src/event/mxeventpresenter.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "mxeventpresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxeventmanager.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxvariabletable.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxEventPresenter, 0x54);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2b70
|
||||
MxEventPresenter::MxEventPresenter()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2d40
|
||||
MxEventPresenter::~MxEventPresenter()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2da0
|
||||
void MxEventPresenter::Init()
|
||||
{
|
||||
m_data = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2db0
|
||||
MxResult MxEventPresenter::AddToManager()
|
||||
{
|
||||
MxResult ret = FAILURE;
|
||||
|
||||
if (EventManager()) {
|
||||
ret = SUCCESS;
|
||||
EventManager()->AddPresenter(*this);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2de0
|
||||
void MxEventPresenter::Destroy()
|
||||
{
|
||||
if (EventManager())
|
||||
EventManager()->RemovePresenter(*this);
|
||||
|
||||
m_criticalSection.Enter();
|
||||
|
||||
if (m_data)
|
||||
delete[] m_data;
|
||||
|
||||
Init();
|
||||
|
||||
m_criticalSection.Leave();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2e30
|
||||
void MxEventPresenter::CopyData(MxStreamChunk* p_chunk)
|
||||
{
|
||||
m_data = new MxU8[p_chunk->GetLength()];
|
||||
memcpy(m_data, p_chunk->GetData(), p_chunk->GetLength());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2e70
|
||||
void MxEventPresenter::ReadyTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk) {
|
||||
CopyData(chunk);
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
ParseExtra();
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Starting;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2eb0
|
||||
void MxEventPresenter::StartingTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Streaming;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2ef0
|
||||
MxResult MxEventPresenter::PutData()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (IsEnabled()) {
|
||||
if (m_currentTickleState >= TickleState_Streaming &&
|
||||
(m_currentTickleState <= TickleState_Repeating || m_currentTickleState == TickleState_Done)) {
|
||||
if (m_currentChunk && m_currentChunk->GetLength()) {
|
||||
if (m_data[12] == 2) {
|
||||
const char* data = (const char*) m_currentChunk->GetData();
|
||||
MxVariableTable* variableTable = VariableTable();
|
||||
|
||||
const char* key = data;
|
||||
const char* value = &data[strlen(data) + 1];
|
||||
strlen(value);
|
||||
variableTable->SetVariable(key, value);
|
||||
}
|
||||
|
||||
if (m_currentTickleState == TickleState_Streaming)
|
||||
m_subscriber->FUN_100b8390(m_currentChunk);
|
||||
m_currentChunk = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
7
LEGO1/omni/src/main/mxmain.cpp
Normal file
7
LEGO1/omni/src/main/mxmain.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
// FUNCTION: LEGO1 0x10091ee0
|
||||
__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
504
LEGO1/omni/src/main/mxomni.cpp
Normal file
504
LEGO1/omni/src/main/mxomni.cpp
Normal file
@@ -0,0 +1,504 @@
|
||||
#include "mxomni.h"
|
||||
|
||||
#include "mxactionnotificationparam.h"
|
||||
#include "mxatomidcounter.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxeventmanager.h"
|
||||
#include "mxmusicmanager.h"
|
||||
#include "mxnotificationmanager.h"
|
||||
#include "mxobjectfactory.h"
|
||||
#include "mxomnicreateparam.h"
|
||||
#include "mxpresenter.h"
|
||||
#include "mxsoundmanager.h"
|
||||
#include "mxstreamer.h"
|
||||
#include "mxticklemanager.h"
|
||||
#include "mxtimer.h"
|
||||
#include "mxvideomanager.h"
|
||||
|
||||
// GLOBAL: LEGO1 0x101015b8
|
||||
char g_hdPath[1024];
|
||||
|
||||
// GLOBAL: LEGO1 0x101019b8
|
||||
char g_cdPath[1024];
|
||||
|
||||
// GLOBAL: LEGO1 0x10101db8
|
||||
MxBool g_use3dSound;
|
||||
|
||||
// GLOBAL: LEGO1 0x101015b0
|
||||
MxOmni* MxOmni::g_instance = NULL;
|
||||
|
||||
// FUNCTION: LEGO1 0x100159e0
|
||||
void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last)
|
||||
{
|
||||
MxDSAction action;
|
||||
|
||||
action.SetAtomId(*p_id);
|
||||
action.SetUnknown24(-2);
|
||||
|
||||
for (MxS32 first = p_first, last = p_last; first <= last; first++) {
|
||||
action.SetObjectId(first);
|
||||
DeleteObject(action);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10058a90
|
||||
MxBool MxOmni::IsTimerRunning()
|
||||
{
|
||||
return m_timerRunning;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acea0
|
||||
MxObjectFactory* ObjectFactory()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetObjectFactory();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aceb0
|
||||
MxNotificationManager* NotificationManager()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetNotificationManager();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acec0
|
||||
MxTickleManager* TickleManager()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetTickleManager();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aced0
|
||||
MxTimer* Timer()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetTimer();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acee0
|
||||
MxAtomIdCounterSet* AtomIdCounterSet()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetAtomIdCounterSet();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acef0
|
||||
MxStreamer* Streamer()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetStreamer();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acf00
|
||||
MxSoundManager* MSoundManager()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetSoundManager();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acf10
|
||||
MxVideoManager* MVideoManager()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetVideoManager();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acf20
|
||||
MxVariableTable* VariableTable()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetVariableTable();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acf30
|
||||
MxMusicManager* MusicManager()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetMusicManager();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acf40
|
||||
MxEventManager* EventManager()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetEventManager();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acf70
|
||||
void DeleteObject(MxDSAction& p_dsAction)
|
||||
{
|
||||
MxOmni::GetInstance()->DeleteObject(p_dsAction);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aef10
|
||||
MxOmni::MxOmni()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aefb0
|
||||
MxEntity* MxOmni::FindWorld(const char*, MxS32, MxPresenter*)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aefc0
|
||||
void MxOmni::NotifyCurrentEntity(MxNotificationParam* p_param)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aeff0
|
||||
MxOmni::~MxOmni()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100af080
|
||||
void MxOmni::Init()
|
||||
{
|
||||
m_windowHandle = NULL;
|
||||
m_objectFactory = NULL;
|
||||
m_variableTable = NULL;
|
||||
m_tickleManager = NULL;
|
||||
m_notificationManager = NULL;
|
||||
m_videoManager = NULL;
|
||||
m_soundManager = NULL;
|
||||
m_musicManager = NULL;
|
||||
m_eventManager = NULL;
|
||||
m_timer = NULL;
|
||||
m_streamer = NULL;
|
||||
m_atomIdCounterSet = NULL;
|
||||
m_timerRunning = FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100af0b0
|
||||
void MxOmni::SetInstance(MxOmni* p_instance)
|
||||
{
|
||||
g_instance = p_instance;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100af0c0
|
||||
MxResult MxOmni::Create(MxOmniCreateParam& p_param)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
if (!(m_atomIdCounterSet = new MxAtomIdCounterSet()))
|
||||
goto done;
|
||||
|
||||
m_mediaPath = p_param.GetMediaPath();
|
||||
m_windowHandle = p_param.GetWindowHandle();
|
||||
|
||||
if (p_param.CreateFlags().CreateObjectFactory()) {
|
||||
if (!(m_objectFactory = new MxObjectFactory()))
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateVariableTable()) {
|
||||
if (!(m_variableTable = new MxVariableTable()))
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateTimer()) {
|
||||
if (!(m_timer = new MxTimer()))
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateTickleManager()) {
|
||||
if (!(m_tickleManager = new MxTickleManager()))
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateNotificationManager()) {
|
||||
if (m_notificationManager = new MxNotificationManager()) {
|
||||
if (m_notificationManager->Create(100, 0) != SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateStreamer()) {
|
||||
if (!(m_streamer = new MxStreamer()) || m_streamer->Create() != SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateVideoManager()) {
|
||||
if (m_videoManager = new MxVideoManager()) {
|
||||
if (m_videoManager->Create(p_param.GetVideoParam(), 100, 0) != SUCCESS) {
|
||||
delete m_videoManager;
|
||||
m_videoManager = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateSoundManager()) {
|
||||
if (m_soundManager = new MxSoundManager()) {
|
||||
if (m_soundManager->Create(10, 0) != SUCCESS) {
|
||||
delete m_soundManager;
|
||||
m_soundManager = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateMusicManager()) {
|
||||
if (m_musicManager = new MxMusicManager()) {
|
||||
if (m_musicManager->Create(50, 0) != SUCCESS) {
|
||||
delete m_musicManager;
|
||||
m_musicManager = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_param.CreateFlags().CreateEventManager()) {
|
||||
if (m_eventManager = new MxEventManager()) {
|
||||
if (m_eventManager->Create(50, 0) != SUCCESS) {
|
||||
delete m_eventManager;
|
||||
m_eventManager = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = SUCCESS;
|
||||
done:
|
||||
if (result != SUCCESS)
|
||||
Destroy();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100afe90
|
||||
void MxOmni::Destroy()
|
||||
{
|
||||
{
|
||||
MxDSAction action;
|
||||
action.SetObjectId(-1);
|
||||
action.SetUnknown24(-2);
|
||||
DeleteObject(action);
|
||||
}
|
||||
|
||||
// TODO: private members
|
||||
if (m_notificationManager) {
|
||||
while (m_notificationManager->GetQueue()) {
|
||||
if (m_notificationManager->GetQueue()->size() == 0)
|
||||
break;
|
||||
m_notificationManager->Tickle();
|
||||
}
|
||||
|
||||
m_notificationManager->SetActive(FALSE);
|
||||
}
|
||||
|
||||
delete m_eventManager;
|
||||
delete m_soundManager;
|
||||
delete m_musicManager;
|
||||
delete m_videoManager;
|
||||
delete m_streamer;
|
||||
delete m_timer;
|
||||
delete m_objectFactory;
|
||||
delete m_variableTable;
|
||||
delete m_notificationManager;
|
||||
delete m_tickleManager;
|
||||
|
||||
// There could be a tree/iterator function that does this inline
|
||||
if (m_atomIdCounterSet) {
|
||||
while (!m_atomIdCounterSet->empty()) {
|
||||
// Pop each node and delete its value
|
||||
MxAtomIdCounterSet::iterator begin = m_atomIdCounterSet->begin();
|
||||
MxAtomIdCounter* value = *begin;
|
||||
m_atomIdCounterSet->erase(begin);
|
||||
delete value;
|
||||
}
|
||||
delete m_atomIdCounterSet;
|
||||
}
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0090
|
||||
MxResult MxOmni::Start(MxDSAction* p_dsAction)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
if (p_dsAction->GetAtomId().GetInternal() != NULL && p_dsAction->GetObjectId() != -1 && m_streamer != NULL) {
|
||||
result = m_streamer->FUN_100b99b0(p_dsAction);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b00c0
|
||||
void MxOmni::DeleteObject(MxDSAction& p_dsAction)
|
||||
{
|
||||
if (m_streamer != NULL) {
|
||||
m_streamer->DeleteObject(&p_dsAction);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b00e0
|
||||
MxResult MxOmni::CreatePresenter(MxStreamController* p_controller, MxDSAction& p_action)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
const char* name = PresenterNameDispatch(p_action);
|
||||
MxPresenter* object = (MxPresenter*) m_objectFactory->Create(name);
|
||||
|
||||
if (object) {
|
||||
if (object->AddToManager() == SUCCESS) {
|
||||
MxPresenter* sender = p_action.GetUnknown28();
|
||||
if (!sender)
|
||||
sender = p_controller->FUN_100c1e70(p_action);
|
||||
|
||||
if (sender) {
|
||||
p_action.SetOrigin(sender);
|
||||
object->SetCompositePresenter((MxCompositePresenter*) sender);
|
||||
}
|
||||
else {
|
||||
if (!p_action.GetOrigin())
|
||||
p_action.SetOrigin(this);
|
||||
object->SetCompositePresenter(NULL);
|
||||
}
|
||||
|
||||
if (object->StartAction(p_controller, &p_action) == SUCCESS) {
|
||||
if (sender) {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxType4NotificationParam param(this, &p_action, object);
|
||||
NotificationManager()->Send(sender, ¶m);
|
||||
}
|
||||
#else
|
||||
NotificationManager()->Send(sender, &MxType4NotificationParam(this, &p_action, object));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (p_action.GetUnknown84()) {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxStartActionNotificationParam param(c_notificationStartAction, object, &p_action, FALSE);
|
||||
NotificationManager()->Send(p_action.GetUnknown84(), ¶m);
|
||||
}
|
||||
#else
|
||||
NotificationManager()->Send(
|
||||
p_action.GetUnknown84(),
|
||||
&MxStartActionNotificationParam(c_notificationStartAction, object, &p_action, FALSE)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0680
|
||||
MxOmni* MxOmni::GetInstance()
|
||||
{
|
||||
return g_instance;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0690
|
||||
void MxOmni::DestroyInstance()
|
||||
{
|
||||
if (g_instance != NULL) {
|
||||
delete g_instance;
|
||||
g_instance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100b06b0
|
||||
MxBool MxOmni::FUN_100b06b0(MxDSAction* p_action, const char* p_name)
|
||||
{
|
||||
// TODO
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b07f0
|
||||
MxLong MxOmni::Notify(MxParam& p_param)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalsection);
|
||||
|
||||
if (((MxNotificationParam&) p_param).GetNotification() != c_notificationEndAction)
|
||||
return 0;
|
||||
|
||||
return HandleActionEnd(p_param);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0880
|
||||
MxLong MxOmni::HandleActionEnd(MxParam& p_param)
|
||||
{
|
||||
MxDSAction* action = ((MxEndActionNotificationParam&) p_param).GetAction();
|
||||
MxStreamController* controller = Streamer()->GetOpenStream(action->GetAtomId().GetInternal());
|
||||
|
||||
if (controller != NULL) {
|
||||
action = controller->GetUnk0x54().Find(action, FALSE);
|
||||
if (action) {
|
||||
if (FUN_100b06b0(action, "LegoLoopingAnimPresenter") == FALSE) {
|
||||
delete controller->GetUnk0x54().Find(action, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((MxEndActionNotificationParam&) p_param).GetSender()) {
|
||||
delete ((MxEndActionNotificationParam&) p_param).GetSender();
|
||||
}
|
||||
|
||||
if (((MxEndActionNotificationParam&) p_param).GetAction()) {
|
||||
delete ((MxEndActionNotificationParam&) p_param).GetAction();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0900
|
||||
const char* MxOmni::GetHD()
|
||||
{
|
||||
return g_hdPath;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0910
|
||||
void MxOmni::SetHD(const char* p_hd)
|
||||
{
|
||||
strcpy(g_hdPath, p_hd);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0940
|
||||
const char* MxOmni::GetCD()
|
||||
{
|
||||
return g_cdPath;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0950
|
||||
void MxOmni::SetCD(const char* p_cd)
|
||||
{
|
||||
strcpy(g_cdPath, p_cd);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0980
|
||||
MxBool MxOmni::IsSound3D()
|
||||
{
|
||||
return g_use3dSound;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0990
|
||||
void MxOmni::SetSound3D(MxBool p_use3dSound)
|
||||
{
|
||||
g_use3dSound = p_use3dSound;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b09a0
|
||||
MxBool MxOmni::DoesEntityExist(MxDSAction& p_dsAction)
|
||||
{
|
||||
if (m_streamer->FUN_100b9b30(p_dsAction)) {
|
||||
MxNotificationPtrList* queue = m_notificationManager->GetQueue();
|
||||
|
||||
if (!queue || queue->size() == 0)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b09d0
|
||||
void MxOmni::StartTimer()
|
||||
{
|
||||
if (m_timerRunning == FALSE && m_timer != NULL && m_soundManager != NULL) {
|
||||
m_timer->Start();
|
||||
m_soundManager->Pause();
|
||||
m_timerRunning = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0a00
|
||||
void MxOmni::StopTimer()
|
||||
{
|
||||
if (m_timerRunning != FALSE && m_timer != NULL && m_soundManager != NULL) {
|
||||
m_timer->Stop();
|
||||
m_soundManager->Resume();
|
||||
m_timerRunning = FALSE;
|
||||
}
|
||||
}
|
||||
17
LEGO1/omni/src/main/mxomnicreateflags.cpp
Normal file
17
LEGO1/omni/src/main/mxomnicreateflags.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "mxomnicreateflags.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0a30
|
||||
MxOmniCreateFlags::MxOmniCreateFlags()
|
||||
{
|
||||
this->CreateObjectFactory(TRUE);
|
||||
this->CreateVariableTable(TRUE);
|
||||
this->CreateTickleManager(TRUE);
|
||||
this->CreateNotificationManager(TRUE);
|
||||
this->CreateVideoManager(TRUE);
|
||||
this->CreateSoundManager(TRUE);
|
||||
this->CreateMusicManager(TRUE);
|
||||
this->CreateEventManager(TRUE);
|
||||
|
||||
this->CreateTimer(TRUE);
|
||||
this->CreateStreamer(TRUE);
|
||||
}
|
||||
15
LEGO1/omni/src/main/mxomnicreateparam.cpp
Normal file
15
LEGO1/omni/src/main/mxomnicreateparam.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "mxomnicreateparam.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0b00
|
||||
MxOmniCreateParam::MxOmniCreateParam(
|
||||
const char* p_mediaPath,
|
||||
struct HWND__* p_windowHandle,
|
||||
MxVideoParam& p_vparam,
|
||||
MxOmniCreateFlags p_flags
|
||||
)
|
||||
{
|
||||
this->m_mediaPath = p_mediaPath;
|
||||
this->m_windowHandle = (HWND) p_windowHandle;
|
||||
this->m_videoParam = p_vparam;
|
||||
this->m_createFlags = p_flags;
|
||||
}
|
||||
33
LEGO1/omni/src/notify/mxactionnotificationparam.cpp
Normal file
33
LEGO1/omni/src/notify/mxactionnotificationparam.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "mxactionnotificationparam.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxActionNotificationParam, 0x14)
|
||||
DECOMP_SIZE_ASSERT(MxEndActionNotificationParam, 0x14)
|
||||
|
||||
// FUNCTION: LEGO1 0x100510c0
|
||||
MxNotificationParam* MxActionNotificationParam::Clone()
|
||||
{
|
||||
return new MxActionNotificationParam(this->m_type, this->m_sender, this->m_action, this->m_realloc);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10051270
|
||||
MxNotificationParam* MxEndActionNotificationParam::Clone()
|
||||
{
|
||||
return new MxEndActionNotificationParam(c_notificationEndAction, this->m_sender, this->m_action, this->m_realloc);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b0300
|
||||
MxNotificationParam* MxStartActionNotificationParam::Clone()
|
||||
{
|
||||
return new MxStartActionNotificationParam(
|
||||
c_notificationStartAction,
|
||||
this->m_sender,
|
||||
this->m_action,
|
||||
this->m_realloc
|
||||
);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b04f0
|
||||
MxNotificationParam* MxType4NotificationParam::Clone()
|
||||
{
|
||||
return new MxType4NotificationParam(this->m_sender, this->m_action, this->m_unk0x14);
|
||||
}
|
||||
189
LEGO1/omni/src/notify/mxnotificationmanager.cpp
Normal file
189
LEGO1/omni/src/notify/mxnotificationmanager.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "mxnotificationmanager.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "decomp.h"
|
||||
#include "legoomni.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxparam.h"
|
||||
#include "mxticklemanager.h"
|
||||
#include "mxtypes.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxNotification, 0x8);
|
||||
DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40);
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac220
|
||||
MxNotification::MxNotification(MxCore* p_target, MxNotificationParam* p_param)
|
||||
{
|
||||
m_target = p_target;
|
||||
m_param = p_param->Clone();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac240
|
||||
MxNotification::~MxNotification()
|
||||
{
|
||||
delete m_param;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac250
|
||||
MxNotificationManager::MxNotificationManager() : MxCore(), m_lock(), m_listenerIds()
|
||||
{
|
||||
m_unk0x2c = 0;
|
||||
m_queue = NULL;
|
||||
m_active = TRUE;
|
||||
m_sendList = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac450
|
||||
MxNotificationManager::~MxNotificationManager()
|
||||
{
|
||||
MxAutoLocker lock(&m_lock);
|
||||
Tickle();
|
||||
delete m_queue;
|
||||
m_queue = NULL;
|
||||
|
||||
TickleManager()->UnregisterClient(this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac600
|
||||
MxResult MxNotificationManager::Create(MxU32 p_frequencyMS, MxBool p_createThread)
|
||||
{
|
||||
MxResult result = SUCCESS;
|
||||
m_queue = new MxNotificationPtrList();
|
||||
|
||||
if (m_queue == NULL) {
|
||||
result = FAILURE;
|
||||
}
|
||||
else {
|
||||
TickleManager()->RegisterClient(this, 10);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac6c0
|
||||
MxResult MxNotificationManager::Send(MxCore* p_listener, MxNotificationParam* p_param)
|
||||
{
|
||||
MxAutoLocker lock(&m_lock);
|
||||
|
||||
if (m_active == FALSE) {
|
||||
return FAILURE;
|
||||
}
|
||||
else {
|
||||
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
|
||||
if (it == m_listenerIds.end()) {
|
||||
return FAILURE;
|
||||
}
|
||||
else {
|
||||
MxNotification* notif = new MxNotification(p_listener, p_param);
|
||||
if (notif != NULL) {
|
||||
m_queue->push_back(notif);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac800
|
||||
MxResult MxNotificationManager::Tickle()
|
||||
{
|
||||
m_sendList = new MxNotificationPtrList();
|
||||
if (m_sendList == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
else {
|
||||
{
|
||||
MxAutoLocker lock(&m_lock);
|
||||
MxNotificationPtrList* temp1 = m_queue;
|
||||
MxNotificationPtrList* temp2 = m_sendList;
|
||||
m_queue = temp2;
|
||||
m_sendList = temp1;
|
||||
}
|
||||
|
||||
while (m_sendList->size() != 0) {
|
||||
MxNotification* notif = m_sendList->front();
|
||||
m_sendList->pop_front();
|
||||
notif->GetTarget()->Notify(*notif->GetParam());
|
||||
delete notif;
|
||||
}
|
||||
|
||||
delete m_sendList;
|
||||
m_sendList = NULL;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac990
|
||||
void MxNotificationManager::FlushPending(MxCore* p_listener)
|
||||
{
|
||||
MxNotificationPtrList pending;
|
||||
MxNotification* notif;
|
||||
|
||||
{
|
||||
MxAutoLocker lock(&m_lock);
|
||||
|
||||
// Find all notifications from, and addressed to, p_listener.
|
||||
if (m_sendList != NULL) {
|
||||
MxNotificationPtrList::iterator it = m_sendList->begin();
|
||||
while (it != m_sendList->end()) {
|
||||
notif = *it;
|
||||
if ((notif->GetTarget()->GetId() == p_listener->GetId()) ||
|
||||
(notif->GetParam()->GetSender()) &&
|
||||
(notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) {
|
||||
m_sendList->erase(it++);
|
||||
pending.push_back(notif);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MxNotificationPtrList::iterator it = m_queue->begin();
|
||||
while (it != m_queue->end()) {
|
||||
notif = *it;
|
||||
if ((notif->GetTarget()->GetId() == p_listener->GetId()) ||
|
||||
(notif->GetParam()->GetSender()) && (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) {
|
||||
m_queue->erase(it++);
|
||||
pending.push_back(notif);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deliver those notifications.
|
||||
while (pending.size() != 0) {
|
||||
notif = pending.front();
|
||||
pending.pop_front();
|
||||
notif->GetTarget()->Notify(*notif->GetParam());
|
||||
delete notif;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acd20
|
||||
void MxNotificationManager::Register(MxCore* p_listener)
|
||||
{
|
||||
MxAutoLocker lock(&m_lock);
|
||||
|
||||
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
|
||||
if (it != m_listenerIds.end())
|
||||
return;
|
||||
|
||||
m_listenerIds.push_back(p_listener->GetId());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100acdf0
|
||||
void MxNotificationManager::Unregister(MxCore* p_listener)
|
||||
{
|
||||
MxAutoLocker lock(&m_lock);
|
||||
|
||||
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
|
||||
|
||||
if (it != m_listenerIds.end()) {
|
||||
m_listenerIds.erase(it);
|
||||
FlushPending(p_listener);
|
||||
}
|
||||
}
|
||||
11
LEGO1/omni/src/notify/mxnotificationparam.cpp
Normal file
11
LEGO1/omni/src/notify/mxnotificationparam.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "mxnotificationparam.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxNotificationParam, 0xc);
|
||||
|
||||
// FUNCTION: LEGO1 0x10010390
|
||||
MxNotificationParam* MxNotificationParam::Clone()
|
||||
{
|
||||
return new MxNotificationParam(m_type, m_sender);
|
||||
}
|
||||
3
LEGO1/omni/src/notify/mxtype17notificationparam.cpp
Normal file
3
LEGO1/omni/src/notify/mxtype17notificationparam.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "mxtype17notificationparam.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxType17NotificationParam, 0x2c)
|
||||
443
LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp
Normal file
443
LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp
Normal file
@@ -0,0 +1,443 @@
|
||||
#include "mxdiskstreamcontroller.h"
|
||||
|
||||
#include "mxactionnotificationparam.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdiskstreamprovider.h"
|
||||
#include "mxdsstreamingaction.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDiskStreamController, 0xc8);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7120
|
||||
MxDiskStreamController::MxDiskStreamController()
|
||||
{
|
||||
m_unk0x8c = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7530
|
||||
MxDiskStreamController::~MxDiskStreamController()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
m_unk0xc4 = FALSE;
|
||||
m_unk0x70 = FALSE;
|
||||
|
||||
if (m_provider) {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxDSAction action;
|
||||
m_provider->VTable0x20(&action);
|
||||
}
|
||||
#else
|
||||
m_provider->VTable0x20(&MxDSAction());
|
||||
#endif
|
||||
}
|
||||
|
||||
MxDSAction* action;
|
||||
while (m_unk0x3c.PopFront(action))
|
||||
delete action;
|
||||
|
||||
if (m_provider) {
|
||||
delete m_provider;
|
||||
m_provider = NULL;
|
||||
}
|
||||
|
||||
FUN_100c8720();
|
||||
|
||||
while (m_list0x80.PopFront(action))
|
||||
FUN_100c7cb0((MxDSStreamingAction*) action);
|
||||
|
||||
while (m_list0x64.PopFront(action))
|
||||
FUN_100c7cb0((MxDSStreamingAction*) action);
|
||||
|
||||
while (!m_list0x74.empty()) {
|
||||
MxDSBuffer* buffer = m_list0x74.front();
|
||||
m_list0x74.pop_front();
|
||||
FUN_100c7ce0(buffer);
|
||||
}
|
||||
|
||||
TickleManager()->UnregisterClient(this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7790
|
||||
MxResult MxDiskStreamController::Open(const char* p_filename)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxResult result = MxStreamController::Open(p_filename);
|
||||
|
||||
if (result == SUCCESS) {
|
||||
m_provider = new MxDiskStreamProvider();
|
||||
if (m_provider == NULL) {
|
||||
result = FAILURE;
|
||||
}
|
||||
else {
|
||||
result = m_provider->SetResourceToGet(this);
|
||||
if (result != SUCCESS) {
|
||||
delete m_provider;
|
||||
m_provider = NULL;
|
||||
}
|
||||
else {
|
||||
TickleManager()->RegisterClient(this, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7880
|
||||
MxResult MxDiskStreamController::VTable0x18(undefined4, undefined4)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7890
|
||||
MxResult MxDiskStreamController::FUN_100c7890(MxDSStreamingAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
if (p_action == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
m_list0x80.push_back(p_action);
|
||||
FUN_100c7970();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7960
|
||||
MxResult MxDiskStreamController::VTable0x34(undefined4)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7970
|
||||
void MxDiskStreamController::FUN_100c7970()
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7980
|
||||
void MxDiskStreamController::FUN_100c7980()
|
||||
{
|
||||
MxDSBuffer* buffer;
|
||||
MxDSStreamingAction* action = NULL;
|
||||
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
if (m_unk0x3c.size() && m_unk0x8c < m_provider->GetStreamBuffersNum()) {
|
||||
buffer = new MxDSBuffer();
|
||||
|
||||
if (buffer->AllocateBuffer(m_provider->GetFileSize(), MxDSBufferType_Chunk) != SUCCESS) {
|
||||
if (buffer)
|
||||
delete buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
action = VTable0x28();
|
||||
if (!action) {
|
||||
if (buffer)
|
||||
delete buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
action->SetUnknowna0(buffer);
|
||||
m_unk0x8c++;
|
||||
}
|
||||
}
|
||||
|
||||
if (action) {
|
||||
((MxDiskStreamProvider*) m_provider)->FUN_100d1780(action);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7ac0
|
||||
MxDSStreamingAction* MxDiskStreamController::VTable0x28()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxDSAction* oldAction;
|
||||
MxDSStreamingAction* result = NULL;
|
||||
MxU32 filesize = m_provider->GetFileSize();
|
||||
|
||||
if (m_unk0x3c.PopFront(oldAction)) {
|
||||
result = new MxDSStreamingAction((MxDSStreamingAction&) *oldAction);
|
||||
if (result) {
|
||||
MxU32 offset = result->GetBufferOffset() + filesize;
|
||||
((MxDSStreamingAction*) oldAction)->SetUnknown94(offset);
|
||||
((MxDSStreamingAction*) oldAction)->SetBufferOffset(offset);
|
||||
m_unk0x3c.push_back(oldAction);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7c00
|
||||
MxResult MxDiskStreamController::VTable0x30(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxResult result = MxStreamController::VTable0x30(p_action);
|
||||
|
||||
MxDSStreamingAction* item;
|
||||
while (TRUE) {
|
||||
item = (MxDSStreamingAction*) m_list0x90.Find(p_action, TRUE);
|
||||
if (item == NULL) {
|
||||
break;
|
||||
}
|
||||
FUN_100c7cb0(item);
|
||||
}
|
||||
|
||||
while (TRUE) {
|
||||
item = (MxDSStreamingAction*) m_list0x64.Find(p_action, TRUE);
|
||||
if (item == NULL) {
|
||||
break;
|
||||
}
|
||||
FUN_100c7cb0(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7cb0
|
||||
void MxDiskStreamController::FUN_100c7cb0(MxDSStreamingAction* p_action)
|
||||
{
|
||||
if (p_action->GetUnknowna0()) {
|
||||
FUN_100c7ce0(p_action->GetUnknowna0());
|
||||
}
|
||||
p_action->SetUnknowna0(NULL);
|
||||
delete p_action;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7ce0
|
||||
void MxDiskStreamController::FUN_100c7ce0(MxDSBuffer* p_buffer)
|
||||
{
|
||||
switch (p_buffer->GetMode()) {
|
||||
case MxDSBufferType_Chunk:
|
||||
m_unk0x8c--;
|
||||
case MxDSBufferType_Allocate:
|
||||
case MxDSBufferType_Unknown:
|
||||
delete p_buffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7d10
|
||||
MxResult MxDiskStreamController::FUN_100c7d10()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxDSStreamingAction* action = FUN_100c7db0();
|
||||
|
||||
if (!action)
|
||||
return FAILURE;
|
||||
|
||||
if (FUN_100c8360(action) != SUCCESS) {
|
||||
VTable0x24(action);
|
||||
FUN_100c7cb0(action);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7db0
|
||||
MxDSStreamingAction* MxDiskStreamController::FUN_100c7db0()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
for (MxStreamListMxNextActionDataStart::iterator it = m_nextActionList.begin(); it != m_nextActionList.end();
|
||||
it++) {
|
||||
MxNextActionDataStart* data = *it;
|
||||
for (MxStreamListMxDSAction::iterator it2 = m_list0x64.begin(); it2 != m_list0x64.end(); it2++) {
|
||||
MxDSStreamingAction* streamingAction = (MxDSStreamingAction*) *it2;
|
||||
if (streamingAction->GetObjectId() == data->GetObjectId() &&
|
||||
streamingAction->GetUnknown24() == data->GetUnknown24() &&
|
||||
streamingAction->GetBufferOffset() == data->GetData()) {
|
||||
m_nextActionList.erase(it);
|
||||
|
||||
data->SetData(m_provider->GetFileSize() + data->GetData());
|
||||
m_nextActionList.push_back(data);
|
||||
|
||||
m_list0x64.erase(it2);
|
||||
return streamingAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7f40
|
||||
void MxDiskStreamController::FUN_100c7f40(MxDSStreamingAction* p_streamingaction)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
if (p_streamingaction) {
|
||||
m_list0x64.push_back(p_streamingaction);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c7ff0
|
||||
MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxDSStreamingAction* entry =
|
||||
(MxDSStreamingAction*) m_list0x80.Find(p_action, FALSE); // TODO: is this a seperate class?
|
||||
if (entry) {
|
||||
MxDSStreamingAction* action = new MxDSStreamingAction(*p_action, 0);
|
||||
action->SetUnknown28(entry->GetUnknown28());
|
||||
action->SetUnknown84(entry->GetUnknown84());
|
||||
action->SetOrigin(entry->GetOrigin());
|
||||
action->SetUnknowna0(entry->GetUnknowna4());
|
||||
|
||||
FUN_100c7f40(action);
|
||||
|
||||
if (VTable0x2c(p_action, entry->GetUnknown94()) != SUCCESS)
|
||||
return FAILURE;
|
||||
}
|
||||
else if (MxStreamController::VTable0x20(p_action) != SUCCESS)
|
||||
return FAILURE;
|
||||
|
||||
m_unk0x70 = TRUE;
|
||||
m_unk0xc4 = TRUE;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8160
|
||||
MxResult MxDiskStreamController::VTable0x24(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
if (m_unk0x54.Find(p_action, FALSE) == NULL) {
|
||||
if (VTable0x30(p_action) == SUCCESS) {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxEndActionNotificationParam param(c_notificationEndAction, NULL, p_action, TRUE);
|
||||
MxOmni::GetInstance()->NotifyCurrentEntity(¶m);
|
||||
}
|
||||
#else
|
||||
MxOmni::GetInstance()->NotifyCurrentEntity(
|
||||
&MxEndActionNotificationParam(c_notificationEndAction, NULL, p_action, TRUE)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
MxDSAction action;
|
||||
if (m_provider) {
|
||||
m_provider->VTable0x20(p_action);
|
||||
}
|
||||
|
||||
do {
|
||||
if (m_action0x60 != NULL) {
|
||||
delete m_action0x60;
|
||||
m_action0x60 = NULL;
|
||||
}
|
||||
|
||||
action = *p_action;
|
||||
MxStreamController::VTable0x24(&action);
|
||||
} while (m_action0x60 != NULL);
|
||||
|
||||
if (m_unk0x3c.empty()) {
|
||||
m_unk0x70 = FALSE;
|
||||
m_unk0xc4 = FALSE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8360
|
||||
MxResult MxDiskStreamController::FUN_100c8360(MxDSStreamingAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
MxDSBuffer* buffer = p_action->GetUnknowna0();
|
||||
MxDSStreamingAction* action2 = (MxDSStreamingAction*) m_list0x90.Find(p_action, TRUE);
|
||||
buffer->FUN_100c6f80(p_action->GetUnknown94() - p_action->GetBufferOffset());
|
||||
buffer->FUN_100c67b0(this, p_action, &action2);
|
||||
|
||||
if (buffer->GetRefCount()) {
|
||||
p_action->SetUnknowna0(NULL);
|
||||
InsertToList74(buffer);
|
||||
}
|
||||
|
||||
if (action2) {
|
||||
if (action2->GetUnknowna0() == NULL) {
|
||||
FUN_100c7cb0(action2);
|
||||
}
|
||||
else {
|
||||
if (action2->GetObjectId() == -1) {
|
||||
action2->SetObjectId(p_action->GetObjectId());
|
||||
}
|
||||
|
||||
m_list0x90.push_back(action2);
|
||||
}
|
||||
}
|
||||
|
||||
FUN_100c7cb0(p_action);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c84a0
|
||||
void MxDiskStreamController::InsertToList74(MxDSBuffer* p_buffer)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
m_list0x74.push_back(p_buffer);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8540
|
||||
void MxDiskStreamController::FUN_100c8540()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
for (list<MxDSBuffer*>::iterator it = m_list0x74.begin(); it != m_list0x74.end();) {
|
||||
MxDSBuffer* buf = *it;
|
||||
if (buf->GetRefCount() == 0) {
|
||||
m_list0x74.erase(it++);
|
||||
FUN_100c7ce0(buf);
|
||||
}
|
||||
else
|
||||
it++;
|
||||
}
|
||||
|
||||
if (m_nextActionList.empty()) {
|
||||
while (!m_list0x64.empty()) {
|
||||
MxDSStreamingAction* action = (MxDSStreamingAction*) m_list0x64.front();
|
||||
m_list0x64.pop_front();
|
||||
FUN_100c7cb0(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8640
|
||||
MxResult MxDiskStreamController::Tickle()
|
||||
{
|
||||
if (m_unk0xc4) {
|
||||
FUN_100c7d10();
|
||||
}
|
||||
|
||||
FUN_100c8540();
|
||||
FUN_100c8720();
|
||||
|
||||
if (m_unk0x70) {
|
||||
FUN_100c7980();
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8670
|
||||
void MxDiskStreamController::FUN_100c8670(MxDSStreamingAction* p_streamingAction)
|
||||
{
|
||||
MxAutoLocker lock(&this->m_critical9c);
|
||||
m_list0xb8.push_back(p_streamingAction);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8720
|
||||
void MxDiskStreamController::FUN_100c8720()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_critical9c);
|
||||
|
||||
MxDSStreamingAction* action;
|
||||
while (!m_list0xb8.empty()) {
|
||||
action = (MxDSStreamingAction*) m_list0xb8.front();
|
||||
m_list0xb8.pop_front();
|
||||
|
||||
FUN_100c7cb0(action);
|
||||
}
|
||||
}
|
||||
298
LEGO1/omni/src/stream/mxdiskstreamprovider.cpp
Normal file
298
LEGO1/omni/src/stream/mxdiskstreamprovider.cpp
Normal file
@@ -0,0 +1,298 @@
|
||||
#include "mxdiskstreamprovider.h"
|
||||
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdiskstreamcontroller.h"
|
||||
#include "mxdsbuffer.h"
|
||||
#include "mxdsstreamingaction.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxstreamcontroller.h"
|
||||
#include "mxstring.h"
|
||||
#include "mxthread.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDiskStreamProviderThread, 0x1c)
|
||||
DECOMP_SIZE_ASSERT(MxDiskStreamProvider, 0x60);
|
||||
|
||||
// GLOBAL: LEGO1 0x10102878
|
||||
MxU32 g_unk0x10102878 = 0;
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0f30
|
||||
MxResult MxDiskStreamProviderThread::Run()
|
||||
{
|
||||
if (m_target)
|
||||
((MxDiskStreamProvider*) m_target)->WaitForWorkToComplete();
|
||||
MxThread::Run();
|
||||
// They should probably have writen "return MxThread::Run()" but they didn't.
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0f50
|
||||
MxResult MxDiskStreamProviderThread::StartWithTarget(MxDiskStreamProvider* p_target)
|
||||
{
|
||||
m_target = p_target;
|
||||
return Start(0x1000, 0);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0f70
|
||||
MxDiskStreamProvider::MxDiskStreamProvider()
|
||||
{
|
||||
this->m_pFile = NULL;
|
||||
this->m_remainingWork = FALSE;
|
||||
this->m_unk0x35 = FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d1240
|
||||
MxDiskStreamProvider::~MxDiskStreamProvider()
|
||||
{
|
||||
MxDSStreamingAction* action;
|
||||
m_unk0x35 = FALSE;
|
||||
|
||||
do {
|
||||
action = NULL;
|
||||
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
m_list.PopFrontStreamingAction(action);
|
||||
}
|
||||
|
||||
if (!action)
|
||||
break;
|
||||
|
||||
if (action->GetUnknowna0()->GetWriteOffset() < 0x20000)
|
||||
g_unk0x10102878--;
|
||||
|
||||
((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action);
|
||||
} while (action);
|
||||
|
||||
if (m_remainingWork) {
|
||||
m_remainingWork = FALSE;
|
||||
m_busySemaphore.Release(1);
|
||||
m_thread.Terminate();
|
||||
}
|
||||
|
||||
if (m_pFile)
|
||||
delete m_pFile;
|
||||
|
||||
m_pFile = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d13d0
|
||||
MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
MxString path;
|
||||
m_pLookup = p_resource;
|
||||
|
||||
path = (MxString(MxOmni::GetHD()) + p_resource->GetAtom().GetInternal() + ".si");
|
||||
|
||||
m_pFile = new MxDSFile(path.GetData(), 0);
|
||||
if (m_pFile != NULL) {
|
||||
if (m_pFile->Open(0) != 0) {
|
||||
path = MxString(MxOmni::GetCD()) + p_resource->GetAtom().GetInternal() + ".si";
|
||||
m_pFile->SetFileName(path.GetData());
|
||||
|
||||
if (m_pFile->Open(0) != 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
m_remainingWork = TRUE;
|
||||
m_busySemaphore.Init(0, 100);
|
||||
|
||||
if (m_thread.StartWithTarget(this) == SUCCESS && p_resource != NULL) {
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d15e0
|
||||
void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action)
|
||||
{
|
||||
MxDSStreamingAction* action;
|
||||
|
||||
if (p_action->GetObjectId() == -1) {
|
||||
m_unk0x35 = FALSE;
|
||||
|
||||
do {
|
||||
action = NULL;
|
||||
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
m_list.PopFrontStreamingAction(action);
|
||||
}
|
||||
|
||||
if (!action)
|
||||
return;
|
||||
|
||||
if (action->GetUnknowna0()->GetWriteOffset() < 0x20000)
|
||||
g_unk0x10102878--;
|
||||
|
||||
((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action);
|
||||
} while (action);
|
||||
}
|
||||
else {
|
||||
do {
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
action = (MxDSStreamingAction*) m_list.Find(p_action, TRUE);
|
||||
}
|
||||
|
||||
if (!action)
|
||||
return;
|
||||
|
||||
if (action->GetUnknowna0()->GetWriteOffset() < 0x20000)
|
||||
g_unk0x10102878--;
|
||||
|
||||
((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action);
|
||||
} while (action);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d1750
|
||||
MxResult MxDiskStreamProvider::WaitForWorkToComplete()
|
||||
{
|
||||
while (m_remainingWork) {
|
||||
m_busySemaphore.Wait(INFINITE);
|
||||
if (m_unk0x35)
|
||||
PerformWork();
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d1780
|
||||
MxResult MxDiskStreamProvider::FUN_100d1780(MxDSStreamingAction* p_action)
|
||||
{
|
||||
if (!m_remainingWork)
|
||||
return FAILURE;
|
||||
|
||||
if (p_action->GetUnknown9c() > 0 && !p_action->GetUnknowna0()) {
|
||||
MxDSBuffer* buffer = new MxDSBuffer();
|
||||
|
||||
if (!buffer)
|
||||
return FAILURE;
|
||||
|
||||
if (buffer->AllocateBuffer(GetFileSize(), MxDSBufferType_Allocate) != SUCCESS) {
|
||||
delete buffer;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
p_action->SetUnknowna0(buffer);
|
||||
}
|
||||
|
||||
if (p_action->GetUnknowna0()->GetWriteOffset() < 0x20000) {
|
||||
g_unk0x10102878++;
|
||||
}
|
||||
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
m_list.push_back(p_action);
|
||||
}
|
||||
|
||||
m_unk0x35 = TRUE;
|
||||
m_busySemaphore.Release(1);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d18f0
|
||||
void MxDiskStreamProvider::PerformWork()
|
||||
{
|
||||
MxDiskStreamController* controller = (MxDiskStreamController*) m_pLookup;
|
||||
MxDSStreamingAction* streamingAction = NULL;
|
||||
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
if (!m_list.empty()) {
|
||||
streamingAction = (MxDSStreamingAction*) m_list.front();
|
||||
|
||||
if (streamingAction && !FUN_100d1af0(streamingAction)) {
|
||||
m_thread.Sleep(500);
|
||||
m_busySemaphore.Release(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (!m_list.PopFrontStreamingAction(streamingAction))
|
||||
return;
|
||||
}
|
||||
|
||||
if (streamingAction->GetUnknowna0()->GetWriteOffset() < 0x20000) {
|
||||
g_unk0x10102878--;
|
||||
}
|
||||
|
||||
MxDSBuffer* buffer = streamingAction->GetUnknowna0();
|
||||
|
||||
if (m_pFile->GetPosition() == streamingAction->GetBufferOffset() ||
|
||||
m_pFile->Seek(streamingAction->GetBufferOffset(), 0) == 0) {
|
||||
buffer->SetUnknown14(m_pFile->GetPosition());
|
||||
|
||||
if (m_pFile->ReadToBuffer(buffer) == SUCCESS) {
|
||||
buffer->SetUnknown1c(m_pFile->GetPosition());
|
||||
|
||||
if (streamingAction->GetUnknown9c() > 0) {
|
||||
FUN_100d1b20(streamingAction);
|
||||
}
|
||||
else {
|
||||
if (m_pLookup == NULL || !((MxDiskStreamController*) m_pLookup)->GetUnk0xc4()) {
|
||||
controller->FUN_100c8670(streamingAction);
|
||||
}
|
||||
else {
|
||||
controller->FUN_100c7f40(streamingAction);
|
||||
}
|
||||
}
|
||||
|
||||
streamingAction = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (streamingAction) {
|
||||
controller->FUN_100c8670(streamingAction);
|
||||
}
|
||||
|
||||
m_thread.Sleep(0);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d1af0
|
||||
MxBool MxDiskStreamProvider::FUN_100d1af0(MxDSStreamingAction* p_action)
|
||||
{
|
||||
if (p_action->GetUnknowna0()->GetWriteOffset() == 0x20000) {
|
||||
return g_unk0x10102878 == 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100d1b20
|
||||
MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d1e90
|
||||
MxU32 MxDiskStreamProvider::GetFileSize()
|
||||
{
|
||||
return m_pFile->GetBufferSize();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d1ea0
|
||||
MxS32 MxDiskStreamProvider::GetStreamBuffersNum()
|
||||
{
|
||||
return m_pFile->GetStreamBuffersNum();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d1eb0
|
||||
MxU32 MxDiskStreamProvider::GetLengthInDWords()
|
||||
{
|
||||
return m_pFile->GetLengthInDWords();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d1ec0
|
||||
MxU32* MxDiskStreamProvider::GetBufferForDWords()
|
||||
{
|
||||
return m_pFile->GetBuffer();
|
||||
}
|
||||
493
LEGO1/omni/src/stream/mxdsbuffer.cpp
Normal file
493
LEGO1/omni/src/stream/mxdsbuffer.cpp
Normal file
@@ -0,0 +1,493 @@
|
||||
#include "mxdsbuffer.h"
|
||||
|
||||
#include "mxdiskstreamcontroller.h"
|
||||
#include "mxdschunk.h"
|
||||
#include "mxdsstreamingaction.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxstreamchunk.h"
|
||||
#include "mxstreamcontroller.h"
|
||||
#include "mxstreamer.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSBuffer, 0x34);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6470
|
||||
MxDSBuffer::MxDSBuffer()
|
||||
{
|
||||
m_refcount = 0;
|
||||
m_pBuffer = NULL;
|
||||
m_pIntoBuffer = NULL;
|
||||
m_pIntoBuffer2 = NULL;
|
||||
m_unk0x14 = 0;
|
||||
m_unk0x18 = 0;
|
||||
m_unk0x1c = 0;
|
||||
m_writeOffset = 0;
|
||||
m_bytesRemaining = 0;
|
||||
m_mode = MxDSBufferType_Preallocated;
|
||||
m_unk0x30 = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6530
|
||||
MxDSBuffer::~MxDSBuffer()
|
||||
{
|
||||
if (m_pBuffer != NULL) {
|
||||
switch (m_mode) {
|
||||
case MxDSBufferType_Allocate:
|
||||
case MxDSBufferType_Unknown:
|
||||
delete[] m_pBuffer;
|
||||
break;
|
||||
|
||||
case MxDSBufferType_Chunk: {
|
||||
MxU32 offset = m_writeOffset / 1024;
|
||||
MxStreamer* streamer = Streamer();
|
||||
|
||||
switch (offset) {
|
||||
case 0x40: {
|
||||
MxU32 a =
|
||||
(m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10);
|
||||
|
||||
MxU32 bit = 1 << ((MxU8) a & 0x1f);
|
||||
MxU32 index = (a & ~0x18u) >> 3;
|
||||
|
||||
if ((*(MxU32*) (&streamer->GetSubclass1().GetUnk08Ref()[index])) & bit) {
|
||||
MxU32* ptr = (MxU32*) (&streamer->GetSubclass1().GetUnk08Ref()[index]);
|
||||
*ptr = *ptr ^ bit;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x80: {
|
||||
MxU32 a =
|
||||
(m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10);
|
||||
|
||||
MxU32 bit = 1 << ((MxU8) a & 0x1f);
|
||||
MxU32 index = (a & ~0x18u) >> 3;
|
||||
|
||||
if ((*(MxU32*) (&streamer->GetSubclass2().GetUnk08Ref()[index])) & bit) {
|
||||
MxU32* ptr = (MxU32*) (&streamer->GetSubclass2().GetUnk08Ref()[index]);
|
||||
*ptr = *ptr ^ bit;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_unk0x14 = 0;
|
||||
m_unk0x1c = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6640
|
||||
MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
switch (p_mode) {
|
||||
case MxDSBufferType_Allocate:
|
||||
m_pBuffer = new MxU8[p_bufferSize];
|
||||
break;
|
||||
|
||||
case MxDSBufferType_Chunk: {
|
||||
MxStreamer* streamer = Streamer();
|
||||
|
||||
switch (p_bufferSize / 1024) {
|
||||
case 0x40: {
|
||||
for (MxU32 i = 0; i < 22; i++) {
|
||||
if (((1 << (i & 0x1f)) & (*(MxU32*) &streamer->GetSubclass1().GetUnk08Ref()[(i & ~0x18u) >> 3])) == 0) {
|
||||
MxU32* ptr = (MxU32*) &streamer->GetSubclass1().GetUnk08Ref()[(i & 0xffffffe7) >> 3];
|
||||
|
||||
*ptr = *ptr ^ 1 << (i & 0x1f);
|
||||
|
||||
m_pBuffer =
|
||||
(MxU8*) (streamer->GetSubclass1().GetSize() * i * 0x400 + streamer->GetSubclass1().GetBuffer());
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
m_pBuffer = NULL;
|
||||
break;
|
||||
}
|
||||
case 0x80: {
|
||||
for (MxU32 i = 0; i < 2; i++) {
|
||||
if (((1 << (i & 0x1f)) & (*(MxU32*) &streamer->GetSubclass2().GetUnk08Ref()[(i & ~0x18u) >> 3])) == 0) {
|
||||
MxU32* ptr = (MxU32*) &streamer->GetSubclass2().GetUnk08Ref()[(i & 0xffffffe7) >> 3];
|
||||
|
||||
*ptr = *ptr ^ 1 << (i & 0x1f);
|
||||
|
||||
m_pBuffer =
|
||||
(MxU8*) (streamer->GetSubclass2().GetSize() * i * 0x400 + streamer->GetSubclass2().GetBuffer());
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
m_pBuffer = NULL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
m_pBuffer = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
m_pIntoBuffer = m_pBuffer;
|
||||
m_pIntoBuffer2 = m_pBuffer;
|
||||
|
||||
if (m_pBuffer != NULL) {
|
||||
m_mode = p_mode;
|
||||
m_bytesRemaining = p_bufferSize;
|
||||
m_writeOffset = p_bufferSize;
|
||||
result = SUCCESS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6780
|
||||
MxResult MxDSBuffer::SetBufferPointer(MxU32* p_buffer, MxU32 p_size)
|
||||
{
|
||||
m_pBuffer = (MxU8*) p_buffer;
|
||||
m_pIntoBuffer = (MxU8*) p_buffer;
|
||||
m_pIntoBuffer2 = (MxU8*) p_buffer;
|
||||
m_bytesRemaining = p_size;
|
||||
m_writeOffset = p_size;
|
||||
m_mode = MxDSBufferType_Preallocated;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c67b0
|
||||
MxResult MxDSBuffer::FUN_100c67b0(
|
||||
MxStreamController* p_controller,
|
||||
MxDSAction* p_action,
|
||||
MxDSStreamingAction** p_streamingAction
|
||||
)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
m_unk0x30 = (MxDSStreamingAction*) p_controller->GetUnk0x3c().Find(p_action, FALSE);
|
||||
if (m_unk0x30 == NULL)
|
||||
return FAILURE;
|
||||
|
||||
MxU8* data;
|
||||
while (data = (MxU8*) SkipToData()) {
|
||||
if (*p_streamingAction == NULL) {
|
||||
result = CreateObject(p_controller, (MxU32*) data, p_action, p_streamingAction);
|
||||
|
||||
if (result == FAILURE)
|
||||
return result;
|
||||
// TODO: Not a MxResult value?
|
||||
if (result == 1)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
MxDSBuffer* buffer = (*p_streamingAction)->GetUnknowna0();
|
||||
|
||||
if (buffer->CalcBytesRemaining(data) != SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (buffer->GetBytesRemaining() == 0) {
|
||||
buffer->SetUnk30(m_unk0x30);
|
||||
|
||||
result = buffer->CreateObject(p_controller, (MxU32*) buffer->GetBuffer(), p_action, p_streamingAction);
|
||||
if (result != SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (buffer->GetRefCount() != 0) {
|
||||
// Note: *p_streamingAction is always null in MxRamStreamProvider
|
||||
((MxDiskStreamController*) p_controller)->InsertToList74(buffer);
|
||||
(*p_streamingAction)->SetUnknowna0(NULL);
|
||||
}
|
||||
|
||||
((MxDiskStreamController*) p_controller)->FUN_100c7cb0(*p_streamingAction);
|
||||
*p_streamingAction = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c68a0
|
||||
MxResult MxDSBuffer::CreateObject(
|
||||
MxStreamController* p_controller,
|
||||
MxU32* p_data,
|
||||
MxDSAction* p_action,
|
||||
MxDSStreamingAction** p_streamingAction
|
||||
)
|
||||
{
|
||||
if (p_data == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
MxCore* header = ReadChunk(this, p_data, p_action->GetUnknown24());
|
||||
|
||||
if (header == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (*p_data == FOURCC('M', 'x', 'O', 'b'))
|
||||
return StartPresenterFromAction(p_controller, p_action, (MxDSAction*) header);
|
||||
else if (*p_data == FOURCC('M', 'x', 'C', 'h')) {
|
||||
MxStreamChunk* chunk = (MxStreamChunk*) header;
|
||||
if (!m_unk0x30->HasId((chunk)->GetObjectId())) {
|
||||
delete header;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return ParseChunk(p_controller, p_data, p_action, p_streamingAction, chunk);
|
||||
}
|
||||
|
||||
delete header;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6960
|
||||
MxResult MxDSBuffer::StartPresenterFromAction(
|
||||
MxStreamController* p_controller,
|
||||
MxDSAction* p_action1,
|
||||
MxDSAction* p_objectheader
|
||||
)
|
||||
{
|
||||
if (!m_unk0x30->GetInternalAction()) {
|
||||
p_objectheader->SetAtomId(p_action1->GetAtomId());
|
||||
p_objectheader->SetUnknown28(p_action1->GetUnknown28());
|
||||
p_objectheader->SetUnknown84(p_action1->GetUnknown84());
|
||||
p_objectheader->SetOrigin(p_action1->GetOrigin());
|
||||
p_objectheader->SetUnknown90(p_action1->GetUnknown90());
|
||||
p_objectheader->MergeFrom(*p_action1);
|
||||
|
||||
m_unk0x30->SetInternalAction(p_objectheader->Clone());
|
||||
|
||||
p_controller->InsertActionToList54(p_objectheader);
|
||||
|
||||
if (MxOmni::GetInstance()->CreatePresenter(p_controller, *p_objectheader) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
m_unk0x30->SetLoopCount(p_objectheader->GetLoopCount());
|
||||
m_unk0x30->SetFlags(p_objectheader->GetFlags());
|
||||
m_unk0x30->SetDuration(p_objectheader->GetDuration());
|
||||
|
||||
if (m_unk0x30->GetInternalAction() == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
else if (p_objectheader) {
|
||||
delete p_objectheader;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6a50
|
||||
MxResult MxDSBuffer::ParseChunk(
|
||||
MxStreamController* p_controller,
|
||||
MxU32* p_data,
|
||||
MxDSAction* p_action,
|
||||
MxDSStreamingAction** p_streamingAction,
|
||||
MxStreamChunk* p_header
|
||||
)
|
||||
{
|
||||
MxResult result = SUCCESS;
|
||||
|
||||
if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && m_unk0x30->GetUnknowna8() && p_header->GetTime() < 0) {
|
||||
delete p_header;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
p_header->SetTime(p_header->GetTime() + m_unk0x30->GetUnknowna8());
|
||||
|
||||
if (p_header->GetFlags() & MxDSChunk::Flag_Split) {
|
||||
MxU32 length = p_header->GetLength() + MxDSChunk::ReturnE() + 8;
|
||||
MxDSBuffer* buffer = new MxDSBuffer();
|
||||
|
||||
if (buffer && buffer->AllocateBuffer(length, MxDSBufferType_Allocate) == SUCCESS &&
|
||||
buffer->CalcBytesRemaining((MxU8*) p_data) == SUCCESS) {
|
||||
*p_streamingAction = new MxDSStreamingAction((MxDSStreamingAction&) *p_action);
|
||||
|
||||
if (*p_streamingAction) {
|
||||
MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer());
|
||||
*flags = p_header->GetFlags() & ~MxDSChunk::Flag_Split;
|
||||
|
||||
delete p_header;
|
||||
(*p_streamingAction)->SetUnknowna0(buffer);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
delete buffer;
|
||||
|
||||
delete p_header;
|
||||
return FAILURE;
|
||||
}
|
||||
else {
|
||||
if (p_header->GetFlags() & MxDSChunk::Flag_End) {
|
||||
if (m_unk0x30->HasId(p_header->GetObjectId())) {
|
||||
if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 &&
|
||||
(m_unk0x30->GetLoopCount() > 1 || m_unk0x30->GetDuration() == -1)) {
|
||||
|
||||
if (p_action->GetObjectId() == p_header->GetObjectId()) {
|
||||
MxU32 val = p_controller->GetProvider()->GetBufferForDWords()[m_unk0x30->GetObjectId()];
|
||||
|
||||
m_unk0x30->SetUnknown94(val);
|
||||
m_unk0x30->SetBufferOffset(m_writeOffset * (val / m_writeOffset));
|
||||
|
||||
MxNextActionDataStart* data =
|
||||
p_controller->FindNextActionDataStartFromStreamingAction(m_unk0x30);
|
||||
|
||||
if (data)
|
||||
data->SetData(m_unk0x30->GetBufferOffset());
|
||||
|
||||
m_unk0x30->FUN_100cd2d0();
|
||||
}
|
||||
|
||||
delete p_header;
|
||||
p_header = NULL;
|
||||
}
|
||||
else {
|
||||
if (p_action->GetObjectId() == p_header->GetObjectId() &&
|
||||
p_controller->VTable0x30(p_action) == SUCCESS) {
|
||||
p_controller->GetProvider()->VTable0x20(p_action);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_header) {
|
||||
if (p_header->SendChunk(p_controller->GetSubscriberList(), TRUE, p_action->GetUnknown24()) != SUCCESS) {
|
||||
delete p_header;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6d00
|
||||
MxCore* MxDSBuffer::ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags)
|
||||
{
|
||||
// This function reads a chunk. If it is an object, this function returns an MxDSObject. If it is a chunk,
|
||||
// returns a MxDSChunk.
|
||||
MxCore* result = NULL;
|
||||
MxU8* dataStart = (MxU8*) p_chunkData + 8;
|
||||
|
||||
switch (*p_chunkData) {
|
||||
case FOURCC('M', 'x', 'O', 'b'):
|
||||
result = DeserializeDSObjectDispatch(&dataStart, p_flags);
|
||||
break;
|
||||
case FOURCC('M', 'x', 'C', 'h'):
|
||||
result = new MxStreamChunk();
|
||||
if (result != NULL && ((MxStreamChunk*) result)->ReadChunk(p_buffer, (MxU8*) p_chunkData) != SUCCESS) {
|
||||
delete result;
|
||||
result = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6df0
|
||||
MxU8* MxDSBuffer::SkipToData()
|
||||
{
|
||||
MxU8* result = NULL;
|
||||
|
||||
if (m_pIntoBuffer != NULL) {
|
||||
do {
|
||||
MxU32* ptr = (MxU32*) m_pIntoBuffer;
|
||||
switch (*ptr) {
|
||||
case FOURCC('L', 'I', 'S', 'T'):
|
||||
case FOURCC('R', 'I', 'F', 'F'):
|
||||
m_pIntoBuffer = (MxU8*) (ptr + 3);
|
||||
break;
|
||||
case FOURCC('M', 'x', 'O', 'b'):
|
||||
case FOURCC('M', 'x', 'C', 'h'):
|
||||
result = m_pIntoBuffer;
|
||||
m_pIntoBuffer = (MxU8*) ((ptr[1] & 1) + ptr[1] + (MxU32) ptr);
|
||||
m_pIntoBuffer = (MxU8*) ((MxU32*) m_pIntoBuffer + 2);
|
||||
if (m_pBuffer + (m_writeOffset - 8) < m_pIntoBuffer) {
|
||||
m_pIntoBuffer2 = result;
|
||||
m_pIntoBuffer = NULL;
|
||||
return result;
|
||||
}
|
||||
goto done;
|
||||
case FOURCC('M', 'x', 'D', 'a'):
|
||||
case FOURCC('M', 'x', 'S', 't'):
|
||||
m_pIntoBuffer = (MxU8*) (ptr + 2);
|
||||
break;
|
||||
case FOURCC('M', 'x', 'H', 'd'):
|
||||
m_pIntoBuffer = (MxU8*) ((MxU32) ptr + ptr[1] + 8);
|
||||
break;
|
||||
default:
|
||||
m_pIntoBuffer = NULL;
|
||||
m_pIntoBuffer2 = NULL;
|
||||
return NULL;
|
||||
}
|
||||
} while (m_pIntoBuffer <= m_pBuffer + (m_writeOffset - 8));
|
||||
}
|
||||
done:
|
||||
m_pIntoBuffer2 = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6ec0
|
||||
MxU8 MxDSBuffer::ReleaseRef(MxDSChunk*)
|
||||
{
|
||||
if (m_refcount != 0) {
|
||||
m_refcount--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6ee0
|
||||
void MxDSBuffer::AddRef(MxDSChunk* p_chunk)
|
||||
{
|
||||
if (p_chunk) {
|
||||
m_refcount++;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6ef0
|
||||
MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
if (m_mode == MxDSBufferType_Allocate && m_bytesRemaining != 0) {
|
||||
MxU32 bytesRead;
|
||||
MxU8* ptr;
|
||||
|
||||
if (m_writeOffset == m_bytesRemaining) {
|
||||
bytesRead = *(MxU32*) (p_data + 4) + 8;
|
||||
ptr = p_data;
|
||||
}
|
||||
else {
|
||||
ptr = &p_data[MxStreamChunk::ReturnE() + 8];
|
||||
bytesRead = (*(MxU32*) (p_data + 4)) - MxStreamChunk::ReturnE();
|
||||
}
|
||||
|
||||
if (bytesRead <= m_bytesRemaining) {
|
||||
memcpy(m_pBuffer + m_writeOffset - m_bytesRemaining, ptr, bytesRead);
|
||||
|
||||
if (m_writeOffset == m_bytesRemaining)
|
||||
*(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoLength(m_pBuffer) + MxStreamChunk::ReturnE();
|
||||
|
||||
m_bytesRemaining -= bytesRead;
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6f80
|
||||
void MxDSBuffer::FUN_100c6f80(MxU32 p_writeOffset)
|
||||
{
|
||||
if (p_writeOffset < m_writeOffset) {
|
||||
m_pIntoBuffer2 = m_pBuffer + p_writeOffset;
|
||||
m_pIntoBuffer = m_pBuffer + p_writeOffset;
|
||||
}
|
||||
}
|
||||
26
LEGO1/omni/src/stream/mxdschunk.cpp
Normal file
26
LEGO1/omni/src/stream/mxdschunk.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "mxdschunk.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSChunk, 0x1c);
|
||||
|
||||
// FUNCTION: LEGO1 0x100be050
|
||||
MxDSChunk::MxDSChunk()
|
||||
{
|
||||
m_flags = 0;
|
||||
m_data = NULL;
|
||||
m_objectId = -1;
|
||||
m_time = 0;
|
||||
m_length = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be170
|
||||
MxDSChunk::~MxDSChunk()
|
||||
{
|
||||
if (m_flags & Flag_Bit1)
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be1e0
|
||||
MxU32 MxDSChunk::ReturnE()
|
||||
{
|
||||
return 0xe;
|
||||
}
|
||||
124
LEGO1/omni/src/stream/mxdsfile.cpp
Normal file
124
LEGO1/omni/src/stream/mxdsfile.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "mxdsfile.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define SI_MAJOR_VERSION 2
|
||||
#define SI_MINOR_VERSION 2
|
||||
|
||||
// FUNCTION: LEGO1 0x100bfed0
|
||||
MxDSFile::~MxDSFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc4b0
|
||||
MxDSFile::MxDSFile(const char* p_filename, MxULong p_skipReadingChunks)
|
||||
{
|
||||
m_filename = p_filename;
|
||||
m_skipReadingChunks = p_skipReadingChunks;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc590
|
||||
MxLong MxDSFile::Open(MxULong p_uStyle)
|
||||
{
|
||||
MXIOINFO& io = m_io;
|
||||
MxLong longResult = 1;
|
||||
memset(&io, 0, sizeof(MXIOINFO));
|
||||
|
||||
if (io.Open(m_filename.GetData(), p_uStyle) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
io.SetBuffer(NULL, 0, 0);
|
||||
m_position = 0;
|
||||
|
||||
if (m_skipReadingChunks == 0) {
|
||||
longResult = ReadChunks();
|
||||
}
|
||||
|
||||
if (longResult != 0) {
|
||||
Close(); // vtable + 0x18
|
||||
}
|
||||
else {
|
||||
Seek(0, 0); // vtable + 0x24
|
||||
}
|
||||
|
||||
return longResult;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc620
|
||||
MxLong MxDSFile::ReadChunks()
|
||||
{
|
||||
_MMCKINFO topChunk;
|
||||
_MMCKINFO childChunk;
|
||||
char tempBuffer[80];
|
||||
|
||||
topChunk.fccType = FOURCC('O', 'M', 'N', 'I');
|
||||
if (m_io.Descend(&topChunk, NULL, MMIO_FINDRIFF) != 0) {
|
||||
return -1;
|
||||
}
|
||||
childChunk.ckid = FOURCC('M', 'x', 'H', 'd');
|
||||
if (m_io.Descend(&childChunk, &topChunk, 0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_io.Read(&m_header, 0xc);
|
||||
if ((m_header.m_majorVersion == SI_MAJOR_VERSION) && (m_header.m_minorVersion == SI_MINOR_VERSION)) {
|
||||
childChunk.ckid = FOURCC('M', 'x', 'O', 'f');
|
||||
if (m_io.Descend(&childChunk, &topChunk, 0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
MxULong* pLengthInDWords = &m_lengthInDWords;
|
||||
m_io.Read(pLengthInDWords, 4);
|
||||
m_pBuffer = new MxU32[*pLengthInDWords];
|
||||
m_io.Read(m_pBuffer, *pLengthInDWords * 4);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
sprintf(tempBuffer, "Wrong SI file version. %d.%d expected.", SI_MAJOR_VERSION, SI_MINOR_VERSION);
|
||||
MessageBoxA(NULL, tempBuffer, NULL, MB_ICONERROR);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc740
|
||||
MxLong MxDSFile::Close()
|
||||
{
|
||||
m_io.Close(0);
|
||||
m_position = -1;
|
||||
memset(&m_header, 0, sizeof(m_header));
|
||||
if (m_lengthInDWords != 0) {
|
||||
m_lengthInDWords = 0;
|
||||
delete[] m_pBuffer;
|
||||
m_pBuffer = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc780
|
||||
MxResult MxDSFile::Read(unsigned char* p_buf, MxULong p_nbytes)
|
||||
{
|
||||
if (m_io.Read(p_buf, p_nbytes) != p_nbytes)
|
||||
return FAILURE;
|
||||
|
||||
m_position += p_nbytes;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc7b0
|
||||
MxLong MxDSFile::Seek(MxLong p_lOffset, MxS32 p_iOrigin)
|
||||
{
|
||||
return (m_position = m_io.Seek(p_lOffset, p_iOrigin)) == -1 ? -1 : 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc7e0
|
||||
MxULong MxDSFile::GetBufferSize()
|
||||
{
|
||||
return m_header.m_bufferSize;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc7f0
|
||||
MxULong MxDSFile::GetStreamBuffersNum()
|
||||
{
|
||||
return m_header.m_streamBuffersNum;
|
||||
}
|
||||
23
LEGO1/omni/src/stream/mxdssource.cpp
Normal file
23
LEGO1/omni/src/stream/mxdssource.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "mxdssource.h"
|
||||
|
||||
#include "mxdsbuffer.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSSource, 0x14)
|
||||
|
||||
// FUNCTION: LEGO1 0x100bffd0
|
||||
MxResult MxDSSource::ReadToBuffer(MxDSBuffer* p_buffer)
|
||||
{
|
||||
return Read(p_buffer->GetBuffer(), p_buffer->GetWriteOffset());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bfff0
|
||||
MxLong MxDSSource::GetLengthInDWords()
|
||||
{
|
||||
return m_lengthInDWords;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0000
|
||||
MxU32* MxDSSource::GetBuffer()
|
||||
{
|
||||
return m_pBuffer;
|
||||
}
|
||||
125
LEGO1/omni/src/stream/mxdssubscriber.cpp
Normal file
125
LEGO1/omni/src/stream/mxdssubscriber.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "mxdssubscriber.h"
|
||||
|
||||
#include "mxstreamcontroller.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDSSubscriber, 0x4c);
|
||||
|
||||
// FUNCTION: LEGO1 0x100b7bb0
|
||||
MxDSSubscriber::MxDSSubscriber()
|
||||
{
|
||||
m_unk0x48 = -1;
|
||||
m_objectId = -1;
|
||||
m_unk0x20 = NULL;
|
||||
m_unk0x3c = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b7e00
|
||||
MxDSSubscriber::~MxDSSubscriber()
|
||||
{
|
||||
if (m_controller)
|
||||
m_controller->RemoveSubscriber(this);
|
||||
|
||||
DeleteChunks();
|
||||
|
||||
if (m_unk0x20)
|
||||
delete m_unk0x20;
|
||||
m_unk0x20 = NULL;
|
||||
|
||||
if (m_unk0x3c)
|
||||
delete m_unk0x3c;
|
||||
m_unk0x3c = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b7ed0
|
||||
MxResult MxDSSubscriber::Create(MxStreamController* p_controller, MxU32 p_objectId, MxS16 p_unk0x48)
|
||||
{
|
||||
m_objectId = p_objectId;
|
||||
m_unk0x48 = p_unk0x48;
|
||||
|
||||
if (!p_controller)
|
||||
return FAILURE;
|
||||
m_controller = p_controller;
|
||||
|
||||
m_unk0x20 = new MxStreamChunkListCursor(&m_unk0x08);
|
||||
if (!m_unk0x20)
|
||||
return FAILURE;
|
||||
|
||||
m_unk0x3c = new MxStreamChunkListCursor(&m_unk0x24);
|
||||
if (!m_unk0x3c)
|
||||
return FAILURE;
|
||||
|
||||
m_controller->AddSubscriber(this);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8030
|
||||
void MxDSSubscriber::DeleteChunks()
|
||||
{
|
||||
if (m_controller) {
|
||||
MxStreamChunk* chunk = NULL;
|
||||
|
||||
while (m_unk0x20->First(chunk)) {
|
||||
m_unk0x20->Detach();
|
||||
delete chunk;
|
||||
}
|
||||
|
||||
while (m_unk0x3c->First(chunk)) {
|
||||
m_unk0x3c->Detach();
|
||||
delete chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8150
|
||||
MxResult MxDSSubscriber::AddChunk(MxStreamChunk* p_chunk, MxBool p_append)
|
||||
{
|
||||
if (m_unk0x20) {
|
||||
if (p_append)
|
||||
m_unk0x08.Append(p_chunk);
|
||||
else
|
||||
m_unk0x08.Prepend(p_chunk);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8250
|
||||
MxStreamChunk* MxDSSubscriber::FUN_100b8250()
|
||||
{
|
||||
MxStreamChunk* chunk = NULL;
|
||||
|
||||
if (m_unk0x20)
|
||||
m_unk0x20->First(chunk);
|
||||
|
||||
if (chunk) {
|
||||
m_unk0x20->Detach();
|
||||
m_unk0x24.Append(chunk);
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8360
|
||||
MxStreamChunk* MxDSSubscriber::FUN_100b8360()
|
||||
{
|
||||
MxStreamChunk* chunk = NULL;
|
||||
|
||||
if (m_unk0x20)
|
||||
m_unk0x20->First(chunk);
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8390
|
||||
void MxDSSubscriber::FUN_100b8390(MxStreamChunk* p_chunk)
|
||||
{
|
||||
if (p_chunk) {
|
||||
if (m_unk0x3c->Find(p_chunk)) {
|
||||
m_unk0x3c->Detach();
|
||||
if (p_chunk)
|
||||
delete p_chunk;
|
||||
}
|
||||
else if (p_chunk->GetFlags() & MxDSChunk::Flag_Bit1 && p_chunk)
|
||||
delete p_chunk;
|
||||
}
|
||||
}
|
||||
460
LEGO1/omni/src/stream/mxioinfo.cpp
Normal file
460
LEGO1/omni/src/stream/mxioinfo.cpp
Normal file
@@ -0,0 +1,460 @@
|
||||
#include "mxioinfo.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
// This class should be 72 bytes in size, same as the MMIOINFO struct.
|
||||
// The current implementation has MMIOINFO as the only member of the class,
|
||||
// but this assert will enforce the size if we decide to change that.
|
||||
DECOMP_SIZE_ASSERT(MXIOINFO, sizeof(MMIOINFO));
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc800
|
||||
MXIOINFO::MXIOINFO()
|
||||
{
|
||||
memset(&m_info, 0, sizeof(m_info));
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc820
|
||||
MXIOINFO::~MXIOINFO()
|
||||
{
|
||||
Close(0);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc830
|
||||
MxU16 MXIOINFO::Open(const char* p_filename, MxULong p_flags)
|
||||
{
|
||||
OFSTRUCT unused;
|
||||
MxU16 result = 0;
|
||||
|
||||
m_info.lBufOffset = 0;
|
||||
m_info.lDiskOffset = 0;
|
||||
|
||||
// DECOMP: Cast of p_flags to u16 forces the `movzx` instruction
|
||||
m_info.hmmio = (HMMIO) OpenFile(p_filename, &unused, (MxU16) p_flags);
|
||||
|
||||
if ((HFILE) m_info.hmmio != HFILE_ERROR) {
|
||||
m_info.dwFlags = p_flags;
|
||||
if (p_flags & MMIO_ALLOCBUF) {
|
||||
|
||||
// Default buffer length of 8k if none specified
|
||||
MxLong len = m_info.cchBuffer ? m_info.cchBuffer : 8192;
|
||||
HPSTR buf = new char[len];
|
||||
|
||||
if (!buf) {
|
||||
result = MMIOERR_OUTOFMEMORY;
|
||||
m_info.cchBuffer = 0;
|
||||
m_info.dwFlags &= ~MMIO_ALLOCBUF;
|
||||
m_info.pchBuffer = 0;
|
||||
}
|
||||
else {
|
||||
m_info.pchBuffer = buf;
|
||||
m_info.cchBuffer = len;
|
||||
}
|
||||
|
||||
m_info.pchEndRead = m_info.pchBuffer;
|
||||
m_info.pchNext = m_info.pchBuffer;
|
||||
m_info.pchEndWrite = m_info.pchBuffer + m_info.cchBuffer;
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = MMIOERR_CANNOTOPEN;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc8e0
|
||||
MxU16 MXIOINFO::Close(MxLong p_unused)
|
||||
{
|
||||
MxU16 result = 0;
|
||||
|
||||
if (m_info.hmmio) {
|
||||
result = Flush(0);
|
||||
_lclose((HFILE) m_info.hmmio);
|
||||
m_info.hmmio = 0;
|
||||
|
||||
if (m_info.dwFlags & MMIO_ALLOCBUF)
|
||||
delete[] m_info.pchBuffer;
|
||||
|
||||
m_info.pchEndWrite = 0;
|
||||
m_info.pchEndRead = 0;
|
||||
m_info.pchBuffer = 0;
|
||||
m_info.dwFlags = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cc930
|
||||
MxLong MXIOINFO::Read(void* p_buf, MxLong p_len)
|
||||
{
|
||||
MxLong bytesRead = 0;
|
||||
|
||||
if (m_info.pchBuffer) {
|
||||
|
||||
MxLong bytesLeft = m_info.pchEndRead - m_info.pchNext;
|
||||
while (p_len > 0) {
|
||||
|
||||
if (bytesLeft > 0) {
|
||||
if (p_len < bytesLeft)
|
||||
bytesLeft = p_len;
|
||||
|
||||
memcpy(p_buf, m_info.pchNext, bytesLeft);
|
||||
p_len -= bytesLeft;
|
||||
|
||||
m_info.pchNext += bytesLeft;
|
||||
bytesRead += bytesLeft;
|
||||
}
|
||||
|
||||
if (p_len <= 0 || Advance(0))
|
||||
break;
|
||||
|
||||
bytesLeft = m_info.pchEndRead - m_info.pchNext;
|
||||
if (bytesLeft <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (m_info.hmmio && p_len > 0) {
|
||||
bytesRead = _hread((HFILE) m_info.hmmio, p_buf, p_len);
|
||||
|
||||
if (bytesRead == -1) {
|
||||
bytesRead = 0;
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
m_info.lDiskOffset += bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cca00
|
||||
MxLong MXIOINFO::Seek(MxLong p_offset, MxLong p_origin)
|
||||
{
|
||||
MxLong result = -1;
|
||||
|
||||
// If buffered I/O
|
||||
if (m_info.pchBuffer) {
|
||||
if (p_origin == SEEK_CUR) {
|
||||
if (!p_offset) {
|
||||
// don't seek at all and just return where we are.
|
||||
return m_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
|
||||
}
|
||||
else {
|
||||
// With SEEK_CUR, p_offset is a relative offset.
|
||||
// Get the absolute position instead and use SEEK_SET.
|
||||
p_offset += m_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
|
||||
p_origin = SEEK_SET;
|
||||
}
|
||||
}
|
||||
else if (p_origin == SEEK_END) {
|
||||
// not possible with buffered I/O
|
||||
return -1;
|
||||
}
|
||||
|
||||
// else p_origin == SEEK_SET.
|
||||
|
||||
// is p_offset between the start and end of the buffer?
|
||||
// i.e. can we do the seek without reading more from disk?
|
||||
if (p_offset >= m_info.lBufOffset && p_offset < m_info.lBufOffset + m_info.cchBuffer) {
|
||||
m_info.pchNext = m_info.pchBuffer + (p_offset - m_info.lBufOffset);
|
||||
result = p_offset;
|
||||
}
|
||||
else {
|
||||
// we have to read another chunk from disk.
|
||||
if (m_info.hmmio && !Flush(0)) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, p_offset, p_origin);
|
||||
|
||||
if (m_info.lDiskOffset == -1) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
|
||||
// align offset to buffer size
|
||||
MxLong newOffset = p_offset - (p_offset % m_info.cchBuffer);
|
||||
m_info.lBufOffset = newOffset;
|
||||
|
||||
// do we need to seek again?
|
||||
// (i.e. are we already aligned to buffer size?)
|
||||
if (p_offset != newOffset) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, newOffset, SEEK_SET);
|
||||
|
||||
if (m_info.lDiskOffset == -1) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_info.lBufOffset == m_info.lDiskOffset) {
|
||||
// is the file open for writing only?
|
||||
if ((m_info.dwFlags & MMIO_RWMODE) && ((m_info.dwFlags & MMIO_RWMODE) != MMIO_READWRITE)) {
|
||||
|
||||
m_info.pchNext = m_info.pchBuffer - m_info.lBufOffset + p_offset;
|
||||
|
||||
result = p_offset;
|
||||
}
|
||||
else {
|
||||
// We can read from the file. Fill the buffer.
|
||||
MxLong bytesRead = _hread((HFILE) m_info.hmmio, m_info.pchBuffer, m_info.cchBuffer);
|
||||
|
||||
if (bytesRead == -1) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
m_info.lDiskOffset += bytesRead;
|
||||
m_info.pchNext = p_offset - m_info.lBufOffset + m_info.pchBuffer;
|
||||
m_info.pchEndRead = m_info.pchBuffer + bytesRead;
|
||||
|
||||
if (m_info.pchNext < m_info.pchEndRead) {
|
||||
result = p_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No buffer so just seek the file directly (if we have a valid handle)
|
||||
if (m_info.hmmio) {
|
||||
// i.e. if we just want to get the current file position
|
||||
if (p_origin == SEEK_CUR && p_offset == 0) {
|
||||
return m_info.lDiskOffset;
|
||||
}
|
||||
else {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, p_offset, p_origin);
|
||||
|
||||
result = m_info.lDiskOffset;
|
||||
|
||||
if (result == -1) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ccbc0
|
||||
MxU16 MXIOINFO::SetBuffer(char* p_buf, MxLong p_len, MxLong p_unused)
|
||||
{
|
||||
MxU16 result = Flush(0);
|
||||
|
||||
if (m_info.dwFlags & MMIO_ALLOCBUF) {
|
||||
m_info.dwFlags &= ~MMIO_ALLOCBUF;
|
||||
delete[] m_info.pchBuffer;
|
||||
}
|
||||
|
||||
m_info.pchBuffer = p_buf;
|
||||
m_info.cchBuffer = p_len;
|
||||
m_info.pchEndWrite = m_info.pchBuffer + m_info.cchBuffer;
|
||||
m_info.pchEndRead = m_info.pchBuffer;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ccc10
|
||||
MxU16 MXIOINFO::Flush(MxU16 p_unused)
|
||||
{
|
||||
MxU16 result = 0;
|
||||
|
||||
// if buffer is dirty
|
||||
if (m_info.dwFlags & MMIO_DIRTY) {
|
||||
// if we have allocated an IO buffer
|
||||
if (m_info.pchBuffer) {
|
||||
// if we have a file open for writing
|
||||
if (m_info.hmmio && (m_info.dwFlags & MMIO_RWMODE)) {
|
||||
// DECOMP: pulling this value out into a variable forces it into EBX
|
||||
MxLong cchBuffer = m_info.cchBuffer;
|
||||
if (cchBuffer > 0) {
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, m_info.lBufOffset, SEEK_SET);
|
||||
}
|
||||
|
||||
// Was the previous seek (if required) successful?
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
result = MMIOERR_CANNOTSEEK;
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
MxLong bytesWritten = _hwrite((HFILE) m_info.hmmio, m_info.pchBuffer, cchBuffer);
|
||||
|
||||
if (bytesWritten != -1 && bytesWritten == cchBuffer) {
|
||||
m_info.lDiskOffset += bytesWritten;
|
||||
m_info.pchNext = m_info.pchBuffer;
|
||||
m_info.dwFlags &= ~MMIO_DIRTY;
|
||||
}
|
||||
else {
|
||||
result = MMIOERR_CANNOTWRITE;
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = MMIOERR_CANNOTWRITE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = MMIOERR_UNBUFFERED;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ccd00
|
||||
MxU16 MXIOINFO::Advance(MxU16 p_option)
|
||||
{
|
||||
MxU16 result = 0;
|
||||
MxULong rwmode = m_info.dwFlags & MMIO_RWMODE;
|
||||
|
||||
if (m_info.pchBuffer) {
|
||||
MxLong cch = m_info.cchBuffer;
|
||||
|
||||
// If we can and should write to the file,
|
||||
// if we are being asked to write to the file,
|
||||
// and if there is a buffer *to* write:
|
||||
if ((rwmode == MMIO_WRITE || rwmode == MMIO_READWRITE) && (m_info.dwFlags & MMIO_DIRTY) &&
|
||||
((p_option & MMIO_WRITE) || (rwmode == MMIO_READWRITE)) && cch > 0) {
|
||||
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, m_info.lBufOffset, SEEK_SET);
|
||||
}
|
||||
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
result = MMIOERR_CANNOTSEEK;
|
||||
}
|
||||
else {
|
||||
MxLong bytesWritten = _hwrite((HFILE) m_info.hmmio, m_info.pchBuffer, cch);
|
||||
|
||||
if (bytesWritten != -1 && bytesWritten == cch) {
|
||||
m_info.lDiskOffset += bytesWritten;
|
||||
m_info.pchNext = m_info.pchBuffer;
|
||||
m_info.pchEndRead = m_info.pchBuffer;
|
||||
m_info.dwFlags &= ~MMIO_DIRTY;
|
||||
}
|
||||
else {
|
||||
result = MMIOERR_CANNOTWRITE;
|
||||
}
|
||||
}
|
||||
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
m_info.lBufOffset += cch;
|
||||
if ((!rwmode || rwmode == MMIO_READWRITE) && cch > 0) {
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, m_info.lBufOffset, SEEK_SET);
|
||||
}
|
||||
|
||||
// if previous seek failed
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
result = MMIOERR_CANNOTSEEK;
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
MxLong bytesRead = _hread((HFILE) m_info.hmmio, m_info.pchBuffer, cch);
|
||||
|
||||
if (bytesRead == -1) {
|
||||
result = MMIOERR_CANNOTREAD;
|
||||
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
m_info.lDiskOffset += bytesRead;
|
||||
m_info.pchNext = m_info.pchBuffer;
|
||||
m_info.pchEndRead = m_info.pchBuffer + bytesRead;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = MMIOERR_UNBUFFERED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100cce60
|
||||
MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU16 p_descend)
|
||||
{
|
||||
MxU16 result = 0;
|
||||
|
||||
if (!p_chunkInfo)
|
||||
return MMIOERR_BASE; // ?
|
||||
|
||||
if (!p_descend) {
|
||||
p_chunkInfo->dwFlags = 0;
|
||||
if (Read(p_chunkInfo, 8) != 8) {
|
||||
result = MMIOERR_CANNOTREAD;
|
||||
}
|
||||
else {
|
||||
if (m_info.pchBuffer) {
|
||||
p_chunkInfo->dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
|
||||
}
|
||||
else {
|
||||
p_chunkInfo->dwDataOffset = m_info.lDiskOffset;
|
||||
}
|
||||
|
||||
if ((p_chunkInfo->ckid == FOURCC_RIFF || p_chunkInfo->ckid == FOURCC_LIST) &&
|
||||
Read(&p_chunkInfo->fccType, 4) != 4) {
|
||||
result = MMIOERR_CANNOTREAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
MxULong ofs = MAXLONG;
|
||||
|
||||
if (p_parentInfo)
|
||||
ofs = p_parentInfo->cksize + p_parentInfo->dwDataOffset;
|
||||
|
||||
BOOL running = TRUE;
|
||||
BOOL readOk = FALSE;
|
||||
MMCKINFO tmp;
|
||||
tmp.dwFlags = 0;
|
||||
|
||||
while (running) {
|
||||
if (Read(&tmp, 8) != 8) {
|
||||
// If the first read fails, report read error. Else EOF.
|
||||
result = readOk ? MMIOERR_CHUNKNOTFOUND : MMIOERR_CANNOTREAD;
|
||||
running = FALSE;
|
||||
}
|
||||
else {
|
||||
readOk = TRUE;
|
||||
if (m_info.pchBuffer) {
|
||||
tmp.dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
|
||||
}
|
||||
else {
|
||||
tmp.dwDataOffset = m_info.lDiskOffset;
|
||||
}
|
||||
|
||||
if (ofs < tmp.dwDataOffset) {
|
||||
result = MMIOERR_CHUNKNOTFOUND;
|
||||
running = FALSE;
|
||||
}
|
||||
else if ((p_descend == MMIO_FINDLIST && tmp.ckid == FOURCC_LIST) || (p_descend == MMIO_FINDRIFF && tmp.ckid == FOURCC_RIFF)) {
|
||||
if (Read(&tmp.fccType, 4) != 4) {
|
||||
result = MMIOERR_CANNOTREAD;
|
||||
running = FALSE;
|
||||
}
|
||||
else if (p_chunkInfo->fccType == tmp.fccType) {
|
||||
running = FALSE;
|
||||
}
|
||||
}
|
||||
else if (p_chunkInfo->ckid == tmp.ckid) {
|
||||
running = FALSE;
|
||||
}
|
||||
else if (Seek((tmp.cksize & 1) + tmp.cksize, SEEK_CUR) == -1) {
|
||||
result = MMIOERR_CANNOTSEEK;
|
||||
running = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!result)
|
||||
memcpy(p_chunkInfo, &tmp, sizeof(MMCKINFO));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
103
LEGO1/omni/src/stream/mxramstreamcontroller.cpp
Normal file
103
LEGO1/omni/src/stream/mxramstreamcontroller.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "mxramstreamcontroller.h"
|
||||
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdsstreamingaction.h"
|
||||
#include "mxramstreamprovider.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxRAMStreamController, 0x98);
|
||||
|
||||
undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6110
|
||||
MxResult MxRAMStreamController::Open(const char* p_filename)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
if (MxStreamController::Open(p_filename) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
m_provider = new MxRAMStreamProvider();
|
||||
if (((MxRAMStreamProvider*) m_provider) != NULL) {
|
||||
if (m_provider->SetResourceToGet(this) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
ReadData(
|
||||
((MxRAMStreamProvider*) m_provider)->GetBufferOfFileSize(),
|
||||
((MxRAMStreamProvider*) m_provider)->GetFileSize()
|
||||
);
|
||||
m_buffer.SetBufferPointer(
|
||||
((MxRAMStreamProvider*) m_provider)->GetBufferOfFileSize(),
|
||||
((MxRAMStreamProvider*) m_provider)->GetFileSize()
|
||||
);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6210
|
||||
MxResult MxRAMStreamController::VTable0x20(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
MxS32 unk0x24 = 0;
|
||||
MxResult result = FAILURE;
|
||||
|
||||
if (p_action->GetUnknown24() == -1) {
|
||||
p_action->SetUnknown24(-3);
|
||||
MxDSAction* action = m_unk0x54.Find(p_action, FALSE);
|
||||
if (action != NULL) {
|
||||
unk0x24 = action->GetUnknown24() + 1;
|
||||
}
|
||||
p_action->SetUnknown24(unk0x24);
|
||||
}
|
||||
else {
|
||||
if (m_unk0x54.Find(p_action, FALSE)) {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (MxStreamController::VTable0x20(p_action) == SUCCESS) {
|
||||
MxDSStreamingAction* action = (MxDSStreamingAction*) m_unk0x3c.Find(p_action, FALSE);
|
||||
MxDSStreamingAction streamingaction(*action);
|
||||
result = DeserializeObject(streamingaction);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6320
|
||||
MxResult MxRAMStreamController::VTable0x24(MxDSAction* p_action)
|
||||
{
|
||||
MxDSAction action;
|
||||
do {
|
||||
if (m_action0x60 != NULL) {
|
||||
delete m_action0x60;
|
||||
m_action0x60 = NULL;
|
||||
}
|
||||
action = *p_action;
|
||||
MxStreamController::VTable0x24(&action);
|
||||
} while (m_action0x60 != NULL);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c63c0
|
||||
MxResult MxRAMStreamController::DeserializeObject(MxDSStreamingAction& p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
MxResult result;
|
||||
MxDSStreamingAction* value = NULL;
|
||||
|
||||
do {
|
||||
m_buffer.FUN_100c6f80(p_action.GetUnknown94());
|
||||
// Probably not MxResult, see below
|
||||
result = m_buffer.FUN_100c67b0(this, &p_action, &value);
|
||||
} while (m_unk0x3c.Find(&p_action, FALSE) != NULL);
|
||||
|
||||
return result == SUCCESS ? SUCCESS : FAILURE;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100d0d80
|
||||
undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
98
LEGO1/omni/src/stream/mxramstreamprovider.cpp
Normal file
98
LEGO1/omni/src/stream/mxramstreamprovider.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "mxramstreamprovider.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxstreamcontroller.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxRAMStreamProvider, 0x24);
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0730
|
||||
MxRAMStreamProvider::MxRAMStreamProvider()
|
||||
{
|
||||
m_bufferSize = 0;
|
||||
m_fileSize = 0;
|
||||
m_pBufferOfFileSize = NULL;
|
||||
m_lengthInDWords = 0;
|
||||
m_bufferForDWords = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0930
|
||||
MxU32 MxRAMStreamProvider::GetFileSize()
|
||||
{
|
||||
return m_fileSize;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0940
|
||||
MxS32 MxRAMStreamProvider::GetStreamBuffersNum()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0950
|
||||
MxU32 MxRAMStreamProvider::GetLengthInDWords()
|
||||
{
|
||||
return m_lengthInDWords;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0960
|
||||
MxU32* MxRAMStreamProvider::GetBufferForDWords()
|
||||
{
|
||||
return m_bufferForDWords;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0a50
|
||||
MxRAMStreamProvider::~MxRAMStreamProvider()
|
||||
{
|
||||
m_bufferSize = 0;
|
||||
m_fileSize = 0;
|
||||
|
||||
free(m_pBufferOfFileSize);
|
||||
m_pBufferOfFileSize = NULL;
|
||||
|
||||
m_lengthInDWords = 0;
|
||||
|
||||
free(m_bufferForDWords);
|
||||
m_bufferForDWords = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0ae0
|
||||
MxResult MxRAMStreamProvider::SetResourceToGet(MxStreamController* p_resource)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
MxString path;
|
||||
m_pLookup = p_resource;
|
||||
|
||||
path = (MxString(MxOmni::GetHD()) + p_resource->GetAtom().GetInternal() + ".si");
|
||||
|
||||
m_pFile = new MxDSFile(path.GetData(), 0);
|
||||
if (m_pFile != NULL) {
|
||||
if (m_pFile->Open(0) != 0) {
|
||||
path = MxString(MxOmni::GetCD()) + p_resource->GetAtom().GetInternal() + ".si";
|
||||
m_pFile->SetFileName(path.GetData());
|
||||
|
||||
if (m_pFile->Open(0) != 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
m_fileSize = m_pFile->CalcFileSize();
|
||||
if (m_fileSize != 0) {
|
||||
m_bufferSize = m_pFile->GetBufferSize();
|
||||
m_pBufferOfFileSize = (MxU32*) new MxU8[m_fileSize];
|
||||
if (m_pBufferOfFileSize != NULL &&
|
||||
m_pFile->Read((unsigned char*) m_pBufferOfFileSize, m_fileSize) == SUCCESS) {
|
||||
m_lengthInDWords = m_pFile->GetLengthInDWords();
|
||||
m_bufferForDWords = new MxU32[m_lengthInDWords];
|
||||
|
||||
if (m_bufferForDWords != NULL) {
|
||||
memcpy(m_bufferForDWords, m_pFile->GetBuffer(), m_lengthInDWords * sizeof(MxU32));
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
delete m_pFile;
|
||||
m_pFile = NULL;
|
||||
return result;
|
||||
}
|
||||
99
LEGO1/omni/src/stream/mxstreamchunk.cpp
Normal file
99
LEGO1/omni/src/stream/mxstreamchunk.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "mxstreamchunk.h"
|
||||
|
||||
#include "legoutil.h"
|
||||
#include "mxdsbuffer.h"
|
||||
#include "mxstreamlist.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2fe0
|
||||
MxStreamChunk::~MxStreamChunk()
|
||||
{
|
||||
if (m_buffer) {
|
||||
m_buffer->ReleaseRef(this);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3050
|
||||
MxResult MxStreamChunk::ReadChunk(MxDSBuffer* p_buffer, MxU8* p_chunkData)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
if (p_chunkData != NULL && *(MxU32*) p_chunkData == FOURCC('M', 'x', 'C', 'h')) {
|
||||
if (ReadChunkHeader(p_chunkData + 8)) {
|
||||
if (p_buffer) {
|
||||
SetBuffer(p_buffer);
|
||||
p_buffer->AddRef(this);
|
||||
}
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c30a0
|
||||
MxU32 MxStreamChunk::ReadChunkHeader(MxU8* p_chunkData)
|
||||
{
|
||||
MxU32 headersize = 0;
|
||||
if (p_chunkData) {
|
||||
MxU8* chunkData = p_chunkData;
|
||||
// Note: the alpha debug version uses memcpy calls here,
|
||||
// but the code generation is the same.
|
||||
GetScalar(&p_chunkData, m_flags);
|
||||
GetScalar(&p_chunkData, m_objectId);
|
||||
GetScalar(&p_chunkData, m_time);
|
||||
GetScalar(&p_chunkData, m_length);
|
||||
m_data = p_chunkData;
|
||||
headersize = p_chunkData - chunkData;
|
||||
}
|
||||
|
||||
return headersize;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c30e0
|
||||
MxResult MxStreamChunk::SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_append, MxS16 p_obj24val)
|
||||
{
|
||||
for (MxStreamListMxDSSubscriber::iterator it = p_subscriberList.begin(); it != p_subscriberList.end(); it++) {
|
||||
if ((*it)->GetObjectId() == m_objectId && (*it)->GetUnknown48() == p_obj24val) {
|
||||
if (m_flags & MxDSChunk::Flag_End && m_buffer) {
|
||||
m_buffer->ReleaseRef(this);
|
||||
m_buffer = NULL;
|
||||
}
|
||||
|
||||
(*it)->AddChunk(this, p_append);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3170
|
||||
void MxStreamChunk::SetBuffer(MxDSBuffer* p_buffer)
|
||||
{
|
||||
m_buffer = p_buffer;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3180
|
||||
MxU16* MxStreamChunk::IntoFlags(MxU8* p_buffer)
|
||||
{
|
||||
return (MxU16*) (p_buffer + 0x08);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3190
|
||||
MxU32* MxStreamChunk::IntoObjectId(MxU8* p_buffer)
|
||||
{
|
||||
return (MxU32*) (p_buffer + 0x0a);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c31a0
|
||||
MxLong* MxStreamChunk::IntoTime(MxU8* p_buffer)
|
||||
{
|
||||
return (MxLong*) (p_buffer + 0x0e);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c31b0
|
||||
MxU32* MxStreamChunk::IntoLength(MxU8* p_buffer)
|
||||
{
|
||||
return (MxU32*) (p_buffer + 0x12);
|
||||
}
|
||||
318
LEGO1/omni/src/stream/mxstreamcontroller.cpp
Normal file
318
LEGO1/omni/src/stream/mxstreamcontroller.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
#include "mxstreamcontroller.h"
|
||||
|
||||
#include "legoomni.h"
|
||||
#include "legoutil.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdsmultiaction.h"
|
||||
#include "mxdsstreamingaction.h"
|
||||
#include "mxnextactiondatastart.h"
|
||||
#include "mxstl/stlcompat.h"
|
||||
#include "mxstreamchunk.h"
|
||||
#include "mxtimer.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxStreamController, 0x64)
|
||||
DECOMP_SIZE_ASSERT(MxNextActionDataStart, 0x14)
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9400
|
||||
MxResult MxStreamController::VTable0x18(undefined4, undefined4)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9410
|
||||
MxResult MxStreamController::VTable0x1c(undefined4, undefined4)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9420
|
||||
MxDSStreamingAction* MxStreamController::VTable0x28()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c0b90
|
||||
MxStreamController::MxStreamController()
|
||||
{
|
||||
m_provider = NULL;
|
||||
m_unk0x2c = NULL;
|
||||
m_action0x60 = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1290
|
||||
MxStreamController::~MxStreamController()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxDSSubscriber* subscriber;
|
||||
while (m_subscriberList.PopFront(subscriber))
|
||||
delete subscriber;
|
||||
|
||||
MxDSAction* action;
|
||||
while (m_unk0x3c.PopFront(action))
|
||||
delete action;
|
||||
|
||||
if (m_provider) {
|
||||
MxStreamProvider* provider = m_provider;
|
||||
m_provider = NULL;
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxDSAction action;
|
||||
provider->VTable0x20(&action);
|
||||
}
|
||||
#else
|
||||
provider->VTable0x20(&MxDSAction());
|
||||
#endif
|
||||
delete provider;
|
||||
}
|
||||
|
||||
if (m_unk0x2c) {
|
||||
delete m_unk0x2c;
|
||||
m_unk0x2c = NULL;
|
||||
}
|
||||
|
||||
while (m_unk0x54.PopFront(action))
|
||||
delete action;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1520
|
||||
MxResult MxStreamController::Open(const char* p_filename)
|
||||
{
|
||||
char sourceName[256];
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MakeSourceName(sourceName, p_filename);
|
||||
this->m_atom = MxAtomId(sourceName, LookupMode_LowerCase2);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c15d0
|
||||
void MxStreamController::AddSubscriber(MxDSSubscriber* p_subscriber)
|
||||
{
|
||||
m_subscriberList.push_back(p_subscriber);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1620
|
||||
void MxStreamController::RemoveSubscriber(MxDSSubscriber* p_subscriber)
|
||||
{
|
||||
m_subscriberList.remove(p_subscriber);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1690
|
||||
MxResult MxStreamController::VTable0x20(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxResult result;
|
||||
MxU32 offset = 0;
|
||||
|
||||
MxS32 objectId = p_action->GetObjectId();
|
||||
MxStreamProvider* provider = m_provider;
|
||||
|
||||
if ((MxS32) provider->GetLengthInDWords() > objectId)
|
||||
offset = provider->GetBufferForDWords()[objectId];
|
||||
|
||||
if (offset)
|
||||
result = VTable0x2c(p_action, offset);
|
||||
else
|
||||
result = FAILURE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1740
|
||||
MxResult MxStreamController::VTable0x24(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
VTable0x30(p_action);
|
||||
m_action0x60 = m_unk0x54.Find(p_action, TRUE);
|
||||
if (m_action0x60 == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
else {
|
||||
p_action->SetUnknown24(m_action0x60->GetUnknown24());
|
||||
p_action->SetObjectId(m_action0x60->GetObjectId());
|
||||
return FUN_100c1f00(m_action0x60);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1800
|
||||
MxResult MxStreamController::FUN_100c1800(MxDSAction* p_action, MxU32 p_val)
|
||||
{
|
||||
MxNextActionDataStart* dataActionStart =
|
||||
new MxNextActionDataStart(p_action->GetObjectId(), p_action->GetUnknown24(), p_val);
|
||||
if (dataActionStart == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
m_nextActionList.push_back(dataActionStart);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1a00
|
||||
MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset)
|
||||
{
|
||||
if (p_action->GetUnknown24() == -1) {
|
||||
MxS16 newUnknown24 = -1;
|
||||
|
||||
// These loops might be a template function in the list classes
|
||||
for (MxStreamListMxDSAction::iterator it = m_unk0x54.begin(); it != m_unk0x54.end(); it++) {
|
||||
MxDSAction* action = *it;
|
||||
|
||||
if (action->GetObjectId() == p_action->GetObjectId())
|
||||
newUnknown24 = Max(newUnknown24, action->GetUnknown24());
|
||||
}
|
||||
|
||||
if (newUnknown24 == -1) {
|
||||
for (MxStreamListMxDSAction::iterator it = m_unk0x3c.begin(); it != m_unk0x3c.end(); it++) {
|
||||
MxDSAction* action = *it;
|
||||
|
||||
if (action->GetObjectId() == p_action->GetObjectId())
|
||||
newUnknown24 = Max(newUnknown24, action->GetUnknown24());
|
||||
}
|
||||
|
||||
if (newUnknown24 == -1) {
|
||||
for (MxStreamListMxDSSubscriber::iterator it = m_subscriberList.begin(); it != m_subscriberList.end();
|
||||
it++) {
|
||||
MxDSSubscriber* subscriber = *it;
|
||||
|
||||
if (subscriber->GetObjectId() == p_action->GetObjectId())
|
||||
newUnknown24 = Max(newUnknown24, subscriber->GetUnknown48());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p_action->SetUnknown24(newUnknown24 + 1);
|
||||
}
|
||||
else {
|
||||
if (m_unk0x3c.Find(p_action, FALSE))
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
MxDSStreamingAction* streamingAction = new MxDSStreamingAction(*p_action, p_offset);
|
||||
|
||||
if (!streamingAction)
|
||||
return FAILURE;
|
||||
|
||||
MxU32 fileSize = m_provider->GetFileSize();
|
||||
streamingAction->SetBufferOffset(fileSize * (p_offset / fileSize));
|
||||
streamingAction->SetObjectId(p_action->GetObjectId());
|
||||
|
||||
MxLong time = Timer()->GetTime();
|
||||
streamingAction->SetUnknown90(time);
|
||||
|
||||
m_unk0x3c.push_back(streamingAction);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1c10
|
||||
MxResult MxStreamController::VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
if (FUN_100c1a00(p_action, p_bufferval) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
return FUN_100c1800(p_action, (p_bufferval / m_provider->GetFileSize()) * m_provider->GetFileSize());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1ce0
|
||||
MxResult MxStreamController::VTable0x30(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
MxResult result = FAILURE;
|
||||
MxDSAction* action = m_unk0x3c.Find(p_action, TRUE);
|
||||
if (action != NULL) {
|
||||
MxNextActionDataStart* data = m_nextActionList.FindAndErase(action->GetObjectId(), action->GetUnknown24());
|
||||
delete action;
|
||||
delete data;
|
||||
result = SUCCESS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1da0
|
||||
MxResult MxStreamController::InsertActionToList54(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
MxDSAction* action = p_action->Clone();
|
||||
|
||||
if (action == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
else {
|
||||
m_unk0x54.push_back(action);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1e70
|
||||
MxPresenter* MxStreamController::FUN_100c1e70(MxDSAction& p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
MxPresenter* result = NULL;
|
||||
if (p_action.GetObjectId() != -1) {
|
||||
MxDSAction* action = m_unk0x3c.Find(&p_action, FALSE);
|
||||
if (action != NULL) {
|
||||
result = action->GetUnknown28();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c1f00
|
||||
MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action)
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
MxU32 objectId = p_action->GetObjectId();
|
||||
MxStreamChunk* chunk = new MxStreamChunk;
|
||||
|
||||
if (!chunk)
|
||||
return FAILURE;
|
||||
|
||||
chunk->SetFlags(MxDSChunk::Flag_Bit3);
|
||||
chunk->SetObjectId(objectId);
|
||||
|
||||
if (chunk->SendChunk(m_subscriberList, FALSE, p_action->GetUnknown24()) != SUCCESS)
|
||||
delete chunk;
|
||||
|
||||
if (p_action->IsA("MxDSMultiAction")) {
|
||||
MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList();
|
||||
MxDSActionListCursor cursor(actions);
|
||||
MxDSAction* action;
|
||||
|
||||
while (cursor.Next(action)) {
|
||||
if (FUN_100c1f00(action) != SUCCESS)
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c20b0
|
||||
MxNextActionDataStart* MxStreamController::FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action)
|
||||
{
|
||||
return m_nextActionList.Find(p_action->GetObjectId(), p_action->GetUnknown24());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c20d0
|
||||
MxBool MxStreamController::FUN_100c20d0(MxDSObject& p_obj)
|
||||
{
|
||||
if (m_subscriberList.Find(&p_obj))
|
||||
return FALSE;
|
||||
|
||||
if (p_obj.IsA("MxDSMultiAction")) {
|
||||
MxDSActionList* actions = ((MxDSMultiAction&) p_obj).GetActionList();
|
||||
MxDSActionListCursor cursor(actions);
|
||||
MxDSAction* action;
|
||||
|
||||
while (cursor.Next(action)) {
|
||||
if (!FUN_100c20d0(*action))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
209
LEGO1/omni/src/stream/mxstreamer.cpp
Normal file
209
LEGO1/omni/src/stream/mxstreamer.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "mxstreamer.h"
|
||||
|
||||
#include "legoomni.h"
|
||||
#include "mxdiskstreamcontroller.h"
|
||||
#include "mxnotificationmanager.h"
|
||||
#include "mxramstreamcontroller.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxStreamer, 0x2c);
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8f00
|
||||
MxStreamer::MxStreamer()
|
||||
{
|
||||
NotificationManager()->Register(this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9190
|
||||
MxResult MxStreamer::Create()
|
||||
{
|
||||
undefined* b = new undefined[m_subclass1.GetSize() * 0x5800];
|
||||
m_subclass1.SetBuffer(b);
|
||||
if (b) {
|
||||
b = new undefined[m_subclass2.GetSize() * 0x800];
|
||||
m_subclass2.SetBuffer(b);
|
||||
if (b) {
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b91d0
|
||||
MxStreamer::~MxStreamer()
|
||||
{
|
||||
while (!m_openStreams.empty()) {
|
||||
MxStreamController* c = m_openStreams.front();
|
||||
m_openStreams.pop_front();
|
||||
delete c;
|
||||
}
|
||||
|
||||
NotificationManager()->Unregister(this);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b92c0
|
||||
MxStreamController* MxStreamer::Open(const char* p_name, MxU16 p_lookupType)
|
||||
{
|
||||
MxStreamController* stream = NULL;
|
||||
|
||||
if (!GetOpenStream(p_name)) {
|
||||
switch (p_lookupType) {
|
||||
case e_DiskStream:
|
||||
stream = new MxDiskStreamController();
|
||||
break;
|
||||
case e_RAMStream:
|
||||
stream = new MxRAMStreamController();
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream && (stream->Open(p_name) != SUCCESS || AddStreamControllerToOpenList(stream) != SUCCESS)) {
|
||||
delete stream;
|
||||
stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9570
|
||||
MxLong MxStreamer::Close(const char* p_name)
|
||||
{
|
||||
MxDSAction ds;
|
||||
ds.SetUnknown24(-2);
|
||||
|
||||
for (list<MxStreamController*>::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) {
|
||||
MxStreamController* c = *it;
|
||||
|
||||
if (!p_name || !strcmp(p_name, c->GetAtom().GetInternal())) {
|
||||
m_openStreams.erase(it);
|
||||
|
||||
if (c->FUN_100c20d0(ds))
|
||||
delete c;
|
||||
else {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxStreamerNotification notification(MXSTREAMER_DELETE_NOTIFY, NULL, c);
|
||||
NotificationManager()->Send(this, ¬ification);
|
||||
}
|
||||
#else
|
||||
NotificationManager()->Send(this, &MxStreamerNotification(MXSTREAMER_DELETE_NOTIFY, NULL, c));
|
||||
#endif
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9700
|
||||
MxNotificationParam* MxStreamerNotification::Clone()
|
||||
{
|
||||
return new MxStreamerNotification(m_type, m_sender, m_controller);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9870
|
||||
MxStreamController* MxStreamer::GetOpenStream(const char* p_name)
|
||||
{
|
||||
for (list<MxStreamController*>::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) {
|
||||
MxStreamController* c = *it;
|
||||
MxAtomId& atom = c->GetAtom();
|
||||
if (p_name) {
|
||||
if (!strcmp(atom.GetInternal(), p_name)) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9930
|
||||
MxResult MxStreamer::AddStreamControllerToOpenList(MxStreamController* p_stream)
|
||||
{
|
||||
if (find(m_openStreams.begin(), m_openStreams.end(), p_stream) == m_openStreams.end()) {
|
||||
m_openStreams.push_back(p_stream);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b99b0
|
||||
MxResult MxStreamer::FUN_100b99b0(MxDSAction* p_action)
|
||||
{
|
||||
MxStreamController* controller;
|
||||
if (p_action != NULL && p_action->GetAtomId().GetInternal() != NULL && p_action->GetObjectId() != -1) {
|
||||
controller = GetOpenStream(p_action->GetAtomId().GetInternal());
|
||||
if (controller == NULL) {
|
||||
return FAILURE;
|
||||
}
|
||||
return controller->VTable0x20(p_action);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b99f0
|
||||
MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction)
|
||||
{
|
||||
MxDSAction tempAction;
|
||||
|
||||
if (p_dsAction == NULL) {
|
||||
tempAction.SetUnknown24(-2);
|
||||
}
|
||||
else {
|
||||
tempAction.SetObjectId(p_dsAction->GetObjectId());
|
||||
tempAction.SetAtomId(p_dsAction->GetAtomId());
|
||||
tempAction.SetUnknown24(p_dsAction->GetUnknown24());
|
||||
}
|
||||
|
||||
MxResult result = FAILURE;
|
||||
for (list<MxStreamController*>::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) {
|
||||
const char* id = p_dsAction->GetAtomId().GetInternal();
|
||||
if (!id || id == (*it)->GetAtom().GetInternal()) {
|
||||
tempAction.SetAtomId((*it)->GetAtom());
|
||||
result = (*it)->VTable0x24(&tempAction);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9b30
|
||||
MxBool MxStreamer::FUN_100b9b30(MxDSObject& p_dsObject)
|
||||
{
|
||||
MxStreamController* controller = GetOpenStream(p_dsObject.GetAtomId().GetInternal());
|
||||
if (controller)
|
||||
return controller->FUN_100c20d0(p_dsObject);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9b60
|
||||
MxLong MxStreamer::Notify(MxParam& p_param)
|
||||
{
|
||||
if (((MxNotificationParam&) p_param).GetNotification() == MXSTREAMER_DELETE_NOTIFY) {
|
||||
MxDSAction ds;
|
||||
|
||||
ds.SetUnknown24(-2);
|
||||
|
||||
MxStreamController* c = static_cast<MxStreamerNotification&>(p_param).GetController();
|
||||
|
||||
if (c->FUN_100c20d0(ds))
|
||||
delete c;
|
||||
else {
|
||||
#ifdef COMPAT_MODE
|
||||
{
|
||||
MxStreamerNotification notification(MXSTREAMER_DELETE_NOTIFY, NULL, c);
|
||||
NotificationManager()->Send(this, ¬ification);
|
||||
}
|
||||
#else
|
||||
NotificationManager()->Send(this, &MxStreamerNotification(MXSTREAMER_DELETE_NOTIFY, NULL, c));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
77
LEGO1/omni/src/stream/mxstreamlist.cpp
Normal file
77
LEGO1/omni/src/stream/mxstreamlist.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "mxstreamlist.h"
|
||||
|
||||
// Wrappers around STL list that are used by the MxStream* classes.
|
||||
DECOMP_SIZE_ASSERT(MxStreamListMxDSAction, 0xc);
|
||||
DECOMP_SIZE_ASSERT(MxStreamListMxNextActionDataStart, 0xc);
|
||||
DECOMP_SIZE_ASSERT(MxStreamListMxDSSubscriber, 0xc);
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8450
|
||||
MxDSSubscriber* MxStreamListMxDSSubscriber::Find(MxDSObject* p_object)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); it++) {
|
||||
if (p_object->GetObjectId() == -1 || p_object->GetObjectId() == (*it)->GetObjectId()) {
|
||||
if (p_object->GetUnknown24() == -2 || p_object->GetUnknown24() == (*it)->GetUnknown48()) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bfa80
|
||||
MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete)
|
||||
{
|
||||
// DECOMP ALPHA 0x1008b99d ?
|
||||
|
||||
MxDSAction* found = NULL;
|
||||
|
||||
#ifdef COMPAT_MODE
|
||||
iterator it;
|
||||
for (it = begin(); it != end(); it++) {
|
||||
#else
|
||||
for (iterator it = begin(); it != end(); it++) {
|
||||
#endif
|
||||
if (p_action->GetObjectId() == -1 || p_action->GetObjectId() == (*it)->GetObjectId()) {
|
||||
if (p_action->GetUnknown24() == -2 || p_action->GetUnknown24() == -3 ||
|
||||
p_action->GetUnknown24() == (*it)->GetUnknown24()) {
|
||||
found = *it;
|
||||
if (p_action->GetUnknown24() != -3)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_delete && found != NULL) {
|
||||
erase(it);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c21e0
|
||||
MxNextActionDataStart* MxStreamListMxNextActionDataStart::Find(MxU32 p_id, MxS16 p_value)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); it++) {
|
||||
if (p_id == (*it)->GetObjectId() && p_value == (*it)->GetUnknown24())
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c2240
|
||||
MxNextActionDataStart* MxStreamListMxNextActionDataStart::FindAndErase(MxU32 p_id, MxS16 p_value)
|
||||
{
|
||||
MxNextActionDataStart* match = NULL;
|
||||
|
||||
for (iterator it = begin(); it != end(); it++) {
|
||||
if (p_id == (*it)->GetObjectId() && (p_value == -2 || p_value == (*it)->GetUnknown24())) {
|
||||
match = *it;
|
||||
erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
17
LEGO1/omni/src/stream/mxstreamprovider.cpp
Normal file
17
LEGO1/omni/src/stream/mxstreamprovider.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "mxstreamprovider.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxStreamProvider, 0x10);
|
||||
|
||||
// FUNCTION: LEGO1 0x100d07c0
|
||||
MxResult MxStreamProvider::SetResourceToGet(MxStreamController* p_resource)
|
||||
{
|
||||
m_pLookup = p_resource;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d07d0
|
||||
void MxStreamProvider::VTable0x20(MxDSAction* p_action)
|
||||
{
|
||||
}
|
||||
16
LEGO1/omni/src/system/mxautolocker.cpp
Normal file
16
LEGO1/omni/src/system/mxautolocker.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "mxautolocker.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8ed0
|
||||
MxAutoLocker::MxAutoLocker(MxCriticalSection* p_criticalSection)
|
||||
{
|
||||
this->m_criticalSection = p_criticalSection;
|
||||
if (this->m_criticalSection != 0)
|
||||
this->m_criticalSection->Enter();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8ef0
|
||||
MxAutoLocker::~MxAutoLocker()
|
||||
{
|
||||
if (this->m_criticalSection != 0)
|
||||
this->m_criticalSection->Leave();
|
||||
}
|
||||
76
LEGO1/omni/src/system/mxcriticalsection.cpp
Normal file
76
LEGO1/omni/src/system/mxcriticalsection.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "mxcriticalsection.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxCriticalSection, 0x1c);
|
||||
|
||||
// GLOBAL: LEGO1 0x10101e78
|
||||
int g_useMutex = 0;
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6d20
|
||||
MxCriticalSection::MxCriticalSection()
|
||||
{
|
||||
HANDLE mutex;
|
||||
|
||||
if (g_useMutex != 0) {
|
||||
mutex = CreateMutexA(NULL, FALSE, NULL);
|
||||
this->m_mutex = mutex;
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&this->m_criticalSection);
|
||||
this->m_mutex = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6d60
|
||||
MxCriticalSection::~MxCriticalSection()
|
||||
{
|
||||
if (this->m_mutex != NULL) {
|
||||
CloseHandle(this->m_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&this->m_criticalSection);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6d80
|
||||
void MxCriticalSection::Enter()
|
||||
{
|
||||
DWORD result;
|
||||
FILE* file;
|
||||
|
||||
if (this->m_mutex != NULL) {
|
||||
result = WaitForSingleObject(this->m_mutex, 5000);
|
||||
if (result == WAIT_FAILED) {
|
||||
file = fopen("C:\\DEADLOCK.TXT", "a");
|
||||
if (file != NULL) {
|
||||
fprintf(file, "mutex timeout occurred!\n");
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
}
|
||||
else {
|
||||
EnterCriticalSection(&this->m_criticalSection);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6de0
|
||||
void MxCriticalSection::Leave()
|
||||
{
|
||||
if (this->m_mutex != NULL) {
|
||||
ReleaseMutex(this->m_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&this->m_criticalSection);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b6e00
|
||||
void MxCriticalSection::SetDoMutex()
|
||||
{
|
||||
g_useMutex = 1;
|
||||
}
|
||||
14
LEGO1/omni/src/system/mxscheduler.cpp
Normal file
14
LEGO1/omni/src/system/mxscheduler.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "mxscheduler.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf4f0
|
||||
MxScheduler* MxScheduler::GetInstance()
|
||||
{
|
||||
// Intentionally empty
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf500
|
||||
void MxScheduler::StartMultiTasking(MxULong)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
33
LEGO1/omni/src/system/mxsemaphore.cpp
Normal file
33
LEGO1/omni/src/system/mxsemaphore.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
#include "mxsemaphore.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxSemaphore, 0x08)
|
||||
|
||||
// FUNCTION: LEGO1 0x100c87d0
|
||||
MxSemaphore::MxSemaphore()
|
||||
{
|
||||
m_hSemaphore = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8800
|
||||
MxResult MxSemaphore::Init(MxU32 p_initialCount, MxU32 p_maxCount)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
if (m_hSemaphore = CreateSemaphoreA(NULL, p_initialCount, p_maxCount, NULL))
|
||||
result = SUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8830
|
||||
void MxSemaphore::Wait(MxU32 p_timeoutMS)
|
||||
{
|
||||
WaitForSingleObject(m_hSemaphore, p_timeoutMS);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c8850
|
||||
void MxSemaphore::Release(MxU32 p_releaseCount)
|
||||
{
|
||||
ReleaseSemaphore(m_hSemaphore, p_releaseCount, NULL);
|
||||
}
|
||||
97
LEGO1/omni/src/system/mxthread.cpp
Normal file
97
LEGO1/omni/src/system/mxthread.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
#include "mxthread.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxtimer.h"
|
||||
|
||||
#include <process.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxThread, 0x1c)
|
||||
DECOMP_SIZE_ASSERT(MxTickleThread, 0x20)
|
||||
|
||||
// FUNCTION: LEGO1 0x100b8bb0
|
||||
MxTickleThread::MxTickleThread(MxCore* p_target, MxS32 p_frequencyMS)
|
||||
{
|
||||
m_target = p_target;
|
||||
m_frequencyMS = p_frequencyMS;
|
||||
}
|
||||
|
||||
// Match except for register allocation
|
||||
// FUNCTION: LEGO1 0x100b8c90
|
||||
MxResult MxTickleThread::Run()
|
||||
{
|
||||
MxTimer* timer = Timer();
|
||||
MxS32 lastTickled = -m_frequencyMS;
|
||||
while (IsRunning()) {
|
||||
MxLong currentTime = timer->GetTime();
|
||||
|
||||
if (currentTime < lastTickled) {
|
||||
lastTickled = -m_frequencyMS;
|
||||
}
|
||||
|
||||
MxS32 timeRemainingMS = (m_frequencyMS - currentTime) + lastTickled;
|
||||
if (timeRemainingMS <= 0) {
|
||||
m_target->Tickle();
|
||||
timeRemainingMS = 0;
|
||||
lastTickled = currentTime;
|
||||
}
|
||||
Sleep(timeRemainingMS);
|
||||
}
|
||||
return MxThread::Run();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf510
|
||||
MxThread::MxThread()
|
||||
{
|
||||
m_hThread = NULL;
|
||||
m_running = TRUE;
|
||||
m_threadId = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf5a0
|
||||
MxThread::~MxThread()
|
||||
{
|
||||
if (m_hThread)
|
||||
CloseHandle((HANDLE) m_hThread);
|
||||
}
|
||||
|
||||
typedef unsigned(__stdcall* ThreadFunc)(void*);
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf610
|
||||
MxResult MxThread::Start(MxS32 p_stack, MxS32 p_flag)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
if (m_semaphore.Init(0, 1) == SUCCESS) {
|
||||
if (m_hThread =
|
||||
_beginthreadex(NULL, p_stack << 2, (ThreadFunc) &MxThread::ThreadProc, this, p_flag, &m_threadId))
|
||||
result = SUCCESS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf660
|
||||
void MxThread::Sleep(MxS32 p_milliseconds)
|
||||
{
|
||||
::Sleep(p_milliseconds);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf670
|
||||
void MxThread::Terminate()
|
||||
{
|
||||
m_running = FALSE;
|
||||
m_semaphore.Wait(INFINITE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf680
|
||||
unsigned MxThread::ThreadProc(void* p_thread)
|
||||
{
|
||||
return static_cast<MxThread*>(p_thread)->Run();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf690
|
||||
MxResult MxThread::Run()
|
||||
{
|
||||
m_semaphore.Release(1);
|
||||
return SUCCESS;
|
||||
}
|
||||
393
LEGO1/omni/src/video/mxbitmap.cpp
Normal file
393
LEGO1/omni/src/video/mxbitmap.cpp
Normal file
@@ -0,0 +1,393 @@
|
||||
#include "mxbitmap.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxBitmap, 0x20);
|
||||
DECOMP_SIZE_ASSERT(MxBITMAPINFO, 0x428);
|
||||
|
||||
// Bitmap header magic string "BM" (42 4d)
|
||||
// Sources: https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapfileheader, DirectX Complete
|
||||
// (1998) GLOBAL: LEGO1 0x10102184
|
||||
MxU16 g_bitmapSignature = TWOCC('B', 'M');
|
||||
|
||||
// FUNCTION: LEGO1 0x1004e0d0
|
||||
int MxBitmap::VTable0x28(int)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bc980
|
||||
MxBitmap::MxBitmap()
|
||||
{
|
||||
this->m_info = NULL;
|
||||
this->m_bmiHeader = NULL;
|
||||
this->m_paletteData = NULL;
|
||||
this->m_data = NULL;
|
||||
this->m_isHighColor = FALSE;
|
||||
this->m_palette = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bca10
|
||||
MxBitmap::~MxBitmap()
|
||||
{
|
||||
if (this->m_info)
|
||||
delete m_info;
|
||||
if (this->m_data)
|
||||
delete m_data;
|
||||
if (this->m_palette)
|
||||
delete m_palette;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bcaa0
|
||||
MxResult MxBitmap::SetSize(MxS32 p_width, MxS32 p_height, MxPalette* p_palette, MxBool p_isHighColor)
|
||||
{
|
||||
MxResult ret = FAILURE;
|
||||
MxLong size = AlignToFourByte(p_width) * p_height;
|
||||
|
||||
m_info = new MxBITMAPINFO;
|
||||
if (m_info) {
|
||||
m_data = new MxU8[size];
|
||||
if (m_data) {
|
||||
m_bmiHeader = &m_info->m_bmiHeader;
|
||||
m_paletteData = m_info->m_bmiColors;
|
||||
memset(&m_info->m_bmiHeader, 0, sizeof(m_info->m_bmiHeader));
|
||||
|
||||
m_bmiHeader->biSize = sizeof(*m_bmiHeader); // should be 40 bytes
|
||||
m_bmiHeader->biWidth = p_width;
|
||||
m_bmiHeader->biHeight = p_height;
|
||||
m_bmiHeader->biPlanes = 1;
|
||||
m_bmiHeader->biBitCount = 8;
|
||||
m_bmiHeader->biCompression = 0;
|
||||
m_bmiHeader->biSizeImage = size;
|
||||
|
||||
if (!ImportColorsToPalette(m_paletteData, p_palette)) {
|
||||
if (!SetBitDepth(p_isHighColor)) {
|
||||
ret = SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
if (m_info) {
|
||||
delete m_info;
|
||||
m_info = NULL;
|
||||
}
|
||||
|
||||
if (m_data) {
|
||||
delete[] m_data;
|
||||
m_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bcba0
|
||||
MxResult MxBitmap::ImportBitmapInfo(MxBITMAPINFO* p_info)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
MxLong width = p_info->m_bmiHeader.biWidth;
|
||||
MxLong height = p_info->m_bmiHeader.biHeight;
|
||||
MxLong size = AlignToFourByte(width) * height;
|
||||
|
||||
this->m_info = new MxBITMAPINFO;
|
||||
if (this->m_info) {
|
||||
this->m_data = new MxU8[size];
|
||||
if (this->m_data) {
|
||||
memcpy(this->m_info, p_info, sizeof(*this->m_info));
|
||||
this->m_bmiHeader = &this->m_info->m_bmiHeader;
|
||||
this->m_paletteData = this->m_info->m_bmiColors;
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != SUCCESS) {
|
||||
if (this->m_info) {
|
||||
delete this->m_info;
|
||||
this->m_info = NULL;
|
||||
}
|
||||
|
||||
if (this->m_data) {
|
||||
delete this->m_data;
|
||||
this->m_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bcc40
|
||||
MxResult MxBitmap::ImportBitmap(MxBitmap* p_bitmap)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
this->m_info = new MxBITMAPINFO;
|
||||
if (this->m_info) {
|
||||
this->m_data = new MxU8[p_bitmap->GetDataSize()];
|
||||
if (this->m_data) {
|
||||
memcpy(this->m_info, p_bitmap->GetBitmapInfo(), MxBITMAPINFO::Size());
|
||||
memcpy(this->m_data, p_bitmap->GetBitmapData(), p_bitmap->GetDataSize());
|
||||
|
||||
this->m_bmiHeader = &this->m_info->m_bmiHeader;
|
||||
this->m_paletteData = this->m_info->m_bmiColors;
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != SUCCESS) {
|
||||
if (this->m_info) {
|
||||
delete this->m_info;
|
||||
this->m_info = NULL;
|
||||
}
|
||||
|
||||
if (this->m_data) {
|
||||
delete this->m_data;
|
||||
this->m_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bcd10
|
||||
MxLong MxBitmap::Read(const char* p_filename)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
HANDLE handle =
|
||||
CreateFileA(p_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (handle != INVALID_HANDLE_VALUE && !LoadFile(handle))
|
||||
result = SUCCESS;
|
||||
|
||||
if (handle)
|
||||
CloseHandle(handle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bcd60
|
||||
MxResult MxBitmap::LoadFile(HANDLE p_handle)
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
DWORD bytesRead;
|
||||
BITMAPFILEHEADER hdr;
|
||||
|
||||
BOOL ret = ReadFile(p_handle, &hdr, sizeof(hdr), &bytesRead, NULL);
|
||||
if (ret && (hdr.bfType == g_bitmapSignature)) {
|
||||
this->m_info = new MxBITMAPINFO;
|
||||
if (this->m_info) {
|
||||
ret = ReadFile(p_handle, this->m_info, sizeof(*this->m_info), &bytesRead, NULL);
|
||||
if (ret && (this->m_info->m_bmiHeader.biBitCount == 8)) {
|
||||
MxLong size = hdr.bfSize - (sizeof(MxBITMAPINFO) + sizeof(BITMAPFILEHEADER));
|
||||
this->m_data = new MxU8[size];
|
||||
if (this->m_data) {
|
||||
ret = ReadFile(p_handle, this->m_data, size, &bytesRead, NULL);
|
||||
if (ret) {
|
||||
this->m_bmiHeader = &this->m_info->m_bmiHeader;
|
||||
this->m_paletteData = this->m_info->m_bmiColors;
|
||||
if (this->m_info->m_bmiHeader.biSizeImage == 0) {
|
||||
MxLong height = AbsFlipped(this->m_info->m_bmiHeader.biHeight);
|
||||
this->m_info->m_bmiHeader.biSizeImage =
|
||||
AlignToFourByte(this->m_info->m_bmiHeader.biWidth) * height;
|
||||
}
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result != SUCCESS) {
|
||||
if (this->m_info) {
|
||||
delete this->m_info;
|
||||
this->m_info = NULL;
|
||||
}
|
||||
|
||||
if (this->m_data) {
|
||||
delete this->m_data;
|
||||
this->m_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100bce70
|
||||
void MxBitmap::VTable0x2c(int, int, int, int, int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100bd020
|
||||
void MxBitmap::VTable0x30(int, int, int, int, int, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bd1c0
|
||||
MxPalette* MxBitmap::CreatePalette()
|
||||
{
|
||||
MxBool success = FALSE;
|
||||
MxPalette* palette = NULL;
|
||||
|
||||
switch (this->m_isHighColor) {
|
||||
case FALSE:
|
||||
palette = new MxPalette(this->m_paletteData);
|
||||
|
||||
if (!palette)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
case TRUE:
|
||||
palette = this->m_palette->Clone();
|
||||
|
||||
if (!palette)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
done:
|
||||
if (!success && palette) {
|
||||
delete palette;
|
||||
palette = NULL;
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bd280
|
||||
void MxBitmap::ImportPalette(MxPalette* p_palette)
|
||||
{
|
||||
// Odd to use a switch on a boolean, but it matches.
|
||||
switch (this->m_isHighColor) {
|
||||
case FALSE:
|
||||
ImportColorsToPalette(this->m_paletteData, p_palette);
|
||||
break;
|
||||
|
||||
case TRUE:
|
||||
if (this->m_palette) {
|
||||
delete this->m_palette;
|
||||
}
|
||||
this->m_palette = p_palette->Clone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bd2d0
|
||||
MxResult MxBitmap::SetBitDepth(MxBool p_isHighColor)
|
||||
{
|
||||
MxResult ret = FAILURE;
|
||||
MxPalette* pal = NULL;
|
||||
|
||||
if (m_isHighColor == p_isHighColor) {
|
||||
// no change: do nothing.
|
||||
ret = SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (p_isHighColor) {
|
||||
case FALSE:
|
||||
ImportColorsToPalette(m_paletteData, m_palette);
|
||||
if (m_palette)
|
||||
delete m_palette;
|
||||
|
||||
m_palette = NULL;
|
||||
break;
|
||||
case TRUE: {
|
||||
pal = NULL;
|
||||
pal = new MxPalette(m_paletteData);
|
||||
|
||||
if (!pal)
|
||||
goto done;
|
||||
|
||||
m_palette = pal;
|
||||
|
||||
// TODO: what is this? zeroing out top half of palette?
|
||||
MxU16* buf = (MxU16*) m_paletteData;
|
||||
for (MxU16 i = 0; i < 256; i++) {
|
||||
buf[i] = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
|
||||
m_isHighColor = p_isHighColor;
|
||||
ret = SUCCESS;
|
||||
|
||||
done:
|
||||
// If we were unsuccessful overall but did manage to alloc
|
||||
// the MxPalette, free it.
|
||||
if (ret && pal)
|
||||
delete pal;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bd3e0
|
||||
MxResult MxBitmap::StretchBits(
|
||||
HDC p_hdc,
|
||||
MxS32 p_xSrc,
|
||||
MxS32 p_ySrc,
|
||||
MxS32 p_xDest,
|
||||
MxS32 p_yDest,
|
||||
MxS32 p_destWidth,
|
||||
MxS32 p_destHeight
|
||||
)
|
||||
{
|
||||
// Compression fix?
|
||||
if ((this->m_bmiHeader->biCompression != BI_RGB_TOPDOWN) && (0 < this->m_bmiHeader->biHeight)) {
|
||||
p_ySrc = (this->m_bmiHeader->biHeight - p_destHeight) - p_ySrc;
|
||||
}
|
||||
|
||||
return StretchDIBits(
|
||||
p_hdc,
|
||||
p_xDest,
|
||||
p_yDest,
|
||||
p_destWidth,
|
||||
p_destHeight,
|
||||
p_xSrc,
|
||||
p_ySrc,
|
||||
p_destWidth,
|
||||
p_destHeight,
|
||||
this->m_data,
|
||||
(BITMAPINFO*) this->m_info,
|
||||
this->m_isHighColor,
|
||||
SRCCOPY
|
||||
);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bd450
|
||||
MxResult MxBitmap::ImportColorsToPalette(RGBQUAD* p_rgbquad, MxPalette* p_palette)
|
||||
{
|
||||
MxResult ret = FAILURE;
|
||||
PALETTEENTRY entries[256];
|
||||
|
||||
if (p_palette) {
|
||||
if (p_palette->GetEntries(entries))
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
MxPalette palette;
|
||||
if (palette.GetEntries(entries))
|
||||
goto done;
|
||||
}
|
||||
|
||||
MxS32 i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
p_rgbquad[i].rgbRed = entries[i].peRed;
|
||||
p_rgbquad[i].rgbGreen = entries[i].peGreen;
|
||||
p_rgbquad[i].rgbBlue = entries[i].peBlue;
|
||||
p_rgbquad[i].rgbReserved = 0;
|
||||
}
|
||||
|
||||
ret = SUCCESS;
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
606
LEGO1/omni/src/video/mxdisplaysurface.cpp
Normal file
606
LEGO1/omni/src/video/mxdisplaysurface.cpp
Normal file
@@ -0,0 +1,606 @@
|
||||
#include "mxdisplaysurface.h"
|
||||
|
||||
#include "legoomni.h"
|
||||
#include "mxvideomanager.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac);
|
||||
|
||||
MxU32 g_unk0x1010215c = 0;
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba500
|
||||
MxDisplaySurface::MxDisplaySurface()
|
||||
{
|
||||
this->Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba5a0
|
||||
MxDisplaySurface::~MxDisplaySurface()
|
||||
{
|
||||
this->Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba610
|
||||
void MxDisplaySurface::Init()
|
||||
{
|
||||
this->m_ddSurface1 = NULL;
|
||||
this->m_ddSurface2 = NULL;
|
||||
this->m_ddClipper = NULL;
|
||||
this->m_16bitPal = NULL;
|
||||
this->m_initialized = FALSE;
|
||||
memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc));
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba640
|
||||
void MxDisplaySurface::FUN_100ba640()
|
||||
{
|
||||
MxS32 backBuffers;
|
||||
DDSURFACEDESC desc;
|
||||
HRESULT hr;
|
||||
|
||||
if (!m_videoParam.Flags().GetFlipSurfaces()) {
|
||||
backBuffers = 1;
|
||||
}
|
||||
else {
|
||||
backBuffers = m_videoParam.GetBackBuffers() + 1;
|
||||
}
|
||||
|
||||
for (MxS32 i = 0; i < backBuffers; i++) {
|
||||
memset(&desc, 0, sizeof(DDSURFACEDESC));
|
||||
|
||||
desc.dwSize = sizeof(DDSURFACEDESC);
|
||||
hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL);
|
||||
if (hr == DDERR_SURFACELOST) {
|
||||
m_ddSurface2->Restore();
|
||||
hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL);
|
||||
}
|
||||
|
||||
if (hr != DD_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
MxU8* surface = (MxU8*) desc.lpSurface;
|
||||
MxS32 height = m_videoParam.GetRect().GetHeight();
|
||||
|
||||
while (height--) {
|
||||
memset(surface, 0, m_videoParam.GetRect().GetWidth() * desc.ddpfPixelFormat.dwRGBBitCount / 8);
|
||||
surface += desc.lPitch;
|
||||
}
|
||||
|
||||
m_ddSurface2->Unlock(desc.lpSurface);
|
||||
if (m_videoParam.Flags().GetFlipSurfaces()) {
|
||||
m_ddSurface1->Flip(NULL, DDFLIP_WAIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba750
|
||||
MxU8 MxDisplaySurface::CountTotalBitsSetTo1(MxU32 p_param)
|
||||
{
|
||||
MxU8 count = 0;
|
||||
|
||||
for (; p_param; p_param >>= 1)
|
||||
count += ((MxU8) p_param & 1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba770
|
||||
MxU8 MxDisplaySurface::CountContiguousBitsSetTo1(MxU32 p_param)
|
||||
{
|
||||
MxU8 count = 0;
|
||||
|
||||
for (; (p_param & 1) == 0; p_param >>= 1)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba790
|
||||
MxResult MxDisplaySurface::Init(
|
||||
MxVideoParam& p_videoParam,
|
||||
LPDIRECTDRAWSURFACE p_ddSurface1,
|
||||
LPDIRECTDRAWSURFACE p_ddSurface2,
|
||||
LPDIRECTDRAWCLIPPER p_ddClipper
|
||||
)
|
||||
{
|
||||
MxResult result = SUCCESS;
|
||||
|
||||
this->m_videoParam = p_videoParam;
|
||||
this->m_ddSurface1 = p_ddSurface1;
|
||||
this->m_ddSurface2 = p_ddSurface2;
|
||||
this->m_ddClipper = p_ddClipper;
|
||||
this->m_initialized = FALSE;
|
||||
|
||||
memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc));
|
||||
this->m_surfaceDesc.dwSize = sizeof(this->m_surfaceDesc);
|
||||
|
||||
if (this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc))
|
||||
result = FAILURE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba7f0
|
||||
MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam)
|
||||
{
|
||||
DDSURFACEDESC ddsd;
|
||||
MxResult result = FAILURE;
|
||||
LPDIRECTDRAW lpDirectDraw = MVideoManager()->GetDirectDraw();
|
||||
HWND hWnd = MxOmni::GetInstance()->GetWindowHandle();
|
||||
|
||||
this->m_initialized = TRUE;
|
||||
this->m_videoParam = p_videoParam;
|
||||
|
||||
if (!this->m_videoParam.Flags().GetFullScreen())
|
||||
this->m_videoParam.Flags().SetFlipSurfaces(FALSE);
|
||||
|
||||
if (!this->m_videoParam.Flags().GetFlipSurfaces()) {
|
||||
this->m_videoParam.SetBackBuffers(1);
|
||||
}
|
||||
else {
|
||||
MxU32 backBuffers = this->m_videoParam.GetBackBuffers();
|
||||
|
||||
if (backBuffers < 1)
|
||||
this->m_videoParam.SetBackBuffers(1);
|
||||
else if (backBuffers > 2)
|
||||
this->m_videoParam.SetBackBuffers(2);
|
||||
|
||||
this->m_videoParam.Flags().SetBackBuffers(TRUE);
|
||||
}
|
||||
|
||||
if (this->m_videoParam.Flags().GetFullScreen()) {
|
||||
MxS32 width = this->m_videoParam.GetRect().GetWidth();
|
||||
MxS32 height = this->m_videoParam.GetRect().GetHeight();
|
||||
|
||||
if (lpDirectDraw->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN))
|
||||
goto done;
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
if (lpDirectDraw->GetDisplayMode(&ddsd))
|
||||
goto done;
|
||||
|
||||
MxS32 bitdepth = !this->m_videoParam.Flags().Get16Bit() ? 8 : 16;
|
||||
|
||||
if (ddsd.dwWidth != width || ddsd.dwHeight != height || ddsd.ddpfPixelFormat.dwRGBBitCount != bitdepth) {
|
||||
if (lpDirectDraw->SetDisplayMode(width, height, bitdepth))
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_videoParam.Flags().GetFlipSurfaces()) {
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwBackBufferCount = this->m_videoParam.GetBackBuffers();
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
|
||||
|
||||
if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL))
|
||||
goto done;
|
||||
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
|
||||
if (this->m_ddSurface1->GetAttachedSurface(&ddsd.ddsCaps, &this->m_ddSurface2))
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||||
|
||||
if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL))
|
||||
goto done;
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS;
|
||||
ddsd.dwWidth = this->m_videoParam.GetRect().GetWidth();
|
||||
ddsd.dwHeight = this->m_videoParam.GetRect().GetHeight();
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN;
|
||||
|
||||
if (!this->m_videoParam.Flags().GetBackBuffers())
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
|
||||
|
||||
if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface2, NULL))
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc));
|
||||
this->m_surfaceDesc.dwSize = sizeof(this->m_surfaceDesc);
|
||||
|
||||
if (!this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) {
|
||||
if (!lpDirectDraw->CreateClipper(0, &this->m_ddClipper, NULL) && !this->m_ddClipper->SetHWnd(0, hWnd) &&
|
||||
!this->m_ddSurface1->SetClipper(this->m_ddClipper))
|
||||
result = SUCCESS;
|
||||
}
|
||||
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100baa90
|
||||
void MxDisplaySurface::Destroy()
|
||||
{
|
||||
if (this->m_initialized) {
|
||||
if (this->m_ddSurface2)
|
||||
this->m_ddSurface2->Release();
|
||||
|
||||
if (this->m_ddSurface1)
|
||||
this->m_ddSurface1->Release();
|
||||
|
||||
if (this->m_ddClipper)
|
||||
this->m_ddClipper->Release();
|
||||
}
|
||||
|
||||
if (this->m_16bitPal)
|
||||
delete this->m_16bitPal;
|
||||
|
||||
this->Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100baae0
|
||||
void MxDisplaySurface::SetPalette(MxPalette* p_palette)
|
||||
{
|
||||
if (m_surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
|
||||
m_ddSurface1->SetPalette(p_palette->CreateNativePalette());
|
||||
m_ddSurface2->SetPalette(p_palette->CreateNativePalette());
|
||||
|
||||
if ((m_videoParam.Flags().GetFullScreen() & 1) == 0) {
|
||||
struct {
|
||||
WORD m_palVersion;
|
||||
WORD m_palNumEntries;
|
||||
PALETTEENTRY m_palPalEntry[256];
|
||||
} lpal;
|
||||
|
||||
lpal.m_palVersion = 0x300;
|
||||
lpal.m_palNumEntries = 256;
|
||||
|
||||
memset(lpal.m_palPalEntry, 0, sizeof(lpal.m_palPalEntry));
|
||||
p_palette->GetEntries(lpal.m_palPalEntry);
|
||||
|
||||
HPALETTE hpal = CreatePalette((LPLOGPALETTE) &lpal);
|
||||
HDC hdc = ::GetDC(0);
|
||||
SelectPalette(hdc, hpal, FALSE);
|
||||
RealizePalette(hdc);
|
||||
::ReleaseDC(NULL, hdc);
|
||||
DeleteObject(hpal);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount == 16) {
|
||||
if (!m_16bitPal)
|
||||
m_16bitPal = new MxU16[256];
|
||||
|
||||
PALETTEENTRY palette[256];
|
||||
p_palette->GetEntries(palette);
|
||||
|
||||
MxU8 contiguousBitsRed = CountContiguousBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwRBitMask);
|
||||
MxU8 totalBitsRed = CountTotalBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwRBitMask);
|
||||
MxU8 contiguousBitsGreen = CountContiguousBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwGBitMask);
|
||||
MxU8 totalBitsGreen = CountTotalBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwGBitMask);
|
||||
MxU8 contiguousBitsBlue = CountContiguousBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwBBitMask);
|
||||
MxU8 totalBitsBlue = CountTotalBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwBBitMask);
|
||||
|
||||
for (MxS32 i = 0; i < 256; i++) {
|
||||
m_16bitPal[i] = (((palette[i].peRed >> (8 - totalBitsRed & 0x1f)) << (contiguousBitsRed & 0x1f))) |
|
||||
(((palette[i].peGreen >> (8 - totalBitsGreen & 0x1f)) << (contiguousBitsGreen & 0x1f))) |
|
||||
(((palette[i].peBlue >> (8 - totalBitsBlue & 0x1f)) << (contiguousBitsBlue & 0x1f)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bacc0
|
||||
void MxDisplaySurface::VTable0x28(
|
||||
MxBitmap* p_bitmap,
|
||||
MxS32 p_left,
|
||||
MxS32 p_top,
|
||||
MxS32 p_right,
|
||||
MxS32 p_bottom,
|
||||
MxS32 p_width,
|
||||
MxS32 p_height
|
||||
)
|
||||
{
|
||||
if (FUN_100b6e10(
|
||||
p_bitmap->GetBmiWidth(),
|
||||
p_bitmap->GetBmiHeightAbs(),
|
||||
m_videoParam.GetRect().GetWidth(),
|
||||
m_videoParam.GetRect().GetHeight(),
|
||||
&p_left,
|
||||
&p_top,
|
||||
&p_right,
|
||||
&p_bottom,
|
||||
&p_width,
|
||||
&p_height
|
||||
)) {
|
||||
DDSURFACEDESC ddsd;
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
if (hr == DDERR_SURFACELOST) {
|
||||
m_ddSurface2->Restore();
|
||||
hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
|
||||
}
|
||||
|
||||
if (hr == DD_OK) {
|
||||
MxU8* data;
|
||||
|
||||
switch (p_bitmap->GetBmiHeader()->biCompression) {
|
||||
case BI_RGB: {
|
||||
MxS32 rowsBeforeTop;
|
||||
if (p_bitmap->GetBmiHeight() < 0)
|
||||
rowsBeforeTop = p_top;
|
||||
else
|
||||
rowsBeforeTop = p_bitmap->GetBmiHeightAbs() - p_top - 1;
|
||||
data = p_bitmap->GetBitmapData() + p_left + (p_bitmap->GetBmiStride() * rowsBeforeTop);
|
||||
break;
|
||||
}
|
||||
case BI_RGB_TOPDOWN:
|
||||
data = p_bitmap->GetBitmapData();
|
||||
break;
|
||||
default: {
|
||||
MxS32 rowsBeforeTop;
|
||||
if (p_bitmap->GetBmiHeight() < 0)
|
||||
rowsBeforeTop = 0;
|
||||
else
|
||||
rowsBeforeTop = p_bitmap->GetBmiHeightAbs() - 1;
|
||||
data = p_bitmap->GetBitmapData() + (p_bitmap->GetBmiStride() * rowsBeforeTop);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_videoParam.Flags().GetF1bit3()) {
|
||||
p_bottom *= 2;
|
||||
p_right *= 2;
|
||||
|
||||
switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) {
|
||||
case 8: {
|
||||
MxU8* surface = (MxU8*) ddsd.lpSurface + p_right + (p_bottom * ddsd.lPitch);
|
||||
MxLong stride = p_bitmap->GetAdjustedStride();
|
||||
|
||||
MxLong v22 = stride - p_width;
|
||||
MxLong length = ddsd.lPitch - (2 * p_width);
|
||||
while (p_height--) {
|
||||
MxU8* surfaceBefore = surface;
|
||||
|
||||
for (MxS32 i = 0; p_width > i; i++) {
|
||||
MxU8 element = *data;
|
||||
*surface++ = element;
|
||||
data++;
|
||||
*surface++ = *(data - 1);
|
||||
}
|
||||
|
||||
data += v22;
|
||||
surface += length;
|
||||
|
||||
memcpy(surface, surfaceBefore, 2 * p_width);
|
||||
surface += ddsd.lPitch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
MxU8* surface = (MxU8*) ddsd.lpSurface + (2 * p_right) + (p_bottom * ddsd.lPitch);
|
||||
MxLong stride = p_bitmap->GetAdjustedStride();
|
||||
|
||||
// TODO: Match
|
||||
stride -= p_width;
|
||||
MxS32 length = p_width * 4;
|
||||
MxLong v62 = ddsd.lPitch - length;
|
||||
MxS32 height = p_height;
|
||||
MxS32 width = p_width;
|
||||
MxU16* p16BitPal = m_16bitPal;
|
||||
|
||||
if (stride || v62) {
|
||||
while (height--) {
|
||||
MxU8* surfaceBefore = surface;
|
||||
|
||||
for (MxS32 i = width; i > 0; i--) {
|
||||
MxU16 element = p16BitPal[*data++];
|
||||
*(MxU16*) surface = element;
|
||||
surface += 2;
|
||||
*(MxU16*) surface = element;
|
||||
surface += 2;
|
||||
}
|
||||
|
||||
data += stride;
|
||||
surface += v62;
|
||||
|
||||
// Odd expression for the length?
|
||||
memcpy(surface, surfaceBefore, 4 * ((MxU32) (4 * p_width) / 4));
|
||||
surface += ddsd.lPitch;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (height--) {
|
||||
MxU8* surfaceBefore = surface;
|
||||
|
||||
for (MxS32 i = width; i > 0; i--) {
|
||||
MxU16 element = p16BitPal[*data++];
|
||||
*(MxU16*) surface = element;
|
||||
surface += 2;
|
||||
*(MxU16*) surface = element;
|
||||
surface += 2;
|
||||
}
|
||||
|
||||
memcpy(surface, surfaceBefore, length);
|
||||
surface += ddsd.lPitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) {
|
||||
case 8: {
|
||||
MxU8* surface = (MxU8*) ddsd.lpSurface + p_right + (p_bottom * ddsd.lPitch);
|
||||
MxLong stride = p_bitmap->GetAdjustedStride();
|
||||
|
||||
MxLong length = ddsd.lPitch;
|
||||
while (p_height--) {
|
||||
memcpy(surface, data, p_width);
|
||||
data += stride;
|
||||
surface += length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
MxU8* surface = (MxU8*) ddsd.lpSurface + (2 * p_right) + (p_bottom * ddsd.lPitch);
|
||||
MxLong stride = p_bitmap->GetAdjustedStride();
|
||||
|
||||
MxLong v50 = stride - p_width;
|
||||
MxLong length = ddsd.lPitch - (2 * p_width);
|
||||
for (MxS32 i = 0; p_height > i; i++) {
|
||||
for (MxS32 j = 0; p_width > j; j++) {
|
||||
*(MxU16*) surface = m_16bitPal[*data++];
|
||||
surface += 2;
|
||||
}
|
||||
|
||||
data += v50;
|
||||
surface += length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_ddSurface2->Unlock(ddsd.lpSurface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100bb1d0
|
||||
MxBool MxDisplaySurface::VTable0x30(
|
||||
MxBitmap* p_bitmap,
|
||||
MxS32 p_left,
|
||||
MxS32 p_top,
|
||||
MxS32 p_right,
|
||||
MxS32 p_bottom,
|
||||
MxS32 p_width,
|
||||
MxS32 p_height,
|
||||
MxBool
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100bb850
|
||||
undefined4 MxDisplaySurface::VTable0x34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bba50
|
||||
void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height)
|
||||
{
|
||||
if (m_videoParam.Flags().GetF2bit1()) {
|
||||
if (m_videoParam.Flags().GetFlipSurfaces()) {
|
||||
if (g_unk0x1010215c < 2) {
|
||||
g_unk0x1010215c++;
|
||||
|
||||
DDSURFACEDESC ddsd;
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
if (m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) == DD_OK) {
|
||||
MxU8* surface = (MxU8*) ddsd.lpSurface;
|
||||
MxS32 height = m_videoParam.GetRect().GetHeight();
|
||||
|
||||
for (MxU32 i = 0; i < ddsd.dwHeight; i++) {
|
||||
memset(surface, 0, ddsd.dwWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8);
|
||||
surface += ddsd.lPitch;
|
||||
}
|
||||
|
||||
m_ddSurface2->Unlock(ddsd.lpSurface);
|
||||
}
|
||||
else {
|
||||
OutputDebugString("MxDisplaySurface::Display error\n");
|
||||
}
|
||||
}
|
||||
m_ddSurface1->Flip(NULL, DDFLIP_WAIT);
|
||||
}
|
||||
else {
|
||||
POINT point = {0, 0};
|
||||
ClientToScreen(MxOmni::GetInstance()->GetWindowHandle(), &point);
|
||||
|
||||
// TODO: Match
|
||||
RECT rect1, rect2;
|
||||
rect1.left = p_left2 + m_videoParam.GetRect().GetLeft() + point.x;
|
||||
rect2.left = p_left;
|
||||
rect1.top = p_top2 + m_videoParam.GetRect().GetTop() + point.y;
|
||||
rect2.right = p_left + p_width;
|
||||
rect2.top = p_top;
|
||||
rect2.bottom = p_top + p_height;
|
||||
rect1.right = rect1.left + p_width;
|
||||
rect1.bottom = rect1.top + p_height;
|
||||
|
||||
DDBLTFX data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.dwSize = sizeof(data);
|
||||
data.dwDDFX = 8;
|
||||
|
||||
if (m_ddSurface1->Blt(&rect1, m_ddSurface2, &rect2, 0, &data) == DDERR_SURFACELOST) {
|
||||
m_ddSurface1->Restore();
|
||||
m_ddSurface1->Blt(&rect1, m_ddSurface2, &rect2, 0, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bbc10
|
||||
void MxDisplaySurface::GetDC(HDC* p_hdc)
|
||||
{
|
||||
if (this->m_ddSurface2 && !this->m_ddSurface2->GetDC(p_hdc))
|
||||
return;
|
||||
|
||||
*p_hdc = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bbc40
|
||||
void MxDisplaySurface::ReleaseDC(HDC p_hdc)
|
||||
{
|
||||
if (this->m_ddSurface2 && p_hdc)
|
||||
this->m_ddSurface2->ReleaseDC(p_hdc);
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100bbc60
|
||||
LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100bc070
|
||||
LPDIRECTDRAWSURFACE MxDisplaySurface::FUN_100bc070()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100bc200
|
||||
void MxDisplaySurface::VTable0x24(
|
||||
LPDDSURFACEDESC,
|
||||
MxBitmap*,
|
||||
undefined4,
|
||||
undefined4,
|
||||
undefined4,
|
||||
undefined4,
|
||||
undefined4,
|
||||
undefined4
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100bc630
|
||||
MxBool MxDisplaySurface::VTable0x2c(
|
||||
LPDDSURFACEDESC,
|
||||
MxBitmap*,
|
||||
undefined4,
|
||||
undefined4,
|
||||
undefined4,
|
||||
undefined4,
|
||||
undefined4,
|
||||
undefined4,
|
||||
MxBool
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
50
LEGO1/omni/src/video/mxflcpresenter.cpp
Normal file
50
LEGO1/omni/src/video/mxflcpresenter.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "mxflcpresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxbitmap.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxpalette.h"
|
||||
#include "mxvideomanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68);
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3310
|
||||
MxFlcPresenter::MxFlcPresenter()
|
||||
{
|
||||
this->m_flicHeader = NULL;
|
||||
this->m_flags &= ~Flag_Bit2;
|
||||
this->m_flags &= ~Flag_Bit3;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3420
|
||||
MxFlcPresenter::~MxFlcPresenter()
|
||||
{
|
||||
if (this->m_flicHeader) {
|
||||
delete this->m_flicHeader;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3490
|
||||
void MxFlcPresenter::LoadHeader(MxStreamChunk* p_chunk)
|
||||
{
|
||||
m_flicHeader = (FLIC_HEADER*) new MxU8[p_chunk->GetLength()];
|
||||
memcpy(m_flicHeader, p_chunk->GetData(), p_chunk->GetLength());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b34d0
|
||||
void MxFlcPresenter::CreateBitmap()
|
||||
{
|
||||
if (m_bitmap)
|
||||
delete m_bitmap;
|
||||
|
||||
m_bitmap = new MxBitmap;
|
||||
m_bitmap->SetSize(m_flicHeader->width, m_flicHeader->height, NULL, FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3620
|
||||
void MxFlcPresenter::RealizePalette()
|
||||
{
|
||||
MxPalette* palette = m_bitmap->CreatePalette();
|
||||
MVideoManager()->RealizePalette(palette);
|
||||
delete palette;
|
||||
}
|
||||
54
LEGO1/omni/src/video/mxloopingflcpresenter.cpp
Normal file
54
LEGO1/omni/src/video/mxloopingflcpresenter.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "mxloopingflcpresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxLoopingFlcPresenter, 0x6c);
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4310
|
||||
MxLoopingFlcPresenter::MxLoopingFlcPresenter()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b43b0
|
||||
MxLoopingFlcPresenter::~MxLoopingFlcPresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4410
|
||||
void MxLoopingFlcPresenter::Init()
|
||||
{
|
||||
this->m_unk0x68 = 0;
|
||||
this->m_flags &= ~Flag_Bit2;
|
||||
this->m_flags &= ~Flag_Bit3;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4430
|
||||
void MxLoopingFlcPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
Init();
|
||||
m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxFlcPresenter::Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4470
|
||||
void MxLoopingFlcPresenter::NextFrame()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk->GetFlags() & MxDSChunk::Flag_End) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Repeating;
|
||||
}
|
||||
else {
|
||||
LoadFrame(chunk);
|
||||
AppendChunk(chunk);
|
||||
m_unk0x68 += m_flicHeader->speed;
|
||||
}
|
||||
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
}
|
||||
131
LEGO1/omni/src/video/mxloopingsmkpresenter.cpp
Normal file
131
LEGO1/omni/src/video/mxloopingsmkpresenter.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
#include "mxloopingsmkpresenter.h"
|
||||
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdsmediaaction.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxLoopingSmkPresenter, 0x724);
|
||||
|
||||
// FUNCTION: LEGO1 0x100b48b0
|
||||
MxLoopingSmkPresenter::MxLoopingSmkPresenter()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4950
|
||||
MxLoopingSmkPresenter::~MxLoopingSmkPresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b49b0
|
||||
void MxLoopingSmkPresenter::Init()
|
||||
{
|
||||
this->m_elapsedDuration = 0;
|
||||
this->m_flags &= ~Flag_Bit2;
|
||||
this->m_flags &= ~Flag_Bit3;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b49d0
|
||||
void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
Init();
|
||||
m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxSmkPresenter::Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4a00
|
||||
void MxLoopingSmkPresenter::VTable0x88()
|
||||
{
|
||||
if (m_mxSmack.m_smackTag.Frames == m_currentFrame) {
|
||||
m_currentFrame = 0;
|
||||
// TODO: struct incorrect, Palette at wrong offset?
|
||||
memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette));
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4a30
|
||||
void MxLoopingSmkPresenter::NextFrame()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk->GetFlags() & MxDSChunk::Flag_End) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Repeating;
|
||||
}
|
||||
else {
|
||||
LoadFrame(chunk);
|
||||
AppendChunk(chunk);
|
||||
m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
|
||||
}
|
||||
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4a90
|
||||
void MxLoopingSmkPresenter::VTable0x8c()
|
||||
{
|
||||
if (m_action->GetDuration() < m_elapsedDuration) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_unk5;
|
||||
}
|
||||
else {
|
||||
MxStreamChunk* chunk;
|
||||
m_cursor->Current(chunk);
|
||||
LoadFrame(chunk);
|
||||
m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4b00
|
||||
void MxLoopingSmkPresenter::RepeatingTickle()
|
||||
{
|
||||
for (MxS16 i = 0; i < m_unk0x5c; i++) {
|
||||
if (!m_cursor->HasMatch()) {
|
||||
MxStreamChunk* chunk;
|
||||
MxStreamChunkListCursor cursor(m_chunks);
|
||||
|
||||
cursor.Last(chunk);
|
||||
MxLong time = chunk->GetTime();
|
||||
|
||||
cursor.First(chunk);
|
||||
|
||||
time -= chunk->GetTime();
|
||||
time += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
|
||||
|
||||
cursor.Reset();
|
||||
while (cursor.Next(chunk))
|
||||
chunk->SetTime(chunk->GetTime() + time);
|
||||
|
||||
m_cursor->Next();
|
||||
}
|
||||
|
||||
MxStreamChunk* chunk;
|
||||
m_cursor->Current(chunk);
|
||||
|
||||
if (m_action->GetElapsedTime() < chunk->GetTime())
|
||||
break;
|
||||
|
||||
VTable0x8c();
|
||||
|
||||
m_cursor->Next(chunk);
|
||||
|
||||
if (m_currentTickleState != TickleState_Repeating)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4cd0
|
||||
MxResult MxLoopingSmkPresenter::AddToManager()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
return MxSmkPresenter::AddToManager();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4d40
|
||||
void MxLoopingSmkPresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
280
LEGO1/omni/src/video/mxpalette.cpp
Normal file
280
LEGO1/omni/src/video/mxpalette.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "mxpalette.h"
|
||||
|
||||
#include "mxomni.h"
|
||||
#include "mxvideomanager.h"
|
||||
|
||||
// GLOBAL: LEGO1 0x10102188
|
||||
PALETTEENTRY g_defaultPaletteEntries[256] = {
|
||||
{0u, 0u, 0u, 0u}, {128u, 0u, 0u, 0u}, {0u, 128u, 0u, 0u}, {128u, 128u, 0u, 0u},
|
||||
{0u, 0u, 128u, 0u}, {128u, 0u, 128u, 0u}, {0u, 128u, 128u, 0u}, {128u, 128u, 128u, 0u},
|
||||
{192u, 220u, 192u, 0u}, {166u, 202u, 240u, 0u}, {255u, 255u, 255u, 0u}, {250u, 250u, 250u, 0u},
|
||||
{239u, 239u, 239u, 0u}, {228u, 228u, 228u, 0u}, {217u, 217u, 217u, 0u}, {206u, 206u, 206u, 0u},
|
||||
{195u, 195u, 195u, 0u}, {185u, 185u, 185u, 0u}, {174u, 174u, 174u, 0u}, {163u, 163u, 163u, 0u},
|
||||
{152u, 152u, 152u, 0u}, {141u, 141u, 141u, 0u}, {130u, 130u, 130u, 0u}, {123u, 123u, 123u, 0u},
|
||||
{115u, 115u, 115u, 0u}, {108u, 108u, 108u, 0u}, {101u, 101u, 101u, 0u}, {93u, 93u, 93u, 0u},
|
||||
{86u, 86u, 86u, 0u}, {79u, 79u, 79u, 0u}, {71u, 71u, 71u, 0u}, {64u, 64u, 64u, 0u},
|
||||
{54u, 54u, 54u, 0u}, {43u, 43u, 43u, 0u}, {33u, 33u, 33u, 0u}, {22u, 22u, 22u, 0u},
|
||||
{12u, 12u, 12u, 0u}, {8u, 8u, 8u, 0u}, {4u, 4u, 4u, 0u}, {0u, 0u, 0u, 0u},
|
||||
{225u, 218u, 217u, 0u}, {195u, 182u, 179u, 0u}, {165u, 145u, 141u, 0u}, {134u, 108u, 102u, 0u},
|
||||
{104u, 72u, 64u, 0u}, {74u, 35u, 26u, 0u}, {59u, 28u, 21u, 0u}, {44u, 21u, 16u, 0u},
|
||||
{30u, 14u, 10u, 0u}, {15u, 7u, 5u, 0u}, {250u, 231u, 232u, 0u}, {240u, 185u, 189u, 0u},
|
||||
{233u, 154u, 160u, 0u}, {226u, 124u, 131u, 0u}, {219u, 93u, 102u, 0u}, {213u, 62u, 73u, 0u},
|
||||
{203u, 18u, 32u, 0u}, {172u, 15u, 27u, 0u}, {159u, 14u, 25u, 0u}, {146u, 13u, 23u, 0u},
|
||||
{133u, 12u, 21u, 0u}, {120u, 11u, 19u, 0u}, {107u, 10u, 17u, 0u}, {94u, 8u, 15u, 0u},
|
||||
{81u, 7u, 13u, 0u}, {68u, 6u, 11u, 0u}, {55u, 5u, 9u, 0u}, {42u, 4u, 7u, 0u},
|
||||
{29u, 3u, 5u, 0u}, {10u, 1u, 2u, 0u}, {227u, 236u, 242u, 0u}, {178u, 203u, 220u, 0u},
|
||||
{145u, 181u, 205u, 0u}, {112u, 159u, 191u, 0u}, {79u, 137u, 176u, 0u}, {30u, 104u, 154u, 0u},
|
||||
{0u, 84u, 140u, 0u}, {0u, 79u, 132u, 0u}, {0u, 72u, 119u, 0u}, {0u, 66u, 110u, 0u},
|
||||
{0u, 61u, 101u, 0u}, {0u, 55u, 92u, 0u}, {0u, 47u, 78u, 0u}, {0u, 39u, 65u, 0u},
|
||||
{0u, 34u, 56u, 0u}, {0u, 28u, 47u, 0u}, {0u, 23u, 38u, 0u}, {0u, 18u, 29u, 0u},
|
||||
{0u, 12u, 20u, 0u}, {0u, 4u, 7u, 0u}, {230u, 242u, 234u, 0u}, {180u, 215u, 193u, 0u},
|
||||
{147u, 198u, 166u, 0u}, {113u, 180u, 138u, 0u}, {80u, 162u, 111u, 0u}, {30u, 136u, 70u, 0u},
|
||||
{0u, 120u, 45u, 0u}, {0u, 114u, 43u, 0u}, {0u, 102u, 38u, 0u}, {0u, 95u, 35u, 0u},
|
||||
{0u, 83u, 31u, 0u}, {0u, 72u, 27u, 0u}, {0u, 63u, 24u, 0u}, {0u, 56u, 21u, 0u},
|
||||
{0u, 48u, 18u, 0u}, {0u, 36u, 14u, 0u}, {0u, 25u, 9u, 0u}, {0u, 17u, 6u, 0u},
|
||||
{0u, 9u, 3u, 0u}, {0u, 1u, 1u, 0u}, {254u, 244u, 220u, 0u}, {255u, 239u, 181u, 0u},
|
||||
{255u, 231u, 156u, 0u}, {255u, 222u, 132u, 0u}, {255u, 222u, 115u, 0u}, {255u, 214u, 99u, 0u},
|
||||
{255u, 206u, 66u, 0u}, {255u, 198u, 41u, 0u}, {255u, 185u, 0u, 0u}, {255u, 189u, 8u, 0u},
|
||||
{247u, 181u, 0u, 0u}, {222u, 156u, 0u, 0u}, {189u, 140u, 0u, 0u}, {173u, 123u, 0u, 0u},
|
||||
{148u, 107u, 0u, 0u}, {132u, 90u, 0u, 0u}, {107u, 74u, 0u, 0u}, {74u, 49u, 0u, 0u},
|
||||
{57u, 41u, 0u, 0u}, {33u, 24u, 0u, 0u}, {117u, 52u, 87u, 0u}, {176u, 158u, 50u, 0u},
|
||||
{122u, 165u, 29u, 0u}, {242u, 142u, 8u, 0u}, {164u, 43u, 36u, 0u}, {113u, 67u, 20u, 0u},
|
||||
{255u, 0u, 255u, 0u}, {255u, 0u, 255u, 0u}, {255u, 0u, 255u, 0u}, {255u, 0u, 255u, 0u},
|
||||
{255u, 0u, 255u, 0u}, {57u, 163u, 217u, 0u}, {255u, 255u, 255u, 0u}, {254u, 255u, 247u, 0u},
|
||||
{253u, 253u, 239u, 0u}, {248u, 247u, 247u, 0u}, {248u, 247u, 231u, 0u}, {240u, 240u, 240u, 0u},
|
||||
{239u, 239u, 218u, 0u}, {227u, 232u, 236u, 0u}, {224u, 221u, 209u, 0u}, {215u, 222u, 215u, 0u},
|
||||
{213u, 214u, 215u, 0u}, {214u, 214u, 203u, 0u}, {255u, 219u, 57u, 0u}, {206u, 206u, 206u, 0u},
|
||||
{206u, 206u, 198u, 0u}, {255u, 214u, 18u, 0u}, {207u, 203u, 186u, 0u}, {197u, 199u, 199u, 0u},
|
||||
{255u, 206u, 0u, 0u}, {207u, 198u, 159u, 0u}, {247u, 204u, 0u, 0u}, {189u, 198u, 189u, 0u},
|
||||
{189u, 189u, 189u, 0u}, {238u, 199u, 0u, 0u}, {189u, 189u, 181u, 0u}, {238u, 190u, 24u, 0u},
|
||||
{181u, 189u, 184u, 0u}, {161u, 186u, 224u, 0u}, {181u, 181u, 181u, 0u}, {231u, 189u, 0u, 0u},
|
||||
{173u, 182u, 173u, 0u}, {222u, 181u, 0u, 0u}, {173u, 173u, 173u, 0u}, {213u, 182u, 0u, 0u},
|
||||
{172u, 173u, 160u, 0u}, {214u, 173u, 0u, 0u}, {165u, 165u, 165u, 0u}, {206u, 173u, 0u, 0u},
|
||||
{160u, 168u, 151u, 0u}, {206u, 164u, 0u, 0u}, {198u, 165u, 0u, 0u}, {157u, 156u, 156u, 0u},
|
||||
{134u, 156u, 200u, 0u}, {153u, 156u, 144u, 0u}, {142u, 156u, 161u, 0u}, {189u, 156u, 0u, 0u},
|
||||
{148u, 148u, 148u, 0u}, {146u, 148u, 138u, 0u}, {133u, 143u, 161u, 0u}, {189u, 143u, 0u, 0u},
|
||||
{140u, 140u, 140u, 0u}, {177u, 147u, 0u, 0u}, {131u, 140u, 136u, 0u}, {146u, 130u, 126u, 0u},
|
||||
{170u, 137u, 0u, 0u}, {132u, 132u, 130u, 0u}, {123u, 125u, 125u, 0u}, {123u, 123u, 133u, 0u},
|
||||
{153u, 126u, 0u, 0u}, {114u, 116u, 118u, 0u}, {110u, 112u, 108u, 0u}, {97u, 109u, 136u, 0u},
|
||||
{127u, 108u, 6u, 0u}, {0u, 173u, 0u, 0u}, {100u, 99u, 101u, 0u}, {176u, 71u, 41u, 0u},
|
||||
{36u, 142u, 33u, 0u}, {98u, 91u, 75u, 0u}, {80u, 88u, 104u, 0u}, {252u, 0u, 0u, 0u},
|
||||
{78u, 71u, 73u, 0u}, {73u, 71u, 78u, 0u}, {62u, 63u, 61u, 0u}, {0u, 66u, 211u, 0u},
|
||||
{99u, 51u, 14u, 0u}, {198u, 0u, 0u, 0u}, {189u, 0u, 0u, 0u}, {0u, 57u, 206u, 0u},
|
||||
{181u, 0u, 0u, 0u}, {0u, 56u, 185u, 0u}, {173u, 0u, 0u, 0u}, {165u, 0u, 0u, 0u},
|
||||
{49u, 49u, 49u, 0u}, {0u, 49u, 165u, 0u}, {156u, 0u, 0u, 0u}, {42u, 45u, 60u, 0u},
|
||||
{148u, 0u, 0u, 0u}, {140u, 0u, 0u, 0u}, {41u, 41u, 41u, 0u}, {0u, 41u, 144u, 0u},
|
||||
{132u, 0u, 0u, 0u}, {123u, 0u, 0u, 0u}, {7u, 35u, 114u, 0u}, {34u, 36u, 32u, 0u},
|
||||
{115u, 0u, 0u, 0u}, {107u, 0u, 0u, 0u}, {90u, 0u, 0u, 0u}, {23u, 24u, 27u, 0u},
|
||||
{74u, 0u, 0u, 0u}, {15u, 15u, 16u, 0u}, {49u, 0u, 0u, 0u}, {16u, 12u, 4u, 0u},
|
||||
{7u, 8u, 8u, 0u}, {0u, 0u, 8u, 0u}, {255u, 251u, 240u, 0u}, {160u, 160u, 164u, 0u},
|
||||
{128u, 128u, 128u, 0u}, {255u, 0u, 0u, 0u}, {0u, 255u, 0u, 0u}, {255u, 255u, 0u, 0u},
|
||||
{0u, 0u, 255u, 0u}, {255u, 0u, 255u, 0u}, {0u, 255u, 255u, 0u}, {255u, 255u, 255u, 0u}
|
||||
};
|
||||
|
||||
// FUNCTION: LEGO1 0x100bee30
|
||||
MxPalette::MxPalette()
|
||||
{
|
||||
this->m_overrideSkyColor = FALSE;
|
||||
this->m_palette = NULL;
|
||||
GetDefaultPalette(this->m_entries);
|
||||
this->m_skyColor = this->m_entries[141];
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100beed0
|
||||
MxPalette::MxPalette(const RGBQUAD* p_colors)
|
||||
{
|
||||
this->m_overrideSkyColor = FALSE;
|
||||
this->m_palette = NULL;
|
||||
ApplySystemEntriesToPalette(this->m_entries);
|
||||
|
||||
for (MxS32 i = 10; i < 246; i++) {
|
||||
this->m_entries[i].peRed = p_colors[i].rgbRed;
|
||||
this->m_entries[i].peGreen = p_colors[i].rgbGreen;
|
||||
this->m_entries[i].peBlue = p_colors[i].rgbBlue;
|
||||
this->m_entries[i].peFlags = 0;
|
||||
}
|
||||
|
||||
this->m_skyColor = this->m_entries[141];
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bef90
|
||||
MxPalette::~MxPalette()
|
||||
{
|
||||
if (m_palette) {
|
||||
m_palette->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf000
|
||||
LPDIRECTDRAWPALETTE MxPalette::CreateNativePalette()
|
||||
{
|
||||
MxS32 i;
|
||||
if (this->m_palette == NULL) {
|
||||
for (i = 0; i < 10; i++)
|
||||
this->m_entries[i].peFlags = 0x80;
|
||||
for (i = 10; i < 136; i++)
|
||||
this->m_entries[i].peFlags = 0x44;
|
||||
for (i = 136; i < 140; i++)
|
||||
this->m_entries[i].peFlags = 0x84;
|
||||
this->m_entries[140].peFlags = 0x84;
|
||||
this->m_entries[141].peFlags = 0x44;
|
||||
for (i = 142; i < 246; i++)
|
||||
this->m_entries[i].peFlags = 0x84;
|
||||
for (i = 246; i < 256; i++)
|
||||
this->m_entries[i].peFlags = 0x80;
|
||||
|
||||
if (MVideoManager() && MVideoManager()->GetDirectDraw()) {
|
||||
MVideoManager()->GetDirectDraw()->CreatePalette(4, this->m_entries, &this->m_palette, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return this->m_palette;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf0b0
|
||||
MxPalette* MxPalette::Clone()
|
||||
{
|
||||
MxPalette* result = new MxPalette;
|
||||
this->GetEntries(result->m_entries);
|
||||
result->m_overrideSkyColor = this->m_overrideSkyColor;
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf150
|
||||
MxResult MxPalette::GetEntries(LPPALETTEENTRY p_entries)
|
||||
{
|
||||
memcpy(p_entries, this->m_entries, sizeof(this->m_entries));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf170
|
||||
MxResult MxPalette::SetEntries(LPPALETTEENTRY p_entries)
|
||||
{
|
||||
MxS32 i;
|
||||
MxResult status = SUCCESS;
|
||||
|
||||
if (this->m_palette) {
|
||||
for (i = 0; i < 10; i++)
|
||||
this->m_entries[i].peFlags = 0x80;
|
||||
for (i = 10; i < 136; i++) {
|
||||
this->m_entries[i].peFlags = 68;
|
||||
this->m_entries[i].peRed = p_entries[i].peRed;
|
||||
this->m_entries[i].peGreen = p_entries[i].peGreen;
|
||||
this->m_entries[i].peBlue = p_entries[i].peBlue;
|
||||
}
|
||||
for (i = 136; i < 140; i++) {
|
||||
this->m_entries[i].peFlags = 132;
|
||||
this->m_entries[i].peRed = p_entries[i].peRed;
|
||||
this->m_entries[i].peGreen = p_entries[i].peGreen;
|
||||
this->m_entries[i].peBlue = p_entries[i].peBlue;
|
||||
}
|
||||
if (!this->m_overrideSkyColor) {
|
||||
this->m_entries[140].peFlags = 0x44;
|
||||
this->m_entries[140].peRed = p_entries[140].peRed;
|
||||
this->m_entries[140].peGreen = p_entries[140].peGreen;
|
||||
this->m_entries[140].peBlue = p_entries[140].peBlue;
|
||||
this->m_entries[141].peFlags = 0x84;
|
||||
this->m_entries[141].peRed = p_entries[141].peRed;
|
||||
this->m_entries[141].peGreen = p_entries[141].peGreen;
|
||||
this->m_entries[141].peBlue = p_entries[141].peBlue;
|
||||
}
|
||||
|
||||
for (i = 142; i < 246; i++) {
|
||||
this->m_entries[i].peFlags = 132;
|
||||
this->m_entries[i].peRed = p_entries[i].peRed;
|
||||
this->m_entries[i].peGreen = p_entries[i].peGreen;
|
||||
this->m_entries[i].peBlue = p_entries[i].peBlue;
|
||||
}
|
||||
|
||||
for (i = 246; i < 256; i++)
|
||||
this->m_entries[i].peFlags = 0x80;
|
||||
|
||||
if (this->m_palette->SetEntries(0, 0, 256, this->m_entries))
|
||||
status = FAILURE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf2d0
|
||||
MxResult MxPalette::SetSkyColor(LPPALETTEENTRY p_skyColor)
|
||||
{
|
||||
MxResult status = 0;
|
||||
if (this->m_palette != NULL) {
|
||||
this->m_entries[141].peRed = p_skyColor->peRed;
|
||||
this->m_entries[141].peGreen = p_skyColor->peGreen;
|
||||
this->m_entries[141].peBlue = p_skyColor->peBlue;
|
||||
this->m_skyColor = this->m_entries[141];
|
||||
if (this->m_palette->SetEntries(0, 141, 1, &this->m_skyColor)) {
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf330
|
||||
void MxPalette::Detach()
|
||||
{
|
||||
this->m_palette = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf340
|
||||
MxBool MxPalette::operator==(MxPalette& p_other)
|
||||
{
|
||||
for (MxS32 i = 0; i < 256; i++) {
|
||||
if (this->m_entries[i].peRed != p_other.m_entries[i].peRed)
|
||||
return FALSE;
|
||||
if (this->m_entries[i].peGreen != p_other.m_entries[i].peGreen)
|
||||
return FALSE;
|
||||
if (this->m_entries[i].peBlue != p_other.m_entries[i].peBlue)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf390
|
||||
void MxPalette::ApplySystemEntriesToPalette(LPPALETTEENTRY p_entries)
|
||||
{
|
||||
HDC hdc;
|
||||
|
||||
hdc = GetDC(0);
|
||||
if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) != 0 && GetDeviceCaps(hdc, SIZEPALETTE) == 256) {
|
||||
GetSystemPaletteEntries(hdc, 0, 10, p_entries);
|
||||
GetSystemPaletteEntries(hdc, 246, 10, &p_entries[246]);
|
||||
}
|
||||
else {
|
||||
memcpy(p_entries, g_defaultPaletteEntries, sizeof(PALETTEENTRY) * 10);
|
||||
memcpy(&p_entries[246], &g_defaultPaletteEntries[246], sizeof(PALETTEENTRY) * 10);
|
||||
}
|
||||
ReleaseDC(0, hdc);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf420
|
||||
void MxPalette::GetDefaultPalette(LPPALETTEENTRY p_entries)
|
||||
{
|
||||
HDC hdc;
|
||||
|
||||
hdc = GetDC(0);
|
||||
if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) != 0 && GetDeviceCaps(hdc, SIZEPALETTE) == 256) {
|
||||
GetSystemPaletteEntries(hdc, 0, 256, p_entries);
|
||||
memcpy(&p_entries[10], &g_defaultPaletteEntries[10], sizeof(PALETTEENTRY) * 236);
|
||||
}
|
||||
else {
|
||||
memcpy(p_entries, g_defaultPaletteEntries, sizeof(PALETTEENTRY) * 256);
|
||||
}
|
||||
|
||||
ReleaseDC(0, hdc);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bf490
|
||||
void MxPalette::Reset(MxBool p_ignoreSkyColor)
|
||||
{
|
||||
if (this->m_palette != NULL) {
|
||||
GetDefaultPalette(this->m_entries);
|
||||
if (!p_ignoreSkyColor) {
|
||||
this->m_entries[140] = this->m_entries[141] = this->m_skyColor;
|
||||
}
|
||||
SetEntries(this->m_entries);
|
||||
this->m_palette->SetEntries(0, 0, 256, this->m_entries);
|
||||
}
|
||||
}
|
||||
197
LEGO1/omni/src/video/mxregion.cpp
Normal file
197
LEGO1/omni/src/video/mxregion.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
#include "mxregion.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxRegion, 0x1c);
|
||||
DECOMP_SIZE_ASSERT(MxRegionTopBottom, 0x0c);
|
||||
DECOMP_SIZE_ASSERT(MxRegionLeftRight, 0x08);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c31c0
|
||||
MxRegion::MxRegion()
|
||||
{
|
||||
m_list = new MxRegionTopBottomList;
|
||||
m_rect = MxRect32(INT_MAX, INT_MAX, -1, -1);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3660
|
||||
MxBool MxRegion::VTable0x20()
|
||||
{
|
||||
return m_list->GetCount() == 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3690
|
||||
MxRegion::~MxRegion()
|
||||
{
|
||||
if (m_list)
|
||||
delete m_list;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3700
|
||||
void MxRegion::Reset()
|
||||
{
|
||||
m_list->DeleteAll();
|
||||
m_rect = MxRect32(INT_MAX, INT_MAX, -1, -1);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3750
|
||||
void MxRegion::VTable0x18(MxRect32& p_rect)
|
||||
{
|
||||
MxRect32 rect(p_rect);
|
||||
MxRect32 newRect;
|
||||
MxRegionTopBottomListCursor cursor(m_list);
|
||||
MxRegionTopBottom* topBottom;
|
||||
|
||||
while (rect.IsValid() && cursor.Next(topBottom)) {
|
||||
if (topBottom->GetTop() >= rect.GetBottom()) {
|
||||
MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(rect);
|
||||
cursor.Prepend(newTopBottom);
|
||||
rect.SetTop(rect.GetBottom());
|
||||
}
|
||||
else if (rect.GetTop() < topBottom->GetBottom()) {
|
||||
if (rect.GetTop() < topBottom->GetTop()) {
|
||||
newRect = rect;
|
||||
newRect.SetBottom(topBottom->GetTop());
|
||||
MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(newRect);
|
||||
cursor.Prepend(newTopBottom);
|
||||
rect.SetTop(topBottom->GetTop());
|
||||
}
|
||||
else if (topBottom->GetTop() < rect.GetTop()) {
|
||||
MxRegionTopBottom* newTopBottom = topBottom->Clone();
|
||||
newTopBottom->SetBottom(rect.GetTop());
|
||||
topBottom->SetTop(rect.GetTop());
|
||||
cursor.Prepend(newTopBottom);
|
||||
}
|
||||
|
||||
if (rect.GetBottom() < topBottom->GetBottom()) {
|
||||
MxRegionTopBottom* newTopBottom = topBottom->Clone();
|
||||
newTopBottom->SetBottom(rect.GetBottom());
|
||||
topBottom->SetTop(rect.GetBottom());
|
||||
newTopBottom->FUN_100c5280(rect.GetLeft(), rect.GetRight());
|
||||
cursor.Prepend(newTopBottom);
|
||||
rect.SetTop(rect.GetBottom());
|
||||
}
|
||||
else {
|
||||
topBottom->FUN_100c5280(rect.GetLeft(), rect.GetRight());
|
||||
rect.SetTop(topBottom->GetBottom());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rect.IsValid()) {
|
||||
MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(rect);
|
||||
m_list->Append(newTopBottom);
|
||||
}
|
||||
|
||||
m_rect.UpdateBounds(p_rect);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3e20
|
||||
MxBool MxRegion::VTable0x1c(MxRect32& p_rect)
|
||||
{
|
||||
if (!m_rect.IntersectsWith(p_rect))
|
||||
return FALSE;
|
||||
|
||||
MxRegionTopBottomListCursor cursor(m_list);
|
||||
MxRegionTopBottom* topBottom;
|
||||
|
||||
while (cursor.Next(topBottom)) {
|
||||
if (topBottom->GetTop() >= p_rect.GetBottom())
|
||||
return FALSE;
|
||||
if (topBottom->GetBottom() > p_rect.GetTop() && topBottom->FUN_100c57b0(p_rect))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4c90
|
||||
MxRegionTopBottom::MxRegionTopBottom(MxS32 p_top, MxS32 p_bottom)
|
||||
{
|
||||
m_top = p_top;
|
||||
m_bottom = p_bottom;
|
||||
m_leftRightList = new MxRegionLeftRightList;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c50e0
|
||||
MxRegionTopBottom::MxRegionTopBottom(MxRect32& p_rect)
|
||||
{
|
||||
m_top = p_rect.GetTop();
|
||||
m_bottom = p_rect.GetBottom();
|
||||
m_leftRightList = new MxRegionLeftRightList;
|
||||
|
||||
MxRegionLeftRight* leftRight = new MxRegionLeftRight(p_rect.GetLeft(), p_rect.GetRight());
|
||||
m_leftRightList->Append(leftRight);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c5280
|
||||
void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right)
|
||||
{
|
||||
MxRegionLeftRightListCursor a(m_leftRightList);
|
||||
MxRegionLeftRightListCursor b(m_leftRightList);
|
||||
|
||||
MxRegionLeftRight* leftRight;
|
||||
while (a.Next(leftRight) && leftRight->GetRight() < p_left)
|
||||
;
|
||||
|
||||
if (!a.HasMatch()) {
|
||||
MxRegionLeftRight* copy = new MxRegionLeftRight(p_left, p_right);
|
||||
m_leftRightList->Append(copy);
|
||||
}
|
||||
else {
|
||||
if (p_left > leftRight->GetLeft())
|
||||
p_left = leftRight->GetLeft();
|
||||
|
||||
while (leftRight->GetLeft() < p_right) {
|
||||
if (p_right < leftRight->GetRight())
|
||||
p_right = leftRight->GetRight();
|
||||
|
||||
b = a;
|
||||
b.Next();
|
||||
a.Destroy();
|
||||
|
||||
if (!b.Current(leftRight))
|
||||
break;
|
||||
|
||||
a = b;
|
||||
}
|
||||
|
||||
if (a.HasMatch()) {
|
||||
MxRegionLeftRight* copy = new MxRegionLeftRight(p_left, p_right);
|
||||
a.Prepend(copy);
|
||||
}
|
||||
else {
|
||||
MxRegionLeftRight* copy = new MxRegionLeftRight(p_left, p_right);
|
||||
m_leftRightList->Append(copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c55d0
|
||||
MxRegionTopBottom* MxRegionTopBottom::Clone()
|
||||
{
|
||||
MxRegionTopBottom* clone = new MxRegionTopBottom(m_top, m_bottom);
|
||||
|
||||
MxRegionLeftRightListCursor cursor(m_leftRightList);
|
||||
MxRegionLeftRight* leftRight;
|
||||
|
||||
while (cursor.Next(leftRight))
|
||||
clone->m_leftRightList->Append(leftRight->Clone());
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c57b0
|
||||
MxBool MxRegionTopBottom::FUN_100c57b0(MxRect32& p_rect)
|
||||
{
|
||||
MxRegionLeftRightListCursor cursor(m_leftRightList);
|
||||
MxRegionLeftRight* leftRight;
|
||||
|
||||
while (cursor.Next(leftRight)) {
|
||||
if (p_rect.GetRight() <= leftRight->GetLeft())
|
||||
return FALSE;
|
||||
if (leftRight->GetRight() > p_rect.GetLeft())
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
284
LEGO1/omni/src/video/mxregioncursor.cpp
Normal file
284
LEGO1/omni/src/video/mxregioncursor.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
#include "mxregioncursor.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxRegionCursor, 0x18);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c3f70
|
||||
MxRegionCursor::MxRegionCursor(MxRegion* p_region)
|
||||
{
|
||||
m_region = p_region;
|
||||
m_rect = NULL;
|
||||
m_topBottomCursor = new MxRegionTopBottomListCursor(m_region->m_list);
|
||||
m_leftRightCursor = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c40b0
|
||||
MxRegionCursor::~MxRegionCursor()
|
||||
{
|
||||
if (m_rect)
|
||||
delete m_rect;
|
||||
|
||||
if (m_topBottomCursor)
|
||||
delete m_topBottomCursor;
|
||||
|
||||
if (m_leftRightCursor)
|
||||
delete m_leftRightCursor;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4140
|
||||
MxRect32* MxRegionCursor::VTable0x18()
|
||||
{
|
||||
m_topBottomCursor->Head();
|
||||
|
||||
MxRegionTopBottom* topBottom;
|
||||
if (m_topBottomCursor->Current(topBottom)) {
|
||||
FUN_100c46c0(*topBottom->m_leftRightList);
|
||||
|
||||
MxRegionLeftRight* leftRight;
|
||||
m_leftRightCursor->First(leftRight);
|
||||
|
||||
UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom());
|
||||
}
|
||||
else
|
||||
Reset();
|
||||
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c41d0
|
||||
MxRect32* MxRegionCursor::VTable0x20()
|
||||
{
|
||||
m_topBottomCursor->Tail();
|
||||
|
||||
MxRegionTopBottom* topBottom;
|
||||
if (m_topBottomCursor->Current(topBottom)) {
|
||||
FUN_100c46c0(*topBottom->m_leftRightList);
|
||||
|
||||
MxRegionLeftRight* leftRight;
|
||||
m_leftRightCursor->Last(leftRight);
|
||||
|
||||
UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom());
|
||||
}
|
||||
else
|
||||
Reset();
|
||||
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4260
|
||||
MxRect32* MxRegionCursor::VTable0x28()
|
||||
{
|
||||
MxRegionLeftRight* leftRight;
|
||||
MxRegionTopBottom* topBottom;
|
||||
|
||||
if (m_leftRightCursor && m_leftRightCursor->Next(leftRight)) {
|
||||
m_topBottomCursor->Current(topBottom);
|
||||
|
||||
UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom());
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
if (m_topBottomCursor->Next(topBottom)) {
|
||||
FUN_100c46c0(*topBottom->m_leftRightList);
|
||||
m_leftRightCursor->First(leftRight);
|
||||
|
||||
UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom());
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
Reset();
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4360
|
||||
MxRect32* MxRegionCursor::VTable0x30()
|
||||
{
|
||||
MxRegionLeftRight* leftRight;
|
||||
MxRegionTopBottom* topBottom;
|
||||
|
||||
if (m_leftRightCursor && m_leftRightCursor->Prev(leftRight)) {
|
||||
m_topBottomCursor->Current(topBottom);
|
||||
|
||||
UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom());
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
if (m_topBottomCursor->Prev(topBottom)) {
|
||||
FUN_100c46c0(*topBottom->m_leftRightList);
|
||||
m_leftRightCursor->Last(leftRight);
|
||||
|
||||
UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom());
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
Reset();
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4460
|
||||
MxRect32* MxRegionCursor::VTable0x14(MxRect32& p_rect)
|
||||
{
|
||||
m_topBottomCursor->Reset();
|
||||
FUN_100c4a20(p_rect);
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4480
|
||||
MxRect32* MxRegionCursor::VTable0x1c(MxRect32& p_rect)
|
||||
{
|
||||
m_topBottomCursor->Reset();
|
||||
FUN_100c4b50(p_rect);
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c44a0
|
||||
MxRect32* MxRegionCursor::VTable0x24(MxRect32& p_rect)
|
||||
{
|
||||
MxRegionLeftRight* leftRight;
|
||||
|
||||
if (m_leftRightCursor && m_leftRightCursor->Next(leftRight)) {
|
||||
MxRegionTopBottom* topBottom;
|
||||
|
||||
m_topBottomCursor->Current(topBottom);
|
||||
|
||||
if (topBottom->IntersectsWith(p_rect) && leftRight->IntersectsWith(p_rect)) {
|
||||
UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom());
|
||||
m_rect->Intersect(p_rect);
|
||||
}
|
||||
else
|
||||
FUN_100c4a20(p_rect);
|
||||
}
|
||||
else
|
||||
FUN_100c4a20(p_rect);
|
||||
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4590
|
||||
MxRect32* MxRegionCursor::VTable0x2c(MxRect32& p_rect)
|
||||
{
|
||||
MxRegionLeftRight* leftRight;
|
||||
|
||||
if (m_leftRightCursor && m_leftRightCursor->Prev(leftRight)) {
|
||||
MxRegionTopBottom* topBottom;
|
||||
|
||||
m_topBottomCursor->Current(topBottom);
|
||||
|
||||
if (topBottom->IntersectsWith(p_rect) && leftRight->IntersectsWith(p_rect)) {
|
||||
UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom());
|
||||
m_rect->Intersect(p_rect);
|
||||
}
|
||||
else
|
||||
FUN_100c4b50(p_rect);
|
||||
}
|
||||
else
|
||||
FUN_100c4b50(p_rect);
|
||||
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4680
|
||||
void MxRegionCursor::Reset()
|
||||
{
|
||||
if (m_rect) {
|
||||
delete m_rect;
|
||||
m_rect = NULL;
|
||||
}
|
||||
|
||||
m_topBottomCursor->Reset();
|
||||
|
||||
if (m_leftRightCursor) {
|
||||
delete m_leftRightCursor;
|
||||
m_leftRightCursor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c46c0
|
||||
void MxRegionCursor::FUN_100c46c0(MxRegionLeftRightList& p_leftRightList)
|
||||
{
|
||||
if (m_leftRightCursor)
|
||||
delete m_leftRightCursor;
|
||||
|
||||
m_leftRightCursor = new MxRegionLeftRightListCursor(&p_leftRightList);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4980
|
||||
void MxRegionCursor::UpdateRect(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom)
|
||||
{
|
||||
if (!m_rect)
|
||||
m_rect = new MxRect32;
|
||||
|
||||
m_rect->SetLeft(p_left);
|
||||
m_rect->SetTop(p_top);
|
||||
m_rect->SetRight(p_right);
|
||||
m_rect->SetBottom(p_bottom);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4a20
|
||||
void MxRegionCursor::FUN_100c4a20(MxRect32& p_rect)
|
||||
{
|
||||
MxRegionTopBottom* topBottom;
|
||||
while (m_topBottomCursor->Next(topBottom)) {
|
||||
if (p_rect.GetBottom() <= topBottom->GetTop()) {
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_rect.GetTop() < topBottom->GetBottom()) {
|
||||
FUN_100c46c0(*topBottom->m_leftRightList);
|
||||
|
||||
MxRegionLeftRight* leftRight;
|
||||
while (m_leftRightCursor->Next(leftRight)) {
|
||||
if (p_rect.GetRight() <= leftRight->GetLeft())
|
||||
break;
|
||||
|
||||
if (p_rect.GetLeft() < leftRight->GetRight()) {
|
||||
UpdateRect(
|
||||
leftRight->GetLeft(),
|
||||
topBottom->GetTop(),
|
||||
leftRight->GetRight(),
|
||||
topBottom->GetBottom()
|
||||
);
|
||||
m_rect->Intersect(p_rect);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c4b50
|
||||
void MxRegionCursor::FUN_100c4b50(MxRect32& p_rect)
|
||||
{
|
||||
MxRegionTopBottom* topBottom;
|
||||
while (m_topBottomCursor->Prev(topBottom)) {
|
||||
if (topBottom->GetBottom() <= p_rect.GetTop()) {
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (topBottom->GetTop() < p_rect.GetBottom()) {
|
||||
FUN_100c46c0(*topBottom->m_leftRightList);
|
||||
|
||||
MxRegionLeftRight* leftRight;
|
||||
while (m_leftRightCursor->Prev(leftRight)) {
|
||||
if (leftRight->GetRight() <= p_rect.GetLeft())
|
||||
break;
|
||||
|
||||
if (leftRight->GetLeft() < p_rect.GetRight()) {
|
||||
UpdateRect(
|
||||
leftRight->GetLeft(),
|
||||
topBottom->GetTop(),
|
||||
leftRight->GetRight(),
|
||||
topBottom->GetBottom()
|
||||
);
|
||||
m_rect->Intersect(p_rect);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
252
LEGO1/omni/src/video/mxsmack.cpp
Normal file
252
LEGO1/omni/src/video/mxsmack.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
#include "mxsmack.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(SmackTag, 0x390);
|
||||
DECOMP_SIZE_ASSERT(MxSmack, 0x6b8);
|
||||
|
||||
// FUNCTION: LEGO1 0x100c5a90
|
||||
MxResult MxSmack::LoadHeader(MxU8* p_data, MxSmack* p_mxSmack)
|
||||
{
|
||||
// Macros for readability
|
||||
#define FRAME_COUNT(mxSmack) (p_mxSmack->m_smackTag.Frames + (p_mxSmack->m_smackTag.SmackerType & 1))
|
||||
|
||||
MxResult result = SUCCESS;
|
||||
MxU8* frameTypes = NULL;
|
||||
MxU8* huffmanTrees = NULL;
|
||||
|
||||
if (!p_data || !p_mxSmack) {
|
||||
result = FAILURE;
|
||||
}
|
||||
else {
|
||||
p_mxSmack->m_frameTypes = NULL;
|
||||
p_mxSmack->m_frameSizes = NULL;
|
||||
p_mxSmack->m_huffmanTrees = NULL;
|
||||
p_mxSmack->m_huffmanTables = NULL;
|
||||
|
||||
memcpy(&p_mxSmack->m_smackTag, p_data, SmackHeaderSize(&p_mxSmack->m_smackTag));
|
||||
p_data += SmackHeaderSize(&p_mxSmack->m_smackTag);
|
||||
|
||||
MxU32* frameSizes = new MxU32[FRAME_COUNT(p_mxSmack)];
|
||||
|
||||
if (!frameSizes) {
|
||||
result = FAILURE;
|
||||
}
|
||||
else {
|
||||
memcpy(frameSizes, p_data, FRAME_COUNT(p_mxSmack) * sizeof(MxU32));
|
||||
|
||||
p_data += FRAME_COUNT(p_mxSmack) * sizeof(MxU32);
|
||||
p_mxSmack->m_maxFrameSize = 0;
|
||||
|
||||
// TODO
|
||||
for (MxU32 i = 0; i < FRAME_COUNT(p_mxSmack); i++) {
|
||||
if (p_mxSmack->m_maxFrameSize < frameSizes[i])
|
||||
p_mxSmack->m_maxFrameSize = frameSizes[i];
|
||||
}
|
||||
|
||||
frameTypes = new MxU8[FRAME_COUNT(p_mxSmack)];
|
||||
|
||||
if (!frameTypes) {
|
||||
result = FAILURE;
|
||||
}
|
||||
else {
|
||||
memcpy(frameTypes, p_data, FRAME_COUNT(p_mxSmack));
|
||||
p_data += FRAME_COUNT(p_mxSmack);
|
||||
|
||||
MxU32 treeSize = p_mxSmack->m_smackTag.tablesize + 0x1000;
|
||||
if (treeSize <= 0x2000)
|
||||
treeSize = 0x2000;
|
||||
|
||||
huffmanTrees = new MxU8[treeSize];
|
||||
|
||||
if (!huffmanTrees) {
|
||||
result = FAILURE;
|
||||
}
|
||||
else {
|
||||
memcpy(huffmanTrees + 0x1000, p_data, p_mxSmack->m_smackTag.tablesize);
|
||||
|
||||
p_mxSmack->m_huffmanTables = new MxU8
|
||||
[p_mxSmack->m_smackTag.codesize + p_mxSmack->m_smackTag.absize +
|
||||
p_mxSmack->m_smackTag.detailsize + p_mxSmack->m_smackTag.typesize + SmackGetSizeTables()];
|
||||
|
||||
if (!p_mxSmack->m_huffmanTables) {
|
||||
result = FAILURE;
|
||||
}
|
||||
else {
|
||||
SmackDoTables(
|
||||
huffmanTrees,
|
||||
p_mxSmack->m_huffmanTables,
|
||||
p_mxSmack->m_smackTag.codesize,
|
||||
p_mxSmack->m_smackTag.absize,
|
||||
p_mxSmack->m_smackTag.detailsize,
|
||||
p_mxSmack->m_smackTag.typesize
|
||||
);
|
||||
|
||||
MxU32 size = SmackGetSizeDeltas(p_mxSmack->m_smackTag.Width, p_mxSmack->m_smackTag.Height) + 32;
|
||||
p_mxSmack->m_unk0x6b4 = new MxU8[size];
|
||||
memset(p_mxSmack->m_unk0x6b4, 0, size);
|
||||
|
||||
MxS32 width = p_mxSmack->m_smackTag.Width;
|
||||
MxU32* data = (MxU32*) p_mxSmack->m_unk0x6b4;
|
||||
|
||||
*data = 1;
|
||||
data++;
|
||||
*data = NULL; // MxU8* bitmapData
|
||||
data++;
|
||||
*data = p_mxSmack->m_smackTag.Width / 4;
|
||||
data++;
|
||||
*data = p_mxSmack->m_smackTag.Height / 4;
|
||||
data++;
|
||||
*data = width - 4;
|
||||
data++;
|
||||
*data = width * 3;
|
||||
data++;
|
||||
*data = width;
|
||||
data++;
|
||||
*data = width * 4 - p_mxSmack->m_smackTag.Width;
|
||||
data++;
|
||||
data++;
|
||||
*data = p_mxSmack->m_smackTag.Width;
|
||||
data++;
|
||||
*data = p_mxSmack->m_smackTag.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p_mxSmack->m_frameTypes = frameTypes;
|
||||
p_mxSmack->m_frameSizes = frameSizes;
|
||||
p_mxSmack->m_huffmanTrees = huffmanTrees;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
#undef FRAME_COUNT
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c5d40
|
||||
void MxSmack::Destroy(MxSmack* p_mxSmack)
|
||||
{
|
||||
if (p_mxSmack->m_frameSizes)
|
||||
delete[] p_mxSmack->m_frameSizes;
|
||||
if (p_mxSmack->m_frameTypes)
|
||||
delete[] p_mxSmack->m_frameTypes;
|
||||
if (p_mxSmack->m_huffmanTrees)
|
||||
delete[] p_mxSmack->m_huffmanTrees;
|
||||
if (p_mxSmack->m_huffmanTables)
|
||||
delete[] p_mxSmack->m_huffmanTables;
|
||||
if (p_mxSmack->m_unk0x6b4)
|
||||
delete[] p_mxSmack->m_unk0x6b4;
|
||||
}
|
||||
|
||||
// This should be refactored to somewhere else
|
||||
inline MxLong AbsFlipped(MxLong p_value)
|
||||
{
|
||||
return p_value > 0 ? p_value : -p_value;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c5db0
|
||||
MxResult MxSmack::LoadFrame(
|
||||
MxBITMAPINFO* p_bitmapInfo,
|
||||
MxU8* p_bitmapData,
|
||||
MxSmack* p_mxSmack,
|
||||
MxU8* p_chunkData,
|
||||
MxBool p_paletteChanged,
|
||||
MxRectList* p_list
|
||||
)
|
||||
{
|
||||
p_bitmapInfo->m_bmiHeader.biHeight = -AbsFlipped(p_bitmapInfo->m_bmiHeader.biHeight);
|
||||
*(MxU8**) (p_mxSmack->m_unk0x6b4 + 4) = p_bitmapData;
|
||||
|
||||
// Reference: https://wiki.multimedia.cx/index.php/Smacker#Palette_Chunk
|
||||
if (p_paletteChanged) {
|
||||
MxU8 palette[772];
|
||||
|
||||
MxU8* intoChunk = p_chunkData + 1;
|
||||
MxU8* intoPalette = palette;
|
||||
MxU16 paletteIndex = 0;
|
||||
// TODO: struct incorrect, Palette at wrong offset?
|
||||
MxU8* currentPalette = &p_mxSmack->m_smackTag.Palette[4];
|
||||
|
||||
do {
|
||||
if (*intoChunk & 0x80) {
|
||||
MxU8 length = (*intoChunk & 0x7f) + 1;
|
||||
memcpy(intoPalette, ¤tPalette[paletteIndex * 3], length * 3);
|
||||
intoPalette += length * 3;
|
||||
paletteIndex += length;
|
||||
intoChunk++;
|
||||
}
|
||||
else {
|
||||
if (*intoChunk & 0x40) {
|
||||
MxU8 length = (*intoChunk & 0x3f) + 1;
|
||||
memcpy(intoPalette, ¤tPalette[*(intoChunk + 1) * 3], length * 3);
|
||||
intoPalette += length * 3;
|
||||
paletteIndex += length;
|
||||
intoChunk += 2;
|
||||
}
|
||||
else {
|
||||
*(MxU32*) intoPalette = *(MxU32*) intoChunk;
|
||||
intoPalette += 3;
|
||||
paletteIndex++;
|
||||
intoChunk += 3;
|
||||
}
|
||||
}
|
||||
} while (paletteIndex < 256);
|
||||
|
||||
for (MxU32 i = 0; i < 256; i++) {
|
||||
memcpy(currentPalette, &palette[i * 3], 3);
|
||||
currentPalette += 3;
|
||||
p_bitmapInfo->m_bmiColors[i].rgbBlue = palette[i * 3 + 2] * 4;
|
||||
p_bitmapInfo->m_bmiColors[i].rgbGreen = palette[i * 3 + 1] * 4;
|
||||
p_bitmapInfo->m_bmiColors[i].rgbRed = palette[i * 3] * 4;
|
||||
}
|
||||
|
||||
p_chunkData += *p_chunkData * 4;
|
||||
}
|
||||
|
||||
SmackDoFrameToBuffer(p_chunkData, p_mxSmack->m_huffmanTables, p_mxSmack->m_unk0x6b4);
|
||||
|
||||
MxU16 und = 1;
|
||||
u32 smackRect[4];
|
||||
MxRect32 rect;
|
||||
|
||||
while (GetRect(p_mxSmack->m_unk0x6b4, &und, smackRect, &rect)) {
|
||||
MxRect32* newRect = new MxRect32(rect);
|
||||
p_list->Append(newRect);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6050
|
||||
MxBool MxSmack::GetRect(MxU8* p_unk0x6b4, MxU16* p_und, u32* p_smackRect, MxRect32* p_rect)
|
||||
{
|
||||
u32 left, bottom, top, right;
|
||||
|
||||
if (!*p_und)
|
||||
return FALSE;
|
||||
|
||||
if (*p_und == 1) {
|
||||
if (!SmackGetRect(p_unk0x6b4, p_smackRect))
|
||||
return FALSE;
|
||||
*p_und = 2;
|
||||
}
|
||||
|
||||
left = p_smackRect[0];
|
||||
top = p_smackRect[1];
|
||||
right = p_smackRect[2] + p_smackRect[0];
|
||||
bottom = p_smackRect[3] + p_smackRect[1];
|
||||
|
||||
while (SmackGetRect(p_unk0x6b4, p_smackRect)) {
|
||||
if (left > p_smackRect[0])
|
||||
left = p_smackRect[0];
|
||||
if (right < p_smackRect[0] + p_smackRect[2])
|
||||
right = p_smackRect[0] + p_smackRect[2];
|
||||
|
||||
bottom = p_smackRect[1] + p_smackRect[3];
|
||||
}
|
||||
|
||||
*p_und = 0;
|
||||
*p_rect = MxRect32(left, top, right, bottom);
|
||||
return TRUE;
|
||||
}
|
||||
124
LEGO1/omni/src/video/mxsmkpresenter.cpp
Normal file
124
LEGO1/omni/src/video/mxsmkpresenter.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "mxsmkpresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "mxdsmediaaction.h"
|
||||
#include "mxvideomanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxSmkPresenter, 0x720);
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3650
|
||||
MxSmkPresenter::MxSmkPresenter()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3870
|
||||
MxSmkPresenter::~MxSmkPresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b38d0
|
||||
void MxSmkPresenter::Init()
|
||||
{
|
||||
m_currentFrame = 0;
|
||||
memset(&m_mxSmack, 0, sizeof(m_mxSmack));
|
||||
m_flags &= ~Flag_Bit2;
|
||||
m_flags &= ~Flag_Bit3;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3900
|
||||
void MxSmkPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
|
||||
MxSmack::Destroy(&m_mxSmack);
|
||||
Init();
|
||||
|
||||
m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor) {
|
||||
MxVideoPresenter::Destroy(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3940
|
||||
void MxSmkPresenter::LoadHeader(MxStreamChunk* p_chunk)
|
||||
{
|
||||
MxSmack::LoadHeader(p_chunk->GetData(), &m_mxSmack);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3960
|
||||
void MxSmkPresenter::CreateBitmap()
|
||||
{
|
||||
if (m_bitmap)
|
||||
delete m_bitmap;
|
||||
|
||||
m_bitmap = new MxBitmap;
|
||||
m_bitmap->SetSize(m_mxSmack.m_smackTag.Width, m_mxSmack.m_smackTag.Height, NULL, FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3a00
|
||||
void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
||||
{
|
||||
MxBITMAPINFO* bitmapInfo = m_bitmap->GetBitmapInfo();
|
||||
MxU8* bitmapData = m_bitmap->GetBitmapData();
|
||||
MxU8* chunkData = p_chunk->GetData();
|
||||
|
||||
MxBool paletteChanged = m_mxSmack.m_frameTypes[m_currentFrame] & 1;
|
||||
m_currentFrame++;
|
||||
VTable0x88();
|
||||
|
||||
MxRectList list(TRUE);
|
||||
MxSmack::LoadFrame(bitmapInfo, bitmapData, &m_mxSmack, chunkData, paletteChanged, &list);
|
||||
|
||||
if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && paletteChanged)
|
||||
RealizePalette();
|
||||
|
||||
MxRect32 invalidateRect;
|
||||
MxRectListCursor cursor(&list);
|
||||
MxRect32* rect;
|
||||
|
||||
while (cursor.Next(rect)) {
|
||||
invalidateRect = *rect;
|
||||
invalidateRect.AddPoint(GetLocation());
|
||||
MVideoManager()->InvalidateRect(invalidateRect);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4260
|
||||
void MxSmkPresenter::VTable0x88()
|
||||
{
|
||||
if ((m_mxSmack.m_smackTag.SmackerType & 1) != 0) {
|
||||
MxU32 und = (m_currentFrame % m_mxSmack.m_smackTag.Frames);
|
||||
if (1 < m_currentFrame && und == 1)
|
||||
m_currentFrame = 1;
|
||||
}
|
||||
else {
|
||||
if (m_mxSmack.m_smackTag.Frames == m_currentFrame) {
|
||||
m_currentFrame = 0;
|
||||
// TODO: struct incorrect, Palette at wrong offset?
|
||||
memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b42c0
|
||||
void MxSmkPresenter::RealizePalette()
|
||||
{
|
||||
MxPalette* palette = m_bitmap->CreatePalette();
|
||||
MVideoManager()->RealizePalette(palette);
|
||||
delete palette;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b42f0
|
||||
MxResult MxSmkPresenter::AddToManager()
|
||||
{
|
||||
return MxVideoPresenter::AddToManager();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b4300
|
||||
void MxSmkPresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
229
LEGO1/omni/src/video/mxstillpresenter.cpp
Normal file
229
LEGO1/omni/src/video/mxstillpresenter.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
#include "mxstillpresenter.h"
|
||||
|
||||
#include "decomp.h"
|
||||
#include "define.h"
|
||||
#include "legoomni.h"
|
||||
#include "mxcompositepresenter.h"
|
||||
#include "mxdsmediaaction.h"
|
||||
#include "mxomni.h"
|
||||
#include "mxvideomanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxStillPresenter, 0x6c);
|
||||
|
||||
// GLOBAL: LEGO1 0x10101eb0
|
||||
const char* g_strBmpIsmap = "BMP_ISMAP";
|
||||
|
||||
// FUNCTION: LEGO1 0x100435b0
|
||||
void MxStillPresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9c70
|
||||
void MxStillPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
|
||||
if (m_bitmapInfo)
|
||||
delete m_bitmapInfo;
|
||||
m_bitmapInfo = NULL;
|
||||
|
||||
m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxVideoPresenter::Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9cc0
|
||||
void MxStillPresenter::LoadHeader(MxStreamChunk* p_chunk)
|
||||
{
|
||||
if (m_bitmapInfo)
|
||||
delete m_bitmapInfo;
|
||||
|
||||
MxU8* data = new MxU8[p_chunk->GetLength()];
|
||||
m_bitmapInfo = (MxBITMAPINFO*) data;
|
||||
memcpy(m_bitmapInfo, p_chunk->GetData(), p_chunk->GetLength());
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9d10
|
||||
void MxStillPresenter::CreateBitmap()
|
||||
{
|
||||
if (m_bitmap)
|
||||
delete m_bitmap;
|
||||
|
||||
m_bitmap = new MxBitmap;
|
||||
m_bitmap->ImportBitmapInfo(m_bitmapInfo);
|
||||
|
||||
delete m_bitmapInfo;
|
||||
m_bitmapInfo = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9db0
|
||||
void MxStillPresenter::NextFrame()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
LoadFrame(chunk);
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9dd0
|
||||
void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
||||
{
|
||||
memcpy(m_bitmap->GetBitmapData(), p_chunk->GetData(), p_chunk->GetLength());
|
||||
|
||||
// MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight()));
|
||||
MxS32 height = GetHeight() - 1;
|
||||
MxS32 width = GetWidth() - 1;
|
||||
MxS32 x = m_location.GetX();
|
||||
MxS32 y = m_location.GetY();
|
||||
|
||||
MxRect32 rect(x, y, width + x, height + y);
|
||||
MVideoManager()->InvalidateRect(rect);
|
||||
|
||||
if (m_flags & Flag_Bit2) {
|
||||
undefined4 und = 0;
|
||||
m_unk0x58 = MxOmni::GetInstance()->GetVideoManager()->GetDisplaySurface()->VTable0x44(
|
||||
m_bitmap,
|
||||
&und,
|
||||
(m_flags & Flag_Bit4) / 8,
|
||||
m_action->GetFlags() & MxDSAction::Flag_Bit4
|
||||
);
|
||||
|
||||
delete m_alpha;
|
||||
m_alpha = new AlphaMask(*m_bitmap);
|
||||
|
||||
delete m_bitmap;
|
||||
m_bitmap = NULL;
|
||||
|
||||
if (m_unk0x58 && und)
|
||||
m_flags |= Flag_Bit3;
|
||||
else
|
||||
m_flags &= ~Flag_Bit3;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9f30
|
||||
void MxStillPresenter::RealizePalette()
|
||||
{
|
||||
MxPalette* palette = m_bitmap->CreatePalette();
|
||||
MVideoManager()->RealizePalette(palette);
|
||||
delete palette;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9f60
|
||||
void MxStillPresenter::StartingTickle()
|
||||
{
|
||||
MxVideoPresenter::StartingTickle();
|
||||
|
||||
if (m_currentTickleState == TickleState_Streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement())
|
||||
RealizePalette();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9f90
|
||||
void MxStillPresenter::StreamingTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = FUN_100b5650();
|
||||
|
||||
if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) {
|
||||
m_chunkTime = chunk->GetTime();
|
||||
NextFrame();
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Repeating;
|
||||
|
||||
if (m_action->GetDuration() == -1 && m_compositePresenter)
|
||||
m_compositePresenter->VTable0x60(this);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b9ff0
|
||||
void MxStillPresenter::RepeatingTickle()
|
||||
{
|
||||
if (m_action->GetDuration() != -1) {
|
||||
if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_unk5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba040
|
||||
void MxStillPresenter::VTable0x88(MxS32 p_x, MxS32 p_y)
|
||||
{
|
||||
MxS32 x = m_location.GetX();
|
||||
MxS32 y = m_location.GetY();
|
||||
m_location.SetX(p_x);
|
||||
m_location.SetY(p_y);
|
||||
|
||||
if (IsEnabled()) {
|
||||
// Most likely needs to work with MxSize32 and MxPoint32
|
||||
MxS32 height = GetHeight() - 1;
|
||||
MxS32 width = GetWidth() - 1;
|
||||
|
||||
MxRect32 rectA(x, y, width + x, height + y);
|
||||
MxRect32 rectB(m_location.GetX(), m_location.GetY(), width + m_location.GetX(), height + m_location.GetY());
|
||||
|
||||
MVideoManager()->InvalidateRect(rectA);
|
||||
MVideoManager()->VTable0x34(rectA.GetLeft(), rectA.GetTop(), rectA.GetWidth(), rectA.GetHeight());
|
||||
|
||||
MVideoManager()->InvalidateRect(rectB);
|
||||
MVideoManager()->VTable0x34(rectB.GetLeft(), rectB.GetTop(), rectB.GetWidth(), rectB.GetHeight());
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba140
|
||||
void MxStillPresenter::Enable(MxBool p_enable)
|
||||
{
|
||||
MxVideoPresenter::Enable(p_enable);
|
||||
|
||||
if (MVideoManager() && (m_alpha || m_bitmap)) {
|
||||
// MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight()));
|
||||
MxS32 height = GetHeight();
|
||||
MxS32 width = GetWidth();
|
||||
MxS32 x = m_location.GetX();
|
||||
MxS32 y = m_location.GetY();
|
||||
|
||||
MxRect32 rect(x, y, width + x, height + y);
|
||||
MVideoManager()->InvalidateRect(rect);
|
||||
MVideoManager()->VTable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100ba1e0
|
||||
void MxStillPresenter::ParseExtra()
|
||||
{
|
||||
MxPresenter::ParseExtra();
|
||||
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Bit5)
|
||||
m_flags |= Flag_Bit4;
|
||||
|
||||
MxU32 len = m_action->GetExtraLength();
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
len &= MAXWORD;
|
||||
|
||||
char buf[512];
|
||||
memcpy(buf, m_action->GetExtraData(), len);
|
||||
buf[len] = '\0';
|
||||
|
||||
char output[512];
|
||||
if (KeyValueStringParse(output, g_strVISIBILITY, buf)) {
|
||||
if (strcmpi(output, "FALSE") == 0) {
|
||||
Enable(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (KeyValueStringParse(output, g_strBmpIsmap, buf)) {
|
||||
m_flags |= Flag_Bit5;
|
||||
m_flags &= ~Flag_Bit2;
|
||||
m_flags &= ~Flag_Bit3;
|
||||
}
|
||||
}
|
||||
|
||||
// STUB: LEGO1 0x100ba2c0
|
||||
MxStillPresenter* MxStillPresenter::Clone()
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
607
LEGO1/omni/src/video/mxtransitionmanager.cpp
Normal file
607
LEGO1/omni/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()
|
||||
);
|
||||
}
|
||||
}
|
||||
317
LEGO1/omni/src/video/mxvideomanager.cpp
Normal file
317
LEGO1/omni/src/video/mxvideomanager.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
#include "mxvideomanager.h"
|
||||
|
||||
#include "legoomni.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxpresenter.h"
|
||||
#include "mxticklemanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxVideoManager, 0x64)
|
||||
|
||||
// FUNCTION: LEGO1 0x100be1f0
|
||||
MxVideoManager::MxVideoManager()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be270
|
||||
void MxVideoManager::VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height)
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be2a0
|
||||
MxVideoManager::~MxVideoManager()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be320
|
||||
MxResult MxVideoManager::Init()
|
||||
{
|
||||
this->m_pDirectDraw = NULL;
|
||||
this->m_pDirect3D = NULL;
|
||||
this->m_displaySurface = NULL;
|
||||
this->m_region = NULL;
|
||||
this->m_videoParam.SetPalette(NULL);
|
||||
this->m_unk0x60 = FALSE;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be340
|
||||
void MxVideoManager::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
if (m_thread) {
|
||||
m_thread->Terminate();
|
||||
delete m_thread;
|
||||
}
|
||||
else
|
||||
TickleManager()->UnregisterClient(this);
|
||||
|
||||
m_criticalSection.Enter();
|
||||
|
||||
if (m_displaySurface)
|
||||
delete m_displaySurface;
|
||||
|
||||
if (m_region)
|
||||
delete m_region;
|
||||
|
||||
if (m_videoParam.GetPalette())
|
||||
delete m_videoParam.GetPalette();
|
||||
|
||||
if (m_unk0x60) {
|
||||
if (m_pDirectDraw)
|
||||
m_pDirectDraw->Release();
|
||||
if (m_pDirect3D)
|
||||
m_pDirect3D->Release();
|
||||
}
|
||||
|
||||
Init();
|
||||
m_criticalSection.Leave();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxMediaManager::Destroy();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be3e0
|
||||
void MxVideoManager::UpdateRegion()
|
||||
{
|
||||
if (m_region->VTable0x20() == FALSE) {
|
||||
MxRect32 rect(m_region->GetRect());
|
||||
rect.Intersect(m_videoParam.GetRect());
|
||||
|
||||
m_displaySurface
|
||||
->Display(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be440
|
||||
void MxVideoManager::SortPresenterList()
|
||||
{
|
||||
if (this->m_presenters->GetCount() <= 1)
|
||||
return;
|
||||
|
||||
MxPresenterListCursor a(this->m_presenters);
|
||||
MxPresenterListCursor b(this->m_presenters);
|
||||
MxU32 count = this->m_presenters->GetCount() - 1;
|
||||
MxBool finished;
|
||||
|
||||
if (count != 0) {
|
||||
do {
|
||||
a.Reset();
|
||||
b.Head();
|
||||
|
||||
finished = TRUE;
|
||||
for (MxU32 i = count; i != 0; i--) {
|
||||
MxPresenter *presenterA, *presenterB;
|
||||
|
||||
a.Next(presenterA);
|
||||
b.Next(presenterB);
|
||||
|
||||
if (presenterA->GetDisplayZ() < presenterB->GetDisplayZ()) {
|
||||
a.SetValue(presenterB);
|
||||
b.SetValue(presenterA);
|
||||
finished = FALSE;
|
||||
}
|
||||
}
|
||||
} while (!finished && --count != 0);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be600
|
||||
MxResult MxVideoManager::VTable0x28(
|
||||
MxVideoParam& p_videoParam,
|
||||
LPDIRECTDRAW p_pDirectDraw,
|
||||
LPDIRECT3D2 p_pDirect3D,
|
||||
LPDIRECTDRAWSURFACE p_ddSurface1,
|
||||
LPDIRECTDRAWSURFACE p_ddSurface2,
|
||||
LPDIRECTDRAWCLIPPER p_ddClipper,
|
||||
MxU32 p_frequencyMS,
|
||||
MxBool p_createThread
|
||||
)
|
||||
{
|
||||
MxBool locked = FALSE;
|
||||
MxResult status = FAILURE;
|
||||
|
||||
m_unk0x60 = FALSE;
|
||||
|
||||
if (MxMediaManager::InitPresenters() != SUCCESS)
|
||||
goto done;
|
||||
|
||||
m_criticalSection.Enter();
|
||||
locked = TRUE;
|
||||
|
||||
m_videoParam = p_videoParam;
|
||||
m_region = new MxRegion();
|
||||
|
||||
if (!m_region)
|
||||
goto done;
|
||||
|
||||
m_pDirectDraw = p_pDirectDraw;
|
||||
m_pDirect3D = p_pDirect3D;
|
||||
|
||||
MxPalette* palette;
|
||||
if (p_videoParam.GetPalette() == NULL) {
|
||||
palette = new MxPalette();
|
||||
m_videoParam.SetPalette(palette);
|
||||
|
||||
if (!palette)
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
palette = p_videoParam.GetPalette()->Clone();
|
||||
m_videoParam.SetPalette(palette);
|
||||
|
||||
if (!palette)
|
||||
goto done;
|
||||
}
|
||||
|
||||
m_displaySurface = new MxDisplaySurface();
|
||||
if (m_displaySurface && m_displaySurface->Init(m_videoParam, p_ddSurface1, p_ddSurface2, p_ddClipper) == SUCCESS) {
|
||||
m_displaySurface->SetPalette(m_videoParam.GetPalette());
|
||||
|
||||
if (p_createThread) {
|
||||
m_thread = new MxTickleThread(this, p_frequencyMS);
|
||||
|
||||
if (!m_thread || m_thread->Start(0, 0) != SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
TickleManager()->RegisterClient(this, p_frequencyMS);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
|
||||
done:
|
||||
if (status != SUCCESS)
|
||||
Destroy();
|
||||
|
||||
if (locked)
|
||||
m_criticalSection.Leave();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100be820
|
||||
MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread)
|
||||
{
|
||||
MxBool locked = FALSE;
|
||||
MxResult status = FAILURE;
|
||||
|
||||
m_unk0x60 = TRUE;
|
||||
|
||||
if (MxMediaManager::InitPresenters() != SUCCESS)
|
||||
goto done;
|
||||
|
||||
m_criticalSection.Enter();
|
||||
locked = TRUE;
|
||||
|
||||
m_videoParam = p_videoParam;
|
||||
m_region = new MxRegion();
|
||||
|
||||
if (!m_region)
|
||||
goto done;
|
||||
|
||||
if (DirectDrawCreate(NULL, &m_pDirectDraw, NULL) != DD_OK)
|
||||
goto done;
|
||||
|
||||
if (m_pDirectDraw->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DDSCL_NORMAL) != DD_OK)
|
||||
goto done;
|
||||
|
||||
MxPalette* palette;
|
||||
if (p_videoParam.GetPalette() == NULL) {
|
||||
palette = new MxPalette();
|
||||
m_videoParam.SetPalette(palette);
|
||||
|
||||
if (!palette)
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
palette = p_videoParam.GetPalette()->Clone();
|
||||
m_videoParam.SetPalette(palette);
|
||||
|
||||
if (!palette)
|
||||
goto done;
|
||||
}
|
||||
|
||||
m_displaySurface = new MxDisplaySurface();
|
||||
if (m_displaySurface && m_displaySurface->Create(m_videoParam) == SUCCESS) {
|
||||
m_displaySurface->SetPalette(m_videoParam.GetPalette());
|
||||
|
||||
if (p_createThread) {
|
||||
m_thread = new MxTickleThread(this, p_frequencyMS);
|
||||
|
||||
if (!m_thread || m_thread->Start(0, 0) != SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
TickleManager()->RegisterClient(this, p_frequencyMS);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
|
||||
done:
|
||||
if (status != SUCCESS)
|
||||
Destroy();
|
||||
|
||||
if (locked)
|
||||
m_criticalSection.Leave();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bea50
|
||||
void MxVideoManager::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bea60
|
||||
void MxVideoManager::InvalidateRect(MxRect32& p_rect)
|
||||
{
|
||||
m_criticalSection.Enter();
|
||||
|
||||
if (m_region)
|
||||
m_region->VTable0x18(p_rect);
|
||||
|
||||
m_criticalSection.Leave();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bea90
|
||||
MxResult MxVideoManager::Tickle()
|
||||
{
|
||||
MxAutoLocker lock(&this->m_criticalSection);
|
||||
|
||||
SortPresenterList();
|
||||
|
||||
MxPresenter* presenter;
|
||||
MxPresenterListCursor cursor(this->m_presenters);
|
||||
|
||||
while (cursor.Next(presenter))
|
||||
presenter->Tickle();
|
||||
|
||||
cursor.Reset();
|
||||
|
||||
while (cursor.Next(presenter))
|
||||
presenter->PutData();
|
||||
|
||||
UpdateRegion();
|
||||
m_region->Reset();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bebe0
|
||||
MxResult MxVideoManager::RealizePalette(MxPalette* p_palette)
|
||||
{
|
||||
PALETTEENTRY paletteEntries[256];
|
||||
|
||||
this->m_criticalSection.Enter();
|
||||
|
||||
if (p_palette && this->m_videoParam.GetPalette()) {
|
||||
p_palette->GetEntries(paletteEntries);
|
||||
this->m_videoParam.GetPalette()->SetEntries(paletteEntries);
|
||||
this->m_displaySurface->SetPalette(this->m_videoParam.GetPalette());
|
||||
}
|
||||
|
||||
this->m_criticalSection.Leave();
|
||||
return SUCCESS;
|
||||
}
|
||||
87
LEGO1/omni/src/video/mxvideoparam.cpp
Normal file
87
LEGO1/omni/src/video/mxvideoparam.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "mxvideoparam.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxVideoParam, 0x24);
|
||||
|
||||
// FUNCTION: LEGO1 0x100bec70
|
||||
MxVideoParam::MxVideoParam()
|
||||
{
|
||||
this->m_rect.SetRight(640);
|
||||
this->m_rect.SetBottom(480);
|
||||
this->m_rect.SetLeft(0);
|
||||
this->m_rect.SetTop(0);
|
||||
this->m_palette = NULL;
|
||||
this->m_backBuffers = 0;
|
||||
this->m_unk0x1c = 0;
|
||||
this->m_deviceId = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100beca0
|
||||
MxVideoParam::MxVideoParam(
|
||||
COMPAT_CONST MxRect32& p_rect,
|
||||
MxPalette* p_palette,
|
||||
MxULong p_backBuffers,
|
||||
COMPAT_CONST MxVideoParamFlags& p_flags
|
||||
)
|
||||
{
|
||||
this->m_rect = p_rect;
|
||||
this->m_palette = p_palette;
|
||||
this->m_backBuffers = p_backBuffers;
|
||||
this->m_flags = p_flags;
|
||||
this->m_unk0x1c = 0;
|
||||
this->m_deviceId = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100becf0
|
||||
MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam)
|
||||
{
|
||||
this->m_rect = p_videoParam.m_rect;
|
||||
this->m_palette = p_videoParam.m_palette;
|
||||
this->m_backBuffers = p_videoParam.m_backBuffers;
|
||||
this->m_flags = p_videoParam.m_flags;
|
||||
this->m_unk0x1c = p_videoParam.m_unk0x1c;
|
||||
this->m_deviceId = NULL;
|
||||
SetDeviceName(p_videoParam.m_deviceId);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bed50
|
||||
MxVideoParam::~MxVideoParam()
|
||||
{
|
||||
if (this->m_deviceId != NULL)
|
||||
delete[] this->m_deviceId;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bed70
|
||||
void MxVideoParam::SetDeviceName(char* p_deviceId)
|
||||
{
|
||||
if (this->m_deviceId != NULL)
|
||||
delete[] this->m_deviceId;
|
||||
|
||||
if (p_deviceId != NULL) {
|
||||
this->m_deviceId = new char[strlen(p_deviceId) + 1];
|
||||
|
||||
if (this->m_deviceId != NULL) {
|
||||
strcpy(this->m_deviceId, p_deviceId);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->m_deviceId = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bede0
|
||||
MxVideoParam& MxVideoParam::operator=(const MxVideoParam& p_videoParam)
|
||||
{
|
||||
this->m_rect = p_videoParam.m_rect;
|
||||
this->m_palette = p_videoParam.m_palette;
|
||||
this->m_backBuffers = p_videoParam.m_backBuffers;
|
||||
this->m_flags = p_videoParam.m_flags;
|
||||
this->m_unk0x1c = p_videoParam.m_unk0x1c;
|
||||
SetDeviceName(p_videoParam.m_deviceId);
|
||||
|
||||
return *this;
|
||||
}
|
||||
15
LEGO1/omni/src/video/mxvideoparamflags.cpp
Normal file
15
LEGO1/omni/src/video/mxvideoparamflags.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "mxvideoparamflags.h"
|
||||
|
||||
// FUNCTION: LEGO1 0x100bec40
|
||||
MxVideoParamFlags::MxVideoParamFlags()
|
||||
{
|
||||
this->SetFullScreen(0);
|
||||
this->SetFlipSurfaces(0);
|
||||
this->SetBackBuffers(0);
|
||||
this->SetF1bit3(0);
|
||||
this->SetF1bit4(0);
|
||||
this->Set16Bit(0);
|
||||
this->SetWideViewAngle(1);
|
||||
this->SetF1bit7(1);
|
||||
this->SetF2bit1(1);
|
||||
}
|
||||
627
LEGO1/omni/src/video/mxvideopresenter.cpp
Normal file
627
LEGO1/omni/src/video/mxvideopresenter.cpp
Normal file
@@ -0,0 +1,627 @@
|
||||
#include "mxvideopresenter.h"
|
||||
|
||||
#include "mxautolocker.h"
|
||||
#include "mxdsmediaaction.h"
|
||||
#include "mxregioncursor.h"
|
||||
#include "mxvideomanager.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64);
|
||||
DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0xc);
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c700
|
||||
void MxVideoPresenter::LoadHeader(MxStreamChunk* p_chunk)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c710
|
||||
void MxVideoPresenter::CreateBitmap()
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c720
|
||||
void MxVideoPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c730
|
||||
void MxVideoPresenter::RealizePalette()
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c740
|
||||
MxVideoPresenter::~MxVideoPresenter()
|
||||
{
|
||||
Destroy(TRUE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c7a0
|
||||
void MxVideoPresenter::Destroy()
|
||||
{
|
||||
Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c7b0
|
||||
LPDIRECTDRAWSURFACE MxVideoPresenter::VTable0x78()
|
||||
{
|
||||
return m_unk0x58;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c7c0
|
||||
MxBool MxVideoPresenter::VTable0x7c()
|
||||
{
|
||||
return (m_bitmap != NULL) || (m_alpha != NULL);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c7e0
|
||||
MxS32 MxVideoPresenter::GetWidth()
|
||||
{
|
||||
return m_alpha ? m_alpha->m_width : m_bitmap->GetBmiWidth();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1000c800
|
||||
MxS32 MxVideoPresenter::GetHeight()
|
||||
{
|
||||
return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeightAbs();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b24f0
|
||||
MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap)
|
||||
{
|
||||
m_width = p_bitmap.GetBmiWidth();
|
||||
// DECOMP: ECX becomes word-sized if these are not two separate actions.
|
||||
MxLong height = p_bitmap.GetBmiHeightAbs();
|
||||
m_height = height;
|
||||
|
||||
MxS32 size = ((m_width * m_height) / 8) + 1;
|
||||
m_bitmask = new MxU8[size];
|
||||
memset(m_bitmask, 0, size);
|
||||
|
||||
MxU32 biCompression = p_bitmap.GetBmiHeader()->biCompression;
|
||||
MxU32 rowsBeforeTop;
|
||||
MxU8* bitmapSrcPtr;
|
||||
|
||||
// The goal here is to enable us to walk through the bitmap's rows
|
||||
// in order, regardless of the orientation. We want to end up at the
|
||||
// start of the first row, which is either at position 0, or at
|
||||
// (image_stride * biHeight) - 1.
|
||||
|
||||
// Reminder: Negative biHeight means this is a top-down DIB.
|
||||
// Otherwise it is bottom-up.
|
||||
|
||||
if (biCompression == BI_RGB) {
|
||||
// DECOMP: I think this must be an OR. If not, the check for
|
||||
// biCompression == 16 gets optimized away.
|
||||
if (biCompression == BI_RGB_TOPDOWN || p_bitmap.GetBmiHeight() < 0) {
|
||||
rowsBeforeTop = 0;
|
||||
}
|
||||
else {
|
||||
rowsBeforeTop = p_bitmap.GetBmiHeightAbs();
|
||||
rowsBeforeTop--;
|
||||
}
|
||||
|
||||
goto seek_to_last_row;
|
||||
}
|
||||
else if (biCompression == BI_RGB_TOPDOWN) {
|
||||
// DECOMP: This is the only condition where we skip the
|
||||
// calculation below.
|
||||
bitmapSrcPtr = p_bitmap.GetBitmapData();
|
||||
}
|
||||
else {
|
||||
if (p_bitmap.GetBmiHeight() < 0) {
|
||||
rowsBeforeTop = 0;
|
||||
}
|
||||
else {
|
||||
rowsBeforeTop = p_bitmap.GetBmiHeightAbs();
|
||||
rowsBeforeTop--;
|
||||
}
|
||||
|
||||
// TODO: would prefer not to use goto if we can figure this structure out
|
||||
seek_to_last_row:
|
||||
bitmapSrcPtr = p_bitmap.GetBmiStride() * rowsBeforeTop + p_bitmap.GetBitmapData();
|
||||
}
|
||||
|
||||
// How many bytes are there for each row of the bitmap?
|
||||
// (i.e. the image stride)
|
||||
// If this is a bottom-up DIB, we will walk it in reverse.
|
||||
// TODO: Same rounding trick as in MxBitmap
|
||||
MxS32 rowSeek = ((m_width + 3) & -4);
|
||||
if (p_bitmap.GetBmiHeight() < 0)
|
||||
rowSeek = -rowSeek;
|
||||
|
||||
// The actual offset into the m_bitmask array. The two for-loops
|
||||
// are just for counting the pixels.
|
||||
MxS32 offset = 0;
|
||||
|
||||
MxU8* tPtr = bitmapSrcPtr;
|
||||
for (MxS32 j = 0; j < m_height; j++) {
|
||||
for (MxS32 i = 0; i < m_width; i++) {
|
||||
if (*tPtr) {
|
||||
// TODO: Second CDQ instruction for abs() should not be there.
|
||||
MxU32 shift = abs(offset) & 7;
|
||||
m_bitmask[offset / 8] |= (1 << abs((MxS32) shift));
|
||||
}
|
||||
tPtr++;
|
||||
offset++;
|
||||
}
|
||||
// Seek to the start of the next row
|
||||
bitmapSrcPtr += rowSeek;
|
||||
tPtr = bitmapSrcPtr;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2670
|
||||
MxVideoPresenter::AlphaMask::AlphaMask(const MxVideoPresenter::AlphaMask& p_alpha)
|
||||
{
|
||||
m_width = p_alpha.m_width;
|
||||
m_height = p_alpha.m_height;
|
||||
|
||||
MxS32 size = ((m_width * m_height) / 8) + 1;
|
||||
m_bitmask = new MxU8[size];
|
||||
memcpy(m_bitmask, p_alpha.m_bitmask, size);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b26d0
|
||||
MxVideoPresenter::AlphaMask::~AlphaMask()
|
||||
{
|
||||
if (m_bitmask)
|
||||
delete[] m_bitmask;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b26f0
|
||||
MxS32 MxVideoPresenter::AlphaMask::IsHit(MxU32 p_x, MxU32 p_y)
|
||||
{
|
||||
if (p_x >= m_width || p_y >= m_height)
|
||||
return 0;
|
||||
|
||||
MxS32 pos = p_y * m_width + p_x;
|
||||
return m_bitmask[pos / 8] & (1 << abs(abs(pos) & 7)) ? 1 : 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2760
|
||||
void MxVideoPresenter::Init()
|
||||
{
|
||||
m_bitmap = NULL;
|
||||
m_alpha = NULL;
|
||||
m_unk0x5c = 1;
|
||||
m_unk0x58 = NULL;
|
||||
m_unk0x60 = -1;
|
||||
m_flags &= ~Flag_Bit1;
|
||||
|
||||
if (MVideoManager() != NULL) {
|
||||
MVideoManager();
|
||||
m_flags |= Flag_Bit2;
|
||||
m_flags &= ~Flag_Bit3;
|
||||
}
|
||||
|
||||
m_flags &= ~Flag_Bit4;
|
||||
m_flags &= ~Flag_Bit5;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b27b0
|
||||
void MxVideoPresenter::Destroy(MxBool p_fromDestructor)
|
||||
{
|
||||
if (MVideoManager() != NULL)
|
||||
MVideoManager()->RemovePresenter(*this);
|
||||
|
||||
if (m_unk0x58) {
|
||||
m_unk0x58->Release();
|
||||
m_unk0x58 = NULL;
|
||||
m_flags &= ~Flag_Bit2;
|
||||
m_flags &= ~Flag_Bit3;
|
||||
}
|
||||
|
||||
if (MVideoManager() && (m_alpha || m_bitmap)) {
|
||||
// MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight()));
|
||||
MxS32 height = GetHeight();
|
||||
MxS32 width = GetWidth();
|
||||
MxS32 x = m_location.GetX();
|
||||
MxS32 y = m_location.GetY();
|
||||
|
||||
MxRect32 rect(x, y, x + width, y + height);
|
||||
MVideoManager()->InvalidateRect(rect);
|
||||
MVideoManager()->VTable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
|
||||
}
|
||||
|
||||
delete m_bitmap;
|
||||
delete m_alpha;
|
||||
|
||||
Init();
|
||||
|
||||
if (!p_fromDestructor)
|
||||
MxMediaPresenter::Destroy(FALSE);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b28b0
|
||||
void MxVideoPresenter::NextFrame()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk->GetFlags() & MxDSChunk::Flag_End) {
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Repeating;
|
||||
}
|
||||
else {
|
||||
LoadFrame(chunk);
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2900
|
||||
MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y)
|
||||
{
|
||||
MxDSAction* action = GetAction();
|
||||
if ((action == NULL) || (((action->GetFlags() & MxDSAction::Flag_Bit11) == 0) && !IsEnabled()) ||
|
||||
(!m_bitmap && !m_alpha))
|
||||
return FALSE;
|
||||
|
||||
if (!m_bitmap)
|
||||
return m_alpha->IsHit(p_x - m_location.GetX(), p_y - m_location.GetY());
|
||||
|
||||
MxLong heightAbs = m_bitmap->GetBmiHeightAbs();
|
||||
|
||||
MxLong minX = m_location.GetX();
|
||||
MxLong minY = m_location.GetY();
|
||||
|
||||
MxLong maxY = minY + heightAbs;
|
||||
MxLong maxX = minX + m_bitmap->GetBmiWidth();
|
||||
|
||||
if (p_x < minX || p_x >= maxX || p_y < minY || p_y >= maxY)
|
||||
return FALSE;
|
||||
|
||||
MxU8* pixel;
|
||||
|
||||
MxLong biCompression = m_bitmap->GetBmiHeader()->biCompression;
|
||||
MxLong height = m_bitmap->GetBmiHeight();
|
||||
MxLong seekRow;
|
||||
|
||||
// DECOMP: Same basic layout as AlphaMask constructor
|
||||
// The idea here is to again seek to the correct place in the bitmap's
|
||||
// m_data buffer. The x,y args are (most likely) screen x and y, so we
|
||||
// need to shift that to coordinates local to the bitmap by removing
|
||||
// the MxPresenter location x and y coordinates.
|
||||
if (biCompression == BI_RGB) {
|
||||
if (biCompression == BI_RGB_TOPDOWN || height < 0) {
|
||||
seekRow = p_y - m_location.GetY();
|
||||
}
|
||||
else {
|
||||
height = height > 0 ? height : -height;
|
||||
seekRow = height - p_y - 1 + m_location.GetY();
|
||||
}
|
||||
pixel = m_bitmap->GetBmiStride() * seekRow + m_bitmap->GetBitmapData() - m_location.GetX() + p_x;
|
||||
}
|
||||
else if (biCompression == BI_RGB_TOPDOWN) {
|
||||
pixel = m_bitmap->GetBitmapData();
|
||||
}
|
||||
else {
|
||||
height = height > 0 ? height : -height;
|
||||
height--;
|
||||
pixel = m_bitmap->GetBmiStride() * height + m_bitmap->GetBitmapData();
|
||||
}
|
||||
|
||||
// DECOMP: m_flags is 1 byte, so no enum here
|
||||
if (m_flags & 0x10)
|
||||
return (MxBool) *pixel;
|
||||
|
||||
if ((GetAction()->GetFlags() & MxDSAction::Flag_Bit4) && *pixel == 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
inline MxS32 MxVideoPresenter::PrepareRects(MxRect32& p_rectDest, MxRect32& p_rectSrc)
|
||||
{
|
||||
if (p_rectDest.GetTop() > 480 || p_rectDest.GetLeft() > 640 || p_rectSrc.GetTop() > 480 ||
|
||||
p_rectSrc.GetLeft() > 640)
|
||||
return -1;
|
||||
|
||||
if (p_rectDest.GetBottom() > 480)
|
||||
p_rectDest.SetBottom(480);
|
||||
|
||||
if (p_rectDest.GetRight() > 640)
|
||||
p_rectDest.SetRight(640);
|
||||
|
||||
if (p_rectSrc.GetBottom() > 480)
|
||||
p_rectSrc.SetBottom(480);
|
||||
|
||||
if (p_rectSrc.GetRight() > 640)
|
||||
p_rectSrc.SetRight(640);
|
||||
|
||||
MxS32 height = p_rectDest.GetHeight();
|
||||
if (height <= 1)
|
||||
return -1;
|
||||
|
||||
MxS32 width = p_rectDest.GetWidth();
|
||||
if (width <= 1)
|
||||
return -1;
|
||||
|
||||
if (p_rectSrc.GetRight() - width - p_rectSrc.GetLeft() == -1 &&
|
||||
p_rectSrc.GetBottom() - height - p_rectSrc.GetTop() == -1)
|
||||
return 1;
|
||||
|
||||
p_rectSrc.SetRight(p_rectSrc.GetLeft() + width - 1);
|
||||
p_rectSrc.SetBottom(p_rectSrc.GetTop() + height - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2a70
|
||||
void MxVideoPresenter::PutFrame()
|
||||
{
|
||||
MxDisplaySurface* displaySurface = MVideoManager()->GetDisplaySurface();
|
||||
MxRegion* region = MVideoManager()->GetRegion();
|
||||
MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight()));
|
||||
LPDIRECTDRAWSURFACE ddSurface = displaySurface->GetDirectDrawSurface2();
|
||||
|
||||
MxRect32 rectSrc, rectDest;
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Bit5) {
|
||||
if (m_unk0x58) {
|
||||
// TODO: Match
|
||||
rectSrc.SetPoint(MxPoint32(0, 0));
|
||||
rectSrc.SetRight(GetWidth());
|
||||
rectSrc.SetBottom(GetHeight());
|
||||
|
||||
rectDest.SetPoint(m_location);
|
||||
rectDest.SetRight(rectDest.GetLeft() + GetWidth());
|
||||
rectDest.SetBottom(rectDest.GetTop() + GetHeight());
|
||||
|
||||
switch (PrepareRects(rectDest, rectSrc)) {
|
||||
case 0:
|
||||
ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, DDBLT_KEYSRC, NULL);
|
||||
break;
|
||||
case 1:
|
||||
ddSurface->BltFast(
|
||||
rectDest.GetLeft(),
|
||||
rectDest.GetTop(),
|
||||
m_unk0x58,
|
||||
(LPRECT) &rectSrc,
|
||||
DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
displaySurface->VTable0x30(
|
||||
m_bitmap,
|
||||
0,
|
||||
0,
|
||||
rect.GetLeft(),
|
||||
rect.GetTop(),
|
||||
m_bitmap->GetBmiWidth(),
|
||||
m_bitmap->GetBmiHeightAbs(),
|
||||
TRUE
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MxRegionCursor cursor(region);
|
||||
MxRect32* regionRect;
|
||||
|
||||
while (regionRect = cursor.VTable0x24(rect)) {
|
||||
if (regionRect->GetWidth() >= 1 && regionRect->GetHeight() >= 1) {
|
||||
if (m_unk0x58) {
|
||||
rectSrc.SetLeft(regionRect->GetLeft() - m_location.GetX());
|
||||
rectSrc.SetTop(regionRect->GetTop() - m_location.GetY());
|
||||
rectSrc.SetRight(rectSrc.GetLeft() + regionRect->GetWidth());
|
||||
rectSrc.SetBottom(rectSrc.GetTop() + regionRect->GetHeight());
|
||||
|
||||
rectDest.SetLeft(regionRect->GetLeft());
|
||||
rectDest.SetTop(regionRect->GetTop());
|
||||
rectDest.SetRight(rectDest.GetLeft() + regionRect->GetWidth());
|
||||
rectDest.SetBottom(rectDest.GetTop() + regionRect->GetHeight());
|
||||
}
|
||||
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Bit4) {
|
||||
if (m_unk0x58) {
|
||||
if (PrepareRects(rectDest, rectSrc) >= 0)
|
||||
ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, DDBLT_KEYSRC, NULL);
|
||||
}
|
||||
else {
|
||||
displaySurface->VTable0x30(
|
||||
m_bitmap,
|
||||
regionRect->GetLeft() - m_location.GetX(),
|
||||
regionRect->GetTop() - m_location.GetY(),
|
||||
regionRect->GetLeft(),
|
||||
regionRect->GetTop(),
|
||||
regionRect->GetWidth(),
|
||||
regionRect->GetHeight(),
|
||||
FALSE
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (m_unk0x58) {
|
||||
if (PrepareRects(rectDest, rectSrc) >= 0)
|
||||
ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, 0, NULL);
|
||||
}
|
||||
else {
|
||||
displaySurface->VTable0x28(
|
||||
m_bitmap,
|
||||
regionRect->GetLeft() - m_location.GetX(),
|
||||
regionRect->GetTop() - m_location.GetY(),
|
||||
regionRect->GetLeft(),
|
||||
regionRect->GetTop(),
|
||||
regionRect->GetWidth(),
|
||||
regionRect->GetHeight()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2f60
|
||||
void MxVideoPresenter::ReadyTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = NextChunk();
|
||||
|
||||
if (chunk) {
|
||||
LoadHeader(chunk);
|
||||
m_subscriber->FUN_100b8390(chunk);
|
||||
ParseExtra();
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Starting;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2fa0
|
||||
void MxVideoPresenter::StartingTickle()
|
||||
{
|
||||
MxStreamChunk* chunk = FUN_100b5650();
|
||||
|
||||
if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) {
|
||||
CreateBitmap();
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Streaming;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b2fe0
|
||||
void MxVideoPresenter::StreamingTickle()
|
||||
{
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Bit10) {
|
||||
if (!m_currentChunk)
|
||||
MxMediaPresenter::StreamingTickle();
|
||||
|
||||
if (m_currentChunk) {
|
||||
LoadFrame(m_currentChunk);
|
||||
m_currentChunk = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (MxS16 i = 0; i < m_unk0x5c; i++) {
|
||||
if (!m_currentChunk) {
|
||||
MxMediaPresenter::StreamingTickle();
|
||||
|
||||
if (!m_currentChunk)
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_action->GetElapsedTime() < m_currentChunk->GetTime())
|
||||
break;
|
||||
|
||||
LoadFrame(m_currentChunk);
|
||||
m_subscriber->FUN_100b8390(m_currentChunk);
|
||||
m_currentChunk = NULL;
|
||||
m_flags |= Flag_Bit1;
|
||||
|
||||
if (m_currentTickleState != TickleState_Streaming)
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_flags & Flag_Bit1)
|
||||
m_unk0x5c = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3080
|
||||
void MxVideoPresenter::RepeatingTickle()
|
||||
{
|
||||
if (IsEnabled()) {
|
||||
if (m_action->GetFlags() & MxDSAction::Flag_Bit10) {
|
||||
if (!m_currentChunk)
|
||||
MxMediaPresenter::RepeatingTickle();
|
||||
|
||||
if (m_currentChunk) {
|
||||
LoadFrame(m_currentChunk);
|
||||
m_currentChunk = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (MxS16 i = 0; i < m_unk0x5c; i++) {
|
||||
if (!m_currentChunk) {
|
||||
MxMediaPresenter::RepeatingTickle();
|
||||
|
||||
if (!m_currentChunk)
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_action->GetElapsedTime() % m_action->GetLoopCount() < m_currentChunk->GetTime())
|
||||
break;
|
||||
|
||||
LoadFrame(m_currentChunk);
|
||||
m_currentChunk = NULL;
|
||||
m_flags |= Flag_Bit1;
|
||||
|
||||
if (m_currentTickleState != TickleState_Repeating)
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_flags & Flag_Bit1)
|
||||
m_unk0x5c = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3130
|
||||
void MxVideoPresenter::Unk5Tickle()
|
||||
{
|
||||
MxLong sustainTime = ((MxDSMediaAction*) m_action)->GetSustainTime();
|
||||
|
||||
if (sustainTime != -1) {
|
||||
if (sustainTime) {
|
||||
if (m_unk0x60 == -1)
|
||||
m_unk0x60 = m_action->GetElapsedTime();
|
||||
|
||||
if (m_action->GetElapsedTime() >= m_unk0x60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Done;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||
m_currentTickleState = TickleState_Done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b31a0
|
||||
MxResult MxVideoPresenter::AddToManager()
|
||||
{
|
||||
MxResult result = FAILURE;
|
||||
|
||||
if (MVideoManager()) {
|
||||
result = SUCCESS;
|
||||
MVideoManager()->AddPresenter(*this);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b31d0
|
||||
void MxVideoPresenter::EndAction()
|
||||
{
|
||||
if (m_action) {
|
||||
MxMediaPresenter::EndAction();
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (m_bitmap) {
|
||||
MxLong height = m_bitmap->GetBmiHeightAbs();
|
||||
MxLong width = m_bitmap->GetBmiWidth();
|
||||
MxS32 x = m_location.GetX();
|
||||
MxS32 y = m_location.GetY();
|
||||
|
||||
MxRect32 rect(x, y, x + width, y + height);
|
||||
|
||||
MVideoManager()->InvalidateRect(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3280
|
||||
MxResult MxVideoPresenter::PutData()
|
||||
{
|
||||
MxAutoLocker lock(&m_criticalSection);
|
||||
|
||||
if (IsEnabled() && m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_unk5)
|
||||
PutFrame();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100b3300
|
||||
undefined MxVideoPresenter::VTable0x74()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user