From 89539a64f17cbd0c21c65aa66cf7af63ffaed924 Mon Sep 17 00:00:00 2001 From: Fabian Neundorf Date: Sat, 28 Jun 2025 16:28:13 +0200 Subject: [PATCH 01/13] Clear unknown 0x10 in `LegoEntity` (#1593) The naming is a bit weird, as only one bit is used so there are no other usages of this value. --- LEGO1/lego/legoomni/include/legoanimpresenter.h | 2 +- LEGO1/lego/legoomni/include/legoentity.h | 10 +++++----- LEGO1/lego/legoomni/src/entity/legoactor.cpp | 2 +- LEGO1/lego/legoomni/src/entity/legoentity.cpp | 8 ++++---- LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp | 2 +- LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp | 12 ++++++------ 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 85917cbc..a3d6cd60 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -121,7 +121,7 @@ class LegoAnimPresenter : public MxVideoPresenter { void SubstituteVariables(); void FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); void FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); - void FUN_1006c8a0(MxBool p_bool); + void SetDisabled(MxBool p_disabled); LegoAnim* m_anim; // 0x64 LegoROI** m_roiMap; // 0x68 diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index eecf6867..2859b6ac 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -28,7 +28,7 @@ class LegoEntity : public MxEntity { }; enum { - c_altBit1 = 0x01 + c_disabled = 0x01 }; LegoEntity() { Init(); } @@ -83,7 +83,7 @@ class LegoEntity : public MxEntity { Mx3DPointFloat GetWorldUp(); Mx3DPointFloat GetWorldPosition(); - MxBool GetUnknown0x10IsSet(MxU8 p_flag) { return m_unk0x10 & p_flag; } + MxBool IsInteraction(MxU8 p_flag) { return m_interaction & p_flag; } MxBool GetFlagsIsSet(MxU8 p_flag) { return m_flags & p_flag; } MxU8 GetFlags() { return m_flags; } @@ -101,14 +101,14 @@ class LegoEntity : public MxEntity { void SetFlags(MxU8 p_flags) { m_flags = p_flags; } void SetFlag(MxU8 p_flag) { m_flags |= p_flag; } void ClearFlag(MxU8 p_flag) { m_flags &= ~p_flag; } - void SetUnknown0x10Flag(MxU8 p_flag) { m_unk0x10 |= p_flag; } - void ClearUnknown0x10Flag(MxU8 p_flag) { m_unk0x10 &= ~p_flag; } + void SetInteractionFlag(MxU8 p_flag) { m_interaction |= p_flag; } + void ClearInteractionFlag(MxU8 p_flag) { m_interaction &= ~p_flag; } protected: void Init(); void SetWorld(); - MxU8 m_unk0x10; // 0x10 + MxU8 m_interaction; // 0x10 MxU8 m_flags; // 0x11 Mx3DPointFloat m_worldLocation; // 0x14 Mx3DPointFloat m_worldDirection; // 0x28 diff --git a/LEGO1/lego/legoomni/src/entity/legoactor.cpp b/LEGO1/lego/legoomni/src/entity/legoactor.cpp index c1ce3f74..4b0428b8 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -18,7 +18,7 @@ LegoActor::LegoActor() m_frequencyFactor = 0.0f; m_sound = NULL; m_unk0x70 = 0.0f; - m_unk0x10 = 0; + m_interaction = 0; m_actorId = 0; } diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index 467d65d8..b76da503 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -29,7 +29,7 @@ void LegoEntity::Init() m_roi = NULL; m_cameraFlag = FALSE; m_siFile = NULL; - m_unk0x10 = 0; + m_interaction = 0; m_flags = 0; m_actionType = Extra::ActionType::e_unknown; m_targetEntityId = -1; @@ -265,7 +265,7 @@ void LegoEntity::ParseAction(char* p_extra) // FUNCTION: BETA10 0x1007ee87 void LegoEntity::ClickSound(MxBool p_und) { - if (!GetUnknown0x10IsSet(c_altBit1)) { + if (!IsInteraction(c_disabled)) { MxU32 objectId = 0; const char* name = m_roi->GetName(); @@ -297,7 +297,7 @@ void LegoEntity::ClickSound(MxBool p_und) // FUNCTION: BETA10 0x1007f062 void LegoEntity::ClickAnimation() { - if (!GetUnknown0x10IsSet(c_altBit1)) { + if (!IsInteraction(c_disabled)) { MxU32 objectId = 0; MxDSAction action; const char* name = m_roi->GetName(); @@ -329,7 +329,7 @@ void LegoEntity::ClickAnimation() action.SetObjectId(objectId); action.AppendExtra(strlen(extra) + 1, extra); LegoOmni::GetInstance()->GetAnimationManager()->StartEntityAction(action, this); - m_unk0x10 |= c_altBit1; + m_interaction |= c_disabled; } } } diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 1c306c1b..fa8158da 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -691,7 +691,7 @@ MxLong LegoNavController::Notify(MxParam& p_param) for (MxS32 i = 0; i < numPlants; i++) { LegoEntity* entity = plantMgr->CreatePlant(i, NULL, LegoOmni::e_act1); - if (entity != NULL && !entity->GetUnknown0x10IsSet(LegoEntity::c_altBit1)) { + if (entity != NULL && !entity->IsInteraction(LegoEntity::c_disabled)) { LegoROI* roi = entity->GetROI(); if (roi != NULL && roi->GetVisibility()) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 852263fc..73918606 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -790,7 +790,7 @@ void LegoAnimPresenter::StartingTickle() } FUN_10069b10(); - FUN_1006c8a0(TRUE); + SetDisabled(TRUE); if (m_unk0x78 == NULL) { if (fabs(m_action->GetDirection()[0]) >= 0.00000047683716F || @@ -1090,7 +1090,7 @@ void LegoAnimPresenter::EndAction() } } - FUN_1006c8a0(FALSE); + SetDisabled(FALSE); FUN_1006ab70(); VTable0x90(); @@ -1151,18 +1151,18 @@ void LegoAnimPresenter::VTable0x90() } // FUNCTION: LEGO1 0x1006c8a0 -void LegoAnimPresenter::FUN_1006c8a0(MxBool p_bool) +void LegoAnimPresenter::SetDisabled(MxBool p_disabled) { if (m_roiMapSize != 0 && m_roiMap != NULL) { for (MxU32 i = 1; i <= m_roiMapSize; i++) { LegoEntity* entity = m_roiMap[i]->GetEntity(); if (entity != NULL) { - if (p_bool) { - entity->SetUnknown0x10Flag(LegoEntity::c_altBit1); + if (p_disabled) { + entity->SetInteractionFlag(LegoEntity::c_disabled); } else { - entity->ClearUnknown0x10Flag(LegoEntity::c_altBit1); + entity->ClearInteractionFlag(LegoEntity::c_disabled); } } } From 9dcc701fcb18eb84e7d57ae3454a9391decdba6d Mon Sep 17 00:00:00 2001 From: Fabian Neundorf Date: Sat, 28 Jun 2025 20:32:09 +0200 Subject: [PATCH 02/13] Clear unknowns in GetSoundId (#1594) --- LEGO1/lego/legoomni/include/legobuildingmanager.h | 2 +- LEGO1/lego/legoomni/include/legocharactermanager.h | 2 +- LEGO1/lego/legoomni/include/legoentity.h | 14 +++++++------- LEGO1/lego/legoomni/include/legoplantmanager.h | 2 +- .../legoomni/src/common/legobuildingmanager.cpp | 12 ++++++------ .../legoomni/src/common/legocharactermanager.cpp | 12 ++++++------ .../lego/legoomni/src/common/legoplantmanager.cpp | 12 ++++++------ LEGO1/lego/legoomni/src/entity/legoentity.cpp | 8 ++++---- 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 3d251c98..c5a69309 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -78,7 +78,7 @@ class LegoBuildingManager : public MxCore { MxBool SwitchMove(LegoEntity* p_entity); MxBool SwitchMood(LegoEntity* p_entity); MxU32 GetAnimationId(LegoEntity* p_entity); - MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state); + MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood); MxBool DecrementCounter(LegoEntity* p_entity); MxBool DecrementCounter(MxS32 p_index); MxBool DecrementCounter(LegoBuildingInfo* p_data); diff --git a/LEGO1/lego/legoomni/include/legocharactermanager.h b/LEGO1/lego/legoomni/include/legocharactermanager.h index 174db01e..c5a0c242 100644 --- a/LEGO1/lego/legoomni/include/legocharactermanager.h +++ b/LEGO1/lego/legoomni/include/legocharactermanager.h @@ -86,7 +86,7 @@ class LegoCharacterManager { MxBool SwitchMove(LegoROI* p_roi); MxBool SwitchMood(LegoROI* p_roi); MxU32 GetAnimationId(LegoROI* p_roi); - MxU32 GetSoundId(LegoROI* p_roi, MxBool p_und); + MxU32 GetSoundId(LegoROI* p_roi, MxBool p_basedOnMood); MxU8 GetMood(LegoROI* p_roi); LegoROI* CreateAutoROI(const char* p_name, const char* p_lodName, MxBool p_createEntity); MxResult UpdateBoundingSphereAndBox(LegoROI* p_roi); diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index 2859b6ac..a6d9d9ee 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -68,13 +68,13 @@ class LegoEntity : public MxEntity { // FUNCTION: BETA10 0x10013260 virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 - virtual void ClickSound(MxBool p_und); // vtable+0x34 - virtual void ClickAnimation(); // vtable+0x38 - virtual void SwitchVariant(); // vtable+0x3c - virtual void SwitchSound(); // vtable+0x40 - virtual void SwitchMove(); // vtable+0x44 - virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48 - virtual void SwitchMood(); // vtable+0x4c + virtual void ClickSound(MxBool p_basedOnMood); // vtable+0x34 + virtual void ClickAnimation(); // vtable+0x38 + virtual void SwitchVariant(); // vtable+0x3c + virtual void SwitchSound(); // vtable+0x40 + virtual void SwitchMove(); // vtable+0x44 + virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48 + virtual void SwitchMood(); // vtable+0x4c void FUN_10010c30(); void SetType(MxU8 p_type); diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index 91fe49c8..c3b2c4e1 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -49,7 +49,7 @@ class LegoPlantManager : public MxCore { MxBool SwitchMove(LegoEntity* p_entity); MxBool SwitchMood(LegoEntity* p_entity); MxU32 GetAnimationId(LegoEntity* p_entity); - MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state); + MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood); LegoPlantInfo* GetInfoArray(MxS32& p_length); LegoEntity* CreatePlant(MxS32 p_index, LegoWorld* p_world, LegoOmni::World p_worldId); MxBool DecrementCounter(LegoEntity* p_entity); diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index d46b8a49..1e4a8b82 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -199,10 +199,10 @@ LegoBuildingInfo g_buildingInfoInit[16] = { MxU32 LegoBuildingManager::g_maxSound = 6; // GLOBAL: LEGO1 0x100f373c -MxU32 g_unk0x100f373c = 0x3c; +MxU32 g_buildingSoundIdOffset = 0x3c; // GLOBAL: LEGO1 0x100f3740 -MxU32 g_unk0x100f3740 = 0x42; +MxU32 g_buildingSoundIdMoodOffset = 0x42; // clang-format off // GLOBAL: LEGO1 0x100f3788 @@ -548,7 +548,7 @@ MxU32 LegoBuildingManager::GetAnimationId(LegoEntity* p_entity) // FUNCTION: LEGO1 0x1002ff40 // FUNCTION: BETA10 0x10064398 -MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_state) +MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood) { LegoBuildingInfo* info = GetInfo(p_entity); @@ -556,12 +556,12 @@ MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_state) return 0; } - if (p_state) { - return info->m_mood + g_unk0x100f3740; + if (p_basedOnMood) { + return info->m_mood + g_buildingSoundIdMoodOffset; } if (info != NULL) { - return info->m_sound + g_unk0x100f373c; + return info->m_sound + g_buildingSoundIdOffset; } return 0; diff --git a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp index 80b69efc..ff7cf23b 100644 --- a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp @@ -37,10 +37,10 @@ MxU32 g_characterAnimationId = 10; char* LegoCharacterManager::g_customizeAnimFile = NULL; // GLOBAL: LEGO1 0x100fc4d8 -MxU32 g_soundIdOffset = 50; +MxU32 g_characterSoundIdOffset = 50; // GLOBAL: LEGO1 0x100fc4dc -MxU32 g_soundIdMoodOffset = 66; +MxU32 g_characterSoundIdMoodOffset = 66; // GLOBAL: LEGO1 0x100fc4e8 MxU32 g_headTextureCounter = 0; @@ -931,16 +931,16 @@ MxU32 LegoCharacterManager::GetAnimationId(LegoROI* p_roi) // FUNCTION: LEGO1 0x10085140 // FUNCTION: BETA10 0x10076855 -MxU32 LegoCharacterManager::GetSoundId(LegoROI* p_roi, MxBool p_und) +MxU32 LegoCharacterManager::GetSoundId(LegoROI* p_roi, MxBool p_basedOnMood) { LegoActorInfo* info = GetActorInfo(p_roi); - if (p_und) { - return info->m_mood + g_soundIdMoodOffset; + if (p_basedOnMood) { + return info->m_mood + g_characterSoundIdMoodOffset; } if (info != NULL) { - return info->m_sound + g_soundIdOffset; + return info->m_sound + g_characterSoundIdOffset; } else { return 0; diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 766edf79..4e8e2626 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -40,10 +40,10 @@ MxU8 g_counters[] = {1, 2, 2, 3}; MxU32 LegoPlantManager::g_maxSound = 8; // GLOBAL: LEGO1 0x100f3160 -MxU32 g_unk0x100f3160 = 56; +MxU32 g_plantSoundIdOffset = 56; // GLOBAL: LEGO1 0x100f3164 -MxU32 g_unk0x100f3164 = 66; +MxU32 g_plantSoundIdMoodOffset = 66; // GLOBAL: LEGO1 0x100f3168 MxS32 LegoPlantManager::g_maxMove[4] = {3, 3, 3, 3}; @@ -513,16 +513,16 @@ MxU32 LegoPlantManager::GetAnimationId(LegoEntity* p_entity) // FUNCTION: LEGO1 0x10026ba0 // FUNCTION: BETA10 0x100c61ba -MxU32 LegoPlantManager::GetSoundId(LegoEntity* p_entity, MxBool p_state) +MxU32 LegoPlantManager::GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood) { LegoPlantInfo* info = GetInfo(p_entity); - if (p_state) { - return (info->m_mood & 1) + g_unk0x100f3164; + if (p_basedOnMood) { + return (info->m_mood & 1) + g_plantSoundIdMoodOffset; } if (info != NULL) { - return info->m_sound + g_unk0x100f3160; + return info->m_sound + g_plantSoundIdOffset; } return 0; diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index b76da503..9ac9aad6 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -263,7 +263,7 @@ void LegoEntity::ParseAction(char* p_extra) // FUNCTION: LEGO1 0x10010f10 // FUNCTION: BETA10 0x1007ee87 -void LegoEntity::ClickSound(MxBool p_und) +void LegoEntity::ClickSound(MxBool p_basedOnMood) { if (!IsInteraction(c_disabled)) { MxU32 objectId = 0; @@ -271,15 +271,15 @@ void LegoEntity::ClickSound(MxBool p_und) switch (m_type) { case e_actor: - objectId = CharacterManager()->GetSoundId(m_roi, p_und); + objectId = CharacterManager()->GetSoundId(m_roi, p_basedOnMood); break; case e_unk1: break; case e_plant: - objectId = PlantManager()->GetSoundId(this, p_und); + objectId = PlantManager()->GetSoundId(this, p_basedOnMood); break; case e_building: - objectId = BuildingManager()->GetSoundId(this, p_und); + objectId = BuildingManager()->GetSoundId(this, p_basedOnMood); break; } From 0982038453babc6233710fea5318b1437516a188 Mon Sep 17 00:00:00 2001 From: Fabian Neundorf Date: Sun, 29 Jun 2025 00:38:48 +0200 Subject: [PATCH 03/13] Clear unknown in `Hospital` (#1595) --- LEGO1/lego/legoomni/include/hospital.h | 2 +- LEGO1/lego/legoomni/src/worlds/hospital.cpp | 22 ++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/LEGO1/lego/legoomni/include/hospital.h b/LEGO1/lego/legoomni/include/hospital.h index 4a136568..2a90764b 100644 --- a/LEGO1/lego/legoomni/include/hospital.h +++ b/LEGO1/lego/legoomni/include/hospital.h @@ -123,7 +123,7 @@ class Hospital : public LegoWorld { MxLong m_copLedAnimTimer; // 0x11c MxLong m_pizzaLedAnimTimer; // 0x120 MxLong m_time; // 0x124 - undefined m_unk0x128; // 0x128 + MxBool m_exited; // 0x128 }; #endif // HOSPITAL_H diff --git a/LEGO1/lego/legoomni/src/worlds/hospital.cpp b/LEGO1/lego/legoomni/src/worlds/hospital.cpp index 4aa4b5a8..dbb1c00c 100644 --- a/LEGO1/lego/legoomni/src/worlds/hospital.cpp +++ b/LEGO1/lego/legoomni/src/worlds/hospital.cpp @@ -46,7 +46,7 @@ Hospital::Hospital() m_flashingLeds = 0; m_copLedAnimTimer = 0; m_pizzaLedAnimTimer = 0; - m_unk0x128 = 0; + m_exited = FALSE; NotificationManager()->Register(this); } @@ -367,8 +367,8 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param) act1State = (Act1State*) GameState()->GetState("Act1State"); act1State->SetUnknown18(9); case HospitalState::e_exitToFront: - if (m_unk0x128 == 0) { - m_unk0x128 = 1; + if (m_exited == FALSE) { + m_exited = TRUE; m_destLocation = LegoGameState::e_hospitalExited; DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); @@ -376,8 +376,8 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param) } break; case HospitalState::e_exitToInfocenter: - if (m_unk0x128 == 0) { - m_unk0x128 = 1; + if (m_exited == FALSE) { + m_exited = TRUE; m_destLocation = LegoGameState::e_infomain; DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); @@ -410,8 +410,8 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param) m_interactionMode = 3; if (m_hospitalState->m_state == HospitalState::e_explainQuestShort) { - if (m_unk0x128 == 0) { - m_unk0x128 = 1; + if (m_exited == FALSE) { + m_exited = TRUE; TickleManager()->UnregisterClient(this); @@ -566,8 +566,8 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param) m_currentAction = HospitalScript::c_hho016cl_RunAnim; m_setWithCurrentAction = 1; } - else if (m_unk0x128 == 0) { - m_unk0x128 = 1; + else if (m_exited == FALSE) { + m_exited = TRUE; m_hospitalState->m_state = HospitalState::e_exitImmediately; m_destLocation = LegoGameState::e_infomain; @@ -587,8 +587,8 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param) m_currentAction = HospitalScript::c_hho016cl_RunAnim; m_setWithCurrentAction = 1; } - else if (m_unk0x128 == 0) { - m_unk0x128 = 1; + else if (m_exited == FALSE) { + m_exited = TRUE; m_hospitalState->m_state = HospitalState::e_exitImmediately; m_destLocation = LegoGameState::e_hospitalExited; From aa825aeecf44e61a02a240d72986bf49e26315d3 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 29 Jun 2025 08:55:34 -0700 Subject: [PATCH 04/13] Add macro for switchable building index (#1596) --- LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index 1e4a8b82..4ea96d2b 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -227,6 +227,8 @@ LegoBuildingInfo g_buildingInfo[16]; // GLOBAL: LEGO1 0x100f3748 MxS32 LegoBuildingManager::g_maxMove[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0}; +#define HAUS1_INDEX 12 + // FUNCTION: LEGO1 0x1002f8b0 void LegoBuildingManager::configureLegoBuildingManager(MxS32 p_buildingManagerConfig) { @@ -461,7 +463,7 @@ MxBool LegoBuildingManager::SwitchVariant(LegoEntity* p_entity) roi->SetVisibility(FALSE); info->m_variant = g_buildingInfoVariants[m_nextVariant]; - CreateBuilding(12, CurrentWorld()); + CreateBuilding(HAUS1_INDEX, CurrentWorld()); if (info->m_entity != NULL) { info->m_entity->GetROI()->SetVisibility(TRUE); From 77bbbfe2ca29c95bfc6f64cc9231b921c446c410 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 29 Jun 2025 09:15:42 -0700 Subject: [PATCH 05/13] (Pepper) Fix building variant switch bug (#451) * (Pepper) Fix building variant switch bug * Add comment --- LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index 4ea96d2b..8dae5d61 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -394,6 +394,9 @@ MxResult LegoBuildingManager::Read(LegoStorage* p_storage) m_nextVariant = 0; } + // Bugfix: allow Pepper to change variant building after save game load + g_buildingInfo[HAUS1_INDEX].m_variant = g_buildingInfoVariants[m_nextVariant]; + result = SUCCESS; done: From 6e7347621c535a3992be40692e950e21a9f6110f Mon Sep 17 00:00:00 2001 From: Brenden Davidson Date: Sun, 29 Jun 2025 14:04:08 -0500 Subject: [PATCH 06/13] Flatpak Build Support (#407) --- .editorconfig | 5 + .gitattributes | 4 + .github/workflows/release.yml | 34 +++- .gitignore | 6 + CMakeLists.txt | 2 + packaging/CMakeLists.txt | 19 +++ packaging/icons/isle.svg | 161 ++++++++++++++++++ packaging/linux/CMakeLists.txt | 7 + .../linux/flatpak/org.legoisland.Isle.json | 89 ++++++++++ packaging/linux/isledecomp.desktop.in | 37 ++++ packaging/linux/isledecomp.metainfo.xml.in | 91 ++++++++++ 11 files changed, 453 insertions(+), 2 deletions(-) create mode 100644 packaging/CMakeLists.txt create mode 100644 packaging/icons/isle.svg create mode 100644 packaging/linux/CMakeLists.txt create mode 100644 packaging/linux/flatpak/org.legoisland.Isle.json create mode 100644 packaging/linux/isledecomp.desktop.in create mode 100644 packaging/linux/isledecomp.metainfo.xml.in diff --git a/.editorconfig b/.editorconfig index c8d511ec..05d09a66 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,3 +14,8 @@ trim_trailing_whitespace = true [{CMakeLists.txt,*.cmake}] indent_size = 2 +insert_final_newline = true + +[*.{json,xml.in,desktop.in}] +indent_size = 2 +insert_final_newline = true diff --git a/.gitattributes b/.gitattributes index 232342c7..04926c6b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,7 @@ *.html text eol=lf diff=html *.mdp binary *.mak text eol=crlf +**/*.ico binary +**/*.png binary +**/*.svg text eol=lf +**/*.desktop text eol=lf diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef8fdae2..966ef3c6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -91,15 +91,45 @@ jobs: path: | build/dist/isle-* + flatpak: + name: "Flatpak (${{ matrix.arch }})" + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + os: ubuntu-latest + + - arch: aarch64 + os: ubuntu-22.04-arm + + container: + image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8 + options: --privileged + + steps: + - uses: actions/checkout@v4 + + - name: Build Flatpak + uses: flatpak/flatpak-github-actions/flatpak-builder@v6 + with: + bundle: org.legoisland.Isle.${{ matrix.arch }}.flatpak + manifest-path: packaging/linux/flatpak/org.legoisland.Isle.json + arch: ${{ matrix.arch }} + release: name: 'Release' runs-on: ubuntu-latest - needs: build + needs: + - build + - flatpak steps: - name: Download All Artifacts uses: actions/download-artifact@main with: - pattern: Release-* + pattern: "{Release-*,*.flatpak}" path: Release merge-multiple: true diff --git a/.gitignore b/.gitignore index 662466db..1610ba3d 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,9 @@ LEGO1.DLL # Kate - Text /.cache + +# Flatpak build cache +**/.flatpak-builder/ + +# Flatpak build dir +**/flatpak-build/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f7e0595..d77ce732 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -643,6 +643,8 @@ if(EMSCRIPTEN) ) endif() +add_subdirectory(packaging) + set(CPACK_PACKAGE_DIRECTORY "dist") set(CPACK_PACKAGE_FILE_NAME "isle-${PROJECT_VERSION}-${ISLE_PACKAGE_NAME}-${CMAKE_SYSTEM_PROCESSOR}") if(MSVC) diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt new file mode 100644 index 00000000..9994b0c0 --- /dev/null +++ b/packaging/CMakeLists.txt @@ -0,0 +1,19 @@ +set(APP_ID "org.legoisland.Isle") +set(APP_NAME "Isle Portable") +set(APP_SUMMARY "Portable version of the LEGO Island Decompilation Project") +set(APP_SPDX "LGPL-3.0-or-later") + +string(TIMESTAMP BUILD_DATE UTC) + +# The following will need to be refined if we wish to post actual releases to a repo such as Flathub +if(DEFINED ENV{GITHUB_ACTIONS} AND ENV{GITHUB_ACTIONS} EQUAL TRUE) + # Use the sequential run# of the current pipeline when running in GH Actions + set(SEMANTIC_VERSION "${PROJECT_VERSION}~build$ENV{GITHUB_RUN_NUMBER}") +else() + # Don't worry about the build number for local builds + set(SEMANTIC_VERSION "${PROJECT_VERSION}") +endif() + +if(LINUX) + add_subdirectory(linux) +endif() diff --git a/packaging/icons/isle.svg b/packaging/icons/isle.svg new file mode 100644 index 00000000..d3f6dbf1 --- /dev/null +++ b/packaging/icons/isle.svg @@ -0,0 +1,161 @@ + + + +LEGO Island IconLEGO Island Icon2025-06-22 diff --git a/packaging/linux/CMakeLists.txt b/packaging/linux/CMakeLists.txt new file mode 100644 index 00000000..2ece9db8 --- /dev/null +++ b/packaging/linux/CMakeLists.txt @@ -0,0 +1,7 @@ +# Injects the required variables into the Desktop and MetaInfo files +configure_file(isledecomp.desktop.in "${APP_ID}.desktop" @ONLY) +configure_file(isledecomp.metainfo.xml.in "${APP_ID}.metainfo.xml" @ONLY) + +install(FILES "../icons/isle.svg" RENAME "${APP_ID}.svg" DESTINATION "share/icons/hicolor/scalable/apps") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${APP_ID}.desktop" DESTINATION "share/applications") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${APP_ID}.metainfo.xml" DESTINATION "share/metainfo") diff --git a/packaging/linux/flatpak/org.legoisland.Isle.json b/packaging/linux/flatpak/org.legoisland.Isle.json new file mode 100644 index 00000000..e8cd3f8e --- /dev/null +++ b/packaging/linux/flatpak/org.legoisland.Isle.json @@ -0,0 +1,89 @@ +{ + "id": "org.legoisland.Isle", + + "runtime": "org.kde.Platform", + "sdk": "org.kde.Sdk", + "runtime-version": "6.8", + + "command": "isle", + + "finish-args": [ + "--share=ipc", + "--socket=wayland", + "--socket=fallback-x11", + "--socket=pulseaudio", + "--device=dri", + "--device=input", + "--filesystem=/run/media/:ro", + "--filesystem=/media/:ro", + "--filesystem=/mnt/:ro", + "--filesystem=home:ro" + ], + + "modules": [ + { + "name": "isle", + "buildsystem": "cmake-ninja", + "config-opts": [ + "-DCMAKE_BUILD_TYPE=RelWithDebInfo", + "-DISLE_DEBUG=OFF" + ], + "sources": [ + { + "type": "dir", + "path": "../../../3rdparty", + "dest": "3rdparty/" + }, + { + "type": "dir", + "path": "../../../cmake", + "dest": "cmake/" + }, + { + "type": "dir", + "path": "../../../CMake", + "dest": "CMake/" + }, + { + "type": "dir", + "path": "../../../CONFIG", + "dest": "CONFIG/" + }, + { + "type": "dir", + "path": "../../../ISLE", + "dest": "ISLE/" + }, + { + "type": "dir", + "path": "../../../LEGO1", + "dest": "LEGO1/" + }, + { + "type": "dir", + "path": "../../../miniwin", + "dest": "miniwin/" + }, + { + "type": "dir", + "path": "../../../packaging", + "dest": "packaging/" + }, + { + "type": "dir", + "path": "../../../util", + "dest": "util/" + }, + { + "type": "file", + "path": "../../../CMakeLists.txt" + } + ], + "build-options": { + "build-args": [ + "--share=network" + ] + } + } + ] +} diff --git a/packaging/linux/isledecomp.desktop.in b/packaging/linux/isledecomp.desktop.in new file mode 100644 index 00000000..a40c4a2a --- /dev/null +++ b/packaging/linux/isledecomp.desktop.in @@ -0,0 +1,37 @@ +[Desktop Entry] +Version=1.5 + +Name=@APP_NAME@ +Comment=@APP_SUMMARY@ + +Icon=@APP_ID@ +Type=Application +Categories=Game;KidsGame;AdventureGame;Qt + +Keywords=LEGO;lego;LEGO Island +Keywords[da]=LEGO;lego;Panik på LEGO Øen +Keywords[de]=LEGO;lego;Abenteuer auf der LEGO Insel +Keywords[es]=LEGO;lego;La Isla LEGO +Keywords[fr]=LEGO;lego;Aventures sur L'île LEGO +Keywords[it]=LEGO;lego;Isola LEGO +Keywords[ja]=LEGO;lego;レゴアイランドの大冒険 +Keywords[ko]=LEGO;lego;레고 아일랜드 +Keywords[pt]=LEGO;lego;A Ilha LEGO +Keywords[ru]=LEGO;lego;Остров LEGO + +SingleMainWindow=true + +TryExec=isle +Exec=isle + +Actions=play;configure + +[Desktop Action play] +Name=Play Game +Icon=currenttrack_play +Exec=isle + +[Desktop Action configure] +Name=Configure Settings +Icon=settings +Exec=isle-config diff --git a/packaging/linux/isledecomp.metainfo.xml.in b/packaging/linux/isledecomp.metainfo.xml.in new file mode 100644 index 00000000..b8faecc1 --- /dev/null +++ b/packaging/linux/isledecomp.metainfo.xml.in @@ -0,0 +1,91 @@ + + + + + @APP_ID@ + + @APP_NAME@ + @APP_SUMMARY@ + + @APP_ID@.desktop + + + #e3000b + + + + Isle Decomp Team + + + https://github.com/isledecomp/isle-portable + https://github.com/isledecomp/isle-portable/blob/master/CONTRIBUTING.md + https://github.com/isledecomp/isle-portable/tree/master + https://github.com/isledecomp/isle-portable/issues + + MIT + @APP_SPDX@ + + + 640 + offline-only + + + + 128 + + + + pointing + keyboard + gamepad + + + +

This initiative is a portable version of LEGO Island (Version 1.1, English) + based on the decompilation project. Our primary goal is to transform the codebase to achieve + platform independence, thereby enhancing compatibility across various systems while preserving + the original game's experience as faithfully as possible. +

+ +

+ Please note: this project is dedicated to achieving platform independence without altering the + core gameplay, adding new features, enhancing visual quality, or rewriting code for + improvement's sake. While those are worthwhile objectives, they are not within the scope + of this project. +

+ +
+ + + mild + mild + + + + Game + KidsGame + AdventureGame + Qt + + + + LEGO + lego + + LEGO Island + + Panik på LEGO Øen + Abenteuer auf der LEGO Insel + La Isla LEGO + Aventures sur L'île LEGO + Isola LEGO + レゴアイランドの大冒険 + 레고 아일랜드 + A Ilha LEGO + Остров LEGO + + + + + +
From 54694a4611ecf78392e71373687bde450186d934 Mon Sep 17 00:00:00 2001 From: Damglador <52221087+Damglador@users.noreply.github.com> Date: Sun, 29 Jun 2025 22:53:54 +0200 Subject: [PATCH 07/13] AppImage packaging (#439) * AppImage packaging * Add flags to specify location of required local files `--build=path` specifies where on the system is the directory with pre-build game binaries (must have binaries `isle` and `isle-config` in `path/bin` and game-specific libraries in `path/lib`) `--apprun=path` specifies where the apprun is `--desktop-file=path` same for the desktop file * Move to packaging/linux * Move building to appimage/build and ignore it in git * Use local icon. Option to specify location for it * Cleaning * Attempt at Github automation * Update CMakeLists.txt * Fix build * I guess it doesn't need quotes * Update CMakeLists.txt * Update release.yml * Work around for liblego1.so loading, fix arguments * Create testing.yml * Update testing.yml * I should pay more attention to what docs say * Fix copy-pasting mistake * Add AppImage packaging to the Release workflow * Try fixing filepicker * Delete testing.yml * Fix releases Can't specify where linuxdeploy leaves the file without specifying the name of the file, which I don't want to do, so just move the file in `dist` after packaging. * Remove unnecessary changes * Add qt6-xdgdesktopportal-platformtheme as deps Needed to call the xdg filepicker, basically desktop-specific filepicker. Hopefully this will allow to use it in AppImage * Get back flatpak in release * Update release.yml * Remove libglew-dev from apt install * Fix duplicate upload artifact * Update release.yml Co-authored-by: Christian Semmler * Remove *.AppImage pattern in Download All Artifacts --------- Co-authored-by: Christian Semmler --- .github/workflows/release.yml | 28 +++++++- packaging/CMakeLists.txt | 3 + packaging/linux/appimage/AppRun | 25 +++++++ packaging/linux/appimage/Build | 100 ++++++++++++++++++++++++++ packaging/linux/isledecomp.desktop.in | 1 + 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100755 packaging/linux/appimage/AppRun create mode 100755 packaging/linux/appimage/Build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 966ef3c6..e5d42a8b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,7 +46,7 @@ jobs: sudo apt-get install -y \ libx11-dev libxext-dev libxrandr-dev libxrender-dev libxfixes-dev libxi-dev libxinerama-dev \ libxcursor-dev libwayland-dev libxkbcommon-dev wayland-protocols libgl1-mesa-dev qt6-base-dev \ - libasound2-dev + libasound2-dev qt6-xdgdesktopportal-platformtheme - name: Install macOS dependencies (brew) if: ${{ matrix.brew }} @@ -84,12 +84,36 @@ jobs: cd build cpack . + - name: Install linuxdeploy + if: ${{ matrix.linux }} + id: install-linuxdeploy + uses: miurahr/install-linuxdeploy-action@v1.8.0 + with: + plugins: qt appimage + + - name: Package (AppImage) + if: ${{ matrix.linux }} + run: | + cd build && \ + export LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH" && \ + NO_STRIP=1 ${{ steps.install-linuxdeploy.outputs.linuxdeploy }} \ + -p qt \ + -e isle \ + -e isle-config \ + -d packaging/linux/org.legoisland.Isle.desktop \ + -i icons/org.legoisland.Isle.svg \ + --custom-apprun=../packaging/linux/appimage/AppRun \ + --appdir packaging/linux/appimage/AppDir \ + --output appimage && \ + mv *.AppImage dist/ + - name: Upload Artifact uses: actions/upload-artifact@main with: name: Release-${{ matrix.name }} path: | build/dist/isle-* + build/dist/*.AppImage flatpak: name: "Flatpak (${{ matrix.arch }})" @@ -118,7 +142,7 @@ jobs: bundle: org.legoisland.Isle.${{ matrix.arch }}.flatpak manifest-path: packaging/linux/flatpak/org.legoisland.Isle.json arch: ${{ matrix.arch }} - + release: name: 'Release' runs-on: ubuntu-latest diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt index 9994b0c0..d6fc19f0 100644 --- a/packaging/CMakeLists.txt +++ b/packaging/CMakeLists.txt @@ -5,6 +5,9 @@ set(APP_SPDX "LGPL-3.0-or-later") string(TIMESTAMP BUILD_DATE UTC) +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/icons) +file(COPY_FILE icons/isle.svg ${CMAKE_BINARY_DIR}/icons/${APP_ID}.svg) + # The following will need to be refined if we wish to post actual releases to a repo such as Flathub if(DEFINED ENV{GITHUB_ACTIONS} AND ENV{GITHUB_ACTIONS} EQUAL TRUE) # Use the sequential run# of the current pipeline when running in GH Actions diff --git a/packaging/linux/appimage/AppRun b/packaging/linux/appimage/AppRun new file mode 100755 index 00000000..0da15db1 --- /dev/null +++ b/packaging/linux/appimage/AppRun @@ -0,0 +1,25 @@ +#!/bin/sh + +HERE="$(dirname "$(readlink -f "${0}")")" + +MAIN=$(grep -r "^Exec=.*" "$HERE"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1) + +# MAIN_BIN=$(find "$HERE/usr/bin" -name "$MAIN" | head -n 1) +MAIN_BIN="$HERE/usr/bin/isle-config" + +export PATH="${HERE}/usr/bin/":$PATH # Prefer bundled binaries + +export QT_QPA_PLATFORMTHEME=xdgdesktopportal # Use XDG filepicker for forward compatability +[ -z "$QT_PLUGIN_PATH" ] && export QT_PLUGIN_PATH=/usr/lib/qt6/plugins:/usr/lib64/qt6/plugins # Use system Qt theme, will fallback to the default one if unavailable + + +if [ ! -z $APPIMAGE ]; then + BINARY_NAME=$(basename "$ARGV0") + if [ -e "$HERE/usr/bin/$BINARY_NAME" ]; then + exec "$HERE/usr/bin/$BINARY_NAME" "$@" + else + exec "${MAIN_BIN}" "$@" + fi +else + exec "${MAIN_BIN}" "$@" +fi diff --git a/packaging/linux/appimage/Build b/packaging/linux/appimage/Build new file mode 100755 index 00000000..9cf0325c --- /dev/null +++ b/packaging/linux/appimage/Build @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +set -e + +export LD_LIBRARY_PATH="build/source/lib:$LD_LIBRARY_PATH" +[ -z "$QMAKE" ] && export QMAKE=/usr/lib/qt6/bin/qmake + +# Sets a directory that has to have a following structure: +# build +# ├── bin +# │   ├── isle +# │   └── isle-config +# └── lib +# ├── liblego1.so +# ├── libSDL3.so -> libSDL3.so.0 # Not important if available on the system +# ├── libSDL3.so.0 -> libSDL3.so.0.3.0 # Not important if available on the system +# └── libSDL3.so.0.3.0 # Not important if available on the system +# Can also be defined using --build=path +BUILD_SOURCE=source + +# Sets where AppRun for AppImage is, can also be defined using --apprun=path +APPRUN_SOURCE=AppRun + +# Sets where desktop file for AppImage is, can also be defined using --desktop-file=path +DESKTOP_FILE_SOURCE=isledecomp.desktop + +# You know the drill +ICON_SOURCE=../../icons/isle.svg + +cd $(dirname $0) + +clean(){ + echo "Deleting build directory" + rm -rf build +} + +download(){ + if [ ! -e "$1" ]; then + curl -Lo "$1" "$2" + fi +} + +prepare(){ + mkdir -p build/tools + mkdir -p build/assets + + download build/tools/appimagetool.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$(uname -m).AppImage + chmod u+x build/tools/appimagetool.AppImage + + download build/tools/linuxdeploy.AppImage https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-$(uname -m).AppImage + chmod u+x build/tools/linuxdeploy.AppImage + + download build/tools/linuxdeploy-plugin-qt.AppImage https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/latest/download/linuxdeploy-plugin-qt-$(uname -m).AppImage + chmod u+x build/tools/linuxdeploy-plugin-qt.AppImage + + if [ ! -f "build/assets/isledecomp.desktop" ]; then + cp $DESKTOP_FILE_SOURCE build/assets/isledecomp.desktop + cp $APPRUN_SOURCE build/assets/AppRun + cp ../../icons/isle.svg build/assets/isle.svg + fi + + if [ ! -d "build/source" ]; then + cp -r $BUILD_SOURCE build/source + fi +} + +compile(){ + NO_STRIP=1 build/tools/linuxdeploy.AppImage \ + --plugin qt \ + -e build/source/bin/isle \ + -e build/source/bin/isle-config \ + -d build/assets/isledecomp.desktop \ + -i build/assets/isle.svg \ + --custom-apprun=AppRun \ + --appdir=build/AppDir +} + +package(){ + build/tools/appimagetool.AppImage build/AppDir build/"LEGO_Island-$(uname -m).AppImage" +} + +stop(){ # Can be used to do `Build clean stop` to just clean the directory + exit +} + +for arg in "$@"; do + case "$arg" in + --build=*) BUILD_SOURCE="${arg#--build=}";; + --apprun=*) APPRUN_SOURCE="${arg#--apprun=}";; + --desktop-file=*) DESKTOP_FILE_SOURCE="${arg#--desktop-file=}";; + --icon=*) ICON_SOURCE="${arg#--icon=}";; + *) "$arg" + esac +done + +prepare +compile +package +# Symlinks named as binaries in appimage can call these binaries specifically +# ln -s "LEGO_Island-$(uname -m).AppImage" isle-config +# ln -s "LEGO_Island-$(uname -m).AppImage" isle \ No newline at end of file diff --git a/packaging/linux/isledecomp.desktop.in b/packaging/linux/isledecomp.desktop.in index a40c4a2a..28309205 100644 --- a/packaging/linux/isledecomp.desktop.in +++ b/packaging/linux/isledecomp.desktop.in @@ -18,6 +18,7 @@ Keywords[ja]=LEGO;lego;レゴアイランドの大冒険 Keywords[ko]=LEGO;lego;레고 아일랜드 Keywords[pt]=LEGO;lego;A Ilha LEGO Keywords[ru]=LEGO;lego;Остров LEGO +Keywords[uk_UA]=LEGO;lego;LEGO острів SingleMainWindow=true From daa0bd1a32e5f92845817d0e52170dfa9c2da074 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sun, 29 Jun 2025 22:50:28 +0000 Subject: [PATCH 08/13] ci: combine ci and release workflow (#453) --- .github/workflows/ci.yml | 105 ++++++++++++++++++--- .github/workflows/release.yml | 170 ---------------------------------- 2 files changed, 93 insertions(+), 182 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64c447e5..43248276 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,14 +33,14 @@ jobs: fail-fast: false matrix: include: - - { name: 'Linux', os: 'ubuntu-latest', dx5: false, config: true, build-type: 'Debug', linux: true, werror: true, clang-tidy: true } - - { name: 'MSVC (x86)', os: 'windows-latest', dx5: true, config: false, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_x86' } - - { name: 'MSVC (x64)', os: 'windows-latest', dx5: false, config: false, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64' } - - { name: 'MSVC (arm64)', os: 'windows-latest', dx5: false, config: false, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_arm64' } - - { name: 'msys2 mingw32', os: 'windows-latest', dx5: false, config: false, build-type: 'Debug', 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, build-type: 'Debug', mingw: true, werror: true, clang-tidy: true, msystem: 'mingw64', msys-env: 'mingw-w64-x86_64', shell: 'msys2 {0}' } - - { name: 'macOS', os: 'macos-latest', dx5: false, config: true, build-type: 'Debug', brew: true, werror: true, clang-tidy: false } - - { name: 'Emscripten', os: 'ubuntu-latest', dx5: false, config: false, build-type: 'Debug', emsdk: true, werror: true, clang-tidy: false, cmake-wrapper: 'emcmake' } + - { 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 (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}' } + - { name: 'macOS', os: 'macos-latest', dx5: false, config: true, brew: true, werror: true, clang-tidy: false } + - { name: 'Emscripten', os: 'ubuntu-latest', dx5: false, config: false, emsdk: true, werror: true, clang-tidy: false, cmake-wrapper: 'emcmake' } steps: - name: Setup vcvars if: ${{ !!matrix.msvc }} @@ -67,7 +67,7 @@ jobs: sudo apt-get install -y \ libx11-dev libxext-dev libxrandr-dev libxrender-dev libxfixes-dev libxi-dev libxinerama-dev \ libxcursor-dev libwayland-dev libxkbcommon-dev wayland-protocols libgl1-mesa-dev qt6-base-dev \ - libasound2-dev + libasound2-dev qt6-xdgdesktopportal-platformtheme - name: Install macOS dependencies (brew) if: ${{ matrix.brew }} @@ -89,11 +89,12 @@ jobs: - name: Configure (CMake) run: | ${{ matrix.cmake-wrapper || '' }} cmake -S . -B build -GNinja \ - -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ + -DCMAKE_BUILD_TYPE=Release \ -DISLE_USE_DX5=${{ !!matrix.dx5 }} \ -DISLE_BUILD_CONFIG=${{ matrix.config }} \ -DENABLE_CLANG_TIDY=${{ !!matrix.clang-tidy }} \ -DISLE_WERROR=${{ !!matrix.werror }} \ + -DISLE_DEBUG=OFF \ -Werror=dev - name: Build (CMake) @@ -104,11 +105,64 @@ jobs: cd build cpack . + - name: Install linuxdeploy + if: ${{ matrix.linux }} + id: install-linuxdeploy + uses: miurahr/install-linuxdeploy-action@v1.8.0 + with: + plugins: qt appimage + + - name: Package (AppImage) + if: ${{ matrix.linux }} + run: | + cd build && \ + export LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH" && \ + NO_STRIP=1 ${{ steps.install-linuxdeploy.outputs.linuxdeploy }} \ + -p qt \ + -e isle \ + -e isle-config \ + -d packaging/linux/org.legoisland.Isle.desktop \ + -i icons/org.legoisland.Isle.svg \ + --custom-apprun=../packaging/linux/appimage/AppRun \ + --appdir packaging/linux/appimage/AppDir \ + --output appimage && \ + mv *.AppImage dist/ + - name: Upload Build Artifacts uses: actions/upload-artifact@v4 with: - name: '${{ matrix.name }} ${{ matrix.build-type }}' - path: build/dist/isle-* + name: '${{ matrix.name }}' + path: | + build/dist/isle-* + build/dist/*.AppImage + + flatpak: + name: "Flatpak (${{ matrix.arch }})" + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + os: ubuntu-latest + + - arch: aarch64 + os: ubuntu-22.04-arm + + container: + image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8 + options: --privileged + + steps: + - uses: actions/checkout@v4 + + - name: Build Flatpak + uses: flatpak/flatpak-github-actions/flatpak-builder@v6 + with: + bundle: org.legoisland.Isle.${{ matrix.arch }}.flatpak + manifest-path: packaging/linux/flatpak/org.legoisland.Isle.json + arch: ${{ matrix.arch }} ncc: name: 'C++' @@ -148,3 +202,30 @@ jobs: LEGO1/omni/src/video/flic.cpp \ $action_headers \ --path LEGO1/omni LEGO1/lego/legoomni + + release: + name: 'Release' + if: ${{ github.event_name == 'push' && github.ref_name == 'master' }} + runs-on: ubuntu-latest + needs: + - build + - flatpak + steps: + - name: Download All Artifacts + uses: actions/download-artifact@main + with: + pattern: "{Release-*,*.flatpak}" + path: Release + merge-multiple: true + + - name: Checkout uploadtool + uses: actions/checkout@v4 + with: + repository: 'probonopd/uploadtool' + path: 'uploadtool' + + - name: Upload Continuous Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ./uploadtool/upload.sh Release/* diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index e5d42a8b..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,170 +0,0 @@ -name: Release - -on: - push: - branches: - - master - -jobs: - build: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - defaults: - run: - shell: ${{ matrix.shell || 'sh' }} - - strategy: - fail-fast: false - matrix: - include: - - { name: 'Linux', os: 'ubuntu-latest', dx5: false, config: true, build-type: 'Release', linux: true, werror: true, clang-tidy: false } - - { name: 'Windows', os: 'windows-latest', dx5: false, config: false, build-type: 'Release', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64' } - - { name: 'macOS', os: 'macos-latest', dx5: false, config: true, build-type: 'Release', brew: true, werror: true, clang-tidy: false } - steps: - - name: Setup vcvars - if: ${{ !!matrix.msvc }} - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: ${{ matrix.vc-arch }} - - - name: Set up MSYS2 - if: ${{ !!matrix.msystem }} - uses: msys2/setup-msys2@v2 - with: - msystem: ${{ matrix.msystem }} - install: >- - ${{ matrix.msys-env }}-cc - ${{ matrix.msys-env }}-cmake - ${{ matrix.msys-env }}-ninja - ${{ matrix.msys-env }}-clang-tools-extra - ${{ (matrix.config && format('{0}-qt6-base', matrix.msys-env)) || '' }} - - - name: Install Linux dependencies (apt-get) - if: ${{ matrix.linux }} - run: | - sudo apt-get update - sudo apt-get install -y \ - libx11-dev libxext-dev libxrandr-dev libxrender-dev libxfixes-dev libxi-dev libxinerama-dev \ - libxcursor-dev libwayland-dev libxkbcommon-dev wayland-protocols libgl1-mesa-dev qt6-base-dev \ - libasound2-dev qt6-xdgdesktopportal-platformtheme - - - name: Install macOS dependencies (brew) - if: ${{ matrix.brew }} - run: | - brew update - brew install cmake ninja llvm qt6 - echo "LLVM_ROOT=$(brew --prefix llvm)/bin" >> $GITHUB_ENV - - - name: Setup Emscripten - uses: mymindstorm/setup-emsdk@master - if: ${{ matrix.emsdk }} - - - name: Setup ninja - if: ${{ matrix.msvc }} - uses: ashutoshvarma/setup-ninja@master - - - uses: actions/checkout@v4 - - - name: Configure (CMake) - run: | - ${{ matrix.cmake-wrapper || '' }} cmake -S . -B build -GNinja \ - -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ - -DISLE_USE_DX5=${{ !!matrix.dx5 }} \ - -DISLE_BUILD_CONFIG=${{ matrix.config }} \ - -DENABLE_CLANG_TIDY=${{ !!matrix.clang-tidy }} \ - -DISLE_WERROR=${{ !!matrix.werror }} \ - -DISLE_DEBUG=OFF \ - -Werror=dev - - - name: Build (CMake) - run: cmake --build build --verbose - - - name: Package (CPack) - run: | - cd build - cpack . - - - name: Install linuxdeploy - if: ${{ matrix.linux }} - id: install-linuxdeploy - uses: miurahr/install-linuxdeploy-action@v1.8.0 - with: - plugins: qt appimage - - - name: Package (AppImage) - if: ${{ matrix.linux }} - run: | - cd build && \ - export LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH" && \ - NO_STRIP=1 ${{ steps.install-linuxdeploy.outputs.linuxdeploy }} \ - -p qt \ - -e isle \ - -e isle-config \ - -d packaging/linux/org.legoisland.Isle.desktop \ - -i icons/org.legoisland.Isle.svg \ - --custom-apprun=../packaging/linux/appimage/AppRun \ - --appdir packaging/linux/appimage/AppDir \ - --output appimage && \ - mv *.AppImage dist/ - - - name: Upload Artifact - uses: actions/upload-artifact@main - with: - name: Release-${{ matrix.name }} - path: | - build/dist/isle-* - build/dist/*.AppImage - - flatpak: - name: "Flatpak (${{ matrix.arch }})" - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - include: - - arch: x86_64 - os: ubuntu-latest - - - arch: aarch64 - os: ubuntu-22.04-arm - - container: - image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8 - options: --privileged - - steps: - - uses: actions/checkout@v4 - - - name: Build Flatpak - uses: flatpak/flatpak-github-actions/flatpak-builder@v6 - with: - bundle: org.legoisland.Isle.${{ matrix.arch }}.flatpak - manifest-path: packaging/linux/flatpak/org.legoisland.Isle.json - arch: ${{ matrix.arch }} - - release: - name: 'Release' - runs-on: ubuntu-latest - needs: - - build - - flatpak - steps: - - name: Download All Artifacts - uses: actions/download-artifact@main - with: - pattern: "{Release-*,*.flatpak}" - path: Release - merge-multiple: true - - - name: Checkout uploadtool - uses: actions/checkout@v4 - with: - repository: 'probonopd/uploadtool' - path: 'uploadtool' - - - name: Upload Continuous Release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - ./uploadtool/upload.sh Release/* From 79462824e85deb81848ef5242e7a6b7948c43632 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sun, 29 Jun 2025 23:35:24 +0000 Subject: [PATCH 09/13] Fix continuous release (#454) --- .github/workflows/ci.yml | 4 +- CMakeLists.txt | 8 +- cmake/detectcpu.cmake | 156 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 cmake/detectcpu.cmake diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43248276..c6124f37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: ${{ matrix.cmake-wrapper || '' }} cmake -S . -B build -GNinja \ -DCMAKE_BUILD_TYPE=Release \ -DISLE_USE_DX5=${{ !!matrix.dx5 }} \ - -DISLE_BUILD_CONFIG=${{ matrix.config }} \ + -DISLE_BUILD_CONFIG=${{ !!matrix.config }} \ -DENABLE_CLANG_TIDY=${{ !!matrix.clang-tidy }} \ -DISLE_WERROR=${{ !!matrix.werror }} \ -DISLE_DEBUG=OFF \ @@ -214,7 +214,7 @@ jobs: - name: Download All Artifacts uses: actions/download-artifact@main with: - pattern: "{Release-*,*.flatpak}" + pattern: "*" path: Release merge-multiple: true diff --git a/CMakeLists.txt b/CMakeLists.txt index d77ce732..f221d342 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") include(CheckCXXSourceCompiles) include(CMakeDependentOption) include(CMakePushCheckState) +include(cmake/detectcpu.cmake) + +DetectTargetCPUArchitectures(ISLE_CPUS) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -624,7 +627,8 @@ else() include(GNUInstallDirs) endif() -set(ISLE_PACKAGE_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CACHE STRING "Platform name of the package") +string(REPLACE ";" "-" ISLE_CPUS_STRING "${ISLE_CPU}") +set(ISLE_PACKAGE_NAME "${CMAKE_SYSTEM_NAME}-${ISLE_CPUS_STRING}" CACHE STRING "Platform name of the package") if(BUILD_SHARED_LIBS) list(APPEND install_extra_targets lego1) endif() @@ -646,7 +650,7 @@ endif() add_subdirectory(packaging) set(CPACK_PACKAGE_DIRECTORY "dist") -set(CPACK_PACKAGE_FILE_NAME "isle-${PROJECT_VERSION}-${ISLE_PACKAGE_NAME}-${CMAKE_SYSTEM_PROCESSOR}") +set(CPACK_PACKAGE_FILE_NAME "isle-${PROJECT_VERSION}-${ISLE_PACKAGE_NAME}") if(MSVC) set(CPACK_GENERATOR ZIP) else() diff --git a/cmake/detectcpu.cmake b/cmake/detectcpu.cmake new file mode 100644 index 00000000..e0b6feae --- /dev/null +++ b/cmake/detectcpu.cmake @@ -0,0 +1,156 @@ +function(DetectTargetCPUArchitectures DETECTED_ARCHS) + + set(known_archs EMSCRIPTEN ARM32 ARM64 ARM64EC LOONGARCH64 POWERPC32 POWERPC64 X86 X64) + + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + foreach(known_arch IN LISTS known_archs) + set(CPU_${known_arch} "0" PARENT_SCOPE) + endforeach() + set(detected_archs) + foreach(osx_arch IN LISTS CMAKE_OSX_ARCHITECTURES) + if(osx_arch STREQUAL "x86_64") + set(CPU_X64 "1" PARENT_SCOPE) + list(APPEND detected_archs "X64") + elseif(osx_arch STREQUAL "arm64") + set(CPU_ARM64 "1" PARENT_SCOPE) + list(APPEND detected_archs "ARM64") + endif() + endforeach() + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) + return() + endif() + + set(detected_archs) + foreach(known_arch IN LISTS known_archs) + if(CPU_${known_arch}) + list(APPEND detected_archs "${known_arch}") + endif() + endforeach() + + if(detected_archs) + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) + return() + endif() + + set(arch_check_ARM32 "defined(__arm__) || defined(_M_ARM)") + set(arch_check_ARM64 "defined(__aarch64__) || defined(_M_ARM64)") + set(arch_check_ARM64EC "defined(_M_ARM64EC)") + set(arch_check_EMSCRIPTEN "defined(__EMSCRIPTEN__)") + set(arch_check_LOONGARCH64 "defined(__loongarch64)") + set(arch_check_POWERPC32 "(defined(__PPC__) || defined(__powerpc__)) && !defined(__powerpc64__)") + set(arch_check_POWERPC64 "defined(__PPC64__) || defined(__powerpc64__)") + set(arch_check_X86 "defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)") + set(arch_check_X64 "(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC)") + + set(src_vars "") + set(src_main "") + foreach(known_arch IN LISTS known_archs) + set(detected_${known_arch} "0") + + string(APPEND src_vars " +#if ${arch_check_${known_arch}} +#define ARCH_${known_arch} \"1\" +#else +#define ARCH_${known_arch} \"0\" +#endif +const char *arch_${known_arch} = \"INFO<${known_arch}=\" ARCH_${known_arch} \">\"; +") + string(APPEND src_main " + result += arch_${known_arch}[argc];") + endforeach() + + set(src_arch_detect "${src_vars} +int main(int argc, char *argv[]) { + int result = 0; + (void)argv; +${src_main} + return result; +}") + + if(CMAKE_C_COMPILER) + set(ext ".c") + elseif(CMAKE_CXX_COMPILER) + set(ext ".cpp") + else() + enable_language(C) + set(ext ".c") + endif() + set(path_src_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/detect_arch${ext}") + file(WRITE "${path_src_arch_detect}" "${src_arch_detect}") + set(path_dir_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/detect_arch") + set(path_bin_arch_detect "${path_dir_arch_detect}/bin") + + set(detected_archs) + + set(msg "Detecting Target CPU Architecture") + message(STATUS "${msg}") + + include(CMakePushCheckState) + + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + + cmake_push_check_state(RESET) + try_compile(CPU_CHECK_ALL + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/detect_arch" + SOURCES "${path_src_arch_detect}" + COPY_FILE "${path_bin_arch_detect}" + ) + cmake_pop_check_state() + if(NOT CPU_CHECK_ALL) + message(STATUS "${msg} - ") + message(WARNING "Failed to compile source detecting the target CPU architecture") + else() + set(re "INFO<([A-Z0-9]+)=([01])>") + file(STRINGS "${path_bin_arch_detect}" infos REGEX "${re}") + + foreach(info_arch_01 IN LISTS infos) + string(REGEX MATCH "${re}" A "${info_arch_01}") + if(NOT "${CMAKE_MATCH_1}" IN_LIST known_archs) + message(WARNING "Unknown architecture: \"${CMAKE_MATCH_1}\"") + continue() + endif() + set(arch "${CMAKE_MATCH_1}") + set(arch_01 "${CMAKE_MATCH_2}") + set(detected_${arch} "${arch_01}") + endforeach() + + foreach(known_arch IN LISTS known_archs) + if(detected_${known_arch}) + list(APPEND detected_archs ${known_arch}) + endif() + endforeach() + endif() + + if(detected_archs) + foreach(known_arch IN LISTS known_archs) + set("CPU_${known_arch}" "${detected_${known_arch}}" CACHE BOOL "Detected architecture ${known_arch}") + endforeach() + message(STATUS "${msg} - ${detected_archs}") + else() + include(CheckCSourceCompiles) + cmake_push_check_state(RESET) + foreach(known_arch IN LISTS known_archs) + if(NOT detected_archs) + set(cache_variable "CPU_${known_arch}") + set(test_src " + int main(int argc, char *argv[]) { + #if ${arch_check_${known_arch}} + return 0; + #else + choke + #endif + } + ") + check_c_source_compiles("${test_src}" "${cache_variable}") + if(${cache_variable}) + set(CPU_${known_arch} "1" CACHE BOOL "Detected architecture ${known_arch}") + set(detected_archs ${known_arch}) + else() + set(CPU_${known_arch} "0" CACHE BOOL "Detected architecture ${known_arch}") + endif() + endif() + endforeach() + cmake_pop_check_state() + endif() + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) +endfunction() From a258a89b1f7265efc8240ca0ee2551e3c6d747f8 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 30 Jun 2025 00:06:21 +0000 Subject: [PATCH 10/13] cmake: fix typo of architecture used in binary artifact (#455) --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f221d342..ac3663fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -627,7 +627,8 @@ else() include(GNUInstallDirs) endif() -string(REPLACE ";" "-" ISLE_CPUS_STRING "${ISLE_CPU}") +string(REPLACE ";" "-" ISLE_CPUS_STRING "${ISLE_CPUS}") +string(TOLOWER "${ISLE_CPUS_STRING}" ISLE_CPUS_STRING) set(ISLE_PACKAGE_NAME "${CMAKE_SYSTEM_NAME}-${ISLE_CPUS_STRING}" CACHE STRING "Platform name of the package") if(BUILD_SHARED_LIBS) list(APPEND install_extra_targets lego1) From 225adda309deaba0d289fc8fa9543737e51dc953 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Mon, 30 Jun 2025 22:51:26 +0200 Subject: [PATCH 11/13] Rendering refactoring (#459) * Hint texture intent to renderer * improve transparancy for 32bit rendering * Align OpenGL ES 2.0 with SDL_GPU's 2D rendering --- LEGO1/omni/src/video/mxdisplaysurface.cpp | 20 +- .../src/d3drm/backends/directx9/renderer.cpp | 20 +- .../src/d3drm/backends/opengl1/renderer.cpp | 20 +- .../src/d3drm/backends/opengles2/renderer.cpp | 353 +++++++++--------- .../src/d3drm/backends/sdl3gpu/renderer.cpp | 53 +-- .../src/d3drm/backends/software/renderer.cpp | 20 +- miniwin/src/ddraw/ddraw.cpp | 16 +- miniwin/src/ddraw/framebuffer.cpp | 2 +- miniwin/src/internal/d3drmrenderer.h | 4 +- miniwin/src/internal/d3drmrenderer_directx9.h | 23 +- miniwin/src/internal/d3drmrenderer_opengl1.h | 23 +- .../src/internal/d3drmrenderer_opengles2.h | 38 +- miniwin/src/internal/d3drmrenderer_sdl3gpu.h | 23 +- miniwin/src/internal/d3drmrenderer_software.h | 20 +- miniwin/src/internal/ddraw_impl.h | 9 +- miniwin/src/internal/meshutils.cpp | 28 ++ miniwin/src/internal/meshutils.h | 10 + 17 files changed, 330 insertions(+), 352 deletions(-) diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index 6c93a0e7..c2886ebe 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -926,7 +926,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( transparentColor = RGB555_CREATE(0x1f, 0, 0x1f); break; default: - transparentColor = RGB8888_CREATE(0xff, 0, 0xff, 0); + transparentColor = RGB8888_CREATE(0, 0, 0, 0); break; } @@ -971,25 +971,11 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( surfacePtr += adjustedPitch; } - if (p_transparent && surface) { - DDCOLORKEY key; - key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = transparentColor; - surface->SetColorKey(DDCKEY_SRCBLT, &key); - } - surface->Unlock(ddsd.lpSurface); - if (p_transparent && surface) { + if (p_transparent && surface && bytesPerPixel != 4) { DDCOLORKEY key; - if (bytesPerPixel == 1) { - key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = 0; - } - else if (bytesPerPixel == 2) { - key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = RGB555_CREATE(0x1f, 0, 0x1f); - } - else { - key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = RGB8888_CREATE(0xff, 0, 0xff, 0); - } + key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = transparentColor; surface->SetColorKey(DDCKEY_SRCBLT, &key); } } diff --git a/miniwin/src/d3drm/backends/directx9/renderer.cpp b/miniwin/src/d3drm/backends/directx9/renderer.cpp index 574939f5..5917cd07 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) +Uint32 DirectX9Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -216,24 +216,6 @@ Uint32 DirectX9Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshG return static_cast(m_meshs.size() - 1); } -void DirectX9Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - halDesc->dcmColorModel = D3DCOLORMODEL::RGB; - halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - halDesc->dwDeviceZBufferBitDepth = DDBD_24; - helDesc->dwDeviceRenderBitDepth = DDBD_32; - halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; - halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; - halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; - - memset(helDesc, 0, sizeof(D3DDEVICEDESC)); -} - -const char* DirectX9Renderer::GetName() -{ - return "DirectX 9 HAL"; -} - HRESULT DirectX9Renderer::BeginFrame() { return Actual_BeginFrame(); diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index a0b84a80..66f08d23 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -122,7 +122,7 @@ void OpenGL1Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* t ); } -Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture) +Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -265,24 +265,6 @@ Uint32 OpenGL1Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGr return (Uint32) (m_meshs.size() - 1); } -void OpenGL1Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - halDesc->dcmColorModel = D3DCOLORMODEL::RGB; - halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - halDesc->dwDeviceZBufferBitDepth = DDBD_24; - helDesc->dwDeviceRenderBitDepth = DDBD_32; - halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; - halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; - halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; - - memset(helDesc, 0, sizeof(D3DDEVICEDESC)); -} - -const char* OpenGL1Renderer::GetName() -{ - return "OpenGL 1.1 HAL"; -} - HRESULT OpenGL1Renderer::BeginFrame() { GL11_BeginFrame((Matrix4x4*) &m_projection[0][0]); diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp index 9305510a..8c39d937 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp @@ -181,14 +181,88 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) return new OpenGLES2Renderer(width, height, context, shaderProgram); } +GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = false) +{ + GLES2MeshCacheEntry cache{&meshGroup, meshGroup.version}; + + cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT; + + std::vector vertices; + if (cache.flat) { + FlattenSurfaces( + meshGroup.vertices.data(), + meshGroup.vertices.size(), + meshGroup.indices.data(), + meshGroup.indices.size(), + meshGroup.texture != nullptr || forceUV, + vertices, + cache.indices + ); + } + else { + vertices = meshGroup.vertices; + cache.indices.resize(meshGroup.indices.size()); + std::transform(meshGroup.indices.begin(), meshGroup.indices.end(), cache.indices.begin(), [](DWORD index) { + return static_cast(index); + }); + } + + std::vector texcoords; + if (meshGroup.texture || forceUV) { + texcoords.resize(vertices.size()); + std::transform(vertices.begin(), vertices.end(), texcoords.begin(), [](const D3DRMVERTEX& v) { + return v.texCoord; + }); + } + std::vector positions(vertices.size()); + std::transform(vertices.begin(), vertices.end(), positions.begin(), [](const D3DRMVERTEX& v) { + return v.position; + }); + std::vector normals(vertices.size()); + std::transform(vertices.begin(), vertices.end(), normals.begin(), [](const D3DRMVERTEX& v) { return v.normal; }); + + glGenBuffers(1, &cache.vboPositions); + glBindBuffer(GL_ARRAY_BUFFER, cache.vboPositions); + glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(D3DVECTOR), positions.data(), GL_STATIC_DRAW); + + glGenBuffers(1, &cache.vboNormals); + glBindBuffer(GL_ARRAY_BUFFER, cache.vboNormals); + glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(D3DVECTOR), normals.data(), GL_STATIC_DRAW); + + if (meshGroup.texture || forceUV) { + glGenBuffers(1, &cache.vboTexcoords); + glBindBuffer(GL_ARRAY_BUFFER, cache.vboTexcoords); + glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(TexCoord), texcoords.data(), GL_STATIC_DRAW); + } + + glGenBuffers(1, &cache.ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache.ibo); + glBufferData( + GL_ELEMENT_ARRAY_BUFFER, + cache.indices.size() * sizeof(cache.indices[0]), + cache.indices.data(), + GL_STATIC_DRAW + ); + + return cache; +} + OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram) : m_context(context), m_shaderProgram(shaderProgram) { - m_width = width; - m_height = height; m_virtualWidth = width; m_virtualHeight = height; - m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32); + ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f}; + Resize(width, height, viewportTransform); + + m_uiMesh.vertices = { + {{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}}, + {{1.0f, 0.0f, 0.0f}, {0, 0, -1}, {1.0f, 0.0f}}, + {{1.0f, 1.0f, 0.0f}, {0, 0, -1}, {1.0f, 1.0f}}, + {{0.0f, 1.0f, 0.0f}, {0, 0, -1}, {0.0f, 1.0f}} + }; + m_uiMesh.indices = {0, 1, 2, 0, 2, 3}; + m_uiMeshCache = GLES2UploadMesh(m_uiMesh, true); } OpenGLES2Renderer::~OpenGLES2Renderer() @@ -239,7 +313,48 @@ void OpenGLES2Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* ); } -Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture) +bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUi) +{ + SDL_Surface* surf = source; + if (source->format != SDL_PIXELFORMAT_RGBA32) { + surf = SDL_ConvertSurface(source, SDL_PIXELFORMAT_RGBA32); + if (!surf) { + return false; + } + } + + glGenTextures(1, &outTexId); + 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) { + 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if (strstr((const char*) glGetString(GL_EXTENSIONS), "GL_EXT_texture_filter_anisotropic")) { + GLfloat maxAniso = 0.0f; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); + GLfloat desiredAniso = fminf(8.0f, maxAniso); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, desiredAniso); + } + glGenerateMipmap(GL_TEXTURE_2D); + } + + if (surf != source) { + SDL_DestroySurface(surf); + } + + return true; +} + +Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -249,31 +364,18 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture) if (tex.texture == texture) { if (tex.version != texture->m_version) { glDeleteTextures(1, &tex.glTextureId); - glGenTextures(1, &tex.glTextureId); - glBindTexture(GL_TEXTURE_2D, tex.glTextureId); - - SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32); - if (!surf) { - return NO_TEXTURE_ID; + if (UploadTexture(surface->m_surface, tex.glTextureId, isUi)) { + tex.version = texture->m_version; } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); - SDL_DestroySurface(surf); - - tex.version = texture->m_version; } return i; } } GLuint texId; - glGenTextures(1, &texId); - glBindTexture(GL_TEXTURE_2D, texId); - - SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32); - if (!surf) { + if (!UploadTexture(surface->m_surface, texId, isUi)) { return NO_TEXTURE_ID; } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); for (Uint32 i = 0; i < m_textures.size(); ++i) { auto& tex = m_textures[i]; @@ -281,85 +383,20 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture) tex.texture = texture; tex.version = texture->m_version; tex.glTextureId = texId; - tex.width = surf->w; - tex.height = surf->h; + tex.width = surface->m_surface->w; + tex.height = surface->m_surface->h; AddTextureDestroyCallback(i, texture); return i; } } - m_textures.push_back({texture, texture->m_version, texId, (uint16_t) surf->w, (uint16_t) surf->h}); - SDL_DestroySurface(surf); + m_textures.push_back( + {texture, texture->m_version, texId, (uint16_t) surface->m_surface->w, (uint16_t) surface->m_surface->h} + ); AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture); return (Uint32) (m_textures.size() - 1); } -GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup) -{ - GLES2MeshCacheEntry cache{&meshGroup, meshGroup.version}; - - cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT; - - std::vector vertices; - if (cache.flat) { - FlattenSurfaces( - meshGroup.vertices.data(), - meshGroup.vertices.size(), - meshGroup.indices.data(), - meshGroup.indices.size(), - meshGroup.texture != nullptr, - vertices, - cache.indices - ); - } - else { - vertices = meshGroup.vertices; - cache.indices.resize(meshGroup.indices.size()); - std::transform(meshGroup.indices.begin(), meshGroup.indices.end(), cache.indices.begin(), [](DWORD index) { - return static_cast(index); - }); - } - - std::vector texcoords; - if (meshGroup.texture) { - texcoords.resize(vertices.size()); - std::transform(vertices.begin(), vertices.end(), texcoords.begin(), [](const D3DRMVERTEX& v) { - return v.texCoord; - }); - } - std::vector positions(vertices.size()); - std::transform(vertices.begin(), vertices.end(), positions.begin(), [](const D3DRMVERTEX& v) { - return v.position; - }); - std::vector normals(vertices.size()); - std::transform(vertices.begin(), vertices.end(), normals.begin(), [](const D3DRMVERTEX& v) { return v.normal; }); - - glGenBuffers(1, &cache.vboPositions); - glBindBuffer(GL_ARRAY_BUFFER, cache.vboPositions); - glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(D3DVECTOR), positions.data(), GL_STATIC_DRAW); - - glGenBuffers(1, &cache.vboNormals); - glBindBuffer(GL_ARRAY_BUFFER, cache.vboNormals); - glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(D3DVECTOR), normals.data(), GL_STATIC_DRAW); - - if (meshGroup.texture) { - glGenBuffers(1, &cache.vboTexcoords); - glBindBuffer(GL_ARRAY_BUFFER, cache.vboTexcoords); - glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(TexCoord), texcoords.data(), GL_STATIC_DRAW); - } - - glGenBuffers(1, &cache.ibo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache.ibo); - glBufferData( - GL_ELEMENT_ARRAY_BUFFER, - cache.indices.size() * sizeof(cache.indices[0]), - cache.indices.data(), - GL_STATIC_DRAW - ); - - return cache; -} - struct GLES2MeshDestroyContext { OpenGLES2Renderer* renderer; Uint32 id; @@ -411,37 +448,11 @@ Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* mesh return (Uint32) (m_meshs.size() - 1); } -void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - halDesc->dcmColorModel = D3DCOLORMODEL::RGB; - halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - halDesc->dwDeviceZBufferBitDepth = DDBD_16; - const char* extensions = (const char*) glGetString(GL_EXTENSIONS); - if (extensions) { - if (strstr(extensions, "GL_OES_depth24")) { - halDesc->dwDeviceZBufferBitDepth |= DDBD_24; - } - if (strstr(extensions, "GL_OES_depth32")) { - halDesc->dwDeviceZBufferBitDepth |= DDBD_32; - } - } - helDesc->dwDeviceRenderBitDepth = DDBD_32; - halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; - halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; - halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; - - memset(helDesc, 0, sizeof(D3DDEVICEDESC)); -} - -const char* OpenGLES2Renderer::GetName() -{ - return "OpenGL ES 2.0 HAL"; -} - HRESULT OpenGLES2Renderer::BeginFrame() { m_dirty = true; + glEnable(GL_CULL_FACE); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); @@ -516,8 +527,6 @@ void OpenGLES2Renderer::SubmitDraw( glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_textures[appearance.textureId].glTextureId); glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 0); @@ -543,7 +552,6 @@ void OpenGLES2Renderer::SubmitDraw( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo); glDrawElements(GL_TRIANGLES, static_cast(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr); - glDisableVertexAttribArray(posLoc); glDisableVertexAttribArray(normLoc); glDisableVertexAttribArray(texLoc); } @@ -562,7 +570,9 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v m_width = width; m_height = height; m_viewportTransform = viewportTransform; - SDL_DestroySurface(m_renderedImage); + if (m_renderedImage) { + SDL_DestroySurface(m_renderedImage); + } m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32); glViewport(0, 0, m_width, m_height); } @@ -584,35 +594,6 @@ void OpenGLES2Renderer::Flip() } } -void CreateOrthoMatrix(float left, float right, float bottom, float top, D3DRMMATRIX4D& outMatrix) -{ - float near = -1.0f; - float far = 1.0f; - float rl = right - left; - float tb = top - bottom; - float fn = far - near; - - outMatrix[0][0] = 2.0f / rl; - outMatrix[0][1] = 0.0f; - outMatrix[0][2] = 0.0f; - outMatrix[0][3] = 0.0f; - - outMatrix[1][0] = 0.0f; - outMatrix[1][1] = 2.0f / tb; - outMatrix[1][2] = 0.0f; - outMatrix[1][3] = 0.0f; - - outMatrix[2][0] = 0.0f; - outMatrix[2][1] = 0.0f; - outMatrix[2][2] = -2.0f / fn; - outMatrix[2][3] = 0.0f; - - outMatrix[3][0] = -(right + left) / rl; - outMatrix[3][1] = -(top + bottom) / tb; - outMatrix[3][2] = -(far + near) / fn; - outMatrix[3][3] = 1.0f; -} - void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) { m_dirty = true; @@ -632,17 +613,29 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c glUniform4f(glGetUniformLocation(m_shaderProgram, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f); glUniform1f(glGetUniformLocation(m_shaderProgram, "u_shininess"), 0.0f); - float left = -m_viewportTransform.offsetX / m_viewportTransform.scale; - float right = (m_width - m_viewportTransform.offsetX) / m_viewportTransform.scale; - float top = -m_viewportTransform.offsetY / m_viewportTransform.scale; - float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale; + const GLES2TextureCacheEntry& texture = m_textures[textureId]; + float scaleX = static_cast(dstRect.w) / srcRect.w; + float scaleY = static_cast(dstRect.h) / srcRect.h; + SDL_Rect expandedDstRect = { + static_cast(std::round(dstRect.x - srcRect.x * scaleX)), + static_cast(std::round(dstRect.y - srcRect.y * scaleY)), + static_cast(std::round(texture.width * scaleX)), + static_cast(std::round(texture.height * scaleY)) + }; - D3DRMMATRIX4D projection; - CreateOrthoMatrix(left, right, bottom, top, projection); + D3DRMMATRIX4D modelView, projection; + Create2DTransformMatrix( + expandedDstRect, + m_viewportTransform.scale, + m_viewportTransform.offsetX, + m_viewportTransform.offsetY, + modelView + ); - D3DRMMATRIX4D identity = {{1.f, 0.f, 0.f, 0.f}, {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 0.f, 1.f}}; - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &identity[0][0]); + glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &modelView[0][0]); + Matrix3x3 identity = {{1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {0.f, 0.f, 1.f}}; glUniformMatrix3fv(glGetUniformLocation(m_shaderProgram, "u_normalMatrix"), 1, GL_FALSE, &identity[0][0]); + CreateOrthographicProjection((float) m_width, (float) m_height, projection); glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"), 1, GL_FALSE, &projection[0][0]); glEnable(GL_BLEND); @@ -650,42 +643,34 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c glActiveTexture(GL_TEXTURE0); glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1); - const GLES2TextureCacheEntry& texture = m_textures[textureId]; glBindTexture(GL_TEXTURE_2D, texture.glTextureId); glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - float texW = texture.width; - float texH = texture.height; - float u1 = srcRect.x / texW; - float v1 = srcRect.y / texH; - float u2 = (srcRect.x + srcRect.w) / texW; - float v2 = (srcRect.y + srcRect.h) / texH; - - float x1 = static_cast(dstRect.x); - float y1 = static_cast(dstRect.y); - float x2 = x1 + dstRect.w; - float y2 = y1 + dstRect.h; - - GLfloat vertices[] = {x1, y1, u1, v1, x2, y1, u2, v1, x1, y2, u1, v2, x2, y2, u2, v2}; + glEnable(GL_SCISSOR_TEST); + glScissor( + static_cast(std::round(dstRect.x * m_viewportTransform.scale + m_viewportTransform.offsetX)), + m_height - static_cast( + std::round((dstRect.y + dstRect.h) * m_viewportTransform.scale + m_viewportTransform.offsetY) + ), + static_cast(std::round(dstRect.w * m_viewportTransform.scale)), + static_cast(std::round(dstRect.h * m_viewportTransform.scale)) + ); GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); - GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); - + glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboPositions); glEnableVertexAttribArray(posLoc); + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + + GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); + glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboTexcoords); glEnableVertexAttribArray(texLoc); + glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); - glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), vertices); - glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), vertices + 2); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiMeshCache.ibo); + glDrawElements(GL_TRIANGLES, static_cast(m_uiMeshCache.indices.size()), GL_UNSIGNED_SHORT, nullptr); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glDisableVertexAttribArray(posLoc); glDisableVertexAttribArray(texLoc); - - glBindTexture(GL_TEXTURE_2D, 0); - glUseProgram(0); + glDisable(GL_SCISSOR_TEST); } void OpenGLES2Renderer::Download(SDL_Surface* target) diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp index 4ee5a35c..a499193c 100644 --- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp +++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp @@ -533,7 +533,7 @@ SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* return texptr; } -Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture) +Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -585,7 +585,7 @@ SDL3MeshCache Direct3DRMSDL3GPURenderer::UploadMesh(const MeshGroup& meshGroup) meshGroup.vertices.size(), meshGroup.indices.data(), meshGroup.indices.size(), - meshGroup.texture != nullptr, + true, finalVertices, newIndices ); @@ -712,24 +712,6 @@ Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGro return (Uint32) (m_meshs.size() - 1); } -void Direct3DRMSDL3GPURenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - halDesc->dcmColorModel = D3DCOLORMODEL::RGB; - halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - halDesc->dwDeviceZBufferBitDepth = DDBD_32; // Todo add support for other depths - halDesc->dwDeviceRenderBitDepth = DDBD_32; - halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; - halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; - halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; - - memset(helDesc, 0, sizeof(D3DDEVICEDESC)); -} - -const char* Direct3DRMSDL3GPURenderer::GetName() -{ - return "SDL3 GPU HAL"; -} - void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNormalMatrix4x4) { for (int row = 0; row < 3; ++row) { @@ -940,37 +922,6 @@ void Direct3DRMSDL3GPURenderer::Flip() m_cmdbuf = nullptr; } -// TODO use SDL_SetGPUScissor(SDL_GPURenderPass *render_pass, const SDL_Rect *scissor) when srcRect isn't 100% of -// texture - -void Create2DTransformMatrix( - const SDL_Rect& dstRect, - float scale, - float offsetX, - float offsetY, - D3DRMMATRIX4D& outMatrix -) -{ - float x = static_cast(dstRect.x) * scale + offsetX; - float y = static_cast(dstRect.y) * scale + offsetY; - float w = static_cast(dstRect.w) * scale; - float h = static_cast(dstRect.h) * scale; - - D3DVALUE tmp[4][4] = {{w, 0, 0, 0}, {0, h, 0, 0}, {0, 0, 1, 0}, {x, y, 0, 1}}; - memcpy(outMatrix, tmp, sizeof(tmp)); -} - -void CreateOrthographicProjection(float width, float height, D3DRMMATRIX4D& outProj) -{ - D3DVALUE tmp[4][4] = { - {2.0f / width, 0.0f, 0.0f, 0.0f}, - {0.0f, -2.0f / height, 0.0f, 0.0f}, - {0.0f, 0.0f, 1.0f, 0.0f}, - {-1.0f, 1.0f, 0.0f, 1.0f} - }; - memcpy(outProj, tmp, sizeof(tmp)); -} - void Direct3DRMSDL3GPURenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) { if (!m_renderPass) { diff --git a/miniwin/src/d3drm/backends/software/renderer.cpp b/miniwin/src/d3drm/backends/software/renderer.cpp index 64adc93b..6b969769 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) +Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -664,24 +664,6 @@ Uint32 Direct3DRMSoftwareRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGr return (Uint32) (m_meshs.size() - 1); } -void Direct3DRMSoftwareRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - memset(halDesc, 0, sizeof(D3DDEVICEDESC)); - - helDesc->dcmColorModel = D3DCOLORMODEL::RGB; - helDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - helDesc->dwDeviceZBufferBitDepth = DDBD_32; - helDesc->dwDeviceRenderBitDepth = DDBD_32; - helDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; - helDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; - helDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; -} - -const char* Direct3DRMSoftwareRenderer::GetName() -{ - return "Miniwin Emulation"; -} - HRESULT Direct3DRMSoftwareRenderer::BeginFrame() { if (!m_renderedImage || !SDL_LockSurface(m_renderedImage)) { diff --git a/miniwin/src/ddraw/ddraw.cpp b/miniwin/src/ddraw/ddraw.cpp index acf695eb..018fffd1 100644 --- a/miniwin/src/ddraw/ddraw.cpp +++ b/miniwin/src/ddraw/ddraw.cpp @@ -207,14 +207,18 @@ HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) return S_OK; } -void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMRenderer* device, GUID deviceGuid) +void EnumDevice( + LPD3DENUMDEVICESCALLBACK cb, + void* ctx, + const char* name, + D3DDEVICEDESC* halDesc, + D3DDEVICEDESC* helDesc, + GUID deviceGuid +) { - D3DDEVICEDESC halDesc = {}; - D3DDEVICEDESC helDesc = {}; - device->GetDesc(&halDesc, &helDesc); - char* deviceNameDup = SDL_strdup(device->GetName()); + char* deviceNameDup = SDL_strdup(name); char* deviceDescDup = SDL_strdup("Miniwin driver"); - cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &helDesc, ctx); + cb(&deviceGuid, deviceNameDup, deviceDescDup, halDesc, helDesc, ctx); SDL_free(deviceDescDup); SDL_free(deviceNameDup); } diff --git a/miniwin/src/ddraw/framebuffer.cpp b/miniwin/src/ddraw/framebuffer.cpp index eb21abef..9f4224fd 100644 --- a/miniwin/src/ddraw/framebuffer.cpp +++ b/miniwin/src/ddraw/framebuffer.cpp @@ -62,7 +62,7 @@ HRESULT FrameBufferImpl::Blt( if (!surface) { return DDERR_GENERIC; } - Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture()); + 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 = diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h index e76f0759..259b20eb 100644 --- a/miniwin/src/internal/d3drmrenderer.h +++ b/miniwin/src/internal/d3drmrenderer.h @@ -31,14 +31,12 @@ 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) = 0; + virtual Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi = false) = 0; virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0; int GetWidth() { return m_width; } int GetHeight() { return m_height; } int GetVirtualWidth() { return m_virtualWidth; } int GetVirtualHeight() { return m_virtualHeight; } - virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0; - virtual const char* GetName() = 0; virtual HRESULT BeginFrame() = 0; virtual void EnableTransparency() = 0; virtual void SubmitDraw( diff --git a/miniwin/src/internal/d3drmrenderer_directx9.h b/miniwin/src/internal/d3drmrenderer_directx9.h index b7badb03..900bbe03 100644 --- a/miniwin/src/internal/d3drmrenderer_directx9.h +++ b/miniwin/src/internal/d3drmrenderer_directx9.h @@ -18,10 +18,8 @@ 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) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -52,8 +50,21 @@ class DirectX9Renderer : public Direct3DRMRenderer { inline static void DirectX9Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { Direct3DRMRenderer* device = DirectX9Renderer::Create(640, 480); - if (device) { - EnumDevice(cb, ctx, device, DirectX9_GUID); - delete device; + if (!device) { + return; } + delete device; + + D3DDEVICEDESC halDesc = {}; + halDesc.dcmColorModel = D3DCOLOR_RGB; + halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + halDesc.dwDeviceZBufferBitDepth = DDBD_24; + halDesc.dwDeviceRenderBitDepth = DDBD_32; + halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + D3DDEVICEDESC helDesc = {}; + + EnumDevice(cb, ctx, "DirectX 9 HAL", &halDesc, &helDesc, DirectX9_GUID); } diff --git a/miniwin/src/internal/d3drmrenderer_opengl1.h b/miniwin/src/internal/d3drmrenderer_opengl1.h index d80621a5..58406709 100644 --- a/miniwin/src/internal/d3drmrenderer_opengl1.h +++ b/miniwin/src/internal/d3drmrenderer_opengl1.h @@ -18,10 +18,8 @@ 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) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -57,8 +55,21 @@ class OpenGL1Renderer : public Direct3DRMRenderer { inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { Direct3DRMRenderer* device = OpenGL1Renderer::Create(640, 480); - if (device) { - EnumDevice(cb, ctx, device, OpenGL1_GUID); - delete device; + if (!device) { + return; } + delete device; + + D3DDEVICEDESC halDesc = {}; + halDesc.dcmColorModel = D3DCOLORMODEL::RGB; + halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + halDesc.dwDeviceZBufferBitDepth = DDBD_24; + halDesc.dwDeviceRenderBitDepth = DDBD_32; + halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + D3DDEVICEDESC helDesc = {}; + + EnumDevice(cb, ctx, "OpenGL 1.1 HAL", &halDesc, &helDesc, OpenGL1_GUID); } diff --git a/miniwin/src/internal/d3drmrenderer_opengles2.h b/miniwin/src/internal/d3drmrenderer_opengles2.h index 7ea1ed9a..432f124e 100644 --- a/miniwin/src/internal/d3drmrenderer_opengles2.h +++ b/miniwin/src/internal/d3drmrenderer_opengles2.h @@ -39,10 +39,8 @@ 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) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -64,10 +62,12 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh); + MeshGroup m_uiMesh; + GLES2MeshCacheEntry m_uiMeshCache; std::vector m_textures; std::vector m_meshs; D3DRMMATRIX4D m_projection; - SDL_Surface* m_renderedImage; + SDL_Surface* m_renderedImage = nullptr; bool m_dirty = false; std::vector m_lights; SDL_GLContext m_context; @@ -78,8 +78,32 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480); - if (device) { - EnumDevice(cb, ctx, device, OpenGLES2_GUID); - delete device; + if (!device) { + return; } + + D3DDEVICEDESC halDesc = {}; + halDesc.dcmColorModel = D3DCOLOR_RGB; + halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + halDesc.dwDeviceZBufferBitDepth = DDBD_16; + halDesc.dwDeviceRenderBitDepth = DDBD_32; + halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + const char* extensions = (const char*) glGetString(GL_EXTENSIONS); + if (extensions) { + if (strstr(extensions, "GL_OES_depth24")) { + halDesc.dwDeviceZBufferBitDepth |= DDBD_24; + } + if (strstr(extensions, "GL_OES_depth32")) { + halDesc.dwDeviceZBufferBitDepth |= DDBD_32; + } + } + + delete device; + + D3DDEVICEDESC helDesc = {}; + + EnumDevice(cb, ctx, "OpenGL ES 2.0 HAL", &halDesc, &helDesc, OpenGLES2_GUID); } diff --git a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h index 25485b1f..02ec05d0 100644 --- a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h +++ b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h @@ -47,12 +47,10 @@ 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) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) 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; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -122,8 +120,21 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer { inline static void Direct3DRMSDL3GPU_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { Direct3DRMRenderer* device = Direct3DRMSDL3GPURenderer::Create(640, 480); - if (device) { - EnumDevice(cb, ctx, device, SDL3_GPU_GUID); - delete device; + if (!device) { + return; } + delete device; + + D3DDEVICEDESC halDesc = {}; + halDesc.dcmColorModel = D3DCOLOR_RGB; + halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + halDesc.dwDeviceZBufferBitDepth = DDBD_32; + halDesc.dwDeviceRenderBitDepth = DDBD_32; + halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + D3DDEVICEDESC helDesc = {}; + + EnumDevice(cb, ctx, "SDL3 GPU HAL", &halDesc, &helDesc, SDL3_GPU_GUID); } diff --git a/miniwin/src/internal/d3drmrenderer_software.h b/miniwin/src/internal/d3drmrenderer_software.h index 444a80a3..87715999 100644 --- a/miniwin/src/internal/d3drmrenderer_software.h +++ b/miniwin/src/internal/d3drmrenderer_software.h @@ -29,12 +29,10 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { Direct3DRMSoftwareRenderer(DWORD width, DWORD height); ~Direct3DRMSoftwareRenderer() override; void PushLights(const SceneLight* vertices, size_t count) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) 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; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -87,8 +85,16 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { inline static void Direct3DRMSoftware_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { - Direct3DRMRenderer* device = nullptr; - device = new Direct3DRMSoftwareRenderer(640, 480); - EnumDevice(cb, ctx, device, SOFTWARE_GUID); - delete device; + D3DDEVICEDESC halDesc = {}; + + D3DDEVICEDESC helDesc = {}; + helDesc.dcmColorModel = D3DCOLOR_RGB; + helDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + helDesc.dwDeviceZBufferBitDepth = DDBD_32; + helDesc.dwDeviceRenderBitDepth = DDBD_32; + helDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + helDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + helDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + EnumDevice(cb, ctx, "Miniwin Emulation", &halDesc, &helDesc, SOFTWARE_GUID); } diff --git a/miniwin/src/internal/ddraw_impl.h b/miniwin/src/internal/ddraw_impl.h index f2604946..4adfb4a5 100644 --- a/miniwin/src/internal/ddraw_impl.h +++ b/miniwin/src/internal/ddraw_impl.h @@ -56,4 +56,11 @@ HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context); HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter); -void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMRenderer* device, GUID deviceGuid); +void EnumDevice( + LPD3DENUMDEVICESCALLBACK cb, + void* ctx, + const char* name, + D3DDEVICEDESC* halDesc, + D3DDEVICEDESC* helDesc, + GUID deviceGuid +); diff --git a/miniwin/src/internal/meshutils.cpp b/miniwin/src/internal/meshutils.cpp index 818ecd87..e0ce59e6 100644 --- a/miniwin/src/internal/meshutils.cpp +++ b/miniwin/src/internal/meshutils.cpp @@ -75,3 +75,31 @@ void FlattenSurfaces( } } } + +void Create2DTransformMatrix( + const SDL_Rect& dstRect, + float scale, + float offsetX, + float offsetY, + D3DRMMATRIX4D& outMatrix +) +{ + float x = static_cast(dstRect.x) * scale + offsetX; + float y = static_cast(dstRect.y) * scale + offsetY; + float w = static_cast(dstRect.w) * scale; + float h = static_cast(dstRect.h) * scale; + + D3DVALUE tmp[4][4] = {{w, 0, 0, 0}, {0, h, 0, 0}, {0, 0, 1, 0}, {x, y, 0, 1}}; + memcpy(outMatrix, tmp, sizeof(tmp)); +} + +void CreateOrthographicProjection(float width, float height, D3DRMMATRIX4D& outProj) +{ + D3DVALUE tmp[4][4] = { + {2.0f / width, 0.0f, 0.0f, 0.0f}, + {0.0f, -2.0f / height, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f, 0.0f}, + {-1.0f, 1.0f, 0.0f, 1.0f} + }; + memcpy(outProj, tmp, sizeof(tmp)); +} diff --git a/miniwin/src/internal/meshutils.h b/miniwin/src/internal/meshutils.h index fb12a145..12c509ad 100644 --- a/miniwin/src/internal/meshutils.h +++ b/miniwin/src/internal/meshutils.h @@ -13,3 +13,13 @@ void FlattenSurfaces( std::vector& dedupedVertices, std::vector& newIndices ); + +void Create2DTransformMatrix( + const SDL_Rect& dstRect, + float scale, + float offsetX, + float offsetY, + D3DRMMATRIX4D& outMatrix +); + +void CreateOrthographicProjection(float width, float height, D3DRMMATRIX4D& outProj); From ab48ce60b0ccdedfb0053b1ad555e45e16a5a58c Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Mon, 30 Jun 2025 23:38:44 +0200 Subject: [PATCH 12/13] OpenGL ES 2.0 Only lookup shader locations once (#460) --- .../src/d3drm/backends/opengles2/renderer.cpp | 95 +++++++++++-------- .../src/internal/d3drmrenderer_opengles2.h | 12 +++ 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp index 8c39d937..55719807 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp @@ -263,6 +263,23 @@ OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext co }; m_uiMesh.indices = {0, 1, 2, 0, 2, 3}; m_uiMeshCache = GLES2UploadMesh(m_uiMesh, true); + m_posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); + m_normLoc = glGetAttribLocation(m_shaderProgram, "a_normal"); + m_texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); + m_colorLoc = glGetUniformLocation(m_shaderProgram, "u_color"); + m_shinLoc = glGetUniformLocation(m_shaderProgram, "u_shininess"); + m_lightCountLoc = glGetUniformLocation(m_shaderProgram, "u_lightCount"); + m_useTextureLoc = glGetUniformLocation(m_shaderProgram, "u_useTexture"); + m_textureLoc = glGetUniformLocation(m_shaderProgram, "u_texture"); + for (int i = 0; i < 3; ++i) { + std::string base = "u_lights[" + std::to_string(i) + "]"; + u_lightLocs[i][0] = glGetUniformLocation(m_shaderProgram, (base + ".color").c_str()); + u_lightLocs[i][1] = glGetUniformLocation(m_shaderProgram, (base + ".position").c_str()); + u_lightLocs[i][2] = glGetUniformLocation(m_shaderProgram, (base + ".direction").c_str()); + } + m_modelViewMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"); + m_normalMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_normalMatrix"); + m_projectionMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"); } OpenGLES2Renderer::~OpenGLES2Renderer() @@ -481,12 +498,11 @@ HRESULT OpenGLES2Renderer::BeginFrame() } for (int i = 0; i < lightCount; ++i) { - std::string base = "u_lights[" + std::to_string(i) + "]"; - glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".color").c_str()), 1, lightData[i].color); - glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".position").c_str()), 1, lightData[i].position); - glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".direction").c_str()), 1, lightData[i].direction); + glUniform4fv(u_lightLocs[i][0], 1, lightData[i].color); + glUniform4fv(u_lightLocs[i][1], 1, lightData[i].position); + glUniform4fv(u_lightLocs[i][2], 1, lightData[i].direction); } - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), lightCount); + glUniform1i(m_lightCountLoc, lightCount); return DD_OK; } @@ -508,52 +524,49 @@ void OpenGLES2Renderer::SubmitDraw( { auto& mesh = m_meshs[meshId]; - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &modelViewMatrix[0][0]); - glUniformMatrix3fv(glGetUniformLocation(m_shaderProgram, "u_normalMatrix"), 1, GL_FALSE, &normalMatrix[0][0]); - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"), 1, GL_FALSE, &m_projection[0][0]); + glUniformMatrix4fv(m_modelViewMatrixLoc, 1, GL_FALSE, &modelViewMatrix[0][0]); + glUniformMatrix3fv(m_normalMatrixLoc, 1, GL_FALSE, &normalMatrix[0][0]); + glUniformMatrix4fv(m_projectionMatrixLoc, 1, GL_FALSE, &m_projection[0][0]); glUniform4f( - glGetUniformLocation(m_shaderProgram, "u_color"), + m_colorLoc, appearance.color.r / 255.0f, appearance.color.g / 255.0f, appearance.color.b / 255.0f, appearance.color.a / 255.0f ); - glUniform1f(glGetUniformLocation(m_shaderProgram, "u_shininess"), appearance.shininess); + glUniform1f(m_shinLoc, appearance.shininess); if (appearance.textureId != NO_TEXTURE_ID) { - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1); + glUniform1i(m_useTextureLoc, 1); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_textures[appearance.textureId].glTextureId); - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); + glUniform1i(m_textureLoc, 0); } else { - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 0); + glUniform1i(m_useTextureLoc, 0); } glBindBuffer(GL_ARRAY_BUFFER, mesh.vboPositions); - GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); - glEnableVertexAttribArray(posLoc); - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_posLoc); + glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glBindBuffer(GL_ARRAY_BUFFER, mesh.vboNormals); - GLint normLoc = glGetAttribLocation(m_shaderProgram, "a_normal"); - glEnableVertexAttribArray(normLoc); - glVertexAttribPointer(normLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_normLoc); + glVertexAttribPointer(m_normLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); if (appearance.textureId != NO_TEXTURE_ID) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboTexcoords); - glEnableVertexAttribArray(texLoc); - glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_texLoc); + glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo); glDrawElements(GL_TRIANGLES, static_cast(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr); - glDisableVertexAttribArray(normLoc); - glDisableVertexAttribArray(texLoc); + glDisableVertexAttribArray(m_normLoc); + glDisableVertexAttribArray(m_texLoc); } HRESULT OpenGLES2Renderer::FinalizeFrame() @@ -605,13 +618,13 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c float color[] = {1.0f, 1.0f, 1.0f, 1.0f}; float blank[] = {0.0f, 0.0f, 0.0f, 0.0f}; - glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].color"), 1, color); - glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].position"), 1, blank); - glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].direction"), 1, blank); - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), 1); + glUniform4fv(u_lightLocs[0][0], 1, color); + glUniform4fv(u_lightLocs[0][1], 1, blank); + glUniform4fv(u_lightLocs[0][2], 1, blank); + glUniform1i(m_lightCountLoc, 1); - glUniform4f(glGetUniformLocation(m_shaderProgram, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1f(glGetUniformLocation(m_shaderProgram, "u_shininess"), 0.0f); + glUniform4f(m_colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1f(m_shinLoc, 0.0f); const GLES2TextureCacheEntry& texture = m_textures[textureId]; float scaleX = static_cast(dstRect.w) / srcRect.w; @@ -632,19 +645,19 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c modelView ); - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &modelView[0][0]); + glUniformMatrix4fv(m_modelViewMatrixLoc, 1, GL_FALSE, &modelView[0][0]); Matrix3x3 identity = {{1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {0.f, 0.f, 1.f}}; - glUniformMatrix3fv(glGetUniformLocation(m_shaderProgram, "u_normalMatrix"), 1, GL_FALSE, &identity[0][0]); + glUniformMatrix3fv(m_normalMatrixLoc, 1, GL_FALSE, &identity[0][0]); CreateOrthographicProjection((float) m_width, (float) m_height, projection); - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"), 1, GL_FALSE, &projection[0][0]); + glUniformMatrix4fv(m_projectionMatrixLoc, 1, GL_FALSE, &projection[0][0]); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glActiveTexture(GL_TEXTURE0); - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1); + glUniform1i(m_useTextureLoc, 1); glBindTexture(GL_TEXTURE_2D, texture.glTextureId); - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); + glUniform1i(m_textureLoc, 0); glEnable(GL_SCISSOR_TEST); glScissor( @@ -656,20 +669,18 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c static_cast(std::round(dstRect.h * m_viewportTransform.scale)) ); - GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboPositions); - glEnableVertexAttribArray(posLoc); - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_posLoc); + glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboTexcoords); - glEnableVertexAttribArray(texLoc); - glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_texLoc); + glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiMeshCache.ibo); glDrawElements(GL_TRIANGLES, static_cast(m_uiMeshCache.indices.size()), GL_UNSIGNED_SHORT, nullptr); - glDisableVertexAttribArray(texLoc); + glDisableVertexAttribArray(m_texLoc); glDisable(GL_SCISSOR_TEST); } diff --git a/miniwin/src/internal/d3drmrenderer_opengles2.h b/miniwin/src/internal/d3drmrenderer_opengles2.h index 432f124e..f5d62579 100644 --- a/miniwin/src/internal/d3drmrenderer_opengles2.h +++ b/miniwin/src/internal/d3drmrenderer_opengles2.h @@ -72,6 +72,18 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { std::vector m_lights; SDL_GLContext m_context; GLuint m_shaderProgram; + GLint m_posLoc; + GLint m_normLoc; + GLint m_texLoc; + GLint m_colorLoc; + GLint m_shinLoc; + GLint m_lightCountLoc; + GLint m_useTextureLoc; + GLint m_textureLoc; + GLint u_lightLocs[3][3]; + GLint m_modelViewMatrixLoc; + GLint m_normalMatrixLoc; + GLint m_projectionMatrixLoc; ViewportTransform m_viewportTransform; }; From e2ff65cf91fbf6142f439acea933f58f565ffd3e Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Tue, 1 Jul 2025 02:23:13 +0200 Subject: [PATCH 13/13] Expose window during device probing (#462) --- CONFIG/config.cpp | 10 +++- .../legoomni/src/video/legovideomanager.cpp | 2 +- LEGO1/mxdirectx/mxdirectxinfo.cpp | 30 ++++++---- LEGO1/mxdirectx/mxdirectxinfo.h | 3 +- .../src/d3drm/backends/opengl1/renderer.cpp | 36 ++++------- .../src/d3drm/backends/opengles2/renderer.cpp | 30 ++++------ .../src/d3drm/backends/sdl3gpu/renderer.cpp | 60 ++++--------------- 7 files changed, 63 insertions(+), 108 deletions(-) diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp index bd38e669..9030ae67 100644 --- a/CONFIG/config.cpp +++ b/CONFIG/config.cpp @@ -56,9 +56,17 @@ bool CConfigApp::InitInstance() return false; } m_device_enumerator = new LegoDeviceEnumerate; - if (m_device_enumerator->DoEnumerate()) { + SDL_Window* window = SDL_CreateWindow("Test window", 640, 480, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); + HWND hWnd; +#ifdef MINIWIN + hWnd = reinterpret_cast(window); +#else + hWnd = (HWND) SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); +#endif + if (m_device_enumerator->DoEnumerate(hWnd)) { return FALSE; } + SDL_DestroyWindow(window); m_driver = NULL; m_device = NULL; m_full_screen = TRUE; diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index a0173224..7e2f7e42 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -108,7 +108,7 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM goto done; } - if (deviceEnumerate.DoEnumerate() != SUCCESS) { + if (deviceEnumerate.DoEnumerate(hwnd) != SUCCESS) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "LegoDeviceEnumerate::DoEnumerate failed"); goto done; } diff --git a/LEGO1/mxdirectx/mxdirectxinfo.cpp b/LEGO1/mxdirectx/mxdirectxinfo.cpp index c5100031..639a2864 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.cpp +++ b/LEGO1/mxdirectx/mxdirectxinfo.cpp @@ -216,27 +216,33 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); } else { - newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); - result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); - + result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); if (result != DD_OK) { - BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); + BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result)); } else { - result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); + newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); + result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); if (result != DD_OK) { - BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); + BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); } else { - result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); + result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); if (result != DD_OK) { - BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); + BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); } else { - if (!newDevice.m_devices.size()) { - m_list.pop_back(); + result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); + + if (result != DD_OK) { + BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); + } + else { + if (!newDevice.m_devices.size()) { + m_list.pop_back(); + } } } } @@ -306,12 +312,14 @@ HRESULT MxDeviceEnumerate::EnumDevicesCallback( // FUNCTION: CONFIG 0x00401dc0 // FUNCTION: LEGO1 0x1009c6c0 // FUNCTION: BETA10 0x1011e3fa -int MxDeviceEnumerate::DoEnumerate() +int MxDeviceEnumerate::DoEnumerate(HWND hWnd) { if (IsInitialized()) { return -1; } + m_hWnd = hWnd; + HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this); if (ret != DD_OK) { BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret)); diff --git a/LEGO1/mxdirectx/mxdirectxinfo.h b/LEGO1/mxdirectx/mxdirectxinfo.h index a4ebef91..9bc480de 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.h +++ b/LEGO1/mxdirectx/mxdirectxinfo.h @@ -194,7 +194,7 @@ class MxDeviceEnumerate { MxDeviceEnumerate(); ~MxDeviceEnumerate(); - virtual int DoEnumerate(); // vtable+0x00 + virtual int DoEnumerate(HWND hWnd); // vtable+0x00 BOOL EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); HRESULT EnumDevicesCallback( @@ -242,6 +242,7 @@ class MxDeviceEnumerate { protected: list m_list; // 0x04 unsigned char m_initialized; // 0x10 + HWND m_hWnd; }; // TEMPLATE: BETA10 0x1011c1b0 diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index 66f08d23..fb7fccd4 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -28,40 +28,25 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); - SDL_Window* window = DDWindow; - bool testWindow = false; - if (!window) { - window = SDL_CreateWindow("OpenGL 1.1 test", width, height, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); - if (!window) { - SDL_Log("SDL_CreateWindow: %s", SDL_GetError()); - return nullptr; - } - testWindow = true; - } - - SDL_GLContext context = SDL_GL_CreateContext(window); - if (!context) { - SDL_Log("SDL_GL_CreateContext: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } + if (!DDWindow) { + SDL_Log("No window handler"); return nullptr; } - if (!SDL_GL_MakeCurrent(window, context)) { + SDL_GLContext context = SDL_GL_CreateContext(DDWindow); + if (!context) { + SDL_Log("SDL_GL_CreateContext: %s", SDL_GetError()); + return nullptr; + } + + if (!SDL_GL_MakeCurrent(DDWindow, context)) { + SDL_GL_DestroyContext(context); SDL_Log("SDL_GL_MakeCurrent: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } GL11_InitState(); - if (testWindow) { - SDL_DestroyWindow(window); - } - return new OpenGL1Renderer(width, height, context); } @@ -78,6 +63,7 @@ OpenGL1Renderer::OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext contex OpenGL1Renderer::~OpenGL1Renderer() { SDL_DestroySurface(m_renderedImage); + SDL_GL_DestroyContext(m_context); } void OpenGL1Renderer::PushLights(const SceneLight* lightsArray, size_t count) diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp index 55719807..d3594298 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp @@ -40,25 +40,18 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_Window* window = DDWindow; - bool testWindow = false; - if (!window) { - window = SDL_CreateWindow("OpenGL ES 2.0 test", width, height, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); - testWindow = true; - } - - SDL_GLContext context = SDL_GL_CreateContext(window); - if (!context) { - if (testWindow) { - SDL_DestroyWindow(window); - } + if (!DDWindow) { + SDL_Log("No window handler"); return nullptr; } - if (!SDL_GL_MakeCurrent(window, context)) { - if (testWindow) { - SDL_DestroyWindow(window); - } + SDL_GLContext context = SDL_GL_CreateContext(DDWindow); + if (!context) { + return nullptr; + } + + if (!SDL_GL_MakeCurrent(DDWindow, context)) { + SDL_GL_DestroyContext(context); return nullptr; } @@ -174,10 +167,6 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) glDeleteShader(vs); glDeleteShader(fs); - if (testWindow) { - SDL_DestroyWindow(window); - } - return new OpenGLES2Renderer(width, height, context, shaderProgram); } @@ -285,6 +274,7 @@ OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext co OpenGLES2Renderer::~OpenGLES2Renderer() { SDL_DestroySurface(m_renderedImage); + SDL_GL_DestroyContext(m_context); glDeleteProgram(m_shaderProgram); } diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp index a499193c..98704c66 100644 --- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp +++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp @@ -203,49 +203,31 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) return nullptr; } - SDL_Window* window = DDWindow; - bool testWindow = false; - if (!window) { - window = SDL_CreateWindow("SDL_GPU test", width, height, SDL_WINDOW_HIDDEN); - if (!window) { - SDL_Log("SDL_CreateWindow: %s", SDL_GetError()); - return nullptr; - } - testWindow = true; - } - - if (!SDL_ClaimWindowForGPUDevice(device.ptr, window)) { - SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ClaimWindowForGPUDevice: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } + if (!DDWindow) { + SDL_Log("No window handler"); return nullptr; } - ScopedPipeline opaquePipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, true, true)}; + if (!SDL_ClaimWindowForGPUDevice(device.ptr, DDWindow)) { + SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ClaimWindowForGPUDevice: %s", SDL_GetError()); + return nullptr; + } + + ScopedPipeline opaquePipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, DDWindow, true, true)}; if (!opaquePipeline.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for opaquePipeline"); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } - ScopedPipeline transparentPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, true, false)}; + ScopedPipeline transparentPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, DDWindow, true, false)}; if (!transparentPipeline.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for transparentPipeline"); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } - ScopedPipeline uiPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, false, false)}; + ScopedPipeline uiPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, DDWindow, false, false)}; if (!uiPipeline.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for uiPipeline"); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } @@ -257,9 +239,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) ScopedTransferBuffer uploadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &uploadBufferInfo)}; if (!uploadBuffer.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTransferBuffer filed for upload buffer (%s)", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } @@ -273,9 +252,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) ScopedSampler sampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &samplerInfo)}; if (!sampler.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } @@ -289,17 +265,9 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) ScopedSampler uiSampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &uiSamplerInfo)}; if (!uiSampler.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } - if (testWindow) { - SDL_ReleaseWindowFromGPUDevice(device.ptr, window); - SDL_DestroyWindow(window); - } - auto renderer = new Direct3DRMSDL3GPURenderer( width, height, @@ -383,9 +351,7 @@ Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer() { SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.vertexBuffer); SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.indexBuffer); - if (DDWindow) { - SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow); - } + SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow); if (m_downloadBuffer) { SDL_ReleaseGPUTransferBuffer(m_device, m_downloadBuffer); } @@ -839,10 +805,6 @@ void Direct3DRMSDL3GPURenderer::Resize(int width, int height, const ViewportTran m_height = height; m_viewportTransform = viewportTransform; - if (!DDWindow) { - return; - } - if (m_transferTexture) { SDL_ReleaseGPUTexture(m_device, m_transferTexture); }