Merge branch 'master' of github.com:isledecomp/isle-portable into webgl

This commit is contained in:
Anders Jenbo 2025-07-01 03:15:31 +02:00
commit 26cc7c6295
48 changed files with 1145 additions and 553 deletions

View File

@ -14,3 +14,8 @@ trim_trailing_whitespace = true
[{CMakeLists.txt,*.cmake}] [{CMakeLists.txt,*.cmake}]
indent_size = 2 indent_size = 2
insert_final_newline = true
[*.{json,xml.in,desktop.in}]
indent_size = 2
insert_final_newline = true

4
.gitattributes vendored
View File

@ -5,3 +5,7 @@
*.html text eol=lf diff=html *.html text eol=lf diff=html
*.mdp binary *.mdp binary
*.mak text eol=crlf *.mak text eol=crlf
**/*.ico binary
**/*.png binary
**/*.svg text eol=lf
**/*.desktop text eol=lf

View File

@ -33,14 +33,14 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- { name: 'Linux', os: 'ubuntu-latest', dx5: false, config: true, build-type: 'Debug', linux: true, werror: true, clang-tidy: true } - { 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, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_x86' } - { 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, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64' } - { 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, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_arm64' } - { 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, build-type: 'Debug', mingw: true, werror: true, clang-tidy: true, msystem: 'mingw32', msys-env: 'mingw-w64-i686', shell: 'msys2 {0}' } - { 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, build-type: 'Debug', mingw: true, werror: true, clang-tidy: true, msystem: 'mingw64', msys-env: 'mingw-w64-x86_64', 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, build-type: 'Debug', brew: true, werror: true, clang-tidy: false } - { 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, build-type: 'Debug', emsdk: true, werror: true, clang-tidy: false, cmake-wrapper: 'emcmake' } - { name: 'Emscripten', os: 'ubuntu-latest', dx5: false, config: false, emsdk: true, werror: true, clang-tidy: false, cmake-wrapper: 'emcmake' }
steps: steps:
- name: Setup vcvars - name: Setup vcvars
if: ${{ !!matrix.msvc }} if: ${{ !!matrix.msvc }}
@ -67,7 +67,7 @@ jobs:
sudo apt-get install -y \ sudo apt-get install -y \
libx11-dev libxext-dev libxrandr-dev libxrender-dev libxfixes-dev libxi-dev libxinerama-dev \ 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 \ 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) - name: Install macOS dependencies (brew)
if: ${{ matrix.brew }} if: ${{ matrix.brew }}
@ -89,11 +89,12 @@ jobs:
- name: Configure (CMake) - name: Configure (CMake)
run: | run: |
${{ matrix.cmake-wrapper || '' }} cmake -S . -B build -GNinja \ ${{ matrix.cmake-wrapper || '' }} cmake -S . -B build -GNinja \
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ -DCMAKE_BUILD_TYPE=Release \
-DISLE_USE_DX5=${{ !!matrix.dx5 }} \ -DISLE_USE_DX5=${{ !!matrix.dx5 }} \
-DISLE_BUILD_CONFIG=${{ matrix.config }} \ -DISLE_BUILD_CONFIG=${{ !!matrix.config }} \
-DENABLE_CLANG_TIDY=${{ !!matrix.clang-tidy }} \ -DENABLE_CLANG_TIDY=${{ !!matrix.clang-tidy }} \
-DISLE_WERROR=${{ !!matrix.werror }} \ -DISLE_WERROR=${{ !!matrix.werror }} \
-DISLE_DEBUG=OFF \
-Werror=dev -Werror=dev
- name: Build (CMake) - name: Build (CMake)
@ -104,11 +105,64 @@ jobs:
cd build cd build
cpack . 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 - name: Upload Build Artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: '${{ matrix.name }} ${{ matrix.build-type }}' name: '${{ matrix.name }}'
path: build/dist/isle-* 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: ncc:
name: 'C++' name: 'C++'
@ -148,3 +202,30 @@ jobs:
LEGO1/omni/src/video/flic.cpp \ LEGO1/omni/src/video/flic.cpp \
$action_headers \ $action_headers \
--path LEGO1/omni LEGO1/lego/legoomni --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: "*"
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/*

View File

@ -1,116 +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
- 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: Upload Artifact
uses: actions/upload-artifact@main
with:
name: Release-${{ matrix.name }}
path: |
build/dist/isle-*
release:
name: 'Release'
runs-on: ubuntu-latest
needs: build
steps:
- name: Download All Artifacts
uses: actions/download-artifact@main
with:
pattern: Release-*
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/*

6
.gitignore vendored
View File

@ -30,3 +30,9 @@ LEGO1.DLL
# Kate - Text # Kate - Text
/.cache /.cache
# Flatpak build cache
**/.flatpak-builder/
# Flatpak build dir
**/flatpak-build/

View File

@ -13,6 +13,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
include(CheckCXXSourceCompiles) include(CheckCXXSourceCompiles)
include(CMakeDependentOption) include(CMakeDependentOption)
include(CMakePushCheckState) include(CMakePushCheckState)
include(cmake/detectcpu.cmake)
DetectTargetCPUArchitectures(ISLE_CPUS)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -624,7 +627,9 @@ else()
include(GNUInstallDirs) include(GNUInstallDirs)
endif() endif()
set(ISLE_PACKAGE_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CACHE STRING "Platform name of the package") 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) if(BUILD_SHARED_LIBS)
list(APPEND install_extra_targets lego1) list(APPEND install_extra_targets lego1)
endif() endif()
@ -643,8 +648,10 @@ if(EMSCRIPTEN)
) )
endif() endif()
add_subdirectory(packaging)
set(CPACK_PACKAGE_DIRECTORY "dist") 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) if(MSVC)
set(CPACK_GENERATOR ZIP) set(CPACK_GENERATOR ZIP)
else() else()

View File

@ -56,9 +56,17 @@ bool CConfigApp::InitInstance()
return false; return false;
} }
m_device_enumerator = new LegoDeviceEnumerate; 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<HWND>(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; return FALSE;
} }
SDL_DestroyWindow(window);
m_driver = NULL; m_driver = NULL;
m_device = NULL; m_device = NULL;
m_full_screen = TRUE; m_full_screen = TRUE;

View File

@ -123,7 +123,7 @@ class Hospital : public LegoWorld {
MxLong m_copLedAnimTimer; // 0x11c MxLong m_copLedAnimTimer; // 0x11c
MxLong m_pizzaLedAnimTimer; // 0x120 MxLong m_pizzaLedAnimTimer; // 0x120
MxLong m_time; // 0x124 MxLong m_time; // 0x124
undefined m_unk0x128; // 0x128 MxBool m_exited; // 0x128
}; };
#endif // HOSPITAL_H #endif // HOSPITAL_H

View File

@ -121,7 +121,7 @@ class LegoAnimPresenter : public MxVideoPresenter {
void SubstituteVariables(); void SubstituteVariables();
void FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); 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_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 LegoAnim* m_anim; // 0x64
LegoROI** m_roiMap; // 0x68 LegoROI** m_roiMap; // 0x68

View File

@ -79,7 +79,7 @@ class LegoBuildingManager : public MxCore {
MxBool SwitchMove(LegoEntity* p_entity); MxBool SwitchMove(LegoEntity* p_entity);
MxBool SwitchMood(LegoEntity* p_entity); MxBool SwitchMood(LegoEntity* p_entity);
MxU32 GetAnimationId(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(LegoEntity* p_entity);
MxBool DecrementCounter(MxS32 p_index); MxBool DecrementCounter(MxS32 p_index);
MxBool DecrementCounter(LegoBuildingInfo* p_data); MxBool DecrementCounter(LegoBuildingInfo* p_data);

View File

@ -88,7 +88,7 @@ class LegoCharacterManager {
MxBool SwitchMove(LegoROI* p_roi); MxBool SwitchMove(LegoROI* p_roi);
MxBool SwitchMood(LegoROI* p_roi); MxBool SwitchMood(LegoROI* p_roi);
MxU32 GetAnimationId(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); MxU8 GetMood(LegoROI* p_roi);
LegoROI* CreateAutoROI(const char* p_name, const char* p_lodName, MxBool p_createEntity); LegoROI* CreateAutoROI(const char* p_name, const char* p_lodName, MxBool p_createEntity);
MxResult UpdateBoundingSphereAndBox(LegoROI* p_roi); MxResult UpdateBoundingSphereAndBox(LegoROI* p_roi);

View File

@ -28,7 +28,7 @@ class LegoEntity : public MxEntity {
}; };
enum { enum {
c_altBit1 = 0x01 c_disabled = 0x01
}; };
LegoEntity() { Init(); } LegoEntity() { Init(); }
@ -68,13 +68,13 @@ class LegoEntity : public MxEntity {
// FUNCTION: BETA10 0x10013260 // FUNCTION: BETA10 0x10013260
virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30
virtual void ClickSound(MxBool p_und); // vtable+0x34 virtual void ClickSound(MxBool p_basedOnMood); // vtable+0x34
virtual void ClickAnimation(); // vtable+0x38 virtual void ClickAnimation(); // vtable+0x38
virtual void SwitchVariant(); // vtable+0x3c virtual void SwitchVariant(); // vtable+0x3c
virtual void SwitchSound(); // vtable+0x40 virtual void SwitchSound(); // vtable+0x40
virtual void SwitchMove(); // vtable+0x44 virtual void SwitchMove(); // vtable+0x44
virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48 virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48
virtual void SwitchMood(); // vtable+0x4c virtual void SwitchMood(); // vtable+0x4c
void FUN_10010c30(); void FUN_10010c30();
void SetType(MxU8 p_type); void SetType(MxU8 p_type);
@ -83,7 +83,7 @@ class LegoEntity : public MxEntity {
Mx3DPointFloat GetWorldUp(); Mx3DPointFloat GetWorldUp();
Mx3DPointFloat GetWorldPosition(); 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; } MxBool GetFlagsIsSet(MxU8 p_flag) { return m_flags & p_flag; }
MxU8 GetFlags() { return m_flags; } MxU8 GetFlags() { return m_flags; }
@ -101,14 +101,14 @@ class LegoEntity : public MxEntity {
void SetFlags(MxU8 p_flags) { m_flags = p_flags; } void SetFlags(MxU8 p_flags) { m_flags = p_flags; }
void SetFlag(MxU8 p_flag) { m_flags |= p_flag; } void SetFlag(MxU8 p_flag) { m_flags |= p_flag; }
void ClearFlag(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 SetInteractionFlag(MxU8 p_flag) { m_interaction |= p_flag; }
void ClearUnknown0x10Flag(MxU8 p_flag) { m_unk0x10 &= ~p_flag; } void ClearInteractionFlag(MxU8 p_flag) { m_interaction &= ~p_flag; }
protected: protected:
void Init(); void Init();
void SetWorld(); void SetWorld();
MxU8 m_unk0x10; // 0x10 MxU8 m_interaction; // 0x10
MxU8 m_flags; // 0x11 MxU8 m_flags; // 0x11
Mx3DPointFloat m_worldLocation; // 0x14 Mx3DPointFloat m_worldLocation; // 0x14
Mx3DPointFloat m_worldDirection; // 0x28 Mx3DPointFloat m_worldDirection; // 0x28

View File

@ -49,7 +49,7 @@ class LEGO1_EXPORT LegoPlantManager : public MxCore {
MxBool SwitchMove(LegoEntity* p_entity); MxBool SwitchMove(LegoEntity* p_entity);
MxBool SwitchMood(LegoEntity* p_entity); MxBool SwitchMood(LegoEntity* p_entity);
MxU32 GetAnimationId(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); LegoPlantInfo* GetInfoArray(MxS32& p_length);
LegoEntity* CreatePlant(MxS32 p_index, LegoWorld* p_world, LegoOmni::World p_worldId); LegoEntity* CreatePlant(MxS32 p_index, LegoWorld* p_world, LegoOmni::World p_worldId);
MxBool DecrementCounter(LegoEntity* p_entity); MxBool DecrementCounter(LegoEntity* p_entity);

View File

@ -199,10 +199,10 @@ LegoBuildingInfo g_buildingInfoInit[16] = {
MxU32 LegoBuildingManager::g_maxSound = 6; MxU32 LegoBuildingManager::g_maxSound = 6;
// GLOBAL: LEGO1 0x100f373c // GLOBAL: LEGO1 0x100f373c
MxU32 g_unk0x100f373c = 0x3c; MxU32 g_buildingSoundIdOffset = 0x3c;
// GLOBAL: LEGO1 0x100f3740 // GLOBAL: LEGO1 0x100f3740
MxU32 g_unk0x100f3740 = 0x42; MxU32 g_buildingSoundIdMoodOffset = 0x42;
// clang-format off // clang-format off
// GLOBAL: LEGO1 0x100f3788 // GLOBAL: LEGO1 0x100f3788
@ -227,6 +227,8 @@ LegoBuildingInfo g_buildingInfo[16];
// GLOBAL: LEGO1 0x100f3748 // GLOBAL: LEGO1 0x100f3748
MxS32 LegoBuildingManager::g_maxMove[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0}; 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 // FUNCTION: LEGO1 0x1002f8b0
void LegoBuildingManager::configureLegoBuildingManager(MxS32 p_buildingManagerConfig) void LegoBuildingManager::configureLegoBuildingManager(MxS32 p_buildingManagerConfig)
{ {
@ -392,6 +394,9 @@ MxResult LegoBuildingManager::Read(LegoStorage* p_storage)
m_nextVariant = 0; 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; result = SUCCESS;
done: done:
@ -461,7 +466,7 @@ MxBool LegoBuildingManager::SwitchVariant(LegoEntity* p_entity)
roi->SetVisibility(FALSE); roi->SetVisibility(FALSE);
info->m_variant = g_buildingInfoVariants[m_nextVariant]; info->m_variant = g_buildingInfoVariants[m_nextVariant];
CreateBuilding(12, CurrentWorld()); CreateBuilding(HAUS1_INDEX, CurrentWorld());
if (info->m_entity != NULL) { if (info->m_entity != NULL) {
info->m_entity->GetROI()->SetVisibility(TRUE); info->m_entity->GetROI()->SetVisibility(TRUE);
@ -548,7 +553,7 @@ MxU32 LegoBuildingManager::GetAnimationId(LegoEntity* p_entity)
// FUNCTION: LEGO1 0x1002ff40 // FUNCTION: LEGO1 0x1002ff40
// FUNCTION: BETA10 0x10064398 // 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); LegoBuildingInfo* info = GetInfo(p_entity);
@ -556,12 +561,12 @@ MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_state)
return 0; return 0;
} }
if (p_state) { if (p_basedOnMood) {
return info->m_mood + g_unk0x100f3740; return info->m_mood + g_buildingSoundIdMoodOffset;
} }
if (info != NULL) { if (info != NULL) {
return info->m_sound + g_unk0x100f373c; return info->m_sound + g_buildingSoundIdOffset;
} }
return 0; return 0;

View File

@ -39,10 +39,10 @@ MxU32 g_characterAnimationId = 10;
char* LegoCharacterManager::g_customizeAnimFile = NULL; char* LegoCharacterManager::g_customizeAnimFile = NULL;
// GLOBAL: LEGO1 0x100fc4d8 // GLOBAL: LEGO1 0x100fc4d8
MxU32 g_soundIdOffset = 50; MxU32 g_characterSoundIdOffset = 50;
// GLOBAL: LEGO1 0x100fc4dc // GLOBAL: LEGO1 0x100fc4dc
MxU32 g_soundIdMoodOffset = 66; MxU32 g_characterSoundIdMoodOffset = 66;
// GLOBAL: LEGO1 0x100fc4e8 // GLOBAL: LEGO1 0x100fc4e8
MxU32 g_headTextureCounter = 0; MxU32 g_headTextureCounter = 0;
@ -933,16 +933,16 @@ MxU32 LegoCharacterManager::GetAnimationId(LegoROI* p_roi)
// FUNCTION: LEGO1 0x10085140 // FUNCTION: LEGO1 0x10085140
// FUNCTION: BETA10 0x10076855 // 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); LegoActorInfo* info = GetActorInfo(p_roi);
if (p_und) { if (p_basedOnMood) {
return info->m_mood + g_soundIdMoodOffset; return info->m_mood + g_characterSoundIdMoodOffset;
} }
if (info != NULL) { if (info != NULL) {
return info->m_sound + g_soundIdOffset; return info->m_sound + g_characterSoundIdOffset;
} }
else { else {
return 0; return 0;

View File

@ -40,10 +40,10 @@ MxU8 g_counters[] = {1, 2, 2, 3};
MxU32 LegoPlantManager::g_maxSound = 8; MxU32 LegoPlantManager::g_maxSound = 8;
// GLOBAL: LEGO1 0x100f3160 // GLOBAL: LEGO1 0x100f3160
MxU32 g_unk0x100f3160 = 56; MxU32 g_plantSoundIdOffset = 56;
// GLOBAL: LEGO1 0x100f3164 // GLOBAL: LEGO1 0x100f3164
MxU32 g_unk0x100f3164 = 66; MxU32 g_plantSoundIdMoodOffset = 66;
// GLOBAL: LEGO1 0x100f3168 // GLOBAL: LEGO1 0x100f3168
MxS32 LegoPlantManager::g_maxMove[4] = {3, 3, 3, 3}; MxS32 LegoPlantManager::g_maxMove[4] = {3, 3, 3, 3};
@ -514,16 +514,16 @@ MxU32 LegoPlantManager::GetAnimationId(LegoEntity* p_entity)
// FUNCTION: LEGO1 0x10026ba0 // FUNCTION: LEGO1 0x10026ba0
// FUNCTION: BETA10 0x100c61ba // 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); LegoPlantInfo* info = GetInfo(p_entity);
if (p_state) { if (p_basedOnMood) {
return (info->m_mood & 1) + g_unk0x100f3164; return (info->m_mood & 1) + g_plantSoundIdMoodOffset;
} }
if (info != NULL) { if (info != NULL) {
return info->m_sound + g_unk0x100f3160; return info->m_sound + g_plantSoundIdOffset;
} }
return 0; return 0;

View File

@ -20,7 +20,7 @@ LegoActor::LegoActor()
m_frequencyFactor = 0.0f; m_frequencyFactor = 0.0f;
m_sound = NULL; m_sound = NULL;
m_unk0x70 = 0.0f; m_unk0x70 = 0.0f;
m_unk0x10 = 0; m_interaction = 0;
m_actorId = 0; m_actorId = 0;
} }

View File

@ -31,7 +31,7 @@ void LegoEntity::Init()
m_roi = NULL; m_roi = NULL;
m_cameraFlag = FALSE; m_cameraFlag = FALSE;
m_siFile = NULL; m_siFile = NULL;
m_unk0x10 = 0; m_interaction = 0;
m_flags = 0; m_flags = 0;
m_actionType = Extra::ActionType::e_unknown; m_actionType = Extra::ActionType::e_unknown;
m_targetEntityId = -1; m_targetEntityId = -1;
@ -266,23 +266,23 @@ void LegoEntity::ParseAction(char* p_extra)
// FUNCTION: LEGO1 0x10010f10 // FUNCTION: LEGO1 0x10010f10
// FUNCTION: BETA10 0x1007ee87 // FUNCTION: BETA10 0x1007ee87
void LegoEntity::ClickSound(MxBool p_und) void LegoEntity::ClickSound(MxBool p_basedOnMood)
{ {
if (!GetUnknown0x10IsSet(c_altBit1)) { if (!IsInteraction(c_disabled)) {
MxU32 objectId = 0; MxU32 objectId = 0;
const char* name = m_roi->GetName(); const char* name = m_roi->GetName();
switch (m_type) { switch (m_type) {
case e_actor: case e_actor:
objectId = CharacterManager()->GetSoundId(m_roi, p_und); objectId = CharacterManager()->GetSoundId(m_roi, p_basedOnMood);
break; break;
case e_unk1: case e_unk1:
break; break;
case e_plant: case e_plant:
objectId = PlantManager()->GetSoundId(this, p_und); objectId = PlantManager()->GetSoundId(this, p_basedOnMood);
break; break;
case e_building: case e_building:
objectId = BuildingManager()->GetSoundId(this, p_und); objectId = BuildingManager()->GetSoundId(this, p_basedOnMood);
break; break;
} }
@ -300,7 +300,7 @@ void LegoEntity::ClickSound(MxBool p_und)
// FUNCTION: BETA10 0x1007f062 // FUNCTION: BETA10 0x1007f062
void LegoEntity::ClickAnimation() void LegoEntity::ClickAnimation()
{ {
if (!GetUnknown0x10IsSet(c_altBit1)) { if (!IsInteraction(c_disabled)) {
MxU32 objectId = 0; MxU32 objectId = 0;
MxDSAction action; MxDSAction action;
const char* name = m_roi->GetName(); const char* name = m_roi->GetName();
@ -332,7 +332,7 @@ void LegoEntity::ClickAnimation()
action.SetObjectId(objectId); action.SetObjectId(objectId);
action.AppendExtra(strlen(extra) + 1, extra); action.AppendExtra(strlen(extra) + 1, extra);
LegoOmni::GetInstance()->GetAnimationManager()->StartEntityAction(action, this); LegoOmni::GetInstance()->GetAnimationManager()->StartEntityAction(action, this);
m_unk0x10 |= c_altBit1; m_interaction |= c_disabled;
} }
} }
} }

View File

@ -697,7 +697,7 @@ MxLong LegoNavController::Notify(MxParam& p_param)
for (MxS32 i = 0; i < numPlants; i++) { for (MxS32 i = 0; i < numPlants; i++) {
LegoEntity* entity = plantMgr->CreatePlant(i, NULL, LegoOmni::e_act1); 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(); LegoROI* roi = entity->GetROI();
if (roi != NULL && roi->GetVisibility()) { if (roi != NULL && roi->GetVisibility()) {

View File

@ -793,7 +793,7 @@ void LegoAnimPresenter::StartingTickle()
} }
FUN_10069b10(); FUN_10069b10();
FUN_1006c8a0(TRUE); SetDisabled(TRUE);
if (m_unk0x78 == NULL) { if (m_unk0x78 == NULL) {
if (fabs(m_action->GetDirection()[0]) >= 0.00000047683716F || if (fabs(m_action->GetDirection()[0]) >= 0.00000047683716F ||
@ -1093,7 +1093,7 @@ void LegoAnimPresenter::EndAction()
} }
} }
FUN_1006c8a0(FALSE); SetDisabled(FALSE);
FUN_1006ab70(); FUN_1006ab70();
VTable0x90(); VTable0x90();
@ -1154,18 +1154,18 @@ void LegoAnimPresenter::VTable0x90()
} }
// FUNCTION: LEGO1 0x1006c8a0 // FUNCTION: LEGO1 0x1006c8a0
void LegoAnimPresenter::FUN_1006c8a0(MxBool p_bool) void LegoAnimPresenter::SetDisabled(MxBool p_disabled)
{ {
if (m_roiMapSize != 0 && m_roiMap != NULL) { if (m_roiMapSize != 0 && m_roiMap != NULL) {
for (MxU32 i = 1; i <= m_roiMapSize; i++) { for (MxU32 i = 1; i <= m_roiMapSize; i++) {
LegoEntity* entity = m_roiMap[i]->GetEntity(); LegoEntity* entity = m_roiMap[i]->GetEntity();
if (entity != NULL) { if (entity != NULL) {
if (p_bool) { if (p_disabled) {
entity->SetUnknown0x10Flag(LegoEntity::c_altBit1); entity->SetInteractionFlag(LegoEntity::c_disabled);
} }
else { else {
entity->ClearUnknown0x10Flag(LegoEntity::c_altBit1); entity->ClearInteractionFlag(LegoEntity::c_disabled);
} }
} }
} }

View File

@ -108,7 +108,7 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM
goto done; goto done;
} }
if (deviceEnumerate.DoEnumerate() != SUCCESS) { if (deviceEnumerate.DoEnumerate(hwnd) != SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "LegoDeviceEnumerate::DoEnumerate failed"); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "LegoDeviceEnumerate::DoEnumerate failed");
goto done; goto done;
} }

View File

@ -48,7 +48,7 @@ Hospital::Hospital()
m_flashingLeds = 0; m_flashingLeds = 0;
m_copLedAnimTimer = 0; m_copLedAnimTimer = 0;
m_pizzaLedAnimTimer = 0; m_pizzaLedAnimTimer = 0;
m_unk0x128 = 0; m_exited = FALSE;
NotificationManager()->Register(this); NotificationManager()->Register(this);
} }
@ -369,8 +369,8 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
act1State = (Act1State*) GameState()->GetState("Act1State"); act1State = (Act1State*) GameState()->GetState("Act1State");
act1State->SetUnknown18(9); act1State->SetUnknown18(9);
case HospitalState::e_exitToFront: case HospitalState::e_exitToFront:
if (m_unk0x128 == 0) { if (m_exited == FALSE) {
m_unk0x128 = 1; m_exited = TRUE;
m_destLocation = LegoGameState::e_hospitalExited; m_destLocation = LegoGameState::e_hospitalExited;
DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
@ -378,8 +378,8 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
} }
break; break;
case HospitalState::e_exitToInfocenter: case HospitalState::e_exitToInfocenter:
if (m_unk0x128 == 0) { if (m_exited == FALSE) {
m_unk0x128 = 1; m_exited = TRUE;
m_destLocation = LegoGameState::e_infomain; m_destLocation = LegoGameState::e_infomain;
DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
@ -412,8 +412,8 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
m_interactionMode = 3; m_interactionMode = 3;
if (m_hospitalState->m_state == HospitalState::e_explainQuestShort) { if (m_hospitalState->m_state == HospitalState::e_explainQuestShort) {
if (m_unk0x128 == 0) { if (m_exited == FALSE) {
m_unk0x128 = 1; m_exited = TRUE;
TickleManager()->UnregisterClient(this); TickleManager()->UnregisterClient(this);
@ -568,8 +568,8 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
m_currentAction = HospitalScript::c_hho016cl_RunAnim; m_currentAction = HospitalScript::c_hho016cl_RunAnim;
m_setWithCurrentAction = 1; m_setWithCurrentAction = 1;
} }
else if (m_unk0x128 == 0) { else if (m_exited == FALSE) {
m_unk0x128 = 1; m_exited = TRUE;
m_hospitalState->m_state = HospitalState::e_exitImmediately; m_hospitalState->m_state = HospitalState::e_exitImmediately;
m_destLocation = LegoGameState::e_infomain; m_destLocation = LegoGameState::e_infomain;
@ -589,8 +589,8 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
m_currentAction = HospitalScript::c_hho016cl_RunAnim; m_currentAction = HospitalScript::c_hho016cl_RunAnim;
m_setWithCurrentAction = 1; m_setWithCurrentAction = 1;
} }
else if (m_unk0x128 == 0) { else if (m_exited == FALSE) {
m_unk0x128 = 1; m_exited = TRUE;
m_hospitalState->m_state = HospitalState::e_exitImmediately; m_hospitalState->m_state = HospitalState::e_exitImmediately;
m_destLocation = LegoGameState::e_hospitalExited; m_destLocation = LegoGameState::e_hospitalExited;

View File

@ -216,27 +216,33 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc
BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result));
} }
else { else {
newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL);
if (result != DD_OK) { if (result != DD_OK) {
BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result));
} }
else { 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) { if (result != DD_OK) {
BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result));
} }
else { else {
result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2);
if (result != DD_OK) { if (result != DD_OK) {
BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result));
} }
else { else {
if (!newDevice.m_devices.size()) { result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this);
m_list.pop_back();
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: CONFIG 0x00401dc0
// FUNCTION: LEGO1 0x1009c6c0 // FUNCTION: LEGO1 0x1009c6c0
// FUNCTION: BETA10 0x1011e3fa // FUNCTION: BETA10 0x1011e3fa
int MxDeviceEnumerate::DoEnumerate() int MxDeviceEnumerate::DoEnumerate(HWND hWnd)
{ {
if (IsInitialized()) { if (IsInitialized()) {
return -1; return -1;
} }
m_hWnd = hWnd;
HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this); HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this);
if (ret != DD_OK) { if (ret != DD_OK) {
BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret)); BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret));

View File

@ -194,7 +194,7 @@ class MxDeviceEnumerate {
MxDeviceEnumerate(); 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); BOOL EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName);
HRESULT EnumDevicesCallback( HRESULT EnumDevicesCallback(
@ -242,6 +242,7 @@ class MxDeviceEnumerate {
protected: protected:
list<MxDriver> m_list; // 0x04 list<MxDriver> m_list; // 0x04
unsigned char m_initialized; // 0x10 unsigned char m_initialized; // 0x10
HWND m_hWnd;
}; };
// TEMPLATE: BETA10 0x1011c1b0 // TEMPLATE: BETA10 0x1011c1b0

View File

@ -926,7 +926,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(
transparentColor = RGB555_CREATE(0x1f, 0, 0x1f); transparentColor = RGB555_CREATE(0x1f, 0, 0x1f);
break; break;
default: default:
transparentColor = RGB8888_CREATE(0xff, 0, 0xff, 0); transparentColor = RGB8888_CREATE(0, 0, 0, 0);
break; break;
} }
@ -971,25 +971,11 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(
surfacePtr += adjustedPitch; surfacePtr += adjustedPitch;
} }
if (p_transparent && surface) {
DDCOLORKEY key;
key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = transparentColor;
surface->SetColorKey(DDCKEY_SRCBLT, &key);
}
surface->Unlock(ddsd.lpSurface); surface->Unlock(ddsd.lpSurface);
if (p_transparent && surface) { if (p_transparent && surface && bytesPerPixel != 4) {
DDCOLORKEY key; DDCOLORKEY key;
if (bytesPerPixel == 1) { key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = transparentColor;
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);
}
surface->SetColorKey(DDCKEY_SRCBLT, &key); surface->SetColorKey(DDCKEY_SRCBLT, &key);
} }
} }

156
cmake/detectcpu.cmake Normal file
View File

@ -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} - <ERROR>")
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()

View File

@ -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<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface); auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
@ -216,24 +216,6 @@ Uint32 DirectX9Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshG
return static_cast<Uint32>(m_meshs.size() - 1); return static_cast<Uint32>(m_meshs.size() - 1);
} }
void DirectX9Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{
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;
memset(helDesc, 0, sizeof(D3DDEVICEDESC));
}
const char* DirectX9Renderer::GetName()
{
return "DirectX 9 HAL";
}
HRESULT DirectX9Renderer::BeginFrame() HRESULT DirectX9Renderer::BeginFrame()
{ {
return Actual_BeginFrame(); return Actual_BeginFrame();

View File

@ -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_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_Window* window = DDWindow; if (!DDWindow) {
bool testWindow = false; SDL_Log("No window handler");
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);
}
return nullptr; 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()); SDL_Log("SDL_GL_MakeCurrent: %s", SDL_GetError());
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
GL11_InitState(); GL11_InitState();
if (testWindow) {
SDL_DestroyWindow(window);
}
return new OpenGL1Renderer(width, height, context); return new OpenGL1Renderer(width, height, context);
} }
@ -78,6 +63,7 @@ OpenGL1Renderer::OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext contex
OpenGL1Renderer::~OpenGL1Renderer() OpenGL1Renderer::~OpenGL1Renderer()
{ {
SDL_DestroySurface(m_renderedImage); SDL_DestroySurface(m_renderedImage);
SDL_GL_DestroyContext(m_context);
} }
void OpenGL1Renderer::PushLights(const SceneLight* lightsArray, size_t count) void OpenGL1Renderer::PushLights(const SceneLight* lightsArray, size_t count)
@ -122,7 +108,7 @@ void OpenGL1Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* t
); );
} }
Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture) Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
{ {
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface); auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
@ -265,24 +251,6 @@ Uint32 OpenGL1Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGr
return (Uint32) (m_meshs.size() - 1); 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;
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* OpenGL1Renderer::GetName()
{
return "OpenGL 1.1 HAL";
}
HRESULT OpenGL1Renderer::BeginFrame() HRESULT OpenGL1Renderer::BeginFrame()
{ {
GL11_BeginFrame((Matrix4x4*) &m_projection[0][0]); GL11_BeginFrame((Matrix4x4*) &m_projection[0][0]);

View File

@ -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_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_Window* window = DDWindow; if (!DDWindow) {
bool testWindow = false; SDL_Log("No window handler");
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);
}
return nullptr; return nullptr;
} }
if (!SDL_GL_MakeCurrent(window, context)) { SDL_GLContext context = SDL_GL_CreateContext(DDWindow);
if (testWindow) { if (!context) {
SDL_DestroyWindow(window); return nullptr;
} }
if (!SDL_GL_MakeCurrent(DDWindow, context)) {
SDL_GL_DestroyContext(context);
return nullptr; return nullptr;
} }
@ -174,31 +167,9 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
glDeleteShader(vs); glDeleteShader(vs);
glDeleteShader(fs); glDeleteShader(fs);
if (testWindow) {
SDL_DestroyWindow(window);
}
return new OpenGLES2Renderer(width, height, context, shaderProgram); return new OpenGLES2Renderer(width, height, context, shaderProgram);
} }
void OpenGLES2Desc::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{
halDesc->dcmColorModel = D3DCOLORMODEL::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;
memset(helDesc, 0, sizeof(D3DDEVICEDESC));
}
const char* OpenGLES2Desc::GetName()
{
return "OpenGL ES 2.0 HAL";
}
GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = false) GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = false)
{ {
GLES2MeshCacheEntry cache{&meshGroup, meshGroup.version}; GLES2MeshCacheEntry cache{&meshGroup, meshGroup.version};
@ -268,11 +239,10 @@ GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = f
OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram) OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram)
: m_context(context), m_shaderProgram(shaderProgram) : m_context(context), m_shaderProgram(shaderProgram)
{ {
m_width = width;
m_height = height;
m_virtualWidth = width; m_virtualWidth = width;
m_virtualHeight = height; 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 = { m_uiMesh.vertices = {
{{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}}, {{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}},
@ -282,12 +252,30 @@ OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext co
}; };
m_uiMesh.indices = {0, 1, 2, 0, 2, 3}; m_uiMesh.indices = {0, 1, 2, 0, 2, 3};
m_uiMeshCache = GLES2UploadMesh(m_uiMesh, true); 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() OpenGLES2Renderer::~OpenGLES2Renderer()
{ {
SDL_DestroySurface(m_renderedImage); SDL_DestroySurface(m_renderedImage);
glDeleteProgram(m_shaderProgram); glDeleteProgram(m_shaderProgram);
SDL_GL_DestroyContext(m_context);
} }
void OpenGLES2Renderer::PushLights(const SceneLight* lightsArray, size_t count) void OpenGLES2Renderer::PushLights(const SceneLight* lightsArray, size_t count)
@ -332,12 +320,7 @@ void OpenGLES2Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture*
); );
} }
bool isPowerOfTwo(int x) bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUi)
{
return (x & (x - 1)) == 0;
}
bool UploadTexture(SDL_Surface* source, GLuint& outTexId)
{ {
SDL_Surface* surf = source; SDL_Surface* surf = source;
if (source->format != SDL_PIXELFORMAT_RGBA32) { if (source->format != SDL_PIXELFORMAT_RGBA32) {
@ -351,17 +334,23 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId)
glBindTexture(GL_TEXTURE_2D, 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); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
if (!isPowerOfTwo(surf->w) || !isPowerOfTwo(surf->h)) { if (isUi) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 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_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
} }
else { else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 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_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_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); glGenerateMipmap(GL_TEXTURE_2D);
} }
@ -372,7 +361,7 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId)
return true; return true;
} }
Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture) Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
{ {
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface); auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
@ -382,7 +371,7 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
if (tex.texture == texture) { if (tex.texture == texture) {
if (tex.version != texture->m_version) { if (tex.version != texture->m_version) {
glDeleteTextures(1, &tex.glTextureId); glDeleteTextures(1, &tex.glTextureId);
if (UploadTexture(surface->m_surface, tex.glTextureId)) { if (UploadTexture(surface->m_surface, tex.glTextureId, isUi)) {
tex.version = texture->m_version; tex.version = texture->m_version;
} }
} }
@ -391,7 +380,7 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
} }
GLuint texId; GLuint texId;
if (!UploadTexture(surface->m_surface, texId)) { if (!UploadTexture(surface->m_surface, texId, isUi)) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
@ -466,30 +455,11 @@ Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* mesh
return (Uint32) (m_meshs.size() - 1); return (Uint32) (m_meshs.size() - 1);
} }
void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{
OpenGLES2Desc::GetDesc(halDesc, helDesc);
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;
}
}
}
const char* OpenGLES2Renderer::GetName()
{
return OpenGLES2Desc::GetName();
}
HRESULT OpenGLES2Renderer::BeginFrame() HRESULT OpenGLES2Renderer::BeginFrame()
{ {
m_dirty = true; m_dirty = true;
glEnable(GL_CULL_FACE);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
@ -518,12 +488,11 @@ HRESULT OpenGLES2Renderer::BeginFrame()
} }
for (int i = 0; i < lightCount; ++i) { for (int i = 0; i < lightCount; ++i) {
std::string base = "u_lights[" + std::to_string(i) + "]"; glUniform4fv(u_lightLocs[i][0], 1, lightData[i].color);
glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".color").c_str()), 1, lightData[i].color); glUniform4fv(u_lightLocs[i][1], 1, lightData[i].position);
glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".position").c_str()), 1, lightData[i].position); glUniform4fv(u_lightLocs[i][2], 1, lightData[i].direction);
glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".direction").c_str()), 1, lightData[i].direction);
} }
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), lightCount); glUniform1i(m_lightCountLoc, lightCount);
return DD_OK; return DD_OK;
} }
@ -545,52 +514,49 @@ void OpenGLES2Renderer::SubmitDraw(
{ {
auto& mesh = m_meshs[meshId]; auto& mesh = m_meshs[meshId];
glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &modelViewMatrix[0][0]); glUniformMatrix4fv(m_modelViewMatrixLoc, 1, GL_FALSE, &modelViewMatrix[0][0]);
glUniformMatrix3fv(glGetUniformLocation(m_shaderProgram, "u_normalMatrix"), 1, GL_FALSE, &normalMatrix[0][0]); glUniformMatrix3fv(m_normalMatrixLoc, 1, GL_FALSE, &normalMatrix[0][0]);
glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"), 1, GL_FALSE, &m_projection[0][0]); glUniformMatrix4fv(m_projectionMatrixLoc, 1, GL_FALSE, &m_projection[0][0]);
glUniform4f( glUniform4f(
glGetUniformLocation(m_shaderProgram, "u_color"), m_colorLoc,
appearance.color.r / 255.0f, appearance.color.r / 255.0f,
appearance.color.g / 255.0f, appearance.color.g / 255.0f,
appearance.color.b / 255.0f, appearance.color.b / 255.0f,
appearance.color.a / 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) { if (appearance.textureId != NO_TEXTURE_ID) {
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1); glUniform1i(m_useTextureLoc, 1);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textures[appearance.textureId].glTextureId); glBindTexture(GL_TEXTURE_2D, m_textures[appearance.textureId].glTextureId);
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); glUniform1i(m_textureLoc, 0);
} }
else { else {
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 0); glUniform1i(m_useTextureLoc, 0);
} }
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboPositions); glBindBuffer(GL_ARRAY_BUFFER, mesh.vboPositions);
GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); glEnableVertexAttribArray(m_posLoc);
glEnableVertexAttribArray(posLoc); glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboNormals); glBindBuffer(GL_ARRAY_BUFFER, mesh.vboNormals);
GLint normLoc = glGetAttribLocation(m_shaderProgram, "a_normal"); glEnableVertexAttribArray(m_normLoc);
glEnableVertexAttribArray(normLoc); glVertexAttribPointer(m_normLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glVertexAttribPointer(normLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord");
if (appearance.textureId != NO_TEXTURE_ID) { if (appearance.textureId != NO_TEXTURE_ID) {
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboTexcoords); glBindBuffer(GL_ARRAY_BUFFER, mesh.vboTexcoords);
glEnableVertexAttribArray(texLoc); glEnableVertexAttribArray(m_texLoc);
glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
} }
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo);
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr); glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr);
glDisableVertexAttribArray(normLoc); glDisableVertexAttribArray(m_normLoc);
glDisableVertexAttribArray(texLoc); glDisableVertexAttribArray(m_texLoc);
} }
HRESULT OpenGLES2Renderer::FinalizeFrame() HRESULT OpenGLES2Renderer::FinalizeFrame()
@ -607,7 +573,9 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v
m_width = width; m_width = width;
m_height = height; m_height = height;
m_viewportTransform = viewportTransform; 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); m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
glViewport(0, 0, m_width, m_height); glViewport(0, 0, m_width, m_height);
} }
@ -640,13 +608,13 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c
float color[] = {1.0f, 1.0f, 1.0f, 1.0f}; float color[] = {1.0f, 1.0f, 1.0f, 1.0f};
float blank[] = {0.0f, 0.0f, 0.0f, 0.0f}; float blank[] = {0.0f, 0.0f, 0.0f, 0.0f};
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].color"), 1, color); glUniform4fv(u_lightLocs[0][0], 1, color);
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].position"), 1, blank); glUniform4fv(u_lightLocs[0][1], 1, blank);
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].direction"), 1, blank); glUniform4fv(u_lightLocs[0][2], 1, blank);
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), 1); glUniform1i(m_lightCountLoc, 1);
glUniform4f(glGetUniformLocation(m_shaderProgram, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f); glUniform4f(m_colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(m_shaderProgram, "u_shininess"), 0.0f); glUniform1f(m_shinLoc, 0.0f);
const GLES2TextureCacheEntry& texture = m_textures[textureId]; const GLES2TextureCacheEntry& texture = m_textures[textureId];
float scaleX = static_cast<float>(dstRect.w) / srcRect.w; float scaleX = static_cast<float>(dstRect.w) / srcRect.w;
@ -667,19 +635,19 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c
modelView 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}}; 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); 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); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glUniform1i(m_useTextureLoc, 1);
glBindTexture(GL_TEXTURE_2D, texture.glTextureId); glBindTexture(GL_TEXTURE_2D, texture.glTextureId);
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); glUniform1i(m_textureLoc, 0);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glScissor( glScissor(
@ -691,20 +659,18 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c
static_cast<int>(std::round(dstRect.h * m_viewportTransform.scale)) static_cast<int>(std::round(dstRect.h * m_viewportTransform.scale))
); );
GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position");
glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboPositions); glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboPositions);
glEnableVertexAttribArray(posLoc); glEnableVertexAttribArray(m_posLoc);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord");
glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboTexcoords); glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboTexcoords);
glEnableVertexAttribArray(texLoc); glEnableVertexAttribArray(m_texLoc);
glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiMeshCache.ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiMeshCache.ibo);
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_uiMeshCache.indices.size()), GL_UNSIGNED_SHORT, nullptr); glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_uiMeshCache.indices.size()), GL_UNSIGNED_SHORT, nullptr);
glDisableVertexAttribArray(texLoc); glDisableVertexAttribArray(m_texLoc);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }

View File

@ -203,49 +203,31 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
return nullptr; return nullptr;
} }
SDL_Window* window = DDWindow; if (!DDWindow) {
bool testWindow = false; SDL_Log("No window handler");
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);
}
return nullptr; 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) { if (!opaquePipeline.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for opaquePipeline"); SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for opaquePipeline");
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; 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) { if (!transparentPipeline.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for transparentPipeline"); SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for transparentPipeline");
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; 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) { if (!uiPipeline.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for uiPipeline"); SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for uiPipeline");
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
@ -257,9 +239,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
ScopedTransferBuffer uploadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &uploadBufferInfo)}; ScopedTransferBuffer uploadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &uploadBufferInfo)};
if (!uploadBuffer.ptr) { if (!uploadBuffer.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTransferBuffer filed for upload buffer (%s)", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTransferBuffer filed for upload buffer (%s)", SDL_GetError());
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
@ -273,9 +252,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
ScopedSampler sampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &samplerInfo)}; ScopedSampler sampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &samplerInfo)};
if (!sampler.ptr) { if (!sampler.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError());
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
@ -289,17 +265,9 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
ScopedSampler uiSampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &uiSamplerInfo)}; ScopedSampler uiSampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &uiSamplerInfo)};
if (!uiSampler.ptr) { if (!uiSampler.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError());
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
if (testWindow) {
SDL_ReleaseWindowFromGPUDevice(device.ptr, window);
SDL_DestroyWindow(window);
}
auto renderer = new Direct3DRMSDL3GPURenderer( auto renderer = new Direct3DRMSDL3GPURenderer(
width, width,
height, height,
@ -383,9 +351,7 @@ Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
{ {
SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.vertexBuffer); SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.vertexBuffer);
SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.indexBuffer); SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.indexBuffer);
if (DDWindow) { SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow);
SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow);
}
if (m_downloadBuffer) { if (m_downloadBuffer) {
SDL_ReleaseGPUTransferBuffer(m_device, m_downloadBuffer); SDL_ReleaseGPUTransferBuffer(m_device, m_downloadBuffer);
} }
@ -533,7 +499,7 @@ SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface*
return texptr; return texptr;
} }
Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture) Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
{ {
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface); auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
@ -585,7 +551,7 @@ SDL3MeshCache Direct3DRMSDL3GPURenderer::UploadMesh(const MeshGroup& meshGroup)
meshGroup.vertices.size(), meshGroup.vertices.size(),
meshGroup.indices.data(), meshGroup.indices.data(),
meshGroup.indices.size(), meshGroup.indices.size(),
meshGroup.texture != nullptr, true,
finalVertices, finalVertices,
newIndices newIndices
); );
@ -712,24 +678,6 @@ Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGro
return (Uint32) (m_meshs.size() - 1); 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) void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNormalMatrix4x4)
{ {
for (int row = 0; row < 3; ++row) { for (int row = 0; row < 3; ++row) {
@ -857,10 +805,6 @@ void Direct3DRMSDL3GPURenderer::Resize(int width, int height, const ViewportTran
m_height = height; m_height = height;
m_viewportTransform = viewportTransform; m_viewportTransform = viewportTransform;
if (!DDWindow) {
return;
}
if (m_transferTexture) { if (m_transferTexture) {
SDL_ReleaseGPUTexture(m_device, m_transferTexture); SDL_ReleaseGPUTexture(m_device, m_transferTexture);
} }

View File

@ -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<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface); auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
@ -664,24 +664,6 @@ Uint32 Direct3DRMSoftwareRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGr
return (Uint32) (m_meshs.size() - 1); 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() HRESULT Direct3DRMSoftwareRenderer::BeginFrame()
{ {
if (!m_renderedImage || !SDL_LockSurface(m_renderedImage)) { if (!m_renderedImage || !SDL_LockSurface(m_renderedImage)) {

View File

@ -207,14 +207,18 @@ HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
return S_OK; return S_OK;
} }
void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMDesc* desc, GUID deviceGuid) void EnumDevice(
LPD3DENUMDEVICESCALLBACK cb,
void* ctx,
const char* name,
D3DDEVICEDESC* halDesc,
D3DDEVICEDESC* helDesc,
GUID deviceGuid
)
{ {
D3DDEVICEDESC halDesc = {}; char* deviceNameDup = SDL_strdup(name);
D3DDEVICEDESC helDesc = {};
desc->GetDesc(&halDesc, &helDesc);
char* deviceNameDup = SDL_strdup(desc->GetName());
char* deviceDescDup = SDL_strdup("Miniwin driver"); 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(deviceDescDup);
SDL_free(deviceNameDup); SDL_free(deviceNameDup);
} }

View File

@ -62,7 +62,7 @@ HRESULT FrameBufferImpl::Blt(
if (!surface) { if (!surface) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture()); Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture(), true);
SDL_Rect srcRect = SDL_Rect srcRect =
lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, surface->m_surface->w, surface->m_surface->h}; lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, surface->m_surface->w, surface->m_surface->h};
SDL_Rect dstRect = SDL_Rect dstRect =

View File

@ -26,19 +26,12 @@ struct Plane {
float d; float d;
}; };
class Direct3DRMDesc { class Direct3DRMRenderer : public IDirect3DDevice2 {
public:
virtual ~Direct3DRMDesc() {}
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
virtual const char* GetName() = 0;
};
class Direct3DRMRenderer : public IDirect3DDevice2, public Direct3DRMDesc {
public: public:
virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void PushLights(const SceneLight* vertices, size_t count) = 0;
virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0; virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0;
virtual void SetFrustumPlanes(const Plane* frustumPlanes) = 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; virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0;
int GetWidth() { return m_width; } int GetWidth() { return m_width; }
int GetHeight() { return m_height; } int GetHeight() { return m_height; }

View File

@ -18,10 +18,8 @@ class DirectX9Renderer : public Direct3DRMRenderer {
void PushLights(const SceneLight* lightsArray, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
void SetFrustumPlanes(const Plane* frustumPlanes) 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; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
void EnableTransparency() override; void EnableTransparency() override;
void SubmitDraw( void SubmitDraw(
@ -52,8 +50,21 @@ class DirectX9Renderer : public Direct3DRMRenderer {
inline static void DirectX9Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void DirectX9Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{ {
Direct3DRMRenderer* device = DirectX9Renderer::Create(640, 480); Direct3DRMRenderer* device = DirectX9Renderer::Create(640, 480);
if (device) { if (!device) {
EnumDevice(cb, ctx, device, DirectX9_GUID); return;
delete device;
} }
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);
} }

View File

@ -18,10 +18,8 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
void PushLights(const SceneLight* lightsArray, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
void SetFrustumPlanes(const Plane* frustumPlanes) 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; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
void EnableTransparency() override; void EnableTransparency() override;
void SubmitDraw( void SubmitDraw(
@ -57,8 +55,21 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{ {
Direct3DRMRenderer* device = OpenGL1Renderer::Create(640, 480); Direct3DRMRenderer* device = OpenGL1Renderer::Create(640, 480);
if (device) { if (!device) {
EnumDevice(cb, ctx, device, OpenGL1_GUID); return;
delete device;
} }
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);
} }

View File

@ -30,13 +30,7 @@ struct GLES2MeshCacheEntry {
GLuint ibo; GLuint ibo;
}; };
class OpenGLES2Desc : public Direct3DRMDesc { class OpenGLES2Renderer : public Direct3DRMRenderer {
public:
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override;
};
class OpenGLES2Renderer : public Direct3DRMRenderer, public OpenGLES2Desc {
public: public:
static Direct3DRMRenderer* Create(DWORD width, DWORD height); static Direct3DRMRenderer* Create(DWORD width, DWORD height);
OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram); OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram);
@ -45,10 +39,8 @@ class OpenGLES2Renderer : public Direct3DRMRenderer, public OpenGLES2Desc {
void PushLights(const SceneLight* lightsArray, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
void SetFrustumPlanes(const Plane* frustumPlanes) 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; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
void EnableTransparency() override; void EnableTransparency() override;
void SubmitDraw( void SubmitDraw(
@ -75,24 +67,55 @@ class OpenGLES2Renderer : public Direct3DRMRenderer, public OpenGLES2Desc {
std::vector<GLES2TextureCacheEntry> m_textures; std::vector<GLES2TextureCacheEntry> m_textures;
std::vector<GLES2MeshCacheEntry> m_meshs; std::vector<GLES2MeshCacheEntry> m_meshs;
D3DRMMATRIX4D m_projection; D3DRMMATRIX4D m_projection;
SDL_Surface* m_renderedImage; SDL_Surface* m_renderedImage = nullptr;
bool m_dirty = false; bool m_dirty = false;
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;
SDL_GLContext m_context; SDL_GLContext m_context;
GLuint m_shaderProgram; 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; ViewportTransform m_viewportTransform;
}; };
inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{ {
#ifdef __EMSCRIPTEN__ Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480);
// We need a static description since creating test windows, context changes etc. are not allowed if (!device) {
Direct3DRMDesc* desc = new OpenGLES2Desc(); return;
#else
Direct3DRMDesc* desc = OpenGLES2Renderer::Create(640, 480);
#endif
if (desc) {
EnumDevice(cb, ctx, desc, OpenGLES2_GUID);
delete desc;
} }
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);
} }

View File

@ -47,12 +47,10 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
static Direct3DRMRenderer* Create(DWORD width, DWORD height); static Direct3DRMRenderer* Create(DWORD width, DWORD height);
~Direct3DRMSDL3GPURenderer() override; ~Direct3DRMSDL3GPURenderer() override;
void PushLights(const SceneLight* vertices, size_t count) 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; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
void SetFrustumPlanes(const Plane* frustumPlanes) override; void SetFrustumPlanes(const Plane* frustumPlanes) override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
void EnableTransparency() override; void EnableTransparency() override;
void SubmitDraw( void SubmitDraw(
@ -122,8 +120,21 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
inline static void Direct3DRMSDL3GPU_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void Direct3DRMSDL3GPU_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{ {
Direct3DRMRenderer* device = Direct3DRMSDL3GPURenderer::Create(640, 480); Direct3DRMRenderer* device = Direct3DRMSDL3GPURenderer::Create(640, 480);
if (device) { if (!device) {
EnumDevice(cb, ctx, device, SDL3_GPU_GUID); return;
delete device;
} }
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);
} }

View File

@ -29,12 +29,10 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
Direct3DRMSoftwareRenderer(DWORD width, DWORD height); Direct3DRMSoftwareRenderer(DWORD width, DWORD height);
~Direct3DRMSoftwareRenderer() override; ~Direct3DRMSoftwareRenderer() override;
void PushLights(const SceneLight* vertices, size_t count) 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; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
void SetFrustumPlanes(const Plane* frustumPlanes) override; void SetFrustumPlanes(const Plane* frustumPlanes) override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
void EnableTransparency() override; void EnableTransparency() override;
void SubmitDraw( void SubmitDraw(
@ -87,8 +85,16 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
inline static void Direct3DRMSoftware_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void Direct3DRMSoftware_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{ {
Direct3DRMRenderer* device = nullptr; D3DDEVICEDESC halDesc = {};
device = new Direct3DRMSoftwareRenderer(640, 480);
EnumDevice(cb, ctx, device, SOFTWARE_GUID); D3DDEVICEDESC helDesc = {};
delete device; 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);
} }

View File

@ -56,4 +56,11 @@ HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context);
HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter); HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter);
void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMDesc* desc, GUID deviceGuid); void EnumDevice(
LPD3DENUMDEVICESCALLBACK cb,
void* ctx,
const char* name,
D3DDEVICEDESC* halDesc,
D3DDEVICEDESC* helDesc,
GUID deviceGuid
);

22
packaging/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
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)
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
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()

161
packaging/icons/isle.svg Normal file
View File

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="180"
height="180"
viewBox="0 0 180 180"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="isle_icon.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><title
id="title19">LEGO Island Icon</title><sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="px"
inkscape:zoom="3.2222222"
inkscape:cx="99.931034"
inkscape:cy="94.034483"
inkscape:window-width="2560"
inkscape:window-height="1371"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer2" /><defs
id="defs1" /><g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Sun"
style="display:inline"><circle
style="fill:#ffff00;fill-opacity:1;stroke-width:6.09858"
id="path1"
cx="16.087624"
cy="16.087624"
r="16.087624" /><g
id="g7"
inkscape:label="Rays"
transform="scale(6.0985759)"><path
style="fill:#ffff00;fill-opacity:1;stroke:#ffff00;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 1.512931,6.2456897 V 10.74569"
id="path2" /><path
style="fill:#ffff00;fill-opacity:1;stroke:#ffff00;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 10.922387,1.4939611 h -4.5"
id="path3" /><path
style="fill:#ffff00;fill-opacity:1;stroke:#ffff00;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 3.5838432,6.4674267 4.802595,10.158437"
id="path4" /><path
style="fill:#ffff00;fill-opacity:1;stroke:#ffff00;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 5.4215806,5.3718411 3.20707,2.1962729"
id="path6" /><path
style="fill:#ffff00;fill-opacity:1;stroke:#ffff00;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 6.3519773,3.3961872 3.6866627,1.23184"
id="path7" /></g></g><g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="House"
style="display:inline"><g
id="g11"
inkscape:label="Wall"
style="display:inline"
transform="scale(6.0985759)"><rect
style="fill:#ffff00;fill-opacity:1;stroke:#ffff00;stroke-width:1.31354;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect7"
width="21.557148"
height="2.960166"
x="5.2214251"
y="25.898151" /><rect
style="fill:#ffff00;fill-opacity:1;stroke:#ffff00;stroke-width:1.31354;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect9"
width="21.557148"
height="2.960166"
x="5.2214251"
y="13.077032" /><rect
style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:1.31354;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect10"
width="21.557148"
height="2.960166"
x="5.2214251"
y="21.624445" /><rect
style="fill:#0000ff;fill-opacity:1;stroke:#0000ff;stroke-width:1.31354;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect11"
width="21.557148"
height="2.960166"
x="5.2214251"
y="17.350739" /></g><g
id="g16"
inkscape:label="Window"
transform="scale(6.0985759)"><rect
style="display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.46119;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
id="rect12"
width="9.0243168"
height="11.312326"
x="11.487842"
y="13.257705" /><rect
style="fill:#00ffff;fill-opacity:1;stroke:#00ffff;stroke-width:0.498507;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect13"
width="3.3376997"
height="4.0214062"
x="11.928134"
y="13.989297" /><rect
style="fill:#00ffff;fill-opacity:1;stroke:#00ffff;stroke-width:0.498507;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect14"
width="3.3376997"
height="4.0214062"
x="16.719082"
y="13.989297" /><rect
style="fill:#00ffff;fill-opacity:1;stroke:#00ffff;stroke-width:0.547494;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect15"
width="3.288712"
height="4.9228497"
x="11.952628"
y="19.056892" /><rect
style="fill:#00ffff;fill-opacity:1;stroke:#00ffff;stroke-width:0.547494;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect16"
width="3.288712"
height="4.9228497"
x="16.743576"
y="19.056892" /></g></g><g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Roof"><g
id="g19"
inkscape:label="Antenna"
transform="scale(6.0985759)"><path
style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 21.510776,1.2025862 V 9.1163793"
id="path17" /><path
style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 18.363745,0.526459 6.294062,4.7971783"
id="path18" /><path
style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 18.99097,3.2200622 4.951565,3.7739605"
id="path19" /></g><path
style="display:inline;fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:3.04929;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 19.991237,75.943041 H 173.06023 L 150.40272,51.317332 h -7.63224 l -5.01561,6.189336 h -7.47182 l -4.27253,-8.057106 h -7.58654 l -4.56632,8.057106 h -8.00228 l -4.6922,-8.057106 h -7.441784 l -4.178171,8.057106 h -8.447839 l -3.904314,-8.057106 h -7.225947 l -4.362281,8.057106 h -8.610195 l -5.453345,-6.189336 h -6.082013 z"
id="path16"
sodipodi:nodetypes="ccccccccccccccccccccc"
inkscape:label="Roof" /></g><metadata
id="metadata19"><rdf:RDF><cc:Work
rdf:about=""><dc:title>LEGO Island Icon</dc:title><dc:date>2025-06-22</dc:date><cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc/4.0/" /></cc:Work><cc:License
rdf:about="http://creativecommons.org/licenses/by-nc/4.0/"><cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" /><cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" /><cc:prohibits
rdf:resource="http://creativecommons.org/ns#CommercialUse" /><cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata></svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -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")

25
packaging/linux/appimage/AppRun Executable file
View File

@ -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

100
packaging/linux/appimage/Build Executable file
View File

@ -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

View File

@ -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"
]
}
}
]
}

View File

@ -0,0 +1,38 @@
[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
Keywords[uk_UA]=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

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Freedesktop AppStream metadata file (https://www.freedesktop.org/software/appstream/docs) -->
<component type="desktop-application">
<id>@APP_ID@</id>
<name>@APP_NAME@</name>
<summary>@APP_SUMMARY@</summary>
<launchable type="desktop-id">@APP_ID@.desktop</launchable>
<branding>
<color type="primary">#e3000b</color>
</branding>
<developer id="io.github.isledecomp">
<name>Isle Decomp Team</name>
</developer>
<url type="homepage">https://github.com/isledecomp/isle-portable</url>
<url type="contribute">https://github.com/isledecomp/isle-portable/blob/master/CONTRIBUTING.md</url>
<url type="vcs-browser">https://github.com/isledecomp/isle-portable/tree/master</url>
<url type="bugtracker">https://github.com/isledecomp/isle-portable/issues</url>
<metadata_license>MIT</metadata_license>
<project_license>@APP_SPDX@</project_license>
<requires>
<display_length side="longest" compare="ge">640</display_length>
<internet>offline-only</internet>
</requires>
<recommends>
<memory>128</memory>
</recommends>
<supports>
<control>pointing</control>
<control>keyboard</control>
<control>gamepad</control>
</supports>
<description>
<p> 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.
</p>
<p>
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.
</p>
</description>
<content_rating type="oars-1.1">
<content_attribute id="violence-cartoon">mild</content_attribute>
<content_attribute id="language-humor">mild</content_attribute>
</content_rating>
<categories>
<category>Game</category>
<category>KidsGame</category>
<category>AdventureGame</category>
<category>Qt</category>
</categories>
<keywords>
<keyword translate="no">LEGO</keyword>
<keyword translate="no">lego</keyword>
<keyword>LEGO Island</keyword>
<!-- Translations sourced from https://www.pcgamingwiki.com/wiki/Lego_Island#Localizations -->
<keyword xml:lang="da">Panik på LEGO Øen</keyword>
<keyword xml:lang="de">Abenteuer auf der LEGO Insel</keyword>
<keyword xml:lang="es">La Isla LEGO</keyword>
<keyword xml:lang="fr">Aventures sur L'île LEGO</keyword>
<keyword xml:lang="it">Isola LEGO</keyword>
<keyword xml:lang="ja">レゴアイランドの大冒険</keyword>
<keyword xml:lang="ko">레고 아일랜드</keyword>
<keyword xml:lang="pt">A Ilha LEGO</keyword>
<keyword xml:lang="ru">Остров LEGO</keyword>
</keywords>
<releases>
<release version="@SEMANTIC_VERSION@" type="development" date="@BUILD_DATE@" />
</releases>
</component>