From 4d8ba1986e3d46e9a6bcf7b182d8b77a5bc51bf2 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 2 Jul 2025 17:07:16 -0700 Subject: [PATCH 01/11] Fix writing default texture (#1602) --- LEGO1/lego/legoomni/src/common/legoutils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index a9ea98a7..1e0dbba5 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -705,14 +705,14 @@ void WriteDefaultTexture(LegoStorage* p_storage, const char* p_name) if (image != NULL) { if (desc.dwWidth == desc.lPitch) { - memcpy(desc.lpSurface, image->GetBits(), desc.dwWidth * desc.dwHeight); + memcpy(image->GetBits(), desc.lpSurface, desc.dwWidth * desc.dwHeight); } else { MxU8* surface = (MxU8*) desc.lpSurface; - const LegoU8* bits = image->GetBits(); + LegoU8* bits = image->GetBits(); for (MxS32 i = 0; i < desc.dwHeight; i++) { - memcpy(surface, bits, desc.dwWidth); + memcpy(bits, surface, desc.dwWidth); surface += desc.lPitch; bits += desc.dwWidth; } From 44d1ad13fed7416451348f0401477bf202eb680a Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Thu, 3 Jul 2025 21:57:47 +0200 Subject: [PATCH 02/11] Set dwDDFX using flag (#1603) --- LEGO1/omni/src/video/mxdisplaysurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index 86f1b4dc..bd751a57 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -861,7 +861,7 @@ void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p DDBLTFX data; memset(&data, 0, sizeof(data)); data.dwSize = sizeof(data); - data.dwDDFX = 8; + data.dwDDFX = DDBLTFX_NOTEARING; if (m_ddSurface1->Blt((LPRECT) &b, m_ddSurface2, (LPRECT) &a, 0, &data) == DDERR_SURFACELOST) { m_ddSurface1->Restore(); From 16c76c96f23aa26967ba2fdc3291d8f33536ee80 Mon Sep 17 00:00:00 2001 From: Fabian Neundorf Date: Thu, 3 Jul 2025 23:56:48 +0200 Subject: [PATCH 03/11] Clear time started unknown in `MxDSAction` (#1604) This should not be confused with `GetStartTime()`, as that represents the time offset from the SI file. --- .../legoomni/src/common/legoanimmmpresenter.cpp | 2 +- .../src/common/mxcompositemediapresenter.cpp | 4 ++-- .../legoomni/src/common/mxcontrolpresenter.cpp | 2 +- .../lego/legoomni/src/video/legoanimpresenter.cpp | 2 +- LEGO1/omni/include/mxdsaction.h | 6 +++--- LEGO1/omni/include/mxdsmultiaction.h | 2 +- LEGO1/omni/src/action/mxdsaction.cpp | 14 +++++++------- LEGO1/omni/src/action/mxdsmultiaction.cpp | 6 +++--- LEGO1/omni/src/common/mxmediapresenter.cpp | 2 +- LEGO1/omni/src/stream/mxdsbuffer.cpp | 2 +- LEGO1/omni/src/stream/mxstreamcontroller.cpp | 2 +- 11 files changed, 22 insertions(+), 22 deletions(-) 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 13ce2cee..76780d6e 100644 --- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp @@ -189,7 +189,7 @@ void MxControlPresenter::VTable0x6c(MxS16 p_unk0x4e) m_unk0x4e = p_unk0x4e; } - 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++) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 73918606..82c76aa6 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -815,7 +815,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/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h index 7e2c4d89..2899d3fb 100644 --- a/LEGO1/omni/include/mxdsaction.h +++ b/LEGO1/omni/include/mxdsaction.h @@ -55,8 +55,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); @@ -130,7 +130,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 035b1046..4b77c6ed 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 39adfe9b..648de181 100644 --- a/LEGO1/omni/src/action/mxdsmultiaction.cpp +++ b/LEGO1/omni/src/action/mxdsmultiaction.cpp @@ -57,14 +57,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 d9216b3f..a73be62f 100644 --- a/LEGO1/omni/src/stream/mxdsbuffer.cpp +++ b/LEGO1/omni/src/stream/mxdsbuffer.cpp @@ -209,7 +209,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; From df3d144ed9b71006e142074ff8fbb9b62d8561b5 Mon Sep 17 00:00:00 2001 From: MasterTimeThief Date: Thu, 3 Jul 2025 20:23:07 -0400 Subject: [PATCH 04/11] Renamed more functions and variables in Car Build sections (#1605) * Renamed variables and functions related to the Car Build sections * Car Build variable renaming - fixed issues and added enum `ShelfState` * Fixed some spacing in `legocarbuildpresenter.h` * Fixed tab spacing * Changed `m_shelfState` back to `MxU16` * Cleared up `InitBuildPlatform` * Fixed comments * Renamed more functions and variables in Car Build sections * Named `SelectPartFromMousePosition` * Updated spacing formatting in `LegoCarBuild` --- LEGO1/lego/legoomni/include/legocarbuild.h | 14 +-- .../legoomni/include/legocarbuildpresenter.h | 6 +- .../lego/legoomni/src/build/legocarbuild.cpp | 112 +++++++++--------- .../src/build/legocarbuildpresenter.cpp | 16 +-- 4 files changed, 74 insertions(+), 74 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index f13f0450..a96b7b67 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -135,11 +135,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); @@ -182,7 +182,7 @@ class LegoCarBuild : public LegoWorld { MxU8 m_unk0x109; // 0x109 MxU16 m_unk0x10a; // 0x10a DWORD m_unk0x10c; // 0x10c - LegoROI* m_unk0x110; // 0x110 + LegoROI* m_selectedPart; // 0x110 BoundingSphere m_unk0x114; // 0x114 MxMatrix m_unk0x12c; // 0x12c undefined m_unk0x174; // 0x174 @@ -200,10 +200,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/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 6876d199..a7b1e863 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -93,9 +93,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; @@ -135,7 +135,7 @@ LegoCarBuild::LegoCarBuild() LegoCarBuild::~LegoCarBuild() { m_unk0x100 = 0; - m_unk0x110 = NULL; + m_selectedPart = NULL; if (m_animPresenter) { m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_selected); @@ -288,7 +288,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; @@ -299,18 +299,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; } } @@ -320,8 +320,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(); } @@ -360,7 +360,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]; @@ -408,7 +408,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); } } } @@ -474,15 +474,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()) { @@ -541,15 +541,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) { @@ -687,7 +687,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() ); @@ -817,7 +817,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; @@ -828,34 +828,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(); } } @@ -892,21 +892,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(); @@ -1021,7 +1021,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); } @@ -1125,7 +1125,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); } @@ -1268,7 +1268,7 @@ void LegoCarBuild::FUN_10024f30() // FUNCTION: BETA10 0x1006dfce void LegoCarBuild::FUN_10024f50() { - m_unk0x2d4 = FALSE; + m_selectedPartIsPlaced = FALSE; m_animPresenter->RotateAroundYAxis(g_rotationAngleStepYAxis); } @@ -1276,7 +1276,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); } } @@ -1311,31 +1311,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 (strnicmp(m_unk0x110->GetName(), "JSFRNT", strlen("JSFRNT")) == 0) { + if (m_animPresenter->StringDoesNotEndOnZero(m_selectedPart->GetName()) && m_Decals_Ctl) { + if (strnicmp(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 (strnicmp(m_unk0x110->GetName(), "JSWNSH", strlen("JSWNSH")) == 0) { + else if (strnicmp(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 (strnicmp(m_unk0x110->GetName(), "RCBACK", strlen("RCBACK")) == 0) { + else if (strnicmp(m_selectedPart->GetName(), "RCBACK", strlen("RCBACK")) == 0) { m_Decals_Ctl1->Enable(p_enabled); } - else if (strnicmp(m_unk0x110->GetName(), "RCTAIL", strlen("RCTAIL")) == 0) { + else if (strnicmp(m_selectedPart->GetName(), "RCTAIL", strlen("RCTAIL")) == 0) { m_Decals_Ctl2->Enable(p_enabled); } - else if (m_Decals_Ctl1 && strnicmp(m_unk0x110->GetName(), "chljety", strlen("chljety")) == 0) { + else if (m_Decals_Ctl1 && strnicmp(m_selectedPart->GetName(), "chljety", strlen("chljety")) == 0) { m_Decals_Ctl1->Enable(p_enabled); } - else if (m_Decals_Ctl2 && strnicmp(m_unk0x110->GetName(), "chrjety", strlen("chrjety")) == 0) { + else if (m_Decals_Ctl2 && strnicmp(m_selectedPart->GetName(), "chrjety", strlen("chrjety")) == 0) { m_Decals_Ctl2->Enable(p_enabled); } else if (m_Decals_Ctl) { @@ -1351,7 +1351,7 @@ void LegoCarBuild::FUN_10025350(MxS32 p_objectId) const LegoChar* color; LegoChar buffer[256]; - if (!m_unk0x110) { + if (!m_selectedPart) { return; } @@ -1379,8 +1379,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); } @@ -1388,7 +1388,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]); @@ -1401,10 +1401,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; @@ -1418,17 +1418,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]; diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index d6512c8b..c2dbbd8a 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -202,15 +202,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; @@ -319,7 +319,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 @@ -445,7 +445,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); @@ -467,7 +467,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); @@ -534,7 +534,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]; @@ -557,7 +557,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); } } From 5544640b228ccf3ac2e735363c72b57e9e961c42 Mon Sep 17 00:00:00 2001 From: Fabian Neundorf Date: Fri, 4 Jul 2025 21:53:50 +0200 Subject: [PATCH 05/11] Clear unknowns in `MxControlPresenter` (#1606) --- .../legoomni/include/mxcontrolpresenter.h | 29 ++++--- LEGO1/lego/legoomni/src/actors/radio.cpp | 2 +- .../lego/legoomni/src/build/legocarbuild.cpp | 6 +- .../src/common/mxcontrolpresenter.cpp | 86 +++++++++---------- .../src/control/legocontrolmanager.cpp | 10 +-- 5 files changed, 70 insertions(+), 63 deletions(-) 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/src/actors/radio.cpp b/LEGO1/lego/legoomni/src/actors/radio.cpp index d32955fe..fa600b7d 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 a7b1e863..0cea0c0d 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -1650,8 +1650,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; @@ -1664,7 +1664,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/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp index 76780d6e..9374cb9f 100644 --- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp @@ -16,12 +16,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 @@ -35,7 +35,7 @@ MxControlPresenter::~MxControlPresenter() // FUNCTION: LEGO1 0x10044180 MxResult MxControlPresenter::AddToManager() { - m_unk0x4e = 0; + m_enabledChild = 0; return SUCCESS; } @@ -49,11 +49,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); } @@ -74,12 +74,12 @@ 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 = (MxVideoPresenter*) p_presenter; - if (m_unk0x4c == 3) { + if (m_style == e_map) { MxStillPresenter* map = (MxStillPresenter*) m_list.front(); assert(map && map->IsA("MxStillPresenter")); @@ -94,23 +94,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; } } @@ -119,21 +119,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; @@ -144,27 +144,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; @@ -175,25 +175,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->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++; } } @@ -224,20 +224,20 @@ void MxControlPresenter::ParseExtra() char* token = strtok(output, g_parseExtraTokens); if (!strcmpi(token, g_strTOGGLE)) { - m_unk0x4c = 1; + m_style = e_toggle; } else if (!strcmpi(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 (!strcmpi(token, g_strMAP)) { - m_unk0x4c = 3; + m_style = e_map; token = strtok(NULL, g_parseExtraTokens); if (token) { @@ -254,7 +254,7 @@ void MxControlPresenter::ParseExtra() } } else { - m_unk0x4c = 0; + m_style = e_none; } } @@ -274,8 +274,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; } @@ -283,7 +283,7 @@ void MxControlPresenter::Enable(MxBool p_enable) } if (!p_enable) { - m_unk0x4e = 0; + m_enabledChild = 0; } } } @@ -294,10 +294,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/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(); } From af9f7cd7915bd2ef7b87a34e051f2bebcb8b61d6 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Sat, 5 Jul 2025 01:48:13 +0200 Subject: [PATCH 06/11] 3DS: Account for sprite scaling when resizing UI (#503) --- .../src/common/mxtransitionmanager.cpp | 88 +++++++++++-------- .../src/d3drm/backends/citro3d/renderer.cpp | 61 ++++++++----- .../src/d3drm/backends/directx9/renderer.cpp | 2 +- miniwin/src/d3drm/backends/opengl1/actual.cpp | 4 +- miniwin/src/d3drm/backends/opengl1/actual.h | 2 +- .../src/d3drm/backends/opengl1/renderer.cpp | 10 +-- .../src/d3drm/backends/opengles2/renderer.cpp | 10 +-- .../src/d3drm/backends/sdl3gpu/renderer.cpp | 2 +- .../src/d3drm/backends/software/renderer.cpp | 2 +- miniwin/src/ddraw/framebuffer.cpp | 4 +- miniwin/src/internal/d3drmrenderer.h | 2 +- miniwin/src/internal/d3drmrenderer_citro3d.h | 2 +- miniwin/src/internal/d3drmrenderer_directx9.h | 2 +- miniwin/src/internal/d3drmrenderer_opengl1.h | 2 +- .../src/internal/d3drmrenderer_opengles2.h | 2 +- miniwin/src/internal/d3drmrenderer_sdl3gpu.h | 2 +- miniwin/src/internal/d3drmrenderer_software.h | 2 +- 17 files changed, 116 insertions(+), 83 deletions(-) diff --git a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp index 6c4f94ea..27086eb3 100644 --- a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp @@ -642,8 +642,14 @@ int GetColorIndexWithLocality(int p_col, int p_row) void MxTransitionManager::FakeMosaicTransition() { + static LPDIRECTDRAWSURFACE g_fakeTranstionSurface = nullptr; + if (m_animationTimer == 16) { m_animationTimer = 0; + if (g_fakeTranstionSurface) { + g_fakeTranstionSurface->Release(); + g_fakeTranstionSurface = nullptr; + } EndTransition(TRUE); return; } @@ -662,12 +668,33 @@ void MxTransitionManager::FakeMosaicTransition() } } + if (!g_fakeTranstionSurface) { + DDSURFACEDESC mainDesc = {}; + mainDesc.dwSize = sizeof(mainDesc); + if (m_ddSurface->GetSurfaceDesc(&mainDesc) != DD_OK) { + return; + } + + DDSURFACEDESC tempDesc = {}; + tempDesc.dwSize = sizeof(tempDesc); + tempDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; + tempDesc.dwWidth = 64; + tempDesc.dwHeight = 48; + tempDesc.ddpfPixelFormat = mainDesc.ddpfPixelFormat; + tempDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + + HRESULT hr = MVideoManager()->GetDirectDraw()->CreateSurface(&tempDesc, &g_fakeTranstionSurface, nullptr); + if (hr != DD_OK || !g_fakeTranstionSurface) { + return; + } + } + DDSURFACEDESC ddsd = {}; ddsd.dwSize = sizeof(ddsd); - HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL); + HRESULT res = g_fakeTranstionSurface->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); + g_fakeTranstionSurface->Restore(); + res = g_fakeTranstionSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL); } if (res == DD_OK) { @@ -694,50 +721,33 @@ void MxTransitionManager::FakeMosaicTransition() } 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); + int paletteIndex = GetColorIndexWithLocality(col, 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; - } - } + MxS32 xShift = (m_randomShift[row] + col) % 64; + MxU8* dest = (MxU8*) ddsd.lpSurface + row * ddsd.lPitch + xShift * bytesPerPixel; + + switch (bytesPerPixel) { + case 1: + *dest = paletteIndex; + break; + case 2: + *((MxU16*) dest) = RGB555_CREATE(color[2], color[1], color[0]); + break; + default: + *((MxU32*) dest) = RGB8888_CREATE(color[2], color[1], color[0], 255); + break; } } } SetupCopyRect(&ddsd); - m_ddSurface->Unlock(ddsd.lpSurface); + g_fakeTranstionSurface->Unlock(ddsd.lpSurface); - if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) { - VideoManager() - ->GetDisplaySurface() - ->GetDirectDrawSurface1() - ->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT); - } - - m_animationTimer++; + RECT srcRect = {0, 0, 64, 48}; + m_ddSurface->Blt(&g_fullScreenRect, g_fakeTranstionSurface, &srcRect, DDBLT_WAIT, NULL); } + + m_animationTimer++; } diff --git a/miniwin/src/d3drm/backends/citro3d/renderer.cpp b/miniwin/src/d3drm/backends/citro3d/renderer.cpp index f71f9255..ab9088bc 100644 --- a/miniwin/src/d3drm/backends/citro3d/renderer.cpp +++ b/miniwin/src/d3drm/backends/citro3d/renderer.cpp @@ -115,31 +115,34 @@ static int NearestPowerOfTwoClamp(int val) return 512; } -static SDL_Surface* ConvertAndResizeSurface(SDL_Surface* original, bool isUI, float scale) +static SDL_Surface* ConvertAndResizeSurface(SDL_Surface* original, bool isUI, float scaleX, float scaleY) { - SDL_Surface* converted = SDL_ConvertSurface(original, SDL_PIXELFORMAT_RGBA8888); - if (!converted) { - return nullptr; - } if (!isUI) { - return converted; + return SDL_ConvertSurface(original, SDL_PIXELFORMAT_RGBA8888); } - int scaledW = static_cast(converted->w * scale); - int scaledH = static_cast(converted->h * scale); + scaleX = std::min(scaleX, 1.0f); + scaleY = std::min(scaleY, 1.0f); + + int scaledW = static_cast(original->w * scaleX); + int scaledH = static_cast(original->h * scaleY); int paddedW = NearestPowerOfTwoClamp(scaledW); int paddedH = NearestPowerOfTwoClamp(scaledH); SDL_Surface* padded = SDL_CreateSurface(paddedW, paddedH, SDL_PIXELFORMAT_RGBA8888); if (!padded) { - SDL_DestroySurface(converted); return nullptr; } - SDL_Rect dstRect = {0, 0, scaledW, scaledH}; - SDL_BlitSurfaceScaled(converted, nullptr, padded, &dstRect, SDL_SCALEMODE_LINEAR); - SDL_DestroySurface(converted); + if (scaleX == 1.0f && scaleY == 1.0f) { + SDL_BlitSurface(original, nullptr, padded, nullptr); + } + else { + SDL_ScaleMode scaleMode = (scaleX >= 1.0f && scaleY >= 1.0f) ? SDL_SCALEMODE_NEAREST : SDL_SCALEMODE_LINEAR; + SDL_Rect dstRect = {0, 0, scaledW, scaledH}; + SDL_BlitSurfaceScaled(original, nullptr, padded, &dstRect, scaleMode); + } return padded; } @@ -181,9 +184,9 @@ static void EncodeTextureLayout(const u8* src, u8* dst, int width, int height) } } -static bool ConvertAndUploadTexture(C3D_Tex* tex, SDL_Surface* originalSurface, bool isUI, float scale) +static bool ConvertAndUploadTexture(C3D_Tex* tex, SDL_Surface* originalSurface, bool isUI, float scaleX, float scaleY) { - SDL_Surface* resized = ConvertAndResizeSurface(originalSurface, isUI, scale); + SDL_Surface* resized = ConvertAndResizeSurface(originalSurface, isUI, scaleX, scaleY); if (!resized) { return false; } @@ -198,18 +201,24 @@ static bool ConvertAndUploadTexture(C3D_Tex* tex, SDL_Surface* originalSurface, params.maxLevel = isUI ? 0 : 4; params.type = GPU_TEX_2D; if (!C3D_TexInitWithParams(tex, nullptr, params)) { - SDL_DestroySurface(resized); + if (resized != originalSurface) { + SDL_DestroySurface(resized); + } return false; } uint8_t* tiledData = (uint8_t*) malloc(width * height * 4); if (!tiledData) { - SDL_DestroySurface(resized); + if (resized != originalSurface) { + SDL_DestroySurface(resized); + } return false; } EncodeTextureLayout((const u8*) resized->pixels, tiledData, width, height); - SDL_DestroySurface(resized); + if (resized != originalSurface) { + SDL_DestroySurface(resized); + } C3D_TexUpload(tex, tiledData); free(tiledData); @@ -228,7 +237,7 @@ static bool ConvertAndUploadTexture(C3D_Tex* tex, SDL_Surface* originalSurface, return true; } -Uint32 Citro3DRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) +Uint32 Citro3DRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -242,7 +251,13 @@ Uint32 Citro3DRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) if (tex.texture == texture) { if (tex.version != texture->m_version) { C3D_TexDelete(&tex.c3dTex); - if (!ConvertAndUploadTexture(&tex.c3dTex, originalSurface, isUi, m_viewportTransform.scale)) { + if (!ConvertAndUploadTexture( + &tex.c3dTex, + originalSurface, + isUI, + scaleX * m_viewportTransform.scale, + scaleY * m_viewportTransform.scale + )) { return NO_TEXTURE_ID; } @@ -260,7 +275,13 @@ Uint32 Citro3DRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) entry.width = NearestPowerOfTwoClamp(originalW * m_viewportTransform.scale); entry.height = NearestPowerOfTwoClamp(originalH * m_viewportTransform.scale); - if (!ConvertAndUploadTexture(&entry.c3dTex, originalSurface, isUi, m_viewportTransform.scale)) { + if (!ConvertAndUploadTexture( + &entry.c3dTex, + originalSurface, + isUI, + scaleX * m_viewportTransform.scale, + scaleY * m_viewportTransform.scale + )) { return NO_TEXTURE_ID; } diff --git a/miniwin/src/d3drm/backends/directx9/renderer.cpp b/miniwin/src/d3drm/backends/directx9/renderer.cpp index 5c8a2354..e97dfa17 100644 --- a/miniwin/src/d3drm/backends/directx9/renderer.cpp +++ b/miniwin/src/d3drm/backends/directx9/renderer.cpp @@ -76,7 +76,7 @@ void DirectX9Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* ); } -Uint32 DirectX9Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) +Uint32 DirectX9Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); diff --git a/miniwin/src/d3drm/backends/opengl1/actual.cpp b/miniwin/src/d3drm/backends/opengl1/actual.cpp index a86ebec1..4b83daff 100644 --- a/miniwin/src/d3drm/backends/opengl1/actual.cpp +++ b/miniwin/src/d3drm/backends/opengl1/actual.cpp @@ -49,12 +49,12 @@ int GL11_GetMaxTextureSize() return maxTextureSize; } -GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUi) +GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUI, float scaleX, float scaleY) { GLuint texId; glGenTextures(1, &texId); glBindTexture(GL_TEXTURE_2D, texId); - if (isUi) { + if (isUI) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); diff --git a/miniwin/src/d3drm/backends/opengl1/actual.h b/miniwin/src/d3drm/backends/opengl1/actual.h index 87f33687..232fc88d 100644 --- a/miniwin/src/d3drm/backends/opengl1/actual.h +++ b/miniwin/src/d3drm/backends/opengl1/actual.h @@ -65,7 +65,7 @@ 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); +GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUI, float scaleX, float scaleY); void GL11_UploadMesh(GLMeshCacheEntry& cache, bool hasTexture); void GL11_DestroyMesh(GLMeshCacheEntry& cache); void GL11_BeginFrame(const Matrix4x4* projection); diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index 00088da9..e537a396 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -119,7 +119,7 @@ static int NextPowerOfTwo(int v) return power; } -static Uint32 UploadTextureData(SDL_Surface* src, bool useNPOT, bool isUi) +static Uint32 UploadTextureData(SDL_Surface* src, bool useNPOT, bool isUI, float scaleX, float scaleY) { SDL_Surface* working = src; if (src->format != SDL_PIXELFORMAT_RGBA32) { @@ -166,14 +166,14 @@ static Uint32 UploadTextureData(SDL_Surface* src, bool useNPOT, bool isUi) finalSurface = resized; } - Uint32 texId = GL11_UploadTextureData(finalSurface->pixels, finalSurface->w, finalSurface->h, isUi); + Uint32 texId = GL11_UploadTextureData(finalSurface->pixels, finalSurface->w, finalSurface->h, isUI, scaleX, scaleY); if (finalSurface != src) { SDL_DestroySurface(finalSurface); } return texId; } -Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) +Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -183,7 +183,7 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) if (tex.texture == texture) { if (tex.version != texture->m_version) { GL11_DestroyTexture(tex.glTextureId); - tex.glTextureId = UploadTextureData(surface->m_surface, m_useNPOT, isUi); + tex.glTextureId = UploadTextureData(surface->m_surface, m_useNPOT, isUI, scaleX, scaleY); tex.version = texture->m_version; tex.width = surface->m_surface->w; tex.height = surface->m_surface->h; @@ -192,7 +192,7 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) } } - GLuint texId = UploadTextureData(surface->m_surface, m_useNPOT, isUi); + GLuint texId = UploadTextureData(surface->m_surface, m_useNPOT, isUI, scaleX, scaleY); for (Uint32 i = 0; i < m_textures.size(); ++i) { auto& tex = m_textures[i]; diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp index 850e8b6e..ebcb38e6 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp @@ -321,7 +321,7 @@ void OpenGLES2Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* ); } -bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUi) +bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) { SDL_Surface* surf = source; if (source->format != SDL_PIXELFORMAT_RGBA32) { @@ -335,7 +335,7 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUi) glBindTexture(GL_TEXTURE_2D, outTexId); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); - if (isUi) { + if (isUI) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -362,7 +362,7 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUi) return true; } -Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) +Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -372,7 +372,7 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) if (tex.texture == texture) { if (tex.version != texture->m_version) { glDeleteTextures(1, &tex.glTextureId); - if (UploadTexture(surface->m_surface, tex.glTextureId, isUi)) { + if (UploadTexture(surface->m_surface, tex.glTextureId, isUI)) { tex.version = texture->m_version; } } @@ -381,7 +381,7 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) } GLuint texId; - if (!UploadTexture(surface->m_surface, texId, isUi)) { + if (!UploadTexture(surface->m_surface, texId, isUI)) { return NO_TEXTURE_ID; } diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp index c6324f03..0609bbdc 100644 --- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp +++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp @@ -499,7 +499,7 @@ SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* return texptr; } -Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) +Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); diff --git a/miniwin/src/d3drm/backends/software/renderer.cpp b/miniwin/src/d3drm/backends/software/renderer.cpp index 2ae8697e..bd99d2aa 100644 --- a/miniwin/src/d3drm/backends/software/renderer.cpp +++ b/miniwin/src/d3drm/backends/software/renderer.cpp @@ -554,7 +554,7 @@ void Direct3DRMSoftwareRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DR ); } -Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) +Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); diff --git a/miniwin/src/ddraw/framebuffer.cpp b/miniwin/src/ddraw/framebuffer.cpp index 20490b42..843c36ec 100644 --- a/miniwin/src/ddraw/framebuffer.cpp +++ b/miniwin/src/ddraw/framebuffer.cpp @@ -78,11 +78,13 @@ HRESULT FrameBufferImpl::Blt( if (!surface) { return DDERR_GENERIC; } - Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture(), true); SDL_Rect srcRect = lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, surface->m_surface->w, surface->m_surface->h}; SDL_Rect dstRect = lpDestRect ? ConvertRect(lpDestRect) : SDL_Rect{0, 0, (int) m_virtualWidth, (int) m_virtualHeight}; + float scaleX = (float) dstRect.w / (float) srcRect.w; + float scaleY = (float) dstRect.h / (float) srcRect.h; + Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture(), true, scaleX, scaleY); DDRenderer->Draw2DImage(textureId, srcRect, dstRect, {1.0f, 1.0f, 1.0f, 1.0f}); return DD_OK; diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h index d6464eb7..7cfe14b2 100644 --- a/miniwin/src/internal/d3drmrenderer.h +++ b/miniwin/src/internal/d3drmrenderer.h @@ -31,7 +31,7 @@ class Direct3DRMRenderer : public IDirect3DDevice2 { virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0; virtual void SetFrustumPlanes(const Plane* frustumPlanes) = 0; - virtual Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi = false) = 0; + virtual Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUI = false, float scaleX = 0, float scaleY = 0) = 0; virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0; int GetWidth() { return m_width; } int GetHeight() { return m_height; } diff --git a/miniwin/src/internal/d3drmrenderer_citro3d.h b/miniwin/src/internal/d3drmrenderer_citro3d.h index 34863497..2359a88e 100644 --- a/miniwin/src/internal/d3drmrenderer_citro3d.h +++ b/miniwin/src/internal/d3drmrenderer_citro3d.h @@ -32,7 +32,7 @@ class Citro3DRenderer : public Direct3DRMRenderer { void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUI, float scaleX, float scaleY) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; HRESULT BeginFrame() override; void EnableTransparency() override; diff --git a/miniwin/src/internal/d3drmrenderer_directx9.h b/miniwin/src/internal/d3drmrenderer_directx9.h index d1b0a581..5e87aed3 100644 --- a/miniwin/src/internal/d3drmrenderer_directx9.h +++ b/miniwin/src/internal/d3drmrenderer_directx9.h @@ -18,7 +18,7 @@ class DirectX9Renderer : public Direct3DRMRenderer { void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUI, float scaleX, float scaleY) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; HRESULT BeginFrame() override; void EnableTransparency() override; diff --git a/miniwin/src/internal/d3drmrenderer_opengl1.h b/miniwin/src/internal/d3drmrenderer_opengl1.h index bd0fa003..2f1c8173 100644 --- a/miniwin/src/internal/d3drmrenderer_opengl1.h +++ b/miniwin/src/internal/d3drmrenderer_opengl1.h @@ -18,7 +18,7 @@ class OpenGL1Renderer : public Direct3DRMRenderer { void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUI, float scaleX, float scaleY) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; HRESULT BeginFrame() override; void EnableTransparency() override; diff --git a/miniwin/src/internal/d3drmrenderer_opengles2.h b/miniwin/src/internal/d3drmrenderer_opengles2.h index 7dbb1f4b..0472ff80 100644 --- a/miniwin/src/internal/d3drmrenderer_opengles2.h +++ b/miniwin/src/internal/d3drmrenderer_opengles2.h @@ -39,7 +39,7 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUI, float scaleX, float scaleY) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; HRESULT BeginFrame() override; void EnableTransparency() override; diff --git a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h index b3afd674..7f948a37 100644 --- a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h +++ b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h @@ -47,7 +47,7 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer { static Direct3DRMRenderer* Create(DWORD width, DWORD height); ~Direct3DRMSDL3GPURenderer() override; void PushLights(const SceneLight* vertices, size_t count) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUI, float scaleX, float scaleY) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; diff --git a/miniwin/src/internal/d3drmrenderer_software.h b/miniwin/src/internal/d3drmrenderer_software.h index 8b8c0dde..0c422597 100644 --- a/miniwin/src/internal/d3drmrenderer_software.h +++ b/miniwin/src/internal/d3drmrenderer_software.h @@ -29,7 +29,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { Direct3DRMSoftwareRenderer(DWORD width, DWORD height); ~Direct3DRMSoftwareRenderer() override; void PushLights(const SceneLight* vertices, size_t count) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUI, float scaleX, float scaleY) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; From b2156c94bf6170cacd22f167199912720777d470 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Sat, 5 Jul 2025 05:21:32 +0200 Subject: [PATCH 07/11] Fix uninitialized presenter (#525) --- LEGO1/lego/legoomni/src/worlds/registrationbook.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index adaf45d4..709b338d 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -671,14 +671,14 @@ MxLong RegistrationBook::HandlePathStruct(LegoPathStructNotificationParam& p_par MxBool RegistrationBook::CreateSurface() { MxCompositePresenterList* presenters = m_checkmark[0]->GetList(); - MxStillPresenter *presenter, *uninitialized; + MxStillPresenter* presenter; if (presenters) { if (presenters->begin() != presenters->end()) { presenter = (MxStillPresenter*) presenters->front(); } else { - presenter = uninitialized; // intentionally uninitialized variable + presenter = NULL; } if (presenter) { From 761dc31ac04433a4019c57908c32aa50e7fa5f1e Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Sat, 5 Jul 2025 07:39:51 +0200 Subject: [PATCH 08/11] Render buttons as sprites (#488) --- LEGO1/omni/src/video/mxdisplaysurface.cpp | 49 +++++++++++++++++------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index 5d08a64b..612caba4 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -409,9 +409,16 @@ void MxDisplaySurface::VTable0x28( return; } - DDCOLORKEY colorKey; - colorKey.dwColorSpaceLowValue = colorKey.dwColorSpaceHighValue = RGB555_CREATE(0x1f, 0, 0x1f); - tempSurface->SetColorKey(DDCKEY_SRCBLT, &colorKey); + if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount != 32) { + DDCOLORKEY colorKey; + if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount == 8) { + colorKey.dwColorSpaceLowValue = colorKey.dwColorSpaceHighValue = 0x10; + } + else { + colorKey.dwColorSpaceLowValue = colorKey.dwColorSpaceHighValue = RGB555_CREATE(0x1f, 0, 0x1f); + } + tempSurface->SetColorKey(DDCKEY_SRCBLT, &colorKey); + } DDSURFACEDESC tempDesc; memset(&tempDesc, 0, sizeof(tempDesc)); @@ -503,29 +510,43 @@ void MxDisplaySurface::VTable0x30( 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); - if (hr == DDERR_SURFACELOST) { - m_ddSurface2->Restore(); - hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL); + LPDIRECTDRAW draw = MVideoManager()->GetDirectDraw(); + LPDIRECTDRAWSURFACE tempSurface = nullptr; + if (draw->CreateSurface(&ddsd, &tempSurface, nullptr) != DD_OK || !tempSurface) { + return; } - if (hr != DD_OK) { + DDCOLORKEY colorKey; + colorKey.dwColorSpaceLowValue = colorKey.dwColorSpaceHighValue = 0; + tempSurface->SetColorKey(DDCKEY_SRCBLT, &colorKey); + + DDSURFACEDESC tempDesc; + memset(&tempDesc, 0, sizeof(tempDesc)); + tempDesc.dwSize = sizeof(tempDesc); + + if (tempSurface->Lock(NULL, &tempDesc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) != DD_OK) { + tempSurface->Release(); return; } MxU8* data = p_bitmap->GetStart(p_left, p_top); MxS32 bytesPerPixel = m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount / 8; - MxU8* surface = (MxU8*) ddsd.lpSurface + (bytesPerPixel * p_right) + (p_bottom * ddsd.lPitch); + MxU8* surface = (MxU8*) tempDesc.lpSurface; if (p_RLE) { MxS32 size = p_bitmap->GetBmiHeader()->biSizeImage; - DrawTransparentRLE(data, surface, size, p_width, p_height, ddsd.lPitch, bytesPerPixel * 8); + DrawTransparentRLE(data, surface, size, p_width, p_height, tempDesc.lPitch, bytesPerPixel * 8); } else { MxLong stride = -p_width + GetAdjustedStride(p_bitmap); - MxLong length = -bytesPerPixel * p_width + ddsd.lPitch; + MxLong length = -bytesPerPixel * p_width + tempDesc.lPitch; for (MxS32 i = 0; i < p_height; i++) { for (MxS32 j = 0; j < p_width; j++) { @@ -550,7 +571,11 @@ void MxDisplaySurface::VTable0x30( } } - m_ddSurface2->Unlock(ddsd.lpSurface); + tempSurface->Unlock(NULL); + + m_ddSurface2->BltFast(p_right, p_bottom, tempSurface, NULL, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY); + + tempSurface->Release(); } // FUNCTION: LEGO1 0x100bb500 From 80514e2af7bec24da2c607de0a25d016f5e12bd5 Mon Sep 17 00:00:00 2001 From: Helloyunho Date: Sun, 6 Jul 2025 04:27:24 +0900 Subject: [PATCH 09/11] Support gamepad (#527) --- ISLE/isleapp.cpp | 94 ++++++++++++++++++- ISLE/isleapp.h | 3 + .../lego/legoomni/include/legoinputmanager.h | 2 +- .../legoomni/src/input/legoinputmanager.cpp | 60 ++++-------- 4 files changed, 115 insertions(+), 44 deletions(-) diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 6cb0375c..cd0a6849 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -90,6 +90,11 @@ MxS32 g_targetDepth = 16; // GLOBAL: ISLE 0x410064 MxS32 g_reqEnableRMDevice = FALSE; +MxFloat g_lastJoystickMouseX = 0; +MxFloat g_lastJoystickMouseY = 0; +MxFloat g_lastMouseX = 0; +MxFloat g_lastMouseY = 0; + // STRING: ISLE 0x4101dc #define WINDOW_TITLE "LEGO®" @@ -149,6 +154,7 @@ IsleApp::IsleApp() m_maxLod = RealtimeView::GetUserMaxLOD(); m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20; m_transitionType = MxTransitionManager::e_mosaic; + m_cursorSensitivity = 4; } // FUNCTION: ISLE 0x4011a0 @@ -270,7 +276,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK)) { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) { char buffer[256]; SDL_snprintf( buffer, @@ -379,6 +385,8 @@ SDL_AppResult SDL_AppIterate(void* appstate) if (g_mousemoved) { g_mousemoved = FALSE; } + + g_isle->MoveVirtualMouseViaJoystick(); } return SDL_APP_CONTINUE; @@ -457,6 +465,63 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) } break; } + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: { + { + if (event->gbutton.button == SDL_GAMEPAD_BUTTON_SOUTH) { + if (InputManager()) { + InputManager()->QueueEvent(c_notificationKeyPress, SDLK_SPACE, 0, 0, SDLK_SPACE); + } + } + if (event->gbutton.button == SDL_GAMEPAD_BUTTON_START) { + if (InputManager()) { + InputManager()->QueueEvent(c_notificationKeyPress, SDLK_ESCAPE, 0, 0, SDLK_ESCAPE); + } + } + } + break; + } + case SDL_EVENT_GAMEPAD_AXIS_MOTION: { + MxS16 axisValue = 0; + if (event->gaxis.value < -8000 || event->gaxis.value > 8000) { + // Ignore small axis values + axisValue = event->gaxis.value; + } + if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTX) { + g_lastJoystickMouseX = ((MxFloat) axisValue) / SDL_JOYSTICK_AXIS_MAX * g_isle->GetCursorSensitivity(); + } + else if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTY) { + g_lastJoystickMouseY = ((MxFloat) axisValue) / SDL_JOYSTICK_AXIS_MAX * g_isle->GetCursorSensitivity(); + } + else if (event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) { + if (axisValue != 0) { + g_mousedown = TRUE; + + if (InputManager()) { + InputManager()->QueueEvent( + c_notificationButtonDown, + LegoEventNotificationParam::c_lButtonState, + g_lastMouseX, + g_lastMouseY, + 0 + ); + } + } + else { + g_mousedown = FALSE; + + if (InputManager()) { + InputManager()->QueueEvent( + c_notificationButtonUp, + LegoEventNotificationParam::c_lButtonState, + g_lastMouseX, + g_lastMouseY, + 0 + ); + } + } + } + break; + } case SDL_EVENT_MOUSE_MOTION: #ifdef __EMSCRIPTEN__ if (detectedTouchEvents) { @@ -842,6 +907,8 @@ bool IsleApp::LoadConfig() iniparser_set(dict, "isle:UseJoystick", m_useJoystick ? "true" : "false"); iniparser_set(dict, "isle:JoystickIndex", SDL_itoa(m_joystickIndex, buf, 10)); iniparser_set(dict, "isle:Draw Cursor", m_drawCursor ? "true" : "false"); + SDL_snprintf(buf, sizeof(buf), "%f", m_cursorSensitivity); + iniparser_set(dict, "isle:Cursor Sensitivity", buf); iniparser_set(dict, "isle:Back Buffers in Video RAM", "-1"); @@ -896,6 +963,7 @@ bool IsleApp::LoadConfig() m_useJoystick = iniparser_getboolean(dict, "isle:UseJoystick", m_useJoystick); m_joystickIndex = iniparser_getint(dict, "isle:JoystickIndex", m_joystickIndex); m_drawCursor = iniparser_getboolean(dict, "isle:Draw Cursor", m_drawCursor); + m_cursorSensitivity = iniparser_getdouble(dict, "isle:Cursor Sensitivity", m_cursorSensitivity); MxS32 backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1); if (backBuffersInVRAM != -1) { @@ -1207,3 +1275,27 @@ IDirect3DRMMiniwinDevice* GetD3DRMMiniwinDevice() } return d3drmMiniwinDev; } + +void IsleApp::MoveVirtualMouseViaJoystick() +{ + if (g_lastJoystickMouseX != 0 || g_lastJoystickMouseY != 0) { + g_mousemoved = TRUE; + + g_lastMouseX = SDL_clamp(g_lastMouseX + g_lastJoystickMouseX, 0, 640); + g_lastMouseY = SDL_clamp(g_lastMouseY + g_lastJoystickMouseY, 0, 480); + + if (InputManager()) { + InputManager()->QueueEvent( + c_notificationMouseMove, + g_mousedown ? LegoEventNotificationParam::c_lButtonState : 0, + g_lastMouseX, + g_lastMouseY, + 0 + ); + } + + if (g_isle->GetDrawCursor()) { + VideoManager()->MoveCursor(Min((MxS32) g_lastMouseX, 639), Min((MxS32) g_lastMouseY, 479)); + } + } +} diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 4064dc25..70445d05 100644 --- a/ISLE/isleapp.h +++ b/ISLE/isleapp.h @@ -52,6 +52,7 @@ class IsleApp { SDL_Cursor* GetCursorNo() { return m_cursorNo; } MxS32 GetDrawCursor() { return m_drawCursor; } MxS32 GetGameStarted() { return m_gameStarted; } + MxFloat GetCursorSensitivity() { return m_cursorSensitivity; } void SetWindowActive(MxS32 p_windowActive) { m_windowActive = p_windowActive; } void SetGameStarted(MxS32 p_gameStarted) { m_gameStarted = p_gameStarted; } @@ -59,6 +60,7 @@ class IsleApp { MxResult ParseArguments(int argc, char** argv); MxResult VerifyFilesystem(); void DetectGameVersion(); + void MoveVirtualMouseViaJoystick(); private: char* m_hdPath; // 0x00 @@ -93,6 +95,7 @@ class IsleApp { const CursorBitmap* m_cursorNoBitmap; const CursorBitmap* m_cursorCurrentBitmap; char* m_mediaPath; + MxFloat m_cursorSensitivity; char* m_iniPath; MxFloat m_maxLod; diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 7ccad404..ece1cbd1 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -166,7 +166,7 @@ class LegoInputManager : public MxPresenter { const bool* m_keyboardState; MxBool m_unk0x195; // 0x195 SDL_JoystickID* m_joyids; - SDL_Joystick* m_joystick; + SDL_Gamepad* m_joystick; MxS32 m_joystickIndex; // 0x19c MxBool m_useJoystick; // 0x334 MxBool m_unk0x335; // 0x335 diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index 3e9622c2..eca8078b 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -148,26 +148,28 @@ MxResult LegoInputManager::GetNavigationKeyStates(MxU32& p_keyFlags) // FUNCTION: LEGO1 0x1005c240 MxResult LegoInputManager::GetJoystick() { - if (m_joystick != NULL && SDL_JoystickConnected(m_joystick) == TRUE) { + if (m_joystick != NULL && SDL_GamepadConnected(m_joystick) == TRUE) { return SUCCESS; } MxS32 numJoysticks = 0; - if (m_joyids == NULL) { - m_joyids = SDL_GetJoysticks(&numJoysticks); + if (m_joyids != NULL) { + SDL_free(m_joyids); + m_joyids = NULL; } + m_joyids = SDL_GetGamepads(&numJoysticks); if (m_useJoystick != FALSE && numJoysticks != 0) { MxS32 joyid = m_joystickIndex; if (joyid >= 0) { - m_joystick = SDL_OpenJoystick(m_joyids[joyid]); + m_joystick = SDL_OpenGamepad(m_joyids[joyid]); if (m_joystick != NULL) { return SUCCESS; } } for (joyid = 0; joyid < numJoysticks; joyid++) { - m_joystick = SDL_OpenJoystick(m_joyids[joyid]); + m_joystick = SDL_OpenGamepad(m_joyids[joyid]); if (m_joystick != NULL) { return SUCCESS; } @@ -184,54 +186,28 @@ MxResult LegoInputManager::GetJoystickState(MxU32* p_joystickX, MxU32* p_joystic if (GetJoystick() == -1) { if (m_joystick != NULL) { // GetJoystick() failed but handle to joystick is still open, close it - SDL_CloseJoystick(m_joystick); + SDL_CloseGamepad(m_joystick); m_joystick = NULL; } return FAILURE; } - MxS16 xPos = SDL_GetJoystickAxis(m_joystick, 0); - MxS16 yPos = SDL_GetJoystickAxis(m_joystick, 1); - MxU8 hatPos = SDL_GetJoystickHat(m_joystick, 0); + MxS16 xPos = SDL_GetGamepadAxis(m_joystick, SDL_GAMEPAD_AXIS_LEFTX); + MxS16 yPos = SDL_GetGamepadAxis(m_joystick, SDL_GAMEPAD_AXIS_LEFTY); + if (xPos > -8000 && xPos < 8000) { + // Ignore small axis values + xPos = 0; + } + if (yPos > -8000 && yPos < 8000) { + // Ignore small axis values + yPos = 0; + } // normalize values acquired from joystick axes *p_joystickX = ((xPos + 32768) * 100) / 65535; *p_joystickY = ((yPos + 32768) * 100) / 65535; - switch (hatPos) { - case SDL_HAT_CENTERED: - *p_povPosition = (MxU32) -1; - break; - case SDL_HAT_UP: - *p_povPosition = (MxU32) 0; - break; - case SDL_HAT_RIGHT: - *p_povPosition = (MxU32) 9000 / 100; - break; - case SDL_HAT_DOWN: - *p_povPosition = (MxU32) 18000 / 100; - break; - case SDL_HAT_LEFT: - *p_povPosition = (MxU32) 27000 / 100; - break; - case SDL_HAT_RIGHTUP: - *p_povPosition = (MxU32) 4500 / 100; - break; - case SDL_HAT_RIGHTDOWN: - *p_povPosition = (MxU32) 13500 / 100; - break; - case SDL_HAT_LEFTUP: - *p_povPosition = (MxU32) 31500 / 100; - break; - case SDL_HAT_LEFTDOWN: - *p_povPosition = (MxU32) 22500 / 100; - break; - default: - *p_povPosition = (MxU32) -1; - break; - } - return SUCCESS; } From 9862705232ee85a11365bd7ed8e8ad04dd9a396a Mon Sep 17 00:00:00 2001 From: BagelSketches <112355083+BagelSketches@users.noreply.github.com> Date: Sun, 6 Jul 2025 05:33:19 +1000 Subject: [PATCH 10/11] Added building config.exe with qt dlls on msvc 64-bit builds (#520) --- .github/workflows/ci.yml | 7 ++++++- CMakeLists.txt | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57d6e539..97b338c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: include: - { name: 'Linux', os: 'ubuntu-latest', dx5: false, config: true, linux: true, werror: true, clang-tidy: true } - { name: 'MSVC (x86)', os: 'windows-latest', dx5: true, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_x86' } - - { name: 'MSVC (x64)', os: 'windows-latest', dx5: false, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64' } + - { name: 'MSVC (x64)', os: 'windows-latest', dx5: false, config: true, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64' } - { name: 'MSVC (arm64)', os: 'windows-latest', dx5: false, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_arm64' } - { name: 'msys2 mingw32', os: 'windows-latest', dx5: false, config: false, mingw: true, werror: true, clang-tidy: true, msystem: 'mingw32', msys-env: 'mingw-w64-i686', shell: 'msys2 {0}' } - { name: 'msys2 mingw64', os: 'windows-latest', dx5: false, config: true, mingw: true, werror: true, clang-tidy: true, msystem: 'mingw64', msys-env: 'mingw-w64-x86_64', shell: 'msys2 {0}' } @@ -61,6 +61,11 @@ jobs: ${{ matrix.msys-env }}-ninja ${{ matrix.msys-env }}-clang-tools-extra ${{ (matrix.config && format('{0}-qt6-base', matrix.msys-env)) || '' }} + - name: Install Qt + if: ${{ !!matrix.msvc && matrix.config }} + uses: jurplel/install-qt-action@v4 + with: + cache: 'true' - name: Install Linux dependencies (apt-get) if: ${{ matrix.linux }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 00ba25ea..00d087df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -680,6 +680,25 @@ install(TARGETS isle ${install_extra_targets} LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) if (ISLE_BUILD_CONFIG) + if(WIN32) + find_program(WINDEPLOYQT_EXECUTABLE windeployqt) + if(WINDEPLOYQT_EXECUTABLE) + install(CODE "message(STATUS \"Running windeployqt with minimal dependencies\") + execute_process(COMMAND \"${WINDEPLOYQT_EXECUTABLE}\" + \"$\" + --dir QTLibs + --no-compiler-runtime + --no-opengl-sw + --no-system-d3d-compiler + --no-translations + --no-quick-import + )" + ) + install(DIRECTORY "Build/QTLibs/" DESTINATION "${CMAKE_INSTALL_BINDIR}") + else() + message(STATUS "windeployqt not found: Qt binaries will not be installed") + endif() + endif() install(TARGETS isle-config RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) From 6b446d242f6dddc7f4b8f6d6d04c978a8f9670f1 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Sun, 6 Jul 2025 00:01:21 +0200 Subject: [PATCH 11/11] SDL_GPU: Fix transitions on scenes with 2D overlay (#529) --- miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp | 2 +- miniwin/src/d3drm/backends/software/renderer.cpp | 3 +-- miniwin/src/ddraw/framebuffer.cpp | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp index 0609bbdc..7a6589f0 100644 --- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp +++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp @@ -1009,7 +1009,7 @@ void Direct3DRMSDL3GPURenderer::Download(SDL_Surface* target) } SDL_Surface* renderedImage = - SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_ARGB8888, downloadedData, width * 4); + SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_XRGB8888, downloadedData, width * 4); SDL_BlitSurfaceScaled(renderedImage, nullptr, target, nullptr, SDL_SCALEMODE_NEAREST); SDL_DestroySurface(renderedImage); diff --git a/miniwin/src/d3drm/backends/software/renderer.cpp b/miniwin/src/d3drm/backends/software/renderer.cpp index bd99d2aa..48c9c3ef 100644 --- a/miniwin/src/d3drm/backends/software/renderer.cpp +++ b/miniwin/src/d3drm/backends/software/renderer.cpp @@ -761,10 +761,9 @@ void Direct3DRMSoftwareRenderer::Resize(int width, int height, const ViewportTra void Direct3DRMSoftwareRenderer::Clear(float r, float g, float b) { - SDL_Rect rect = {0, 0, m_renderedImage->w, m_renderedImage->h}; const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_renderedImage->format); Uint32 color = SDL_MapRGB(details, m_palette, r * 255, g * 255, b * 255); - SDL_FillSurfaceRect(m_renderedImage, &rect, color); + SDL_FillSurfaceRect(m_renderedImage, nullptr, color); } void Direct3DRMSoftwareRenderer::Flip() diff --git a/miniwin/src/ddraw/framebuffer.cpp b/miniwin/src/ddraw/framebuffer.cpp index 843c36ec..ea66e96b 100644 --- a/miniwin/src/ddraw/framebuffer.cpp +++ b/miniwin/src/ddraw/framebuffer.cpp @@ -172,11 +172,10 @@ HRESULT FrameBufferImpl::Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, return DDERR_GENERIC; } if ((dwFlags & DDLOCK_WRITEONLY) == DDLOCK_WRITEONLY) { - SDL_Rect rect = {0, 0, m_transferBuffer->m_surface->w, m_transferBuffer->m_surface->h}; const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_transferBuffer->m_surface->format); SDL_Palette* palette = m_palette ? static_cast(m_palette)->m_palette : nullptr; Uint32 color = SDL_MapRGBA(details, palette, 0, 0, 0, 0); - SDL_FillSurfaceRect(m_transferBuffer->m_surface, &rect, color); + SDL_FillSurfaceRect(m_transferBuffer->m_surface, nullptr, color); } else { DDRenderer->Download(m_transferBuffer->m_surface);