diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
new file mode 100644
index 00000000..ca316590
--- /dev/null
+++ b/.github/workflows/docker.yml
@@ -0,0 +1,55 @@
+name: Docker
+
+on:
+ push:
+ branches: ['master']
+
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: ${{ github.repository }}-emscripten
+
+jobs:
+ publish-emscripten:
+ name: Publish web port
+ env:
+ IMAGE_NAME: ${{ github.repository }}-emscripten
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ attestations: write
+ id-token: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+
+ - name: Build and push Docker image
+ id: push
+ uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
+ with:
+ file: docker/emscripten/Dockerfile
+ context: .
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+
+ - name: Generate artifact attestation
+ uses: actions/attest-build-provenance@v2
+ with:
+ subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
+ subject-digest: ${{ steps.push.outputs.digest }}
+ push-to-registry: true
diff --git a/cmake/Findiniparser.cmake b/CMake/Findiniparser.cmake
similarity index 100%
rename from cmake/Findiniparser.cmake
rename to CMake/Findiniparser.cmake
diff --git a/cmake/detectcpu.cmake b/CMake/detectcpu.cmake
similarity index 100%
rename from cmake/detectcpu.cmake
rename to CMake/detectcpu.cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a2d9494a..271fa67a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ endif()
if(EMSCRIPTEN)
add_compile_options(-pthread)
- add_link_options(-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2gb -sUSE_PTHREADS=1 -sPROXY_TO_PTHREAD=1 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1)
+ add_link_options(-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2gb -sUSE_PTHREADS=1 -sPROXY_TO_PTHREAD=1 -sOFFSCREENCANVAS_SUPPORT=1 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1)
set(SDL_PTHREADS ON CACHE BOOL "Enable SDL pthreads" FORCE)
endif()
@@ -17,7 +17,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
include(CheckCXXSourceCompiles)
include(CMakeDependentOption)
include(CMakePushCheckState)
-include(cmake/detectcpu.cmake)
+include(CMake/detectcpu.cmake)
DetectTargetCPUArchitectures(ISLE_CPUS)
diff --git a/CONFIG/res/maindialog.ui b/CONFIG/res/maindialog.ui
index c2760e7c..c2d429ae 100644
--- a/CONFIG/res/maindialog.ui
+++ b/CONFIG/res/maindialog.ui
@@ -562,8 +562,10 @@
sound3DCheckBox
musicCheckBox
joystickCheckBox
+ fullscreenCheckBox
devicesList
okButton
+ launchButton
cancelButton
diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h
index dc81160c..38e2876e 100644
--- a/LEGO1/lego/legoomni/include/act3.h
+++ b/LEGO1/lego/legoomni/include/act3.h
@@ -129,7 +129,7 @@ class Act3 : public LegoWorld {
void RemoveDonut(Act3Ammo& p_p);
MxResult ShootPizza(LegoPathController* p_controller, Vector3& p_location, Vector3& p_direction, Vector3& p_up);
MxResult ShootDonut(LegoPathController* p_controller, Vector3& p_location, Vector3& p_direction, Vector3& p_up);
- void FUN_10072ad0(undefined4 p_param1);
+ void TriggerHitSound(undefined4 p_param1);
MxResult FUN_10073360(Act3Ammo& p_ammo, const Vector3& p_param2);
MxResult FUN_10073390(Act3Ammo& p_ammo, const Vector3& p_param2);
void SetBrickster(Act3Brickster* p_brickster);
@@ -168,12 +168,12 @@ class Act3 : public LegoWorld {
Helicopter* m_copter; // 0x420c
Act3Shark* m_shark; // 0x4210
MxFloat m_time; // 0x4214
- MxU8 m_unk0x4218; // 0x4218
- MxU8 m_unk0x4219; // 0x4219
- MxU8 m_unk0x421a; // 0x421a
- MxU8 m_unk0x421b; // 0x421b
- MxU8 m_unk0x421c; // 0x421c
- MxU8 m_unk0x421d; // 0x421d
+ MxU8 m_pizzaHitSound; // 0x4218
+ MxU8 m_pizzaMissSound; // 0x4219
+ MxU8 m_copDonutSound; // 0x421a
+ MxU8 m_donutMissSound; // 0x421b
+ MxU8 m_islanderSound; // 0x421c
+ MxU8 m_bricksterDonutSound; // 0x421d
undefined m_unk0x421e; // 0x421e
Act3List m_unk0x4220; // 0x4220
MxPresenter* m_helicopterDots[15]; // 0x4230
diff --git a/LEGO1/lego/legoomni/src/actors/act3actors.cpp b/LEGO1/lego/legoomni/src/actors/act3actors.cpp
index e7706b03..89bdc5fc 100644
--- a/LEGO1/lego/legoomni/src/actors/act3actors.cpp
+++ b/LEGO1/lego/legoomni/src/actors/act3actors.cpp
@@ -580,7 +580,7 @@ void Act3Brickster::Animate(float p_time)
}
if (m_unk0x54 < p_time) {
- ((Act3*) m_world)->FUN_10072ad0(5);
+ ((Act3*) m_world)->TriggerHitSound(5);
m_unk0x54 = p_time + 15000.0f;
}
@@ -596,7 +596,7 @@ void Act3Brickster::Animate(float p_time)
assert(SoundManager()->GetCacheSoundManager());
if (m_unk0x58 >= 8) {
- ((Act3*) m_world)->FUN_10072ad0(6);
+ ((Act3*) m_world)->TriggerHitSound(6);
}
else {
SoundManager()->GetCacheSoundManager()->Play("eatpz", NULL, FALSE);
diff --git a/LEGO1/lego/legoomni/src/actors/act3ammo.cpp b/LEGO1/lego/legoomni/src/actors/act3ammo.cpp
index 04e0e93c..d88a7bee 100644
--- a/LEGO1/lego/legoomni/src/actors/act3ammo.cpp
+++ b/LEGO1/lego/legoomni/src/actors/act3ammo.cpp
@@ -378,11 +378,11 @@ void Act3Ammo::Animate(float p_time)
if (IsBit4()) {
if (IsPizza()) {
m_world->RemovePizza(*this);
- m_world->FUN_10072ad0(2);
+ m_world->TriggerHitSound(2);
}
else {
m_world->RemoveDonut(*this);
- m_world->FUN_10072ad0(4);
+ m_world->TriggerHitSound(4);
}
}
else {
diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp
index 9d3f3c7d..0946a0ab 100644
--- a/LEGO1/lego/legoomni/src/common/legoutils.cpp
+++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp
@@ -511,7 +511,7 @@ MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id)
}
else {
if (((MxPresenter*) object)->GetAction()) {
- FUN_100b7220(((MxPresenter*) object)->GetAction(), MxDSAction::c_world, FALSE);
+ ApplyMask(((MxPresenter*) object)->GetAction(), MxDSAction::c_world, FALSE);
}
((MxPresenter*) object)->EndAction();
@@ -540,7 +540,7 @@ MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_wor
}
else {
if (((MxPresenter*) object)->GetAction()) {
- FUN_100b7220(((MxPresenter*) object)->GetAction(), MxDSAction::c_world, FALSE);
+ ApplyMask(((MxPresenter*) object)->GetAction(), MxDSAction::c_world, FALSE);
}
((MxPresenter*) object)->EndAction();
diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
index 5c533adf..4a026cd3 100644
--- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
@@ -46,7 +46,7 @@ MxResult MxControlPresenter::StartAction(MxStreamController* p_controller, MxDSA
{
MxResult result = MxCompositePresenter::StartAction(p_controller, p_action);
- FUN_100b7220(m_action, MxDSAction::c_world | MxDSAction::c_looping, TRUE);
+ ApplyMask(m_action, MxDSAction::c_world | MxDSAction::c_looping, TRUE);
ParseExtra();
MxS16 i = 0;
diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp
index 90f56d10..7a964a3f 100644
--- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp
+++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp
@@ -122,12 +122,12 @@ void LegoWorld::Destroy(MxBool p_fromDestructor)
animPresenter->DecrementUnknown0xd4();
if (animPresenter->GetUnknown0xd4() == 0) {
- FUN_100b7220(action, MxDSAction::c_world, FALSE);
+ ApplyMask(action, MxDSAction::c_world, FALSE);
presenter->EndAction();
}
}
else {
- FUN_100b7220(action, MxDSAction::c_world, FALSE);
+ ApplyMask(action, MxDSAction::c_world, FALSE);
presenter->EndAction();
}
}
@@ -143,7 +143,7 @@ void LegoWorld::Destroy(MxBool p_fromDestructor)
MxDSAction* action = presenter->GetAction();
if (action) {
- FUN_100b7220(action, MxDSAction::c_world, FALSE);
+ ApplyMask(action, MxDSAction::c_world, FALSE);
presenter->EndAction();
}
}
@@ -159,7 +159,7 @@ void LegoWorld::Destroy(MxBool p_fromDestructor)
MxDSAction* action = presenter->GetAction();
if (action) {
- FUN_100b7220(action, MxDSAction::c_world, FALSE);
+ ApplyMask(action, MxDSAction::c_world, FALSE);
presenter->EndAction();
}
}
diff --git a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp
index 23b8f44a..4849e747 100644
--- a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp
@@ -189,7 +189,7 @@ MxResult LegoPartPresenter::Read(MxDSChunk& p_chunk)
}
if (j == 0) {
- if (surplusLODs != 0 && lod->GetUnknown0x08Test8()) {
+ if (surplusLODs != 0 && lod->IsExtraLOD()) {
numLODs++;
surplusLODs--;
}
diff --git a/LEGO1/lego/legoomni/src/worlds/act3.cpp b/LEGO1/lego/legoomni/src/worlds/act3.cpp
index 0166c9d7..344584a6 100644
--- a/LEGO1/lego/legoomni/src/worlds/act3.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/act3.cpp
@@ -32,7 +32,7 @@ DECOMP_SIZE_ASSERT(Act3ListElement, 0x0c)
DECOMP_SIZE_ASSERT(Act3List, 0x10)
// GLOBAL: LEGO1 0x100d94f8
-Act3Script::Script g_unk0x100d94f8[] = {
+Act3Script::Script g_pizzaHitSounds[] = {
Act3Script::c_sns02xni_PlayWav,
Act3Script::c_sns03xni_PlayWav,
Act3Script::c_sns04xni_PlayWav,
@@ -52,7 +52,7 @@ Act3Script::Script g_unk0x100d94f8[] = {
};
// GLOBAL: LEGO1 0x100d9538
-Act3Script::Script g_unk0x100d9538[] = {
+Act3Script::Script g_pizzaMissSounds[] = {
Act3Script::c_sns19xni_PlayWav,
Act3Script::c_sns20xni_PlayWav,
Act3Script::c_sns22xni_PlayWav,
@@ -62,7 +62,7 @@ Act3Script::Script g_unk0x100d9538[] = {
};
// GLOBAL: LEGO1 0x100d9550
-Act3Script::Script g_unk0x100d9550[] = {
+Act3Script::Script g_copDonutSounds[] = {
Act3Script::c_sns25xni_PlayWav,
Act3Script::c_sns26xni_PlayWav,
Act3Script::c_sns27xni_PlayWav,
@@ -74,7 +74,7 @@ Act3Script::Script g_unk0x100d9550[] = {
};
// GLOBAL: LEGO1 0x100d9570
-Act3Script::Script g_unk0x100d9570[] = {
+Act3Script::Script g_donutMissSounds[] = {
Act3Script::c_sns30xni_PlayWav,
Act3Script::c_sns31xni_PlayWav,
Act3Script::c_sns32xni_PlayWav,
@@ -84,7 +84,7 @@ Act3Script::Script g_unk0x100d9570[] = {
};
// GLOBAL: LEGO1 0x100d9588
-Act3Script::Script g_unk0x100d9588[] = {
+Act3Script::Script g_islanderSounds[] = {
Act3Script::c_sns43xma_PlayWav, Act3Script::c_sns46xin_PlayWav, Act3Script::c_sns60xna_PlayWav,
Act3Script::c_sns52xro_PlayWav, Act3Script::c_sns58xna_PlayWav, Act3Script::c_sns68xbu_PlayWav,
Act3Script::c_sns59xna_PlayWav, Act3Script::c_sns51xin_PlayWav, Act3Script::c_sns61xva_PlayWav,
@@ -95,7 +95,7 @@ Act3Script::Script g_unk0x100d9588[] = {
};
// GLOBAL: LEGO1 0x100d95d8
-Act3Script::Script g_unk0x100d95d8[] = {
+Act3Script::Script g_bricksterDonutSounds[] = {
Act3Script::c_tns080br_PlayWav,
Act3Script::c_tnsx07br_PlayWav,
Act3Script::c_snsxx2br_PlayWav,
@@ -404,58 +404,58 @@ MxResult Act3::ShootDonut(LegoPathController* p_controller, Vector3& p_location,
// FUNCTION: LEGO1 0x10072ad0
// FUNCTION: BETA10 0x10015eec
-void Act3::FUN_10072ad0(undefined4 p_param1)
+void Act3::TriggerHitSound(undefined4 p_param1)
{
float time = Timer()->GetTime();
Act3Script::Script objectId;
switch (p_param1) {
case 1: {
- if (m_unk0x4218 >= sizeOfArray(g_unk0x100d94f8)) {
- m_unk0x4218 = 0;
+ if (m_pizzaHitSound >= sizeOfArray(g_pizzaHitSounds)) {
+ m_pizzaHitSound = 0;
}
- objectId = g_unk0x100d94f8[m_unk0x4218++];
+ objectId = g_pizzaHitSounds[m_pizzaHitSound++];
break;
}
case 2: {
- if (m_unk0x4219 >= sizeOfArray(g_unk0x100d9538) - 1) {
- m_unk0x4219 = 0;
+ if (m_pizzaMissSound >= sizeOfArray(g_pizzaMissSounds) - 1) {
+ m_pizzaMissSound = 0;
}
- objectId = g_unk0x100d9538[m_unk0x4219++];
+ objectId = g_pizzaMissSounds[m_pizzaMissSound++];
break;
}
case 3: {
- if (m_unk0x421a >= sizeOfArray(g_unk0x100d9550)) {
- m_unk0x421a = 0;
+ if (m_copDonutSound >= sizeOfArray(g_copDonutSounds)) {
+ m_copDonutSound = 0;
}
- objectId = g_unk0x100d9550[m_unk0x421a++];
+ objectId = g_copDonutSounds[m_copDonutSound++];
break;
}
case 4: {
- if (m_unk0x421b >= sizeOfArray(g_unk0x100d9570)) {
- m_unk0x421b = 0;
+ if (m_donutMissSound >= sizeOfArray(g_donutMissSounds)) {
+ m_donutMissSound = 0;
}
- objectId = g_unk0x100d9570[m_unk0x421b++];
+ objectId = g_donutMissSounds[m_donutMissSound++];
break;
}
case 5: {
- if (m_unk0x421c >= sizeOfArray(g_unk0x100d9588)) {
- m_unk0x421c = 0;
+ if (m_islanderSound >= sizeOfArray(g_islanderSounds)) {
+ m_islanderSound = 0;
}
- objectId = g_unk0x100d9588[m_unk0x421c++];
+ objectId = g_islanderSounds[m_islanderSound++];
break;
}
case 6: {
- if (m_unk0x421d >= sizeOfArray(g_unk0x100d95d8)) {
- m_unk0x421d = 0;
+ if (m_bricksterDonutSound >= sizeOfArray(g_bricksterDonutSounds)) {
+ m_bricksterDonutSound = 0;
}
- m_unk0x4220.Insert(g_unk0x100d95d8[m_unk0x421d++], 1);
+ m_unk0x4220.Insert(g_bricksterDonutSounds[m_bricksterDonutSound++], 1);
return;
}
default:
@@ -576,13 +576,12 @@ MxLong Act3::Notify(MxParam& p_param)
m_cop2->VTable0xa8();
m_brickster->VTable0xa8();
-
- m_unk0x4218 = 0;
- m_unk0x4219 = 0;
- m_unk0x421a = 0;
- m_unk0x421b = 0;
- m_unk0x421c = 0;
- m_unk0x421d = 0;
+ m_pizzaHitSound = 0;
+ m_pizzaMissSound = 0;
+ m_copDonutSound = 0;
+ m_donutMissSound = 0;
+ m_islanderSound = 0;
+ m_bricksterDonutSound = 0;
MxS32 length;
LegoBuildingInfo* info = BuildingManager()->GetInfoArray(length);
@@ -702,7 +701,7 @@ MxResult Act3::FUN_10073360(Act3Ammo& p_ammo, const Vector3& p_param2)
{
assert(m_brickster);
m_brickster->FUN_100417a0(p_ammo, p_param2);
- FUN_10072ad0(1);
+ TriggerHitSound(1);
return SUCCESS;
}
@@ -719,7 +718,7 @@ MxResult Act3::FUN_10073390(Act3Ammo& p_ammo, const Vector3& p_param2)
m_cop2->FUN_10040350(p_ammo, p_param2);
}
- FUN_10072ad0(3);
+ TriggerHitSound(3);
g_unk0x100f7814++;
return SUCCESS;
}
diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp
index c007dc96..1fe7710b 100644
--- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp
@@ -1457,7 +1457,7 @@ void Infocenter::StartCredits()
MxDSAction* action = presenter->GetAction();
if (action) {
- FUN_100b7220(action, MxDSAction::c_world, FALSE);
+ ApplyMask(action, MxDSAction::c_world, FALSE);
presenter->EndAction();
}
}
@@ -1473,7 +1473,7 @@ void Infocenter::StartCredits()
MxDSAction* action = presenter->GetAction();
if (action) {
- FUN_100b7220(action, MxDSAction::c_world, FALSE);
+ ApplyMask(action, MxDSAction::c_world, FALSE);
presenter->EndAction();
}
}
diff --git a/LEGO1/lego/sources/roi/legolod.cpp b/LEGO1/lego/sources/roi/legolod.cpp
index 94eef6ff..866c9ef4 100644
--- a/LEGO1/lego/sources/roi/legolod.cpp
+++ b/LEGO1/lego/sources/roi/legolod.cpp
@@ -71,11 +71,11 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
LegoU32 i, indexBackwards, indexForwards, tempNumVertsAndNormals;
unsigned char paletteEntries[256];
- if (p_storage->Read(&m_unk0x08, sizeof(undefined4)) != SUCCESS) {
+ if (p_storage->Read(&m_flags, sizeof(LegoU32)) != SUCCESS) {
goto done;
}
- if (GetUnknown0x08Test4()) {
+ if (SkipReadingData()) {
return SUCCESS;
}
@@ -86,11 +86,11 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
}
if (m_numMeshes == 0) {
- ClearFlag(c_bit4);
+ ClearFlag(c_hasMesh);
return SUCCESS;
}
- SetFlag(c_bit4);
+ SetFlag(c_hasMesh);
m_melems = new Mesh[m_numMeshes];
memset(m_melems, 0, sizeof(*m_melems) * m_numMeshes);
@@ -317,7 +317,7 @@ LegoLOD* LegoLOD::Clone(Tgl::Renderer* p_renderer)
dupLod->m_melems[i].m_textured = m_melems[i].m_textured;
}
- dupLod->m_unk0x08 = m_unk0x08;
+ dupLod->m_flags = m_flags;
dupLod->m_numMeshes = m_numMeshes;
dupLod->m_numVertices = m_numVertices;
dupLod->m_numPolys = m_numPolys;
diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp
index 81d8c3d0..aeda3659 100644
--- a/LEGO1/lego/sources/roi/legoroi.cpp
+++ b/LEGO1/lego/sources/roi/legoroi.cpp
@@ -260,7 +260,7 @@ LegoResult LegoROI::Read(
}
if (j == 0) {
- if (surplusLODs != 0 && lod->GetUnknown0x08Test8()) {
+ if (surplusLODs != 0 && lod->IsExtraLOD()) {
numLODs++;
}
}
@@ -277,7 +277,7 @@ LegoResult LegoROI::Read(
}
if (i == 0) {
- if (surplusLODs != 0 && lod->GetUnknown0x08Test8()) {
+ if (surplusLODs != 0 && lod->IsExtraLOD()) {
numLODs++;
}
}
diff --git a/LEGO1/omni/include/mxutilities.h b/LEGO1/omni/include/mxutilities.h
index c68d4201..c5237bb0 100644
--- a/LEGO1/omni/include/mxutilities.h
+++ b/LEGO1/omni/include/mxutilities.h
@@ -92,7 +92,7 @@ void MakeSourceName(char*, const char*);
void OmniError(const char* p_message, MxS32 p_status);
void SetOmniUserMessage(void (*p_omniUserMessage)(const char*, MxS32));
MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter);
-void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags);
+void ApplyMask(MxDSAction* p_action, MxU32 p_mask, MxBool p_setFlags);
MxBool KeyValueStringParse(char*, const char*, const char*);
// TEMPLATE: BETA10 0x1012dfd0
diff --git a/LEGO1/omni/src/common/mxutilities.cpp b/LEGO1/omni/src/common/mxutilities.cpp
index c17e41e5..5d7528fa 100644
--- a/LEGO1/omni/src/common/mxutilities.cpp
+++ b/LEGO1/omni/src/common/mxutilities.cpp
@@ -153,16 +153,16 @@ void SetOmniUserMessage(void (*p_omniUserMessage)(const char*, MxS32))
// FUNCTION: LEGO1 0x100b7220
// FUNCTION: BETA10 0x10136f37
-void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags)
+void ApplyMask(MxDSAction* p_action, MxU32 p_mask, MxBool p_setFlags)
{
MxU32 oldFlags = p_action->GetFlags();
MxU32 newFlags;
if (p_setFlags) {
- newFlags = oldFlags | p_newFlags;
+ newFlags = oldFlags | p_mask;
}
else {
- newFlags = oldFlags & ~p_newFlags;
+ newFlags = oldFlags & ~p_mask;
}
p_action->SetFlags(newFlags);
@@ -172,7 +172,7 @@ void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags)
MxDSAction* action;
while (cursor.Next(action)) {
- FUN_100b7220(action, p_newFlags, p_setFlags);
+ ApplyMask(action, p_mask, p_setFlags);
}
}
}
diff --git a/LEGO1/viewmanager/viewlod.h b/LEGO1/viewmanager/viewlod.h
index 7bf68b52..b7104526 100644
--- a/LEGO1/viewmanager/viewlod.h
+++ b/LEGO1/viewmanager/viewlod.h
@@ -14,10 +14,10 @@
class ViewLOD : public LODObject {
public:
enum {
- c_bit4 = 0x10
+ c_hasMesh = 0x10
};
- ViewLOD(Tgl::Renderer* pRenderer) : m_meshBuilder(NULL), m_unk0x08(3) {}
+ ViewLOD(Tgl::Renderer* pRenderer) : m_meshBuilder(NULL), m_flags(3) {}
~ViewLOD() override;
// FUNCTION: LEGO1 0x100a6f30
@@ -28,19 +28,19 @@ class ViewLOD : public LODObject {
Tgl::MeshBuilder* GetMeshBuilder() { return m_meshBuilder; }
const Tgl::MeshBuilder* GetMeshBuilder() const { return m_meshBuilder; }
- undefined4 GetUnknown0x08() { return m_unk0x08; }
- unsigned char GetUnknown0x08Test4() { return m_unk0x08 & 0xffffff04; }
- unsigned char GetUnknown0x08Test8() { return m_unk0x08 & 0xffffff08; }
+ unsigned int GetFlags() { return m_flags; }
+ unsigned char SkipReadingData() { return m_flags & 0xffffff04; }
+ unsigned char IsExtraLOD() { return m_flags & 0xffffff08; }
- void SetFlag(unsigned char p_flag) { m_unk0x08 |= p_flag; }
- void ClearFlag(unsigned char p_flag) { m_unk0x08 &= ~p_flag; }
+ void SetFlag(unsigned char p_flag) { m_flags |= p_flag; }
+ void ClearFlag(unsigned char p_flag) { m_flags &= ~p_flag; }
// SYNTHETIC: LEGO1 0x100a6f60
// ViewLOD::`scalar deleting destructor'
protected:
Tgl::MeshBuilder* m_meshBuilder; // 0x04
- undefined4 m_unk0x08; // 0x08
+ unsigned int m_flags; // 0x08
};
#endif // VIEWLOD_H
diff --git a/LEGO1/viewmanager/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp
index 9ec2da58..fd0d4a84 100644
--- a/LEGO1/viewmanager/viewmanager.cpp
+++ b/LEGO1/viewmanager/viewmanager.cpp
@@ -165,7 +165,7 @@ void ViewManager::UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_lodLevel)
if (lodLevel < 0) {
lod = (ViewLOD*) p_roi->GetLOD(p_lodLevel);
- if (lod->GetUnknown0x08() & ViewLOD::c_bit4) {
+ if (lod->GetFlags() & ViewLOD::c_hasMesh) {
scene->Add(group);
SetAppData(p_roi, reinterpret_cast(p_roi));
}
@@ -184,7 +184,7 @@ void ViewManager::UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_lodLevel)
lod = (ViewLOD*) p_roi->GetLOD(p_lodLevel);
}
- if (lod->GetUnknown0x08() & ViewLOD::c_bit4) {
+ if (lod->GetFlags() & ViewLOD::c_hasMesh) {
meshBuilder = lod->GetMeshBuilder();
if (meshBuilder != NULL) {
@@ -389,7 +389,7 @@ inline int ViewManager::GetFirstLODIndex(ViewROI* p_roi)
const LODListBase* lods = p_roi->GetLODs();
if (lods != NULL && lods->Size() > 0) {
- if (((ViewLOD*) p_roi->GetLOD(0))->GetUnknown0x08Test8()) {
+ if (((ViewLOD*) p_roi->GetLOD(0))->IsExtraLOD()) {
return 1;
}
else {
@@ -404,7 +404,7 @@ inline int ViewManager::GetFirstLODIndex(ViewROI* p_roi)
const LODListBase* lods = ((ViewROI*) *it)->GetLODs();
if (lods != NULL && lods->Size() > 0) {
- if (((ViewLOD*) ((ViewROI*) *it)->GetLOD(0))->GetUnknown0x08Test8()) {
+ if (((ViewLOD*) ((ViewROI*) *it)->GetLOD(0))->IsExtraLOD()) {
return 1;
}
else {
diff --git a/README.md b/README.md
index dd7a9d46..7fa015cc 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,6 @@ Please note: this project is dedicated to achieving platform independence withou
## Status
-### Supported platforms
-
| Platform | Status |
| - | - |
| Windows | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
@@ -20,7 +18,16 @@ Please note: this project is dedicated to achieving platform independence withou
We are actively working to support more platforms. If you have experience with a particular platform, we encourage you to contribute to `isle-portable`. You can find a [list of ongoing efforts](https://github.com/isledecomp/isle-portable/wiki/Work%E2%80%90in%E2%80%90progress-ports) in our Wiki.
-### Library substitutions
+
+## Usage
+
+**An existing copy of LEGO Island is required to use this project.**
+
+As it stands, builds provided in the [Releases tab](https://github.com/isledecomp/isle-portable/releases/tag/continuous) are mainly for developers; as such, they may not work properly for all end-users. Work is currently ongoing to create workable release builds ready for gameplay and general use by end-users. If you are technically inclined, you may find it easiest to compile the project yourself to get it running at this current point in time.
+
+[Installation instructions](https://github.com/isledecomp/isle-portable/wiki/Installation) for some ports can be found in our Wiki.
+
+## Library substitutions
To achieve our goal of platform independence, we need to replace any Windows-only libraries with platform-independent alternatives. This ensures that our codebase remains versatile and compatible across various systems. The following table serves as an overview of major libraries / subsystems and their chosen replacements. For any significant changes or additions, it's recommended to discuss them with the team on the Matrix chat first to ensure consistency and alignment with our project's objectives.
@@ -43,12 +50,6 @@ To achieve our goal of platform independence, we need to replace any Windows-onl
This project uses the [CMake](https://cmake.org/) build system, which allows for a high degree of versatility regarding compilers and development environments. Please refer to the [GitHub action](/.github/workflows//ci.yml) for guidance.
-## Usage
-
-**An existing copy of LEGO Island is required to use this project.**
-
-As it stands, the builds provided in the Releases tab are for developers; as such, they may not work properly for end-users. Work is currently ongoing to create workable release builds ready for gameplay and general use by end-users. If you are technically inclined, you may find it easiest to compile the project yourself to get it running at this current point in time.
-
## Contributing
If you're interested in helping or contributing to this project, check out the [CONTRIBUTING](/CONTRIBUTING.md) page.
diff --git a/docker/emscripten/Dockerfile b/docker/emscripten/Dockerfile
new file mode 100644
index 00000000..d15d2406
--- /dev/null
+++ b/docker/emscripten/Dockerfile
@@ -0,0 +1,37 @@
+FROM emscripten/emsdk:latest AS builder
+
+ARG CMAKE_VERSION=3.29.3
+
+WORKDIR /src
+
+USER root
+
+RUN apt-get update && apt-get install -y git wget && rm -rf /var/lib/apt/lists/*
+RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.sh -O /tmp/cmake.sh && \
+ chmod +x /tmp/cmake.sh && \
+ /tmp/cmake.sh --skip-license --prefix=/usr/local && \
+ rm /tmp/cmake.sh
+
+RUN chown -R emscripten:emscripten /src
+
+USER emscripten
+
+COPY ISLE/emscripten/libwasmfs_fetch.js.patch /tmp/
+RUN cd /emsdk/upstream/emscripten && \
+ git apply --check /tmp/libwasmfs_fetch.js.patch && \
+ git apply /tmp/libwasmfs_fetch.js.patch
+
+COPY --chown=emscripten:emscripten . .
+
+RUN emcmake cmake -S . -B build -DISLE_BUILD_CONFIG=OFF -DISLE_DEBUG=OFF -DCMAKE_BUILD_TYPE=Release -DISLE_EMSCRIPTEN_HOST=/assets && \
+ emmake cmake --build build -j 32
+
+RUN echo "Fetching isle.pizza frontend..."; \
+ git clone --depth 1 https://github.com/isledecomp/isle.pizza /tmp/isle.pizza;
+
+FROM nginx:alpine
+
+COPY docker/emscripten/nginx.conf /etc/nginx/nginx.conf
+COPY --from=builder /tmp/isle.pizza /usr/share/nginx/html
+COPY --from=builder /src/build/isle.* /usr/share/nginx/html
+EXPOSE 6931
diff --git a/docker/emscripten/nginx.conf b/docker/emscripten/nginx.conf
new file mode 100644
index 00000000..30d9e34d
--- /dev/null
+++ b/docker/emscripten/nginx.conf
@@ -0,0 +1,27 @@
+events {
+ worker_connections 1024;
+}
+
+http {
+ include /etc/nginx/mime.types;
+
+ server {
+ listen 6931;
+ server_name localhost;
+
+ add_header 'Cross-Origin-Embedder-Policy' 'require-corp';
+ add_header 'Cross-Origin-Opener-Policy' 'same-origin';
+ add_header 'Cross-Origin-Resource-Policy' 'cross-origin';
+
+ location / {
+ root /usr/share/nginx/html;
+ index index.html isle.html;
+ try_files $uri $uri/ =404;
+ }
+
+ location ~* ^/assets/(.*)$ {
+ alias /assets/;
+ try_files /$1 /DATA/disk/$1 =404;
+ }
+ }
+}
diff --git a/miniwin/CMakeLists.txt b/miniwin/CMakeLists.txt
index 53d00c31..456028df 100644
--- a/miniwin/CMakeLists.txt
+++ b/miniwin/CMakeLists.txt
@@ -45,11 +45,13 @@ else()
endif()
find_library(OPENGL_ES2_LIBRARY NAMES GLESv2)
-if(OPENGL_ES2_LIBRARY AND NOT WINDOWS_STORE)
+if(EMSCRIPTEN OR OPENGL_ES2_LIBRARY AND NOT WINDOWS_STORE)
message(STATUS "Found OpenGL: enabling OpenGL ES 2.x renderer")
target_sources(miniwin PRIVATE src/d3drm/backends/opengles2/renderer.cpp)
target_compile_definitions(miniwin PRIVATE USE_OPENGLES2)
- target_link_libraries(miniwin PRIVATE OpenGL::GL)
+ if(OPENGL_ES2_LIBRARY)
+ target_link_libraries(miniwin PRIVATE OpenGL::GL)
+ endif()
else()
message(STATUS "🧩 OpenGL ES 2.x support not enabled")
endif()
diff --git a/miniwin/src/d3drm/backends/citro3d/renderer.cpp b/miniwin/src/d3drm/backends/citro3d/renderer.cpp
index f9167401..72d729bc 100644
--- a/miniwin/src/d3drm/backends/citro3d/renderer.cpp
+++ b/miniwin/src/d3drm/backends/citro3d/renderer.cpp
@@ -600,6 +600,10 @@ void Citro3DRenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, con
C3D_ImmDrawEnd();
}
+void Citro3DRenderer::SetDither(bool dither)
+{
+}
+
void Citro3DRenderer::Download(SDL_Surface* target)
{
MINIWIN_NOT_IMPLEMENTED();
diff --git a/miniwin/src/d3drm/backends/directx9/renderer.cpp b/miniwin/src/d3drm/backends/directx9/renderer.cpp
index 5917cd07..2701528b 100644
--- a/miniwin/src/d3drm/backends/directx9/renderer.cpp
+++ b/miniwin/src/d3drm/backends/directx9/renderer.cpp
@@ -278,6 +278,10 @@ void DirectX9Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, co
Actual_Draw2DImage(m_textures[textureId].dxTexture, srcRect, dstRect);
}
+void DirectX9Renderer::SetDither(bool dither)
+{
+}
+
void DirectX9Renderer::Download(SDL_Surface* target)
{
Actual_Download(target);
diff --git a/miniwin/src/d3drm/backends/opengl1/actual.cpp b/miniwin/src/d3drm/backends/opengl1/actual.cpp
index e1c56636..b9234c8e 100644
--- a/miniwin/src/d3drm/backends/opengl1/actual.cpp
+++ b/miniwin/src/d3drm/backends/opengl1/actual.cpp
@@ -42,12 +42,26 @@ void GL11_DestroyTexture(GLuint texId)
glDeleteTextures(1, &texId);
}
-GLuint GL11_UploadTextureData(void* pixels, int width, int height)
+GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUi)
{
GLuint texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
+ if (isUi) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
return texId;
}
@@ -111,7 +125,6 @@ void GL11_BeginFrame(const Matrix4x4* projection)
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
- glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Disable all lights and reset global ambient
for (int i = 0; i < 8; ++i) {
@@ -198,6 +211,7 @@ void GL11_SubmitDraw(
glLoadMatrixf(&modelViewMatrix[0][0]);
glEnable(GL_NORMALIZE);
+ glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
if (appearance.shininess != 0.0f) {
@@ -220,8 +234,6 @@ void GL11_SubmitDraw(
// Bind texture if present
if (appearance.textureId != NO_TEXTURE_ID) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texId);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -279,7 +291,7 @@ void GL11_Clear(float r, float g, float b)
}
void GL11_Draw2DImage(
- GLuint texId,
+ GLTextureCacheEntry& cache,
const SDL_Rect& srcRect,
const SDL_Rect& dstRect,
float left,
@@ -305,24 +317,14 @@ void GL11_Draw2DImage(
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texId);
+ glBindTexture(GL_TEXTURE_2D, cache.glTextureId);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
- GLint boundTexture = 0;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
-
- GLfloat texW, texH;
- glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texW);
- glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texH);
-
- 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 u1 = srcRect.x / cache.width;
+ float v1 = srcRect.y / cache.height;
+ float u2 = (srcRect.x + srcRect.w) / cache.width;
+ float v2 = (srcRect.y + srcRect.h) / cache.height;
float x1 = (float) dstRect.x;
float y1 = (float) dstRect.y;
@@ -352,3 +354,13 @@ void GL11_Download(SDL_Surface* target)
glFinish();
glReadPixels(0, 0, target->w, target->h, GL_RGBA, GL_UNSIGNED_BYTE, target->pixels);
}
+
+void GL11_SetDither(bool dither)
+{
+ if (dither) {
+ glEnable(GL_DITHER);
+ }
+ else {
+ glDisable(GL_DITHER);
+ }
+}
diff --git a/miniwin/src/d3drm/backends/opengl1/actual.h b/miniwin/src/d3drm/backends/opengl1/actual.h
index 8a4fb8e8..7a6a4432 100644
--- a/miniwin/src/d3drm/backends/opengl1/actual.h
+++ b/miniwin/src/d3drm/backends/opengl1/actual.h
@@ -39,6 +39,8 @@ struct GLTextureCacheEntry {
IDirect3DRMTexture* texture;
Uint32 version;
GLuint glTextureId;
+ float width;
+ float height;
};
struct GLMeshCacheEntry {
@@ -62,7 +64,7 @@ struct GLMeshCacheEntry {
void GL11_InitState();
void GL11_LoadExtensions();
void GL11_DestroyTexture(GLuint texId);
-GLuint GL11_UploadTextureData(void* pixels, int width, int height);
+GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUI);
void GL11_UploadMesh(GLMeshCacheEntry& cache, bool hasTexture);
void GL11_DestroyMesh(GLMeshCacheEntry& cache);
void GL11_BeginFrame(const Matrix4x4* projection);
@@ -77,7 +79,7 @@ void GL11_SubmitDraw(
void GL11_Resize(int width, int height);
void GL11_Clear(float r, float g, float b);
void GL11_Draw2DImage(
- GLuint texId,
+ GLTextureCacheEntry& cache,
const SDL_Rect& srcRect,
const SDL_Rect& dstRect,
float left,
@@ -85,4 +87,5 @@ void GL11_Draw2DImage(
float bottom,
float top
);
+void GL11_SetDither(bool dither);
void GL11_Download(SDL_Surface* target);
diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp
index fb7fccd4..4c6aacf9 100644
--- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp
+++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp
@@ -58,6 +58,8 @@ OpenGL1Renderer::OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext contex
m_virtualHeight = height;
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
GL11_LoadExtensions();
+ m_useVBOs = SDL_GL_ExtensionSupported("GL_ARB_vertex_buffer_object");
+ m_useNPOT = SDL_GL_ExtensionSupported("GL_OES_texture_npot");
}
OpenGL1Renderer::~OpenGL1Renderer()
@@ -108,6 +110,58 @@ void OpenGL1Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* t
);
}
+static int NextPowerOfTwo(int v)
+{
+ int power = 1;
+ while (power < v) {
+ power <<= 1;
+ }
+ return power;
+}
+
+static Uint32 UploadTextureData(SDL_Surface* src, bool useNPOT, bool isUi)
+{
+ SDL_Surface* working = src;
+ if (src->format != SDL_PIXELFORMAT_RGBA32) {
+ working = SDL_ConvertSurface(src, SDL_PIXELFORMAT_RGBA32);
+ if (!working) {
+ SDL_Log("SDL_ConvertSurface failed: %s", SDL_GetError());
+ return NO_TEXTURE_ID;
+ }
+ }
+
+ SDL_Surface* finalSurface = working;
+
+ int newW = NextPowerOfTwo(working->w);
+ int newH = NextPowerOfTwo(working->h);
+
+ if (!useNPOT && (newW != working->w || newH != working->h)) {
+ SDL_Surface* resized = SDL_CreateSurface(newW, newH, working->format);
+ if (!resized) {
+ SDL_Log("SDL_CreateSurface (resize) failed: %s", SDL_GetError());
+ if (working != src) {
+ SDL_DestroySurface(working);
+ }
+ return NO_TEXTURE_ID;
+ }
+
+ SDL_Rect srcRect = {0, 0, working->w, working->h};
+ SDL_Rect dstRect = {0, 0, newW, newH};
+ SDL_BlitSurfaceScaled(working, &srcRect, resized, &dstRect, SDL_SCALEMODE_NEAREST);
+
+ if (working != src) {
+ SDL_DestroySurface(working);
+ }
+ finalSurface = resized;
+ }
+
+ Uint32 texId = GL11_UploadTextureData(finalSurface->pixels, finalSurface->w, finalSurface->h, isUi);
+ if (finalSurface != src) {
+ SDL_DestroySurface(finalSurface);
+ }
+ return texId;
+}
+
Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
{
auto texture = static_cast(iTexture);
@@ -118,28 +172,16 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
if (tex.texture == texture) {
if (tex.version != texture->m_version) {
GL11_DestroyTexture(tex.glTextureId);
-
- SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
- if (!surf) {
- return NO_TEXTURE_ID;
- }
- tex.glTextureId = GL11_UploadTextureData(surf->pixels, surf->w, surf->h);
- SDL_DestroySurface(surf);
-
+ tex.glTextureId = UploadTextureData(surface->m_surface, m_useNPOT, isUi);
tex.version = texture->m_version;
+ tex.width = surface->m_surface->w;
+ tex.height = surface->m_surface->h;
}
return i;
}
}
- GLuint texId;
-
- SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
- if (!surf) {
- return NO_TEXTURE_ID;
- }
- texId = GL11_UploadTextureData(surf->pixels, surf->w, surf->h);
- SDL_DestroySurface(surf);
+ GLuint texId = UploadTextureData(surface->m_surface, m_useNPOT, isUi);
for (Uint32 i = 0; i < m_textures.size(); ++i) {
auto& tex = m_textures[i];
@@ -147,12 +189,20 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
tex.texture = texture;
tex.version = texture->m_version;
tex.glTextureId = texId;
+ 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});
+ m_textures.push_back(
+ {texture,
+ texture->m_version,
+ texId,
+ static_cast(surface->m_surface->w),
+ static_cast(surface->m_surface->h)}
+ );
AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture);
return (Uint32) (m_textures.size() - 1);
}
@@ -331,7 +381,12 @@ void OpenGL1Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, con
float top = -m_viewportTransform.offsetY / m_viewportTransform.scale;
float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
- GL11_Draw2DImage(m_textures[textureId].glTextureId, srcRect, dstRect, left, right, bottom, top);
+ GL11_Draw2DImage(m_textures[textureId], srcRect, dstRect, left, right, bottom, top);
+}
+
+void OpenGL1Renderer::SetDither(bool dither)
+{
+ GL11_SetDither(dither);
}
void OpenGL1Renderer::Download(SDL_Surface* target)
diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp
index 6695da81..28466bea 100644
--- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp
+++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp
@@ -47,6 +47,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
SDL_GLContext context = SDL_GL_CreateContext(DDWindow);
if (!context) {
+ SDL_Log("SDL_GL_CreateContext: %s", SDL_GetError());
return nullptr;
}
@@ -705,3 +706,13 @@ void OpenGLES2Renderer::Download(SDL_Surface* target)
SDL_DestroySurface(bufferClone);
}
+
+void OpenGLES2Renderer::SetDither(bool dither)
+{
+ if (dither) {
+ glEnable(GL_DITHER);
+ }
+ else {
+ glDisable(GL_DITHER);
+ }
+}
diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp
index 98704c66..69b326b6 100644
--- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp
+++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp
@@ -942,6 +942,10 @@ void Direct3DRMSDL3GPURenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& sr
SDL_SetGPUScissor(m_renderPass, &fullViewport);
}
+void Direct3DRMSDL3GPURenderer::SetDither(bool dither)
+{
+}
+
void Direct3DRMSDL3GPURenderer::Download(SDL_Surface* target)
{
if (!m_cmdbuf) {
diff --git a/miniwin/src/d3drm/backends/software/renderer.cpp b/miniwin/src/d3drm/backends/software/renderer.cpp
index 02c5bfc0..b4fab671 100644
--- a/miniwin/src/d3drm/backends/software/renderer.cpp
+++ b/miniwin/src/d3drm/backends/software/renderer.cpp
@@ -788,6 +788,10 @@ void Direct3DRMSoftwareRenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& s
SDL_LockSurface(surface);
}
+void Direct3DRMSoftwareRenderer::SetDither(bool dither)
+{
+}
+
void Direct3DRMSoftwareRenderer::Download(SDL_Surface* target)
{
SDL_Rect srcRect = {
diff --git a/miniwin/src/d3drm/d3drmdevice.cpp b/miniwin/src/d3drm/d3drmdevice.cpp
index b738c809..822f412e 100644
--- a/miniwin/src/d3drm/d3drmdevice.cpp
+++ b/miniwin/src/d3drm/d3drmdevice.cpp
@@ -84,9 +84,7 @@ D3DRMRENDERQUALITY Direct3DRMDevice2Impl::GetQuality()
HRESULT Direct3DRMDevice2Impl::SetDither(BOOL dither)
{
- if (dither) {
- MINIWIN_NOT_IMPLEMENTED();
- }
+ m_renderer->SetDither(dither);
return DD_OK;
}
diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h
index 259b20eb..a871bb26 100644
--- a/miniwin/src/internal/d3drmrenderer.h
+++ b/miniwin/src/internal/d3drmrenderer.h
@@ -53,6 +53,7 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
virtual void Flip() = 0;
virtual void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) = 0;
virtual void Download(SDL_Surface* target) = 0;
+ virtual void SetDither(bool dither) = 0;
protected:
int m_width, m_height;
diff --git a/miniwin/src/internal/d3drmrenderer_citro3d.h b/miniwin/src/internal/d3drmrenderer_citro3d.h
index 426f75c8..af91b3dc 100644
--- a/miniwin/src/internal/d3drmrenderer_citro3d.h
+++ b/miniwin/src/internal/d3drmrenderer_citro3d.h
@@ -50,6 +50,7 @@ class Citro3DRenderer : public Direct3DRMRenderer {
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
+ void SetDither(bool dither) override;
private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
diff --git a/miniwin/src/internal/d3drmrenderer_directx9.h b/miniwin/src/internal/d3drmrenderer_directx9.h
index 900bbe03..18ac126f 100644
--- a/miniwin/src/internal/d3drmrenderer_directx9.h
+++ b/miniwin/src/internal/d3drmrenderer_directx9.h
@@ -36,6 +36,7 @@ class DirectX9Renderer : public Direct3DRMRenderer {
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
+ void SetDither(bool dither) override;
private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
diff --git a/miniwin/src/internal/d3drmrenderer_opengl1.h b/miniwin/src/internal/d3drmrenderer_opengl1.h
index 58406709..656a964b 100644
--- a/miniwin/src/internal/d3drmrenderer_opengl1.h
+++ b/miniwin/src/internal/d3drmrenderer_opengl1.h
@@ -36,6 +36,7 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
+ void SetDither(bool dither) override;
private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
@@ -46,6 +47,7 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
D3DRMMATRIX4D m_projection;
SDL_Surface* m_renderedImage;
bool m_useVBOs;
+ bool m_useNPOT;
bool m_dirty = false;
std::vector m_lights;
SDL_GLContext m_context;
diff --git a/miniwin/src/internal/d3drmrenderer_opengles2.h b/miniwin/src/internal/d3drmrenderer_opengles2.h
index f5d62579..0aaec63d 100644
--- a/miniwin/src/internal/d3drmrenderer_opengles2.h
+++ b/miniwin/src/internal/d3drmrenderer_opengles2.h
@@ -57,6 +57,7 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
+ void SetDither(bool dither) override;
private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
diff --git a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h
index 02ec05d0..cf68a8c4 100644
--- a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h
+++ b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h
@@ -67,6 +67,7 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
+ void SetDither(bool dither) override;
private:
Direct3DRMSDL3GPURenderer(
diff --git a/miniwin/src/internal/d3drmrenderer_software.h b/miniwin/src/internal/d3drmrenderer_software.h
index 87715999..91abac32 100644
--- a/miniwin/src/internal/d3drmrenderer_software.h
+++ b/miniwin/src/internal/d3drmrenderer_software.h
@@ -49,6 +49,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
+ void SetDither(bool dither) override;
private:
void ClearZBuffer();
diff --git a/packaging/linux/flatpak/org.legoisland.Isle.json b/packaging/linux/flatpak/org.legoisland.Isle.json
index e8cd3f8e..178434fa 100644
--- a/packaging/linux/flatpak/org.legoisland.Isle.json
+++ b/packaging/linux/flatpak/org.legoisland.Isle.json
@@ -1,12 +1,9 @@
{
"id": "org.legoisland.Isle",
-
"runtime": "org.kde.Platform",
"sdk": "org.kde.Sdk",
"runtime-version": "6.8",
-
"command": "isle",
-
"finish-args": [
"--share=ipc",
"--socket=wayland",
@@ -19,7 +16,6 @@
"--filesystem=/mnt/:ro",
"--filesystem=home:ro"
],
-
"modules": [
{
"name": "isle",
@@ -34,11 +30,6 @@
"path": "../../../3rdparty",
"dest": "3rdparty/"
},
- {
- "type": "dir",
- "path": "../../../cmake",
- "dest": "cmake/"
- },
{
"type": "dir",
"path": "../../../CMake",
@@ -86,4 +77,4 @@
}
}
]
-}
+}
\ No newline at end of file