Compare commits

..

No commits in common. "main" and "v2.0-78" have entirely different histories.

364 changed files with 8850 additions and 18692 deletions

View file

@ -15,7 +15,6 @@ BinPackArguments: true
BinPackParameters: true BinPackParameters: true
BraceWrapping: BraceWrapping:
AfterCaseLabel: true AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always AfterControlStatement: Always
AfterEnum: true AfterEnum: true
AfterExternBlock: true AfterExternBlock: true

9
.github/getversion.cpp vendored Normal file
View file

@ -0,0 +1,9 @@
#include <stdio.h>
#include "./../src/Common/version.h"
// output current Cemu version for CI workflow. Do not modify
int main()
{
printf("%d.%d", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR);
return 0;
}

View file

@ -3,10 +3,10 @@ name: Build Cemu
on: on:
workflow_call: workflow_call:
inputs: inputs:
next_version_major: deploymode:
required: false required: false
type: string type: string
next_version_minor: experimentalversion:
required: false required: false
type: string type: string
@ -19,27 +19,41 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: "Checkout repo" - name: "Checkout repo"
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: "recursive" submodules: "recursive"
fetch-depth: 0 fetch-depth: 0
- name: Setup release mode parameters - name: "Fetch full history for vcpkg submodule"
run: |
cd dependencies/vcpkg
git fetch --unshallow
git checkout 431eb6bda0950874c8d4ed929cc66e15d8aae46f
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
run: | run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release" echo "Build mode is release"
- name: Setup build flags for version - name: Setup debug mode parameters (for continous build)
if: ${{ inputs.next_version_major != '' }} if: ${{ inputs.deploymode != 'release' }}
run: | run: |
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}" echo "BUILD_MODE=debug" >> $GITHUB_ENV
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" >> $GITHUB_ENV echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
- name: "Install system dependencies" - name: "Install system dependencies"
run: | run: |
sudo apt update -qq sudo apt update -qq
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libudev-dev nasm ninja-build libbluetooth-dev sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libudev-dev nasm ninja-build
- name: "Setup cmake" - name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2 uses: jwlawson/actions-setup-cmake@v2
@ -73,10 +87,12 @@ jobs:
cmake --build build cmake --build build
- name: Prepare artifact - name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: mv bin/Cemu_release bin/Cemu run: mv bin/Cemu_release bin/Cemu
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
if: ${{ inputs.deploymode == 'release' }}
with: with:
name: cemu-bin-linux-x64 name: cemu-bin-linux-x64
path: ./bin/Cemu path: ./bin/Cemu
@ -86,9 +102,9 @@ jobs:
needs: build-ubuntu needs: build-ubuntu
steps: steps:
- name: Checkout Upstream Repo - name: Checkout Upstream Repo
uses: actions/checkout@v4 uses: actions/checkout@v3
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v3
with: with:
name: cemu-bin-linux-x64 name: cemu-bin-linux-x64
path: bin path: bin
@ -96,7 +112,7 @@ jobs:
- name: "Install system dependencies" - name: "Install system dependencies"
run: | run: |
sudo apt update -qq sudo apt update -qq
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build appstream libbluetooth-dev sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build appstream
- name: "Build AppImage" - name: "Build AppImage"
run: | run: |
@ -105,7 +121,7 @@ jobs:
dist/linux/appimage.sh dist/linux/appimage.sh
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: cemu-appimage-x64 name: cemu-appimage-x64
path: artifacts path: artifacts
@ -114,21 +130,34 @@ jobs:
runs-on: windows-2022 runs-on: windows-2022
steps: steps:
- name: "Checkout repo" - name: "Checkout repo"
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: "recursive" submodules: "recursive"
- name: Setup release mode parameters - name: "Fetch full history for vcpkg submodule"
run: |
cd dependencies/vcpkg
git fetch --unshallow
git checkout 431eb6bda0950874c8d4ed929cc66e15d8aae46f
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
run: | run: |
echo "BUILD_MODE=release" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_MODE=release" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "Build mode is release" echo "Build mode is release"
- name: Setup build flags for version - name: Setup debug mode parameters (for continous build)
if: ${{ inputs.next_version_major != '' }} if: ${{ inputs.deploymode != 'release' }}
run: | run: |
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}" echo "BUILD_MODE=debug" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
- name: "Setup cmake" - name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2 uses: jwlawson/actions-setup-cmake@v2
@ -167,45 +196,53 @@ jobs:
cmake --build . --config ${{ env.BUILD_MODE }} cmake --build . --config ${{ env.BUILD_MODE }}
- name: Prepare artifact - name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: Rename-Item bin/Cemu_release.exe Cemu.exe run: Rename-Item bin/Cemu_release.exe Cemu.exe
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
if: ${{ inputs.deploymode == 'release' }}
with: with:
name: cemu-bin-windows-x64 name: cemu-bin-windows-x64
path: ./bin/Cemu.exe path: ./bin/Cemu.exe
build-macos: build-macos:
runs-on: macos-14 runs-on: macos-12
steps: steps:
- name: "Checkout repo" - name: "Checkout repo"
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: "recursive" submodules: "recursive"
- name: Setup release mode parameters - name: "Fetch full history for vcpkg submodule"
run: |
cd dependencies/vcpkg
git fetch --unshallow
git pull --all
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
run: | run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release" echo "Build mode is release"
- name: Setup debug mode parameters (for continous build)
- name: Setup build flags for version if: ${{ inputs.deploymode != 'release' }}
if: ${{ inputs.next_version_major != '' }}
run: | run: |
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}" echo "BUILD_MODE=debug" >> $GITHUB_ENV
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" >> $GITHUB_ENV echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
- name: "Install system dependencies" - name: "Install system dependencies"
run: | run: |
brew update brew update
brew install ninja nasm automake libtool brew install llvm@15 ninja nasm molten-vk automake libtool
- name: "Install molten-vk"
run: |
curl -L -O https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.9/MoltenVK-macos.tar
tar xf MoltenVK-macos.tar
sudo mkdir -p /usr/local/lib
sudo cp MoltenVK/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib /usr/local/lib
- name: "Setup cmake" - name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2 uses: jwlawson/actions-setup-cmake@v2
@ -236,8 +273,9 @@ jobs:
cd build cd build
cmake .. ${{ env.BUILD_FLAGS }} \ cmake .. ${{ env.BUILD_FLAGS }} \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \ -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DMACOS_BUNDLE=ON \ -DMACOS_BUNDLE=ON \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++ \
-G Ninja -G Ninja
- name: "Build Cemu" - name: "Build Cemu"
@ -245,19 +283,21 @@ jobs:
cmake --build build cmake --build build
- name: Prepare artifact - name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: | run: |
mkdir bin/Cemu_app mkdir bin/Cemu_app
mv bin/Cemu_release.app bin/Cemu_app/Cemu.app mv bin/Cemu_release.app bin/Cemu_app/Cemu.app
mv bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu_release bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu mv bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu_release bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu
sed -i '' 's/Cemu_release/Cemu/g' bin/Cemu_app/Cemu.app/Contents/Info.plist sed -i '' 's/Cemu_release/Cemu/g' bin/Cemu_app/Cemu.app/Contents/Info.plist
chmod a+x bin/Cemu_app/Cemu.app/Contents/MacOS/{Cemu,update.sh} chmod a+x bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu
ln -s /Applications bin/Cemu_app/Applications ln -s /Applications bin/Cemu_app/Applications
hdiutil create ./bin/tmp.dmg -ov -volname "Cemu" -fs HFS+ -srcfolder "./bin/Cemu_app" hdiutil create ./bin/tmp.dmg -ov -volname "Cemu" -fs HFS+ -srcfolder "./bin/Cemu_app"
hdiutil convert ./bin/tmp.dmg -format UDZO -o bin/Cemu.dmg hdiutil convert ./bin/tmp.dmg -format UDZO -o bin/Cemu.dmg
rm bin/tmp.dmg rm bin/tmp.dmg
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
if: ${{ inputs.deploymode == 'release' }}
with: with:
name: cemu-bin-macos-x64 name: cemu-bin-macos-x64
path: ./bin/Cemu.dmg path: ./bin/Cemu.dmg

View file

@ -16,3 +16,6 @@ on:
jobs: jobs:
build: build:
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
with:
deploymode: release
experimentalversion: 999999

View file

@ -0,0 +1,86 @@
name: Deploy experimental release
on:
workflow_dispatch:
jobs:
call-release-build:
uses: ./.github/workflows/build.yml
with:
deploymode: release
experimentalversion: ${{ github.run_number }}
deploy:
name: Deploy experimental release
runs-on: ubuntu-22.04
needs: call-release-build
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: cemu-bin-linux-x64
path: cemu-bin-linux-x64
- uses: actions/download-artifact@v3
with:
name: cemu-appimage-x64
path: cemu-appimage-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-windows-x64
path: cemu-bin-windows-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-macos-x64
path: cemu-bin-macos-x64
- name: Initialize
run: |
mkdir upload
sudo apt install zip
- name: Get version
run: |
echo "Experimental version: ${{ github.run_number }}"
ls
gcc -o getversion .github/getversion.cpp
./getversion
echo "Cemu CI version: $(./getversion)"
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)-${{ github.run_number }}" >> $GITHUB_ENV
echo "CEMU_VERSION=$(./getversion)-${{ github.run_number }}" >> $GITHUB_ENV
- name: Create release from windows-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create appimage
run: |
VERSION=${{ env.CEMU_VERSION }}
echo "Cemu Version is $VERSION"
ls cemu-appimage-x64
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
- name: Create release from linux-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-linux-x64/Cemu ./${{ env.CEMU_FOLDER_NAME }}/Cemu
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-ubuntu-22.04-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create release from macos-bin
run: cp cemu-bin-macos-x64/Cemu.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.dmg
- name: Create release
run: |
wget -O ghr.tar.gz https://github.com/tcnksm/ghr/releases/download/v0.15.0/ghr_v0.15.0_linux_amd64.tar.gz
tar xvzf ghr.tar.gz; rm ghr.tar.gz
echo "[INFO] Release tag: v${{ env.CEMU_VERSION }}"
ghr_v0.15.0_linux_amd64/ghr -prerelease -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }} (Experimental)" -b "Cemu experimental release" "v${{ env.CEMU_VERSION }}" ./upload

View file

@ -1,151 +0,0 @@
name: Deploy release
on:
workflow_dispatch:
inputs:
changelog0:
description: 'Enter the changelog lines for this release. Each line is a feature / bullet point. Do not use dash.'
required: true
type: string
changelog1:
description: 'Feature 2'
required: false
type: string
changelog2:
description: 'Feature 3'
required: false
type: string
changelog3:
description: 'Feature 4'
required: false
type: string
changelog4:
description: 'Feature 5'
required: false
type: string
changelog5:
description: 'Feature 6'
required: false
type: string
changelog6:
description: 'Feature 7'
required: false
type: string
changelog7:
description: 'Feature 8'
required: false
type: string
changelog8:
description: 'Feature 9'
required: false
type: string
changelog9:
description: 'Feature 10'
required: false
type: string
jobs:
calculate-version:
name: Calculate Version
uses: ./.github/workflows/determine_release_version.yml
call-release-build:
uses: ./.github/workflows/build.yml
needs: calculate-version
with:
next_version_major: ${{ needs.calculate-version.outputs.next_version_major }}
next_version_minor: ${{ needs.calculate-version.outputs.next_version_minor }}
deploy:
name: Deploy release
runs-on: ubuntu-22.04
needs: [call-release-build, calculate-version]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: generate_changelog
run: |
CHANGELOG=""
if [ -n "${{ github.event.inputs.changelog0 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog0 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog1 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog1 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog2 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog2 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog3 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog3 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog4 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog4 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog5 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog5 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog6 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog6 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog7 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog7 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog8 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog8 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog9 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog9 }}\n"; fi
echo -e "$CHANGELOG"
echo "RELEASE_BODY=$CHANGELOG" >> $GITHUB_ENV
- uses: actions/download-artifact@v4
with:
name: cemu-bin-linux-x64
path: cemu-bin-linux-x64
- uses: actions/download-artifact@v4
with:
name: cemu-appimage-x64
path: cemu-appimage-x64
- uses: actions/download-artifact@v4
with:
name: cemu-bin-windows-x64
path: cemu-bin-windows-x64
- uses: actions/download-artifact@v4
with:
name: cemu-bin-macos-x64
path: cemu-bin-macos-x64
- name: Initialize
run: |
mkdir upload
sudo apt install zip
- name: Set version dependent vars
run: |
echo "Version: ${{ needs.calculate-version.outputs.next_version }}"
echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}"
echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}"
echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
- name: Create release from windows-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create appimage
run: |
VERSION=${{ env.CEMU_VERSION }}
echo "Cemu Version is $VERSION"
ls cemu-appimage-x64
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
- name: Create release from linux-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-linux-x64/Cemu ./${{ env.CEMU_FOLDER_NAME }}/Cemu
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-ubuntu-22.04-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create release from macos-bin
run: cp cemu-bin-macos-x64/Cemu.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.dmg
- name: Create release
run: |
wget -O ghr.tar.gz https://github.com/tcnksm/ghr/releases/download/v0.15.0/ghr_v0.15.0_linux_amd64.tar.gz
tar xvzf ghr.tar.gz; rm ghr.tar.gz
echo "[INFO] Release tag: v${{ env.CEMU_VERSION }}"
CHANGELOG_UNESCAPED=$(printf "%s\n" "${{ env.RELEASE_BODY }}" | sed 's/\\n/\n/g')
RELEASE_BODY=$(printf "%s\n%s" \
"**Changelog:**" \
"$CHANGELOG_UNESCAPED")
ghr_v0.15.0_linux_amd64/ghr -draft -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }}" -b "$RELEASE_BODY" "v${{ env.CEMU_VERSION }}" ./upload

View file

@ -0,0 +1,85 @@
name: Create new release
on:
workflow_dispatch:
inputs:
PlaceholderInput:
description: PlaceholderInput
required: false
jobs:
call-release-build:
uses: ./.github/workflows/build.yml
with:
deploymode: release
deploy:
name: Deploy release
runs-on: ubuntu-20.04
needs: call-release-build
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: cemu-bin-linux-x64
path: cemu-bin-linux-x64
- uses: actions/download-artifact@v3
with:
name: cemu-appimage-x64
path: cemu-appimage-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-windows-x64
path: cemu-bin-windows-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-macos-x64
path: cemu-bin-macos-x64
- name: Initialize
run: |
mkdir upload
sudo apt update -qq
sudo apt install -y zip
- name: Get Cemu release version
run: |
gcc -o getversion .github/getversion.cpp
echo "Cemu CI version: $(./getversion)"
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)" >> $GITHUB_ENV
echo "CEMU_VERSION=$(./getversion)" >> $GITHUB_ENV
- name: Create release from windows-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create appimage
run: |
VERSION=${{ env.CEMU_VERSION }}
echo "Cemu Version is $VERSION"
ls cemu-appimage-x64
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
- name: Create release from ubuntu-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-linux-x64/Cemu ./${{ env.CEMU_FOLDER_NAME }}/Cemu
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-ubuntu-20.04-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create release from macos-bin
run: cp cemu-bin-macos-x64/Cemu.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.dmg
- name: Create release
run: |
wget -O ghr.tar.gz https://github.com/tcnksm/ghr/releases/download/v0.15.0/ghr_v0.15.0_linux_amd64.tar.gz
tar xvzf ghr.tar.gz; rm ghr.tar.gz
ghr_v0.15.0_linux_amd64/ghr -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }}" -b "Changelog:" v${{ env.CEMU_VERSION }} ./upload

View file

@ -1,74 +0,0 @@
name: Calculate Next Version from release history
on:
workflow_dispatch:
workflow_call:
outputs:
next_version:
description: "The next semantic version"
value: ${{ jobs.calculate-version.outputs.next_version }}
next_version_major:
description: "The next semantic version (major)"
value: ${{ jobs.calculate-version.outputs.next_version_major }}
next_version_minor:
description: "The next semantic version (minor)"
value: ${{ jobs.calculate-version.outputs.next_version_minor }}
jobs:
calculate-version:
runs-on: ubuntu-latest
outputs:
next_version: ${{ steps.calculate_next_version.outputs.next_version }}
next_version_major: ${{ steps.calculate_next_version.outputs.next_version_major }}
next_version_minor: ${{ steps.calculate_next_version.outputs.next_version_minor }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Get all releases
id: get_all_releases
run: |
# Fetch all releases and check for API errors
RESPONSE=$(curl -s -o response.json -w "%{http_code}" "https://api.github.com/repos/${{ github.repository }}/releases?per_page=100")
if [ "$RESPONSE" -ne 200 ]; then
echo "Failed to fetch releases. HTTP status: $RESPONSE"
cat response.json
exit 1
fi
# Extract and sort tags
ALL_TAGS=$(jq -r '.[].tag_name' response.json | grep -E '^v[0-9]+\.[0-9]+(-[0-9]+)?$' | sed 's/-.*//' | sort -V | tail -n 1)
# Exit if no tags were found
if [ -z "$ALL_TAGS" ]; then
echo "No valid tags found."
exit 1
fi
echo "::set-output name=tag::$ALL_TAGS"
# echo "tag=$ALL_TAGS" >> $GITHUB_STATE
- name: Calculate next semver minor
id: calculate_next_version
run: |
LATEST_VERSION=${{ steps.get_all_releases.outputs.tag }}
# strip 'v' prefix and split into major.minor
LATEST_VERSION=${LATEST_VERSION//v/}
IFS='.' read -r -a VERSION_PARTS <<< "$LATEST_VERSION"
MAJOR=${VERSION_PARTS[0]}
MINOR=${VERSION_PARTS[1]}
# increment the minor version
MINOR=$((MINOR + 1))
NEXT_VERSION="${MAJOR}.${MINOR}"
echo "Major: $MAJOR"
echo "Minor: $MINOR"
echo "Next version: $NEXT_VERSION"
echo "::set-output name=next_version::$NEXT_VERSION"
echo "::set-output name=next_version_major::$MAJOR"
echo "::set-output name=next_version_minor::$MINOR"

View file

@ -35,7 +35,7 @@ jobs:
-o cemu.pot -o cemu.pot
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: POT file name: POT file
path: ./cemu.pot path: ./cemu.pot

1
.gitignore vendored
View file

@ -39,7 +39,6 @@ bin/sdcard/*
bin/screenshots/* bin/screenshots/*
bin/dump/* bin/dump/*
bin/cafeLibs/* bin/cafeLibs/*
bin/portable/*
bin/keys.txt bin/keys.txt
!bin/shaderCache/info.txt !bin/shaderCache/info.txt

4
.gitmodules vendored
View file

@ -9,12 +9,10 @@
[submodule "dependencies/vcpkg"] [submodule "dependencies/vcpkg"]
path = dependencies/vcpkg path = dependencies/vcpkg
url = https://github.com/microsoft/vcpkg url = https://github.com/microsoft/vcpkg
shallow = false shallow = true
[submodule "dependencies/Vulkan-Headers"] [submodule "dependencies/Vulkan-Headers"]
path = dependencies/Vulkan-Headers path = dependencies/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers url = https://github.com/KhronosGroup/Vulkan-Headers
shallow = true
[submodule "dependencies/imgui"] [submodule "dependencies/imgui"]
path = dependencies/imgui path = dependencies/imgui
url = https://github.com/ocornut/imgui url = https://github.com/ocornut/imgui
shallow = true

View file

@ -16,11 +16,11 @@
- [Compiling Errors](#compiling-errors) - [Compiling Errors](#compiling-errors)
- [Building Errors](#building-errors) - [Building Errors](#building-errors)
- [macOS](#macos) - [macOS](#macos)
- [On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used](#on-apple-silicon-macs-rosetta-2-and-the-x86_64-version-of-homebrew-must-be-used)
- [Installing brew](#installing-brew) - [Installing brew](#installing-brew)
- [Installing Tool Dependencies](#installing-tool-dependencies) - [Installing Dependencies](#installing-dependencies)
- [Installing Library Dependencies](#installing-library-dependencies) - [Build Cemu using CMake and Clang](#build-cemu-using-cmake-and-clang)
- [Build Cemu using CMake](#build-cemu-using-cmake) - [Updating Cemu and source code](#updating-cemu-and-source-code)
- [Updating Cemu and source code](#updating-cemu-and-source-code)
## Windows ## Windows
@ -46,10 +46,10 @@ To compile Cemu, a recent enough compiler and STL with C++20 support is required
### Dependencies ### Dependencies
#### For Arch and derivatives: #### For Arch and derivatives:
`sudo pacman -S --needed base-devel bluez-libs clang cmake freeglut git glm gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip` `sudo pacman -S --needed base-devel clang cmake freeglut git glm gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
#### For Debian, Ubuntu and derivatives: #### For Debian, Ubuntu and derivatives:
`sudo apt install -y cmake curl clang-15 freeglut3-dev git libbluetooth-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libtool nasm ninja-build` `sudo apt install -y cmake curl clang-15 freeglut3-dev git libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libtool nasm ninja-build`
You may also need to install `libusb-1.0-0-dev` as a workaround for an issue with the vcpkg hidapi package. You may also need to install `libusb-1.0-0-dev` as a workaround for an issue with the vcpkg hidapi package.
@ -57,7 +57,7 @@ At Step 3 in [Build Cemu using cmake and clang](#build-cemu-using-cmake-and-clan
`cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja` `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
#### For Fedora and derivatives: #### For Fedora and derivatives:
`sudo dnf install bluez-libs-devel clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel llvm nasm ninja-build perl-core systemd-devel wayland-protocols-devel zlib-devel zlib-static` `sudo dnf install clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel llvm nasm ninja-build perl-core systemd-devel zlib-devel`
### Build Cemu ### Build Cemu
@ -120,9 +120,6 @@ This section refers to running `cmake -S...` (truncated).
* Compiling failed during rebuild after `git pull` with an error that mentions RPATH * Compiling failed during rebuild after `git pull` with an error that mentions RPATH
* Add the following and try running the command again: * Add the following and try running the command again:
* `-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON` * `-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON`
* Environment variable `VCPKG_FORCE_SYSTEM_BINARIES` must be set.
* Execute the folowing and then try running the command again:
* `export VCPKG_FORCE_SYSTEM_BINARIES=1`
* If you are getting a random error, read the [package-name-and-platform]-out.log and [package-name-and-platform]-err.log for the actual reason to see if you might be lacking the headers from a dependency. * If you are getting a random error, read the [package-name-and-platform]-out.log and [package-name-and-platform]-err.log for the actual reason to see if you might be lacking the headers from a dependency.
@ -144,41 +141,31 @@ If you are getting a different error than any of the errors listed above, you ma
## macOS ## macOS
To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and below To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and
don't support the C++20 feature set required, so either install LLVM from Homebrew or make sure that below, built in LLVM, and Xcode LLVM don't support the C++20 feature set required. The OpenGL graphics
you have a recent enough version of Xcode. Xcode 15 is known to work. The OpenGL graphics API isn't API isn't support on macOS, Vulkan must be used. Additionally Vulkan must be used through the
supported on macOS, so Vulkan must be used through the Molten-VK compatibility layer. Molten-VK compatibility layer
### On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used
You can skip this section if you have an Intel Mac. Every time you compile, you need to perform steps 2.
1. `softwareupdate --install-rosetta` # Install Rosetta 2 if you don't have it. This only has to be done once
2. `arch -x86_64 zsh` # run an x64 shell
### Installing brew ### Installing brew
1. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"` 1. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
2. Set up the Homebrew shell environment: 2. `eval "$(/usr/local/Homebrew/bin/brew shellenv)"` # set x86_64 brew env
1. **On an Intel Mac:** `eval "$(/usr/local/Homebrew/bin/brew shellenv)"`
2. **On an Apple Silicon Mac:** eval `"$(/opt/homebrew/bin/brew shellenv)"`
### Installing Tool Dependencies ### Installing Dependencies
The native versions of these can be used regardless of what type of Mac you have. `brew install boost git cmake llvm ninja nasm molten-vk automake libtool`
`brew install git cmake ninja nasm automake libtool`
### Installing Library Dependencies
**On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used to install these dependencies:**
1. `softwareupdate --install-rosetta` # Install Rosetta 2 if you don't have it. This only has to be done once
2. `arch -x86_64 zsh` # run an x64 shell
3. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
4. `eval "$(/usr/local/Homebrew/bin/brew shellenv)"`
Then install the dependencies:
`brew install boost molten-vk`
### Build Cemu using CMake
### Build Cemu using CMake and Clang
1. `git clone --recursive https://github.com/cemu-project/Cemu` 1. `git clone --recursive https://github.com/cemu-project/Cemu`
2. `cd Cemu` 2. `cd Cemu`
3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_OSX_ARCHITECTURES=x86_64 -G Ninja` 3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -G Ninja`
4. `cmake --build build` 4. `cmake --build build`
5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`. 5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`.
@ -192,41 +179,3 @@ Then install the dependencies:
If CMake complains about Cemu already being compiled or another similar error, try deleting the `CMakeCache.txt` file inside the `build` folder and retry building. If CMake complains about Cemu already being compiled or another similar error, try deleting the `CMakeCache.txt` file inside the `build` folder and retry building.
## CMake configure flags
Some flags can be passed during CMake configure to customise which features are enabled on build.
Example usage: `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DENABLE_SDL=ON -DENABLE_VULKAN=OFF`
### All platforms
| Flag | | Description | Default | Note |
|--------------------|:--|-----------------------------------------------------------------------------|---------|--------------------|
| ALLOW_PORTABLE | | Allow Cemu to use the `portable` directory to store configs and data | ON | |
| CEMU_CXX_FLAGS | | Flags passed straight to the compiler, e.g. `-march=native`, `-Wall`, `/W3` | "" | |
| ENABLE_CUBEB | | Enable cubeb audio backend | ON | |
| ENABLE_DISCORD_RPC | | Enable Discord Rich presence support | ON | |
| ENABLE_OPENGL | | Enable OpenGL graphics backend | ON | Currently required |
| ENABLE_HIDAPI | | Enable HIDAPI (used for Wiimote controller API) | ON | |
| ENABLE_SDL | | Enable SDLController controller API | ON | Currently required |
| ENABLE_VCPKG | | Use VCPKG package manager to obtain dependencies | ON | |
| ENABLE_VULKAN | | Enable the Vulkan graphics backend | ON | |
| ENABLE_WXWIDGETS | | Enable wxWidgets UI | ON | Currently required |
### Windows
| Flag | Description | Default | Note |
|--------------------|-----------------------------------|---------|--------------------|
| ENABLE_DIRECTAUDIO | Enable DirectAudio audio backend | ON | Currently required |
| ENABLE_DIRECTINPUT | Enable DirectInput controller API | ON | Currently required |
| ENABLE_XAUDIO | Enable XAudio audio backend | ON | |
| ENABLE_XINPUT | Enable XInput controller API | ON | |
### Linux
| Flag | Description | Default |
|-----------------------|----------------------------------------------------|---------|
| ENABLE_BLUEZ | Build with Bluez (used for Wiimote controller API) | ON |
| ENABLE_FERAL_GAMEMODE | Enable Feral Interactive GameMode support | ON |
| ENABLE_WAYLAND | Enable Wayland support | ON |
### macOS
| Flag | Description | Default |
|--------------|------------------------------------------------|---------|
| MACOS_BUNDLE | MacOS executable will be an application bundle | OFF |

View file

@ -2,40 +2,20 @@ cmake_minimum_required(VERSION 3.21.1)
option(ENABLE_VCPKG "Enable the vcpkg package manager" ON) option(ENABLE_VCPKG "Enable the vcpkg package manager" ON)
option(MACOS_BUNDLE "The executable when built on macOS will be created as an application bundle" OFF) option(MACOS_BUNDLE "The executable when built on macOS will be created as an application bundle" OFF)
option(ALLOW_PORTABLE "Allow Cemu to be run in portable mode" ON) set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
# used by CI script to set version: if (EXPERIMENTAL_VERSION)
set(EMULATOR_VERSION_MAJOR "0" CACHE STRING "") add_definitions(-DEMULATOR_VERSION_MINOR=${EXPERIMENTAL_VERSION})
set(EMULATOR_VERSION_MINOR "0" CACHE STRING "") execute_process(
set(EMULATOR_VERSION_PATCH "0" CACHE STRING "") COMMAND git log --format=%h -1
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
execute_process( OUTPUT_VARIABLE GIT_HASH
COMMAND git log --format=%h -1 OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} )
OUTPUT_VARIABLE GIT_HASH add_definitions(-DEMULATOR_HASH=${GIT_HASH})
OUTPUT_STRIP_TRAILING_WHITESPACE endif()
)
add_definitions(-DEMULATOR_HASH=${GIT_HASH})
if (ENABLE_VCPKG) if (ENABLE_VCPKG)
# check if vcpkg is shallow and unshallow it if necessary
execute_process(
COMMAND git rev-parse --is-shallow-repository
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/vcpkg
OUTPUT_VARIABLE is_vcpkg_shallow
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(is_vcpkg_shallow STREQUAL "true")
message(STATUS "vcpkg is shallow. Unshallowing it now...")
execute_process(
COMMAND git fetch --unshallow
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/dependencies/vcpkg"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
)
endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux") set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux")
elseif(APPLE) elseif(APPLE)
@ -64,10 +44,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_definitions($<$<CONFIG:Debug>:CEMU_DEBUG_ASSERT>) # if build type is debug, set CEMU_DEBUG_ASSERT add_compile_definitions($<$<CONFIG:Debug>:CEMU_DEBUG_ASSERT>) # if build type is debug, set CEMU_DEBUG_ASSERT
add_definitions(-DEMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR})
add_definitions(-DEMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR})
add_definitions(-DEMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH})
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# enable link time optimization for release builds # enable link time optimization for release builds
@ -93,13 +69,11 @@ endif()
if (APPLE) if (APPLE)
enable_language(OBJC OBJCXX) enable_language(OBJC OBJCXX)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0")
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
option(ENABLE_WAYLAND "Build with Wayland support" ON) option(ENABLE_WAYLAND "Build with Wayland support" ON)
option(ENABLE_FERAL_GAMEMODE "Enables Feral Interactive GameMode Support" ON) option(ENABLE_FERAL_GAMEMODE "Enables Feral Interactive GameMode Support" ON)
option(ENABLE_BLUEZ "Build with Bluez support" ON)
endif() endif()
option(ENABLE_OPENGL "Enables the OpenGL backend" ON) option(ENABLE_OPENGL "Enables the OpenGL backend" ON)
@ -124,6 +98,23 @@ if (WIN32)
endif() endif()
option(ENABLE_CUBEB "Enabled cubeb backend" ON) option(ENABLE_CUBEB "Enabled cubeb backend" ON)
# usb hid backends
if (WIN32)
option(ENABLE_NSYSHID_WINDOWS_HID "Enables the native Windows HID backend for nsyshid" ON)
endif ()
# libusb and windows hid backends shouldn't be active at the same time; otherwise we'd see all devices twice!
if (NOT ENABLE_NSYSHID_WINDOWS_HID)
option(ENABLE_NSYSHID_LIBUSB "Enables the libusb backend for nsyshid" ON)
else ()
set(ENABLE_NSYSHID_LIBUSB OFF CACHE BOOL "" FORCE)
endif ()
if (ENABLE_NSYSHID_WINDOWS_HID)
add_compile_definitions(NSYSHID_ENABLE_BACKEND_WINDOWS_HID)
endif ()
if (ENABLE_NSYSHID_LIBUSB)
add_compile_definitions(NSYSHID_ENABLE_BACKEND_LIBUSB)
endif ()
option(ENABLE_WXWIDGETS "Build with wxWidgets UI (Currently required)" ON) option(ENABLE_WXWIDGETS "Build with wxWidgets UI (Currently required)" ON)
set(THREADS_PREFER_PTHREAD_FLAG true) set(THREADS_PREFER_PTHREAD_FLAG true)
@ -164,12 +155,6 @@ if (UNIX AND NOT APPLE)
endif() endif()
find_package(GTK3 REQUIRED) find_package(GTK3 REQUIRED)
if(ENABLE_BLUEZ)
find_package(bluez REQUIRED)
set(ENABLE_WIIMOTE ON)
add_compile_definitions(HAS_BLUEZ)
endif()
endif() endif()
if (ENABLE_VULKAN) if (ENABLE_VULKAN)
@ -213,7 +198,7 @@ if (ENABLE_CUBEB)
option(BUILD_TOOLS "" OFF) option(BUILD_TOOLS "" OFF)
option(BUNDLE_SPEEX "" OFF) option(BUNDLE_SPEEX "" OFF)
set(USE_WINMM OFF CACHE BOOL "") set(USE_WINMM OFF CACHE BOOL "")
add_subdirectory("dependencies/cubeb" EXCLUDE_FROM_ALL SYSTEM) add_subdirectory("dependencies/cubeb" EXCLUDE_FROM_ALL)
set_property(TARGET cubeb PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") set_property(TARGET cubeb PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
add_library(cubeb::cubeb ALIAS cubeb) add_library(cubeb::cubeb ALIAS cubeb)
endif() endif()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
bin/shaderCache/info.txt Normal file
View file

@ -0,0 +1 @@
If you plan to transfer the shader cache to a different PC or Cemu installation you only need to copy the 'transferable' directory.

View file

@ -1,20 +0,0 @@
# SPDX-FileCopyrightText: 2022 Andrea Pappacoda <andrea@pappacoda.it>
# SPDX-License-Identifier: ISC
find_package(bluez CONFIG)
if (NOT bluez_FOUND)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_search_module(bluez IMPORTED_TARGET GLOBAL bluez-1.0 bluez)
if (bluez_FOUND)
add_library(bluez::bluez ALIAS PkgConfig::bluez)
endif ()
endif ()
endif ()
find_package_handle_standard_args(bluez
REQUIRED_VARS
bluez_LINK_LIBRARIES
bluez_FOUND
VERSION_VAR bluez_VERSION
)

View file

@ -117,13 +117,7 @@ add_library (ih264d
"decoder/ivd.h" "decoder/ivd.h"
) )
if (CMAKE_OSX_ARCHITECTURES) if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64")
set(IH264D_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES})
else()
set(IH264D_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
endif()
if (IH264D_ARCHITECTURE STREQUAL "x86_64" OR IH264D_ARCHITECTURE STREQUAL "amd64" OR IH264D_ARCHITECTURE STREQUAL "AMD64")
set(LIBAVCDEC_X86_INCLUDES "common/x86" "decoder/x86") set(LIBAVCDEC_X86_INCLUDES "common/x86" "decoder/x86")
include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES}) include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES})
target_sources(ih264d PRIVATE target_sources(ih264d PRIVATE
@ -146,7 +140,7 @@ target_sources(ih264d PRIVATE
"decoder/x86/ih264d_function_selector_sse42.c" "decoder/x86/ih264d_function_selector_sse42.c"
"decoder/x86/ih264d_function_selector_ssse3.c" "decoder/x86/ih264d_function_selector_ssse3.c"
) )
elseif(IH264D_ARCHITECTURE STREQUAL "aarch64" OR IH264D_ARCHITECTURE STREQUAL "arm64") elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
enable_language( C CXX ASM ) enable_language( C CXX ASM )
set(LIBAVCDEC_ARM_INCLUDES "common/armv8" "decoder/arm") set(LIBAVCDEC_ARM_INCLUDES "common/armv8" "decoder/arm")
include_directories("common/" "decoder/" ${LIBAVCDEC_ARM_INCLUDES}) include_directories("common/" "decoder/" ${LIBAVCDEC_ARM_INCLUDES})
@ -184,7 +178,7 @@ target_sources(ih264d PRIVATE
) )
target_compile_options(ih264d PRIVATE -DARMV8) target_compile_options(ih264d PRIVATE -DARMV8)
else() else()
message(FATAL_ERROR "ih264d unknown architecture: ${IH264D_ARCHITECTURE}") message(FATAL_ERROR "ih264d unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif() endif()
if(MSVC) if(MSVC)

2
dependencies/vcpkg vendored

@ -1 +1 @@
Subproject commit a4275b7eee79fb24ec2e135481ef5fce8b41c339 Subproject commit 53bef8994c541b6561884a8395ea35715ece75db

View file

@ -0,0 +1,13 @@
diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
index cc8bcf26d..ead829767 100644
--- a/SDL2Config.cmake.in
+++ b/SDL2Config.cmake.in
@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
set(SDL_ALSA @SDL_ALSA@)
set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
+if(SDL_ALSA)
sdlFindALSA()
endif()
unset(SDL_ALSA)

View file

@ -0,0 +1,13 @@
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index 65a98efbe..2f99f28f1 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -352,7 +352,7 @@ endmacro()
# - HAVE_SDL_LOADSO opt
macro(CheckLibSampleRate)
if(SDL_LIBSAMPLERATE)
- find_package(SampleRate QUIET)
+ find_package(SampleRate CONFIG REQUIRED)
if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
set(HAVE_LIBSAMPLERATE TRUE)
set(HAVE_LIBSAMPLERATE_H TRUE)

View file

@ -0,0 +1,137 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO libsdl-org/SDL
REF "release-${VERSION}"
SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
HEAD_REF main
PATCHES
deps.patch
alsa-dep-fix.patch
)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
alsa SDL_ALSA
alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
ibus SDL_IBUS
samplerate SDL_LIBSAMPLERATE
vulkan SDL_VULKAN
wayland SDL_WAYLAND
x11 SDL_X11
INVERTED_FEATURES
alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
)
if ("x11" IN_LIST FEATURES)
message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
endif()
if ("wayland" IN_LIST FEATURES)
message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
endif()
if ("ibus" IN_LIST FEATURES)
message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
endif()
if(VCPKG_TARGET_IS_UWP)
set(configure_opts WINDOWS_USE_MSBUILD)
endif()
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
${configure_opts}
OPTIONS ${FEATURE_OPTIONS}
-DSDL_STATIC=${SDL_STATIC}
-DSDL_SHARED=${SDL_SHARED}
-DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
-DSDL_LIBC=ON
-DSDL_TEST=OFF
-DSDL_INSTALL_CMAKEDIR="cmake"
-DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
-DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
-DSDL_LIBSAMPLERATE_SHARED=OFF
MAYBE_UNUSED_VARIABLES
SDL_FORCE_STATIC_VCRT
PKG_CONFIG_USE_CMAKE_PREFIX_PATH
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
"${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/share/licenses"
"${CURRENT_PACKAGES_DIR}/share/aclocal"
)
file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
if(NOT BINS)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/bin"
"${CURRENT_PACKAGES_DIR}/debug/bin"
)
endif()
if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
endif()
file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
foreach(SHARE_FILE ${SHARE_FILES})
vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
endforeach()
endif()
vcpkg_copy_pdbs()
set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
endif()
if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
endif()
endif()
if(VCPKG_TARGET_IS_UWP)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "d")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
endif()
vcpkg_fixup_pkgconfig()
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")

View file

@ -0,0 +1,8 @@
sdl2 provides CMake targets:
find_package(SDL2 CONFIG REQUIRED)
target_link_libraries(main
PRIVATE
$<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
)

View file

@ -0,0 +1,68 @@
{
"name": "sdl2",
"version": "2.30.0",
"description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
"homepage": "https://www.libsdl.org/download-2.0.php",
"license": "Zlib",
"dependencies": [
{
"name": "dbus",
"default-features": false,
"platform": "linux"
},
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
{
"name": "ibus",
"platform": "linux"
},
{
"name": "wayland",
"platform": "linux"
},
{
"name": "x11",
"platform": "linux"
}
],
"features": {
"alsa": {
"description": "Support for alsa audio",
"dependencies": [
{
"name": "alsa",
"platform": "linux"
}
]
},
"ibus": {
"description": "Build with ibus IME support",
"supports": "linux"
},
"samplerate": {
"description": "Use libsamplerate for audio rate conversion",
"dependencies": [
"libsamplerate"
]
},
"vulkan": {
"description": "Vulkan functionality for SDL"
},
"wayland": {
"description": "Build with Wayland support",
"supports": "linux"
},
"x11": {
"description": "Build with X11 support",
"supports": "!windows"
}
}
}

View file

@ -0,0 +1,13 @@
diff --git a/cmake/FindCMath.cmake b/cmake/FindCMath.cmake
index ad92218..dd42aba 100644
--- a/cmake/FindCMath.cmake
+++ b/cmake/FindCMath.cmake
@@ -31,7 +31,7 @@ include(CheckSymbolExists)
include(CheckLibraryExists)
check_symbol_exists(pow "math.h" CMath_HAVE_LIBC_POW)
-find_library(CMath_LIBRARY NAMES m)
+find_library(CMath_LIBRARY NAMES m PATHS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
if(NOT CMath_HAVE_LIBC_POW)
set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})

View file

@ -0,0 +1,86 @@
vcpkg_from_gitlab(
GITLAB_URL https://gitlab.com
OUT_SOURCE_PATH SOURCE_PATH
REPO libtiff/libtiff
REF "v${VERSION}"
SHA512 ef2f1d424219d9e245069b7d23e78f5e817cf6ee516d46694915ab6c8909522166f84997513d20a702f4e52c3f18467813935b328fafa34bea5156dee00f66fa
HEAD_REF master
PATCHES
FindCMath.patch
)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
cxx cxx
jpeg jpeg
jpeg CMAKE_REQUIRE_FIND_PACKAGE_JPEG
libdeflate libdeflate
libdeflate CMAKE_REQUIRE_FIND_PACKAGE_Deflate
lzma lzma
lzma CMAKE_REQUIRE_FIND_PACKAGE_liblzma
tools tiff-tools
webp webp
webp CMAKE_REQUIRE_FIND_PACKAGE_WebP
zip zlib
zip CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
zstd zstd
zstd CMAKE_REQUIRE_FIND_PACKAGE_ZSTD
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
${FEATURE_OPTIONS}
-DCMAKE_FIND_PACKAGE_PREFER_CONFIG=ON
-Dtiff-docs=OFF
-Dtiff-contrib=OFF
-Dtiff-tests=OFF
-Djbig=OFF # This is disabled by default due to GPL/Proprietary licensing.
-Djpeg12=OFF
-Dlerc=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_OpenGL=ON
-DCMAKE_DISABLE_FIND_PACKAGE_GLUT=ON
-DZSTD_HAVE_DECOMPRESS_STREAM=ON
-DHAVE_JPEGTURBO_DUAL_MODE_8_12=OFF
OPTIONS_DEBUG
-DCMAKE_DEBUG_POSTFIX=d # tiff sets "d" for MSVC only.
MAYBE_UNUSED_VARIABLES
CMAKE_DISABLE_FIND_PACKAGE_GLUT
CMAKE_DISABLE_FIND_PACKAGE_OpenGL
ZSTD_HAVE_DECOMPRESS_STREAM
)
vcpkg_cmake_install()
# CMake config wasn't packaged in the past and is not yet usable now,
# cf. https://gitlab.com/libtiff/libtiff/-/merge_requests/496
# vcpkg_cmake_config_fixup(CONFIG_PATH "lib/cmake/tiff")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/cmake" "${CURRENT_PACKAGES_DIR}/debug/lib/cmake")
set(_file "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libtiff-4.pc")
if(EXISTS "${_file}")
vcpkg_replace_string("${_file}" "-ltiff" "-ltiffd")
endif()
vcpkg_fixup_pkgconfig()
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
)
configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake.in" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY)
if ("tools" IN_LIST FEATURES)
vcpkg_copy_tools(TOOL_NAMES
tiffcp
tiffdump
tiffinfo
tiffset
tiffsplit
AUTO_CLEAN
)
endif()
vcpkg_copy_pdbs()
file(COPY "${CURRENT_PORT_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.md")

View file

@ -0,0 +1,9 @@
tiff is compatible with built-in CMake targets:
find_package(TIFF REQUIRED)
target_link_libraries(main PRIVATE TIFF::TIFF)
tiff provides pkg-config modules:
# Tag Image File Format (TIFF) library.
libtiff-4

View file

@ -0,0 +1,104 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0012 NEW)
cmake_policy(SET CMP0057 NEW)
set(z_vcpkg_tiff_find_options "")
if("REQUIRED" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "REQUIRED")
endif()
if("QUIET" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "QUIET")
endif()
_find_package(${ARGS})
if(TIFF_FOUND AND "@VCPKG_LIBRARY_LINKAGE@" STREQUAL "static")
include(SelectLibraryConfigurations)
set(z_vcpkg_tiff_link_libraries "")
set(z_vcpkg_tiff_libraries "")
if("@webp@")
find_package(WebP CONFIG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:WebP::WebP>")
list(APPEND z_vcpkg_tiff_libraries ${WebP_LIBRARIES})
endif()
if("@lzma@")
find_package(LibLZMA ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:LibLZMA::LibLZMA>")
list(APPEND z_vcpkg_tiff_libraries ${LIBLZMA_LIBRARIES})
endif()
if("@jpeg@")
find_package(JPEG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:JPEG::JPEG>")
list(APPEND z_vcpkg_tiff_libraries ${JPEG_LIBRARIES})
endif()
if("@zstd@")
find_package(zstd CONFIG ${z_vcpkg_tiff_find_options})
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_LOCATION_")
if(TARGET zstd::libzstd_shared)
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_shared>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_shared)
if(WIN32)
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_static>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_static)
endif()
get_target_property(z_vcpkg_tiff_zstd_configs "${z_vcpkg_tiff_zstd_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_tiff_zstd_configs)
get_target_property(ZSTD_LIBRARY_${z_vcpkg_config} "${z_vcpkg_tiff_zstd_target}" "${z_vcpkg_tiff_zstd_target_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(ZSTD)
if(NOT TARGET ZSTD::ZSTD)
add_library(ZSTD::ZSTD INTERFACE IMPORTED)
set_property(TARGET ZSTD::ZSTD APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_zstd})
endif()
list(APPEND z_vcpkg_tiff_link_libraries ${z_vcpkg_tiff_zstd})
list(APPEND z_vcpkg_tiff_libraries ${ZSTD_LIBRARIES})
unset(z_vcpkg_tiff_zstd)
unset(z_vcpkg_tiff_zstd_configs)
unset(z_vcpkg_config)
unset(z_vcpkg_tiff_zstd_target)
endif()
if("@libdeflate@")
find_package(libdeflate ${z_vcpkg_tiff_find_options})
set(z_vcpkg_property "IMPORTED_LOCATION_")
if(TARGET libdeflate::libdeflate_shared)
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_shared)
if(WIN32)
set(z_vcpkg_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_static)
endif()
get_target_property(z_vcpkg_libdeflate_configs "${z_vcpkg_libdeflate_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_libdeflate_configs)
get_target_property(Z_VCPKG_DEFLATE_LIBRARY_${z_vcpkg_config} "${z_vcpkg_libdeflate_target}" "${z_vcpkg_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(Z_VCPKG_DEFLATE)
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:${z_vcpkg_libdeflate_target}>")
list(APPEND z_vcpkg_tiff_libraries ${Z_VCPKG_DEFLATE_LIBRARIES})
unset(z_vcpkg_config)
unset(z_vcpkg_libdeflate_configs)
unset(z_vcpkg_libdeflate_target)
unset(z_vcpkg_property)
unset(Z_VCPKG_DEFLATE_FOUND)
endif()
if("@zlib@")
find_package(ZLIB ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:ZLIB::ZLIB>")
list(APPEND z_vcpkg_tiff_libraries ${ZLIB_LIBRARIES})
endif()
if(UNIX)
list(APPEND z_vcpkg_tiff_link_libraries m)
list(APPEND z_vcpkg_tiff_libraries m)
endif()
if(TARGET TIFF::TIFF)
set_property(TARGET TIFF::TIFF APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_link_libraries})
endif()
list(APPEND TIFF_LIBRARIES ${z_vcpkg_tiff_libraries})
unset(z_vcpkg_tiff_link_libraries)
unset(z_vcpkg_tiff_libraries)
endif()
unset(z_vcpkg_tiff_find_options)
cmake_policy(POP)

View file

@ -0,0 +1,67 @@
{
"name": "tiff",
"version": "4.6.0",
"port-version": 2,
"description": "A library that supports the manipulation of TIFF image files",
"homepage": "https://libtiff.gitlab.io/libtiff/",
"license": "libtiff",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
"jpeg",
"zip"
],
"features": {
"cxx": {
"description": "Build C++ libtiffxx library"
},
"jpeg": {
"description": "Support JPEG compression in TIFF image files",
"dependencies": [
"libjpeg-turbo"
]
},
"libdeflate": {
"description": "Use libdeflate for faster ZIP support",
"dependencies": [
"libdeflate",
{
"name": "tiff",
"default-features": false,
"features": [
"zip"
]
}
]
},
"tools": {
"description": "Build tools"
},
"webp": {
"description": "Support WEBP compression in TIFF image files",
"dependencies": [
"libwebp"
]
},
"zip": {
"description": "Support ZIP/deflate compression in TIFF image files",
"dependencies": [
"zlib"
]
},
"zstd": {
"description": "Support ZSTD compression in TIFF image files",
"dependencies": [
"zstd"
]
}
}
}

View file

@ -0,0 +1,15 @@
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 8cde1ffe0..d4d09f223 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -91,7 +91,9 @@ endif()
add_executable(dbus-launch ${dbus_launch_SOURCES})
target_link_libraries(dbus-launch ${DBUS_LIBRARIES})
if(DBUS_BUILD_X11)
- target_link_libraries(dbus-launch ${X11_LIBRARIES} )
+ find_package(Threads REQUIRED)
+ target_link_libraries(dbus-launch ${X11_LIBRARIES} ${X11_xcb_LIB} ${X11_Xau_LIB} ${X11_Xdmcp_LIB} Threads::Threads)
+ target_include_directories(dbus-launch PRIVATE ${X11_INCLUDE_DIR})
endif()
install(TARGETS dbus-launch ${INSTALL_TARGETS_DEFAULT_ARGS})

View file

@ -0,0 +1,26 @@
diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake
index b7f3702..e2336ba 100644
--- a/cmake/ConfigureChecks.cmake
+++ b/cmake/ConfigureChecks.cmake
@@ -51,6 +51,7 @@ check_symbol_exists(closefrom "unistd.h" HAVE_CLOSEFROM) #
check_symbol_exists(environ "unistd.h" HAVE_DECL_ENVIRON)
check_symbol_exists(fstatfs "sys/vfs.h" HAVE_FSTATFS)
check_symbol_exists(getgrouplist "grp.h" HAVE_GETGROUPLIST) # dbus-sysdeps.c
+check_symbol_exists(getpeereid "sys/types.h;unistd.h" HAVE_GETPEEREID) # dbus-sysdeps.c,
check_symbol_exists(getpeerucred "ucred.h" HAVE_GETPEERUCRED) # dbus-sysdeps.c, dbus-sysdeps-win.c
check_symbol_exists(getpwnam_r "errno.h;pwd.h" HAVE_GETPWNAM_R) # dbus-sysdeps-util-unix.c
check_symbol_exists(getrandom "sys/random.h" HAVE_GETRANDOM)
diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake
index 77fc19c..2f25643 100644
--- a/cmake/config.h.cmake
+++ b/cmake/config.h.cmake
@@ -140,6 +140,9 @@
/* Define to 1 if you have getgrouplist */
#cmakedefine HAVE_GETGROUPLIST 1
+/* Define to 1 if you have getpeereid */
+#cmakedefine HAVE_GETPEEREID 1
+
/* Define to 1 if you have getpeerucred */
#cmakedefine HAVE_GETPEERUCRED 1

View file

@ -0,0 +1,15 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d3ec71b..932066a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -141,6 +141,10 @@ if(DBUS_LINUX)
if(ENABLE_SYSTEMD AND SYSTEMD_FOUND)
set(DBUS_BUS_ENABLE_SYSTEMD ON)
set(HAVE_SYSTEMD ${SYSTEMD_FOUND})
+ pkg_check_modules(SYSTEMD libsystemd IMPORTED_TARGET)
+ set(SYSTEMD_LIBRARIES PkgConfig::SYSTEMD CACHE INTERNAL "")
+ else()
+ set(SYSTEMD_LIBRARIES "" CACHE INTERNAL "")
endif()
option(ENABLE_USER_SESSION "enable user-session semantics for session bus under systemd" OFF)
set(DBUS_ENABLE_USER_SESSION ${ENABLE_USER_SESSION})

View file

@ -0,0 +1,21 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index caef738..b878f42 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -724,11 +724,11 @@ add_custom_target(help-options
#
if(DBUS_ENABLE_PKGCONFIG)
set(PLATFORM_LIBS pthread ${LIBRT})
- if(PKG_CONFIG_FOUND)
- # convert lists of link libraries into -lstdc++ -lm etc..
- foreach(LIB ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS})
- set(LIBDBUS_LIBS "${LIBDBUS_LIBS} -l${LIB}")
- endforeach()
+ if(1)
+ set(LIBDBUS_LIBS "${CMAKE_THREAD_LIBS_INIT}")
+ if(LIBRT)
+ string(APPEND LIBDBUS_LIBS " -lrt")
+ endif()
set(original_prefix "${CMAKE_INSTALL_PREFIX}")
if(DBUS_RELOCATABLE)
set(pkgconfig_prefix "\${pcfiledir}/../..")

View file

@ -0,0 +1,88 @@
vcpkg_check_linkage(ONLY_DYNAMIC_LIBRARY)
vcpkg_from_gitlab(
GITLAB_URL https://gitlab.freedesktop.org/
OUT_SOURCE_PATH SOURCE_PATH
REPO dbus/dbus
REF "dbus-${VERSION}"
SHA512 8e476b408514e6540c36beb84e8025827c22cda8958b6eb74d22b99c64765eb3cd5a6502aea546e3e5f0534039857b37edee89c659acef40e7cab0939947d4af
HEAD_REF master
PATCHES
cmake.dep.patch
pkgconfig.patch
getpeereid.patch # missing check from configure.ac
libsystemd.patch
)
vcpkg_check_features(OUT_FEATURE_OPTIONS options
FEATURES
systemd ENABLE_SYSTEMD
x11 DBUS_BUILD_X11
x11 CMAKE_REQUIRE_FIND_PACKAGE_X11
)
unset(ENV{DBUSDIR})
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
-DDBUS_BUILD_TESTS=OFF
-DDBUS_ENABLE_DOXYGEN_DOCS=OFF
-DDBUS_ENABLE_XML_DOCS=OFF
-DDBUS_INSTALL_SYSTEM_LIBS=OFF
#-DDBUS_SERVICE=ON
-DDBUS_WITH_GLIB=OFF
-DTHREADS_PREFER_PTHREAD_FLAG=ON
-DXSLTPROC_EXECUTABLE=FALSE
"-DCMAKE_INSTALL_SYSCONFDIR=${CURRENT_PACKAGES_DIR}/etc/${PORT}"
"-DWITH_SYSTEMD_SYSTEMUNITDIR=lib/systemd/system"
"-DWITH_SYSTEMD_USERUNITDIR=lib/systemd/user"
${options}
OPTIONS_RELEASE
-DDBUS_DISABLE_ASSERT=OFF
-DDBUS_ENABLE_STATS=OFF
-DDBUS_ENABLE_VERBOSE_MODE=OFF
MAYBE_UNUSED_VARIABLES
DBUS_BUILD_X11
DBUS_WITH_GLIB
ENABLE_SYSTEMD
THREADS_PREFER_PTHREAD_FLAG
WITH_SYSTEMD_SYSTEMUNITDIR
WITH_SYSTEMD_USERUNITDIR
)
vcpkg_cmake_install()
vcpkg_copy_pdbs()
vcpkg_cmake_config_fixup(PACKAGE_NAME "DBus1" CONFIG_PATH "lib/cmake/DBus1")
vcpkg_fixup_pkgconfig()
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
"${CURRENT_PACKAGES_DIR}/debug/var/"
"${CURRENT_PACKAGES_DIR}/etc"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/services"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/session.d"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/system-services"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/system.d"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/system.conf"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/system.conf"
"${CURRENT_PACKAGES_DIR}/share/doc"
"${CURRENT_PACKAGES_DIR}/var"
)
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/dbus-1/session.conf" "<include ignore_missing=\"yes\">${CURRENT_PACKAGES_DIR}/etc/dbus/dbus-1/session.conf</include>" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/dbus-1/session.conf" "<includedir>${CURRENT_PACKAGES_DIR}/etc/dbus/dbus-1/session.d</includedir>" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/dbus-1/session.conf" "<include ignore_missing=\"yes\">${CURRENT_PACKAGES_DIR}/etc/dbus/dbus-1/session-local.conf</include>" "")
set(TOOLS daemon launch monitor run-session send test-tool update-activation-environment)
if(VCPKG_TARGET_IS_WINDOWS)
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/tools/${PORT}")
file(RENAME "${CURRENT_PACKAGES_DIR}/bin/dbus-env.bat" "${CURRENT_PACKAGES_DIR}/tools/${PORT}/dbus-env.bat")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/tools/${PORT}/dbus-env.bat" "${CURRENT_PACKAGES_DIR}" "%~dp0/../..")
else()
list(APPEND TOOLS cleanup-sockets uuidgen)
endif()
list(TRANSFORM TOOLS PREPEND "dbus-" )
vcpkg_copy_tools(TOOL_NAMES ${TOOLS} AUTO_CLEAN)
file(INSTALL "${SOURCE_PATH}/COPYING" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

View file

@ -0,0 +1,30 @@
{
"name": "dbus",
"version": "1.15.8",
"port-version": 2,
"description": "D-Bus specification and reference implementation, including libdbus and dbus-daemon",
"homepage": "https://gitlab.freedesktop.org/dbus/dbus",
"license": "AFL-2.1 OR GPL-2.0-or-later",
"supports": "!uwp & !staticcrt",
"dependencies": [
"expat",
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
],
"features": {
"x11": {
"description": "Build with X11 autolaunch support",
"dependencies": [
"libx11"
]
}
}
}

View file

@ -0,0 +1,13 @@
diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
index cc8bcf26d..ead829767 100644
--- a/SDL2Config.cmake.in
+++ b/SDL2Config.cmake.in
@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
set(SDL_ALSA @SDL_ALSA@)
set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
+if(SDL_ALSA)
sdlFindALSA()
endif()
unset(SDL_ALSA)

View file

@ -0,0 +1,13 @@
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index 65a98efbe..2f99f28f1 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -352,7 +352,7 @@ endmacro()
# - HAVE_SDL_LOADSO opt
macro(CheckLibSampleRate)
if(SDL_LIBSAMPLERATE)
- find_package(SampleRate QUIET)
+ find_package(SampleRate CONFIG REQUIRED)
if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
set(HAVE_LIBSAMPLERATE TRUE)
set(HAVE_LIBSAMPLERATE_H TRUE)

View file

@ -0,0 +1,137 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO libsdl-org/SDL
REF "release-${VERSION}"
SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
HEAD_REF main
PATCHES
deps.patch
alsa-dep-fix.patch
)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
alsa SDL_ALSA
alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
ibus SDL_IBUS
samplerate SDL_LIBSAMPLERATE
vulkan SDL_VULKAN
wayland SDL_WAYLAND
x11 SDL_X11
INVERTED_FEATURES
alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
)
if ("x11" IN_LIST FEATURES)
message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
endif()
if ("wayland" IN_LIST FEATURES)
message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
endif()
if ("ibus" IN_LIST FEATURES)
message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
endif()
if(VCPKG_TARGET_IS_UWP)
set(configure_opts WINDOWS_USE_MSBUILD)
endif()
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
${configure_opts}
OPTIONS ${FEATURE_OPTIONS}
-DSDL_STATIC=${SDL_STATIC}
-DSDL_SHARED=${SDL_SHARED}
-DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
-DSDL_LIBC=ON
-DSDL_TEST=OFF
-DSDL_INSTALL_CMAKEDIR="cmake"
-DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
-DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
-DSDL_LIBSAMPLERATE_SHARED=OFF
MAYBE_UNUSED_VARIABLES
SDL_FORCE_STATIC_VCRT
PKG_CONFIG_USE_CMAKE_PREFIX_PATH
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
"${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/share/licenses"
"${CURRENT_PACKAGES_DIR}/share/aclocal"
)
file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
if(NOT BINS)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/bin"
"${CURRENT_PACKAGES_DIR}/debug/bin"
)
endif()
if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
endif()
file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
foreach(SHARE_FILE ${SHARE_FILES})
vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
endforeach()
endif()
vcpkg_copy_pdbs()
set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
endif()
if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
endif()
endif()
if(VCPKG_TARGET_IS_UWP)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "d")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
endif()
vcpkg_fixup_pkgconfig()
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")

View file

@ -0,0 +1,8 @@
sdl2 provides CMake targets:
find_package(SDL2 CONFIG REQUIRED)
target_link_libraries(main
PRIVATE
$<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
)

View file

@ -0,0 +1,68 @@
{
"name": "sdl2",
"version": "2.30.0",
"description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
"homepage": "https://www.libsdl.org/download-2.0.php",
"license": "Zlib",
"dependencies": [
{
"name": "dbus",
"default-features": false,
"platform": "linux"
},
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
{
"name": "ibus",
"platform": "linux"
},
{
"name": "wayland",
"platform": "linux"
},
{
"name": "x11",
"platform": "linux"
}
],
"features": {
"alsa": {
"description": "Support for alsa audio",
"dependencies": [
{
"name": "alsa",
"platform": "linux"
}
]
},
"ibus": {
"description": "Build with ibus IME support",
"supports": "linux"
},
"samplerate": {
"description": "Use libsamplerate for audio rate conversion",
"dependencies": [
"libsamplerate"
]
},
"vulkan": {
"description": "Vulkan functionality for SDL"
},
"wayland": {
"description": "Build with Wayland support",
"supports": "linux"
},
"x11": {
"description": "Build with X11 support",
"supports": "!windows"
}
}
}

View file

@ -0,0 +1,13 @@
diff --git a/cmake/FindCMath.cmake b/cmake/FindCMath.cmake
index ad92218..dd42aba 100644
--- a/cmake/FindCMath.cmake
+++ b/cmake/FindCMath.cmake
@@ -31,7 +31,7 @@ include(CheckSymbolExists)
include(CheckLibraryExists)
check_symbol_exists(pow "math.h" CMath_HAVE_LIBC_POW)
-find_library(CMath_LIBRARY NAMES m)
+find_library(CMath_LIBRARY NAMES m PATHS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
if(NOT CMath_HAVE_LIBC_POW)
set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})

View file

@ -0,0 +1,86 @@
vcpkg_from_gitlab(
GITLAB_URL https://gitlab.com
OUT_SOURCE_PATH SOURCE_PATH
REPO libtiff/libtiff
REF "v${VERSION}"
SHA512 ef2f1d424219d9e245069b7d23e78f5e817cf6ee516d46694915ab6c8909522166f84997513d20a702f4e52c3f18467813935b328fafa34bea5156dee00f66fa
HEAD_REF master
PATCHES
FindCMath.patch
)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
cxx cxx
jpeg jpeg
jpeg CMAKE_REQUIRE_FIND_PACKAGE_JPEG
libdeflate libdeflate
libdeflate CMAKE_REQUIRE_FIND_PACKAGE_Deflate
lzma lzma
lzma CMAKE_REQUIRE_FIND_PACKAGE_liblzma
tools tiff-tools
webp webp
webp CMAKE_REQUIRE_FIND_PACKAGE_WebP
zip zlib
zip CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
zstd zstd
zstd CMAKE_REQUIRE_FIND_PACKAGE_ZSTD
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
${FEATURE_OPTIONS}
-DCMAKE_FIND_PACKAGE_PREFER_CONFIG=ON
-Dtiff-docs=OFF
-Dtiff-contrib=OFF
-Dtiff-tests=OFF
-Djbig=OFF # This is disabled by default due to GPL/Proprietary licensing.
-Djpeg12=OFF
-Dlerc=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_OpenGL=ON
-DCMAKE_DISABLE_FIND_PACKAGE_GLUT=ON
-DZSTD_HAVE_DECOMPRESS_STREAM=ON
-DHAVE_JPEGTURBO_DUAL_MODE_8_12=OFF
OPTIONS_DEBUG
-DCMAKE_DEBUG_POSTFIX=d # tiff sets "d" for MSVC only.
MAYBE_UNUSED_VARIABLES
CMAKE_DISABLE_FIND_PACKAGE_GLUT
CMAKE_DISABLE_FIND_PACKAGE_OpenGL
ZSTD_HAVE_DECOMPRESS_STREAM
)
vcpkg_cmake_install()
# CMake config wasn't packaged in the past and is not yet usable now,
# cf. https://gitlab.com/libtiff/libtiff/-/merge_requests/496
# vcpkg_cmake_config_fixup(CONFIG_PATH "lib/cmake/tiff")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/cmake" "${CURRENT_PACKAGES_DIR}/debug/lib/cmake")
set(_file "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libtiff-4.pc")
if(EXISTS "${_file}")
vcpkg_replace_string("${_file}" "-ltiff" "-ltiffd")
endif()
vcpkg_fixup_pkgconfig()
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
)
configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake.in" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY)
if ("tools" IN_LIST FEATURES)
vcpkg_copy_tools(TOOL_NAMES
tiffcp
tiffdump
tiffinfo
tiffset
tiffsplit
AUTO_CLEAN
)
endif()
vcpkg_copy_pdbs()
file(COPY "${CURRENT_PORT_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.md")

View file

@ -0,0 +1,9 @@
tiff is compatible with built-in CMake targets:
find_package(TIFF REQUIRED)
target_link_libraries(main PRIVATE TIFF::TIFF)
tiff provides pkg-config modules:
# Tag Image File Format (TIFF) library.
libtiff-4

View file

@ -0,0 +1,104 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0012 NEW)
cmake_policy(SET CMP0057 NEW)
set(z_vcpkg_tiff_find_options "")
if("REQUIRED" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "REQUIRED")
endif()
if("QUIET" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "QUIET")
endif()
_find_package(${ARGS})
if(TIFF_FOUND AND "@VCPKG_LIBRARY_LINKAGE@" STREQUAL "static")
include(SelectLibraryConfigurations)
set(z_vcpkg_tiff_link_libraries "")
set(z_vcpkg_tiff_libraries "")
if("@webp@")
find_package(WebP CONFIG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:WebP::WebP>")
list(APPEND z_vcpkg_tiff_libraries ${WebP_LIBRARIES})
endif()
if("@lzma@")
find_package(LibLZMA ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:LibLZMA::LibLZMA>")
list(APPEND z_vcpkg_tiff_libraries ${LIBLZMA_LIBRARIES})
endif()
if("@jpeg@")
find_package(JPEG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:JPEG::JPEG>")
list(APPEND z_vcpkg_tiff_libraries ${JPEG_LIBRARIES})
endif()
if("@zstd@")
find_package(zstd CONFIG ${z_vcpkg_tiff_find_options})
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_LOCATION_")
if(TARGET zstd::libzstd_shared)
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_shared>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_shared)
if(WIN32)
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_static>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_static)
endif()
get_target_property(z_vcpkg_tiff_zstd_configs "${z_vcpkg_tiff_zstd_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_tiff_zstd_configs)
get_target_property(ZSTD_LIBRARY_${z_vcpkg_config} "${z_vcpkg_tiff_zstd_target}" "${z_vcpkg_tiff_zstd_target_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(ZSTD)
if(NOT TARGET ZSTD::ZSTD)
add_library(ZSTD::ZSTD INTERFACE IMPORTED)
set_property(TARGET ZSTD::ZSTD APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_zstd})
endif()
list(APPEND z_vcpkg_tiff_link_libraries ${z_vcpkg_tiff_zstd})
list(APPEND z_vcpkg_tiff_libraries ${ZSTD_LIBRARIES})
unset(z_vcpkg_tiff_zstd)
unset(z_vcpkg_tiff_zstd_configs)
unset(z_vcpkg_config)
unset(z_vcpkg_tiff_zstd_target)
endif()
if("@libdeflate@")
find_package(libdeflate ${z_vcpkg_tiff_find_options})
set(z_vcpkg_property "IMPORTED_LOCATION_")
if(TARGET libdeflate::libdeflate_shared)
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_shared)
if(WIN32)
set(z_vcpkg_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_static)
endif()
get_target_property(z_vcpkg_libdeflate_configs "${z_vcpkg_libdeflate_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_libdeflate_configs)
get_target_property(Z_VCPKG_DEFLATE_LIBRARY_${z_vcpkg_config} "${z_vcpkg_libdeflate_target}" "${z_vcpkg_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(Z_VCPKG_DEFLATE)
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:${z_vcpkg_libdeflate_target}>")
list(APPEND z_vcpkg_tiff_libraries ${Z_VCPKG_DEFLATE_LIBRARIES})
unset(z_vcpkg_config)
unset(z_vcpkg_libdeflate_configs)
unset(z_vcpkg_libdeflate_target)
unset(z_vcpkg_property)
unset(Z_VCPKG_DEFLATE_FOUND)
endif()
if("@zlib@")
find_package(ZLIB ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:ZLIB::ZLIB>")
list(APPEND z_vcpkg_tiff_libraries ${ZLIB_LIBRARIES})
endif()
if(UNIX)
list(APPEND z_vcpkg_tiff_link_libraries m)
list(APPEND z_vcpkg_tiff_libraries m)
endif()
if(TARGET TIFF::TIFF)
set_property(TARGET TIFF::TIFF APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_link_libraries})
endif()
list(APPEND TIFF_LIBRARIES ${z_vcpkg_tiff_libraries})
unset(z_vcpkg_tiff_link_libraries)
unset(z_vcpkg_tiff_libraries)
endif()
unset(z_vcpkg_tiff_find_options)
cmake_policy(POP)

View file

@ -0,0 +1,67 @@
{
"name": "tiff",
"version": "4.6.0",
"port-version": 2,
"description": "A library that supports the manipulation of TIFF image files",
"homepage": "https://libtiff.gitlab.io/libtiff/",
"license": "libtiff",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
"jpeg",
"zip"
],
"features": {
"cxx": {
"description": "Build C++ libtiffxx library"
},
"jpeg": {
"description": "Support JPEG compression in TIFF image files",
"dependencies": [
"libjpeg-turbo"
]
},
"libdeflate": {
"description": "Use libdeflate for faster ZIP support",
"dependencies": [
"libdeflate",
{
"name": "tiff",
"default-features": false,
"features": [
"zip"
]
}
]
},
"tools": {
"description": "Build tools"
},
"webp": {
"description": "Support WEBP compression in TIFF image files",
"dependencies": [
"libwebp"
]
},
"zip": {
"description": "Support ZIP/deflate compression in TIFF image files",
"dependencies": [
"zlib"
]
},
"zstd": {
"description": "Support ZSTD compression in TIFF image files",
"dependencies": [
"zstd"
]
}
}
}

View file

@ -0,0 +1,13 @@
diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
index cc8bcf26d..ead829767 100644
--- a/SDL2Config.cmake.in
+++ b/SDL2Config.cmake.in
@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
set(SDL_ALSA @SDL_ALSA@)
set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
+if(SDL_ALSA)
sdlFindALSA()
endif()
unset(SDL_ALSA)

View file

@ -0,0 +1,13 @@
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index 65a98efbe..2f99f28f1 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -352,7 +352,7 @@ endmacro()
# - HAVE_SDL_LOADSO opt
macro(CheckLibSampleRate)
if(SDL_LIBSAMPLERATE)
- find_package(SampleRate QUIET)
+ find_package(SampleRate CONFIG REQUIRED)
if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
set(HAVE_LIBSAMPLERATE TRUE)
set(HAVE_LIBSAMPLERATE_H TRUE)

View file

@ -0,0 +1,137 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO libsdl-org/SDL
REF "release-${VERSION}"
SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
HEAD_REF main
PATCHES
deps.patch
alsa-dep-fix.patch
)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
alsa SDL_ALSA
alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
ibus SDL_IBUS
samplerate SDL_LIBSAMPLERATE
vulkan SDL_VULKAN
wayland SDL_WAYLAND
x11 SDL_X11
INVERTED_FEATURES
alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
)
if ("x11" IN_LIST FEATURES)
message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
endif()
if ("wayland" IN_LIST FEATURES)
message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
endif()
if ("ibus" IN_LIST FEATURES)
message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
endif()
if(VCPKG_TARGET_IS_UWP)
set(configure_opts WINDOWS_USE_MSBUILD)
endif()
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
${configure_opts}
OPTIONS ${FEATURE_OPTIONS}
-DSDL_STATIC=${SDL_STATIC}
-DSDL_SHARED=${SDL_SHARED}
-DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
-DSDL_LIBC=ON
-DSDL_TEST=OFF
-DSDL_INSTALL_CMAKEDIR="cmake"
-DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
-DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
-DSDL_LIBSAMPLERATE_SHARED=OFF
MAYBE_UNUSED_VARIABLES
SDL_FORCE_STATIC_VCRT
PKG_CONFIG_USE_CMAKE_PREFIX_PATH
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
"${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/share/licenses"
"${CURRENT_PACKAGES_DIR}/share/aclocal"
)
file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
if(NOT BINS)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/bin"
"${CURRENT_PACKAGES_DIR}/debug/bin"
)
endif()
if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
endif()
file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
foreach(SHARE_FILE ${SHARE_FILES})
vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
endforeach()
endif()
vcpkg_copy_pdbs()
set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
endif()
if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
endif()
endif()
if(VCPKG_TARGET_IS_UWP)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "d")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
endif()
vcpkg_fixup_pkgconfig()
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")

View file

@ -0,0 +1,8 @@
sdl2 provides CMake targets:
find_package(SDL2 CONFIG REQUIRED)
target_link_libraries(main
PRIVATE
$<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
)

View file

@ -0,0 +1,68 @@
{
"name": "sdl2",
"version": "2.30.0",
"description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
"homepage": "https://www.libsdl.org/download-2.0.php",
"license": "Zlib",
"dependencies": [
{
"name": "dbus",
"default-features": false,
"platform": "linux"
},
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
{
"name": "ibus",
"platform": "linux"
},
{
"name": "wayland",
"platform": "linux"
},
{
"name": "x11",
"platform": "linux"
}
],
"features": {
"alsa": {
"description": "Support for alsa audio",
"dependencies": [
{
"name": "alsa",
"platform": "linux"
}
]
},
"ibus": {
"description": "Build with ibus IME support",
"supports": "linux"
},
"samplerate": {
"description": "Use libsamplerate for audio rate conversion",
"dependencies": [
"libsamplerate"
]
},
"vulkan": {
"description": "Vulkan functionality for SDL"
},
"wayland": {
"description": "Build with Wayland support",
"supports": "linux"
},
"x11": {
"description": "Build with X11 support",
"supports": "!windows"
}
}
}

View file

@ -0,0 +1,13 @@
diff --git a/cmake/FindCMath.cmake b/cmake/FindCMath.cmake
index ad92218..dd42aba 100644
--- a/cmake/FindCMath.cmake
+++ b/cmake/FindCMath.cmake
@@ -31,7 +31,7 @@ include(CheckSymbolExists)
include(CheckLibraryExists)
check_symbol_exists(pow "math.h" CMath_HAVE_LIBC_POW)
-find_library(CMath_LIBRARY NAMES m)
+find_library(CMath_LIBRARY NAMES m PATHS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
if(NOT CMath_HAVE_LIBC_POW)
set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})

View file

@ -0,0 +1,86 @@
vcpkg_from_gitlab(
GITLAB_URL https://gitlab.com
OUT_SOURCE_PATH SOURCE_PATH
REPO libtiff/libtiff
REF "v${VERSION}"
SHA512 ef2f1d424219d9e245069b7d23e78f5e817cf6ee516d46694915ab6c8909522166f84997513d20a702f4e52c3f18467813935b328fafa34bea5156dee00f66fa
HEAD_REF master
PATCHES
FindCMath.patch
)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
cxx cxx
jpeg jpeg
jpeg CMAKE_REQUIRE_FIND_PACKAGE_JPEG
libdeflate libdeflate
libdeflate CMAKE_REQUIRE_FIND_PACKAGE_Deflate
lzma lzma
lzma CMAKE_REQUIRE_FIND_PACKAGE_liblzma
tools tiff-tools
webp webp
webp CMAKE_REQUIRE_FIND_PACKAGE_WebP
zip zlib
zip CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
zstd zstd
zstd CMAKE_REQUIRE_FIND_PACKAGE_ZSTD
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
${FEATURE_OPTIONS}
-DCMAKE_FIND_PACKAGE_PREFER_CONFIG=ON
-Dtiff-docs=OFF
-Dtiff-contrib=OFF
-Dtiff-tests=OFF
-Djbig=OFF # This is disabled by default due to GPL/Proprietary licensing.
-Djpeg12=OFF
-Dlerc=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_OpenGL=ON
-DCMAKE_DISABLE_FIND_PACKAGE_GLUT=ON
-DZSTD_HAVE_DECOMPRESS_STREAM=ON
-DHAVE_JPEGTURBO_DUAL_MODE_8_12=OFF
OPTIONS_DEBUG
-DCMAKE_DEBUG_POSTFIX=d # tiff sets "d" for MSVC only.
MAYBE_UNUSED_VARIABLES
CMAKE_DISABLE_FIND_PACKAGE_GLUT
CMAKE_DISABLE_FIND_PACKAGE_OpenGL
ZSTD_HAVE_DECOMPRESS_STREAM
)
vcpkg_cmake_install()
# CMake config wasn't packaged in the past and is not yet usable now,
# cf. https://gitlab.com/libtiff/libtiff/-/merge_requests/496
# vcpkg_cmake_config_fixup(CONFIG_PATH "lib/cmake/tiff")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/cmake" "${CURRENT_PACKAGES_DIR}/debug/lib/cmake")
set(_file "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libtiff-4.pc")
if(EXISTS "${_file}")
vcpkg_replace_string("${_file}" "-ltiff" "-ltiffd")
endif()
vcpkg_fixup_pkgconfig()
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
)
configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake.in" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY)
if ("tools" IN_LIST FEATURES)
vcpkg_copy_tools(TOOL_NAMES
tiffcp
tiffdump
tiffinfo
tiffset
tiffsplit
AUTO_CLEAN
)
endif()
vcpkg_copy_pdbs()
file(COPY "${CURRENT_PORT_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.md")

View file

@ -0,0 +1,9 @@
tiff is compatible with built-in CMake targets:
find_package(TIFF REQUIRED)
target_link_libraries(main PRIVATE TIFF::TIFF)
tiff provides pkg-config modules:
# Tag Image File Format (TIFF) library.
libtiff-4

View file

@ -0,0 +1,104 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0012 NEW)
cmake_policy(SET CMP0057 NEW)
set(z_vcpkg_tiff_find_options "")
if("REQUIRED" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "REQUIRED")
endif()
if("QUIET" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "QUIET")
endif()
_find_package(${ARGS})
if(TIFF_FOUND AND "@VCPKG_LIBRARY_LINKAGE@" STREQUAL "static")
include(SelectLibraryConfigurations)
set(z_vcpkg_tiff_link_libraries "")
set(z_vcpkg_tiff_libraries "")
if("@webp@")
find_package(WebP CONFIG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:WebP::WebP>")
list(APPEND z_vcpkg_tiff_libraries ${WebP_LIBRARIES})
endif()
if("@lzma@")
find_package(LibLZMA ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:LibLZMA::LibLZMA>")
list(APPEND z_vcpkg_tiff_libraries ${LIBLZMA_LIBRARIES})
endif()
if("@jpeg@")
find_package(JPEG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:JPEG::JPEG>")
list(APPEND z_vcpkg_tiff_libraries ${JPEG_LIBRARIES})
endif()
if("@zstd@")
find_package(zstd CONFIG ${z_vcpkg_tiff_find_options})
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_LOCATION_")
if(TARGET zstd::libzstd_shared)
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_shared>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_shared)
if(WIN32)
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_static>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_static)
endif()
get_target_property(z_vcpkg_tiff_zstd_configs "${z_vcpkg_tiff_zstd_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_tiff_zstd_configs)
get_target_property(ZSTD_LIBRARY_${z_vcpkg_config} "${z_vcpkg_tiff_zstd_target}" "${z_vcpkg_tiff_zstd_target_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(ZSTD)
if(NOT TARGET ZSTD::ZSTD)
add_library(ZSTD::ZSTD INTERFACE IMPORTED)
set_property(TARGET ZSTD::ZSTD APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_zstd})
endif()
list(APPEND z_vcpkg_tiff_link_libraries ${z_vcpkg_tiff_zstd})
list(APPEND z_vcpkg_tiff_libraries ${ZSTD_LIBRARIES})
unset(z_vcpkg_tiff_zstd)
unset(z_vcpkg_tiff_zstd_configs)
unset(z_vcpkg_config)
unset(z_vcpkg_tiff_zstd_target)
endif()
if("@libdeflate@")
find_package(libdeflate ${z_vcpkg_tiff_find_options})
set(z_vcpkg_property "IMPORTED_LOCATION_")
if(TARGET libdeflate::libdeflate_shared)
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_shared)
if(WIN32)
set(z_vcpkg_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_static)
endif()
get_target_property(z_vcpkg_libdeflate_configs "${z_vcpkg_libdeflate_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_libdeflate_configs)
get_target_property(Z_VCPKG_DEFLATE_LIBRARY_${z_vcpkg_config} "${z_vcpkg_libdeflate_target}" "${z_vcpkg_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(Z_VCPKG_DEFLATE)
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:${z_vcpkg_libdeflate_target}>")
list(APPEND z_vcpkg_tiff_libraries ${Z_VCPKG_DEFLATE_LIBRARIES})
unset(z_vcpkg_config)
unset(z_vcpkg_libdeflate_configs)
unset(z_vcpkg_libdeflate_target)
unset(z_vcpkg_property)
unset(Z_VCPKG_DEFLATE_FOUND)
endif()
if("@zlib@")
find_package(ZLIB ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:ZLIB::ZLIB>")
list(APPEND z_vcpkg_tiff_libraries ${ZLIB_LIBRARIES})
endif()
if(UNIX)
list(APPEND z_vcpkg_tiff_link_libraries m)
list(APPEND z_vcpkg_tiff_libraries m)
endif()
if(TARGET TIFF::TIFF)
set_property(TARGET TIFF::TIFF APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_link_libraries})
endif()
list(APPEND TIFF_LIBRARIES ${z_vcpkg_tiff_libraries})
unset(z_vcpkg_tiff_link_libraries)
unset(z_vcpkg_tiff_libraries)
endif()
unset(z_vcpkg_tiff_find_options)
cmake_policy(POP)

View file

@ -0,0 +1,67 @@
{
"name": "tiff",
"version": "4.6.0",
"port-version": 2,
"description": "A library that supports the manipulation of TIFF image files",
"homepage": "https://libtiff.gitlab.io/libtiff/",
"license": "libtiff",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
"jpeg",
"zip"
],
"features": {
"cxx": {
"description": "Build C++ libtiffxx library"
},
"jpeg": {
"description": "Support JPEG compression in TIFF image files",
"dependencies": [
"libjpeg-turbo"
]
},
"libdeflate": {
"description": "Use libdeflate for faster ZIP support",
"dependencies": [
"libdeflate",
{
"name": "tiff",
"default-features": false,
"features": [
"zip"
]
}
]
},
"tools": {
"description": "Build tools"
},
"webp": {
"description": "Support WEBP compression in TIFF image files",
"dependencies": [
"libwebp"
]
},
"zip": {
"description": "Support ZIP/deflate compression in TIFF image files",
"dependencies": [
"zlib"
]
},
"zstd": {
"description": "Support ZSTD compression in TIFF image files",
"dependencies": [
"zstd"
]
}
}
}

View file

@ -10,8 +10,6 @@ curl -sSfL https://github.com"$(curl https://github.com/probonopd/go-appimage/re
chmod a+x mkappimage.AppImage chmod a+x mkappimage.AppImage
curl -sSfLO "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh" curl -sSfLO "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh"
chmod a+x linuxdeploy-plugin-gtk.sh chmod a+x linuxdeploy-plugin-gtk.sh
curl -sSfLO "https://github.com/darealshinji/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt.sh"
chmod a+x linuxdeploy-plugin-checkrt.sh
if [[ ! -e /usr/lib/x86_64-linux-gnu ]]; then if [[ ! -e /usr/lib/x86_64-linux-gnu ]]; then
sed -i 's#lib\/x86_64-linux-gnu#lib64#g' linuxdeploy-plugin-gtk.sh sed -i 's#lib\/x86_64-linux-gnu#lib64#g' linuxdeploy-plugin-gtk.sh
@ -35,14 +33,12 @@ chmod +x AppDir/usr/bin/Cemu
cp /usr/lib/x86_64-linux-gnu/{libsepol.so.1,libffi.so.7,libpcre.so.3,libGLU.so.1,libthai.so.0} AppDir/usr/lib cp /usr/lib/x86_64-linux-gnu/{libsepol.so.1,libffi.so.7,libpcre.so.3,libGLU.so.1,libthai.so.0} AppDir/usr/lib
export UPD_INFO="gh-releases-zsync|cemu-project|Cemu|ci|Cemu.AppImage.zsync" export UPD_INFO="gh-releases-zsync|cemu-project|Cemu|ci|Cemu.AppImage.zsync"
export NO_STRIP=1
./linuxdeploy-x86_64.AppImage --appimage-extract-and-run \ ./linuxdeploy-x86_64.AppImage --appimage-extract-and-run \
--appdir="${GITHUB_WORKSPACE}"/AppDir/ \ --appdir="${GITHUB_WORKSPACE}"/AppDir/ \
-d "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.desktop \ -d "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.desktop \
-i "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.png \ -i "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.png \
-e "${GITHUB_WORKSPACE}"/AppDir/usr/bin/Cemu \ -e "${GITHUB_WORKSPACE}"/AppDir/usr/bin/Cemu \
--plugin gtk \ --plugin gtk
--plugin checkrt
if ! GITVERSION="$(git rev-parse --short HEAD 2>/dev/null)"; then if ! GITVERSION="$(git rev-parse --short HEAD 2>/dev/null)"; then
GITVERSION=experimental GITVERSION=experimental
@ -50,6 +46,7 @@ fi
echo "Cemu Version Cemu-${GITVERSION}" echo "Cemu Version Cemu-${GITVERSION}"
rm AppDir/usr/lib/libwayland-client.so.0 rm AppDir/usr/lib/libwayland-client.so.0
cp /lib/x86_64-linux-gnu/libstdc++.so.6 AppDir/usr/lib/
echo -e "export LC_ALL=C\nexport FONTCONFIG_PATH=/etc/fonts" >> AppDir/apprun-hooks/linuxdeploy-plugin-gtk.sh echo -e "export LC_ALL=C\nexport FONTCONFIG_PATH=/etc/fonts" >> AppDir/apprun-hooks/linuxdeploy-plugin-gtk.sh
VERSION="${GITVERSION}" ./mkappimage.AppImage --appimage-extract-and-run "${GITHUB_WORKSPACE}"/AppDir VERSION="${GITVERSION}" ./mkappimage.AppImage --appimage-extract-and-run "${GITHUB_WORKSPACE}"/AppDir

View file

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<content>
<networkname>CustomExample</networkname>
<disablesslverification>0</disablesslverification>
<urls>
<act>https://account.nintendo.net</act>
<ecs>https://ecs.wup.shop.nintendo.net/ecs/services/ECommerceSOAP</ecs>
<nus>https://nus.wup.shop.nintendo.net/nus/services/NetUpdateSOAP</nus>
<ias>https://ias.wup.shop.nintendo.net/ias/services/IdentityAuthenticationSOAP</ias>
<ccsu>https://ccs.wup.shop.nintendo.net/ccs/download</ccsu>
<ccs>http://ccs.cdn.wup.shop.nintendo.net/ccs/download</ccs>
<idbe>https://idbe-wup.cdn.nintendo.net/icondata</idbe>
<boss>https://npts.app.nintendo.net/p01/tasksheet</boss>
<tagaya>https://tagaya.wup.shop.nintendo.net/tagaya/versionlist</tagaya>
<olv>https://discovery.olv.nintendo.net/v1/endpoint</olv>
</urls>
</content>

View file

@ -56,12 +56,6 @@ add_executable(CemuBin
mainLLE.cpp mainLLE.cpp
) )
if(MSVC AND MSVC_VERSION EQUAL 1940)
# workaround for an msvc issue on VS 17.10 where generated ILK files are too large
# see https://developercommunity.visualstudio.com/t/After-updating-to-VS-1710-the-size-of-/10665511
set_target_properties(CemuBin PROPERTIES LINK_FLAGS "/INCREMENTAL:NO")
endif()
if(WIN32) if(WIN32)
target_sources(CemuBin PRIVATE target_sources(CemuBin PRIVATE
resource/cemu.rc resource/cemu.rc
@ -82,8 +76,8 @@ if (MACOS_BUNDLE)
set(MACOSX_BUNDLE_ICON_FILE "cemu.icns") set(MACOSX_BUNDLE_ICON_FILE "cemu.icns")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "info.cemu.Cemu") set(MACOSX_BUNDLE_GUI_IDENTIFIER "info.cemu.Cemu")
set(MACOSX_BUNDLE_BUNDLE_NAME "Cemu") set(MACOSX_BUNDLE_BUNDLE_NAME "Cemu")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}") set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${CMAKE_PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}") set(MACOSX_BUNDLE_BUNDLE_VERSION ${CMAKE_PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2024 Cemu Project") set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2024 Cemu Project")
set(MACOSX_BUNDLE_CATEGORY "public.app-category.games") set(MACOSX_BUNDLE_CATEGORY "public.app-category.games")
@ -101,18 +95,11 @@ if (MACOS_BUNDLE)
COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory "${CMAKE_SOURCE_DIR}/bin/${folder}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/SharedSupport/${folder}") COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory "${CMAKE_SOURCE_DIR}/bin/${folder}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/SharedSupport/${folder}")
endforeach(folder) endforeach(folder)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(LIBUSB_PATH "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-osx/debug/lib/libusb-1.0.0.dylib")
else()
set(LIBUSB_PATH "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-osx/lib/libusb-1.0.0.dylib")
endif()
add_custom_command (TARGET CemuBin POST_BUILD add_custom_command (TARGET CemuBin POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib" COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib"
COMMAND ${CMAKE_COMMAND} ARGS -E copy "${LIBUSB_PATH}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libusb-1.0.0.dylib" COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-osx/lib/libusb-1.0.0.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libusb-1.0.0.dylib"
COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_SOURCE_DIR}/src/resource/update.sh" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/update.sh"
COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}" COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}"
COMMAND bash -c "install_name_tool -change ${LIBUSB_PATH} @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
endif() endif()
set_target_properties(CemuBin PROPERTIES set_target_properties(CemuBin PROPERTIES

View file

@ -10,7 +10,6 @@ add_library(CemuCafe
Filesystem/fscDeviceRedirect.cpp Filesystem/fscDeviceRedirect.cpp
Filesystem/fscDeviceWua.cpp Filesystem/fscDeviceWua.cpp
Filesystem/fscDeviceWud.cpp Filesystem/fscDeviceWud.cpp
Filesystem/fscDeviceWuhb.cpp
Filesystem/fsc.h Filesystem/fsc.h
Filesystem/FST/FST.cpp Filesystem/FST/FST.cpp
Filesystem/FST/FST.h Filesystem/FST/FST.h
@ -19,9 +18,6 @@ add_library(CemuCafe
Filesystem/FST/KeyCache.h Filesystem/FST/KeyCache.h
Filesystem/WUD/wud.cpp Filesystem/WUD/wud.cpp
Filesystem/WUD/wud.h Filesystem/WUD/wud.h
Filesystem/WUHB/RomFSStructs.h
Filesystem/WUHB/WUHBReader.cpp
Filesystem/WUHB/WUHBReader.h
GamePatch.cpp GamePatch.cpp
GamePatch.h GamePatch.h
GameProfile/GameProfile.cpp GameProfile/GameProfile.cpp
@ -218,8 +214,6 @@ add_library(CemuCafe
HW/SI/SI.cpp HW/SI/SI.cpp
HW/SI/si.h HW/SI/si.h
HW/VI/VI.cpp HW/VI/VI.cpp
IOSU/ccr_nfc/iosu_ccr_nfc.cpp
IOSU/ccr_nfc/iosu_ccr_nfc.h
IOSU/fsa/fsa_types.h IOSU/fsa/fsa_types.h
IOSU/fsa/iosu_fsa.cpp IOSU/fsa/iosu_fsa.cpp
IOSU/fsa/iosu_fsa.h IOSU/fsa/iosu_fsa.h
@ -374,24 +368,12 @@ add_library(CemuCafe
OS/libs/gx2/GX2_Texture.h OS/libs/gx2/GX2_Texture.h
OS/libs/gx2/GX2_TilingAperture.cpp OS/libs/gx2/GX2_TilingAperture.cpp
OS/libs/h264_avc/H264Dec.cpp OS/libs/h264_avc/H264Dec.cpp
OS/libs/h264_avc/H264DecBackendAVC.cpp
OS/libs/h264_avc/h264dec.h OS/libs/h264_avc/h264dec.h
OS/libs/h264_avc/H264DecInternal.h
OS/libs/h264_avc/parser OS/libs/h264_avc/parser
OS/libs/h264_avc/parser/H264Parser.cpp OS/libs/h264_avc/parser/H264Parser.cpp
OS/libs/h264_avc/parser/H264Parser.h OS/libs/h264_avc/parser/H264Parser.h
OS/libs/mic/mic.cpp OS/libs/mic/mic.cpp
OS/libs/mic/mic.h OS/libs/mic/mic.h
OS/libs/nfc/ndef.cpp
OS/libs/nfc/ndef.h
OS/libs/nfc/nfc.cpp
OS/libs/nfc/nfc.h
OS/libs/nfc/stream.cpp
OS/libs/nfc/stream.h
OS/libs/nfc/TagV0.cpp
OS/libs/nfc/TagV0.h
OS/libs/nfc/TLV.cpp
OS/libs/nfc/TLV.h
OS/libs/nlibcurl/nlibcurl.cpp OS/libs/nlibcurl/nlibcurl.cpp
OS/libs/nlibcurl/nlibcurlDebug.hpp OS/libs/nlibcurl/nlibcurlDebug.hpp
OS/libs/nlibcurl/nlibcurl.h OS/libs/nlibcurl/nlibcurl.h
@ -459,22 +441,14 @@ add_library(CemuCafe
OS/libs/nsyshid/AttachDefaultBackends.cpp OS/libs/nsyshid/AttachDefaultBackends.cpp
OS/libs/nsyshid/Whitelist.cpp OS/libs/nsyshid/Whitelist.cpp
OS/libs/nsyshid/Whitelist.h OS/libs/nsyshid/Whitelist.h
OS/libs/nsyshid/BackendEmulated.cpp
OS/libs/nsyshid/BackendEmulated.h
OS/libs/nsyshid/BackendLibusb.cpp OS/libs/nsyshid/BackendLibusb.cpp
OS/libs/nsyshid/BackendLibusb.h OS/libs/nsyshid/BackendLibusb.h
OS/libs/nsyshid/Dimensions.cpp OS/libs/nsyshid/BackendWindowsHID.cpp
OS/libs/nsyshid/Dimensions.h OS/libs/nsyshid/BackendWindowsHID.h
OS/libs/nsyshid/Infinity.cpp
OS/libs/nsyshid/Infinity.h
OS/libs/nsyshid/Skylander.cpp
OS/libs/nsyshid/Skylander.h
OS/libs/nsyskbd/nsyskbd.cpp OS/libs/nsyskbd/nsyskbd.cpp
OS/libs/nsyskbd/nsyskbd.h OS/libs/nsyskbd/nsyskbd.h
OS/libs/nsysnet/nsysnet.cpp OS/libs/nsysnet/nsysnet.cpp
OS/libs/nsysnet/nsysnet.h OS/libs/nsysnet/nsysnet.h
OS/libs/ntag/ntag.cpp
OS/libs/ntag/ntag.h
OS/libs/padscore/padscore.cpp OS/libs/padscore/padscore.cpp
OS/libs/padscore/padscore.h OS/libs/padscore/padscore.h
OS/libs/proc_ui/proc_ui.cpp OS/libs/proc_ui/proc_ui.cpp
@ -530,12 +504,6 @@ set_property(TARGET CemuCafe PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CON
target_include_directories(CemuCafe PUBLIC "../") target_include_directories(CemuCafe PUBLIC "../")
if (glslang_VERSION VERSION_LESS "15.0.0")
set(glslang_target "glslang::SPIRV")
else()
set(glslang_target "glslang")
endif()
target_link_libraries(CemuCafe PRIVATE target_link_libraries(CemuCafe PRIVATE
CemuAsm CemuAsm
CemuAudio CemuAudio
@ -551,7 +519,7 @@ target_link_libraries(CemuCafe PRIVATE
Boost::nowide Boost::nowide
CURL::libcurl CURL::libcurl
fmt::fmt fmt::fmt
${glslang_target} glslang::SPIRV
ih264d ih264d
OpenSSL::Crypto OpenSSL::Crypto
OpenSSL::SSL OpenSSL::SSL
@ -567,16 +535,15 @@ if (ENABLE_WAYLAND)
target_link_libraries(CemuCafe PUBLIC Wayland::Client) target_link_libraries(CemuCafe PUBLIC Wayland::Client)
endif() endif()
if (ENABLE_VCPKG) if (ENABLE_NSYSHID_LIBUSB)
if(WIN32) if (ENABLE_VCPKG)
set(PKG_CONFIG_EXECUTABLE "${VCPKG_INSTALLED_DIR}/x64-windows/tools/pkgconf/pkgconf.exe") find_package(PkgConfig REQUIRED)
endif() pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0)
find_package(PkgConfig REQUIRED) target_link_libraries(CemuCafe PRIVATE PkgConfig::libusb)
pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0) else ()
target_link_libraries(CemuCafe PRIVATE PkgConfig::libusb) find_package(libusb MODULE REQUIRED)
else () target_link_libraries(CemuCafe PRIVATE libusb::libusb)
find_package(libusb MODULE REQUIRED) endif ()
target_link_libraries(CemuCafe PRIVATE libusb::libusb)
endif () endif ()
if (ENABLE_WXWIDGETS) if (ENABLE_WXWIDGETS)

View file

@ -9,7 +9,6 @@
#include "audio/IAudioAPI.h" #include "audio/IAudioAPI.h"
#include "audio/IAudioInputAPI.h" #include "audio/IAudioInputAPI.h"
#include "config/ActiveSettings.h" #include "config/ActiveSettings.h"
#include "config/LaunchSettings.h"
#include "Cafe/TitleList/GameInfo.h" #include "Cafe/TitleList/GameInfo.h"
#include "Cafe/GraphicPack/GraphicPack2.h" #include "Cafe/GraphicPack/GraphicPack2.h"
#include "util/helpers/SystemException.h" #include "util/helpers/SystemException.h"
@ -36,7 +35,6 @@
#include "Cafe/IOSU/legacy/iosu_boss.h" #include "Cafe/IOSU/legacy/iosu_boss.h"
#include "Cafe/IOSU/legacy/iosu_nim.h" #include "Cafe/IOSU/legacy/iosu_nim.h"
#include "Cafe/IOSU/PDM/iosu_pdm.h" #include "Cafe/IOSU/PDM/iosu_pdm.h"
#include "Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.h"
// IOSU initializer functions // IOSU initializer functions
#include "Cafe/IOSU/kernel/iosu_kernel.h" #include "Cafe/IOSU/kernel/iosu_kernel.h"
@ -53,8 +51,6 @@
#include "Cafe/OS/libs/gx2/GX2.h" #include "Cafe/OS/libs/gx2/GX2.h"
#include "Cafe/OS/libs/gx2/GX2_Misc.h" #include "Cafe/OS/libs/gx2/GX2_Misc.h"
#include "Cafe/OS/libs/mic/mic.h" #include "Cafe/OS/libs/mic/mic.h"
#include "Cafe/OS/libs/nfc/nfc.h"
#include "Cafe/OS/libs/ntag/ntag.h"
#include "Cafe/OS/libs/nn_aoc/nn_aoc.h" #include "Cafe/OS/libs/nn_aoc/nn_aoc.h"
#include "Cafe/OS/libs/nn_pdm/nn_pdm.h" #include "Cafe/OS/libs/nn_pdm/nn_pdm.h"
#include "Cafe/OS/libs/nn_cmpt/nn_cmpt.h" #include "Cafe/OS/libs/nn_cmpt/nn_cmpt.h"
@ -397,7 +393,7 @@ void cemu_initForGame()
// replace any known function signatures with our HLE implementations and patch bugs in the games // replace any known function signatures with our HLE implementations and patch bugs in the games
GamePatch_scan(); GamePatch_scan();
} }
LatteGPUState.isDRCPrimary = ActiveSettings::DisplayDRCEnabled(); LatteGPUState.alwaysDisplayDRC = ActiveSettings::DisplayDRCEnabled();
InfoLog_PrintActiveSettings(); InfoLog_PrintActiveSettings();
Latte_Start(); Latte_Start();
// check for debugger entrypoint bp // check for debugger entrypoint bp
@ -537,7 +533,6 @@ namespace CafeSystem
iosu::acp::GetModule(), iosu::acp::GetModule(),
iosu::fpd::GetModule(), iosu::fpd::GetModule(),
iosu::pdm::GetModule(), iosu::pdm::GetModule(),
iosu::ccr_nfc::GetModule(),
}; };
// initialize all subsystems which are persistent and don't depend on a game running // initialize all subsystems which are persistent and don't depend on a game running
@ -592,8 +587,6 @@ namespace CafeSystem
H264::Initialize(); H264::Initialize();
snd_core::Initialize(); snd_core::Initialize();
mic::Initialize(); mic::Initialize();
nfc::Initialize();
ntag::Initialize();
// init hardware register interfaces // init hardware register interfaces
HW_SI::Initialize(); HW_SI::Initialize();
} }
@ -638,40 +631,40 @@ namespace CafeSystem
fsc_unmount("/cemuBossStorage/", FSC_PRIORITY_BASE); fsc_unmount("/cemuBossStorage/", FSC_PRIORITY_BASE);
} }
PREPARE_STATUS_CODE LoadAndMountForegroundTitle(TitleId titleId) STATUS_CODE LoadAndMountForegroundTitle(TitleId titleId)
{ {
cemuLog_log(LogType::Force, "Mounting title {:016x}", (uint64)titleId); cemuLog_log(LogType::Force, "Mounting title {:016x}", (uint64)titleId);
sGameInfo_ForegroundTitle = CafeTitleList::GetGameInfo(titleId); sGameInfo_ForegroundTitle = CafeTitleList::GetGameInfo(titleId);
if (!sGameInfo_ForegroundTitle.IsValid()) if (!sGameInfo_ForegroundTitle.IsValid())
{ {
cemuLog_log(LogType::Force, "Mounting failed: Game meta information is either missing, inaccessible or not valid (missing or invalid .xml files in code and meta folder)"); cemuLog_log(LogType::Force, "Mounting failed: Game meta information is either missing, inaccessible or not valid (missing or invalid .xml files in code and meta folder)");
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
} }
// check base // check base
TitleInfo& titleBase = sGameInfo_ForegroundTitle.GetBase(); TitleInfo& titleBase = sGameInfo_ForegroundTitle.GetBase();
if (!titleBase.IsValid()) if (!titleBase.IsValid())
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
if(!titleBase.ParseXmlInfo()) if(!titleBase.ParseXmlInfo())
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
cemuLog_log(LogType::Force, "Base: {}", titleBase.GetPrintPath()); cemuLog_log(LogType::Force, "Base: {}", titleBase.GetPrintPath());
// mount base // mount base
if (!titleBase.Mount("/vol/content", "content", FSC_PRIORITY_BASE) || !titleBase.Mount(GetInternalVirtualCodeFolder(), "code", FSC_PRIORITY_BASE)) if (!titleBase.Mount("/vol/content", "content", FSC_PRIORITY_BASE) || !titleBase.Mount(GetInternalVirtualCodeFolder(), "code", FSC_PRIORITY_BASE))
{ {
cemuLog_log(LogType::Force, "Mounting failed"); cemuLog_log(LogType::Force, "Mounting failed");
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
} }
// check update // check update
TitleInfo& titleUpdate = sGameInfo_ForegroundTitle.GetUpdate(); TitleInfo& titleUpdate = sGameInfo_ForegroundTitle.GetUpdate();
if (titleUpdate.IsValid()) if (titleUpdate.IsValid())
{ {
if (!titleUpdate.ParseXmlInfo()) if (!titleUpdate.ParseXmlInfo())
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
cemuLog_log(LogType::Force, "Update: {}", titleUpdate.GetPrintPath()); cemuLog_log(LogType::Force, "Update: {}", titleUpdate.GetPrintPath());
// mount update // mount update
if (!titleUpdate.Mount("/vol/content", "content", FSC_PRIORITY_PATCH) || !titleUpdate.Mount(GetInternalVirtualCodeFolder(), "code", FSC_PRIORITY_PATCH)) if (!titleUpdate.Mount("/vol/content", "content", FSC_PRIORITY_PATCH) || !titleUpdate.Mount(GetInternalVirtualCodeFolder(), "code", FSC_PRIORITY_PATCH))
{ {
cemuLog_log(LogType::Force, "Mounting failed"); cemuLog_log(LogType::Force, "Mounting failed");
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
} }
} }
else else
@ -683,20 +676,20 @@ namespace CafeSystem
// todo - support for multi-title AOC // todo - support for multi-title AOC
TitleInfo& titleAOC = aocList[0]; TitleInfo& titleAOC = aocList[0];
if (!titleAOC.ParseXmlInfo()) if (!titleAOC.ParseXmlInfo())
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
cemu_assert_debug(titleAOC.IsValid()); cemu_assert_debug(titleAOC.IsValid());
cemuLog_log(LogType::Force, "DLC: {}", titleAOC.GetPrintPath()); cemuLog_log(LogType::Force, "DLC: {}", titleAOC.GetPrintPath());
// mount AOC // mount AOC
if (!titleAOC.Mount(fmt::format("/vol/aoc{:016x}", titleAOC.GetAppTitleId()), "content", FSC_PRIORITY_PATCH)) if (!titleAOC.Mount(fmt::format("/vol/aoc{:016x}", titleAOC.GetAppTitleId()), "content", FSC_PRIORITY_PATCH))
{ {
cemuLog_log(LogType::Force, "Mounting failed"); cemuLog_log(LogType::Force, "Mounting failed");
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
} }
} }
else else
cemuLog_log(LogType::Force, "DLC: Not present"); cemuLog_log(LogType::Force, "DLC: Not present");
sForegroundTitleId = titleId; sForegroundTitleId = titleId;
return PREPARE_STATUS_CODE::SUCCESS; return STATUS_CODE::SUCCESS;
} }
void UnmountForegroundTitle() void UnmountForegroundTitle()
@ -724,7 +717,7 @@ namespace CafeSystem
} }
} }
PREPARE_STATUS_CODE SetupExecutable() STATUS_CODE SetupExecutable()
{ {
// set rpx path from cos.xml if available // set rpx path from cos.xml if available
_pathToBaseExecutable = _pathToExecutable; _pathToBaseExecutable = _pathToExecutable;
@ -756,7 +749,7 @@ namespace CafeSystem
} }
} }
LoadMainExecutable(); LoadMainExecutable();
return PREPARE_STATUS_CODE::SUCCESS; return STATUS_CODE::SUCCESS;
} }
void SetupMemorySpace() void SetupMemorySpace()
@ -770,7 +763,7 @@ namespace CafeSystem
memory_unmapForCurrentTitle(); memory_unmapForCurrentTitle();
} }
PREPARE_STATUS_CODE PrepareForegroundTitle(TitleId titleId) STATUS_CODE PrepareForegroundTitle(TitleId titleId)
{ {
CafeTitleList::WaitForMandatoryScan(); CafeTitleList::WaitForMandatoryScan();
sLaunchModeIsStandalone = false; sLaunchModeIsStandalone = false;
@ -781,21 +774,21 @@ namespace CafeSystem
// mount mlc storage // mount mlc storage
MountBaseDirectories(); MountBaseDirectories();
// mount title folders // mount title folders
PREPARE_STATUS_CODE r = LoadAndMountForegroundTitle(titleId); STATUS_CODE r = LoadAndMountForegroundTitle(titleId);
if (r != PREPARE_STATUS_CODE::SUCCESS) if (r != STATUS_CODE::SUCCESS)
return r; return r;
gameProfile_load(); gameProfile_load();
// setup memory space and PPC recompiler // setup memory space and PPC recompiler
SetupMemorySpace(); SetupMemorySpace();
PPCRecompiler_init(); PPCRecompiler_init();
r = SetupExecutable(); // load RPX r = SetupExecutable(); // load RPX
if (r != PREPARE_STATUS_CODE::SUCCESS) if (r != STATUS_CODE::SUCCESS)
return r; return r;
InitVirtualMlcStorage(); InitVirtualMlcStorage();
return PREPARE_STATUS_CODE::SUCCESS; return STATUS_CODE::SUCCESS;
} }
PREPARE_STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path) STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path)
{ {
sLaunchModeIsStandalone = true; sLaunchModeIsStandalone = true;
cemuLog_log(LogType::Force, "Launching executable in standalone mode due to incorrect layout or missing meta files"); cemuLog_log(LogType::Force, "Launching executable in standalone mode due to incorrect layout or missing meta files");
@ -813,7 +806,7 @@ namespace CafeSystem
if (!r) if (!r)
{ {
cemuLog_log(LogType::Force, "Failed to mount {}", _pathToUtf8(contentPath)); cemuLog_log(LogType::Force, "Failed to mount {}", _pathToUtf8(contentPath));
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT; return STATUS_CODE::UNABLE_TO_MOUNT;
} }
} }
} }
@ -825,7 +818,7 @@ namespace CafeSystem
// since a lot of systems (including save folder location) rely on a TitleId, we derive a placeholder id from the executable hash // since a lot of systems (including save folder location) rely on a TitleId, we derive a placeholder id from the executable hash
auto execData = fsc_extractFile(_pathToExecutable.c_str()); auto execData = fsc_extractFile(_pathToExecutable.c_str());
if (!execData) if (!execData)
return PREPARE_STATUS_CODE::INVALID_RPX; return STATUS_CODE::INVALID_RPX;
uint32 h = generateHashFromRawRPXData(execData->data(), execData->size()); uint32 h = generateHashFromRawRPXData(execData->data(), execData->size());
sForegroundTitleId = 0xFFFFFFFF00000000ULL | (uint64)h; sForegroundTitleId = 0xFFFFFFFF00000000ULL | (uint64)h;
cemuLog_log(LogType::Force, "Generated placeholder TitleId: {:016x}", sForegroundTitleId); cemuLog_log(LogType::Force, "Generated placeholder TitleId: {:016x}", sForegroundTitleId);
@ -835,7 +828,7 @@ namespace CafeSystem
// load executable // load executable
SetupExecutable(); SetupExecutable();
InitVirtualMlcStorage(); InitVirtualMlcStorage();
return PREPARE_STATUS_CODE::SUCCESS; return STATUS_CODE::SUCCESS;
} }
void _LaunchTitleThread() void _LaunchTitleThread()
@ -844,7 +837,7 @@ namespace CafeSystem
module->TitleStart(); module->TitleStart();
cemu_initForGame(); cemu_initForGame();
// enter scheduler // enter scheduler
if (ActiveSettings::GetCPUMode() == CPUMode::MulticoreRecompiler && !LaunchSettings::ForceInterpreter()) if (ActiveSettings::GetCPUMode() == CPUMode::MulticoreRecompiler)
coreinit::OSSchedulerBegin(3); coreinit::OSSchedulerBegin(3);
else else
coreinit::OSSchedulerBegin(1); coreinit::OSSchedulerBegin(1);

View file

@ -15,19 +15,20 @@ namespace CafeSystem
virtual void CafeRecreateCanvas() = 0; virtual void CafeRecreateCanvas() = 0;
}; };
enum class PREPARE_STATUS_CODE enum class STATUS_CODE
{ {
SUCCESS, SUCCESS,
INVALID_RPX, INVALID_RPX,
UNABLE_TO_MOUNT, // failed to mount through TitleInfo (most likely caused by an invalid or outdated path) UNABLE_TO_MOUNT, // failed to mount through TitleInfo (most likely caused by an invalid or outdated path)
//BAD_META_DATA, - the title list only stores titles with valid meta, so this error code is impossible
}; };
void Initialize(); void Initialize();
void SetImplementation(SystemImplementation* impl); void SetImplementation(SystemImplementation* impl);
void Shutdown(); void Shutdown();
PREPARE_STATUS_CODE PrepareForegroundTitle(TitleId titleId); STATUS_CODE PrepareForegroundTitle(TitleId titleId);
PREPARE_STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path); STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path);
void LaunchForegroundTitle(); void LaunchForegroundTitle();
bool IsTitleRunning(); bool IsTitleRunning();

View file

@ -3,7 +3,8 @@
#include "Cemu/ncrypto/ncrypto.h" #include "Cemu/ncrypto/ncrypto.h"
#include "Cafe/Filesystem/WUD/wud.h" #include "Cafe/Filesystem/WUD/wud.h"
#include "util/crypto/aes128.h" #include "util/crypto/aes128.h"
#include "openssl/sha.h" /* SHA1 / SHA256 */ #include "openssl/evp.h" /* EVP_Digest */
#include "openssl/sha.h" /* SHA1 / SHA256_DIGEST_LENGTH */
#include "fstUtil.h" #include "fstUtil.h"
#include "FST.h" #include "FST.h"
@ -140,7 +141,7 @@ struct DiscPartitionTableHeader
static constexpr uint32 MAGIC_VALUE = 0xCCA6E67B; static constexpr uint32 MAGIC_VALUE = 0xCCA6E67B;
/* +0x00 */ uint32be magic; /* +0x00 */ uint32be magic;
/* +0x04 */ uint32be blockSize; // must be 0x8000? /* +0x04 */ uint32be sectorSize; // must be 0x8000?
/* +0x08 */ uint8 partitionTableHash[20]; // hash of the data range at +0x800 to end of sector (0x8000) /* +0x08 */ uint8 partitionTableHash[20]; // hash of the data range at +0x800 to end of sector (0x8000)
/* +0x1C */ uint32be numPartitions; /* +0x1C */ uint32be numPartitions;
}; };
@ -163,10 +164,10 @@ struct DiscPartitionHeader
static constexpr uint32 MAGIC_VALUE = 0xCC93A4F5; static constexpr uint32 MAGIC_VALUE = 0xCC93A4F5;
/* +0x00 */ uint32be magic; /* +0x00 */ uint32be magic;
/* +0x04 */ uint32be sectorSize; // must match DISC_SECTOR_SIZE for hashed blocks /* +0x04 */ uint32be sectorSize; // must match DISC_SECTOR_SIZE
/* +0x08 */ uint32be ukn008; /* +0x08 */ uint32be ukn008;
/* +0x0C */ uint32be ukn00C; // h3 array size? /* +0x0C */ uint32be ukn00C;
/* +0x10 */ uint32be h3HashNum; /* +0x10 */ uint32be h3HashNum;
/* +0x14 */ uint32be fstSize; // in bytes /* +0x14 */ uint32be fstSize; // in bytes
/* +0x18 */ uint32be fstSector; // relative to partition start /* +0x18 */ uint32be fstSector; // relative to partition start
@ -177,15 +178,13 @@ struct DiscPartitionHeader
/* +0x24 */ uint8 fstHashType; /* +0x24 */ uint8 fstHashType;
/* +0x25 */ uint8 fstEncryptionType; // purpose of this isn't really understood. Maybe it controls which key is being used? (1 -> disc key, 2 -> partition key) /* +0x25 */ uint8 fstEncryptionType; // purpose of this isn't really understood. Maybe it controls which key is being used? (1 -> disc key, 2 -> partition key)
/* +0x26 */ uint8be versionA; /* +0x26 */ uint8 versionA;
/* +0x27 */ uint8be ukn027; // also a version field? /* +0x27 */ uint8 ukn027; // also a version field?
// there is an array at +0x40 ? Related to H3 list. Also related to value at +0x0C and h3HashNum // there is an array at +0x40 ? Related to H3 list. Also related to value at +0x0C and h3HashNum
/* +0x28 */ uint8be _uknOrPadding028[0x18];
/* +0x40 */ uint8be h3HashArray[32]; // dynamic size. Only present if fstHashType != 0
}; };
static_assert(sizeof(DiscPartitionHeader) == 0x40+0x20); static_assert(sizeof(DiscPartitionHeader) == 0x28);
bool FSTVolume::FindDiscKey(const fs::path& path, NCrypto::AesKey& discTitleKey) bool FSTVolume::FindDiscKey(const fs::path& path, NCrypto::AesKey& discTitleKey)
{ {
@ -270,7 +269,7 @@ FSTVolume* FSTVolume::OpenFromDiscImage(const fs::path& path, NCrypto::AesKey& d
cemuLog_log(LogType::Force, "Disc image rejected because decryption failed"); cemuLog_log(LogType::Force, "Disc image rejected because decryption failed");
return nullptr; return nullptr;
} }
if (partitionHeader->blockSize != DISC_SECTOR_SIZE) if (partitionHeader->sectorSize != DISC_SECTOR_SIZE)
{ {
cemuLog_log(LogType::Force, "Disc image rejected because partition sector size is invalid"); cemuLog_log(LogType::Force, "Disc image rejected because partition sector size is invalid");
return nullptr; return nullptr;
@ -337,9 +336,6 @@ FSTVolume* FSTVolume::OpenFromDiscImage(const fs::path& path, NCrypto::AesKey& d
cemu_assert_debug(partitionHeaderSI.fstEncryptionType == 1); cemu_assert_debug(partitionHeaderSI.fstEncryptionType == 1);
// todo - check other fields? // todo - check other fields?
if(partitionHeaderSI.fstHashType == 0 && partitionHeaderSI.h3HashNum != 0)
cemuLog_log(LogType::Force, "FST: Partition uses unhashed blocks but stores a non-zero amount of H3 hashes");
// GM partition // GM partition
DiscPartitionHeader partitionHeaderGM{}; DiscPartitionHeader partitionHeaderGM{};
if (!readPartitionHeader(partitionHeaderGM, gmPartitionIndex)) if (!readPartitionHeader(partitionHeaderGM, gmPartitionIndex))
@ -353,10 +349,9 @@ FSTVolume* FSTVolume::OpenFromDiscImage(const fs::path& path, NCrypto::AesKey& d
// if decryption is necessary // if decryption is necessary
// load SI FST // load SI FST
dataSource->SetBaseOffset((uint64)partitionArray[siPartitionIndex].partitionAddress * DISC_SECTOR_SIZE); dataSource->SetBaseOffset((uint64)partitionArray[siPartitionIndex].partitionAddress * DISC_SECTOR_SIZE);
auto siFST = OpenFST(dataSource.get(), (uint64)partitionHeaderSI.fstSector * DISC_SECTOR_SIZE, partitionHeaderSI.fstSize, &discTitleKey, static_cast<FSTVolume::ClusterHashMode>(partitionHeaderSI.fstHashType), nullptr); auto siFST = OpenFST(dataSource.get(), (uint64)partitionHeaderSI.fstSector * DISC_SECTOR_SIZE, partitionHeaderSI.fstSize, &discTitleKey, static_cast<FSTVolume::ClusterHashMode>(partitionHeaderSI.fstHashType));
if (!siFST) if (!siFST)
return nullptr; return nullptr;
cemu_assert_debug(!(siFST->HashIsDisabled() && partitionHeaderSI.h3HashNum != 0)); // if hash is disabled, no H3 data may be present
// load ticket file for partition that we want to decrypt // load ticket file for partition that we want to decrypt
NCrypto::ETicketParser ticketParser; NCrypto::ETicketParser ticketParser;
std::vector<uint8> ticketData = siFST->ExtractFile(fmt::format("{:02x}/title.tik", gmPartitionIndex)); std::vector<uint8> ticketData = siFST->ExtractFile(fmt::format("{:02x}/title.tik", gmPartitionIndex));
@ -365,32 +360,16 @@ FSTVolume* FSTVolume::OpenFromDiscImage(const fs::path& path, NCrypto::AesKey& d
cemuLog_log(LogType::Force, "Disc image ticket file is invalid"); cemuLog_log(LogType::Force, "Disc image ticket file is invalid");
return nullptr; return nullptr;
} }
#if 0
// each SI partition seems to contain a title.tmd that we could parse and which should have information about the associated GM partition
// but the console seems to ignore this file for disc images, at least when mounting, so we shouldn't rely on it either
std::vector<uint8> tmdData = siFST->ExtractFile(fmt::format("{:02x}/title.tmd", gmPartitionIndex));
if (tmdData.empty())
{
cemuLog_log(LogType::Force, "Disc image TMD file is missing");
return nullptr;
}
// parse TMD
NCrypto::TMDParser tmdParser;
if (!tmdParser.parse(tmdData.data(), tmdData.size()))
{
cemuLog_log(LogType::Force, "Disc image TMD file is invalid");
return nullptr;
}
#endif
delete siFST; delete siFST;
NCrypto::AesKey gmTitleKey; NCrypto::AesKey gmTitleKey;
ticketParser.GetTitleKey(gmTitleKey); ticketParser.GetTitleKey(gmTitleKey);
// load GM partition // load GM partition
dataSource->SetBaseOffset((uint64)partitionArray[gmPartitionIndex].partitionAddress * DISC_SECTOR_SIZE); dataSource->SetBaseOffset((uint64)partitionArray[gmPartitionIndex].partitionAddress * DISC_SECTOR_SIZE);
FSTVolume* r = OpenFST(std::move(dataSource), (uint64)partitionHeaderGM.fstSector * DISC_SECTOR_SIZE, partitionHeaderGM.fstSize, &gmTitleKey, static_cast<FSTVolume::ClusterHashMode>(partitionHeaderGM.fstHashType), nullptr); FSTVolume* r = OpenFST(std::move(dataSource), (uint64)partitionHeaderGM.fstSector * DISC_SECTOR_SIZE, partitionHeaderGM.fstSize, &gmTitleKey, static_cast<FSTVolume::ClusterHashMode>(partitionHeaderGM.fstHashType));
if (r) if (r)
SET_FST_ERROR(OK); SET_FST_ERROR(OK);
cemu_assert_debug(!(r->HashIsDisabled() && partitionHeaderGM.h3HashNum != 0)); // if hash is disabled, no H3 data may be present
return r; return r;
} }
@ -447,15 +426,15 @@ FSTVolume* FSTVolume::OpenFromContentFolder(fs::path folderPath, ErrorCode* erro
} }
// load FST // load FST
// fstSize = size of first cluster? // fstSize = size of first cluster?
FSTVolume* fstVolume = FSTVolume::OpenFST(std::move(dataSource), 0, fstSize, &titleKey, fstHashMode, &tmdParser); FSTVolume* fstVolume = FSTVolume::OpenFST(std::move(dataSource), 0, fstSize, &titleKey, fstHashMode);
if (fstVolume) if (fstVolume)
SET_FST_ERROR(OK); SET_FST_ERROR(OK);
return fstVolume; return fstVolume;
} }
FSTVolume* FSTVolume::OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode, NCrypto::TMDParser* optionalTMD) FSTVolume* FSTVolume::OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode)
{ {
cemu_assert_debug(fstHashMode != ClusterHashMode::RAW || fstHashMode != ClusterHashMode::RAW_STREAM); cemu_assert_debug(fstHashMode != ClusterHashMode::RAW || fstHashMode != ClusterHashMode::RAW2);
if (fstSize < sizeof(FSTHeader)) if (fstSize < sizeof(FSTHeader))
return nullptr; return nullptr;
constexpr uint64 FST_CLUSTER_OFFSET = 0; constexpr uint64 FST_CLUSTER_OFFSET = 0;
@ -486,34 +465,6 @@ FSTVolume* FSTVolume::OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint3
clusterTable[i].offset = clusterDataTable[i].offset; clusterTable[i].offset = clusterDataTable[i].offset;
clusterTable[i].size = clusterDataTable[i].size; clusterTable[i].size = clusterDataTable[i].size;
clusterTable[i].hashMode = static_cast<FSTVolume::ClusterHashMode>((uint8)clusterDataTable[i].hashMode); clusterTable[i].hashMode = static_cast<FSTVolume::ClusterHashMode>((uint8)clusterDataTable[i].hashMode);
clusterTable[i].hasContentHash = false; // from the TMD file (H4?)
}
// if the TMD is available (when opening .app files) we can use the extra info from it to validate unhashed clusters
// each content entry in the TMD corresponds to one cluster used by the FST
if(optionalTMD)
{
if(numCluster != optionalTMD->GetContentList().size())
{
cemuLog_log(LogType::Force, "FST: Number of clusters does not match TMD content list");
return nullptr;
}
auto& contentList = optionalTMD->GetContentList();
for(size_t i=0; i<contentList.size(); i++)
{
auto& cluster = clusterTable[i];
auto& content = contentList[i];
cluster.hasContentHash = true;
cluster.contentHashIsSHA1 = HAS_FLAG(contentList[i].contentFlags, NCrypto::TMDParser::TMDContentFlags::FLAG_SHA1);
cluster.contentSize = content.size;
static_assert(sizeof(content.hash32) == sizeof(cluster.contentHash32));
memcpy(cluster.contentHash32, content.hash32, sizeof(cluster.contentHash32));
// if unhashed mode, then initialize the hash context
if(cluster.hashMode == ClusterHashMode::RAW || cluster.hashMode == ClusterHashMode::RAW_STREAM)
{
cluster.singleHashCtx.reset(EVP_MD_CTX_new());
EVP_DigestInit_ex(cluster.singleHashCtx.get(), cluster.contentHashIsSHA1 ? EVP_sha1() : EVP_sha256(), nullptr);
}
}
} }
// preprocess FST table // preprocess FST table
FSTHeader_FileEntry* fileTable = (FSTHeader_FileEntry*)(clusterDataTable + numCluster); FSTHeader_FileEntry* fileTable = (FSTHeader_FileEntry*)(clusterDataTable + numCluster);
@ -540,17 +491,16 @@ FSTVolume* FSTVolume::OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint3
fstVolume->m_offsetFactor = fstHeader->offsetFactor; fstVolume->m_offsetFactor = fstHeader->offsetFactor;
fstVolume->m_sectorSize = DISC_SECTOR_SIZE; fstVolume->m_sectorSize = DISC_SECTOR_SIZE;
fstVolume->m_partitionTitlekey = *partitionTitleKey; fstVolume->m_partitionTitlekey = *partitionTitleKey;
fstVolume->m_hashIsDisabled = fstHeader->hashIsDisabled != 0; std::swap(fstVolume->m_cluster, clusterTable);
fstVolume->m_cluster = std::move(clusterTable); std::swap(fstVolume->m_entries, fstEntries);
fstVolume->m_entries = std::move(fstEntries); std::swap(fstVolume->m_nameStringTable, nameStringTable);
fstVolume->m_nameStringTable = std::move(nameStringTable);
return fstVolume; return fstVolume;
} }
FSTVolume* FSTVolume::OpenFST(std::unique_ptr<FSTDataSource> dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode, NCrypto::TMDParser* optionalTMD) FSTVolume* FSTVolume::OpenFST(std::unique_ptr<FSTDataSource> dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode)
{ {
FSTDataSource* ds = dataSource.release(); FSTDataSource* ds = dataSource.release();
FSTVolume* fstVolume = OpenFST(ds, fstOffset, fstSize, partitionTitleKey, fstHashMode, optionalTMD); FSTVolume* fstVolume = OpenFST(ds, fstOffset, fstSize, partitionTitleKey, fstHashMode);
if (!fstVolume) if (!fstVolume)
{ {
delete ds; delete ds;
@ -807,7 +757,7 @@ uint32 FSTVolume::ReadFile(FSTFileHandle& fileHandle, uint32 offset, uint32 size
return 0; return 0;
cemu_assert_debug(!HAS_FLAG(entry.GetFlags(), FSTEntry::FLAGS::FLAG_LINK)); cemu_assert_debug(!HAS_FLAG(entry.GetFlags(), FSTEntry::FLAGS::FLAG_LINK));
FSTCluster& cluster = m_cluster[entry.fileInfo.clusterIndex]; FSTCluster& cluster = m_cluster[entry.fileInfo.clusterIndex];
if (cluster.hashMode == ClusterHashMode::RAW || cluster.hashMode == ClusterHashMode::RAW_STREAM) if (cluster.hashMode == ClusterHashMode::RAW || cluster.hashMode == ClusterHashMode::RAW2)
return ReadFile_HashModeRaw(entry.fileInfo.clusterIndex, entry, offset, size, dataOut); return ReadFile_HashModeRaw(entry.fileInfo.clusterIndex, entry, offset, size, dataOut);
else if (cluster.hashMode == ClusterHashMode::HASH_INTERLEAVED) else if (cluster.hashMode == ClusterHashMode::HASH_INTERLEAVED)
return ReadFile_HashModeHashed(entry.fileInfo.clusterIndex, entry, offset, size, dataOut); return ReadFile_HashModeHashed(entry.fileInfo.clusterIndex, entry, offset, size, dataOut);
@ -815,15 +765,87 @@ uint32 FSTVolume::ReadFile(FSTFileHandle& fileHandle, uint32 offset, uint32 size
return 0; return 0;
} }
uint32 FSTVolume::ReadFile_HashModeRaw(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut)
{
const uint32 readSizeInput = readSize;
uint8* dataOutU8 = (uint8*)dataOut;
if (readOffset >= entry.fileInfo.fileSize)
return 0;
else if ((readOffset + readSize) >= entry.fileInfo.fileSize)
readSize = (entry.fileInfo.fileSize - readOffset);
const FSTCluster& cluster = m_cluster[clusterIndex];
uint64 clusterOffset = (uint64)cluster.offset * m_sectorSize;
uint64 absFileOffset = entry.fileInfo.fileOffset * m_offsetFactor + readOffset;
// make sure the raw range we read is aligned to AES block size (16)
uint64 readAddrStart = absFileOffset & ~0xF;
uint64 readAddrEnd = (absFileOffset + readSize + 0xF) & ~0xF;
bool usesInitialIV = readOffset < 16;
if (!usesInitialIV)
readAddrStart -= 16; // read previous AES block since we require it for the IV
uint32 prePadding = (uint32)(absFileOffset - readAddrStart); // number of extra bytes we read before readOffset (for AES alignment and IV calculation)
uint32 postPadding = (uint32)(readAddrEnd - (absFileOffset + readSize));
uint8 readBuffer[64 * 1024];
// read first chunk
// if file read offset (readOffset) is within the first AES-block then use initial IV calculated from cluster index
// otherwise read previous AES-block is the IV (AES-CBC)
uint64 readAddrCurrent = readAddrStart;
uint32 rawBytesToRead = (uint32)std::min((readAddrEnd - readAddrStart), (uint64)sizeof(readBuffer));
if (m_dataSource->readData(clusterIndex, clusterOffset, readAddrCurrent, readBuffer, rawBytesToRead) != rawBytesToRead)
{
cemuLog_log(LogType::Force, "FST read error in raw content");
return 0;
}
readAddrCurrent += rawBytesToRead;
uint8 iv[16]{};
if (usesInitialIV)
{
// for the first AES block, the IV is initialized from cluster index
iv[0] = (uint8)(clusterIndex >> 8);
iv[1] = (uint8)(clusterIndex >> 0);
AES128_CBC_decrypt_updateIV(readBuffer, readBuffer, rawBytesToRead, m_partitionTitlekey.b, iv);
std::memcpy(dataOutU8, readBuffer + prePadding, rawBytesToRead - prePadding - postPadding);
dataOutU8 += (rawBytesToRead - prePadding - postPadding);
readSize -= (rawBytesToRead - prePadding - postPadding);
}
else
{
// IV is initialized from previous AES block (AES-CBC)
std::memcpy(iv, readBuffer, 16);
AES128_CBC_decrypt_updateIV(readBuffer + 16, readBuffer + 16, rawBytesToRead - 16, m_partitionTitlekey.b, iv);
std::memcpy(dataOutU8, readBuffer + prePadding, rawBytesToRead - prePadding - postPadding);
dataOutU8 += (rawBytesToRead - prePadding - postPadding);
readSize -= (rawBytesToRead - prePadding - postPadding);
}
// read remaining chunks
while (readSize > 0)
{
uint32 bytesToRead = (uint32)std::min((uint32)sizeof(readBuffer), readSize);
uint32 alignedBytesToRead = (bytesToRead + 15) & ~0xF;
if (m_dataSource->readData(clusterIndex, clusterOffset, readAddrCurrent, readBuffer, alignedBytesToRead) != alignedBytesToRead)
{
cemuLog_log(LogType::Force, "FST read error in raw content");
return 0;
}
AES128_CBC_decrypt_updateIV(readBuffer, readBuffer, alignedBytesToRead, m_partitionTitlekey.b, iv);
std::memcpy(dataOutU8, readBuffer, bytesToRead);
dataOutU8 += bytesToRead;
readSize -= bytesToRead;
readAddrCurrent += alignedBytesToRead;
}
return readSizeInput - readSize;
}
constexpr size_t BLOCK_SIZE = 0x10000; constexpr size_t BLOCK_SIZE = 0x10000;
constexpr size_t BLOCK_HASH_SIZE = 0x0400; constexpr size_t BLOCK_HASH_SIZE = 0x0400;
constexpr size_t BLOCK_FILE_SIZE = 0xFC00; constexpr size_t BLOCK_FILE_SIZE = 0xFC00;
struct FSTRawBlock
{
std::vector<uint8> rawData; // unhashed block size depends on sector size field in partition header
};
struct FSTHashedBlock struct FSTHashedBlock
{ {
uint8 rawData[BLOCK_SIZE]; uint8 rawData[BLOCK_SIZE];
@ -865,160 +887,12 @@ struct FSTHashedBlock
static_assert(sizeof(FSTHashedBlock) == BLOCK_SIZE); static_assert(sizeof(FSTHashedBlock) == BLOCK_SIZE);
struct FSTCachedRawBlock
{
FSTRawBlock blockData;
uint8 ivForNextBlock[16];
uint64 lastAccess;
};
struct FSTCachedHashedBlock struct FSTCachedHashedBlock
{ {
FSTHashedBlock blockData; FSTHashedBlock blockData;
uint64 lastAccess; uint64 lastAccess;
}; };
// Checks cache fill state and if necessary drops least recently accessed block from the cache. Optionally allows to recycle the released cache entry to cut down cost of memory allocation and clearing
void FSTVolume::TrimCacheIfRequired(FSTCachedRawBlock** droppedRawBlock, FSTCachedHashedBlock** droppedHashedBlock)
{
// calculate size used by cache
size_t cacheSize = 0;
for (auto& itr : m_cacheDecryptedRawBlocks)
cacheSize += itr.second->blockData.rawData.size();
for (auto& itr : m_cacheDecryptedHashedBlocks)
cacheSize += sizeof(FSTCachedHashedBlock) + sizeof(FSTHashedBlock);
// only trim if cache is full (larger than 2MB)
if (cacheSize < 2*1024*1024) // 2MB
return;
// scan both cache lists to find least recently accessed block to drop
auto dropRawItr = std::min_element(m_cacheDecryptedRawBlocks.begin(), m_cacheDecryptedRawBlocks.end(), [](const auto& a, const auto& b) -> bool
{ return a.second->lastAccess < b.second->lastAccess; });
auto dropHashedItr = std::min_element(m_cacheDecryptedHashedBlocks.begin(), m_cacheDecryptedHashedBlocks.end(), [](const auto& a, const auto& b) -> bool
{ return a.second->lastAccess < b.second->lastAccess; });
uint64 lastAccess = std::numeric_limits<uint64>::max();
if(dropRawItr != m_cacheDecryptedRawBlocks.end())
lastAccess = dropRawItr->second->lastAccess;
if(dropHashedItr != m_cacheDecryptedHashedBlocks.end())
lastAccess = std::min<uint64>(lastAccess, dropHashedItr->second->lastAccess);
if(dropRawItr != m_cacheDecryptedRawBlocks.end() && dropRawItr->second->lastAccess == lastAccess)
{
if (droppedRawBlock)
*droppedRawBlock = dropRawItr->second;
else
delete dropRawItr->second;
m_cacheDecryptedRawBlocks.erase(dropRawItr);
return;
}
else if(dropHashedItr != m_cacheDecryptedHashedBlocks.end() && dropHashedItr->second->lastAccess == lastAccess)
{
if (droppedHashedBlock)
*droppedHashedBlock = dropHashedItr->second;
else
delete dropHashedItr->second;
m_cacheDecryptedHashedBlocks.erase(dropHashedItr);
}
}
void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, uint8 ivOut[16])
{
memset(ivOut, 0, sizeof(ivOut));
if(blockIndex == 0)
{
ivOut[0] = (uint8)(clusterIndex >> 8);
ivOut[1] = (uint8)(clusterIndex >> 0);
}
else
{
// the last 16 encrypted bytes of the previous block are the IV (AES CBC)
// if the previous block is cached we can grab the IV from there. Otherwise we have to read the 16 bytes from the data source
uint32 prevBlockIndex = blockIndex - 1;
uint64 cacheBlockId = ((uint64)clusterIndex << (64 - 16)) | (uint64)prevBlockIndex;
auto itr = m_cacheDecryptedRawBlocks.find(cacheBlockId);
if (itr != m_cacheDecryptedRawBlocks.end())
{
memcpy(ivOut, itr->second->ivForNextBlock, 16);
}
else
{
cemu_assert(m_sectorSize >= 16);
uint64 clusterOffset = (uint64)m_cluster[clusterIndex].offset * m_sectorSize;
uint8 prevIV[16];
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize - 16, prevIV, 16) != 16)
{
cemuLog_log(LogType::Force, "Failed to read IV for raw FST block");
m_detectedCorruption = true;
return;
}
memcpy(ivOut, prevIV, 16);
}
}
}
FSTCachedRawBlock* FSTVolume::GetDecryptedRawBlock(uint32 clusterIndex, uint32 blockIndex)
{
FSTCluster& cluster = m_cluster[clusterIndex];
uint64 clusterOffset = (uint64)cluster.offset * m_sectorSize;
// generate id for cache
uint64 cacheBlockId = ((uint64)clusterIndex << (64 - 16)) | (uint64)blockIndex;
// lookup block in cache
FSTCachedRawBlock* block = nullptr;
auto itr = m_cacheDecryptedRawBlocks.find(cacheBlockId);
if (itr != m_cacheDecryptedRawBlocks.end())
{
block = itr->second;
block->lastAccess = ++m_cacheAccessCounter;
return block;
}
// if cache already full, drop least recently accessed block and recycle FSTCachedRawBlock object if possible
TrimCacheIfRequired(&block, nullptr);
if (!block)
block = new FSTCachedRawBlock();
block->blockData.rawData.resize(m_sectorSize);
// block not cached, read new
block->lastAccess = ++m_cacheAccessCounter;
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize, block->blockData.rawData.data(), m_sectorSize) != m_sectorSize)
{
cemuLog_log(LogType::Force, "Failed to read raw FST block");
delete block;
m_detectedCorruption = true;
return nullptr;
}
// decrypt hash data
uint8 iv[16]{};
DetermineUnhashedBlockIV(clusterIndex, blockIndex, iv);
memcpy(block->ivForNextBlock, block->blockData.rawData.data() + m_sectorSize - 16, 16);
AES128_CBC_decrypt(block->blockData.rawData.data(), block->blockData.rawData.data(), m_sectorSize, m_partitionTitlekey.b, iv);
// if this is the next block, then hash it
if(cluster.hasContentHash)
{
if(cluster.singleHashNumBlocksHashed == blockIndex)
{
cemu_assert_debug(!(cluster.contentSize % m_sectorSize)); // size should be multiple of sector size? Regardless, the hashing code below can handle non-aligned sizes
bool isLastBlock = blockIndex == (std::max<uint32>(cluster.contentSize / m_sectorSize, 1) - 1);
uint32 hashSize = m_sectorSize;
if(isLastBlock)
hashSize = cluster.contentSize - (uint64)blockIndex*m_sectorSize;
EVP_DigestUpdate(cluster.singleHashCtx.get(), block->blockData.rawData.data(), hashSize);
cluster.singleHashNumBlocksHashed++;
if(isLastBlock)
{
uint8 hash[32];
EVP_DigestFinal_ex(cluster.singleHashCtx.get(), hash, nullptr);
if(memcmp(hash, cluster.contentHash32, cluster.contentHashIsSHA1 ? 20 : 32) != 0)
{
cemuLog_log(LogType::Force, "FST: Raw section hash mismatch");
delete block;
m_detectedCorruption = true;
return nullptr;
}
}
}
}
// register in cache
m_cacheDecryptedRawBlocks.emplace(cacheBlockId, block);
return block;
}
FSTCachedHashedBlock* FSTVolume::GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex) FSTCachedHashedBlock* FSTVolume::GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex)
{ {
const FSTCluster& cluster = m_cluster[clusterIndex]; const FSTCluster& cluster = m_cluster[clusterIndex];
@ -1034,17 +908,22 @@ FSTCachedHashedBlock* FSTVolume::GetDecryptedHashedBlock(uint32 clusterIndex, ui
block->lastAccess = ++m_cacheAccessCounter; block->lastAccess = ++m_cacheAccessCounter;
return block; return block;
} }
// if cache already full, drop least recently accessed block and recycle FSTCachedHashedBlock object if possible // if cache already full, drop least recently accessed block (but recycle the FSTHashedBlock* object)
TrimCacheIfRequired(nullptr, &block); if (m_cacheDecryptedHashedBlocks.size() >= 16)
if (!block) {
auto dropItr = std::min_element(m_cacheDecryptedHashedBlocks.begin(), m_cacheDecryptedHashedBlocks.end(), [](const auto& a, const auto& b) -> bool
{ return a.second->lastAccess < b.second->lastAccess; });
block = dropItr->second;
m_cacheDecryptedHashedBlocks.erase(dropItr);
}
else
block = new FSTCachedHashedBlock(); block = new FSTCachedHashedBlock();
// block not cached, read new // block not cached, read new
block->lastAccess = ++m_cacheAccessCounter; block->lastAccess = ++m_cacheAccessCounter;
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * BLOCK_SIZE, block->blockData.rawData, BLOCK_SIZE) != BLOCK_SIZE) if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * BLOCK_SIZE, block->blockData.rawData, BLOCK_SIZE) != BLOCK_SIZE)
{ {
cemuLog_log(LogType::Force, "Failed to read hashed FST block"); cemuLog_log(LogType::Force, "Failed to read FST block");
delete block; delete block;
m_detectedCorruption = true;
return nullptr; return nullptr;
} }
// decrypt hash data // decrypt hash data
@ -1052,46 +931,11 @@ FSTCachedHashedBlock* FSTVolume::GetDecryptedHashedBlock(uint32 clusterIndex, ui
AES128_CBC_decrypt(block->blockData.getHashData(), block->blockData.getHashData(), BLOCK_HASH_SIZE, m_partitionTitlekey.b, iv); AES128_CBC_decrypt(block->blockData.getHashData(), block->blockData.getHashData(), BLOCK_HASH_SIZE, m_partitionTitlekey.b, iv);
// decrypt file data // decrypt file data
AES128_CBC_decrypt(block->blockData.getFileData(), block->blockData.getFileData(), BLOCK_FILE_SIZE, m_partitionTitlekey.b, block->blockData.getH0Hash(blockIndex%16)); AES128_CBC_decrypt(block->blockData.getFileData(), block->blockData.getFileData(), BLOCK_FILE_SIZE, m_partitionTitlekey.b, block->blockData.getH0Hash(blockIndex%16));
// compare with H0 to verify data integrity
NCrypto::CHash160 h0;
SHA1(block->blockData.getFileData(), BLOCK_FILE_SIZE, h0.b);
uint32 h0Index = (blockIndex % 4096);
if (memcmp(h0.b, block->blockData.getH0Hash(h0Index & 0xF), sizeof(h0.b)) != 0)
{
cemuLog_log(LogType::Force, "FST: Hash H0 mismatch in hashed block (section {} index {})", clusterIndex, blockIndex);
delete block;
m_detectedCorruption = true;
return nullptr;
}
// register in cache // register in cache
m_cacheDecryptedHashedBlocks.emplace(cacheBlockId, block); m_cacheDecryptedHashedBlocks.emplace(cacheBlockId, block);
return block; return block;
} }
uint32 FSTVolume::ReadFile_HashModeRaw(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut)
{
uint8* dataOutU8 = (uint8*)dataOut;
if (readOffset >= entry.fileInfo.fileSize)
return 0;
else if ((readOffset + readSize) >= entry.fileInfo.fileSize)
readSize = (entry.fileInfo.fileSize - readOffset);
uint64 absFileOffset = entry.fileInfo.fileOffset * m_offsetFactor + readOffset;
uint32 remainingReadSize = readSize;
while (remainingReadSize > 0)
{
const FSTCachedRawBlock* rawBlock = this->GetDecryptedRawBlock(clusterIndex, absFileOffset/m_sectorSize);
if (!rawBlock)
break;
uint32 blockOffset = (uint32)(absFileOffset % m_sectorSize);
uint32 bytesToRead = std::min<uint32>(remainingReadSize, m_sectorSize - blockOffset);
std::memcpy(dataOutU8, rawBlock->blockData.rawData.data() + blockOffset, bytesToRead);
dataOutU8 += bytesToRead;
remainingReadSize -= bytesToRead;
absFileOffset += bytesToRead;
}
return readSize - remainingReadSize;
}
uint32 FSTVolume::ReadFile_HashModeHashed(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut) uint32 FSTVolume::ReadFile_HashModeHashed(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut)
{ {
/* /*
@ -1122,6 +966,7 @@ uint32 FSTVolume::ReadFile_HashModeHashed(uint32 clusterIndex, FSTEntry& entry,
*/ */
const FSTCluster& cluster = m_cluster[clusterIndex]; const FSTCluster& cluster = m_cluster[clusterIndex];
uint64 clusterBaseOffset = (uint64)cluster.offset * m_sectorSize;
uint64 fileReadOffset = entry.fileInfo.fileOffset * m_offsetFactor + readOffset; uint64 fileReadOffset = entry.fileInfo.fileOffset * m_offsetFactor + readOffset;
uint32 blockIndex = (uint32)(fileReadOffset / BLOCK_FILE_SIZE); uint32 blockIndex = (uint32)(fileReadOffset / BLOCK_FILE_SIZE);
uint32 bytesRemaining = readSize; uint32 bytesRemaining = readSize;
@ -1174,8 +1019,6 @@ bool FSTVolume::Next(FSTDirectoryIterator& directoryIterator, FSTFileHandle& fil
FSTVolume::~FSTVolume() FSTVolume::~FSTVolume()
{ {
for (auto& itr : m_cacheDecryptedRawBlocks)
delete itr.second;
for (auto& itr : m_cacheDecryptedHashedBlocks) for (auto& itr : m_cacheDecryptedHashedBlocks)
delete itr.second; delete itr.second;
if (m_sourceIsOwned) if (m_sourceIsOwned)

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "Cemu/ncrypto/ncrypto.h" #include "Cemu/ncrypto/ncrypto.h"
#include "openssl/evp.h"
struct FSTFileHandle struct FSTFileHandle
{ {
@ -46,7 +45,6 @@ public:
~FSTVolume(); ~FSTVolume();
uint32 GetFileCount() const; uint32 GetFileCount() const;
bool HasCorruption() const { return m_detectedCorruption; }
bool OpenFile(std::string_view path, FSTFileHandle& fileHandleOut, bool openOnlyFiles = false); bool OpenFile(std::string_view path, FSTFileHandle& fileHandleOut, bool openOnlyFiles = false);
@ -88,25 +86,15 @@ private:
enum class ClusterHashMode : uint8 enum class ClusterHashMode : uint8
{ {
RAW = 0, // raw data + encryption, no hashing? RAW = 0, // raw data + encryption, no hashing?
RAW_STREAM = 1, // raw data + encryption, with hash stored in tmd? RAW2 = 1, // raw data + encryption, with hash stored in tmd?
HASH_INTERLEAVED = 2, // hashes + raw interleaved in 0x10000 blocks (0x400 bytes of hashes at the beginning, followed by 0xFC00 bytes of data) HASH_INTERLEAVED = 2, // hashes + raw interleaved in 0x10000 blocks (0x400 bytes of hashes at the beginning, followed by 0xFC00 bytes of data)
}; };
struct FSTCluster struct FSTCluster
{ {
FSTCluster() : singleHashCtx(nullptr, &EVP_MD_CTX_free) {}
uint32 offset; uint32 offset;
uint32 size; uint32 size;
ClusterHashMode hashMode; ClusterHashMode hashMode;
// extra data if TMD is available
bool hasContentHash;
uint8 contentHash32[32];
bool contentHashIsSHA1; // if true then it's SHA1 (with extra bytes zeroed out), otherwise it's SHA256
uint64 contentSize; // size of the content (in blocks)
// hash context for single hash mode (content hash must be available)
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> singleHashCtx; // unique_ptr to make this move-only
uint32 singleHashNumBlocksHashed{0};
}; };
struct FSTEntry struct FSTEntry
@ -176,30 +164,17 @@ private:
bool m_sourceIsOwned{}; bool m_sourceIsOwned{};
uint32 m_sectorSize{}; // for cluster offsets uint32 m_sectorSize{}; // for cluster offsets
uint32 m_offsetFactor{}; // for file offsets uint32 m_offsetFactor{}; // for file offsets
bool m_hashIsDisabled{}; // disables hash verification (for all clusters of this volume?)
std::vector<FSTCluster> m_cluster; std::vector<FSTCluster> m_cluster;
std::vector<FSTEntry> m_entries; std::vector<FSTEntry> m_entries;
std::vector<char> m_nameStringTable; std::vector<char> m_nameStringTable;
NCrypto::AesKey m_partitionTitlekey; NCrypto::AesKey m_partitionTitlekey;
bool m_detectedCorruption{false};
bool HashIsDisabled() const /* Cache for decrypted hashed blocks */
{
return m_hashIsDisabled;
}
/* Cache for decrypted raw and hashed blocks */
std::unordered_map<uint64, struct FSTCachedRawBlock*> m_cacheDecryptedRawBlocks;
std::unordered_map<uint64, struct FSTCachedHashedBlock*> m_cacheDecryptedHashedBlocks; std::unordered_map<uint64, struct FSTCachedHashedBlock*> m_cacheDecryptedHashedBlocks;
uint64 m_cacheAccessCounter{}; uint64 m_cacheAccessCounter{};
void DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, uint8 ivOut[16]);
struct FSTCachedRawBlock* GetDecryptedRawBlock(uint32 clusterIndex, uint32 blockIndex);
struct FSTCachedHashedBlock* GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex); struct FSTCachedHashedBlock* GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex);
void TrimCacheIfRequired(struct FSTCachedRawBlock** droppedRawBlock, struct FSTCachedHashedBlock** droppedHashedBlock);
/* File reading */ /* File reading */
uint32 ReadFile_HashModeRaw(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut); uint32 ReadFile_HashModeRaw(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut);
uint32 ReadFile_HashModeHashed(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut); uint32 ReadFile_HashModeHashed(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut);
@ -210,10 +185,7 @@ private:
/* +0x00 */ uint32be magic; /* +0x00 */ uint32be magic;
/* +0x04 */ uint32be offsetFactor; /* +0x04 */ uint32be offsetFactor;
/* +0x08 */ uint32be numCluster; /* +0x08 */ uint32be numCluster;
/* +0x0C */ uint8be hashIsDisabled; /* +0x0C */ uint32be ukn0C;
/* +0x0D */ uint8be ukn0D;
/* +0x0E */ uint8be ukn0E;
/* +0x0F */ uint8be ukn0F;
/* +0x10 */ uint32be ukn10; /* +0x10 */ uint32be ukn10;
/* +0x14 */ uint32be ukn14; /* +0x14 */ uint32be ukn14;
/* +0x18 */ uint32be ukn18; /* +0x18 */ uint32be ukn18;
@ -290,8 +262,8 @@ private:
static_assert(sizeof(FSTHeader_FileEntry) == 0x10); static_assert(sizeof(FSTHeader_FileEntry) == 0x10);
static FSTVolume* OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode, NCrypto::TMDParser* optionalTMD); static FSTVolume* OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode);
static FSTVolume* OpenFST(std::unique_ptr<FSTDataSource> dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode, NCrypto::TMDParser* optionalTMD); static FSTVolume* OpenFST(std::unique_ptr<FSTDataSource> dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode);
static bool ProcessFST(FSTHeader_FileEntry* fileTable, uint32 numFileEntries, uint32 numCluster, std::vector<char>& nameStringTable, std::vector<FSTEntry>& fstEntries); static bool ProcessFST(FSTHeader_FileEntry* fileTable, uint32 numFileEntries, uint32 numCluster, std::vector<char>& nameStringTable, std::vector<FSTEntry>& fstEntries);
bool MatchFSTEntryName(FSTEntry& entry, std::string_view comparedName) bool MatchFSTEntryName(FSTEntry& entry, std::string_view comparedName)

View file

@ -3,8 +3,6 @@
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include "../fsc.h"
// path parser and utility class for Wii U paths // path parser and utility class for Wii U paths
// optimized to be allocation-free for common path lengths // optimized to be allocation-free for common path lengths
class FSCPath class FSCPath
@ -121,7 +119,9 @@ public:
template<typename F> template<typename F>
class FSAFileTree class FSAFileTree
{ {
private: public:
private:
enum NODETYPE : uint8 enum NODETYPE : uint8
{ {
@ -133,7 +133,6 @@ class FSAFileTree
{ {
std::string name; std::string name;
std::vector<node_t*> subnodes; std::vector<node_t*> subnodes;
size_t fileSize;
F* custom; F* custom;
NODETYPE type; NODETYPE type;
}; };
@ -180,54 +179,13 @@ class FSAFileTree
return newNode; return newNode;
} }
class DirectoryIterator : public FSCVirtualFile
{
public:
DirectoryIterator(node_t* node)
: m_node(node), m_subnodeIndex(0)
{
}
sint32 fscGetType() override
{
return FSC_TYPE_DIRECTORY;
}
bool fscDirNext(FSCDirEntry* dirEntry) override
{
if (m_subnodeIndex >= m_node->subnodes.size())
return false;
const node_t* subnode = m_node->subnodes[m_subnodeIndex];
strncpy(dirEntry->path, subnode->name.c_str(), sizeof(dirEntry->path) - 1);
dirEntry->path[sizeof(dirEntry->path) - 1] = '\0';
dirEntry->isDirectory = subnode->type == FSAFileTree::NODETYPE_DIRECTORY;
dirEntry->isFile = subnode->type == FSAFileTree::NODETYPE_FILE;
dirEntry->fileSize = subnode->type == FSAFileTree::NODETYPE_FILE ? subnode->fileSize : 0;
++m_subnodeIndex;
return true;
}
bool fscRewindDir() override
{
m_subnodeIndex = 0;
return true;
}
private:
node_t* m_node;
size_t m_subnodeIndex;
};
public: public:
FSAFileTree() FSAFileTree()
{ {
rootNode.type = NODETYPE_DIRECTORY; rootNode.type = NODETYPE_DIRECTORY;
} }
bool addFile(std::string_view path, size_t fileSize, F* custom) bool addFile(std::string_view path, F* custom)
{ {
FSCPath p(path); FSCPath p(path);
if (p.GetNodeCount() == 0) if (p.GetNodeCount() == 0)
@ -238,7 +196,6 @@ public:
return false; // node already exists return false; // node already exists
// add file node // add file node
node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1)); node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1));
fileNode->fileSize = fileSize;
fileNode->custom = custom; fileNode->custom = custom;
return true; return true;
} }
@ -257,20 +214,6 @@ public:
return true; return true;
} }
bool getDirectory(std::string_view path, FSCVirtualFile*& dirIterator)
{
FSCPath p(path);
if (p.GetNodeCount() == 0)
return false;
node_t* node = getByNodePath(p, p.GetNodeCount(), false);
if (node == nullptr)
return false;
if (node->type != NODETYPE_DIRECTORY)
return false;
dirIterator = new DirectoryIterator(node);
return true;
}
bool removeFile(std::string_view path) bool removeFile(std::string_view path)
{ {
FSCPath p(path); FSCPath p(path);

View file

@ -1,40 +0,0 @@
#pragma once
struct romfs_header_t
{
uint32 header_magic;
uint32be header_size;
uint64be dir_hash_table_ofs;
uint64be dir_hash_table_size;
uint64be dir_table_ofs;
uint64be dir_table_size;
uint64be file_hash_table_ofs;
uint64be file_hash_table_size;
uint64be file_table_ofs;
uint64be file_table_size;
uint64be file_partition_ofs;
};
struct romfs_direntry_t
{
uint32be parent;
uint32be listNext; // offset to next directory entry in linked list of parent directory (aka "sibling")
uint32be dirListHead; // offset to first entry in linked list of directory entries (aka "child")
uint32be fileListHead; // offset to first entry in linked list of file entries (aka "file")
uint32be hash;
uint32be name_size;
std::string name;
};
struct romfs_fentry_t
{
uint32be parent;
uint32be listNext; // offset to next file entry in linked list of parent directory (aka "sibling")
uint64be offset;
uint64be size;
uint32be hash;
uint32be name_size;
std::string name;
};
#define ROMFS_ENTRY_EMPTY 0xFFFFFFFF

View file

@ -1,224 +0,0 @@
#include "WUHBReader.h"
WUHBReader* WUHBReader::FromPath(const fs::path& path)
{
FileStream* fileIn{FileStream::openFile2(path)};
if (!fileIn)
return nullptr;
WUHBReader* ret = new WUHBReader(fileIn);
if (!ret->CheckMagicValue())
{
delete ret;
return nullptr;
}
if (!ret->ReadHeader())
{
delete ret;
return nullptr;
}
return ret;
}
static const romfs_direntry_t fallbackDirEntry{
.parent = ROMFS_ENTRY_EMPTY,
.listNext = ROMFS_ENTRY_EMPTY,
.dirListHead = ROMFS_ENTRY_EMPTY,
.fileListHead = ROMFS_ENTRY_EMPTY,
.hash = ROMFS_ENTRY_EMPTY,
.name_size = 0,
.name = ""
};
static const romfs_fentry_t fallbackFileEntry{
.parent = ROMFS_ENTRY_EMPTY,
.listNext = ROMFS_ENTRY_EMPTY,
.offset = 0,
.size = 0,
.hash = ROMFS_ENTRY_EMPTY,
.name_size = 0,
.name = ""
};
template<bool File>
const WUHBReader::EntryType<File>& WUHBReader::GetFallback()
{
if constexpr (File)
return fallbackFileEntry;
else
return fallbackDirEntry;
}
template<bool File>
WUHBReader::EntryType<File> WUHBReader::GetEntry(uint32 offset) const
{
auto fallback = GetFallback<File>();
if(offset == ROMFS_ENTRY_EMPTY)
return fallback;
const char* typeName = File ? "fentry" : "direntry";
EntryType<File> ret;
if (offset >= (File ? m_header.file_table_size : m_header.dir_table_size))
{
cemuLog_log(LogType::Force, "WUHB {} offset exceeds table size declared in header", typeName);
return fallback;
}
// read the entry
m_fileIn->SetPosition((File ? m_header.file_table_ofs : m_header.dir_table_ofs) + offset);
auto read = m_fileIn->readData(&ret, offsetof(EntryType<File>, name));
if (read != offsetof(EntryType<File>, name))
{
cemuLog_log(LogType::Force, "failed to read WUHB {} at offset: {}", typeName, offset);
return fallback;
}
// read the name
ret.name.resize(ret.name_size);
read = m_fileIn->readData(ret.name.data(), ret.name_size);
if (read != ret.name_size)
{
cemuLog_log(LogType::Force, "failed to read WUHB {} name", typeName);
return fallback;
}
return ret;
}
romfs_direntry_t WUHBReader::GetDirEntry(uint32 offset) const
{
return GetEntry<false>(offset);
}
romfs_fentry_t WUHBReader::GetFileEntry(uint32 offset) const
{
return GetEntry<true>(offset);
}
uint64 WUHBReader::GetFileSize(uint32 entryOffset) const
{
return GetFileEntry(entryOffset).size;
}
uint64 WUHBReader::ReadFromFile(uint32 entryOffset, uint64 fileOffset, uint64 length, void* buffer) const
{
const auto fileEntry = GetFileEntry(entryOffset);
if (fileOffset >= fileEntry.size)
return 0;
const uint64 readAmount = std::min(length, fileEntry.size - fileOffset);
const uint64 wuhbOffset = m_header.file_partition_ofs + fileEntry.offset + fileOffset;
m_fileIn->SetPosition(wuhbOffset);
return m_fileIn->readData(buffer, readAmount);
}
uint32 WUHBReader::GetHashTableEntryOffset(uint32 hash, bool isFile) const
{
const uint64 hash_table_size = (isFile ? m_header.file_hash_table_size : m_header.dir_hash_table_size);
const uint64 hash_table_ofs = (isFile ? m_header.file_hash_table_ofs : m_header.dir_hash_table_ofs);
const uint64 hash_table_entry_count = hash_table_size / sizeof(uint32);
const uint64 hash_table_entry_offset = hash_table_ofs + (hash % hash_table_entry_count) * sizeof(uint32);
m_fileIn->SetPosition(hash_table_entry_offset);
uint32 tableOffset;
if (!m_fileIn->readU32(tableOffset))
{
cemuLog_log(LogType::Force, "failed to read WUHB hash table entry at file offset: {}", hash_table_entry_offset);
return ROMFS_ENTRY_EMPTY;
}
return uint32be::from_bevalue(tableOffset);
}
template<bool T>
bool WUHBReader::SearchHashList(uint32& entryOffset, const fs::path& targetName) const
{
for (;;)
{
if (entryOffset == ROMFS_ENTRY_EMPTY)
return false;
auto entry = GetEntry<T>(entryOffset);
if (entry.name == targetName)
return true;
entryOffset = entry.hash;
}
return false;
}
uint32 WUHBReader::Lookup(const std::filesystem::path& path, bool isFile) const
{
uint32 currentEntryOffset = 0;
auto look = [&](const fs::path& part, bool lookInFileHT) {
const auto partString = part.string();
currentEntryOffset = GetHashTableEntryOffset(CalcPathHash(currentEntryOffset, partString.c_str(), 0, partString.size()), lookInFileHT);
if (lookInFileHT)
return SearchHashList<true>(currentEntryOffset, part);
else
return SearchHashList<false>(currentEntryOffset, part);
};
// look for the root entry
if (!look("", false))
return ROMFS_ENTRY_EMPTY;
auto it = path.begin();
while (it != path.end())
{
fs::path part = *it;
++it;
// no need to recurse after trailing forward slash (e.g. directory/)
if (part.empty() && !isFile)
break;
// skip leading forward slash
if (part == "/")
continue;
// if the lookup target is a file and this is the last iteration, look in the file hash table instead.
if (!look(part, it == path.end() && isFile))
return ROMFS_ENTRY_EMPTY;
}
return currentEntryOffset;
}
bool WUHBReader::CheckMagicValue() const
{
uint8 magic[4];
m_fileIn->SetPosition(0);
int read = m_fileIn->readData(magic, 4);
if (read != 4)
{
cemuLog_log(LogType::Force, "Failed to read WUHB magic numbers");
return false;
}
static_assert(sizeof(magic) == s_headerMagicValue.size());
return std::memcmp(&magic, s_headerMagicValue.data(), sizeof(magic)) == 0;
}
bool WUHBReader::ReadHeader()
{
m_fileIn->SetPosition(0);
auto read = m_fileIn->readData(&m_header, sizeof(m_header));
auto readSuccess = read == sizeof(m_header);
if (!readSuccess)
cemuLog_log(LogType::Force, "Failed to read WUHB header");
return readSuccess;
}
unsigned char WUHBReader::NormalizeChar(unsigned char c)
{
if (c >= 'a' && c <= 'z')
{
return c + 'A' - 'a';
}
else
{
return c;
}
}
uint32 WUHBReader::CalcPathHash(uint32 parent, const char* path, uint32 start, size_t path_len)
{
cemu_assert(path != nullptr || path_len == 0);
uint32 hash = parent ^ 123456789;
for (uint32 i = 0; i < path_len; i++)
{
hash = (hash >> 5) | (hash << 27);
hash ^= NormalizeChar(path[start + i]);
}
return hash;
}

View file

@ -1,45 +0,0 @@
#pragma once
#include <Common/FileStream.h>
#include "RomFSStructs.h"
class WUHBReader
{
public:
static WUHBReader* FromPath(const fs::path& path);
romfs_direntry_t GetDirEntry(uint32 offset) const;
romfs_fentry_t GetFileEntry(uint32 offset) const;
uint64 GetFileSize(uint32 entryOffset) const;
uint64 ReadFromFile(uint32 entryOffset, uint64 fileOffset, uint64 length, void* buffer) const;
uint32 Lookup(const std::filesystem::path& path, bool isFile) const;
private:
WUHBReader(FileStream* file)
: m_fileIn(file)
{
cemu_assert_debug(file != nullptr);
};
WUHBReader() = delete;
romfs_header_t m_header;
std::unique_ptr<FileStream> m_fileIn;
constexpr static std::string_view s_headerMagicValue = "WUHB";
bool ReadHeader();
bool CheckMagicValue() const;
static inline unsigned char NormalizeChar(unsigned char c);
static uint32 CalcPathHash(uint32 parent, const char* path, uint32 start, size_t path_len);
template<bool File>
using EntryType = std::conditional_t<File, romfs_fentry_t, romfs_direntry_t>;
template<bool File>
static const EntryType<File>& GetFallback();
template<bool File>
EntryType<File> GetEntry(uint32 offset) const;
template<bool T>
bool SearchHashList(uint32& entryOffset, const fs::path& targetName) const;
uint32 GetHashTableEntryOffset(uint32 hash, bool isFile) const;
};

View file

@ -204,12 +204,9 @@ bool FSCDeviceWUD_Mount(std::string_view mountPath, std::string_view destination
// wua device // wua device
bool FSCDeviceWUA_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class ZArchiveReader* archive, sint32 priority); bool FSCDeviceWUA_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class ZArchiveReader* archive, sint32 priority);
// wuhb device
bool FSCDeviceWUHB_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class WUHBReader* wuhbReader, sint32 priority);
// hostFS device // hostFS device
bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority); bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority);
// redirect device // redirect device
void fscDeviceRedirect_map(); void fscDeviceRedirect_map();
void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize, const fs::path& targetFilePath, sint32 priority); void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority);

View file

@ -11,7 +11,7 @@ struct RedirectEntry
FSAFileTree<RedirectEntry> redirectTree; FSAFileTree<RedirectEntry> redirectTree;
void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize, const fs::path& targetFilePath, sint32 priority) void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority)
{ {
// check if source already has a redirection // check if source already has a redirection
RedirectEntry* existingEntry; RedirectEntry* existingEntry;
@ -24,7 +24,7 @@ void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize,
delete existingEntry; delete existingEntry;
} }
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority); RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
redirectTree.addFile(virtualSourcePath, fileSize, entry); redirectTree.addFile(virtualSourcePath, entry);
} }
class fscDeviceTypeRedirect : public fscDeviceC class fscDeviceTypeRedirect : public fscDeviceC
@ -32,15 +32,8 @@ class fscDeviceTypeRedirect : public fscDeviceC
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
{ {
RedirectEntry* redirectionEntry; RedirectEntry* redirectionEntry;
if (redirectTree.getFile(path, redirectionEntry))
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE) && redirectTree.getFile(path, redirectionEntry))
return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus); return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus);
FSCVirtualFile* dirIterator;
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR) && redirectTree.getDirectory(path, dirIterator))
return dirIterator;
return nullptr; return nullptr;
} }

View file

@ -1,151 +0,0 @@
#include "Filesystem/WUHB/WUHBReader.h"
#include "Cafe/Filesystem/fsc.h"
#include "Cafe/Filesystem/FST/FST.h"
class FSCDeviceWuhbFileCtx : public FSCVirtualFile
{
public:
FSCDeviceWuhbFileCtx(WUHBReader* reader, uint32 entryOffset, uint32 fscType)
: m_wuhbReader(reader), m_entryOffset(entryOffset), m_fscType(fscType)
{
cemu_assert(entryOffset != ROMFS_ENTRY_EMPTY);
if (fscType == FSC_TYPE_DIRECTORY)
{
romfs_direntry_t entry = reader->GetDirEntry(entryOffset);
m_dirIterOffset = entry.dirListHead;
m_fileIterOffset = entry.fileListHead;
}
}
sint32 fscGetType() override
{
return m_fscType;
}
uint64 fscQueryValueU64(uint32 id) override
{
if (m_fscType == FSC_TYPE_FILE)
{
if (id == FSC_QUERY_SIZE)
return m_wuhbReader->GetFileSize(m_entryOffset);
else if (id == FSC_QUERY_WRITEABLE)
return 0; // WUHB images are read-only
else
cemu_assert_error();
}
else
{
cemu_assert_unimplemented();
}
return 0;
}
uint32 fscWriteData(void* buffer, uint32 size) override
{
cemu_assert_error();
return 0;
}
uint32 fscReadData(void* buffer, uint32 size) override
{
if (m_fscType != FSC_TYPE_FILE)
return 0;
auto read = m_wuhbReader->ReadFromFile(m_entryOffset, m_seek, size, buffer);
m_seek += read;
return read;
}
void fscSetSeek(uint64 seek) override
{
m_seek = seek;
}
uint64 fscGetSeek() override
{
if (m_fscType != FSC_TYPE_FILE)
return 0;
return m_seek;
}
void fscSetFileLength(uint64 endOffset) override
{
cemu_assert_error();
}
bool fscDirNext(FSCDirEntry* dirEntry) override
{
if (m_dirIterOffset != ROMFS_ENTRY_EMPTY)
{
romfs_direntry_t entry = m_wuhbReader->GetDirEntry(m_dirIterOffset);
m_dirIterOffset = entry.listNext;
if(entry.name_size > 0)
{
dirEntry->isDirectory = true;
dirEntry->isFile = false;
dirEntry->fileSize = 0;
std::strncpy(dirEntry->path, entry.name.c_str(), FSC_MAX_DIR_NAME_LENGTH);
return true;
}
}
if (m_fileIterOffset != ROMFS_ENTRY_EMPTY)
{
romfs_fentry_t entry = m_wuhbReader->GetFileEntry(m_fileIterOffset);
m_fileIterOffset = entry.listNext;
if(entry.name_size > 0)
{
dirEntry->isDirectory = false;
dirEntry->isFile = true;
dirEntry->fileSize = entry.size;
std::strncpy(dirEntry->path, entry.name.c_str(), FSC_MAX_DIR_NAME_LENGTH);
return true;
}
}
return false;
}
private:
WUHBReader* m_wuhbReader{};
uint32 m_fscType;
uint32 m_entryOffset = ROMFS_ENTRY_EMPTY;
uint32 m_dirIterOffset = ROMFS_ENTRY_EMPTY;
uint32 m_fileIterOffset = ROMFS_ENTRY_EMPTY;
uint64 m_seek = 0;
};
class fscDeviceWUHB : public fscDeviceC
{
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
{
WUHBReader* reader = (WUHBReader*)ctx;
cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to WUHB is not supported
bool isFile;
uint32 table_offset = ROMFS_ENTRY_EMPTY;
if (table_offset == ROMFS_ENTRY_EMPTY && HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR))
{
table_offset = reader->Lookup(path, false);
isFile = false;
}
if (table_offset == ROMFS_ENTRY_EMPTY && HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE))
{
table_offset = reader->Lookup(path, true);
isFile = true;
}
if (table_offset == ROMFS_ENTRY_EMPTY)
{
*fscStatus = FSC_STATUS_FILE_NOT_FOUND;
return nullptr;
}
*fscStatus = FSC_STATUS_OK;
return new FSCDeviceWuhbFileCtx(reader, table_offset, isFile ? FSC_TYPE_FILE : FSC_TYPE_DIRECTORY);
}
// singleton
public:
static fscDeviceWUHB& instance()
{
static fscDeviceWUHB _instance;
return _instance;
}
};
bool FSCDeviceWUHB_Mount(std::string_view mountPath, std::string_view destinationBaseDir, WUHBReader* wuhbReader, sint32 priority)
{
return fsc_mount(mountPath, destinationBaseDir, &fscDeviceWUHB::instance(), wuhbReader, priority) == FSC_STATUS_OK;
}

View file

@ -140,7 +140,7 @@ bool gameProfile_loadEnumOption(IniParser& iniParser, const char* optionName, T&
for(const T& v : T()) for(const T& v : T())
{ {
// test integer option // test integer option
if (boost::iequals(fmt::format("{}", fmt::underlying(v)), *option_value)) if (boost::iequals(fmt::format("{}", static_cast<typename std::underlying_type<T>::type>(v)), *option_value))
{ {
option = v; option = v;
return true; return true;

View file

@ -345,7 +345,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
const auto preset_name = rules.FindOption("name"); const auto preset_name = rules.FindOption("name");
if (!preset_name) if (!preset_name)
{ {
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Preset in line {} skipped because it has no name option defined", GetNormalizedPathString(), rules.GetCurrentSectionLineNumber()); cemuLog_log(LogType::Force, "Graphic pack \"{}\": Preset in line {} skipped because it has no name option defined", m_name, rules.GetCurrentSectionLineNumber());
continue; continue;
} }
@ -369,7 +369,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
} }
catch (const std::exception & ex) catch (const std::exception & ex)
{ {
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Can't parse preset \"{}\": {}", GetNormalizedPathString(), *preset_name, ex.what()); cemuLog_log(LogType::Force, "Graphic pack \"{}\": Can't parse preset \"{}\": {}", m_name, *preset_name, ex.what());
} }
} }
else if (boost::iequals(currentSectionName, "RAM")) else if (boost::iequals(currentSectionName, "RAM"))
@ -383,7 +383,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
{ {
if (m_version <= 5) if (m_version <= 5)
{ {
cemuLog_log(LogType::Force, "Graphic pack \"{}\": [RAM] options are only available for graphic pack version 6 or higher", GetNormalizedPathString(), optionNameBuf); cemuLog_log(LogType::Force, "Graphic pack \"{}\": [RAM] options are only available for graphic pack version 6 or higher", m_name, optionNameBuf);
throw std::exception(); throw std::exception();
} }
@ -393,12 +393,12 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
{ {
if (addrEnd <= addrStart) if (addrEnd <= addrStart)
{ {
cemuLog_log(LogType::Force, "Graphic pack \"{}\": start address (0x{:08x}) must be greater than end address (0x{:08x}) for {}", GetNormalizedPathString(), addrStart, addrEnd, optionNameBuf); cemuLog_log(LogType::Force, "Graphic pack \"{}\": start address (0x{:08x}) must be greater than end address (0x{:08x}) for {}", m_name, addrStart, addrEnd, optionNameBuf);
throw std::exception(); throw std::exception();
} }
else if ((addrStart & 0xFFF) != 0 || (addrEnd & 0xFFF) != 0) else if ((addrStart & 0xFFF) != 0 || (addrEnd & 0xFFF) != 0)
{ {
cemuLog_log(LogType::Force, "Graphic pack \"{}\": addresses for %s are not aligned to 0x1000", GetNormalizedPathString(), optionNameBuf); cemuLog_log(LogType::Force, "Graphic pack \"{}\": addresses for %s are not aligned to 0x1000", m_name, optionNameBuf);
throw std::exception(); throw std::exception();
} }
else else
@ -408,7 +408,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
} }
else else
{ {
cemuLog_log(LogType::Force, "Graphic pack \"{}\": has invalid syntax for option {}", GetNormalizedPathString(), optionNameBuf); cemuLog_log(LogType::Force, "Graphic pack \"{}\": has invalid syntax for option {}", m_name, optionNameBuf);
throw std::exception(); throw std::exception();
} }
} }
@ -422,30 +422,22 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
std::unordered_map<std::string, std::vector<PresetPtr>> tmp_map; std::unordered_map<std::string, std::vector<PresetPtr>> tmp_map;
// all vars must be defined in the default preset vars before // all vars must be defined in the default preset vars before
std::vector<std::pair<std::string, std::string>> mismatchingPresetVars; for (const auto& entry : m_presets)
for (const auto& presetEntry : m_presets)
{ {
tmp_map[presetEntry->category].emplace_back(presetEntry); tmp_map[entry->category].emplace_back(entry);
for (auto& presetVar : presetEntry->variables) for (auto& kv : entry->variables)
{ {
const auto it = m_preset_vars.find(presetVar.first); const auto it = m_preset_vars.find(kv.first);
if (it == m_preset_vars.cend()) if (it == m_preset_vars.cend())
{ {
mismatchingPresetVars.emplace_back(presetEntry->name, presetVar.first); cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains preset variables which are not defined in the default section", m_name);
continue; throw std::exception();
} }
// overwrite var type with default var type
presetVar.second.first = it->second.first;
}
}
if(!mismatchingPresetVars.empty()) // overwrite var type with default var type
{ kv.second.first = it->second.first;
cemuLog_log(LogType::Force, "Graphic pack \"{}\" contains preset variables which are not defined in the [Default] section:", GetNormalizedPathString()); }
for (const auto& [presetName, varName] : mismatchingPresetVars)
cemuLog_log(LogType::Force, "Preset: {} Variable: {}", presetName, varName);
throw std::exception();
} }
// have first entry be default active for every category if no default= is set // have first entry be default active for every category if no default= is set
@ -477,7 +469,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
auto& p2 = kv.second[i + 1]; auto& p2 = kv.second[i + 1];
if (p1->variables.size() != p2->variables.size()) if (p1->variables.size() != p2->variables.size())
{ {
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", GetNormalizedPathString()); cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", m_name);
throw std::exception(); throw std::exception();
} }
@ -485,14 +477,14 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
std::set<std::string> keys2(get_keys(p2->variables).begin(), get_keys(p2->variables).end()); std::set<std::string> keys2(get_keys(p2->variables).begin(), get_keys(p2->variables).end());
if (keys1 != keys2) if (keys1 != keys2)
{ {
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", GetNormalizedPathString()); cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", m_name);
throw std::exception(); throw std::exception();
} }
if(p1->is_default) if(p1->is_default)
{ {
if(has_default) if(has_default)
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" has more than one preset with the default key set for the same category \"{}\"", GetNormalizedPathString(), p1->name); cemuLog_log(LogType::Force, "Graphic pack: \"{}\" has more than one preset with the default key set for the same category \"{}\"", m_name, p1->name);
p1->active = true; p1->active = true;
has_default = true; has_default = true;
} }
@ -838,7 +830,7 @@ void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, bool isAOC
{ {
virtualMountPath = fs::path("vol/content/") / virtualMountPath; virtualMountPath = fs::path("vol/content/") / virtualMountPath;
} }
fscDeviceRedirect_add(virtualMountPath.generic_string(), it.file_size(), it.path().generic_string(), m_fs_priority); fscDeviceRedirect_add(virtualMountPath.generic_string(), it.path().generic_string(), m_fs_priority);
} }
} }
} }
@ -968,7 +960,7 @@ bool GraphicPack2::Activate()
auto option_upscale = rules.FindOption("upscaleMagFilter"); auto option_upscale = rules.FindOption("upscaleMagFilter");
if(option_upscale && boost::iequals(*option_upscale, "NearestNeighbor")) if(option_upscale && boost::iequals(*option_upscale, "NearestNeighbor"))
m_output_settings.upscale_filter = LatteTextureView::MagFilter::kNearestNeighbor; m_output_settings.upscale_filter = LatteTextureView::MagFilter::kNearestNeighbor;
auto option_downscale = rules.FindOption("downscaleMinFilter"); auto option_downscale = rules.FindOption("NearestNeighbor");
if (option_downscale && boost::iequals(*option_downscale, "NearestNeighbor")) if (option_downscale && boost::iequals(*option_downscale, "NearestNeighbor"))
m_output_settings.downscale_filter = LatteTextureView::MagFilter::kNearestNeighbor; m_output_settings.downscale_filter = LatteTextureView::MagFilter::kNearestNeighbor;
} }

View file

@ -8,7 +8,6 @@
#include "gui/debugger/DebuggerWindow2.h" #include "gui/debugger/DebuggerWindow2.h"
#include "Cafe/OS/libs/coreinit/coreinit.h" #include "Cafe/OS/libs/coreinit/coreinit.h"
#include "util/helpers/helpers.h"
#if BOOST_OS_WINDOWS #if BOOST_OS_WINDOWS
#include <Windows.h> #include <Windows.h>
@ -137,6 +136,11 @@ void debugger_createCodeBreakpoint(uint32 address, uint8 bpType)
debugger_updateExecutionBreakpoint(address); debugger_updateExecutionBreakpoint(address);
} }
void debugger_createExecuteBreakpoint(uint32 address)
{
debugger_createCodeBreakpoint(address, DEBUGGER_BP_T_NORMAL);
}
namespace coreinit namespace coreinit
{ {
std::vector<std::thread::native_handle_type>& OSGetSchedulerThreads(); std::vector<std::thread::native_handle_type>& OSGetSchedulerThreads();
@ -290,23 +294,8 @@ void debugger_toggleExecuteBreakpoint(uint32 address)
} }
else else
{ {
// create new execution breakpoint // create new breakpoint
debugger_createCodeBreakpoint(address, DEBUGGER_BP_T_NORMAL); debugger_createExecuteBreakpoint(address);
}
}
void debugger_toggleLoggingBreakpoint(uint32 address)
{
auto existingBP = debugger_getFirstBP(address, DEBUGGER_BP_T_LOGGING);
if (existingBP)
{
// delete existing breakpoint
debugger_deleteBreakpoint(existingBP);
}
else
{
// create new logging breakpoint
debugger_createCodeBreakpoint(address, DEBUGGER_BP_T_LOGGING);
} }
} }
@ -458,34 +447,6 @@ bool debugger_hasPatch(uint32 address)
return false; return false;
} }
void debugger_removePatch(uint32 address)
{
for (sint32 i = 0; i < debuggerState.patches.size(); i++)
{
auto& patch = debuggerState.patches[i];
if (address < patch->address || address >= (patch->address + patch->length))
continue;
MPTR startAddress = patch->address;
MPTR endAddress = patch->address + patch->length;
// remove any breakpoints overlapping with the patch
for (auto& bp : debuggerState.breakpoints)
{
if (bp->address + 4 > startAddress && bp->address < endAddress)
{
bp->enabled = false;
debugger_updateExecutionBreakpoint(bp->address);
}
}
// restore original data
memcpy(MEMPTR<void>(startAddress).GetPtr(), patch->origData.data(), patch->length);
PPCRecompiler_invalidateRange(startAddress, endAddress);
// remove patch
delete patch;
debuggerState.patches.erase(debuggerState.patches.begin() + i);
return;
}
}
void debugger_stepInto(PPCInterpreter_t* hCPU, bool updateDebuggerWindow = true) void debugger_stepInto(PPCInterpreter_t* hCPU, bool updateDebuggerWindow = true)
{ {
bool isRecEnabled = ppcRecompilerEnabled; bool isRecEnabled = ppcRecompilerEnabled;
@ -540,6 +501,8 @@ void debugger_createPPCStateSnapshot(PPCInterpreter_t* hCPU)
debuggerState.debugSession.ppcSnapshot.cr[i] = hCPU->cr[i]; debuggerState.debugSession.ppcSnapshot.cr[i] = hCPU->cr[i];
} }
void DebugLogStackTrace(OSThread_t* thread, MPTR sp);
void debugger_enterTW(PPCInterpreter_t* hCPU) void debugger_enterTW(PPCInterpreter_t* hCPU)
{ {
// handle logging points // handle logging points
@ -549,48 +512,7 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
{ {
if (bp->bpType == DEBUGGER_BP_T_LOGGING && bp->enabled) if (bp->bpType == DEBUGGER_BP_T_LOGGING && bp->enabled)
{ {
std::string comment = !bp->comment.empty() ? boost::nowide::narrow(bp->comment) : fmt::format("Breakpoint at 0x{:08X} (no comment)", bp->address); std::string logName = !bp->comment.empty() ? "Breakpoint '"+boost::nowide::narrow(bp->comment)+"'" : fmt::format("Breakpoint at 0x{:08X} (no comment)", bp->address);
auto replacePlaceholders = [&](const std::string& prefix, const auto& formatFunc)
{
size_t pos = 0;
while ((pos = comment.find(prefix, pos)) != std::string::npos)
{
size_t endPos = comment.find('}', pos);
if (endPos == std::string::npos)
break;
try
{
if (int regNum = ConvertString<int>(comment.substr(pos + prefix.length(), endPos - pos - prefix.length())); regNum >= 0 && regNum < 32)
{
std::string replacement = formatFunc(regNum);
comment.replace(pos, endPos - pos + 1, replacement);
pos += replacement.length();
}
else
{
pos = endPos + 1;
}
}
catch (...)
{
pos = endPos + 1;
}
}
};
// Replace integer register placeholders {rX}
replacePlaceholders("{r", [&](int regNum) {
return fmt::format("0x{:08X}", hCPU->gpr[regNum]);
});
// Replace floating point register placeholders {fX}
replacePlaceholders("{f", [&](int regNum) {
return fmt::format("{}", hCPU->fpr[regNum].fpr);
});
std::string logName = "Breakpoint '" + comment + "'";
std::string logContext = fmt::format("Thread: {:08x} LR: 0x{:08x}", MEMPTR<OSThread_t>(coreinit::OSGetCurrentThread()).GetMPTR(), hCPU->spr.LR, cemuLog_advancedPPCLoggingEnabled() ? " Stack Trace:" : ""); std::string logContext = fmt::format("Thread: {:08x} LR: 0x{:08x}", MEMPTR<OSThread_t>(coreinit::OSGetCurrentThread()).GetMPTR(), hCPU->spr.LR, cemuLog_advancedPPCLoggingEnabled() ? " Stack Trace:" : "");
cemuLog_log(LogType::Force, "[Debugger] {} was executed! {}", logName, logContext); cemuLog_log(LogType::Force, "[Debugger] {} was executed! {}", logName, logContext);
if (cemuLog_advancedPPCLoggingEnabled()) if (cemuLog_advancedPPCLoggingEnabled())
@ -627,7 +549,7 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
debuggerState.debugSession.stepInto = false; debuggerState.debugSession.stepInto = false;
debuggerState.debugSession.stepOver = false; debuggerState.debugSession.stepOver = false;
debuggerState.debugSession.run = false; debuggerState.debugSession.run = false;
while (debuggerState.debugSession.isTrapped) while (true)
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
// check for step commands // check for step commands

View file

@ -100,8 +100,8 @@ extern debuggerState_t debuggerState;
// new API // new API
DebuggerBreakpoint* debugger_getFirstBP(uint32 address); DebuggerBreakpoint* debugger_getFirstBP(uint32 address);
void debugger_createCodeBreakpoint(uint32 address, uint8 bpType); void debugger_createCodeBreakpoint(uint32 address, uint8 bpType);
void debugger_createExecuteBreakpoint(uint32 address);
void debugger_toggleExecuteBreakpoint(uint32 address); // create/remove execute breakpoint void debugger_toggleExecuteBreakpoint(uint32 address); // create/remove execute breakpoint
void debugger_toggleLoggingBreakpoint(uint32 address); // create/remove logging breakpoint
void debugger_toggleBreakpoint(uint32 address, bool state, DebuggerBreakpoint* bp); void debugger_toggleBreakpoint(uint32 address, bool state, DebuggerBreakpoint* bp);
void debugger_createMemoryBreakpoint(uint32 address, bool onRead, bool onWrite); void debugger_createMemoryBreakpoint(uint32 address, bool onRead, bool onWrite);
@ -114,7 +114,6 @@ void debugger_updateExecutionBreakpoint(uint32 address, bool forceRestore = fals
void debugger_createPatch(uint32 address, std::span<uint8> patchData); void debugger_createPatch(uint32 address, std::span<uint8> patchData);
bool debugger_hasPatch(uint32 address); bool debugger_hasPatch(uint32 address);
void debugger_removePatch(uint32 address);
void debugger_forceBreak(); // force breakpoint at the next possible instruction void debugger_forceBreak(); // force breakpoint at the next possible instruction
bool debugger_isTrapped(); bool debugger_isTrapped();

View file

@ -212,12 +212,11 @@ static void PPCInterpreter_SUBF(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_SUBFO(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_SUBFO(PPCInterpreter_t* hCPU, uint32 opcode)
{ {
// Seen in Don't Starve Giant Edition and Teslagrad // untested (Don't Starve Giant Edition uses this)
// also used by DS Virtual Console (Super Mario 64 DS) // also used by DS Virtual Console (Super Mario 64 DS)
PPC_OPC_TEMPL3_XO(); PPC_OPC_TEMPL3_XO();
uint32 result = ~hCPU->gpr[rA] + hCPU->gpr[rB] + 1; hCPU->gpr[rD] = ~hCPU->gpr[rA] + hCPU->gpr[rB] + 1;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~hCPU->gpr[rA], hCPU->gpr[rB], result)); PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~hCPU->gpr[rA], hCPU->gpr[rB], hCPU->gpr[rD]));
hCPU->gpr[rD] = result;
if (opHasRC()) if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]); ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU); PPCInterpreter_nextInstruction(hCPU);

View file

@ -90,7 +90,7 @@ uint8* PPCInterpreterGetStackPointer()
return memory_getPointerFromVirtualOffset(PPCInterpreter_getCurrentInstance()->gpr[1]); return memory_getPointerFromVirtualOffset(PPCInterpreter_getCurrentInstance()->gpr[1]);
} }
uint8* PPCInterpreter_PushAndReturnStackPointer(sint32 offset) uint8* PPCInterpreterGetAndModifyStackPointer(sint32 offset)
{ {
PPCInterpreter_t* hCPU = PPCInterpreter_getCurrentInstance(); PPCInterpreter_t* hCPU = PPCInterpreter_getCurrentInstance();
uint8* result = memory_getPointerFromVirtualOffset(hCPU->gpr[1] - offset); uint8* result = memory_getPointerFromVirtualOffset(hCPU->gpr[1] - offset);

View file

@ -5,28 +5,8 @@ struct PPCCoreCallbackData_t
{ {
sint32 gprCount = 0; sint32 gprCount = 0;
sint32 floatCount = 0; sint32 floatCount = 0;
sint32 stackCount = 0;
}; };
inline void _PPCCoreCallback_writeGPRArg(PPCCoreCallbackData_t& data, PPCInterpreter_t* hCPU, uint32 value)
{
if (data.gprCount < 8)
{
hCPU->gpr[3 + data.gprCount] = value;
data.gprCount++;
}
else
{
uint32 stackOffset = 8 + data.stackCount * 4;
// PPCCore_executeCallbackInternal does -16*4 to save the current stack area
stackOffset -= 16 * 4;
memory_writeU32(hCPU->gpr[1] + stackOffset, value);
data.stackCount++;
}
}
// callback functions // callback functions
inline uint32 PPCCoreCallback(MPTR function, const PPCCoreCallbackData_t& data) inline uint32 PPCCoreCallback(MPTR function, const PPCCoreCallbackData_t& data)
{ {
@ -36,21 +16,23 @@ inline uint32 PPCCoreCallback(MPTR function, const PPCCoreCallbackData_t& data)
template <typename T, typename... TArgs> template <typename T, typename... TArgs>
uint32 PPCCoreCallback(MPTR function, PPCCoreCallbackData_t& data, T currentArg, TArgs... args) uint32 PPCCoreCallback(MPTR function, PPCCoreCallbackData_t& data, T currentArg, TArgs... args)
{ {
// TODO float arguments on stack cemu_assert_debug(data.gprCount <= 8);
cemu_assert_debug(data.floatCount < 8); cemu_assert_debug(data.floatCount <= 8);
PPCInterpreter_t* hCPU = PPCInterpreter_getCurrentInstance(); PPCInterpreter_t* hCPU = PPCInterpreter_getCurrentInstance();
if constexpr (std::is_pointer_v<T>) if constexpr (std::is_pointer_v<T>)
{ {
_PPCCoreCallback_writeGPRArg(data, hCPU, MEMPTR(currentArg).GetMPTR()); hCPU->gpr[3 + data.gprCount] = MEMPTR(currentArg).GetMPTR();
data.gprCount++;
} }
else if constexpr (std::is_base_of_v<MEMPTRBase, std::remove_reference_t<T>>) else if constexpr (std::is_base_of_v<MEMPTRBase, std::remove_reference_t<T>>)
{ {
_PPCCoreCallback_writeGPRArg(data, hCPU, currentArg.GetMPTR()); hCPU->gpr[3 + data.gprCount] = currentArg.GetMPTR();
data.gprCount++;
} }
else if constexpr (std::is_reference_v<T>) else if constexpr (std::is_reference_v<T>)
{ {
_PPCCoreCallback_writeGPRArg(data, hCPU, MEMPTR(&currentArg).GetMPTR()); hCPU->gpr[3 + data.gprCount] = MEMPTR(&currentArg).GetMPTR();
data.gprCount++;
} }
else if constexpr(std::is_enum_v<T>) else if constexpr(std::is_enum_v<T>)
{ {
@ -71,7 +53,8 @@ uint32 PPCCoreCallback(MPTR function, PPCCoreCallbackData_t& data, T currentArg,
} }
else else
{ {
_PPCCoreCallback_writeGPRArg(data, hCPU, (uint32)currentArg); hCPU->gpr[3 + data.gprCount] = (uint32)currentArg;
data.gprCount++;
} }
return PPCCoreCallback(function, data, args...); return PPCCoreCallback(function, data, args...);

View file

@ -213,7 +213,7 @@ void PPCTimer_start();
// core info and control // core info and control
extern uint32 ppcThreadQuantum; extern uint32 ppcThreadQuantum;
uint8* PPCInterpreter_PushAndReturnStackPointer(sint32 offset); uint8* PPCInterpreterGetAndModifyStackPointer(sint32 offset);
uint8* PPCInterpreterGetStackPointer(); uint8* PPCInterpreterGetStackPointer();
void PPCInterpreterModifyStackPointer(sint32 offset); void PPCInterpreterModifyStackPointer(sint32 offset);

View file

@ -114,13 +114,13 @@ void* ATTR_MS_ABI PPCRecompiler_virtualHLE(PPCInterpreter_t* hCPU, uint32 hleFun
void ATTR_MS_ABI PPCRecompiler_getTBL(PPCInterpreter_t* hCPU, uint32 gprIndex) void ATTR_MS_ABI PPCRecompiler_getTBL(PPCInterpreter_t* hCPU, uint32 gprIndex)
{ {
uint64 coreTime = coreinit::OSGetSystemTime(); uint64 coreTime = coreinit::coreinit_getTimerTick();
hCPU->gpr[gprIndex] = (uint32)(coreTime&0xFFFFFFFF); hCPU->gpr[gprIndex] = (uint32)(coreTime&0xFFFFFFFF);
} }
void ATTR_MS_ABI PPCRecompiler_getTBU(PPCInterpreter_t* hCPU, uint32 gprIndex) void ATTR_MS_ABI PPCRecompiler_getTBU(PPCInterpreter_t* hCPU, uint32 gprIndex)
{ {
uint64 coreTime = coreinit::OSGetSystemTime(); uint64 coreTime = coreinit::coreinit_getTimerTick();
hCPU->gpr[gprIndex] = (uint32)((coreTime>>32)&0xFFFFFFFF); hCPU->gpr[gprIndex] = (uint32)((coreTime>>32)&0xFFFFFFFF);
} }

View file

@ -52,7 +52,7 @@ struct LatteGPUState_t
uint32 gx2InitCalled; // incremented every time GX2Init() is called uint32 gx2InitCalled; // incremented every time GX2Init() is called
// OpenGL control // OpenGL control
uint32 glVendor; // GLVENDOR_* uint32 glVendor; // GLVENDOR_*
bool isDRCPrimary = false; bool alwaysDisplayDRC = false;
// temporary (replace with proper solution later) // temporary (replace with proper solution later)
bool tvBufferUsesSRGB; bool tvBufferUsesSRGB;
bool drcBufferUsesSRGB; bool drcBufferUsesSRGB;

View file

@ -141,14 +141,6 @@ private:
void LatteCP_processCommandBuffer(DrawPassContext& drawPassCtx); void LatteCP_processCommandBuffer(DrawPassContext& drawPassCtx);
// called whenever the GPU runs out of commands or hits a wait condition (semaphores, HLE waits)
void LatteCP_signalEnterWait()
{
// based on the assumption that games won't do a rugpull and swap out buffer data in the middle of an uninterrupted sequence of drawcalls,
// we only flush caches when the GPU goes idle or has to wait for any operation
LatteIndices_invalidateAll();
}
/* /*
* Read a U32 from the command buffer * Read a U32 from the command buffer
* If no data is available then wait in a busy loop * If no data is available then wait in a busy loop
@ -474,8 +466,6 @@ LatteCMDPtr LatteCP_itWaitRegMem(LatteCMDPtr cmd, uint32 nWords)
const uint32 GPU7_WAIT_MEM_OP_GREATER = 6; const uint32 GPU7_WAIT_MEM_OP_GREATER = 6;
const uint32 GPU7_WAIT_MEM_OP_NEVER = 7; const uint32 GPU7_WAIT_MEM_OP_NEVER = 7;
LatteCP_signalEnterWait();
bool stalls = false; bool stalls = false;
if ((word0 & 0x10) != 0) if ((word0 & 0x10) != 0)
{ {
@ -604,7 +594,6 @@ LatteCMDPtr LatteCP_itMemSemaphore(LatteCMDPtr cmd, uint32 nWords)
else if(SEM_SIGNAL == 7) else if(SEM_SIGNAL == 7)
{ {
// wait // wait
LatteCP_signalEnterWait();
size_t loopCount = 0; size_t loopCount = 0;
while (true) while (true)
{ {
@ -799,7 +788,7 @@ LatteCMDPtr LatteCP_itHLESampleTimer(LatteCMDPtr cmd, uint32 nWords)
{ {
cemu_assert_debug(nWords == 1); cemu_assert_debug(nWords == 1);
MPTR timerMPTR = (MPTR)LatteReadCMD(); MPTR timerMPTR = (MPTR)LatteReadCMD();
memory_writeU64(timerMPTR, coreinit::OSGetSystemTime()); memory_writeU64(timerMPTR, coreinit::coreinit_getTimerTick());
return cmd; return cmd;
} }
@ -1316,13 +1305,11 @@ void LatteCP_processCommandBuffer(DrawPassContext& drawPassCtx)
} }
case IT_HLE_TRIGGER_SCANBUFFER_SWAP: case IT_HLE_TRIGGER_SCANBUFFER_SWAP:
{ {
LatteCP_signalEnterWait();
LatteCP_itHLESwapScanBuffer(cmdData, nWords); LatteCP_itHLESwapScanBuffer(cmdData, nWords);
break; break;
} }
case IT_HLE_WAIT_FOR_FLIP: case IT_HLE_WAIT_FOR_FLIP:
{ {
LatteCP_signalEnterWait();
LatteCP_itHLEWaitForFlip(cmdData, nWords); LatteCP_itHLEWaitForFlip(cmdData, nWords);
break; break;
} }
@ -1607,14 +1594,12 @@ void LatteCP_ProcessRingbuffer()
} }
case IT_HLE_TRIGGER_SCANBUFFER_SWAP: case IT_HLE_TRIGGER_SCANBUFFER_SWAP:
{ {
LatteCP_signalEnterWait();
LatteCP_itHLESwapScanBuffer(cmd, nWords); LatteCP_itHLESwapScanBuffer(cmd, nWords);
timerRecheck += CP_TIMER_RECHECK / 64; timerRecheck += CP_TIMER_RECHECK / 64;
break; break;
} }
case IT_HLE_WAIT_FOR_FLIP: case IT_HLE_WAIT_FOR_FLIP:
{ {
LatteCP_signalEnterWait();
LatteCP_itHLEWaitForFlip(cmd, nWords); LatteCP_itHLEWaitForFlip(cmd, nWords);
timerRecheck += CP_TIMER_RECHECK / 1; timerRecheck += CP_TIMER_RECHECK / 1;
break; break;

View file

@ -1,7 +1,6 @@
#include "Cafe/HW/Latte/Core/LatteConst.h" #include "Cafe/HW/Latte/Core/LatteConst.h"
#include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Cafe/HW/Latte/ISA/RegDefines.h" #include "Cafe/HW/Latte/ISA/RegDefines.h"
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "Common/cpu_features.h" #include "Common/cpu_features.h"
#if defined(ARCH_X86_64) && defined(__GNUC__) #if defined(ARCH_X86_64) && defined(__GNUC__)
@ -10,53 +9,32 @@
struct struct
{ {
struct CacheEntry const void* lastPtr;
{ uint32 lastCount;
// input data LattePrimitiveMode lastPrimitiveMode;
const void* lastPtr; LatteIndexType lastIndexType;
uint32 lastCount; // output
LattePrimitiveMode lastPrimitiveMode; uint32 indexMin;
LatteIndexType lastIndexType; uint32 indexMax;
uint64 lastUsed; Renderer::INDEX_TYPE renderIndexType;
// output uint32 outputCount;
uint32 indexMin; uint32 indexBufferOffset;
uint32 indexMax; uint32 indexBufferIndex;
Renderer::INDEX_TYPE renderIndexType;
uint32 outputCount;
Renderer::IndexAllocation indexAllocation;
};
std::array<CacheEntry, 8> entry;
uint64 currentUsageCounter{0};
}LatteIndexCache{}; }LatteIndexCache{};
void LatteIndices_invalidate(const void* memPtr, uint32 size) void LatteIndices_invalidate(const void* memPtr, uint32 size)
{ {
for(auto& entry : LatteIndexCache.entry) if (LatteIndexCache.lastPtr >= memPtr && (LatteIndexCache.lastPtr < ((uint8*)memPtr + size)) )
{ {
if (entry.lastPtr >= memPtr && (entry.lastPtr < ((uint8*)memPtr + size)) ) LatteIndexCache.lastPtr = nullptr;
{ LatteIndexCache.lastCount = 0;
if(entry.lastPtr != nullptr)
g_renderer->indexData_releaseIndexMemory(entry.indexAllocation);
entry.lastPtr = nullptr;
entry.lastCount = 0;
}
} }
} }
void LatteIndices_invalidateAll() void LatteIndices_invalidateAll()
{ {
for(auto& entry : LatteIndexCache.entry) LatteIndexCache.lastPtr = nullptr;
{ LatteIndexCache.lastCount = 0;
if (entry.lastPtr != nullptr)
g_renderer->indexData_releaseIndexMemory(entry.indexAllocation);
entry.lastPtr = nullptr;
entry.lastCount = 0;
}
}
uint64 LatteIndices_GetNextUsageIndex()
{
return LatteIndexCache.currentUsageCounter++;
} }
uint32 LatteIndices_calculateIndexOutputSize(LattePrimitiveMode primitiveMode, LatteIndexType indexType, uint32 count) uint32 LatteIndices_calculateIndexOutputSize(LattePrimitiveMode primitiveMode, LatteIndexType indexType, uint32 count)
@ -554,7 +532,7 @@ void LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, LatteIn
} }
} }
void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMin, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, Renderer::IndexAllocation& indexAllocation) void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMin, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, uint32& indexBufferOffset, uint32& indexBufferIndex)
{ {
// what this should do: // what this should do:
// [x] use fast SIMD-based index decoding // [x] use fast SIMD-based index decoding
@ -564,18 +542,17 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
// [ ] better cache implementation, allow to cache across frames // [ ] better cache implementation, allow to cache across frames
// reuse from cache if data didn't change // reuse from cache if data didn't change
auto cacheEntry = std::find_if(LatteIndexCache.entry.begin(), LatteIndexCache.entry.end(), [indexData, count, primitiveMode, indexType](const auto& entry) if (LatteIndexCache.lastPtr == indexData &&
LatteIndexCache.lastCount == count &&
LatteIndexCache.lastPrimitiveMode == primitiveMode &&
LatteIndexCache.lastIndexType == indexType)
{ {
return entry.lastPtr == indexData && entry.lastCount == count && entry.lastPrimitiveMode == primitiveMode && entry.lastIndexType == indexType; indexMin = LatteIndexCache.indexMin;
}); indexMax = LatteIndexCache.indexMax;
if (cacheEntry != LatteIndexCache.entry.end()) renderIndexType = LatteIndexCache.renderIndexType;
{ outputCount = LatteIndexCache.outputCount;
indexMin = cacheEntry->indexMin; indexBufferOffset = LatteIndexCache.indexBufferOffset;
indexMax = cacheEntry->indexMax; indexBufferIndex = LatteIndexCache.indexBufferIndex;
renderIndexType = cacheEntry->renderIndexType;
outputCount = cacheEntry->outputCount;
indexAllocation = cacheEntry->indexAllocation;
cacheEntry->lastUsed = LatteIndices_GetNextUsageIndex();
return; return;
} }
@ -599,12 +576,10 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
indexMin = 0; indexMin = 0;
indexMax = std::max(count, 1u)-1; indexMax = std::max(count, 1u)-1;
renderIndexType = Renderer::INDEX_TYPE::NONE; renderIndexType = Renderer::INDEX_TYPE::NONE;
indexAllocation = {};
return; // no indices return; // no indices
} }
// query index buffer from renderer // query index buffer from renderer
indexAllocation = g_renderer->indexData_reserveIndexMemory(indexOutputSize); void* indexOutputPtr = g_renderer->indexData_reserveIndexMemory(indexOutputSize, indexBufferOffset, indexBufferIndex);
void* indexOutputPtr = indexAllocation.mem;
// decode indices // decode indices
indexMin = std::numeric_limits<uint32>::max(); indexMin = std::numeric_limits<uint32>::max();
@ -729,25 +704,16 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
// recalculate index range but filter out primitive restart index // recalculate index range but filter out primitive restart index
LatteIndices_alternativeCalculateIndexMinMax(indexData, indexType, count, indexMin, indexMax); LatteIndices_alternativeCalculateIndexMinMax(indexData, indexType, count, indexMin, indexMax);
} }
g_renderer->indexData_uploadIndexMemory(indexAllocation); g_renderer->indexData_uploadIndexMemory(indexBufferOffset, indexOutputSize);
performanceMonitor.cycle[performanceMonitor.cycleIndex].indexDataUploaded += indexOutputSize;
// get least recently used cache entry
auto lruEntry = std::min_element(LatteIndexCache.entry.begin(), LatteIndexCache.entry.end(), [](const auto& a, const auto& b)
{
return a.lastUsed < b.lastUsed;
});
// invalidate previous allocation
if(lruEntry->lastPtr != nullptr)
g_renderer->indexData_releaseIndexMemory(lruEntry->indexAllocation);
// update cache // update cache
lruEntry->lastPtr = indexData; LatteIndexCache.lastPtr = indexData;
lruEntry->lastCount = count; LatteIndexCache.lastCount = count;
lruEntry->lastPrimitiveMode = primitiveMode; LatteIndexCache.lastPrimitiveMode = primitiveMode;
lruEntry->lastIndexType = indexType; LatteIndexCache.lastIndexType = indexType;
lruEntry->indexMin = indexMin; LatteIndexCache.indexMin = indexMin;
lruEntry->indexMax = indexMax; LatteIndexCache.indexMax = indexMax;
lruEntry->renderIndexType = renderIndexType; LatteIndexCache.renderIndexType = renderIndexType;
lruEntry->outputCount = outputCount; LatteIndexCache.outputCount = outputCount;
lruEntry->indexAllocation = indexAllocation; LatteIndexCache.indexBufferOffset = indexBufferOffset;
lruEntry->lastUsed = LatteIndices_GetNextUsageIndex(); LatteIndexCache.indexBufferIndex = indexBufferIndex;
} }

View file

@ -4,4 +4,4 @@
void LatteIndices_invalidate(const void* memPtr, uint32 size); void LatteIndices_invalidate(const void* memPtr, uint32 size);
void LatteIndices_invalidateAll(); void LatteIndices_invalidateAll();
void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMin, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, Renderer::IndexAllocation& indexAllocation); void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMin, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, uint32& indexBufferOffset, uint32& indexBufferIndex);

View file

@ -107,13 +107,7 @@ void LatteOverlay_renderOverlay(ImVec2& position, ImVec2& pivot, sint32 directio
ImGui::Text("VRAM: %dMB / %dMB", g_state.vramUsage, g_state.vramTotal); ImGui::Text("VRAM: %dMB / %dMB", g_state.vramUsage, g_state.vramTotal);
if (config.overlay.debug) if (config.overlay.debug)
{
// general debug info
ImGui::Text("--- Debug info ---");
ImGui::Text("IndexUploadPerFrame: %dKB", (performanceMonitor.stats.indexDataUploadPerFrame+1023)/1024);
// backend specific info
g_renderer->AppendOverlayDebugInfo(); g_renderer->AppendOverlayDebugInfo();
}
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction; position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
} }

View file

@ -74,6 +74,7 @@ void LattePerformanceMonitor_frameEnd()
uniformBankDataUploadedPerFrame /= 1024ULL; uniformBankDataUploadedPerFrame /= 1024ULL;
uint32 uniformBankCountUploadedPerFrame = (uint32)(uniformBankUploadedCount / (uint64)elapsedFrames); uint32 uniformBankCountUploadedPerFrame = (uint32)(uniformBankUploadedCount / (uint64)elapsedFrames);
uint64 indexDataUploadPerFrame = (indexDataUploaded / (uint64)elapsedFrames); uint64 indexDataUploadPerFrame = (indexDataUploaded / (uint64)elapsedFrames);
indexDataUploadPerFrame /= 1024ULL;
double fps = (double)elapsedFrames2S * 1000.0 / (double)totalElapsedTimeFPS; double fps = (double)elapsedFrames2S * 1000.0 / (double)totalElapsedTimeFPS;
uint32 shaderBindsPerFrame = shaderBindCounter / elapsedFrames; uint32 shaderBindsPerFrame = shaderBindCounter / elapsedFrames;
@ -81,7 +82,7 @@ void LattePerformanceMonitor_frameEnd()
uint32 rlps = (uint32)((uint64)recompilerLeaveCount * 1000ULL / (uint64)totalElapsedTime); uint32 rlps = (uint32)((uint64)recompilerLeaveCount * 1000ULL / (uint64)totalElapsedTime);
uint32 tlps = (uint32)((uint64)threadLeaveCount * 1000ULL / (uint64)totalElapsedTime); uint32 tlps = (uint32)((uint64)threadLeaveCount * 1000ULL / (uint64)totalElapsedTime);
// set stats // set stats
performanceMonitor.stats.indexDataUploadPerFrame = indexDataUploadPerFrame;
// next counter cycle // next counter cycle
sint32 nextCycleIndex = (performanceMonitor.cycleIndex + 1) % PERFORMANCE_MONITOR_TRACK_CYCLES; sint32 nextCycleIndex = (performanceMonitor.cycleIndex + 1) % PERFORMANCE_MONITOR_TRACK_CYCLES;
performanceMonitor.cycle[nextCycleIndex].drawCallCounter = 0; performanceMonitor.cycle[nextCycleIndex].drawCallCounter = 0;

View file

@ -124,7 +124,6 @@ typedef struct
LattePerfStatCounter numGraphicPipelines; LattePerfStatCounter numGraphicPipelines;
LattePerfStatCounter numImages; LattePerfStatCounter numImages;
LattePerfStatCounter numImageViews; LattePerfStatCounter numImageViews;
LattePerfStatCounter numSamplers;
LattePerfStatCounter numRenderPass; LattePerfStatCounter numRenderPass;
LattePerfStatCounter numFramebuffer; LattePerfStatCounter numFramebuffer;
@ -132,12 +131,6 @@ typedef struct
LattePerfStatCounter numDrawBarriersPerFrame; LattePerfStatCounter numDrawBarriersPerFrame;
LattePerfStatCounter numBeginRenderpassPerFrame; LattePerfStatCounter numBeginRenderpassPerFrame;
}vk; }vk;
// calculated stats (per frame)
struct
{
uint32 indexDataUploadPerFrame;
}stats;
}performanceMonitor_t; }performanceMonitor_t;
extern performanceMonitor_t performanceMonitor; extern performanceMonitor_t performanceMonitor;

View file

@ -11,6 +11,7 @@
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h" #include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "Cafe/GraphicPack/GraphicPack2.h" #include "Cafe/GraphicPack/GraphicPack2.h"
#include "config/ActiveSettings.h" #include "config/ActiveSettings.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
#include "gui/guiWrapper.h" #include "gui/guiWrapper.h"
#include "Cafe/OS/libs/erreula/erreula.h" #include "Cafe/OS/libs/erreula/erreula.h"
#include "input/InputManager.h" #include "input/InputManager.h"
@ -933,6 +934,13 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
{ {
sint32 scaling_filter = downscaling ? GetConfig().downscale_filter : GetConfig().upscale_filter; sint32 scaling_filter = downscaling ? GetConfig().downscale_filter : GetConfig().upscale_filter;
if (g_renderer->GetType() == RendererAPI::Vulkan)
{
// force linear or nearest neighbor filter
if(scaling_filter != kLinearFilter && scaling_filter != kNearestNeighborFilter)
scaling_filter = kLinearFilter;
}
if (scaling_filter == kLinearFilter) if (scaling_filter == kLinearFilter)
{ {
if(renderUpsideDown) if(renderUpsideDown)
@ -949,7 +957,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
else else
shader = RendererOutputShader::s_bicubic_shader; shader = RendererOutputShader::s_bicubic_shader;
filter = LatteTextureView::MagFilter::kLinear; filter = LatteTextureView::MagFilter::kNearestNeighbor;
} }
else if (scaling_filter == kBicubicHermiteFilter) else if (scaling_filter == kBicubicHermiteFilter)
{ {
@ -981,6 +989,8 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
g_renderer->ImguiEnd(); g_renderer->ImguiEnd();
} }
bool ctrlTabHotkeyPressed = false;
void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferSliceIndex, uint32 colorBufferFormat, uint32 colorBufferPitch, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferSwizzle, uint32 renderTarget) void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferSliceIndex, uint32 colorBufferFormat, uint32 colorBufferPitch, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferSwizzle, uint32 renderTarget)
{ {
cemu_assert_debug(colorBufferSliceIndex == 0); // todo - support for non-zero slice cemu_assert_debug(colorBufferSliceIndex == 0); // todo - support for non-zero slice
@ -990,31 +1000,38 @@ void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uin
return; return;
} }
auto getVPADScreenActive = [](size_t n) -> std::pair<bool, bool> {
auto controller = InputManager::instance().get_vpad_controller(n);
if (!controller)
return {false,false};
auto pressed = controller->is_screen_active();
auto toggle = controller->is_screen_active_toggle();
return {pressed && !toggle, pressed && toggle};
};
const bool tabPressed = gui_isKeyDown(PlatformKeyCodes::TAB); const bool tabPressed = gui_isKeyDown(PlatformKeyCodes::TAB);
const bool ctrlPressed = gui_isKeyDown(PlatformKeyCodes::LCONTROL); const bool ctrlPressed = gui_isKeyDown(PlatformKeyCodes::LCONTROL);
const auto [vpad0Active, vpad0Toggle] = getVPADScreenActive(0);
const auto [vpad1Active, vpad1Toggle] = getVPADScreenActive(1);
const bool altScreenRequested = (!ctrlPressed && tabPressed) || vpad0Active || vpad1Active; bool showDRC = swkbd_hasKeyboardInputHook() == false && tabPressed;
const bool togglePressed = (ctrlPressed && tabPressed) || vpad0Toggle || vpad1Toggle; bool& alwaysDisplayDRC = LatteGPUState.alwaysDisplayDRC;
static bool togglePressedLast = false;
bool& isDRCPrimary = LatteGPUState.isDRCPrimary; if (ctrlPressed && tabPressed)
{
if (ctrlTabHotkeyPressed == false)
{
alwaysDisplayDRC = !alwaysDisplayDRC;
ctrlTabHotkeyPressed = true;
}
}
else
ctrlTabHotkeyPressed = false;
if(togglePressed && !togglePressedLast) if (alwaysDisplayDRC)
isDRCPrimary = !isDRCPrimary; showDRC = !tabPressed;
togglePressedLast = togglePressed;
bool showDRC = swkbd_hasKeyboardInputHook() == false && (isDRCPrimary ^ altScreenRequested); if (!showDRC)
{
auto controller = InputManager::instance().get_vpad_controller(0);
if (controller && controller->is_screen_active())
showDRC = true;
if (!showDRC)
{
controller = InputManager::instance().get_vpad_controller(1);
if (controller && controller->is_screen_active())
showDRC = true;
}
}
if ((renderTarget & RENDER_TARGET_DRC) && g_renderer->IsPadWindowActive()) if ((renderTarget & RENDER_TARGET_DRC) && g_renderer->IsPadWindowActive())
LatteRenderTarget_copyToBackbuffer(texView, true); LatteRenderTarget_copyToBackbuffer(texView, true);

View file

@ -451,8 +451,9 @@ void LatteShader_DumpShader(uint64 baseHash, uint64 auxHash, LatteDecompilerShad
suffix = "gs"; suffix = "gs";
else if (shader->shaderType == LatteConst::ShaderType::Pixel) else if (shader->shaderType == LatteConst::ShaderType::Pixel)
suffix = "ps"; suffix = "ps";
fs::path dumpPath = "dump/shaders";
FileStream* fs = FileStream::createFile2(ActiveSettings::GetUserDataPath("dump/shaders/{:016x}_{:016x}_{}.txt", baseHash, auxHash, suffix)); dumpPath /= fmt::format("{:016x}_{:016x}_{}.txt", baseHash, auxHash, suffix);
FileStream* fs = FileStream::createFile2(dumpPath);
if (fs) if (fs)
{ {
if (shader->strBuf_shaderSource) if (shader->strBuf_shaderSource)
@ -478,8 +479,9 @@ void LatteShader_DumpRawShader(uint64 baseHash, uint64 auxHash, uint32 type, uin
suffix = "copy"; suffix = "copy";
else if (type == SHADER_DUMP_TYPE_COMPUTE) else if (type == SHADER_DUMP_TYPE_COMPUTE)
suffix = "compute"; suffix = "compute";
fs::path dumpPath = "dump/shaders";
FileStream* fs = FileStream::createFile2(ActiveSettings::GetUserDataPath("dump/shaders/{:016x}_{:016x}_{}.bin", baseHash, auxHash, suffix)); dumpPath /= fmt::format("{:016x}_{:016x}_{}.bin", baseHash, auxHash, suffix);
FileStream* fs = FileStream::createFile2(dumpPath);
if (fs) if (fs)
{ {
fs->writeData(programCode, programLen); fs->writeData(programCode, programLen);
@ -522,7 +524,7 @@ void LatteSHRC_UpdateGSBaseHash(uint8* geometryShaderPtr, uint32 geometryShaderS
// update hash from geometry shader data // update hash from geometry shader data
uint64 gsHash1 = 0; uint64 gsHash1 = 0;
uint64 gsHash2 = 0; uint64 gsHash2 = 0;
_calculateShaderProgramHash((uint32*)geometryShaderPtr, geometryShaderSize, &hashCacheGS, &gsHash1, &gsHash2); _calculateShaderProgramHash((uint32*)geometryShaderPtr, geometryShaderSize, &hashCacheVS, &gsHash1, &gsHash2);
// get geometry shader // get geometry shader
uint64 gsHash = gsHash1 + gsHash2; uint64 gsHash = gsHash1 + gsHash2;
gsHash += (uint64)_activeVertexShader->ringParameterCount; gsHash += (uint64)_activeVertexShader->ringParameterCount;

View file

@ -25,9 +25,6 @@
#include "util/helpers/Serializer.h" #include "util/helpers/Serializer.h"
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#include <audio/IAudioAPI.h>
#include <util/bootSound/BootSoundReader.h>
#include <thread>
#if BOOST_OS_WINDOWS #if BOOST_OS_WINDOWS
#include <psapi.h> #include <psapi.h>
@ -158,118 +155,6 @@ bool LoadTGAFile(const std::vector<uint8>& buffer, TGAFILE *tgaFile)
return true; return true;
} }
class BootSoundPlayer
{
public:
BootSoundPlayer() = default;
~BootSoundPlayer()
{
m_stopRequested = true;
}
void StartSound()
{
if (!m_bootSndPlayThread.joinable())
{
m_fadeOutRequested = false;
m_stopRequested = false;
m_bootSndPlayThread = std::thread{[this]() {
StreamBootSound();
}};
}
}
void FadeOutSound()
{
m_fadeOutRequested = true;
}
void ApplyFadeOutEffect(std::span<sint16> samples, uint64& fadeOutSample, uint64 fadeOutDuration)
{
for (size_t i = 0; i < samples.size(); i += 2)
{
const float decibel = (float)fadeOutSample / fadeOutDuration * -60.0f;
const float volumeFactor = pow(10, decibel / 20);
samples[i] *= volumeFactor;
samples[i + 1] *= volumeFactor;
fadeOutSample++;
}
}
void StreamBootSound()
{
SetThreadName("bootsnd");
constexpr sint32 sampleRate = 48'000;
constexpr sint32 bitsPerSample = 16;
constexpr sint32 samplesPerBlock = sampleRate / 10; // block is 1/10th of a second
constexpr sint32 nChannels = 2;
static_assert(bitsPerSample % 8 == 0, "bits per sample is not a multiple of 8");
AudioAPIPtr bootSndAudioDev;
try
{
bootSndAudioDev = IAudioAPI::CreateDeviceFromConfig(true, sampleRate, nChannels, samplesPerBlock, bitsPerSample);
if(!bootSndAudioDev)
return;
}
catch (const std::runtime_error& ex)
{
cemuLog_log(LogType::Force, "Failed to initialise audio device for bootup sound");
return;
}
bootSndAudioDev->SetAudioDelayOverride(4);
bootSndAudioDev->Play();
std::string sndPath = fmt::format("{}/meta/{}", CafeSystem::GetMlcStoragePath(CafeSystem::GetForegroundTitleId()), "bootSound.btsnd");
sint32 fscStatus = FSC_STATUS_UNDEFINED;
if(!fsc_doesFileExist(sndPath.c_str()))
return;
FSCVirtualFile* bootSndFileHandle = fsc_open(sndPath.c_str(), FSC_ACCESS_FLAG::OPEN_FILE | FSC_ACCESS_FLAG::READ_PERMISSION, &fscStatus);
if(!bootSndFileHandle)
{
cemuLog_log(LogType::Force, "failed to open bootSound.btsnd");
return;
}
constexpr sint32 audioBlockSize = samplesPerBlock * (bitsPerSample/8) * nChannels;
BootSoundReader bootSndFileReader(bootSndFileHandle, audioBlockSize);
uint64 fadeOutSample = 0; // track how far into the fadeout
constexpr uint64 fadeOutDuration = sampleRate * 2; // fadeout should last 2 seconds
while(fadeOutSample < fadeOutDuration && !m_stopRequested)
{
while (bootSndAudioDev->NeedAdditionalBlocks())
{
sint16* data = bootSndFileReader.getSamples();
if(data == nullptr)
{
// break outer loop
m_stopRequested = true;
break;
}
if(m_fadeOutRequested)
ApplyFadeOutEffect({data, samplesPerBlock * nChannels}, fadeOutSample, fadeOutDuration);
bootSndAudioDev->FeedBlock(data);
}
// sleep for the duration of a single block
std::this_thread::sleep_for(std::chrono::milliseconds(samplesPerBlock / (sampleRate/ 1'000)));
}
if(bootSndFileHandle)
fsc_close(bootSndFileHandle);
}
private:
std::thread m_bootSndPlayThread;
std::atomic_bool m_fadeOutRequested = false;
std::atomic_bool m_stopRequested = false;
};
static BootSoundPlayer g_bootSndPlayer;
void LatteShaderCache_finish() void LatteShaderCache_finish()
{ {
if (g_renderer->GetType() == RendererAPI::Vulkan) if (g_renderer->GetType() == RendererAPI::Vulkan)
@ -414,9 +299,6 @@ void LatteShaderCache_Load()
loadBackgroundTexture(true, g_shaderCacheLoaderState.textureTVId); loadBackgroundTexture(true, g_shaderCacheLoaderState.textureTVId);
loadBackgroundTexture(false, g_shaderCacheLoaderState.textureDRCId); loadBackgroundTexture(false, g_shaderCacheLoaderState.textureDRCId);
if(GetConfig().play_boot_sound)
g_bootSndPlayer.StartSound();
sint32 numLoadedShaders = 0; sint32 numLoadedShaders = 0;
uint32 loadIndex = 0; uint32 loadIndex = 0;
@ -483,11 +365,6 @@ void LatteShaderCache_Load()
g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureTVId); g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureTVId);
if (g_shaderCacheLoaderState.textureDRCId) if (g_shaderCacheLoaderState.textureDRCId)
g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureDRCId); g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureDRCId);
g_bootSndPlayer.FadeOutSound();
if(Latte_GetStopSignal())
LatteThread_Exit();
} }
void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateFunc, bool isPipelines) void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateFunc, bool isPipelines)
@ -628,6 +505,8 @@ void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId)
g_shaderCacheLoaderState.loadedPipelines = 0; g_shaderCacheLoaderState.loadedPipelines = 0;
LatteShaderCache_ShowProgress(LatteShaderCache_updatePipelineLoadingProgress, true); LatteShaderCache_ShowProgress(LatteShaderCache_updatePipelineLoadingProgress, true);
pipelineCache.EndLoading(); pipelineCache.EndLoading();
if(Latte_GetStopSignal())
LatteThread_Exit();
} }
bool LatteShaderCache_updatePipelineLoadingProgress() bool LatteShaderCache_updatePipelineLoadingProgress()

View file

@ -235,9 +235,6 @@ void LatteTexture_InitSliceAndMipInfo(LatteTexture* texture)
// if this function returns false, textures will not be synchronized even if their data overlaps // if this function returns false, textures will not be synchronized even if their data overlaps
bool LatteTexture_IsFormatViewCompatible(Latte::E_GX2SURFFMT formatA, Latte::E_GX2SURFFMT formatB) bool LatteTexture_IsFormatViewCompatible(Latte::E_GX2SURFFMT formatA, Latte::E_GX2SURFFMT formatB)
{ {
if(formatA == formatB)
return true; // if the format is identical then compatibility must be guaranteed (otherwise we can't create the necessary default view of a texture)
// todo - find a better way to handle this // todo - find a better way to handle this
for (sint32 swap = 0; swap < 2; swap++) for (sint32 swap = 0; swap < 2; swap++)
{ {

View file

@ -187,7 +187,7 @@ int Latte_ThreadEntry()
rule.overwrite_settings.width >= 0 || rule.overwrite_settings.height >= 0 || rule.overwrite_settings.depth >= 0) rule.overwrite_settings.width >= 0 || rule.overwrite_settings.height >= 0 || rule.overwrite_settings.depth >= 0)
{ {
LatteGPUState.allowFramebufferSizeOptimization = false; LatteGPUState.allowFramebufferSizeOptimization = false;
cemuLog_log(LogType::Force, "Graphic pack \"{}\" prevents rendertarget size optimization. This warning can be ignored and is intended for graphic pack developers", pack->GetName()); cemuLog_log(LogType::Force, "Graphic pack {} prevents rendertarget size optimization.", pack->GetName());
break; break;
} }
} }
@ -257,7 +257,6 @@ void LatteThread_Exit()
LatteSHRC_UnloadAll(); LatteSHRC_UnloadAll();
// close disk cache // close disk cache
LatteShaderCache_Close(); LatteShaderCache_Close();
RendererOutputShader::ShutdownStatic();
// destroy renderer but make sure that g_renderer remains valid until the destructor has finished // destroy renderer but make sure that g_renderer remains valid until the destructor has finished
if (g_renderer) if (g_renderer)
{ {

View file

@ -370,8 +370,6 @@ bool LatteDecompiler_IsALUTransInstruction(bool isOP3, uint32 opcode)
opcode == ALU_OP2_INST_LSHR_INT || opcode == ALU_OP2_INST_LSHR_INT ||
opcode == ALU_OP2_INST_MAX_INT || opcode == ALU_OP2_INST_MAX_INT ||
opcode == ALU_OP2_INST_MIN_INT || opcode == ALU_OP2_INST_MIN_INT ||
opcode == ALU_OP2_INST_MAX_UINT ||
opcode == ALU_OP2_INST_MIN_UINT ||
opcode == ALU_OP2_INST_MOVA_FLOOR || opcode == ALU_OP2_INST_MOVA_FLOOR ||
opcode == ALU_OP2_INST_MOVA_INT || opcode == ALU_OP2_INST_MOVA_INT ||
opcode == ALU_OP2_INST_SETE_DX10 || opcode == ALU_OP2_INST_SETE_DX10 ||

View file

@ -140,8 +140,6 @@ bool _isIntegerInstruction(const LatteDecompilerALUInstruction& aluInstruction)
case ALU_OP2_INST_SUB_INT: case ALU_OP2_INST_SUB_INT:
case ALU_OP2_INST_MAX_INT: case ALU_OP2_INST_MAX_INT:
case ALU_OP2_INST_MIN_INT: case ALU_OP2_INST_MIN_INT:
case ALU_OP2_INST_MAX_UINT:
case ALU_OP2_INST_MIN_UINT:
case ALU_OP2_INST_SETE_INT: case ALU_OP2_INST_SETE_INT:
case ALU_OP2_INST_SETGT_INT: case ALU_OP2_INST_SETGT_INT:
case ALU_OP2_INST_SETGE_INT: case ALU_OP2_INST_SETGE_INT:

Some files were not shown because too many files have changed in this diff Show more