diff --git a/CONFIG/res/maindialog.ui b/CONFIG/res/maindialog.ui
index 66e2b52e..12739f27 100644
--- a/CONFIG/res/maindialog.ui
+++ b/CONFIG/res/maindialog.ui
@@ -455,6 +455,11 @@
Unknown - Broken
+ -
+
+ Fake Mosaic
+
+
-
diff --git a/ISLE/3ds/config.cpp b/ISLE/3ds/config.cpp
index dc5dd8dc..e70ec4dd 100644
--- a/ISLE/3ds/config.cpp
+++ b/ISLE/3ds/config.cpp
@@ -18,5 +18,5 @@ void N3DS_SetupDefaultConfigOverrides(dictionary* p_dictionary)
iniparser_set(p_dictionary, "isle:savepath", "sdmc:/3ds/isle");
// Use e_noAnimation/cut transition
- iniparser_set(p_dictionary, "isle:Transition Type", "1");
+ iniparser_set(p_dictionary, "isle:Transition Type", "7");
}
diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h
index 916a5937..e15f8598 100644
--- a/LEGO1/lego/legoomni/include/legocarbuild.h
+++ b/LEGO1/lego/legoomni/include/legocarbuild.h
@@ -137,11 +137,11 @@ class LegoCarBuild : public LegoWorld {
void FUN_10022f00();
void FUN_10022f30();
void FUN_10023130(MxLong p_x, MxLong p_y);
- void FUN_100236d0();
+ void AddSelectedPartToBuild();
undefined4 FUN_10024250(LegoEventNotificationParam* p_param);
void FUN_100243a0();
undefined4 FUN_10024480(MxActionNotificationParam* p_param);
- undefined4 FUN_100244e0(MxLong p_x, MxLong p_y);
+ undefined4 SelectPartFromMousePosition(MxLong p_x, MxLong p_y);
undefined4 FUN_100246e0(MxLong p_x, MxLong p_y);
MxS32 FUN_10024850(MxLong p_x, MxLong p_y);
undefined4 FUN_10024890(MxParam* p_param);
@@ -184,7 +184,7 @@ class LegoCarBuild : public LegoWorld {
MxU8 m_unk0x109; // 0x109
MxU16 m_unk0x10a; // 0x10a
Uint64 m_unk0x10c; // 0x10c
- LegoROI* m_unk0x110; // 0x110
+ LegoROI* m_selectedPart; // 0x110
BoundingSphere m_unk0x114; // 0x114
MxMatrix m_unk0x12c; // 0x12c
undefined m_unk0x174; // 0x174
@@ -202,10 +202,10 @@ class LegoCarBuild : public LegoWorld {
MxS32 m_unk0x290[2]; // 0x290
MxS32 m_unk0x298[2]; // 0x298
- MxFloat m_unk0x2a0; // 0x2a0
- Mx4DPointFloat m_unk0x2a4; // 0x2a4
- Mx4DPointFloat m_unk0x2bc; // 0x2bc
- MxBool m_unk0x2d4; // 0x2d4
+ MxFloat m_unk0x2a0; // 0x2a0
+ Mx4DPointFloat m_unk0x2a4; // 0x2a4
+ Mx4DPointFloat m_unk0x2bc; // 0x2bc
+ MxBool m_selectedPartIsPlaced; // 0x2d4
// variable names verified by BETA10 0x1006b27a
MxStillPresenter* m_ColorBook_Bitmap; // 0x2dc
diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h
index a13c1adf..31423e32 100644
--- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h
+++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h
@@ -77,11 +77,11 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter {
void FUN_10079050(MxS16 p_index);
void SwapNodesByName(LegoChar* p_param1, LegoChar* p_param2);
void InitBuildPlatform();
- void FUN_100795d0(LegoChar* p_param);
- void FUN_10079680(LegoChar* p_param);
+ void HideBuildPartByName(LegoChar* p_param);
+ void ShowBuildPartByName(LegoChar* p_param);
LegoAnimNodeData* FindNodeDataByName(LegoTreeNode* p_treeNode, const LegoChar* p_name);
LegoTreeNode* FindNodeByName(LegoTreeNode* p_treeNode, const LegoChar* p_name);
- void FUN_10079790(const LegoChar* p_name);
+ void AddPartToBuildByName(const LegoChar* p_name);
void RotateAroundYAxis(MxFloat p_angle);
MxBool FUN_10079c30(const LegoChar* p_name);
MxBool PartIsPlaced(const LegoChar* p_name);
diff --git a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h
index 8ecfeacf..d3d2a96a 100644
--- a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h
+++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h
@@ -44,21 +44,28 @@ class MxControlPresenter : public MxCompositePresenter {
void EndAction() override; // vtable+0x40
MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48
void Enable(MxBool p_enable) override; // vtable+0x54
- virtual void VTable0x6c(MxS16 p_unk0x4e); // vtable+0x6c
+ virtual void UpdateEnabledChild(MxS16 p_enabledChild); // vtable+0x6c
- MxBool FUN_10044480(LegoControlManagerNotificationParam* p_param, MxPresenter* p_presenter);
- MxBool FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter);
+ MxBool Notify(LegoControlManagerNotificationParam* p_param, MxPresenter* p_presenter);
+ MxBool CheckButtonDown(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter);
- MxS16 GetUnknown0x4e() { return m_unk0x4e; }
+ MxS16 GetEnabledChild() { return m_enabledChild; }
private:
- MxS16 m_unk0x4c; // 0x4c
- MxS16 m_unk0x4e; // 0x4e
- MxBool m_unk0x50; // 0x50
- MxS16 m_unk0x52; // 0x52
- MxS16 m_unk0x54; // 0x54
- MxS16 m_unk0x56; // 0x56
- MxS16* m_states; // 0x58
+ enum {
+ e_none,
+ e_toggle,
+ e_grid,
+ e_map,
+ };
+
+ MxS16 m_style; // 0x4c
+ MxS16 m_enabledChild; // 0x4e
+ MxBool m_unk0x50; // 0x50
+ MxS16 m_columnsOrRows; // 0x52
+ MxS16 m_rowsOrColumns; // 0x54
+ MxS16 m_stateOrCellIndex; // 0x56
+ MxS16* m_states; // 0x58
};
// SYNTHETIC: LEGO1 0x100440f0
diff --git a/LEGO1/lego/legoomni/include/mxtransitionmanager.h b/LEGO1/lego/legoomni/include/mxtransitionmanager.h
index dd9dc9ed..7c31daf7 100644
--- a/LEGO1/lego/legoomni/include/mxtransitionmanager.h
+++ b/LEGO1/lego/legoomni/include/mxtransitionmanager.h
@@ -48,7 +48,8 @@ class MxTransitionManager : public MxCore {
e_mosaic,
e_wipeDown,
e_windows,
- e_broken // Unknown what this is supposed to be, it locks the game up
+ e_broken, // Unknown what this is supposed to be, it locks the game up
+ e_fakeMosaic
};
MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim);
@@ -68,6 +69,7 @@ class MxTransitionManager : public MxCore {
void WipeDownTransition();
void WindowsTransition();
void BrokenTransition();
+ void FakeMosaicTransition();
void SubmitCopyRect(LPDDSURFACEDESC p_ddsc);
void SetupCopyRect(LPDDSURFACEDESC p_ddsc);
diff --git a/LEGO1/lego/legoomni/src/actors/radio.cpp b/LEGO1/lego/legoomni/src/actors/radio.cpp
index 2df84506..104ba823 100644
--- a/LEGO1/lego/legoomni/src/actors/radio.cpp
+++ b/LEGO1/lego/legoomni/src/actors/radio.cpp
@@ -131,7 +131,7 @@ void Radio::Stop()
MxControlPresenter* presenter = (MxControlPresenter*) world->Find(world->GetAtomId(), IsleScript::c_Radio_Ctl);
if (presenter) {
- presenter->VTable0x6c(0);
+ presenter->UpdateEnabledChild(0);
}
BackgroundAudioManager()->Stop();
diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp
index fa0be996..9b983b82 100644
--- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp
+++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp
@@ -96,9 +96,9 @@ MxS16 LegoCarBuild::g_unk0x100f11cc = -1;
LegoCarBuild::LegoCarBuild()
{
m_unk0x100 = 0;
- m_unk0x110 = 0;
+ m_selectedPart = 0;
m_unk0xf8 = c_unknownminusone;
- m_unk0x2d4 = FALSE;
+ m_selectedPartIsPlaced = FALSE;
m_animPresenter = NULL;
m_ColorBook_Bitmap = NULL;
m_Yellow_Ctl = NULL;
@@ -138,7 +138,7 @@ LegoCarBuild::LegoCarBuild()
LegoCarBuild::~LegoCarBuild()
{
m_unk0x100 = 0;
- m_unk0x110 = NULL;
+ m_selectedPart = NULL;
if (m_animPresenter) {
m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_selected);
@@ -291,7 +291,7 @@ void LegoCarBuild::InitPresenters()
// FUNCTION: LEGO1 0x10022f00
void LegoCarBuild::FUN_10022f00()
{
- if (m_unk0x110) {
+ if (m_selectedPart) {
VTable0x6c();
m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_selected);
m_unk0x100 = 5;
@@ -302,18 +302,18 @@ void LegoCarBuild::FUN_10022f00()
// FUNCTION: BETA10 0x1006b835
void LegoCarBuild::FUN_10022f30()
{
- if (m_unk0x110) {
+ if (m_selectedPart) {
FUN_10024f70(FALSE);
FUN_100250e0(FALSE);
- if (m_animPresenter->PartIsPlaced(m_unk0x110->GetName())) {
+ if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) {
m_PlaceBrick_Sound->Enable(FALSE);
m_PlaceBrick_Sound->Enable(TRUE);
}
m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_stopped);
m_animPresenter->PutFrame();
- m_unk0x110 = NULL;
+ m_selectedPart = NULL;
m_unk0x100 = 0;
}
}
@@ -323,8 +323,8 @@ void LegoCarBuild::FUN_10022f30()
void LegoCarBuild::VTable0x6c()
{
m_unk0x178 = m_unk0x1c0;
- m_unk0x110->WrappedSetLocal2WorldWithWorldDataUpdate(m_unk0x178);
- m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition());
+ m_selectedPart->WrappedSetLocal2WorldWithWorldDataUpdate(m_unk0x178);
+ m_unk0x2a4 = Vector4(m_selectedPart->GetWorldPosition());
VTable0x70();
}
@@ -363,7 +363,7 @@ void LegoCarBuild::VTable0x70()
// FUNCTION: BETA10 0x1006bb22
void LegoCarBuild::FUN_10023130(MxLong p_x, MxLong p_y)
{
- if (m_unk0x110) {
+ if (m_selectedPart) {
MxFloat pfVar3[2];
MxFloat local30[3];
MxFloat local84[3];
@@ -411,7 +411,7 @@ void LegoCarBuild::FUN_10023130(MxLong p_x, MxLong p_y)
local78[3][2] = m_unk0x178[3][2] + local18[2];
local78[3][3] = 1.0;
- m_unk0x110->WrappedSetLocal2WorldWithWorldDataUpdate(local78);
+ m_selectedPart->WrappedSetLocal2WorldWithWorldDataUpdate(local78);
}
}
}
@@ -477,15 +477,15 @@ void LegoCarBuild::VTable0x80(MxFloat p_param1[2], MxFloat p_param2[2], MxFloat
// FUNCTION: LEGO1 0x100236d0
// FUNCTION: BETA10 0x1006c076
-void LegoCarBuild::FUN_100236d0()
+void LegoCarBuild::AddSelectedPartToBuild()
{
MxS32 pLVar2;
FUN_10024f70(FALSE);
FUN_100250e0(FALSE);
- m_animPresenter->FUN_10079790(m_unk0x110->GetName());
+ m_animPresenter->AddPartToBuildByName(m_selectedPart->GetName());
m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_stopped);
- m_unk0x110 = NULL;
+ m_selectedPart = NULL;
m_unk0x100 = 0;
if (m_animPresenter->AllPartsPlaced() && !Lego()->IsVersion10()) {
@@ -544,15 +544,15 @@ MxResult LegoCarBuild::Tickle()
FUN_10024f50();
}
- if (m_unk0x110) {
- if (m_animPresenter->PartIsPlaced(m_unk0x110->GetName())) {
+ if (m_selectedPart) {
+ if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) {
FUN_10022f30();
}
}
}
- if (m_unk0x100 == 5 && m_unk0x110) {
- RotateY(m_unk0x110, g_unk0x100d65a4);
+ if (m_unk0x100 == 5 && m_selectedPart) {
+ RotateY(m_selectedPart, g_unk0x100d65a4);
}
if (m_unk0x10a) {
@@ -690,7 +690,7 @@ MxLong LegoCarBuild::Notify(MxParam& p_param)
if (((m_buildState->m_animationState != 4) && (m_buildState->m_animationState != 6)) &&
(m_buildState->m_animationState != 2)) {
m_buildState->m_animationState = LegoVehicleBuildState::e_unknown0;
- result = FUN_100244e0(
+ result = SelectPartFromMousePosition(
((LegoEventNotificationParam&) p_param).GetX(),
((LegoEventNotificationParam&) p_param).GetY()
);
@@ -820,7 +820,7 @@ undefined4 LegoCarBuild::FUN_10024480(MxActionNotificationParam* p_param)
// FUNCTION: LEGO1 0x100244e0
// FUNCTION: BETA10 0x1006cfb6
-undefined4 LegoCarBuild::FUN_100244e0(MxLong p_x, MxLong p_y)
+undefined4 LegoCarBuild::SelectPartFromMousePosition(MxLong p_x, MxLong p_y)
{
m_unk0x250[0] = p_x;
m_unk0x250[1] = p_y;
@@ -831,34 +831,34 @@ undefined4 LegoCarBuild::FUN_100244e0(MxLong p_x, MxLong p_y)
return 0;
}
- if (m_unk0x110 != roi) {
+ if (m_selectedPart != roi) {
FUN_10022f30();
- m_unk0x110 = roi;
+ m_selectedPart = roi;
FUN_10024f70(TRUE);
FUN_100250e0(TRUE);
}
- if (m_unk0x100 == 5 && m_animPresenter->PartIsPlaced(m_unk0x110->GetName())) {
- m_unk0x2d4 = TRUE;
+ if (m_unk0x100 == 5 && m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) {
+ m_selectedPartIsPlaced = TRUE;
}
else {
- m_unk0x2d4 = FALSE;
+ m_selectedPartIsPlaced = FALSE;
}
FUN_10025450();
VTable0x70();
- if (m_animPresenter->PartIsPlaced(m_unk0x110->GetName())) {
+ if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) {
if (m_unk0x100 != 5) {
m_unk0x250[0] += m_unk0x290[0] - m_unk0x298[0];
m_unk0x250[1] += m_unk0x290[1] - m_unk0x298[1];
}
if (m_unk0x100 == 0) {
- m_unk0x114 = m_unk0x110->GetWorldBoundingSphere();
+ m_unk0x114 = m_selectedPart->GetWorldBoundingSphere();
}
}
else {
- if (m_animPresenter->FUN_10079c30(m_unk0x110->GetName())) {
+ if (m_animPresenter->FUN_10079c30(m_selectedPart->GetName())) {
m_unk0x114 = m_animPresenter->FUN_10079e20();
}
}
@@ -895,21 +895,21 @@ undefined4 LegoCarBuild::FUN_100246e0(MxLong p_x, MxLong p_y)
result = 1;
break;
case 6:
- if (m_animPresenter->PartIsPlaced(m_unk0x110->GetName()) &&
- SpheresIntersect(m_unk0x114, m_unk0x110->GetWorldBoundingSphere())) {
+ if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName()) &&
+ SpheresIntersect(m_unk0x114, m_selectedPart->GetWorldBoundingSphere())) {
FUN_10024f70(FALSE);
FUN_100250e0(FALSE);
m_unk0x100 = 0;
- m_unk0x110 = NULL;
+ m_selectedPart = NULL;
m_PlaceBrick_Sound->Enable(FALSE);
m_PlaceBrick_Sound->Enable(TRUE);
m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_stopped);
}
- else if (m_animPresenter->FUN_10079c30(m_unk0x110->GetName())) {
- if (SpheresIntersect(m_unk0x114, m_unk0x110->GetWorldBoundingSphere())) {
+ else if (m_animPresenter->FUN_10079c30(m_selectedPart->GetName())) {
+ if (SpheresIntersect(m_unk0x114, m_selectedPart->GetWorldBoundingSphere())) {
m_PlaceBrick_Sound->Enable(FALSE);
m_PlaceBrick_Sound->Enable(TRUE);
- FUN_100236d0();
+ AddSelectedPartToBuild();
}
else {
VTable0x6c();
@@ -1024,7 +1024,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param)
(m_Decals_Ctl5 && m_Decals_Ctl5->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
(m_Decals_Ctl6 && m_Decals_Ctl6->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
(m_Decals_Ctl7 && m_Decals_Ctl7->GetAction()->GetObjectId() == param->m_clickedObjectId)) {
- m_animPresenter->SetPartObjectIdByName(m_unk0x110->GetName(), param->m_clickedObjectId);
+ m_animPresenter->SetPartObjectIdByName(m_selectedPart->GetName(), param->m_clickedObjectId);
m_Decal_Sound->Enable(FALSE);
m_Decal_Sound->Enable(TRUE);
}
@@ -1128,7 +1128,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param)
(m_Decals_Ctl5 && m_Decals_Ctl5->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
(m_Decals_Ctl6 && m_Decals_Ctl6->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
(m_Decals_Ctl7 && m_Decals_Ctl7->GetAction()->GetObjectId() == param->m_clickedObjectId)) {
- m_animPresenter->SetPartObjectIdByName(m_unk0x110->GetName(), param->m_clickedObjectId);
+ m_animPresenter->SetPartObjectIdByName(m_selectedPart->GetName(), param->m_clickedObjectId);
m_Decal_Sound->Enable(FALSE);
m_Decal_Sound->Enable(TRUE);
}
@@ -1271,7 +1271,7 @@ void LegoCarBuild::FUN_10024f30()
// FUNCTION: BETA10 0x1006dfce
void LegoCarBuild::FUN_10024f50()
{
- m_unk0x2d4 = FALSE;
+ m_selectedPartIsPlaced = FALSE;
m_animPresenter->RotateAroundYAxis(g_rotationAngleStepYAxis);
}
@@ -1279,7 +1279,7 @@ void LegoCarBuild::FUN_10024f50()
// FUNCTION: BETA10 0x1006e002
void LegoCarBuild::FUN_10024f70(MxBool p_enabled)
{
- if (m_animPresenter->StringEndsOnY(m_unk0x110->GetName())) {
+ if (m_animPresenter->StringEndsOnY(m_selectedPart->GetName())) {
SetPresentersEnabled(p_enabled);
}
}
@@ -1314,31 +1314,31 @@ void LegoCarBuild::TogglePresentersEnabled()
// FUNCTION: BETA10 0x1006e124
void LegoCarBuild::FUN_100250e0(MxBool p_enabled)
{
- if (m_animPresenter->StringDoesNotEndOnZero(m_unk0x110->GetName()) && m_Decals_Ctl) {
- if (SDL_strncasecmp(m_unk0x110->GetName(), "JSFRNT", strlen("JSFRNT")) == 0) {
+ if (m_animPresenter->StringDoesNotEndOnZero(m_selectedPart->GetName()) && m_Decals_Ctl) {
+ if (SDL_strncasecmp(m_selectedPart->GetName(), "JSFRNT", strlen("JSFRNT")) == 0) {
m_Decal_Bitmap->Enable(p_enabled);
m_Decals_Ctl->Enable(p_enabled);
m_Decals_Ctl1->Enable(p_enabled);
m_Decals_Ctl2->Enable(p_enabled);
m_Decals_Ctl3->Enable(p_enabled);
}
- else if (SDL_strncasecmp(m_unk0x110->GetName(), "JSWNSH", strlen("JSWNSH")) == 0) {
+ else if (SDL_strncasecmp(m_selectedPart->GetName(), "JSWNSH", strlen("JSWNSH")) == 0) {
m_Decal_Bitmap->Enable(p_enabled);
m_Decals_Ctl4->Enable(p_enabled);
m_Decals_Ctl5->Enable(p_enabled);
m_Decals_Ctl6->Enable(p_enabled);
m_Decals_Ctl7->Enable(p_enabled);
}
- else if (SDL_strncasecmp(m_unk0x110->GetName(), "RCBACK", strlen("RCBACK")) == 0) {
+ else if (SDL_strncasecmp(m_selectedPart->GetName(), "RCBACK", strlen("RCBACK")) == 0) {
m_Decals_Ctl1->Enable(p_enabled);
}
- else if (SDL_strncasecmp(m_unk0x110->GetName(), "RCTAIL", strlen("RCTAIL")) == 0) {
+ else if (SDL_strncasecmp(m_selectedPart->GetName(), "RCTAIL", strlen("RCTAIL")) == 0) {
m_Decals_Ctl2->Enable(p_enabled);
}
- else if (m_Decals_Ctl1 && SDL_strncasecmp(m_unk0x110->GetName(), "chljety", strlen("chljety")) == 0) {
+ else if (m_Decals_Ctl1 && SDL_strncasecmp(m_selectedPart->GetName(), "chljety", strlen("chljety")) == 0) {
m_Decals_Ctl1->Enable(p_enabled);
}
- else if (m_Decals_Ctl2 && SDL_strncasecmp(m_unk0x110->GetName(), "chrjety", strlen("chrjety")) == 0) {
+ else if (m_Decals_Ctl2 && SDL_strncasecmp(m_selectedPart->GetName(), "chrjety", strlen("chrjety")) == 0) {
m_Decals_Ctl2->Enable(p_enabled);
}
else if (m_Decals_Ctl) {
@@ -1354,7 +1354,7 @@ void LegoCarBuild::FUN_10025350(MxS32 p_objectId)
const LegoChar* color;
LegoChar buffer[256];
- if (!m_unk0x110) {
+ if (!m_selectedPart) {
return;
}
@@ -1382,8 +1382,8 @@ void LegoCarBuild::FUN_10025350(MxS32 p_objectId)
m_Paint_Sound->Enable(FALSE);
m_Paint_Sound->Enable(TRUE);
- m_unk0x110->FUN_100a93b0(color);
- sprintf(buffer, "c_%s", m_unk0x110->GetName());
+ m_selectedPart->FUN_100a93b0(color);
+ sprintf(buffer, "c_%s", m_selectedPart->GetName());
VariableTable()->SetVariable(buffer, color);
}
@@ -1391,7 +1391,7 @@ void LegoCarBuild::FUN_10025350(MxS32 p_objectId)
// FUNCTION: BETA10 0x1006e599
void LegoCarBuild::FUN_10025450()
{
- m_unk0x12c = m_unk0x110->GetLocal2World();
+ m_unk0x12c = m_selectedPart->GetLocal2World();
m_unk0x1c0 = m_unk0x12c;
Vector3 lastColumnOfUnk0x1c0(m_unk0x1c0[3]);
@@ -1404,10 +1404,10 @@ void LegoCarBuild::FUN_10025450()
MxMatrix* unk0x178 = &m_unk0x178;
*unk0x178 = m_unk0x12c;
- if (m_animPresenter->PartIsPlaced(m_unk0x110->GetName())) {
- m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition());
+ if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) {
+ m_unk0x2a4 = Vector4(m_selectedPart->GetWorldPosition());
- if (!m_unk0x2d4) {
+ if (!m_selectedPartIsPlaced) {
m_unk0x2bc = m_unk0x2a4;
m_unk0x208 = m_unk0x12c;
@@ -1421,17 +1421,17 @@ void LegoCarBuild::FUN_10025450()
else {
const LegoChar* wiredName;
- if (!m_animPresenter->FUN_10079c30(m_unk0x110->GetName())) {
- wiredName = m_animPresenter->GetWiredNameByPartName(m_unk0x110->GetName());
+ if (!m_animPresenter->FUN_10079c30(m_selectedPart->GetName())) {
+ wiredName = m_animPresenter->GetWiredNameByPartName(m_selectedPart->GetName());
}
else {
wiredName = m_animPresenter->GetWiredNameOfLastPlacedPart();
}
- LegoROI* parentROI = (LegoROI*) m_unk0x110->GetParentROI();
+ LegoROI* parentROI = (LegoROI*) m_selectedPart->GetParentROI();
m_unk0x208 = parentROI->FindChildROI(wiredName, parentROI)->GetLocal2World();
m_unk0x2bc = Vector4(parentROI->FindChildROI(wiredName, parentROI)->GetWorldPosition());
- m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition());
+ m_unk0x2a4 = Vector4(m_selectedPart->GetWorldPosition());
m_unk0x2a4[2] += (m_unk0x1c0[3][2] - m_unk0x12c[3][2]);
m_unk0x178[3][2] = m_unk0x1c0[3][2];
@@ -1653,8 +1653,8 @@ void LegoCarBuild::FUN_10025db0(const char* p_param1, undefined4 p_param2)
}
}
else {
- if (m_unk0x33c->GetUnknown0x4e() != sVar3) {
- m_unk0x33c->VTable0x6c(sVar3);
+ if (m_unk0x33c->GetEnabledChild() != sVar3) {
+ m_unk0x33c->UpdateEnabledChild(sVar3);
}
g_unk0x100f11cc = -1;
@@ -1667,7 +1667,7 @@ void LegoCarBuild::FUN_10025e40()
{
SetPresentersEnabled(m_presentersEnabled);
if (m_unk0x33c && m_Yellow_Ctl != m_unk0x33c) {
- m_unk0x33c->VTable0x6c(0);
+ m_unk0x33c->UpdateEnabledChild(0);
}
}
diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp
index a76987dd..a3adac06 100644
--- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp
@@ -204,15 +204,15 @@ void LegoCarBuildAnimPresenter::StreamingTickle()
for (i = 0; i < m_numberOfParts; i++) {
if (m_placedPartCount == i) {
- FUN_10079680(m_parts[i].m_wiredName);
+ ShowBuildPartByName(m_parts[i].m_wiredName);
}
else {
- FUN_100795d0(m_parts[i].m_wiredName);
+ HideBuildPartByName(m_parts[i].m_wiredName);
}
if (i < m_placedPartCount) {
FUN_10079050(i);
- FUN_10079680(m_parts[i].m_name);
+ ShowBuildPartByName(m_parts[i].m_name);
}
LegoChar* name = m_parts[i].m_wiredName;
@@ -321,7 +321,7 @@ MxResult LegoCarBuildAnimPresenter::Serialize(LegoStorage* p_storage)
void LegoCarBuildAnimPresenter::FUN_10079050(MxS16 p_index)
{
SwapNodesByName(m_parts[p_index].m_wiredName, m_parts[p_index].m_name);
- FUN_100795d0(m_parts[p_index].m_wiredName);
+ HideBuildPartByName(m_parts[p_index].m_wiredName);
}
// FUNCTION: LEGO1 0x10079090
@@ -447,7 +447,7 @@ void LegoCarBuildAnimPresenter::InitBuildPlatform()
// FUNCTION: LEGO1 0x100795d0
// FUNCTION: BETA10 0x10071d96
-void LegoCarBuildAnimPresenter::FUN_100795d0(LegoChar* p_param)
+void LegoCarBuildAnimPresenter::HideBuildPartByName(LegoChar* p_param)
{
LegoAnimNodeData* data = FindNodeDataByName(m_anim->GetRoot(), p_param);
@@ -469,7 +469,7 @@ void LegoCarBuildAnimPresenter::FUN_100795d0(LegoChar* p_param)
// FUNCTION: LEGO1 0x10079680
// FUNCTION: BETA10 0x10071ec5
-void LegoCarBuildAnimPresenter::FUN_10079680(LegoChar* p_param)
+void LegoCarBuildAnimPresenter::ShowBuildPartByName(LegoChar* p_param)
{
LegoAnimNodeData* data = FindNodeDataByName(m_anim->GetRoot(), p_param);
@@ -536,7 +536,7 @@ LegoTreeNode* LegoCarBuildAnimPresenter::FindNodeByName(LegoTreeNode* p_treeNode
// FUNCTION: LEGO1 0x10079790
// FUNCTION: BETA10 0x100720a3
-void LegoCarBuildAnimPresenter::FUN_10079790(const LegoChar* p_name)
+void LegoCarBuildAnimPresenter::AddPartToBuildByName(const LegoChar* p_name)
{
MxS16 i;
LegoChar buffer[40];
@@ -559,7 +559,7 @@ void LegoCarBuildAnimPresenter::FUN_10079790(const LegoChar* p_name)
((LegoCarBuild*) m_currentWorld)->SetPlacedPartCount(m_placedPartCount);
if (m_placedPartCount < m_numberOfParts) {
- FUN_10079680(m_parts[m_placedPartCount].m_wiredName);
+ ShowBuildPartByName(m_parts[m_placedPartCount].m_wiredName);
}
}
diff --git a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp
index dfa55d51..ca6c2412 100644
--- a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp
@@ -400,7 +400,7 @@ MxBool LegoAnimMMPresenter::FUN_1004b610(MxLong p_time)
}
}
- m_action->SetUnknown90(Timer()->GetTime());
+ m_action->SetTimeStarted(Timer()->GetTime());
if (m_compositePresenter != NULL) {
m_compositePresenter->VTable0x60(this);
diff --git a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp
index dadd8de7..04437877 100644
--- a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp
+++ b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp
@@ -84,7 +84,7 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller
if (!m_compositePresenter) {
SetTickleState(e_ready);
MxLong time = Timer()->GetTime();
- m_action->SetUnknown90(time);
+ m_action->SetTimeStarted(time);
}
result = SUCCESS;
@@ -134,7 +134,7 @@ void MxCompositeMediaPresenter::StartingTickle()
if (!m_unk0x4c) {
ProgressTickleState(e_streaming);
MxLong time = Timer()->GetTime();
- m_action->SetUnknown90(time);
+ m_action->SetTimeStarted(time);
}
}
}
diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
index 4a026cd3..16e72fbb 100644
--- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
@@ -18,12 +18,12 @@ DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c)
// FUNCTION: LEGO1 0x10043f50
MxControlPresenter::MxControlPresenter()
{
- m_unk0x4c = 0;
- m_unk0x4e = -1;
+ m_style = e_none;
+ m_enabledChild = -1;
m_unk0x50 = FALSE;
- m_unk0x52 = 0;
+ m_columnsOrRows = 0;
m_states = NULL;
- m_unk0x54 = 0;
+ m_rowsOrColumns = 0;
}
// FUNCTION: LEGO1 0x10044110
@@ -37,7 +37,7 @@ MxControlPresenter::~MxControlPresenter()
// FUNCTION: LEGO1 0x10044180
MxResult MxControlPresenter::AddToManager()
{
- m_unk0x4e = 0;
+ m_enabledChild = 0;
return SUCCESS;
}
@@ -51,11 +51,11 @@ MxResult MxControlPresenter::StartAction(MxStreamController* p_controller, MxDSA
MxS16 i = 0;
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
- (*it)->Enable((m_unk0x4c != 3 || m_unk0x4e) && IsEnabled() ? m_unk0x4e == i : FALSE);
+ (*it)->Enable((m_style != e_map || m_enabledChild) && IsEnabled() ? m_enabledChild == i : FALSE);
i++;
}
- if (m_unk0x4c == 3) {
+ if (m_style == e_map) {
MxDSAction* action = (*m_list.begin())->GetAction();
action->SetFlags(action->GetFlags() | MxDSAction::c_bit11);
}
@@ -76,7 +76,7 @@ void MxControlPresenter::EndAction()
// FUNCTION: LEGO1 0x10044270
// FUNCTION: BETA10 0x100eae68
-MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter)
+MxBool MxControlPresenter::CheckButtonDown(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter)
{
assert(p_presenter);
MxVideoPresenter* presenter = dynamic_cast(p_presenter);
@@ -85,7 +85,7 @@ MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_pre
return FALSE;
}
- if (m_unk0x4c == 3) {
+ if (m_style == e_map) {
MxStillPresenter* map = (MxStillPresenter*) m_list.front();
assert(map && map->IsA("MxStillPresenter"));
@@ -100,23 +100,23 @@ MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_pre
? NULL
: map->GetBitmap()->GetStart(p_x - rect.GetLeft(), p_y - rect.GetTop());
- m_unk0x56 = 0;
+ m_stateOrCellIndex = 0;
if (m_states) {
for (MxS16 i = 1; i <= *m_states; i++) {
// TODO: Can we match without the cast here?
if (m_states[i] == (MxS16) *start) {
- m_unk0x56 = i;
+ m_stateOrCellIndex = i;
break;
}
}
}
else {
if (*start != 0) {
- m_unk0x56 = 1;
+ m_stateOrCellIndex = 1;
}
}
- if (m_unk0x56) {
+ if (m_stateOrCellIndex) {
return TRUE;
}
}
@@ -125,21 +125,21 @@ MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_pre
}
else {
if (ContainsPresenter(m_list, presenter)) {
- if (m_unk0x4c == 2) {
+ if (m_style == e_grid) {
MxS32 width = presenter->GetWidth();
MxS32 height = presenter->GetHeight();
- if (m_unk0x52 == 2 && m_unk0x54 == 2) {
+ if (m_columnsOrRows == 2 && m_rowsOrColumns == 2) {
if (p_x < presenter->GetX() + width / 2) {
- m_unk0x56 = (p_y >= presenter->GetY() + height / 2) ? 3 : 1;
+ m_stateOrCellIndex = (p_y >= presenter->GetY() + height / 2) ? 3 : 1;
}
else {
- m_unk0x56 = (p_y >= presenter->GetY() + height / 2) ? 4 : 2;
+ m_stateOrCellIndex = (p_y >= presenter->GetY() + height / 2) ? 4 : 2;
}
}
}
else {
- m_unk0x56 = -1;
+ m_stateOrCellIndex = -1;
}
return TRUE;
@@ -150,27 +150,27 @@ MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_pre
}
// FUNCTION: LEGO1 0x10044480
-MxBool MxControlPresenter::FUN_10044480(LegoControlManagerNotificationParam* p_param, MxPresenter* p_presenter)
+MxBool MxControlPresenter::Notify(LegoControlManagerNotificationParam* p_param, MxPresenter* p_presenter)
{
if (IsEnabled()) {
switch (p_param->GetNotification()) {
case c_notificationButtonUp:
- if (m_unk0x4c == 0 || m_unk0x4c == 2 || m_unk0x4c == 3) {
+ if (m_style == e_none || m_style == e_grid || m_style == e_map) {
p_param->SetClickedObjectId(m_action->GetObjectId());
p_param->SetClickedAtom(m_action->GetAtomId().GetInternal());
- VTable0x6c(0);
+ UpdateEnabledChild(0);
p_param->SetNotification(c_notificationControl);
- p_param->SetUnknown0x28(m_unk0x4e);
+ p_param->SetUnknown0x28(m_enabledChild);
return TRUE;
}
break;
case c_notificationButtonDown:
- if (FUN_10044270(p_param->GetX(), p_param->GetY(), p_presenter)) {
+ if (CheckButtonDown(p_param->GetX(), p_param->GetY(), p_presenter)) {
p_param->SetClickedObjectId(m_action->GetObjectId());
p_param->SetClickedAtom(m_action->GetAtomId().GetInternal());
- VTable0x6c(m_unk0x56);
+ UpdateEnabledChild(m_stateOrCellIndex);
p_param->SetNotification(c_notificationControl);
- p_param->SetUnknown0x28(m_unk0x4e);
+ p_param->SetUnknown0x28(m_enabledChild);
return TRUE;
}
break;
@@ -181,25 +181,25 @@ MxBool MxControlPresenter::FUN_10044480(LegoControlManagerNotificationParam* p_p
}
// FUNCTION: LEGO1 0x10044540
-void MxControlPresenter::VTable0x6c(MxS16 p_unk0x4e)
+void MxControlPresenter::UpdateEnabledChild(MxS16 p_enabledChild)
{
- if (p_unk0x4e == -1) {
- if ((MxS16) ((MxDSMultiAction*) m_action)->GetActionList()->GetNumElements() - m_unk0x4e == 1) {
- m_unk0x4e = 0;
+ if (p_enabledChild == -1) {
+ if ((MxS16) ((MxDSMultiAction*) m_action)->GetActionList()->GetNumElements() - m_enabledChild == 1) {
+ m_enabledChild = 0;
}
else {
- m_unk0x4e++;
+ m_enabledChild++;
}
}
else {
- m_unk0x4e = p_unk0x4e;
+ m_enabledChild = p_enabledChild;
}
- m_action->SetUnknown90(Timer()->GetTime());
+ m_action->SetTimeStarted(Timer()->GetTime());
MxS16 i = 0;
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
- (*it)->Enable(((m_unk0x4c == 3 && m_unk0x4e == 0) || !IsEnabled()) ? FALSE : m_unk0x4e == i);
+ (*it)->Enable(((m_style == e_map && m_enabledChild == 0) || !IsEnabled()) ? FALSE : m_enabledChild == i);
i++;
}
}
@@ -230,20 +230,20 @@ void MxControlPresenter::ParseExtra()
char* token = strtok(output, g_parseExtraTokens);
if (!SDL_strcasecmp(token, g_strTOGGLE)) {
- m_unk0x4c = 1;
+ m_style = e_toggle;
}
else if (!SDL_strcasecmp(token, g_strGRID)) {
- m_unk0x4c = 2;
+ m_style = e_grid;
token = strtok(NULL, g_parseExtraTokens);
assert(token);
- m_unk0x52 = atoi(token);
+ m_columnsOrRows = atoi(token);
token = strtok(NULL, g_parseExtraTokens);
assert(token);
- m_unk0x54 = atoi(token);
+ m_rowsOrColumns = atoi(token);
}
else if (!SDL_strcasecmp(token, g_strMAP)) {
- m_unk0x4c = 3;
+ m_style = e_map;
token = strtok(NULL, g_parseExtraTokens);
if (token) {
@@ -260,7 +260,7 @@ void MxControlPresenter::ParseExtra()
}
}
else {
- m_unk0x4c = 0;
+ m_style = e_none;
}
}
@@ -280,8 +280,8 @@ void MxControlPresenter::Enable(MxBool p_enable)
MxS16 i = 0;
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
- if (i == m_unk0x4e) {
- (*it)->Enable((m_unk0x4c != 3 || i != 0) ? p_enable : 0);
+ if (i == m_enabledChild) {
+ (*it)->Enable((m_style != e_map || i != 0) ? p_enable : 0);
break;
}
@@ -289,7 +289,7 @@ void MxControlPresenter::Enable(MxBool p_enable)
}
if (!p_enable) {
- m_unk0x4e = 0;
+ m_enabledChild = 0;
}
}
}
@@ -300,10 +300,10 @@ MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState)
MxCompositePresenterList::const_iterator it = m_list.begin();
#ifdef COMPAT_MODE
- advance(it, m_unk0x4e);
+ advance(it, m_enabledChild);
#else
// Uses forward iterator logic instead of bidrectional for some reason.
- _Advance(it, m_unk0x4e, forward_iterator_tag());
+ _Advance(it, m_enabledChild, forward_iterator_tag());
#endif
return (*it)->HasTickleStatePassed(p_tickleState);
diff --git a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp
index 6fd211c6..6c4f94ea 100644
--- a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp
+++ b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp
@@ -84,6 +84,9 @@ MxResult MxTransitionManager::Tickle()
case e_broken:
BrokenTransition();
break;
+ case e_fakeMosaic:
+ FakeMosaicTransition();
+ break;
}
return SUCCESS;
}
@@ -613,3 +616,128 @@ void MxTransitionManager::configureMxTransitionManager(TransitionType p_transiti
{
g_transitionManagerConfig = p_transitionManagerConfig;
}
+
+int g_colorOffset;
+int GetColorIndexWithLocality(int p_col, int p_row)
+{
+ int islandX = p_col / 8;
+ int islandY = p_row / 8; // Dvide screen in 8x6 tiles
+
+ int island = islandY * 8 + islandX; // tile id
+
+ if (SDL_rand(3) > island / 8) {
+ return 6 + SDL_rand(2); // emulate sky
+ }
+
+ if (SDL_rand(16) > 2) {
+ island += SDL_rand(3) - 1 + (SDL_rand(3) - 1) * 8; // blure tiles
+ }
+
+ int hash = (island + g_colorOffset) * 2654435761u;
+ int scrambled = (hash >> 16) % 32;
+
+ int finalIndex = scrambled + SDL_rand(3) - 1;
+ return abs(finalIndex) % 32;
+}
+
+void MxTransitionManager::FakeMosaicTransition()
+{
+ if (m_animationTimer == 16) {
+ m_animationTimer = 0;
+ EndTransition(TRUE);
+ return;
+ }
+
+ if (m_animationTimer == 0) {
+ g_colorOffset = SDL_rand(32);
+ for (MxS32 i = 0; i < 64; i++) {
+ m_columnOrder[i] = i;
+ }
+ for (MxS32 i = 0; i < 64; i++) {
+ MxS32 swap = SDL_rand(64);
+ std::swap(m_columnOrder[i], m_columnOrder[swap]);
+ }
+ for (MxS32 i = 0; i < 48; i++) {
+ m_randomShift[i] = SDL_rand(64);
+ }
+ }
+
+ DDSURFACEDESC ddsd = {};
+ ddsd.dwSize = sizeof(ddsd);
+ HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
+ if (res == DDERR_SURFACELOST) {
+ m_ddSurface->Restore();
+ res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
+ }
+
+ if (res == DD_OK) {
+ SubmitCopyRect(&ddsd);
+
+ static const MxU8 g_palette[32][3] = {
+ {0x00, 0x00, 0x00}, {0x12, 0x1e, 0x50}, {0x00, 0x22, 0x6c}, {0x14, 0x2d, 0x9f}, {0x0e, 0x36, 0xb0},
+ {0x0e, 0x39, 0xd0}, {0x47, 0x96, 0xe2}, {0x79, 0xaa, 0xca}, {0xff, 0xff, 0xff}, {0xc9, 0xcd, 0xcb},
+ {0xad, 0xad, 0xab}, {0xa6, 0x91, 0x8e}, {0xaf, 0x59, 0x49}, {0xc0, 0x00, 0x00}, {0xab, 0x18, 0x18},
+ {0x61, 0x0c, 0x0c}, {0x04, 0x38, 0x12}, {0x2c, 0x67, 0x28}, {0x4a, 0xb4, 0x6b}, {0x94, 0xb7, 0x7c},
+ {0xb6, 0xb9, 0x87}, {0x52, 0x4a, 0x67}, {0x87, 0x8d, 0x8a}, {0xa6, 0x91, 0x8e}, {0xf8, 0xee, 0xdc},
+ {0xf4, 0xe2, 0xc3}, {0x87, 0x8d, 0x8a}, {0xba, 0x9f, 0x12}, {0xb5, 0x83, 0x00}, {0x6a, 0x44, 0x27},
+ {0x36, 0x37, 0x34}, {0x2b, 0x23, 0x0f}
+ };
+
+ MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
+
+ for (MxS32 col = 0; col < 64; col++) {
+ 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);
+ MxS32 yStart = 10 * row;
+
+ int paletteIndex = GetColorIndexWithLocality(xShift / 10, row);
+
+ const MxU8* color = g_palette[paletteIndex];
+
+ for (MxS32 y = 0; y < 10; y++) {
+ MxU8* dest = (MxU8*) ddsd.lpSurface + (yStart + y) * ddsd.lPitch + xShift * bytesPerPixel;
+ switch (bytesPerPixel) {
+ case 1:
+ memset(dest, paletteIndex, 10);
+ break;
+ case 2: {
+ MxU32 pixel = RGB555_CREATE(color[2], color[1], color[0]);
+ MxU16* p = (MxU16*) dest;
+ for (MxS32 i = 0; i < 10; i++) {
+ p[i] = pixel;
+ }
+ break;
+ }
+ default: {
+ MxU32 pixel = RGB8888_CREATE(color[2], color[1], color[0], 255);
+ MxU32* p = (MxU32*) dest;
+ for (MxS32 i = 0; i < 10; i++) {
+ p[i] = pixel;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ SetupCopyRect(&ddsd);
+ m_ddSurface->Unlock(ddsd.lpSurface);
+
+ if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) {
+ VideoManager()
+ ->GetDisplaySurface()
+ ->GetDirectDrawSurface1()
+ ->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT);
+ }
+
+ m_animationTimer++;
+ }
+}
diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp
index 8dd094f9..dc355be7 100644
--- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp
+++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp
@@ -131,9 +131,9 @@ void LegoControlManager::FUN_100293c0(MxU32 p_objectId, const char* p_atom, MxS1
MxDSAction* action = control->GetAction();
if (action->GetObjectId() == p_objectId && action->GetAtomId().GetInternal() == p_atom) {
- ((MxControlPresenter*) control)->VTable0x6c(p_unk0x4e);
+ ((MxControlPresenter*) control)->UpdateEnabledChild(p_unk0x4e);
- if (((MxControlPresenter*) control)->GetUnknown0x4e() == 0) {
+ if (((MxControlPresenter*) control)->GetEnabledChild() == 0) {
g_unk0x100f31b0 = -1;
g_unk0x100f31b4 = NULL;
break;
@@ -154,7 +154,7 @@ MxControlPresenter* LegoControlManager::FUN_100294e0(MxS32 p_x, MxS32 p_y)
if (presenter) {
while (cursor.Next(control)) {
- if (((MxControlPresenter*) control)->FUN_10044270(p_x, p_y, presenter)) {
+ if (((MxControlPresenter*) control)->CheckButtonDown(p_x, p_y, presenter)) {
return (MxControlPresenter*) control;
}
}
@@ -185,7 +185,7 @@ MxBool LegoControlManager::FUN_10029630()
MxPresenter* presenter;
while (cursor.Next(presenter)) {
- if (((MxControlPresenter*) presenter)->FUN_10044480(&m_event, m_unk0x14)) {
+ if (((MxControlPresenter*) presenter)->Notify(&m_event, m_unk0x14)) {
g_unk0x100f31b0 = m_event.m_clickedObjectId;
g_unk0x100f31b4 = m_event.GetClickedAtom();
FUN_100292e0();
@@ -206,7 +206,7 @@ MxBool LegoControlManager::FUN_10029750()
while (cursor.Next(presenter)) {
if (presenter->GetAction() && presenter->GetAction()->GetObjectId() == g_unk0x100f31b0 &&
presenter->GetAction()->GetAtomId().GetInternal() == g_unk0x100f31b4) {
- if (((MxControlPresenter*) presenter)->FUN_10044480(&m_event, m_unk0x14)) {
+ if (((MxControlPresenter*) presenter)->Notify(&m_event, m_unk0x14)) {
FUN_100292e0();
}
diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp
index c49b766e..ebf0c1ad 100644
--- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp
@@ -818,7 +818,7 @@ void LegoAnimPresenter::StartingTickle()
m_compositePresenter->VTable0x60(this);
}
else {
- m_action->SetUnknown90(Timer()->GetTime());
+ m_action->SetTimeStarted(Timer()->GetTime());
}
ProgressTickleState(e_streaming);
diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h
index 3a3dcd08..aa30b543 100644
--- a/LEGO1/omni/include/mxdisplaysurface.h
+++ b/LEGO1/omni/include/mxdisplaysurface.h
@@ -12,6 +12,9 @@
#include
#endif
+#define RGB555_CREATE(R, G, B) (((R) << 10) | (G) << 5 | (B) << 0)
+#define RGB8888_CREATE(R, G, B, A) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B))
+
class MxBitmap;
class MxPalette;
diff --git a/LEGO1/omni/include/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h
index f82c2237..8dbccf46 100644
--- a/LEGO1/omni/include/mxdsaction.h
+++ b/LEGO1/omni/include/mxdsaction.h
@@ -56,8 +56,8 @@ class MxDSAction : public MxDSObject {
virtual MxDSAction* Clone(); // vtable+0x2c
virtual void MergeFrom(MxDSAction& p_dsAction); // vtable+0x30
virtual MxBool HasId(MxU32 p_objectId); // vtable+0x34
- virtual void SetUnknown90(MxLong p_unk0x90); // vtable+0x38
- virtual MxLong GetUnknown90(); // vtable+0x3c
+ virtual void SetTimeStarted(MxLong p_timeStarted); // vtable+0x38
+ virtual MxLong GetTimeStarted(); // vtable+0x3c
virtual MxLong GetElapsedTime(); // vtable+0x40
void AppendExtra(MxU16 p_extraLength, const char* p_extraData);
@@ -131,7 +131,7 @@ class MxDSAction : public MxDSObject {
MxCore* m_notificationObject; // 0x84
undefined4 m_unk0x88; // 0x88
MxCore* m_origin; // 0x8c
- MxLong m_unk0x90; // 0x90
+ MxLong m_timeStarted; // 0x90
};
#endif // MXDSACTION_H
diff --git a/LEGO1/omni/include/mxdsmultiaction.h b/LEGO1/omni/include/mxdsmultiaction.h
index 90cc5192..77ae8d67 100644
--- a/LEGO1/omni/include/mxdsmultiaction.h
+++ b/LEGO1/omni/include/mxdsmultiaction.h
@@ -38,7 +38,7 @@ class MxDSMultiAction : public MxDSAction {
MxDSAction* Clone() override; // vtable+0x2c
void MergeFrom(MxDSAction& p_dsAction) override; // vtable+0x30
MxBool HasId(MxU32 p_objectId) override; // vtable+0x34
- void SetUnknown90(MxLong p_unk0x90) override; // vtable+0x38
+ void SetTimeStarted(MxLong p_timeStarted) override; // vtable+0x38
// FUNCTION: BETA10 0x1004e180
MxDSActionList* GetActionList() const { return m_actionList; }
diff --git a/LEGO1/omni/src/action/mxdsaction.cpp b/LEGO1/omni/src/action/mxdsaction.cpp
index cd422d0d..aa92b9af 100644
--- a/LEGO1/omni/src/action/mxdsaction.cpp
+++ b/LEGO1/omni/src/action/mxdsaction.cpp
@@ -31,7 +31,7 @@ MxDSAction::MxDSAction()
m_notificationObject = NULL;
m_unk0x88 = 0;
m_origin = NULL;
- m_unk0x90 = INT_MIN;
+ m_timeStarted = INT_MIN;
}
// FUNCTION: LEGO1 0x100ad940
@@ -57,16 +57,16 @@ MxBool MxDSAction::HasId(MxU32 p_objectId)
// FUNCTION: LEGO1 0x100ada40
// FUNCTION: BETA10 0x1012bdf0
-void MxDSAction::SetUnknown90(MxLong p_unk0x90)
+void MxDSAction::SetTimeStarted(MxLong p_timeStarted)
{
- m_unk0x90 = p_unk0x90;
+ m_timeStarted = p_timeStarted;
}
// FUNCTION: LEGO1 0x100ada50
// FUNCTION: BETA10 0x1012be20
-MxLong MxDSAction::GetUnknown90()
+MxLong MxDSAction::GetTimeStarted()
{
- return m_unk0x90;
+ return m_timeStarted;
}
// FUNCTION: LEGO1 0x100ada80
@@ -92,7 +92,7 @@ void MxDSAction::CopyFrom(MxDSAction& p_dsAction)
m_notificationObject = p_dsAction.m_notificationObject;
m_unk0x88 = p_dsAction.m_unk0x88;
m_origin = p_dsAction.m_origin;
- m_unk0x90 = p_dsAction.m_unk0x90;
+ m_timeStarted = p_dsAction.m_timeStarted;
}
// FUNCTION: BETA10 0x1012b2b3
@@ -158,7 +158,7 @@ MxDSAction* MxDSAction::Clone()
// FUNCTION: BETA10 0x1012b4ca
MxLong MxDSAction::GetElapsedTime()
{
- return Timer()->GetTime() - m_unk0x90;
+ return Timer()->GetTime() - m_timeStarted;
}
// FUNCTION: LEGO1 0x100add00
diff --git a/LEGO1/omni/src/action/mxdsmultiaction.cpp b/LEGO1/omni/src/action/mxdsmultiaction.cpp
index 452bbee5..fdd493cb 100644
--- a/LEGO1/omni/src/action/mxdsmultiaction.cpp
+++ b/LEGO1/omni/src/action/mxdsmultiaction.cpp
@@ -59,14 +59,14 @@ MxDSMultiAction& MxDSMultiAction::operator=(MxDSMultiAction& p_dsMultiAction)
// FUNCTION: LEGO1 0x100ca290
// FUNCTION: BETA10 0x10159728
-void MxDSMultiAction::SetUnknown90(MxLong p_unk0x90)
+void MxDSMultiAction::SetTimeStarted(MxLong p_timeStarted)
{
- m_unk0x90 = p_unk0x90;
+ m_timeStarted = p_timeStarted;
MxDSActionListCursor cursor(m_actionList);
MxDSAction* action;
while (cursor.Next(action)) {
- action->SetUnknown90(p_unk0x90);
+ action->SetTimeStarted(p_timeStarted);
}
}
diff --git a/LEGO1/omni/src/common/mxmediapresenter.cpp b/LEGO1/omni/src/common/mxmediapresenter.cpp
index 0a1b96d9..c8b9abcd 100644
--- a/LEGO1/omni/src/common/mxmediapresenter.cpp
+++ b/LEGO1/omni/src/common/mxmediapresenter.cpp
@@ -252,7 +252,7 @@ void MxMediaPresenter::Enable(MxBool p_enable)
if (p_enable) {
MxLong time = Timer()->GetTime();
- m_action->SetUnknown90(time);
+ m_action->SetTimeStarted(time);
SetTickleState(e_repeating);
}
else {
diff --git a/LEGO1/omni/src/stream/mxdsbuffer.cpp b/LEGO1/omni/src/stream/mxdsbuffer.cpp
index 9cfe3b24..3634b6c7 100644
--- a/LEGO1/omni/src/stream/mxdsbuffer.cpp
+++ b/LEGO1/omni/src/stream/mxdsbuffer.cpp
@@ -210,7 +210,7 @@ MxResult MxDSBuffer::StartPresenterFromAction(
p_objectheader->SetUnknown28(p_action1->GetUnknown28());
p_objectheader->SetNotificationObject(p_action1->GetNotificationObject());
p_objectheader->SetOrigin(p_action1->GetOrigin());
- p_objectheader->SetUnknown90(p_action1->GetUnknown90());
+ p_objectheader->SetTimeStarted(p_action1->GetTimeStarted());
p_objectheader->MergeFrom(*p_action1);
m_unk0x30->SetInternalAction(p_objectheader->Clone());
diff --git a/LEGO1/omni/src/stream/mxstreamcontroller.cpp b/LEGO1/omni/src/stream/mxstreamcontroller.cpp
index dadd03ca..8c3cf079 100644
--- a/LEGO1/omni/src/stream/mxstreamcontroller.cpp
+++ b/LEGO1/omni/src/stream/mxstreamcontroller.cpp
@@ -202,7 +202,7 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset)
streamingAction->SetObjectId(p_action->GetObjectId());
MxLong time = Timer()->GetTime();
- streamingAction->SetUnknown90(time);
+ streamingAction->SetTimeStarted(time);
m_unk0x3c.PushBack(streamingAction);
return SUCCESS;
diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp
index b10330f2..5d08a64b 100644
--- a/LEGO1/omni/src/video/mxdisplaysurface.cpp
+++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp
@@ -18,9 +18,6 @@
DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac);
-#define RGB555_CREATE(R, G, B) (((R) << 10) | (G) << 5 | (B) << 0)
-#define RGB8888_CREATE(R, G, B, A) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B))
-
// GLOBAL: LEGO1 0x1010215c
MxU32 g_unk0x1010215c = 0;
@@ -399,86 +396,81 @@ void MxDisplaySurface::VTable0x28(
DDSURFACEDESC ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
+ ddsd.dwWidth = p_width;
+ ddsd.dwHeight = p_height;
+ ddsd.ddpfPixelFormat = m_surfaceDesc.ddpfPixelFormat;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
- HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
+ LPDIRECTDRAWSURFACE tempSurface = nullptr;
+ LPDIRECTDRAW draw = MVideoManager()->GetDirectDraw();
+ HRESULT hr = draw->CreateSurface(&ddsd, &tempSurface, nullptr);
+ if (hr != DD_OK || !tempSurface) {
+ return;
+ }
+
+ DDCOLORKEY colorKey;
+ colorKey.dwColorSpaceLowValue = colorKey.dwColorSpaceHighValue = RGB555_CREATE(0x1f, 0, 0x1f);
+ tempSurface->SetColorKey(DDCKEY_SRCBLT, &colorKey);
+
+ DDSURFACEDESC tempDesc;
+ memset(&tempDesc, 0, sizeof(tempDesc));
+ tempDesc.dwSize = sizeof(tempDesc);
+
+ hr = tempSurface->Lock(NULL, &tempDesc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (hr == DDERR_SURFACELOST) {
- m_ddSurface2->Restore();
- hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
+ tempSurface->Restore();
+ hr = tempSurface->Lock(NULL, &tempDesc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
}
if (hr != DD_OK) {
+ tempSurface->Release();
return;
}
MxU8* data = p_bitmap->GetStart(p_left, p_top);
MxS32 bytesPerPixel = m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount / 8;
- if (m_videoParam.Flags().GetF1bit3()) {
- p_bottom *= 2;
- p_right *= 2;
+ MxU8* surface = (MxU8*) tempDesc.lpSurface;
- MxU8* surface = (MxU8*) ddsd.lpSurface + (bytesPerPixel * p_right) + (p_bottom * ddsd.lPitch);
- MxLong stride = -p_width + GetAdjustedStride(p_bitmap);
- MxS32 copyWidth = p_width * bytesPerPixel * 2;
- MxLong length = -(copyWidth) + ddsd.lPitch;
+ MxLong stride = (bytesPerPixel == 1) ? GetAdjustedStride(p_bitmap) : -p_width + GetAdjustedStride(p_bitmap);
+ MxLong length = tempDesc.lPitch - (p_width * bytesPerPixel);
- while (p_height--) {
- MxU8* surfaceBefore = surface;
-
- for (MxS32 i = 0; i < p_width; i++) {
- if (bytesPerPixel == 1) {
- surface[0] = surface[1] = *data;
- }
- else if (bytesPerPixel == 2) {
- ((MxU16*) surface)[0] = ((MxU16*) surface)[1] = m_16bitPal[*data];
- }
- else {
- ((MxU32*) surface)[0] = ((MxU32*) surface)[1] = m_32bitPal[*data];
- }
- surface += bytesPerPixel * 2;
- data++;
- }
-
- if (stride || length != ddsd.lPitch - copyWidth) {
- data += stride;
- surface += length;
- }
-
- memcpy(surface, surfaceBefore, copyWidth);
- surface += ddsd.lPitch;
+ for (MxS32 i = 0; i < p_height; i++) {
+ if (bytesPerPixel == 1) {
+ memcpy(surface, data, p_width);
+ surface += length + p_width;
}
+ else if (bytesPerPixel == 2) {
+ for (MxS32 j = 0; j < p_width; j++) {
+ *(MxU16*) surface = m_16bitPal[*data++];
+ surface += bytesPerPixel;
+ }
+
+ surface += length;
+ }
+ else {
+ for (MxS32 j = 0; j < p_width; j++) {
+ *(MxU32*) surface = m_32bitPal[*data++];
+ surface += bytesPerPixel;
+ }
+ surface += length;
+ }
+
+ data += stride;
+ }
+
+ tempSurface->Unlock(NULL);
+
+ if (m_videoParam.Flags().GetF1bit3()) {
+ RECT destRect = {p_right, p_bottom, p_right + p_width * 2, p_bottom + p_height * 2};
+ m_ddSurface2->Blt(&destRect, tempSurface, NULL, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
}
else {
- MxU8* surface = (MxU8*) ddsd.lpSurface + (bytesPerPixel * p_right) + (p_bottom * ddsd.lPitch);
- MxLong stride = (bytesPerPixel == 1) ? GetAdjustedStride(p_bitmap) : -p_width + GetAdjustedStride(p_bitmap);
- MxLong length = ddsd.lPitch - (p_width * bytesPerPixel);
-
- for (MxS32 i = 0; i < p_height; i++) {
- if (bytesPerPixel == 1) {
- memcpy(surface, data, p_width);
- surface += length + p_width;
- }
- else if (bytesPerPixel == 2) {
- for (MxS32 j = 0; j < p_width; j++) {
- *(MxU16*) surface = m_16bitPal[*data++];
- surface += bytesPerPixel;
- }
-
- surface += length;
- }
- else {
- for (MxS32 j = 0; j < p_width; j++) {
- *(MxU32*) surface = m_32bitPal[*data++];
- surface += bytesPerPixel;
- }
- surface += length;
- }
-
- data += stride;
- }
+ m_ddSurface2->BltFast(p_right, p_bottom, tempSurface, NULL, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);
}
- m_ddSurface2->Unlock(ddsd.lpSurface);
+ tempSurface->Release();
}
// FUNCTION: LEGO1 0x100bb1d0
diff --git a/miniwin/src/d3drm/backends/opengl1/actual.cpp b/miniwin/src/d3drm/backends/opengl1/actual.cpp
index b1a464d5..a86ebec1 100644
--- a/miniwin/src/d3drm/backends/opengl1/actual.cpp
+++ b/miniwin/src/d3drm/backends/opengl1/actual.cpp
@@ -42,6 +42,13 @@ void GL11_DestroyTexture(GLuint texId)
glDeleteTextures(1, &texId);
}
+int GL11_GetMaxTextureSize()
+{
+ GLint maxTextureSize = 0;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+ return maxTextureSize;
+}
+
GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUi)
{
GLuint texId;
diff --git a/miniwin/src/d3drm/backends/opengl1/actual.h b/miniwin/src/d3drm/backends/opengl1/actual.h
index 9460119c..87f33687 100644
--- a/miniwin/src/d3drm/backends/opengl1/actual.h
+++ b/miniwin/src/d3drm/backends/opengl1/actual.h
@@ -64,6 +64,7 @@ struct GLMeshCacheEntry {
void GL11_InitState();
void GL11_LoadExtensions();
void GL11_DestroyTexture(GLuint texId);
+int GL11_GetMaxTextureSize();
GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUI);
void GL11_UploadMesh(GLMeshCacheEntry& cache, bool hasTexture);
void GL11_DestroyMesh(GLMeshCacheEntry& cache);
diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp
index 8c43d14a..00088da9 100644
--- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp
+++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp
@@ -132,10 +132,21 @@ static Uint32 UploadTextureData(SDL_Surface* src, bool useNPOT, bool isUi)
SDL_Surface* finalSurface = working;
- int newW = NextPowerOfTwo(working->w);
- int newH = NextPowerOfTwo(working->h);
+ int newW = working->w;
+ int newH = working->h;
+ if (!useNPOT) {
+ newW = NextPowerOfTwo(newW);
+ newH = NextPowerOfTwo(newH);
+ }
+ int max = GL11_GetMaxTextureSize();
+ if (newW > max) {
+ newW = max;
+ }
+ if (newH > max) {
+ newH = max;
+ }
- if (!useNPOT && (newW != working->w || newH != working->h)) {
+ if (newW != working->w || newH != working->h) {
SDL_Surface* resized = SDL_CreateSurface(newW, newH, working->format);
if (!resized) {
SDL_Log("SDL_CreateSurface (resize) failed: %s", SDL_GetError());