diff --git a/.editorconfig b/.editorconfig index c8d511ec..05d09a66 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,3 +14,8 @@ trim_trailing_whitespace = true [{CMakeLists.txt,*.cmake}] indent_size = 2 +insert_final_newline = true + +[*.{json,xml.in,desktop.in}] +indent_size = 2 +insert_final_newline = true diff --git a/.gitattributes b/.gitattributes index 232342c7..04926c6b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,7 @@ *.html text eol=lf diff=html *.mdp binary *.mak text eol=crlf +**/*.ico binary +**/*.png binary +**/*.svg text eol=lf +**/*.desktop text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64c447e5..c6124f37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,14 +33,14 @@ jobs: fail-fast: false matrix: include: - - { name: 'Linux', os: 'ubuntu-latest', dx5: false, config: true, build-type: 'Debug', linux: true, werror: true, clang-tidy: true } - - { name: 'MSVC (x86)', os: 'windows-latest', dx5: true, config: false, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_x86' } - - { name: 'MSVC (x64)', os: 'windows-latest', dx5: false, config: false, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64' } - - { name: 'MSVC (arm64)', os: 'windows-latest', dx5: false, config: false, build-type: 'Debug', msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_arm64' } - - { name: 'msys2 mingw32', os: 'windows-latest', dx5: false, config: false, build-type: 'Debug', mingw: true, werror: true, clang-tidy: true, msystem: 'mingw32', msys-env: 'mingw-w64-i686', shell: 'msys2 {0}' } - - { name: 'msys2 mingw64', os: 'windows-latest', dx5: false, config: true, build-type: 'Debug', mingw: true, werror: true, clang-tidy: true, msystem: 'mingw64', msys-env: 'mingw-w64-x86_64', shell: 'msys2 {0}' } - - { name: 'macOS', os: 'macos-latest', dx5: false, config: true, build-type: 'Debug', brew: true, werror: true, clang-tidy: false } - - { name: 'Emscripten', os: 'ubuntu-latest', dx5: false, config: false, build-type: 'Debug', emsdk: true, werror: true, clang-tidy: false, cmake-wrapper: 'emcmake' } + - { name: 'Linux', os: 'ubuntu-latest', dx5: false, config: true, linux: true, werror: true, clang-tidy: true } + - { name: 'MSVC (x86)', os: 'windows-latest', dx5: true, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_x86' } + - { name: 'MSVC (x64)', os: 'windows-latest', dx5: false, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64' } + - { name: 'MSVC (arm64)', os: 'windows-latest', dx5: false, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_arm64' } + - { name: 'msys2 mingw32', os: 'windows-latest', dx5: false, config: false, mingw: true, werror: true, clang-tidy: true, msystem: 'mingw32', msys-env: 'mingw-w64-i686', shell: 'msys2 {0}' } + - { name: 'msys2 mingw64', os: 'windows-latest', dx5: false, config: true, mingw: true, werror: true, clang-tidy: true, msystem: 'mingw64', msys-env: 'mingw-w64-x86_64', shell: 'msys2 {0}' } + - { name: 'macOS', os: 'macos-latest', dx5: false, config: true, brew: true, werror: true, clang-tidy: false } + - { name: 'Emscripten', os: 'ubuntu-latest', dx5: false, config: false, emsdk: true, werror: true, clang-tidy: false, cmake-wrapper: 'emcmake' } steps: - name: Setup vcvars if: ${{ !!matrix.msvc }} @@ -67,7 +67,7 @@ jobs: sudo apt-get install -y \ libx11-dev libxext-dev libxrandr-dev libxrender-dev libxfixes-dev libxi-dev libxinerama-dev \ libxcursor-dev libwayland-dev libxkbcommon-dev wayland-protocols libgl1-mesa-dev qt6-base-dev \ - libasound2-dev + libasound2-dev qt6-xdgdesktopportal-platformtheme - name: Install macOS dependencies (brew) if: ${{ matrix.brew }} @@ -89,11 +89,12 @@ jobs: - name: Configure (CMake) run: | ${{ matrix.cmake-wrapper || '' }} cmake -S . -B build -GNinja \ - -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ + -DCMAKE_BUILD_TYPE=Release \ -DISLE_USE_DX5=${{ !!matrix.dx5 }} \ - -DISLE_BUILD_CONFIG=${{ matrix.config }} \ + -DISLE_BUILD_CONFIG=${{ !!matrix.config }} \ -DENABLE_CLANG_TIDY=${{ !!matrix.clang-tidy }} \ -DISLE_WERROR=${{ !!matrix.werror }} \ + -DISLE_DEBUG=OFF \ -Werror=dev - name: Build (CMake) @@ -104,11 +105,64 @@ jobs: cd build cpack . + - name: Install linuxdeploy + if: ${{ matrix.linux }} + id: install-linuxdeploy + uses: miurahr/install-linuxdeploy-action@v1.8.0 + with: + plugins: qt appimage + + - name: Package (AppImage) + if: ${{ matrix.linux }} + run: | + cd build && \ + export LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH" && \ + NO_STRIP=1 ${{ steps.install-linuxdeploy.outputs.linuxdeploy }} \ + -p qt \ + -e isle \ + -e isle-config \ + -d packaging/linux/org.legoisland.Isle.desktop \ + -i icons/org.legoisland.Isle.svg \ + --custom-apprun=../packaging/linux/appimage/AppRun \ + --appdir packaging/linux/appimage/AppDir \ + --output appimage && \ + mv *.AppImage dist/ + - name: Upload Build Artifacts uses: actions/upload-artifact@v4 with: - name: '${{ matrix.name }} ${{ matrix.build-type }}' - path: build/dist/isle-* + name: '${{ matrix.name }}' + path: | + build/dist/isle-* + build/dist/*.AppImage + + flatpak: + name: "Flatpak (${{ matrix.arch }})" + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + os: ubuntu-latest + + - arch: aarch64 + os: ubuntu-22.04-arm + + container: + image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8 + options: --privileged + + steps: + - uses: actions/checkout@v4 + + - name: Build Flatpak + uses: flatpak/flatpak-github-actions/flatpak-builder@v6 + with: + bundle: org.legoisland.Isle.${{ matrix.arch }}.flatpak + manifest-path: packaging/linux/flatpak/org.legoisland.Isle.json + arch: ${{ matrix.arch }} ncc: name: 'C++' @@ -148,3 +202,30 @@ jobs: LEGO1/omni/src/video/flic.cpp \ $action_headers \ --path LEGO1/omni LEGO1/lego/legoomni + + release: + name: 'Release' + if: ${{ github.event_name == 'push' && github.ref_name == 'master' }} + runs-on: ubuntu-latest + needs: + - build + - flatpak + steps: + - name: Download All Artifacts + uses: actions/download-artifact@main + with: + pattern: "*" + path: Release + merge-multiple: true + + - name: Checkout uploadtool + uses: actions/checkout@v4 + with: + repository: 'probonopd/uploadtool' + path: 'uploadtool' + + - name: Upload Continuous Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ./uploadtool/upload.sh Release/* diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index ef8fdae2..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -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/* diff --git a/.gitignore b/.gitignore index 662466db..1610ba3d 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,9 @@ LEGO1.DLL # Kate - Text /.cache + +# Flatpak build cache +**/.flatpak-builder/ + +# Flatpak build dir +**/flatpak-build/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3100f3a1..03d406d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") include(CheckCXXSourceCompiles) include(CMakeDependentOption) include(CMakePushCheckState) +include(cmake/detectcpu.cmake) + +DetectTargetCPUArchitectures(ISLE_CPUS) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -624,7 +627,9 @@ else() include(GNUInstallDirs) endif() -set(ISLE_PACKAGE_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CACHE STRING "Platform name of the package") +string(REPLACE ";" "-" ISLE_CPUS_STRING "${ISLE_CPUS}") +string(TOLOWER "${ISLE_CPUS_STRING}" ISLE_CPUS_STRING) +set(ISLE_PACKAGE_NAME "${CMAKE_SYSTEM_NAME}-${ISLE_CPUS_STRING}" CACHE STRING "Platform name of the package") if(BUILD_SHARED_LIBS) list(APPEND install_extra_targets lego1) endif() @@ -643,8 +648,10 @@ if(EMSCRIPTEN) ) endif() +add_subdirectory(packaging) + set(CPACK_PACKAGE_DIRECTORY "dist") -set(CPACK_PACKAGE_FILE_NAME "isle-${PROJECT_VERSION}-${ISLE_PACKAGE_NAME}-${CMAKE_SYSTEM_PROCESSOR}") +set(CPACK_PACKAGE_FILE_NAME "isle-${PROJECT_VERSION}-${ISLE_PACKAGE_NAME}") if(MSVC) set(CPACK_GENERATOR ZIP) else() diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp index bd38e669..9030ae67 100644 --- a/CONFIG/config.cpp +++ b/CONFIG/config.cpp @@ -56,9 +56,17 @@ bool CConfigApp::InitInstance() return false; } m_device_enumerator = new LegoDeviceEnumerate; - if (m_device_enumerator->DoEnumerate()) { + SDL_Window* window = SDL_CreateWindow("Test window", 640, 480, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); + HWND hWnd; +#ifdef MINIWIN + hWnd = reinterpret_cast(window); +#else + hWnd = (HWND) SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); +#endif + if (m_device_enumerator->DoEnumerate(hWnd)) { return FALSE; } + SDL_DestroyWindow(window); m_driver = NULL; m_device = NULL; m_full_screen = TRUE; diff --git a/LEGO1/lego/legoomni/include/hospital.h b/LEGO1/lego/legoomni/include/hospital.h index 8629c2c2..be198776 100644 --- a/LEGO1/lego/legoomni/include/hospital.h +++ b/LEGO1/lego/legoomni/include/hospital.h @@ -123,7 +123,7 @@ class Hospital : public LegoWorld { MxLong m_copLedAnimTimer; // 0x11c MxLong m_pizzaLedAnimTimer; // 0x120 MxLong m_time; // 0x124 - undefined m_unk0x128; // 0x128 + MxBool m_exited; // 0x128 }; #endif // HOSPITAL_H diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 85917cbc..a3d6cd60 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -121,7 +121,7 @@ class LegoAnimPresenter : public MxVideoPresenter { void SubstituteVariables(); void FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); void FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); - void FUN_1006c8a0(MxBool p_bool); + void SetDisabled(MxBool p_disabled); LegoAnim* m_anim; // 0x64 LegoROI** m_roiMap; // 0x68 diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 5dd83221..4d27695c 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -79,7 +79,7 @@ class LegoBuildingManager : public MxCore { MxBool SwitchMove(LegoEntity* p_entity); MxBool SwitchMood(LegoEntity* p_entity); MxU32 GetAnimationId(LegoEntity* p_entity); - MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state); + MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood); MxBool DecrementCounter(LegoEntity* p_entity); MxBool DecrementCounter(MxS32 p_index); MxBool DecrementCounter(LegoBuildingInfo* p_data); diff --git a/LEGO1/lego/legoomni/include/legocharactermanager.h b/LEGO1/lego/legoomni/include/legocharactermanager.h index 2f9d9551..9b4c5313 100644 --- a/LEGO1/lego/legoomni/include/legocharactermanager.h +++ b/LEGO1/lego/legoomni/include/legocharactermanager.h @@ -88,7 +88,7 @@ class LegoCharacterManager { MxBool SwitchMove(LegoROI* p_roi); MxBool SwitchMood(LegoROI* p_roi); MxU32 GetAnimationId(LegoROI* p_roi); - MxU32 GetSoundId(LegoROI* p_roi, MxBool p_und); + MxU32 GetSoundId(LegoROI* p_roi, MxBool p_basedOnMood); MxU8 GetMood(LegoROI* p_roi); LegoROI* CreateAutoROI(const char* p_name, const char* p_lodName, MxBool p_createEntity); MxResult UpdateBoundingSphereAndBox(LegoROI* p_roi); diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index eecf6867..a6d9d9ee 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -28,7 +28,7 @@ class LegoEntity : public MxEntity { }; enum { - c_altBit1 = 0x01 + c_disabled = 0x01 }; LegoEntity() { Init(); } @@ -68,13 +68,13 @@ class LegoEntity : public MxEntity { // FUNCTION: BETA10 0x10013260 virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 - virtual void ClickSound(MxBool p_und); // vtable+0x34 - virtual void ClickAnimation(); // vtable+0x38 - virtual void SwitchVariant(); // vtable+0x3c - virtual void SwitchSound(); // vtable+0x40 - virtual void SwitchMove(); // vtable+0x44 - virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48 - virtual void SwitchMood(); // vtable+0x4c + virtual void ClickSound(MxBool p_basedOnMood); // vtable+0x34 + virtual void ClickAnimation(); // vtable+0x38 + virtual void SwitchVariant(); // vtable+0x3c + virtual void SwitchSound(); // vtable+0x40 + virtual void SwitchMove(); // vtable+0x44 + virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48 + virtual void SwitchMood(); // vtable+0x4c void FUN_10010c30(); void SetType(MxU8 p_type); @@ -83,7 +83,7 @@ class LegoEntity : public MxEntity { Mx3DPointFloat GetWorldUp(); Mx3DPointFloat GetWorldPosition(); - MxBool GetUnknown0x10IsSet(MxU8 p_flag) { return m_unk0x10 & p_flag; } + MxBool IsInteraction(MxU8 p_flag) { return m_interaction & p_flag; } MxBool GetFlagsIsSet(MxU8 p_flag) { return m_flags & p_flag; } MxU8 GetFlags() { return m_flags; } @@ -101,14 +101,14 @@ class LegoEntity : public MxEntity { void SetFlags(MxU8 p_flags) { m_flags = p_flags; } void SetFlag(MxU8 p_flag) { m_flags |= p_flag; } void ClearFlag(MxU8 p_flag) { m_flags &= ~p_flag; } - void SetUnknown0x10Flag(MxU8 p_flag) { m_unk0x10 |= p_flag; } - void ClearUnknown0x10Flag(MxU8 p_flag) { m_unk0x10 &= ~p_flag; } + void SetInteractionFlag(MxU8 p_flag) { m_interaction |= p_flag; } + void ClearInteractionFlag(MxU8 p_flag) { m_interaction &= ~p_flag; } protected: void Init(); void SetWorld(); - MxU8 m_unk0x10; // 0x10 + MxU8 m_interaction; // 0x10 MxU8 m_flags; // 0x11 Mx3DPointFloat m_worldLocation; // 0x14 Mx3DPointFloat m_worldDirection; // 0x28 diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index 0e72b539..3cdb5105 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -49,7 +49,7 @@ class LEGO1_EXPORT LegoPlantManager : public MxCore { MxBool SwitchMove(LegoEntity* p_entity); MxBool SwitchMood(LegoEntity* p_entity); MxU32 GetAnimationId(LegoEntity* p_entity); - MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state); + MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood); LegoPlantInfo* GetInfoArray(MxS32& p_length); LegoEntity* CreatePlant(MxS32 p_index, LegoWorld* p_world, LegoOmni::World p_worldId); MxBool DecrementCounter(LegoEntity* p_entity); diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index d46b8a49..8dae5d61 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -199,10 +199,10 @@ LegoBuildingInfo g_buildingInfoInit[16] = { MxU32 LegoBuildingManager::g_maxSound = 6; // GLOBAL: LEGO1 0x100f373c -MxU32 g_unk0x100f373c = 0x3c; +MxU32 g_buildingSoundIdOffset = 0x3c; // GLOBAL: LEGO1 0x100f3740 -MxU32 g_unk0x100f3740 = 0x42; +MxU32 g_buildingSoundIdMoodOffset = 0x42; // clang-format off // GLOBAL: LEGO1 0x100f3788 @@ -227,6 +227,8 @@ LegoBuildingInfo g_buildingInfo[16]; // GLOBAL: LEGO1 0x100f3748 MxS32 LegoBuildingManager::g_maxMove[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0}; +#define HAUS1_INDEX 12 + // FUNCTION: LEGO1 0x1002f8b0 void LegoBuildingManager::configureLegoBuildingManager(MxS32 p_buildingManagerConfig) { @@ -392,6 +394,9 @@ MxResult LegoBuildingManager::Read(LegoStorage* p_storage) m_nextVariant = 0; } + // Bugfix: allow Pepper to change variant building after save game load + g_buildingInfo[HAUS1_INDEX].m_variant = g_buildingInfoVariants[m_nextVariant]; + result = SUCCESS; done: @@ -461,7 +466,7 @@ MxBool LegoBuildingManager::SwitchVariant(LegoEntity* p_entity) roi->SetVisibility(FALSE); info->m_variant = g_buildingInfoVariants[m_nextVariant]; - CreateBuilding(12, CurrentWorld()); + CreateBuilding(HAUS1_INDEX, CurrentWorld()); if (info->m_entity != NULL) { info->m_entity->GetROI()->SetVisibility(TRUE); @@ -548,7 +553,7 @@ MxU32 LegoBuildingManager::GetAnimationId(LegoEntity* p_entity) // FUNCTION: LEGO1 0x1002ff40 // FUNCTION: BETA10 0x10064398 -MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_state) +MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood) { LegoBuildingInfo* info = GetInfo(p_entity); @@ -556,12 +561,12 @@ MxU32 LegoBuildingManager::GetSoundId(LegoEntity* p_entity, MxBool p_state) return 0; } - if (p_state) { - return info->m_mood + g_unk0x100f3740; + if (p_basedOnMood) { + return info->m_mood + g_buildingSoundIdMoodOffset; } if (info != NULL) { - return info->m_sound + g_unk0x100f373c; + return info->m_sound + g_buildingSoundIdOffset; } return 0; diff --git a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp index 655b7da8..adf442eb 100644 --- a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp @@ -39,10 +39,10 @@ MxU32 g_characterAnimationId = 10; char* LegoCharacterManager::g_customizeAnimFile = NULL; // GLOBAL: LEGO1 0x100fc4d8 -MxU32 g_soundIdOffset = 50; +MxU32 g_characterSoundIdOffset = 50; // GLOBAL: LEGO1 0x100fc4dc -MxU32 g_soundIdMoodOffset = 66; +MxU32 g_characterSoundIdMoodOffset = 66; // GLOBAL: LEGO1 0x100fc4e8 MxU32 g_headTextureCounter = 0; @@ -933,16 +933,16 @@ MxU32 LegoCharacterManager::GetAnimationId(LegoROI* p_roi) // FUNCTION: LEGO1 0x10085140 // FUNCTION: BETA10 0x10076855 -MxU32 LegoCharacterManager::GetSoundId(LegoROI* p_roi, MxBool p_und) +MxU32 LegoCharacterManager::GetSoundId(LegoROI* p_roi, MxBool p_basedOnMood) { LegoActorInfo* info = GetActorInfo(p_roi); - if (p_und) { - return info->m_mood + g_soundIdMoodOffset; + if (p_basedOnMood) { + return info->m_mood + g_characterSoundIdMoodOffset; } if (info != NULL) { - return info->m_sound + g_soundIdOffset; + return info->m_sound + g_characterSoundIdOffset; } else { return 0; diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index c5b57a17..a67f7e08 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -40,10 +40,10 @@ MxU8 g_counters[] = {1, 2, 2, 3}; MxU32 LegoPlantManager::g_maxSound = 8; // GLOBAL: LEGO1 0x100f3160 -MxU32 g_unk0x100f3160 = 56; +MxU32 g_plantSoundIdOffset = 56; // GLOBAL: LEGO1 0x100f3164 -MxU32 g_unk0x100f3164 = 66; +MxU32 g_plantSoundIdMoodOffset = 66; // GLOBAL: LEGO1 0x100f3168 MxS32 LegoPlantManager::g_maxMove[4] = {3, 3, 3, 3}; @@ -514,16 +514,16 @@ MxU32 LegoPlantManager::GetAnimationId(LegoEntity* p_entity) // FUNCTION: LEGO1 0x10026ba0 // FUNCTION: BETA10 0x100c61ba -MxU32 LegoPlantManager::GetSoundId(LegoEntity* p_entity, MxBool p_state) +MxU32 LegoPlantManager::GetSoundId(LegoEntity* p_entity, MxBool p_basedOnMood) { LegoPlantInfo* info = GetInfo(p_entity); - if (p_state) { - return (info->m_mood & 1) + g_unk0x100f3164; + if (p_basedOnMood) { + return (info->m_mood & 1) + g_plantSoundIdMoodOffset; } if (info != NULL) { - return info->m_sound + g_unk0x100f3160; + return info->m_sound + g_plantSoundIdOffset; } return 0; diff --git a/LEGO1/lego/legoomni/src/entity/legoactor.cpp b/LEGO1/lego/legoomni/src/entity/legoactor.cpp index 34ba9fb8..477bf529 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -20,7 +20,7 @@ LegoActor::LegoActor() m_frequencyFactor = 0.0f; m_sound = NULL; m_unk0x70 = 0.0f; - m_unk0x10 = 0; + m_interaction = 0; m_actorId = 0; } diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index 148d4c16..cce17c18 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -31,7 +31,7 @@ void LegoEntity::Init() m_roi = NULL; m_cameraFlag = FALSE; m_siFile = NULL; - m_unk0x10 = 0; + m_interaction = 0; m_flags = 0; m_actionType = Extra::ActionType::e_unknown; m_targetEntityId = -1; @@ -266,23 +266,23 @@ void LegoEntity::ParseAction(char* p_extra) // FUNCTION: LEGO1 0x10010f10 // FUNCTION: BETA10 0x1007ee87 -void LegoEntity::ClickSound(MxBool p_und) +void LegoEntity::ClickSound(MxBool p_basedOnMood) { - if (!GetUnknown0x10IsSet(c_altBit1)) { + if (!IsInteraction(c_disabled)) { MxU32 objectId = 0; const char* name = m_roi->GetName(); switch (m_type) { case e_actor: - objectId = CharacterManager()->GetSoundId(m_roi, p_und); + objectId = CharacterManager()->GetSoundId(m_roi, p_basedOnMood); break; case e_unk1: break; case e_plant: - objectId = PlantManager()->GetSoundId(this, p_und); + objectId = PlantManager()->GetSoundId(this, p_basedOnMood); break; case e_building: - objectId = BuildingManager()->GetSoundId(this, p_und); + objectId = BuildingManager()->GetSoundId(this, p_basedOnMood); break; } @@ -300,7 +300,7 @@ void LegoEntity::ClickSound(MxBool p_und) // FUNCTION: BETA10 0x1007f062 void LegoEntity::ClickAnimation() { - if (!GetUnknown0x10IsSet(c_altBit1)) { + if (!IsInteraction(c_disabled)) { MxU32 objectId = 0; MxDSAction action; const char* name = m_roi->GetName(); @@ -332,7 +332,7 @@ void LegoEntity::ClickAnimation() action.SetObjectId(objectId); action.AppendExtra(strlen(extra) + 1, extra); LegoOmni::GetInstance()->GetAnimationManager()->StartEntityAction(action, this); - m_unk0x10 |= c_altBit1; + m_interaction |= c_disabled; } } } diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 407fa3cb..4308717a 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -697,7 +697,7 @@ MxLong LegoNavController::Notify(MxParam& p_param) for (MxS32 i = 0; i < numPlants; i++) { LegoEntity* entity = plantMgr->CreatePlant(i, NULL, LegoOmni::e_act1); - if (entity != NULL && !entity->GetUnknown0x10IsSet(LegoEntity::c_altBit1)) { + if (entity != NULL && !entity->IsInteraction(LegoEntity::c_disabled)) { LegoROI* roi = entity->GetROI(); if (roi != NULL && roi->GetVisibility()) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 28642bab..c49b766e 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -793,7 +793,7 @@ void LegoAnimPresenter::StartingTickle() } FUN_10069b10(); - FUN_1006c8a0(TRUE); + SetDisabled(TRUE); if (m_unk0x78 == NULL) { if (fabs(m_action->GetDirection()[0]) >= 0.00000047683716F || @@ -1093,7 +1093,7 @@ void LegoAnimPresenter::EndAction() } } - FUN_1006c8a0(FALSE); + SetDisabled(FALSE); FUN_1006ab70(); VTable0x90(); @@ -1154,18 +1154,18 @@ void LegoAnimPresenter::VTable0x90() } // FUNCTION: LEGO1 0x1006c8a0 -void LegoAnimPresenter::FUN_1006c8a0(MxBool p_bool) +void LegoAnimPresenter::SetDisabled(MxBool p_disabled) { if (m_roiMapSize != 0 && m_roiMap != NULL) { for (MxU32 i = 1; i <= m_roiMapSize; i++) { LegoEntity* entity = m_roiMap[i]->GetEntity(); if (entity != NULL) { - if (p_bool) { - entity->SetUnknown0x10Flag(LegoEntity::c_altBit1); + if (p_disabled) { + entity->SetInteractionFlag(LegoEntity::c_disabled); } else { - entity->ClearUnknown0x10Flag(LegoEntity::c_altBit1); + entity->ClearInteractionFlag(LegoEntity::c_disabled); } } } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index a0173224..7e2f7e42 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -108,7 +108,7 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM goto done; } - if (deviceEnumerate.DoEnumerate() != SUCCESS) { + if (deviceEnumerate.DoEnumerate(hwnd) != SUCCESS) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "LegoDeviceEnumerate::DoEnumerate failed"); goto done; } diff --git a/LEGO1/lego/legoomni/src/worlds/hospital.cpp b/LEGO1/lego/legoomni/src/worlds/hospital.cpp index 66d22168..4a8fa8ac 100644 --- a/LEGO1/lego/legoomni/src/worlds/hospital.cpp +++ b/LEGO1/lego/legoomni/src/worlds/hospital.cpp @@ -48,7 +48,7 @@ Hospital::Hospital() m_flashingLeds = 0; m_copLedAnimTimer = 0; m_pizzaLedAnimTimer = 0; - m_unk0x128 = 0; + m_exited = FALSE; NotificationManager()->Register(this); } @@ -369,8 +369,8 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param) act1State = (Act1State*) GameState()->GetState("Act1State"); act1State->SetUnknown18(9); case HospitalState::e_exitToFront: - if (m_unk0x128 == 0) { - m_unk0x128 = 1; + if (m_exited == FALSE) { + m_exited = TRUE; m_destLocation = LegoGameState::e_hospitalExited; DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); @@ -378,8 +378,8 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param) } break; case HospitalState::e_exitToInfocenter: - if (m_unk0x128 == 0) { - m_unk0x128 = 1; + if (m_exited == FALSE) { + m_exited = TRUE; m_destLocation = LegoGameState::e_infomain; DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); @@ -412,8 +412,8 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param) m_interactionMode = 3; if (m_hospitalState->m_state == HospitalState::e_explainQuestShort) { - if (m_unk0x128 == 0) { - m_unk0x128 = 1; + if (m_exited == FALSE) { + m_exited = TRUE; TickleManager()->UnregisterClient(this); @@ -568,8 +568,8 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param) m_currentAction = HospitalScript::c_hho016cl_RunAnim; m_setWithCurrentAction = 1; } - else if (m_unk0x128 == 0) { - m_unk0x128 = 1; + else if (m_exited == FALSE) { + m_exited = TRUE; m_hospitalState->m_state = HospitalState::e_exitImmediately; m_destLocation = LegoGameState::e_infomain; @@ -589,8 +589,8 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param) m_currentAction = HospitalScript::c_hho016cl_RunAnim; m_setWithCurrentAction = 1; } - else if (m_unk0x128 == 0) { - m_unk0x128 = 1; + else if (m_exited == FALSE) { + m_exited = TRUE; m_hospitalState->m_state = HospitalState::e_exitImmediately; m_destLocation = LegoGameState::e_hospitalExited; diff --git a/LEGO1/mxdirectx/mxdirectxinfo.cpp b/LEGO1/mxdirectx/mxdirectxinfo.cpp index c5100031..639a2864 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.cpp +++ b/LEGO1/mxdirectx/mxdirectxinfo.cpp @@ -216,27 +216,33 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); } else { - newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); - result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); - + result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); if (result != DD_OK) { - BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); + BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result)); } else { - result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); + newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); + result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); if (result != DD_OK) { - BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); + BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); } else { - result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); + result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); if (result != DD_OK) { - BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); + BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); } else { - if (!newDevice.m_devices.size()) { - m_list.pop_back(); + result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); + + if (result != DD_OK) { + BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); + } + else { + if (!newDevice.m_devices.size()) { + m_list.pop_back(); + } } } } @@ -306,12 +312,14 @@ HRESULT MxDeviceEnumerate::EnumDevicesCallback( // FUNCTION: CONFIG 0x00401dc0 // FUNCTION: LEGO1 0x1009c6c0 // FUNCTION: BETA10 0x1011e3fa -int MxDeviceEnumerate::DoEnumerate() +int MxDeviceEnumerate::DoEnumerate(HWND hWnd) { if (IsInitialized()) { return -1; } + m_hWnd = hWnd; + HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this); if (ret != DD_OK) { BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret)); diff --git a/LEGO1/mxdirectx/mxdirectxinfo.h b/LEGO1/mxdirectx/mxdirectxinfo.h index a4ebef91..9bc480de 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.h +++ b/LEGO1/mxdirectx/mxdirectxinfo.h @@ -194,7 +194,7 @@ class MxDeviceEnumerate { MxDeviceEnumerate(); ~MxDeviceEnumerate(); - virtual int DoEnumerate(); // vtable+0x00 + virtual int DoEnumerate(HWND hWnd); // vtable+0x00 BOOL EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); HRESULT EnumDevicesCallback( @@ -242,6 +242,7 @@ class MxDeviceEnumerate { protected: list m_list; // 0x04 unsigned char m_initialized; // 0x10 + HWND m_hWnd; }; // TEMPLATE: BETA10 0x1011c1b0 diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index 6c93a0e7..c2886ebe 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -926,7 +926,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( transparentColor = RGB555_CREATE(0x1f, 0, 0x1f); break; default: - transparentColor = RGB8888_CREATE(0xff, 0, 0xff, 0); + transparentColor = RGB8888_CREATE(0, 0, 0, 0); break; } @@ -971,25 +971,11 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( surfacePtr += adjustedPitch; } - if (p_transparent && surface) { - DDCOLORKEY key; - key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = transparentColor; - surface->SetColorKey(DDCKEY_SRCBLT, &key); - } - surface->Unlock(ddsd.lpSurface); - if (p_transparent && surface) { + if (p_transparent && surface && bytesPerPixel != 4) { DDCOLORKEY key; - if (bytesPerPixel == 1) { - key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = 0; - } - else if (bytesPerPixel == 2) { - key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = RGB555_CREATE(0x1f, 0, 0x1f); - } - else { - key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = RGB8888_CREATE(0xff, 0, 0xff, 0); - } + key.dwColorSpaceLowValue = key.dwColorSpaceHighValue = transparentColor; surface->SetColorKey(DDCKEY_SRCBLT, &key); } } diff --git a/cmake/detectcpu.cmake b/cmake/detectcpu.cmake new file mode 100644 index 00000000..e0b6feae --- /dev/null +++ b/cmake/detectcpu.cmake @@ -0,0 +1,156 @@ +function(DetectTargetCPUArchitectures DETECTED_ARCHS) + + set(known_archs EMSCRIPTEN ARM32 ARM64 ARM64EC LOONGARCH64 POWERPC32 POWERPC64 X86 X64) + + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + foreach(known_arch IN LISTS known_archs) + set(CPU_${known_arch} "0" PARENT_SCOPE) + endforeach() + set(detected_archs) + foreach(osx_arch IN LISTS CMAKE_OSX_ARCHITECTURES) + if(osx_arch STREQUAL "x86_64") + set(CPU_X64 "1" PARENT_SCOPE) + list(APPEND detected_archs "X64") + elseif(osx_arch STREQUAL "arm64") + set(CPU_ARM64 "1" PARENT_SCOPE) + list(APPEND detected_archs "ARM64") + endif() + endforeach() + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) + return() + endif() + + set(detected_archs) + foreach(known_arch IN LISTS known_archs) + if(CPU_${known_arch}) + list(APPEND detected_archs "${known_arch}") + endif() + endforeach() + + if(detected_archs) + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) + return() + endif() + + set(arch_check_ARM32 "defined(__arm__) || defined(_M_ARM)") + set(arch_check_ARM64 "defined(__aarch64__) || defined(_M_ARM64)") + set(arch_check_ARM64EC "defined(_M_ARM64EC)") + set(arch_check_EMSCRIPTEN "defined(__EMSCRIPTEN__)") + set(arch_check_LOONGARCH64 "defined(__loongarch64)") + set(arch_check_POWERPC32 "(defined(__PPC__) || defined(__powerpc__)) && !defined(__powerpc64__)") + set(arch_check_POWERPC64 "defined(__PPC64__) || defined(__powerpc64__)") + set(arch_check_X86 "defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)") + set(arch_check_X64 "(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC)") + + set(src_vars "") + set(src_main "") + foreach(known_arch IN LISTS known_archs) + set(detected_${known_arch} "0") + + string(APPEND src_vars " +#if ${arch_check_${known_arch}} +#define ARCH_${known_arch} \"1\" +#else +#define ARCH_${known_arch} \"0\" +#endif +const char *arch_${known_arch} = \"INFO<${known_arch}=\" ARCH_${known_arch} \">\"; +") + string(APPEND src_main " + result += arch_${known_arch}[argc];") + endforeach() + + set(src_arch_detect "${src_vars} +int main(int argc, char *argv[]) { + int result = 0; + (void)argv; +${src_main} + return result; +}") + + if(CMAKE_C_COMPILER) + set(ext ".c") + elseif(CMAKE_CXX_COMPILER) + set(ext ".cpp") + else() + enable_language(C) + set(ext ".c") + endif() + set(path_src_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/detect_arch${ext}") + file(WRITE "${path_src_arch_detect}" "${src_arch_detect}") + set(path_dir_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/detect_arch") + set(path_bin_arch_detect "${path_dir_arch_detect}/bin") + + set(detected_archs) + + set(msg "Detecting Target CPU Architecture") + message(STATUS "${msg}") + + include(CMakePushCheckState) + + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + + cmake_push_check_state(RESET) + try_compile(CPU_CHECK_ALL + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/detect_arch" + SOURCES "${path_src_arch_detect}" + COPY_FILE "${path_bin_arch_detect}" + ) + cmake_pop_check_state() + if(NOT CPU_CHECK_ALL) + message(STATUS "${msg} - ") + message(WARNING "Failed to compile source detecting the target CPU architecture") + else() + set(re "INFO<([A-Z0-9]+)=([01])>") + file(STRINGS "${path_bin_arch_detect}" infos REGEX "${re}") + + foreach(info_arch_01 IN LISTS infos) + string(REGEX MATCH "${re}" A "${info_arch_01}") + if(NOT "${CMAKE_MATCH_1}" IN_LIST known_archs) + message(WARNING "Unknown architecture: \"${CMAKE_MATCH_1}\"") + continue() + endif() + set(arch "${CMAKE_MATCH_1}") + set(arch_01 "${CMAKE_MATCH_2}") + set(detected_${arch} "${arch_01}") + endforeach() + + foreach(known_arch IN LISTS known_archs) + if(detected_${known_arch}) + list(APPEND detected_archs ${known_arch}) + endif() + endforeach() + endif() + + if(detected_archs) + foreach(known_arch IN LISTS known_archs) + set("CPU_${known_arch}" "${detected_${known_arch}}" CACHE BOOL "Detected architecture ${known_arch}") + endforeach() + message(STATUS "${msg} - ${detected_archs}") + else() + include(CheckCSourceCompiles) + cmake_push_check_state(RESET) + foreach(known_arch IN LISTS known_archs) + if(NOT detected_archs) + set(cache_variable "CPU_${known_arch}") + set(test_src " + int main(int argc, char *argv[]) { + #if ${arch_check_${known_arch}} + return 0; + #else + choke + #endif + } + ") + check_c_source_compiles("${test_src}" "${cache_variable}") + if(${cache_variable}) + set(CPU_${known_arch} "1" CACHE BOOL "Detected architecture ${known_arch}") + set(detected_archs ${known_arch}) + else() + set(CPU_${known_arch} "0" CACHE BOOL "Detected architecture ${known_arch}") + endif() + endif() + endforeach() + cmake_pop_check_state() + endif() + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) +endfunction() diff --git a/miniwin/src/d3drm/backends/directx9/renderer.cpp b/miniwin/src/d3drm/backends/directx9/renderer.cpp index 15d13594..5917cd07 100644 --- a/miniwin/src/d3drm/backends/directx9/renderer.cpp +++ b/miniwin/src/d3drm/backends/directx9/renderer.cpp @@ -76,7 +76,7 @@ void DirectX9Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* ); } -Uint32 DirectX9Renderer::GetTextureId(IDirect3DRMTexture* iTexture) +Uint32 DirectX9Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -216,24 +216,6 @@ Uint32 DirectX9Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshG return static_cast(m_meshs.size() - 1); } -void DirectX9Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - halDesc->dcmColorModel = D3DCOLORMODEL::RGB; - halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - halDesc->dwDeviceZBufferBitDepth = DDBD_24; - 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() { return Actual_BeginFrame(); diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index cd60aaa6..fb7fccd4 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -28,40 +28,25 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); - SDL_Window* window = DDWindow; - bool testWindow = false; - if (!window) { - window = SDL_CreateWindow("OpenGL 1.1 test", width, height, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); - if (!window) { - SDL_Log("SDL_CreateWindow: %s", SDL_GetError()); - return nullptr; - } - testWindow = true; - } - - SDL_GLContext context = SDL_GL_CreateContext(window); - if (!context) { - SDL_Log("SDL_GL_CreateContext: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } + if (!DDWindow) { + SDL_Log("No window handler"); return nullptr; } - if (!SDL_GL_MakeCurrent(window, context)) { + SDL_GLContext context = SDL_GL_CreateContext(DDWindow); + if (!context) { + SDL_Log("SDL_GL_CreateContext: %s", SDL_GetError()); + return nullptr; + } + + if (!SDL_GL_MakeCurrent(DDWindow, context)) { + SDL_GL_DestroyContext(context); SDL_Log("SDL_GL_MakeCurrent: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } GL11_InitState(); - if (testWindow) { - SDL_DestroyWindow(window); - } - return new OpenGL1Renderer(width, height, context); } @@ -78,6 +63,7 @@ OpenGL1Renderer::OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext contex OpenGL1Renderer::~OpenGL1Renderer() { SDL_DestroySurface(m_renderedImage); + SDL_GL_DestroyContext(m_context); } void OpenGL1Renderer::PushLights(const SceneLight* lightsArray, size_t count) @@ -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(iTexture); auto surface = static_cast(texture->m_surface); @@ -265,24 +251,6 @@ Uint32 OpenGL1Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGr return (Uint32) (m_meshs.size() - 1); } -void OpenGL1Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - halDesc->dcmColorModel = D3DCOLORMODEL::RGB; - halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - halDesc->dwDeviceZBufferBitDepth = DDBD_24; - 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() { GL11_BeginFrame((Matrix4x4*) &m_projection[0][0]); diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp index 1f7db967..6695da81 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp @@ -40,25 +40,18 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_Window* window = DDWindow; - bool testWindow = false; - if (!window) { - window = SDL_CreateWindow("OpenGL ES 2.0 test", width, height, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); - testWindow = true; - } - - SDL_GLContext context = SDL_GL_CreateContext(window); - if (!context) { - if (testWindow) { - SDL_DestroyWindow(window); - } + if (!DDWindow) { + SDL_Log("No window handler"); return nullptr; } - if (!SDL_GL_MakeCurrent(window, context)) { - if (testWindow) { - SDL_DestroyWindow(window); - } + SDL_GLContext context = SDL_GL_CreateContext(DDWindow); + if (!context) { + return nullptr; + } + + if (!SDL_GL_MakeCurrent(DDWindow, context)) { + SDL_GL_DestroyContext(context); return nullptr; } @@ -174,31 +167,9 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) glDeleteShader(vs); glDeleteShader(fs); - if (testWindow) { - SDL_DestroyWindow(window); - } - 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 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) : m_context(context), m_shaderProgram(shaderProgram) { - m_width = width; - m_height = height; m_virtualWidth = width; m_virtualHeight = height; - m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32); + ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f}; + Resize(width, height, viewportTransform); m_uiMesh.vertices = { {{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}}, @@ -282,12 +252,30 @@ OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext co }; m_uiMesh.indices = {0, 1, 2, 0, 2, 3}; m_uiMeshCache = GLES2UploadMesh(m_uiMesh, true); + m_posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); + m_normLoc = glGetAttribLocation(m_shaderProgram, "a_normal"); + m_texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); + m_colorLoc = glGetUniformLocation(m_shaderProgram, "u_color"); + m_shinLoc = glGetUniformLocation(m_shaderProgram, "u_shininess"); + m_lightCountLoc = glGetUniformLocation(m_shaderProgram, "u_lightCount"); + m_useTextureLoc = glGetUniformLocation(m_shaderProgram, "u_useTexture"); + m_textureLoc = glGetUniformLocation(m_shaderProgram, "u_texture"); + for (int i = 0; i < 3; ++i) { + std::string base = "u_lights[" + std::to_string(i) + "]"; + u_lightLocs[i][0] = glGetUniformLocation(m_shaderProgram, (base + ".color").c_str()); + u_lightLocs[i][1] = glGetUniformLocation(m_shaderProgram, (base + ".position").c_str()); + u_lightLocs[i][2] = glGetUniformLocation(m_shaderProgram, (base + ".direction").c_str()); + } + m_modelViewMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"); + m_normalMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_normalMatrix"); + m_projectionMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"); } OpenGLES2Renderer::~OpenGLES2Renderer() { SDL_DestroySurface(m_renderedImage); glDeleteProgram(m_shaderProgram); + SDL_GL_DestroyContext(m_context); } void OpenGLES2Renderer::PushLights(const SceneLight* lightsArray, size_t count) @@ -332,12 +320,7 @@ void OpenGLES2Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* ); } -bool isPowerOfTwo(int x) -{ - return (x & (x - 1)) == 0; -} - -bool UploadTexture(SDL_Surface* source, GLuint& outTexId) +bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUi) { SDL_Surface* surf = source; if (source->format != SDL_PIXELFORMAT_RGBA32) { @@ -351,17 +334,23 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId) glBindTexture(GL_TEXTURE_2D, outTexId); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); - if (!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_T, GL_CLAMP_TO_EDGE); 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 { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if (strstr((const char*) glGetString(GL_EXTENSIONS), "GL_EXT_texture_filter_anisotropic")) { + GLfloat maxAniso = 0.0f; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); + GLfloat desiredAniso = fminf(8.0f, maxAniso); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, desiredAniso); + } glGenerateMipmap(GL_TEXTURE_2D); } @@ -372,7 +361,7 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId) return true; } -Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture) +Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -382,7 +371,7 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture) if (tex.texture == texture) { if (tex.version != texture->m_version) { glDeleteTextures(1, &tex.glTextureId); - if (UploadTexture(surface->m_surface, tex.glTextureId)) { + if (UploadTexture(surface->m_surface, tex.glTextureId, isUi)) { tex.version = texture->m_version; } } @@ -391,7 +380,7 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture) } GLuint texId; - if (!UploadTexture(surface->m_surface, texId)) { + if (!UploadTexture(surface->m_surface, texId, isUi)) { return NO_TEXTURE_ID; } @@ -466,30 +455,11 @@ Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* mesh 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() { m_dirty = true; + glEnable(GL_CULL_FACE); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); @@ -518,12 +488,11 @@ HRESULT OpenGLES2Renderer::BeginFrame() } for (int i = 0; i < lightCount; ++i) { - std::string base = "u_lights[" + std::to_string(i) + "]"; - glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".color").c_str()), 1, lightData[i].color); - glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".position").c_str()), 1, lightData[i].position); - glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".direction").c_str()), 1, lightData[i].direction); + glUniform4fv(u_lightLocs[i][0], 1, lightData[i].color); + glUniform4fv(u_lightLocs[i][1], 1, lightData[i].position); + glUniform4fv(u_lightLocs[i][2], 1, lightData[i].direction); } - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), lightCount); + glUniform1i(m_lightCountLoc, lightCount); return DD_OK; } @@ -545,52 +514,49 @@ void OpenGLES2Renderer::SubmitDraw( { auto& mesh = m_meshs[meshId]; - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &modelViewMatrix[0][0]); - glUniformMatrix3fv(glGetUniformLocation(m_shaderProgram, "u_normalMatrix"), 1, GL_FALSE, &normalMatrix[0][0]); - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"), 1, GL_FALSE, &m_projection[0][0]); + glUniformMatrix4fv(m_modelViewMatrixLoc, 1, GL_FALSE, &modelViewMatrix[0][0]); + glUniformMatrix3fv(m_normalMatrixLoc, 1, GL_FALSE, &normalMatrix[0][0]); + glUniformMatrix4fv(m_projectionMatrixLoc, 1, GL_FALSE, &m_projection[0][0]); glUniform4f( - glGetUniformLocation(m_shaderProgram, "u_color"), + m_colorLoc, appearance.color.r / 255.0f, appearance.color.g / 255.0f, appearance.color.b / 255.0f, appearance.color.a / 255.0f ); - glUniform1f(glGetUniformLocation(m_shaderProgram, "u_shininess"), appearance.shininess); + glUniform1f(m_shinLoc, appearance.shininess); if (appearance.textureId != NO_TEXTURE_ID) { - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1); + glUniform1i(m_useTextureLoc, 1); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_textures[appearance.textureId].glTextureId); - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); + glUniform1i(m_textureLoc, 0); } else { - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 0); + glUniform1i(m_useTextureLoc, 0); } glBindBuffer(GL_ARRAY_BUFFER, mesh.vboPositions); - GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); - glEnableVertexAttribArray(posLoc); - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_posLoc); + glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glBindBuffer(GL_ARRAY_BUFFER, mesh.vboNormals); - GLint normLoc = glGetAttribLocation(m_shaderProgram, "a_normal"); - glEnableVertexAttribArray(normLoc); - glVertexAttribPointer(normLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_normLoc); + glVertexAttribPointer(m_normLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); if (appearance.textureId != NO_TEXTURE_ID) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboTexcoords); - glEnableVertexAttribArray(texLoc); - glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_texLoc); + glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo); glDrawElements(GL_TRIANGLES, static_cast(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr); - glDisableVertexAttribArray(normLoc); - glDisableVertexAttribArray(texLoc); + glDisableVertexAttribArray(m_normLoc); + glDisableVertexAttribArray(m_texLoc); } HRESULT OpenGLES2Renderer::FinalizeFrame() @@ -607,7 +573,9 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v m_width = width; m_height = height; m_viewportTransform = viewportTransform; - SDL_DestroySurface(m_renderedImage); + if (m_renderedImage) { + SDL_DestroySurface(m_renderedImage); + } m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32); glViewport(0, 0, m_width, m_height); } @@ -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 blank[] = {0.0f, 0.0f, 0.0f, 0.0f}; - glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].color"), 1, color); - glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].position"), 1, blank); - glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].direction"), 1, blank); - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), 1); + glUniform4fv(u_lightLocs[0][0], 1, color); + glUniform4fv(u_lightLocs[0][1], 1, blank); + glUniform4fv(u_lightLocs[0][2], 1, blank); + glUniform1i(m_lightCountLoc, 1); - glUniform4f(glGetUniformLocation(m_shaderProgram, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1f(glGetUniformLocation(m_shaderProgram, "u_shininess"), 0.0f); + glUniform4f(m_colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1f(m_shinLoc, 0.0f); const GLES2TextureCacheEntry& texture = m_textures[textureId]; float scaleX = static_cast(dstRect.w) / srcRect.w; @@ -667,19 +635,19 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c modelView ); - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &modelView[0][0]); + glUniformMatrix4fv(m_modelViewMatrixLoc, 1, GL_FALSE, &modelView[0][0]); Matrix3x3 identity = {{1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {0.f, 0.f, 1.f}}; - glUniformMatrix3fv(glGetUniformLocation(m_shaderProgram, "u_normalMatrix"), 1, GL_FALSE, &identity[0][0]); + glUniformMatrix3fv(m_normalMatrixLoc, 1, GL_FALSE, &identity[0][0]); CreateOrthographicProjection((float) m_width, (float) m_height, projection); - glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"), 1, GL_FALSE, &projection[0][0]); + glUniformMatrix4fv(m_projectionMatrixLoc, 1, GL_FALSE, &projection[0][0]); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1); glActiveTexture(GL_TEXTURE0); + glUniform1i(m_useTextureLoc, 1); glBindTexture(GL_TEXTURE_2D, texture.glTextureId); - glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); + glUniform1i(m_textureLoc, 0); glEnable(GL_SCISSOR_TEST); glScissor( @@ -691,20 +659,18 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c static_cast(std::round(dstRect.h * m_viewportTransform.scale)) ); - GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboPositions); - glEnableVertexAttribArray(posLoc); - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_posLoc); + glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboTexcoords); - glEnableVertexAttribArray(texLoc); - glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_texLoc); + glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiMeshCache.ibo); glDrawElements(GL_TRIANGLES, static_cast(m_uiMeshCache.indices.size()), GL_UNSIGNED_SHORT, nullptr); - glDisableVertexAttribArray(texLoc); + glDisableVertexAttribArray(m_texLoc); glDisable(GL_SCISSOR_TEST); } diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp index 66c6b57e..98704c66 100644 --- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp +++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp @@ -203,49 +203,31 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) return nullptr; } - SDL_Window* window = DDWindow; - bool testWindow = false; - if (!window) { - window = SDL_CreateWindow("SDL_GPU test", width, height, SDL_WINDOW_HIDDEN); - if (!window) { - SDL_Log("SDL_CreateWindow: %s", SDL_GetError()); - return nullptr; - } - testWindow = true; - } - - if (!SDL_ClaimWindowForGPUDevice(device.ptr, window)) { - SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ClaimWindowForGPUDevice: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } + if (!DDWindow) { + SDL_Log("No window handler"); return nullptr; } - ScopedPipeline opaquePipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, true, true)}; + if (!SDL_ClaimWindowForGPUDevice(device.ptr, DDWindow)) { + SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ClaimWindowForGPUDevice: %s", SDL_GetError()); + return nullptr; + } + + ScopedPipeline opaquePipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, DDWindow, true, true)}; if (!opaquePipeline.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for opaquePipeline"); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } - ScopedPipeline transparentPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, true, false)}; + ScopedPipeline transparentPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, DDWindow, true, false)}; if (!transparentPipeline.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for transparentPipeline"); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } - ScopedPipeline uiPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, false, false)}; + ScopedPipeline uiPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, DDWindow, false, false)}; if (!uiPipeline.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for uiPipeline"); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } @@ -257,9 +239,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) ScopedTransferBuffer uploadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &uploadBufferInfo)}; if (!uploadBuffer.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTransferBuffer filed for upload buffer (%s)", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } @@ -273,9 +252,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) ScopedSampler sampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &samplerInfo)}; if (!sampler.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } @@ -289,17 +265,9 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) ScopedSampler uiSampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &uiSamplerInfo)}; if (!uiSampler.ptr) { SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError()); - if (testWindow) { - SDL_DestroyWindow(window); - } return nullptr; } - if (testWindow) { - SDL_ReleaseWindowFromGPUDevice(device.ptr, window); - SDL_DestroyWindow(window); - } - auto renderer = new Direct3DRMSDL3GPURenderer( width, height, @@ -383,9 +351,7 @@ Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer() { SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.vertexBuffer); SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.indexBuffer); - if (DDWindow) { - SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow); - } + SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow); if (m_downloadBuffer) { SDL_ReleaseGPUTransferBuffer(m_device, m_downloadBuffer); } @@ -533,7 +499,7 @@ SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* return texptr; } -Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture) +Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -585,7 +551,7 @@ SDL3MeshCache Direct3DRMSDL3GPURenderer::UploadMesh(const MeshGroup& meshGroup) meshGroup.vertices.size(), meshGroup.indices.data(), meshGroup.indices.size(), - meshGroup.texture != nullptr, + true, finalVertices, newIndices ); @@ -712,24 +678,6 @@ Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGro return (Uint32) (m_meshs.size() - 1); } -void Direct3DRMSDL3GPURenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - halDesc->dcmColorModel = D3DCOLORMODEL::RGB; - halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - halDesc->dwDeviceZBufferBitDepth = DDBD_32; // Todo add support for other depths - halDesc->dwDeviceRenderBitDepth = DDBD_32; - halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; - halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; - halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; - - memset(helDesc, 0, sizeof(D3DDEVICEDESC)); -} - -const char* Direct3DRMSDL3GPURenderer::GetName() -{ - return "SDL3 GPU HAL"; -} - void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNormalMatrix4x4) { for (int row = 0; row < 3; ++row) { @@ -857,10 +805,6 @@ void Direct3DRMSDL3GPURenderer::Resize(int width, int height, const ViewportTran m_height = height; m_viewportTransform = viewportTransform; - if (!DDWindow) { - return; - } - if (m_transferTexture) { SDL_ReleaseGPUTexture(m_device, m_transferTexture); } diff --git a/miniwin/src/d3drm/backends/software/renderer.cpp b/miniwin/src/d3drm/backends/software/renderer.cpp index 64adc93b..6b969769 100644 --- a/miniwin/src/d3drm/backends/software/renderer.cpp +++ b/miniwin/src/d3drm/backends/software/renderer.cpp @@ -554,7 +554,7 @@ void Direct3DRMSoftwareRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DR ); } -Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture) +Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) { auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -664,24 +664,6 @@ Uint32 Direct3DRMSoftwareRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGr return (Uint32) (m_meshs.size() - 1); } -void Direct3DRMSoftwareRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) -{ - memset(halDesc, 0, sizeof(D3DDEVICEDESC)); - - helDesc->dcmColorModel = D3DCOLORMODEL::RGB; - helDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - helDesc->dwDeviceZBufferBitDepth = DDBD_32; - helDesc->dwDeviceRenderBitDepth = DDBD_32; - helDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; - helDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; - helDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; -} - -const char* Direct3DRMSoftwareRenderer::GetName() -{ - return "Miniwin Emulation"; -} - HRESULT Direct3DRMSoftwareRenderer::BeginFrame() { if (!m_renderedImage || !SDL_LockSurface(m_renderedImage)) { diff --git a/miniwin/src/ddraw/ddraw.cpp b/miniwin/src/ddraw/ddraw.cpp index a79bd4c2..018fffd1 100644 --- a/miniwin/src/ddraw/ddraw.cpp +++ b/miniwin/src/ddraw/ddraw.cpp @@ -207,14 +207,18 @@ HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) return S_OK; } -void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMDesc* desc, GUID deviceGuid) +void EnumDevice( + LPD3DENUMDEVICESCALLBACK cb, + void* ctx, + const char* name, + D3DDEVICEDESC* halDesc, + D3DDEVICEDESC* helDesc, + GUID deviceGuid +) { - D3DDEVICEDESC halDesc = {}; - D3DDEVICEDESC helDesc = {}; - desc->GetDesc(&halDesc, &helDesc); - char* deviceNameDup = SDL_strdup(desc->GetName()); + char* deviceNameDup = SDL_strdup(name); char* deviceDescDup = SDL_strdup("Miniwin driver"); - cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &helDesc, ctx); + cb(&deviceGuid, deviceNameDup, deviceDescDup, halDesc, helDesc, ctx); SDL_free(deviceDescDup); SDL_free(deviceNameDup); } diff --git a/miniwin/src/ddraw/framebuffer.cpp b/miniwin/src/ddraw/framebuffer.cpp index eb21abef..9f4224fd 100644 --- a/miniwin/src/ddraw/framebuffer.cpp +++ b/miniwin/src/ddraw/framebuffer.cpp @@ -62,7 +62,7 @@ HRESULT FrameBufferImpl::Blt( if (!surface) { return DDERR_GENERIC; } - Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture()); + Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture(), true); SDL_Rect srcRect = lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, surface->m_surface->w, surface->m_surface->h}; SDL_Rect dstRect = diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h index ceaa3795..259b20eb 100644 --- a/miniwin/src/internal/d3drmrenderer.h +++ b/miniwin/src/internal/d3drmrenderer.h @@ -26,19 +26,12 @@ struct Plane { float d; }; -class Direct3DRMDesc { -public: - virtual ~Direct3DRMDesc() {} - virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0; - virtual const char* GetName() = 0; -}; - -class Direct3DRMRenderer : public IDirect3DDevice2, public Direct3DRMDesc { +class Direct3DRMRenderer : public IDirect3DDevice2 { public: virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0; virtual void SetFrustumPlanes(const Plane* frustumPlanes) = 0; - virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0; + virtual Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi = false) = 0; virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0; int GetWidth() { return m_width; } int GetHeight() { return m_height; } diff --git a/miniwin/src/internal/d3drmrenderer_directx9.h b/miniwin/src/internal/d3drmrenderer_directx9.h index b7badb03..900bbe03 100644 --- a/miniwin/src/internal/d3drmrenderer_directx9.h +++ b/miniwin/src/internal/d3drmrenderer_directx9.h @@ -18,10 +18,8 @@ class DirectX9Renderer : public Direct3DRMRenderer { void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -52,8 +50,21 @@ class DirectX9Renderer : public Direct3DRMRenderer { inline static void DirectX9Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { Direct3DRMRenderer* device = DirectX9Renderer::Create(640, 480); - if (device) { - EnumDevice(cb, ctx, device, DirectX9_GUID); - delete device; + if (!device) { + return; } + delete device; + + D3DDEVICEDESC halDesc = {}; + halDesc.dcmColorModel = D3DCOLOR_RGB; + halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + halDesc.dwDeviceZBufferBitDepth = DDBD_24; + halDesc.dwDeviceRenderBitDepth = DDBD_32; + halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + D3DDEVICEDESC helDesc = {}; + + EnumDevice(cb, ctx, "DirectX 9 HAL", &halDesc, &helDesc, DirectX9_GUID); } diff --git a/miniwin/src/internal/d3drmrenderer_opengl1.h b/miniwin/src/internal/d3drmrenderer_opengl1.h index d80621a5..58406709 100644 --- a/miniwin/src/internal/d3drmrenderer_opengl1.h +++ b/miniwin/src/internal/d3drmrenderer_opengl1.h @@ -18,10 +18,8 @@ class OpenGL1Renderer : public Direct3DRMRenderer { void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -57,8 +55,21 @@ class OpenGL1Renderer : public Direct3DRMRenderer { inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { Direct3DRMRenderer* device = OpenGL1Renderer::Create(640, 480); - if (device) { - EnumDevice(cb, ctx, device, OpenGL1_GUID); - delete device; + if (!device) { + return; } + delete device; + + D3DDEVICEDESC halDesc = {}; + halDesc.dcmColorModel = D3DCOLORMODEL::RGB; + halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + halDesc.dwDeviceZBufferBitDepth = DDBD_24; + halDesc.dwDeviceRenderBitDepth = DDBD_32; + halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + D3DDEVICEDESC helDesc = {}; + + EnumDevice(cb, ctx, "OpenGL 1.1 HAL", &halDesc, &helDesc, OpenGL1_GUID); } diff --git a/miniwin/src/internal/d3drmrenderer_opengles2.h b/miniwin/src/internal/d3drmrenderer_opengles2.h index 76192842..f5d62579 100644 --- a/miniwin/src/internal/d3drmrenderer_opengles2.h +++ b/miniwin/src/internal/d3drmrenderer_opengles2.h @@ -30,13 +30,7 @@ struct GLES2MeshCacheEntry { GLuint ibo; }; -class OpenGLES2Desc : public Direct3DRMDesc { -public: - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; -}; - -class OpenGLES2Renderer : public Direct3DRMRenderer, public OpenGLES2Desc { +class OpenGLES2Renderer : public Direct3DRMRenderer { public: static Direct3DRMRenderer* Create(DWORD width, DWORD height); 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 SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -75,24 +67,55 @@ class OpenGLES2Renderer : public Direct3DRMRenderer, public OpenGLES2Desc { std::vector m_textures; std::vector m_meshs; D3DRMMATRIX4D m_projection; - SDL_Surface* m_renderedImage; + SDL_Surface* m_renderedImage = nullptr; bool m_dirty = false; std::vector m_lights; SDL_GLContext m_context; 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; }; inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { -#ifdef __EMSCRIPTEN__ - // We need a static description since creating test windows, context changes etc. are not allowed - Direct3DRMDesc* desc = new OpenGLES2Desc(); -#else - Direct3DRMDesc* desc = OpenGLES2Renderer::Create(640, 480); -#endif - if (desc) { - EnumDevice(cb, ctx, desc, OpenGLES2_GUID); - delete desc; + Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480); + if (!device) { + return; } + + D3DDEVICEDESC halDesc = {}; + halDesc.dcmColorModel = D3DCOLOR_RGB; + halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + halDesc.dwDeviceZBufferBitDepth = DDBD_16; + halDesc.dwDeviceRenderBitDepth = DDBD_32; + halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + const char* extensions = (const char*) glGetString(GL_EXTENSIONS); + if (extensions) { + if (strstr(extensions, "GL_OES_depth24")) { + halDesc.dwDeviceZBufferBitDepth |= DDBD_24; + } + if (strstr(extensions, "GL_OES_depth32")) { + halDesc.dwDeviceZBufferBitDepth |= DDBD_32; + } + } + + delete device; + + D3DDEVICEDESC helDesc = {}; + + EnumDevice(cb, ctx, "OpenGL ES 2.0 HAL", &halDesc, &helDesc, OpenGLES2_GUID); } diff --git a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h index 25485b1f..02ec05d0 100644 --- a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h +++ b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h @@ -47,12 +47,10 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer { static Direct3DRMRenderer* Create(DWORD width, DWORD height); ~Direct3DRMSDL3GPURenderer() override; void PushLights(const SceneLight* vertices, size_t count) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -122,8 +120,21 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer { inline static void Direct3DRMSDL3GPU_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { Direct3DRMRenderer* device = Direct3DRMSDL3GPURenderer::Create(640, 480); - if (device) { - EnumDevice(cb, ctx, device, SDL3_GPU_GUID); - delete device; + if (!device) { + return; } + delete device; + + D3DDEVICEDESC halDesc = {}; + halDesc.dcmColorModel = D3DCOLOR_RGB; + halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + halDesc.dwDeviceZBufferBitDepth = DDBD_32; + halDesc.dwDeviceRenderBitDepth = DDBD_32; + halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + D3DDEVICEDESC helDesc = {}; + + EnumDevice(cb, ctx, "SDL3 GPU HAL", &halDesc, &helDesc, SDL3_GPU_GUID); } diff --git a/miniwin/src/internal/d3drmrenderer_software.h b/miniwin/src/internal/d3drmrenderer_software.h index 444a80a3..87715999 100644 --- a/miniwin/src/internal/d3drmrenderer_software.h +++ b/miniwin/src/internal/d3drmrenderer_software.h @@ -29,12 +29,10 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { Direct3DRMSoftwareRenderer(DWORD width, DWORD height); ~Direct3DRMSoftwareRenderer() override; void PushLights(const SceneLight* vertices, size_t count) override; - Uint32 GetTextureId(IDirect3DRMTexture* texture) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetFrustumPlanes(const Plane* frustumPlanes) override; - void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; - const char* GetName() override; HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( @@ -87,8 +85,16 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { inline static void Direct3DRMSoftware_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { - Direct3DRMRenderer* device = nullptr; - device = new Direct3DRMSoftwareRenderer(640, 480); - EnumDevice(cb, ctx, device, SOFTWARE_GUID); - delete device; + D3DDEVICEDESC halDesc = {}; + + D3DDEVICEDESC helDesc = {}; + helDesc.dcmColorModel = D3DCOLOR_RGB; + helDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; + helDesc.dwDeviceZBufferBitDepth = DDBD_32; + helDesc.dwDeviceRenderBitDepth = DDBD_32; + helDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; + helDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; + helDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; + + EnumDevice(cb, ctx, "Miniwin Emulation", &halDesc, &helDesc, SOFTWARE_GUID); } diff --git a/miniwin/src/internal/ddraw_impl.h b/miniwin/src/internal/ddraw_impl.h index 3faa9f89..4adfb4a5 100644 --- a/miniwin/src/internal/ddraw_impl.h +++ b/miniwin/src/internal/ddraw_impl.h @@ -56,4 +56,11 @@ HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context); HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter); -void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMDesc* desc, GUID deviceGuid); +void EnumDevice( + LPD3DENUMDEVICESCALLBACK cb, + void* ctx, + const char* name, + D3DDEVICEDESC* halDesc, + D3DDEVICEDESC* helDesc, + GUID deviceGuid +); diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt new file mode 100644 index 00000000..d6fc19f0 --- /dev/null +++ b/packaging/CMakeLists.txt @@ -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() diff --git a/packaging/icons/isle.svg b/packaging/icons/isle.svg new file mode 100644 index 00000000..d3f6dbf1 --- /dev/null +++ b/packaging/icons/isle.svg @@ -0,0 +1,161 @@ + + + +LEGO Island IconLEGO Island Icon2025-06-22 diff --git a/packaging/linux/CMakeLists.txt b/packaging/linux/CMakeLists.txt new file mode 100644 index 00000000..2ece9db8 --- /dev/null +++ b/packaging/linux/CMakeLists.txt @@ -0,0 +1,7 @@ +# Injects the required variables into the Desktop and MetaInfo files +configure_file(isledecomp.desktop.in "${APP_ID}.desktop" @ONLY) +configure_file(isledecomp.metainfo.xml.in "${APP_ID}.metainfo.xml" @ONLY) + +install(FILES "../icons/isle.svg" RENAME "${APP_ID}.svg" DESTINATION "share/icons/hicolor/scalable/apps") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${APP_ID}.desktop" DESTINATION "share/applications") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${APP_ID}.metainfo.xml" DESTINATION "share/metainfo") diff --git a/packaging/linux/appimage/AppRun b/packaging/linux/appimage/AppRun new file mode 100755 index 00000000..0da15db1 --- /dev/null +++ b/packaging/linux/appimage/AppRun @@ -0,0 +1,25 @@ +#!/bin/sh + +HERE="$(dirname "$(readlink -f "${0}")")" + +MAIN=$(grep -r "^Exec=.*" "$HERE"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1) + +# MAIN_BIN=$(find "$HERE/usr/bin" -name "$MAIN" | head -n 1) +MAIN_BIN="$HERE/usr/bin/isle-config" + +export PATH="${HERE}/usr/bin/":$PATH # Prefer bundled binaries + +export QT_QPA_PLATFORMTHEME=xdgdesktopportal # Use XDG filepicker for forward compatability +[ -z "$QT_PLUGIN_PATH" ] && export QT_PLUGIN_PATH=/usr/lib/qt6/plugins:/usr/lib64/qt6/plugins # Use system Qt theme, will fallback to the default one if unavailable + + +if [ ! -z $APPIMAGE ]; then + BINARY_NAME=$(basename "$ARGV0") + if [ -e "$HERE/usr/bin/$BINARY_NAME" ]; then + exec "$HERE/usr/bin/$BINARY_NAME" "$@" + else + exec "${MAIN_BIN}" "$@" + fi +else + exec "${MAIN_BIN}" "$@" +fi diff --git a/packaging/linux/appimage/Build b/packaging/linux/appimage/Build new file mode 100755 index 00000000..9cf0325c --- /dev/null +++ b/packaging/linux/appimage/Build @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +set -e + +export LD_LIBRARY_PATH="build/source/lib:$LD_LIBRARY_PATH" +[ -z "$QMAKE" ] && export QMAKE=/usr/lib/qt6/bin/qmake + +# Sets a directory that has to have a following structure: +# build +# ├── bin +# │   ├── isle +# │   └── isle-config +# └── lib +# ├── liblego1.so +# ├── libSDL3.so -> libSDL3.so.0 # Not important if available on the system +# ├── libSDL3.so.0 -> libSDL3.so.0.3.0 # Not important if available on the system +# └── libSDL3.so.0.3.0 # Not important if available on the system +# Can also be defined using --build=path +BUILD_SOURCE=source + +# Sets where AppRun for AppImage is, can also be defined using --apprun=path +APPRUN_SOURCE=AppRun + +# Sets where desktop file for AppImage is, can also be defined using --desktop-file=path +DESKTOP_FILE_SOURCE=isledecomp.desktop + +# You know the drill +ICON_SOURCE=../../icons/isle.svg + +cd $(dirname $0) + +clean(){ + echo "Deleting build directory" + rm -rf build +} + +download(){ + if [ ! -e "$1" ]; then + curl -Lo "$1" "$2" + fi +} + +prepare(){ + mkdir -p build/tools + mkdir -p build/assets + + download build/tools/appimagetool.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$(uname -m).AppImage + chmod u+x build/tools/appimagetool.AppImage + + download build/tools/linuxdeploy.AppImage https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-$(uname -m).AppImage + chmod u+x build/tools/linuxdeploy.AppImage + + download build/tools/linuxdeploy-plugin-qt.AppImage https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/latest/download/linuxdeploy-plugin-qt-$(uname -m).AppImage + chmod u+x build/tools/linuxdeploy-plugin-qt.AppImage + + if [ ! -f "build/assets/isledecomp.desktop" ]; then + cp $DESKTOP_FILE_SOURCE build/assets/isledecomp.desktop + cp $APPRUN_SOURCE build/assets/AppRun + cp ../../icons/isle.svg build/assets/isle.svg + fi + + if [ ! -d "build/source" ]; then + cp -r $BUILD_SOURCE build/source + fi +} + +compile(){ + NO_STRIP=1 build/tools/linuxdeploy.AppImage \ + --plugin qt \ + -e build/source/bin/isle \ + -e build/source/bin/isle-config \ + -d build/assets/isledecomp.desktop \ + -i build/assets/isle.svg \ + --custom-apprun=AppRun \ + --appdir=build/AppDir +} + +package(){ + build/tools/appimagetool.AppImage build/AppDir build/"LEGO_Island-$(uname -m).AppImage" +} + +stop(){ # Can be used to do `Build clean stop` to just clean the directory + exit +} + +for arg in "$@"; do + case "$arg" in + --build=*) BUILD_SOURCE="${arg#--build=}";; + --apprun=*) APPRUN_SOURCE="${arg#--apprun=}";; + --desktop-file=*) DESKTOP_FILE_SOURCE="${arg#--desktop-file=}";; + --icon=*) ICON_SOURCE="${arg#--icon=}";; + *) "$arg" + esac +done + +prepare +compile +package +# Symlinks named as binaries in appimage can call these binaries specifically +# ln -s "LEGO_Island-$(uname -m).AppImage" isle-config +# ln -s "LEGO_Island-$(uname -m).AppImage" isle \ No newline at end of file diff --git a/packaging/linux/flatpak/org.legoisland.Isle.json b/packaging/linux/flatpak/org.legoisland.Isle.json new file mode 100644 index 00000000..e8cd3f8e --- /dev/null +++ b/packaging/linux/flatpak/org.legoisland.Isle.json @@ -0,0 +1,89 @@ +{ + "id": "org.legoisland.Isle", + + "runtime": "org.kde.Platform", + "sdk": "org.kde.Sdk", + "runtime-version": "6.8", + + "command": "isle", + + "finish-args": [ + "--share=ipc", + "--socket=wayland", + "--socket=fallback-x11", + "--socket=pulseaudio", + "--device=dri", + "--device=input", + "--filesystem=/run/media/:ro", + "--filesystem=/media/:ro", + "--filesystem=/mnt/:ro", + "--filesystem=home:ro" + ], + + "modules": [ + { + "name": "isle", + "buildsystem": "cmake-ninja", + "config-opts": [ + "-DCMAKE_BUILD_TYPE=RelWithDebInfo", + "-DISLE_DEBUG=OFF" + ], + "sources": [ + { + "type": "dir", + "path": "../../../3rdparty", + "dest": "3rdparty/" + }, + { + "type": "dir", + "path": "../../../cmake", + "dest": "cmake/" + }, + { + "type": "dir", + "path": "../../../CMake", + "dest": "CMake/" + }, + { + "type": "dir", + "path": "../../../CONFIG", + "dest": "CONFIG/" + }, + { + "type": "dir", + "path": "../../../ISLE", + "dest": "ISLE/" + }, + { + "type": "dir", + "path": "../../../LEGO1", + "dest": "LEGO1/" + }, + { + "type": "dir", + "path": "../../../miniwin", + "dest": "miniwin/" + }, + { + "type": "dir", + "path": "../../../packaging", + "dest": "packaging/" + }, + { + "type": "dir", + "path": "../../../util", + "dest": "util/" + }, + { + "type": "file", + "path": "../../../CMakeLists.txt" + } + ], + "build-options": { + "build-args": [ + "--share=network" + ] + } + } + ] +} diff --git a/packaging/linux/isledecomp.desktop.in b/packaging/linux/isledecomp.desktop.in new file mode 100644 index 00000000..28309205 --- /dev/null +++ b/packaging/linux/isledecomp.desktop.in @@ -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 diff --git a/packaging/linux/isledecomp.metainfo.xml.in b/packaging/linux/isledecomp.metainfo.xml.in new file mode 100644 index 00000000..b8faecc1 --- /dev/null +++ b/packaging/linux/isledecomp.metainfo.xml.in @@ -0,0 +1,91 @@ + + + + + @APP_ID@ + + @APP_NAME@ + @APP_SUMMARY@ + + @APP_ID@.desktop + + + #e3000b + + + + Isle Decomp Team + + + https://github.com/isledecomp/isle-portable + https://github.com/isledecomp/isle-portable/blob/master/CONTRIBUTING.md + https://github.com/isledecomp/isle-portable/tree/master + https://github.com/isledecomp/isle-portable/issues + + MIT + @APP_SPDX@ + + + 640 + offline-only + + + + 128 + + + + pointing + keyboard + gamepad + + + +

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

+ +

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

+ +
+ + + mild + mild + + + + Game + KidsGame + AdventureGame + Qt + + + + LEGO + lego + + LEGO Island + + Panik på LEGO Øen + Abenteuer auf der LEGO Insel + La Isla LEGO + Aventures sur L'île LEGO + Isola LEGO + レゴアイランドの大冒険 + 레고 아일랜드 + A Ilha LEGO + Остров LEGO + + + + + +