Merge branch 'refs/heads/main' into loadaudio

# Conflicts:
#	src/gui/GeneralSettings2.cpp
This commit is contained in:
goeiecool9999 2024-09-15 20:26:46 +02:00
commit ac5c44d2cf
185 changed files with 9285 additions and 4542 deletions

View File

@ -15,6 +15,7 @@ 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

View File

@ -1,9 +0,0 @@
#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:
deploymode: next_version_major:
required: false required: false
type: string type: string
experimentalversion: next_version_minor:
required: false required: false
type: string type: string
@ -24,30 +24,17 @@ jobs:
submodules: "recursive" submodules: "recursive"
fetch-depth: 0 fetch-depth: 0
- name: "Fetch full history for vcpkg submodule" - name: Setup release mode parameters
run: |
cd dependencies/vcpkg
git fetch --unshallow
- 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 "BUILD_MODE=debug" >> $GITHUB_ENV echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=" >> $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 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: |
@ -86,12 +73,10 @@ 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@v4
if: ${{ inputs.deploymode == 'release' }}
with: with:
name: cemu-bin-linux-x64 name: cemu-bin-linux-x64
path: ./bin/Cemu path: ./bin/Cemu
@ -133,29 +118,17 @@ jobs:
with: with:
submodules: "recursive" submodules: "recursive"
- name: "Fetch full history for vcpkg submodule" - name: Setup release mode parameters
run: |
cd dependencies/vcpkg
git fetch --unshallow
- 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 debug mode parameters (for continous build) - name: Setup build flags for version
if: ${{ inputs.deploymode != 'release' }} if: ${{ inputs.next_version_major != '' }}
run: | run: |
echo "BUILD_MODE=debug" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=" | 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 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
@ -194,52 +167,45 @@ 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@v4
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-12 runs-on: macos-14
steps: steps:
- name: "Checkout repo" - name: "Checkout repo"
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
submodules: "recursive" submodules: "recursive"
- name: "Fetch full history for vcpkg submodule" - name: Setup release mode parameters
run: |
cd dependencies/vcpkg
git fetch --unshallow
- 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)
if: ${{ inputs.deploymode != 'release' }}
run: |
echo "BUILD_MODE=debug" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental - name: Setup build flags for version
if: ${{ inputs.experimentalversion != '' }} if: ${{ inputs.next_version_major != '' }}
run: | run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}" echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" >> $GITHUB_ENV
- name: "Install system dependencies" - name: "Install system dependencies"
run: | run: |
brew update brew update
brew install llvm@15 ninja nasm molten-vk automake libtool brew install ninja nasm 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
@ -270,9 +236,8 @@ 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"
@ -280,7 +245,6 @@ 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
@ -294,7 +258,6 @@ jobs:
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
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,6 +16,3 @@ on:
jobs: jobs:
build: build:
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
with:
deploymode: release
experimentalversion: 999999

View File

@ -1,20 +1,83 @@
name: Deploy experimental release name: Deploy experimental release
on: on:
workflow_dispatch: 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: jobs:
calculate-version:
name: Calculate Version
uses: ./.github/workflows/determine_release_version.yml
call-release-build: call-release-build:
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
needs: calculate-version
with: with:
deploymode: release next_version_major: ${{ needs.calculate-version.outputs.next_version_major }}
experimentalversion: ${{ github.run_number }} next_version_minor: ${{ needs.calculate-version.outputs.next_version_minor }}
deploy: deploy:
name: Deploy experimental release name: Deploy experimental release
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: call-release-build needs: [call-release-build, calculate-version]
steps: steps:
- uses: actions/checkout@v3 - 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 - uses: actions/download-artifact@v4
with: with:
name: cemu-bin-linux-x64 name: cemu-bin-linux-x64
@ -40,15 +103,13 @@ jobs:
mkdir upload mkdir upload
sudo apt install zip sudo apt install zip
- name: Get version - name: Set version dependent vars
run: | run: |
echo "Experimental version: ${{ github.run_number }}" echo "Version: ${{ needs.calculate-version.outputs.next_version }}"
ls echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}"
gcc -o getversion .github/getversion.cpp echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}"
./getversion echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
echo "Cemu CI version: $(./getversion)" echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
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 - name: Create release from windows-bin
run: | run: |
@ -83,4 +144,8 @@ jobs:
wget -O ghr.tar.gz https://github.com/tcnksm/ghr/releases/download/v0.15.0/ghr_v0.15.0_linux_amd64.tar.gz 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 tar xvzf ghr.tar.gz; rm ghr.tar.gz
echo "[INFO] Release tag: v${{ env.CEMU_VERSION }}" 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 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,74 @@
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"

4
.gitmodules vendored
View File

@ -9,10 +9,12 @@
[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 = true shallow = false
[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 Dependencies](#installing-dependencies) - [Installing Tool Dependencies](#installing-tool-dependencies)
- [Build Cemu using CMake and Clang](#build-cemu-using-cmake-and-clang) - [Installing Library Dependencies](#installing-library-dependencies)
- [Updating Cemu and source code](#updating-cemu-and-source-code) - [Build Cemu using CMake](#build-cemu-using-cmake)
- [Updating Cemu and source code](#updating-cemu-and-source-code)
## Windows ## Windows
@ -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 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` `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 zlib-static`
### Build Cemu ### Build Cemu
@ -141,31 +141,41 @@ 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 To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and below
below, built in LLVM, and Xcode LLVM don't support the C++20 feature set required. The OpenGL graphics don't support the C++20 feature set required, so either install LLVM from Homebrew or make sure that
API isn't support on macOS, Vulkan must be used. Additionally Vulkan must be used through the you have a recent enough version of Xcode. Xcode 15 is known to work. The OpenGL graphics API isn't
Molten-VK compatibility layer supported on macOS, so Vulkan must be used through the 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. `eval "$(/usr/local/Homebrew/bin/brew shellenv)"` # set x86_64 brew env 2. Set up the Homebrew shell environment:
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 Dependencies ### Installing Tool Dependencies
`brew install boost git cmake llvm ninja nasm molten-vk automake libtool` The native versions of these can be used regardless of what type of Mac you have.
`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_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -G Ninja` 3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_OSX_ARCHITECTURES=x86_64 -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`.

View File

@ -2,20 +2,39 @@ 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)
set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
if (EXPERIMENTAL_VERSION) # used by CI script to set version:
add_definitions(-DEMULATOR_VERSION_MINOR=${EXPERIMENTAL_VERSION}) set(EMULATOR_VERSION_MAJOR "0" CACHE STRING "")
execute_process( set(EMULATOR_VERSION_MINOR "0" CACHE STRING "")
COMMAND git log --format=%h -1 set(EMULATOR_VERSION_PATCH "0" CACHE STRING "")
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE GIT_HASH execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND git log --format=%h -1
) WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
add_definitions(-DEMULATOR_HASH=${GIT_HASH}) OUTPUT_VARIABLE GIT_HASH
endif() OUTPUT_STRIP_TRAILING_WHITESPACE
)
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)
@ -44,6 +63,10 @@ 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
@ -69,6 +92,7 @@ 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)

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.

View File

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

@ -117,7 +117,13 @@ add_library (ih264d
"decoder/ivd.h" "decoder/ivd.h"
) )
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") if (CMAKE_OSX_ARCHITECTURES)
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
@ -140,7 +146,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(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") elseif(IH264D_ARCHITECTURE STREQUAL "aarch64" OR IH264D_ARCHITECTURE STREQUAL "arm64")
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})
@ -178,7 +184,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: ${CMAKE_SYSTEM_PROCESSOR}") message(FATAL_ERROR "ih264d unknown architecture: ${IH264D_ARCHITECTURE}")
endif() endif()
if(MSVC) if(MSVC)

2
dependencies/vcpkg vendored

@ -1 +1 @@
Subproject commit cbf4a6641528cee6f172328984576f51698de726 Subproject commit a4275b7eee79fb24ec2e135481ef5fce8b41c339

View File

@ -1,13 +0,0 @@
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

@ -1,13 +0,0 @@
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

@ -1,137 +0,0 @@
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

@ -1,8 +0,0 @@
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

@ -1,68 +0,0 @@
{
"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

@ -1,13 +0,0 @@
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

@ -1,86 +0,0 @@
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

@ -1,9 +0,0 @@
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

@ -1,104 +0,0 @@
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

@ -1,67 +0,0 @@
{
"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

@ -1,15 +0,0 @@
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

@ -1,26 +0,0 @@
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

@ -1,15 +0,0 @@
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

@ -1,21 +0,0 @@
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

@ -1,88 +0,0 @@
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

@ -1,30 +0,0 @@
{
"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

@ -1,13 +0,0 @@
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

@ -1,13 +0,0 @@
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

@ -1,137 +0,0 @@
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

@ -1,8 +0,0 @@
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

@ -1,68 +0,0 @@
{
"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

@ -1,13 +0,0 @@
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

@ -1,86 +0,0 @@
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

@ -1,9 +0,0 @@
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

@ -1,104 +0,0 @@
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

@ -1,67 +0,0 @@
{
"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

@ -1,13 +0,0 @@
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

@ -1,13 +0,0 @@
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

@ -1,137 +0,0 @@
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

@ -1,8 +0,0 @@
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

@ -1,68 +0,0 @@
{
"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

@ -1,13 +0,0 @@
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

@ -1,86 +0,0 @@
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

@ -1,9 +0,0 @@
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

@ -1,104 +0,0 @@
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

@ -1,67 +0,0 @@
{
"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,6 +10,8 @@ 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
@ -39,7 +41,8 @@ export NO_STRIP=1
-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
@ -47,7 +50,6 @@ 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

@ -56,6 +56,12 @@ 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
@ -100,7 +106,7 @@ if (MACOS_BUNDLE)
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_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 ${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 /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}") COMMAND bash -c "install_name_tool -change /Users/runner/work/Cemu/Cemu/build/vcpkg_installed/x64-osx/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

@ -218,6 +218,8 @@ 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
@ -372,12 +374,24 @@ 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
@ -445,14 +459,22 @@ 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/BackendWindowsHID.cpp OS/libs/nsyshid/BackendWindowsHID.cpp
OS/libs/nsyshid/BackendWindowsHID.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

View File

@ -35,6 +35,7 @@
#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"
@ -51,6 +52,8 @@
#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"
@ -533,6 +536,7 @@ 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
@ -587,6 +591,8 @@ 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();
} }

View File

@ -3,6 +3,8 @@
#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
@ -119,9 +121,7 @@ public:
template<typename F> template<typename F>
class FSAFileTree class FSAFileTree
{ {
public: private:
private:
enum NODETYPE : uint8 enum NODETYPE : uint8
{ {
@ -133,6 +133,7 @@ private:
{ {
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;
}; };
@ -179,13 +180,54 @@ private:
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, F* custom) bool addFile(std::string_view path, size_t fileSize, F* custom)
{ {
FSCPath p(path); FSCPath p(path);
if (p.GetNodeCount() == 0) if (p.GetNodeCount() == 0)
@ -196,6 +238,7 @@ 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;
} }
@ -214,6 +257,20 @@ 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

@ -212,4 +212,4 @@ bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTarg
// redirect device // redirect device
void fscDeviceRedirect_map(); void fscDeviceRedirect_map();
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority); void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize, 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, const fs::path& targetFilePath, sint32 priority) void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize, 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, const fs::path& t
delete existingEntry; delete existingEntry;
} }
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority); RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
redirectTree.addFile(virtualSourcePath, entry); redirectTree.addFile(virtualSourcePath, fileSize, entry);
} }
class fscDeviceTypeRedirect : public fscDeviceC class fscDeviceTypeRedirect : public fscDeviceC
@ -32,8 +32,15 @@ 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

@ -830,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.path().generic_string(), m_fs_priority); fscDeviceRedirect_add(virtualMountPath.generic_string(), it.file_size(), it.path().generic_string(), m_fs_priority);
} }
} }
} }

View File

@ -501,8 +501,6 @@ 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

View File

@ -212,11 +212,12 @@ 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)
{ {
// untested (Don't Starve Giant Edition uses this) // Seen in Don't Starve Giant Edition and Teslagrad
// 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();
hCPU->gpr[rD] = ~hCPU->gpr[rA] + hCPU->gpr[rB] + 1; uint32 result = ~hCPU->gpr[rA] + hCPU->gpr[rB] + 1;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~hCPU->gpr[rA], hCPU->gpr[rB], hCPU->gpr[rD])); PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~hCPU->gpr[rA], hCPU->gpr[rB], result));
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* PPCInterpreterGetAndModifyStackPointer(sint32 offset) uint8* PPCInterpreter_PushAndReturnStackPointer(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,8 +5,28 @@ 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)
{ {
@ -16,23 +36,21 @@ 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)
{ {
cemu_assert_debug(data.gprCount <= 8); // TODO float arguments on stack
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>)
{ {
hCPU->gpr[3 + data.gprCount] = MEMPTR(currentArg).GetMPTR(); _PPCCoreCallback_writeGPRArg(data, hCPU, 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>>)
{ {
hCPU->gpr[3 + data.gprCount] = currentArg.GetMPTR(); _PPCCoreCallback_writeGPRArg(data, hCPU, currentArg.GetMPTR());
data.gprCount++;
} }
else if constexpr (std::is_reference_v<T>) else if constexpr (std::is_reference_v<T>)
{ {
hCPU->gpr[3 + data.gprCount] = MEMPTR(&currentArg).GetMPTR(); _PPCCoreCallback_writeGPRArg(data, hCPU, MEMPTR(&currentArg).GetMPTR());
data.gprCount++;
} }
else if constexpr(std::is_enum_v<T>) else if constexpr(std::is_enum_v<T>)
{ {
@ -53,8 +71,7 @@ uint32 PPCCoreCallback(MPTR function, PPCCoreCallbackData_t& data, T currentArg,
} }
else else
{ {
hCPU->gpr[3 + data.gprCount] = (uint32)currentArg; _PPCCoreCallback_writeGPRArg(data, hCPU, (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* PPCInterpreterGetAndModifyStackPointer(sint32 offset); uint8* PPCInterpreter_PushAndReturnStackPointer(sint32 offset);
uint8* PPCInterpreterGetStackPointer(); uint8* PPCInterpreterGetStackPointer();
void PPCInterpreterModifyStackPointer(sint32 offset); void PPCInterpreterModifyStackPointer(sint32 offset);

View File

@ -524,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, &hashCacheVS, &gsHash1, &gsHash2); _calculateShaderProgramHash((uint32*)geometryShaderPtr, geometryShaderSize, &hashCacheGS, &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

@ -235,6 +235,9 @@ 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

@ -241,6 +241,16 @@ void LatteDecompiler_emitAttributeDecodeGLSL(LatteDecompilerShader* shaderContex
src->add("attrDecoder.z = floatBitsToUint(max(float(int(attrDecoder.z))/32767.0,-1.0));" _CRLF); src->add("attrDecoder.z = floatBitsToUint(max(float(int(attrDecoder.z))/32767.0,-1.0));" _CRLF);
src->add("attrDecoder.w = floatBitsToUint(max(float(int(attrDecoder.w))/32767.0,-1.0));" _CRLF); src->add("attrDecoder.w = floatBitsToUint(max(float(int(attrDecoder.w))/32767.0,-1.0));" _CRLF);
} }
else if( attrib->format == FMT_16_16_16_16 && attrib->nfa == 2 && attrib->isSigned == 1 )
{
// seen in Rabbids Land
_readLittleEndianAttributeU16x4(shaderContext, src, attributeInputIndex);
src->add("if( (attrDecoder.x&0x8000) != 0 ) attrDecoder.x |= 0xFFFF0000;" _CRLF);
src->add("if( (attrDecoder.y&0x8000) != 0 ) attrDecoder.y |= 0xFFFF0000;" _CRLF);
src->add("if( (attrDecoder.z&0x8000) != 0 ) attrDecoder.z |= 0xFFFF0000;" _CRLF);
src->add("if( (attrDecoder.w&0x8000) != 0 ) attrDecoder.w |= 0xFFFF0000;" _CRLF);
src->add("attrDecoder.xyzw = floatBitsToUint(vec4(ivec4(attrDecoder)));" _CRLF);
}
else if (attrib->format == FMT_16_16_16_16_FLOAT && attrib->nfa == 2) else if (attrib->format == FMT_16_16_16_16_FLOAT && attrib->nfa == 2)
{ {
// seen in Giana Sisters: Twisted Dreams // seen in Giana Sisters: Twisted Dreams
@ -496,3 +506,5 @@ void LatteDecompiler_emitAttributeDecodeGLSL(LatteDecompilerShader* shaderContex
cemu_assert_debug(false); cemu_assert_debug(false);
} }
} }

View File

@ -23,16 +23,13 @@ bool RendererShaderGL::loadBinary()
cemu_assert_debug(m_baseHash != 0); cemu_assert_debug(m_baseHash != 0);
uint64 h1, h2; uint64 h1, h2;
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2); GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
sint32 fileSize = 0;
std::vector<uint8> cacheFileData; std::vector<uint8> cacheFileData;
if (!s_programBinaryCache->GetFile({h1, h2 }, cacheFileData)) if (!s_programBinaryCache->GetFile({h1, h2 }, cacheFileData))
return false; return false;
if (fileSize < sizeof(uint32)) if (cacheFileData.size() <= sizeof(uint32))
{
return false; return false;
}
uint32 shaderBinFormat = *(uint32*)(cacheFileData.data() + 0); uint32 shaderBinFormat = *(uint32*)(cacheFileData.data());
m_program = glCreateProgram(); m_program = glCreateProgram();
glProgramBinary(m_program, shaderBinFormat, cacheFileData.data()+4, cacheFileData.size()-4); glProgramBinary(m_program, shaderBinFormat, cacheFileData.data()+4, cacheFileData.size()-4);

View File

@ -12,9 +12,9 @@ uint32 RendererShader::GeneratePrecompiledCacheId()
v += (uint32)(*s); v += (uint32)(*s);
s++; s++;
} }
v += (EMULATOR_VERSION_LEAD * 1000000u); v += (EMULATOR_VERSION_MAJOR * 1000000u);
v += (EMULATOR_VERSION_MAJOR * 10000u); v += (EMULATOR_VERSION_MINOR * 10000u);
v += (EMULATOR_VERSION_MINOR * 100u); v += (EMULATOR_VERSION_PATCH * 100u);
// settings that can influence shaders // settings that can influence shaders
v += (uint32)g_current_game_profile->GetAccurateShaderMul() * 133; v += (uint32)g_current_game_profile->GetAccurateShaderMul() * 133;

View File

@ -146,8 +146,17 @@ void SwapchainInfoVk::Create()
UnrecoverableError("Failed to create semaphore for swapchain acquire"); UnrecoverableError("Failed to create semaphore for swapchain acquire");
} }
VkFenceCreateInfo fenceInfo = {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
result = vkCreateFence(m_logicalDevice, &fenceInfo, nullptr, &m_imageAvailableFence);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create fence for swapchain");
m_acquireIndex = 0; m_acquireIndex = 0;
hasDefinedSwapchainImage = false; hasDefinedSwapchainImage = false;
m_queueDepth = 0;
} }
void SwapchainInfoVk::Cleanup() void SwapchainInfoVk::Cleanup()
@ -177,6 +186,12 @@ void SwapchainInfoVk::Cleanup()
m_swapchainFramebuffers.clear(); m_swapchainFramebuffers.clear();
if (m_imageAvailableFence)
{
WaitAvailableFence();
vkDestroyFence(m_logicalDevice, m_imageAvailableFence, nullptr);
m_imageAvailableFence = nullptr;
}
if (m_swapchain) if (m_swapchain)
{ {
vkDestroySwapchainKHR(m_logicalDevice, m_swapchain, nullptr); vkDestroySwapchainKHR(m_logicalDevice, m_swapchain, nullptr);
@ -189,6 +204,18 @@ bool SwapchainInfoVk::IsValid() const
return m_swapchain && !m_acquireSemaphores.empty(); return m_swapchain && !m_acquireSemaphores.empty();
} }
void SwapchainInfoVk::WaitAvailableFence()
{
if(m_awaitableFence != VK_NULL_HANDLE)
vkWaitForFences(m_logicalDevice, 1, &m_awaitableFence, VK_TRUE, UINT64_MAX);
m_awaitableFence = VK_NULL_HANDLE;
}
void SwapchainInfoVk::ResetAvailableFence() const
{
vkResetFences(m_logicalDevice, 1, &m_imageAvailableFence);
}
VkSemaphore SwapchainInfoVk::ConsumeAcquireSemaphore() VkSemaphore SwapchainInfoVk::ConsumeAcquireSemaphore()
{ {
VkSemaphore ret = m_currentSemaphore; VkSemaphore ret = m_currentSemaphore;
@ -198,8 +225,10 @@ VkSemaphore SwapchainInfoVk::ConsumeAcquireSemaphore()
bool SwapchainInfoVk::AcquireImage() bool SwapchainInfoVk::AcquireImage()
{ {
ResetAvailableFence();
VkSemaphore acquireSemaphore = m_acquireSemaphores[m_acquireIndex]; VkSemaphore acquireSemaphore = m_acquireSemaphores[m_acquireIndex];
VkResult result = vkAcquireNextImageKHR(m_logicalDevice, m_swapchain, 1'000'000'000, acquireSemaphore, nullptr, &swapchainImageIndex); VkResult result = vkAcquireNextImageKHR(m_logicalDevice, m_swapchain, 1'000'000'000, acquireSemaphore, m_imageAvailableFence, &swapchainImageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
m_shouldRecreate = true; m_shouldRecreate = true;
if (result == VK_TIMEOUT) if (result == VK_TIMEOUT)
@ -216,6 +245,7 @@ bool SwapchainInfoVk::AcquireImage()
return false; return false;
} }
m_currentSemaphore = acquireSemaphore; m_currentSemaphore = acquireSemaphore;
m_awaitableFence = m_imageAvailableFence;
m_acquireIndex = (m_acquireIndex + 1) % m_swapchainImages.size(); m_acquireIndex = (m_acquireIndex + 1) % m_swapchainImages.size();
return true; return true;
@ -319,6 +349,7 @@ VkExtent2D SwapchainInfoVk::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& cap
VkPresentModeKHR SwapchainInfoVk::ChoosePresentMode(const std::vector<VkPresentModeKHR>& modes) VkPresentModeKHR SwapchainInfoVk::ChoosePresentMode(const std::vector<VkPresentModeKHR>& modes)
{ {
m_maxQueued = 0;
const auto vsyncState = (VSync)GetConfig().vsync.GetValue(); const auto vsyncState = (VSync)GetConfig().vsync.GetValue();
if (vsyncState == VSync::MAILBOX) if (vsyncState == VSync::MAILBOX)
{ {
@ -345,6 +376,7 @@ VkPresentModeKHR SwapchainInfoVk::ChoosePresentMode(const std::vector<VkPresentM
return VK_PRESENT_MODE_FIFO_KHR; return VK_PRESENT_MODE_FIFO_KHR;
} }
m_maxQueued = 1;
return VK_PRESENT_MODE_FIFO_KHR; return VK_PRESENT_MODE_FIFO_KHR;
} }

View File

@ -26,6 +26,9 @@ struct SwapchainInfoVk
bool IsValid() const; bool IsValid() const;
void WaitAvailableFence();
void ResetAvailableFence() const;
bool AcquireImage(); bool AcquireImage();
// retrieve semaphore of last acquire for submitting a wait operation // retrieve semaphore of last acquire for submitting a wait operation
// only one wait operation must be submitted per acquire (which submits a single signal operation) // only one wait operation must be submitted per acquire (which submits a single signal operation)
@ -68,6 +71,9 @@ struct SwapchainInfoVk
VkSwapchainKHR m_swapchain{}; VkSwapchainKHR m_swapchain{};
Vector2i m_desiredExtent{}; Vector2i m_desiredExtent{};
uint32 swapchainImageIndex = (uint32)-1; uint32 swapchainImageIndex = (uint32)-1;
uint64 m_presentId = 1;
uint64 m_queueDepth = 0; // number of frames with pending presentation requests
uint64 m_maxQueued = 0; // the maximum number of frames with presentation requests.
// swapchain image ringbuffer (indexed by swapchainImageIndex) // swapchain image ringbuffer (indexed by swapchainImageIndex)
@ -81,6 +87,8 @@ struct SwapchainInfoVk
private: private:
uint32 m_acquireIndex = 0; uint32 m_acquireIndex = 0;
std::vector<VkSemaphore> m_acquireSemaphores; // indexed by m_acquireIndex std::vector<VkSemaphore> m_acquireSemaphores; // indexed by m_acquireIndex
VkFence m_imageAvailableFence{};
VkFence m_awaitableFence = VK_NULL_HANDLE;
VkSemaphore m_currentSemaphore = VK_NULL_HANDLE; VkSemaphore m_currentSemaphore = VK_NULL_HANDLE;
std::array<uint32, 2> m_swapchainQueueFamilyIndices; std::array<uint32, 2> m_swapchainQueueFamilyIndices;

View File

@ -188,6 +188,9 @@ VKFUNC_DEVICE(vkCmdPipelineBarrier2KHR);
VKFUNC_DEVICE(vkCmdBeginRenderingKHR); VKFUNC_DEVICE(vkCmdBeginRenderingKHR);
VKFUNC_DEVICE(vkCmdEndRenderingKHR); VKFUNC_DEVICE(vkCmdEndRenderingKHR);
// khr_present_wait
VKFUNC_DEVICE(vkWaitForPresentKHR);
// transform feedback extension // transform feedback extension
VKFUNC_DEVICE(vkCmdBindTransformFeedbackBuffersEXT); VKFUNC_DEVICE(vkCmdBindTransformFeedbackBuffersEXT);
VKFUNC_DEVICE(vkCmdBeginTransformFeedbackEXT); VKFUNC_DEVICE(vkCmdBeginTransformFeedbackEXT);

View File

@ -826,7 +826,7 @@ void PipelineCompiler::InitDepthStencilState()
depthStencilState.front.reference = stencilRefFront; depthStencilState.front.reference = stencilRefFront;
depthStencilState.front.compareMask = stencilCompareMaskFront; depthStencilState.front.compareMask = stencilCompareMaskFront;
depthStencilState.front.writeMask = stencilWriteMaskBack; depthStencilState.front.writeMask = stencilWriteMaskFront;
depthStencilState.front.compareOp = vkDepthCompareTable[(size_t)frontStencilFunc]; depthStencilState.front.compareOp = vkDepthCompareTable[(size_t)frontStencilFunc];
depthStencilState.front.depthFailOp = stencilOpTable[(size_t)frontStencilZFail]; depthStencilState.front.depthFailOp = stencilOpTable[(size_t)frontStencilZFail];
depthStencilState.front.failOp = stencilOpTable[(size_t)frontStencilFail]; depthStencilState.front.failOp = stencilOpTable[(size_t)frontStencilFail];

View File

@ -7,6 +7,7 @@
#include "Cafe/HW/Latte/Core/LatteBufferCache.h" #include "Cafe/HW/Latte/Core/LatteBufferCache.h"
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h" #include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "Cafe/HW/Latte/Core/LatteOverlay.h"
#include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h" #include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h"
@ -29,6 +30,7 @@
#include <glslang/Public/ShaderLang.h> #include <glslang/Public/ShaderLang.h>
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#include <wx/intl.h> // for localization
#ifndef VK_API_VERSION_MAJOR #ifndef VK_API_VERSION_MAJOR
#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU) #define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU)
@ -45,7 +47,9 @@ const std::vector<const char*> kOptionalDeviceExtensions =
VK_EXT_FILTER_CUBIC_EXTENSION_NAME, // not supported by any device yet VK_EXT_FILTER_CUBIC_EXTENSION_NAME, // not supported by any device yet
VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME,
VK_KHR_PRESENT_WAIT_EXTENSION_NAME,
VK_KHR_PRESENT_ID_EXTENSION_NAME
}; };
const std::vector<const char*> kRequiredDeviceExtensions = const std::vector<const char*> kRequiredDeviceExtensions =
@ -123,7 +127,7 @@ std::vector<VulkanRenderer::DeviceInfo> VulkanRenderer::GetDevices()
VkApplicationInfo app_info{}; VkApplicationInfo app_info{};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = EMULATOR_NAME; app_info.pApplicationName = EMULATOR_NAME;
app_info.applicationVersion = VK_MAKE_VERSION(EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR); app_info.applicationVersion = VK_MAKE_VERSION(EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH);
app_info.pEngineName = EMULATOR_NAME; app_info.pEngineName = EMULATOR_NAME;
app_info.engineVersion = app_info.applicationVersion; app_info.engineVersion = app_info.applicationVersion;
app_info.apiVersion = apiVersion; app_info.apiVersion = apiVersion;
@ -250,12 +254,24 @@ void VulkanRenderer::GetDeviceFeatures()
pcc.pNext = prevStruct; pcc.pNext = prevStruct;
prevStruct = &pcc; prevStruct = &pcc;
VkPhysicalDevicePresentIdFeaturesKHR pidf{};
pidf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR;
pidf.pNext = prevStruct;
prevStruct = &pidf;
VkPhysicalDevicePresentWaitFeaturesKHR pwf{};
pwf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR;
pwf.pNext = prevStruct;
prevStruct = &pwf;
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{}; VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{};
physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
physicalDeviceFeatures2.pNext = prevStruct; physicalDeviceFeatures2.pNext = prevStruct;
vkGetPhysicalDeviceFeatures2(m_physicalDevice, &physicalDeviceFeatures2); vkGetPhysicalDeviceFeatures2(m_physicalDevice, &physicalDeviceFeatures2);
cemuLog_log(LogType::Force, "Vulkan: present_wait extension: {}", (pwf.presentWait && pidf.presentId) ? "supported" : "unsupported");
/* Get Vulkan device properties and limits */ /* Get Vulkan device properties and limits */
VkPhysicalDeviceFloatControlsPropertiesKHR pfcp{}; VkPhysicalDeviceFloatControlsPropertiesKHR pfcp{};
prevStruct = nullptr; prevStruct = nullptr;
@ -285,7 +301,7 @@ void VulkanRenderer::GetDeviceFeatures()
cemuLog_log(LogType::Force, "VK_EXT_pipeline_creation_cache_control not supported. Cannot use asynchronous shader and pipeline compilation"); cemuLog_log(LogType::Force, "VK_EXT_pipeline_creation_cache_control not supported. Cannot use asynchronous shader and pipeline compilation");
// if async shader compilation is enabled show warning message // if async shader compilation is enabled show warning message
if (GetConfig().async_compile) if (GetConfig().async_compile)
wxMessageBox(_("The currently installed graphics driver does not support the Vulkan extension necessary for asynchronous shader compilation. Asynchronous compilation cannot be used.\n \nRequired extension: VK_EXT_pipeline_creation_cache_control\n\nInstalling the latest graphics driver may solve this error."), _("Information"), wxOK | wxCENTRE); LatteOverlay_pushNotification(_("Async shader compile is enabled but not supported by the graphics driver\nCemu will use synchronous compilation which can cause additional stutter").utf8_string(), 10000);
} }
if (!m_featureControl.deviceExtensions.custom_border_color_without_format) if (!m_featureControl.deviceExtensions.custom_border_color_without_format)
{ {
@ -337,7 +353,7 @@ VulkanRenderer::VulkanRenderer()
VkApplicationInfo app_info{}; VkApplicationInfo app_info{};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = EMULATOR_NAME; app_info.pApplicationName = EMULATOR_NAME;
app_info.applicationVersion = VK_MAKE_VERSION(EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR); app_info.applicationVersion = VK_MAKE_VERSION(EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH);
app_info.pEngineName = EMULATOR_NAME; app_info.pEngineName = EMULATOR_NAME;
app_info.engineVersion = app_info.applicationVersion; app_info.engineVersion = app_info.applicationVersion;
app_info.apiVersion = apiVersion; app_info.apiVersion = apiVersion;
@ -488,6 +504,24 @@ VulkanRenderer::VulkanRenderer()
customBorderColorFeature.customBorderColors = VK_TRUE; customBorderColorFeature.customBorderColors = VK_TRUE;
customBorderColorFeature.customBorderColorWithoutFormat = VK_TRUE; customBorderColorFeature.customBorderColorWithoutFormat = VK_TRUE;
} }
// enable VK_KHR_present_id
VkPhysicalDevicePresentIdFeaturesKHR presentIdFeature{};
if(m_featureControl.deviceExtensions.present_wait)
{
presentIdFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR;
presentIdFeature.pNext = deviceExtensionFeatures;
deviceExtensionFeatures = &presentIdFeature;
presentIdFeature.presentId = VK_TRUE;
}
// enable VK_KHR_present_wait
VkPhysicalDevicePresentWaitFeaturesKHR presentWaitFeature{};
if(m_featureControl.deviceExtensions.present_wait)
{
presentWaitFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR;
presentWaitFeature.pNext = deviceExtensionFeatures;
deviceExtensionFeatures = &presentWaitFeature;
presentWaitFeature.presentWait = VK_TRUE;
}
std::vector<const char*> used_extensions; std::vector<const char*> used_extensions;
VkDeviceCreateInfo createInfo = CreateDeviceCreateInfo(queueCreateInfos, deviceFeatures, deviceExtensionFeatures, used_extensions); VkDeviceCreateInfo createInfo = CreateDeviceCreateInfo(queueCreateInfos, deviceFeatures, deviceExtensionFeatures, used_extensions);
@ -1045,6 +1079,10 @@ VkDeviceCreateInfo VulkanRenderer::CreateDeviceCreateInfo(const std::vector<VkDe
used_extensions.emplace_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); used_extensions.emplace_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.shader_float_controls) if (m_featureControl.deviceExtensions.shader_float_controls)
used_extensions.emplace_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); used_extensions.emplace_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.present_wait)
used_extensions.emplace_back(VK_KHR_PRESENT_ID_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.present_wait)
used_extensions.emplace_back(VK_KHR_PRESENT_WAIT_EXTENSION_NAME);
VkDeviceCreateInfo createInfo{}; VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@ -1142,6 +1180,7 @@ bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device,
info.deviceExtensions.shader_float_controls = isExtensionAvailable(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); info.deviceExtensions.shader_float_controls = isExtensionAvailable(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
info.deviceExtensions.dynamic_rendering = false; // isExtensionAvailable(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); info.deviceExtensions.dynamic_rendering = false; // isExtensionAvailable(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
// dynamic rendering doesn't provide any benefits for us right now. Driver implementations are very unoptimized as of Feb 2022 // dynamic rendering doesn't provide any benefits for us right now. Driver implementations are very unoptimized as of Feb 2022
info.deviceExtensions.present_wait = isExtensionAvailable(VK_KHR_PRESENT_WAIT_EXTENSION_NAME) && isExtensionAvailable(VK_KHR_PRESENT_ID_EXTENSION_NAME);
// check for framedebuggers // check for framedebuggers
info.debugMarkersSupported = false; info.debugMarkersSupported = false;
@ -2198,6 +2237,8 @@ void VulkanRenderer::GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isD
else else
{ {
formatInfoOut->vkImageAspect = VK_IMAGE_ASPECT_COLOR_BIT; formatInfoOut->vkImageAspect = VK_IMAGE_ASPECT_COLOR_BIT;
if(format == (Latte::E_GX2SURFFMT::R16_G16_B16_A16_FLOAT | Latte::E_GX2SURFFMT::FMT_BIT_SRGB)) // Seen in Sonic Transformed level Starry Speedway. SRGB should just be ignored for native float formats?
format = Latte::E_GX2SURFFMT::R16_G16_B16_A16_FLOAT;
switch (format) switch (format)
{ {
// RGBA formats // RGBA formats
@ -2439,6 +2480,11 @@ void VulkanRenderer::GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isD
// used by Color Splash and Resident Evil // used by Color Splash and Resident Evil
formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UINT; // todo - should we use ABGR format? formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UINT; // todo - should we use ABGR format?
formatInfoOut->decoder = TextureDecoder_X24_G8_UINT::getInstance(); // todo - verify formatInfoOut->decoder = TextureDecoder_X24_G8_UINT::getInstance(); // todo - verify
case Latte::E_GX2SURFFMT::R32_X8_FLOAT:
// seen in Disney Infinity 3.0
formatInfoOut->vkImageFormat = VK_FORMAT_R32_SFLOAT;
formatInfoOut->decoder = TextureDecoder_NullData64::getInstance();
break;
default: default:
cemuLog_log(LogType::Force, "Unsupported color texture format {:04x}", (uint32)format); cemuLog_log(LogType::Force, "Unsupported color texture format {:04x}", (uint32)format);
cemu_assert_debug(false); cemu_assert_debug(false);
@ -2686,11 +2732,21 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
ClearColorImageRaw(chainInfo.m_swapchainImages[chainInfo.swapchainImageIndex], 0, 0, clearColor, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); ClearColorImageRaw(chainInfo.m_swapchainImages[chainInfo.swapchainImageIndex], 0, 0, clearColor, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
} }
const size_t currentFrameCmdBufferID = GetCurrentCommandBufferId();
VkSemaphore presentSemaphore = chainInfo.m_presentSemaphores[chainInfo.swapchainImageIndex]; VkSemaphore presentSemaphore = chainInfo.m_presentSemaphores[chainInfo.swapchainImageIndex];
SubmitCommandBuffer(presentSemaphore); // submit all command and signal semaphore SubmitCommandBuffer(presentSemaphore); // submit all command and signal semaphore
cemu_assert_debug(m_numSubmittedCmdBuffers > 0); cemu_assert_debug(m_numSubmittedCmdBuffers > 0);
// wait for the previous frame to finish rendering
WaitCommandBufferFinished(m_commandBufferIDOfPrevFrame);
m_commandBufferIDOfPrevFrame = currentFrameCmdBufferID;
chainInfo.WaitAvailableFence();
VkPresentIdKHR presentId = {};
VkPresentInfoKHR presentInfo = {}; VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.swapchainCount = 1; presentInfo.swapchainCount = 1;
@ -2700,6 +2756,24 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
presentInfo.waitSemaphoreCount = 1; presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &presentSemaphore; presentInfo.pWaitSemaphores = &presentSemaphore;
// if present_wait is available and enabled, add frame markers to present requests
// and limit the number of queued present operations
if (m_featureControl.deviceExtensions.present_wait && chainInfo.m_maxQueued > 0)
{
presentId.sType = VK_STRUCTURE_TYPE_PRESENT_ID_KHR;
presentId.swapchainCount = 1;
presentId.pPresentIds = &chainInfo.m_presentId;
presentInfo.pNext = &presentId;
if(chainInfo.m_queueDepth >= chainInfo.m_maxQueued)
{
uint64 waitFrameId = chainInfo.m_presentId - chainInfo.m_queueDepth;
vkWaitForPresentKHR(m_logicalDevice, chainInfo.m_swapchain, waitFrameId, 40'000'000);
chainInfo.m_queueDepth--;
}
}
VkResult result = vkQueuePresentKHR(m_presentQueue, &presentInfo); VkResult result = vkQueuePresentKHR(m_presentQueue, &presentInfo);
if (result < 0 && result != VK_ERROR_OUT_OF_DATE_KHR) if (result < 0 && result != VK_ERROR_OUT_OF_DATE_KHR)
{ {
@ -2708,6 +2782,12 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
chainInfo.m_shouldRecreate = true; chainInfo.m_shouldRecreate = true;
if(result >= 0)
{
chainInfo.m_queueDepth++;
chainInfo.m_presentId++;
}
chainInfo.hasDefinedSwapchainImage = false; chainInfo.hasDefinedSwapchainImage = false;
chainInfo.swapchainImageIndex = -1; chainInfo.swapchainImageIndex = -1;

View File

@ -450,6 +450,7 @@ private:
bool synchronization2 = false; // VK_KHR_synchronization2 bool synchronization2 = false; // VK_KHR_synchronization2
bool dynamic_rendering = false; // VK_KHR_dynamic_rendering bool dynamic_rendering = false; // VK_KHR_dynamic_rendering
bool shader_float_controls = false; // VK_KHR_shader_float_controls bool shader_float_controls = false; // VK_KHR_shader_float_controls
bool present_wait = false; // VK_KHR_present_wait
}deviceExtensions; }deviceExtensions;
struct struct
@ -635,6 +636,7 @@ private:
size_t m_commandBufferIndex = 0; // current buffer being filled size_t m_commandBufferIndex = 0; // current buffer being filled
size_t m_commandBufferSyncIndex = 0; // latest buffer that finished execution (updated on submit) size_t m_commandBufferSyncIndex = 0; // latest buffer that finished execution (updated on submit)
size_t m_commandBufferIDOfPrevFrame = 0;
std::array<VkFence, kCommandBufferPoolSize> m_cmd_buffer_fences; std::array<VkFence, kCommandBufferPoolSize> m_cmd_buffer_fences;
std::array<VkCommandBuffer, kCommandBufferPoolSize> m_commandBuffers; std::array<VkCommandBuffer, kCommandBufferPoolSize> m_commandBuffers;
std::array<VkSemaphore, kCommandBufferPoolSize> m_commandBufferSemaphores; std::array<VkSemaphore, kCommandBufferPoolSize> m_commandBufferSemaphores;

View File

@ -0,0 +1,406 @@
#include "iosu_ccr_nfc.h"
#include "Cafe/IOSU/kernel/iosu_kernel.h"
#include "util/crypto/aes128.h"
#include <openssl/evp.h>
#include <openssl/hmac.h>
namespace iosu
{
namespace ccr_nfc
{
IOSMsgQueueId sCCRNFCMsgQueue;
SysAllocator<iosu::kernel::IOSMessage, 0x20> sCCRNFCMsgQueueMsgBuffer;
std::thread sCCRNFCThread;
constexpr uint8 sNfcKey[] = { 0xC1, 0x2B, 0x07, 0x10, 0xD7, 0x2C, 0xEB, 0x5D, 0x43, 0x49, 0xB7, 0x43, 0xE3, 0xCA, 0xD2, 0x24 };
constexpr uint8 sNfcKeyIV[] = { 0x4F, 0xD3, 0x9A, 0x6E, 0x79, 0xFC, 0xEA, 0xAD, 0x99, 0x90, 0x4D, 0xB8, 0xEE, 0x38, 0xE9, 0xDB };
constexpr uint8 sUnfixedInfosMagicBytes[] = { 0x00, 0x00, 0xDB, 0x4B, 0x9E, 0x3F, 0x45, 0x27, 0x8F, 0x39, 0x7E, 0xFF, 0x9B, 0x4F, 0xB9, 0x93 };
constexpr uint8 sLockedSecretMagicBytes[] = { 0xFD, 0xC8, 0xA0, 0x76, 0x94, 0xB8, 0x9E, 0x4C, 0x47, 0xD3, 0x7D, 0xE8, 0xCE, 0x5C, 0x74, 0xC1 };
constexpr uint8 sUnfixedInfosString[] = { 0x75, 0x6E, 0x66, 0x69, 0x78, 0x65, 0x64, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x73, 0x00, 0x00, 0x00 };
constexpr uint8 sLockedSecretString[] = { 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x00, 0x00, 0x00 };
constexpr uint8 sLockedSecretHmacKey[] = { 0x7F, 0x75, 0x2D, 0x28, 0x73, 0xA2, 0x00, 0x17, 0xFE, 0xF8, 0x5C, 0x05, 0x75, 0x90, 0x4B, 0x6D };
constexpr uint8 sUnfixedInfosHmacKey[] = { 0x1D, 0x16, 0x4B, 0x37, 0x5B, 0x72, 0xA5, 0x57, 0x28, 0xB9, 0x1D, 0x64, 0xB6, 0xA3, 0xC2, 0x05 };
uint8 sLockedSecretInternalKey[0x10];
uint8 sLockedSecretInternalNonce[0x10];
uint8 sLockedSecretInternalHmacKey[0x10];
uint8 sUnfixedInfosInternalKey[0x10];
uint8 sUnfixedInfosInternalNonce[0x10];
uint8 sUnfixedInfosInternalHmacKey[0x10];
sint32 __CCRNFCValidateCryptData(CCRNFCCryptData* data, uint32 size, bool validateOffsets)
{
if (!data)
{
return CCR_NFC_ERROR;
}
if (size != sizeof(CCRNFCCryptData))
{
return CCR_NFC_ERROR;
}
if (!validateOffsets)
{
return 0;
}
// Make sure all offsets are within bounds
if (data->version == 0)
{
if (data->unfixedInfosHmacOffset < 0x1C9 && data->unfixedInfosOffset < 0x1C9 &&
data->lockedSecretHmacOffset < 0x1C9 && data->lockedSecretOffset < 0x1C9 &&
data->lockedSecretSize < 0x1C9 && data->unfixedInfosSize < 0x1C9)
{
return 0;
}
}
else if (data->version == 2)
{
if (data->unfixedInfosHmacOffset < 0x21D && data->unfixedInfosOffset < 0x21D &&
data->lockedSecretHmacOffset < 0x21D && data->lockedSecretOffset < 0x21D &&
data->lockedSecretSize < 0x21D && data->unfixedInfosSize < 0x21D)
{
return 0;
}
}
return CCR_NFC_ERROR;
}
sint32 CCRNFCAESCTRCrypt(const uint8* key, const void* ivNonce, const void* inData, uint32 inSize, void* outData, uint32 outSize)
{
uint8 tmpIv[0x10];
memcpy(tmpIv, ivNonce, sizeof(tmpIv));
memcpy(outData, inData, inSize);
AES128CTR_transform((uint8*)outData, outSize, (uint8*)key, tmpIv);
return 0;
}
sint32 __CCRNFCGenerateKey(const uint8* hmacKey, uint32 hmacKeySize, const uint8* name, uint32 nameSize, const uint8* inData, uint32 inSize, uint8* outData, uint32 outSize)
{
if (nameSize != 0xe || outSize != 0x40)
{
return CCR_NFC_ERROR;
}
// Create a buffer containing 2 counter bytes, the key name, and the key data
uint8 buffer[0x50];
buffer[0] = 0;
buffer[1] = 0;
memcpy(buffer + 2, name, nameSize);
memcpy(buffer + nameSize + 2, inData, inSize);
uint16 counter = 0;
while (outSize > 0)
{
// Set counter bytes and increment counter
buffer[0] = (counter >> 8) & 0xFF;
buffer[1] = counter & 0xFF;
counter++;
uint32 dataSize = outSize;
if (!HMAC(EVP_sha256(), hmacKey, hmacKeySize, buffer, sizeof(buffer), outData, &dataSize))
{
return CCR_NFC_ERROR;
}
outSize -= 0x20;
outData += 0x20;
}
return 0;
}
sint32 __CCRNFCGenerateInternalKeys(const CCRNFCCryptData* in, const uint8* keyGenSalt)
{
uint8 lockedSecretBuffer[0x40] = { 0 };
uint8 unfixedInfosBuffer[0x40] = { 0 };
uint8 outBuffer[0x40] = { 0 };
// Fill the locked secret buffer
memcpy(lockedSecretBuffer, sLockedSecretMagicBytes, sizeof(sLockedSecretMagicBytes));
if (in->version == 0)
{
// For Version 0 this is the 16-byte Format Info
memcpy(lockedSecretBuffer + 0x10, in->data + in->uuidOffset, 0x10);
}
else if (in->version == 2)
{
// For Version 2 this is 2 times the 7-byte UID + 1 check byte
memcpy(lockedSecretBuffer + 0x10, in->data + in->uuidOffset, 8);
memcpy(lockedSecretBuffer + 0x18, in->data + in->uuidOffset, 8);
}
else
{
return CCR_NFC_ERROR;
}
// Append key generation salt
memcpy(lockedSecretBuffer + 0x20, keyGenSalt, 0x20);
// Generate the key output
sint32 res = __CCRNFCGenerateKey(sLockedSecretHmacKey, sizeof(sLockedSecretHmacKey), sLockedSecretString, 0xe, lockedSecretBuffer, sizeof(lockedSecretBuffer), outBuffer, sizeof(outBuffer));
if (res != 0)
{
return res;
}
// Unpack the key buffer
memcpy(sLockedSecretInternalKey, outBuffer, 0x10);
memcpy(sLockedSecretInternalNonce, outBuffer + 0x10, 0x10);
memcpy(sLockedSecretInternalHmacKey, outBuffer + 0x20, 0x10);
// Fill the unfixed infos buffer
memcpy(unfixedInfosBuffer, in->data + in->seedOffset, 2);
memcpy(unfixedInfosBuffer + 2, sUnfixedInfosMagicBytes + 2, 0xe);
if (in->version == 0)
{
// For Version 0 this is the 16-byte Format Info
memcpy(unfixedInfosBuffer + 0x10, in->data + in->uuidOffset, 0x10);
}
else if (in->version == 2)
{
// For Version 2 this is 2 times the 7-byte UID + 1 check byte
memcpy(unfixedInfosBuffer + 0x10, in->data + in->uuidOffset, 8);
memcpy(unfixedInfosBuffer + 0x18, in->data + in->uuidOffset, 8);
}
else
{
return CCR_NFC_ERROR;
}
// Append key generation salt
memcpy(unfixedInfosBuffer + 0x20, keyGenSalt, 0x20);
// Generate the key output
res = __CCRNFCGenerateKey(sUnfixedInfosHmacKey, sizeof(sUnfixedInfosHmacKey), sUnfixedInfosString, 0xe, unfixedInfosBuffer, sizeof(unfixedInfosBuffer), outBuffer, sizeof(outBuffer));
if (res != 0)
{
return res;
}
// Unpack the key buffer
memcpy(sUnfixedInfosInternalKey, outBuffer, 0x10);
memcpy(sUnfixedInfosInternalNonce, outBuffer + 0x10, 0x10);
memcpy(sUnfixedInfosInternalHmacKey, outBuffer + 0x20, 0x10);
return 0;
}
sint32 __CCRNFCCryptData(const CCRNFCCryptData* in, CCRNFCCryptData* out, bool decrypt)
{
// Decrypt key generation salt
uint8 keyGenSalt[0x20];
sint32 res = CCRNFCAESCTRCrypt(sNfcKey, sNfcKeyIV, in->data + in->keyGenSaltOffset, 0x20, keyGenSalt, sizeof(keyGenSalt));
if (res != 0)
{
return res;
}
// Prepare internal keys
res = __CCRNFCGenerateInternalKeys(in, keyGenSalt);
if (res != 0)
{
return res;
}
if (decrypt)
{
// Only version 0 tags have an encrypted locked secret area
if (in->version == 0)
{
res = CCRNFCAESCTRCrypt(sLockedSecretInternalKey, sLockedSecretInternalNonce, in->data + in->lockedSecretOffset, in->lockedSecretSize, out->data + in->lockedSecretOffset, in->lockedSecretSize);
if (res != 0)
{
return res;
}
}
// Decrypt unfxied infos
res = CCRNFCAESCTRCrypt(sUnfixedInfosInternalKey, sUnfixedInfosInternalNonce, in->data + in->unfixedInfosOffset, in->unfixedInfosSize, out->data + in->unfixedInfosOffset, in->unfixedInfosSize);
if (res != 0)
{
return res;
}
// Verify HMACs
uint8 hmacBuffer[0x20];
uint32 hmacLen = sizeof(hmacBuffer);
if (!HMAC(EVP_sha256(), sLockedSecretInternalHmacKey, sizeof(sLockedSecretInternalHmacKey), out->data + in->lockedSecretHmacOffset + 0x20, (in->dataSize - in->lockedSecretHmacOffset) - 0x20, hmacBuffer, &hmacLen))
{
return CCR_NFC_ERROR;
}
if (memcmp(in->data + in->lockedSecretHmacOffset, hmacBuffer, 0x20) != 0)
{
return CCR_NFC_INVALID_LOCKED_SECRET;
}
if (in->version == 0)
{
hmacLen = sizeof(hmacBuffer);
res = HMAC(EVP_sha256(), sUnfixedInfosInternalHmacKey, sizeof(sUnfixedInfosInternalHmacKey), out->data + in->unfixedInfosHmacOffset + 0x20, (in->dataSize - in->unfixedInfosHmacOffset) - 0x20, hmacBuffer, &hmacLen) ? 0 : CCR_NFC_ERROR;
}
else
{
hmacLen = sizeof(hmacBuffer);
res = HMAC(EVP_sha256(), sUnfixedInfosInternalHmacKey, sizeof(sUnfixedInfosInternalHmacKey), out->data + in->unfixedInfosHmacOffset + 0x21, (in->dataSize - in->unfixedInfosHmacOffset) - 0x21, hmacBuffer, &hmacLen) ? 0 : CCR_NFC_ERROR;
}
if (memcmp(in->data + in->unfixedInfosHmacOffset, hmacBuffer, 0x20) != 0)
{
return CCR_NFC_INVALID_UNFIXED_INFOS;
}
}
else
{
uint8 hmacBuffer[0x20];
uint32 hmacLen = sizeof(hmacBuffer);
if (!HMAC(EVP_sha256(), sLockedSecretInternalHmacKey, sizeof(sLockedSecretInternalHmacKey), out->data + in->lockedSecretHmacOffset + 0x20, (in->dataSize - in->lockedSecretHmacOffset) - 0x20, hmacBuffer, &hmacLen))
{
return CCR_NFC_ERROR;
}
if (memcmp(in->data + in->lockedSecretHmacOffset, hmacBuffer, 0x20) != 0)
{
return CCR_NFC_INVALID_LOCKED_SECRET;
}
// Only version 0 tags have an encrypted locked secret area
if (in->version == 0)
{
uint32 hmacLen = 0x20;
if (!HMAC(EVP_sha256(), sUnfixedInfosInternalHmacKey, sizeof(sUnfixedInfosInternalHmacKey), out->data + in->unfixedInfosHmacOffset + 0x20, (in->dataSize - in->unfixedInfosHmacOffset) - 0x20, out->data + in->unfixedInfosHmacOffset, &hmacLen))
{
return CCR_NFC_ERROR;
}
res = CCRNFCAESCTRCrypt(sLockedSecretInternalKey, sLockedSecretInternalNonce, in->data + in->lockedSecretOffset, in->lockedSecretSize, out->data + in->lockedSecretOffset, in->lockedSecretSize);
if (res != 0)
{
return res;
}
}
else
{
uint32 hmacLen = 0x20;
if (!HMAC(EVP_sha256(), sUnfixedInfosInternalHmacKey, sizeof(sUnfixedInfosInternalHmacKey), out->data + in->unfixedInfosHmacOffset + 0x21, (in->dataSize - in->unfixedInfosHmacOffset) - 0x21, out->data + in->unfixedInfosHmacOffset, &hmacLen))
{
return CCR_NFC_ERROR;
}
}
res = CCRNFCAESCTRCrypt(sUnfixedInfosInternalKey, sUnfixedInfosInternalNonce, in->data + in->unfixedInfosOffset, in->unfixedInfosSize, out->data + in->unfixedInfosOffset, in->unfixedInfosSize);
if (res != 0)
{
return res;
}
}
return res;
}
void CCRNFCThread()
{
iosu::kernel::IOSMessage msg;
while (true)
{
IOS_ERROR error = iosu::kernel::IOS_ReceiveMessage(sCCRNFCMsgQueue, &msg, 0);
cemu_assert(!IOS_ResultIsError(error));
// Check for system exit
if (msg == 0xf00dd00d)
{
return;
}
IPCCommandBody* cmd = MEMPTR<IPCCommandBody>(msg).GetPtr();
if (cmd->cmdId == IPCCommandId::IOS_OPEN)
{
iosu::kernel::IOS_ResourceReply(cmd, IOS_ERROR_OK);
}
else if (cmd->cmdId == IPCCommandId::IOS_CLOSE)
{
iosu::kernel::IOS_ResourceReply(cmd, IOS_ERROR_OK);
}
else if (cmd->cmdId == IPCCommandId::IOS_IOCTL)
{
sint32 result;
uint32 requestId = cmd->args[0];
void* ptrIn = MEMPTR<void>(cmd->args[1]);
uint32 sizeIn = cmd->args[2];
void* ptrOut = MEMPTR<void>(cmd->args[3]);
uint32 sizeOut = cmd->args[4];
if ((result = __CCRNFCValidateCryptData(static_cast<CCRNFCCryptData*>(ptrIn), sizeIn, true)) == 0 &&
(result = __CCRNFCValidateCryptData(static_cast<CCRNFCCryptData*>(ptrOut), sizeOut, false)) == 0)
{
// Initialize outData with inData
memcpy(ptrOut, ptrIn, sizeIn);
switch (requestId)
{
case 1: // encrypt
result = __CCRNFCCryptData(static_cast<CCRNFCCryptData*>(ptrIn), static_cast<CCRNFCCryptData*>(ptrOut), false);
break;
case 2: // decrypt
result = __CCRNFCCryptData(static_cast<CCRNFCCryptData*>(ptrIn), static_cast<CCRNFCCryptData*>(ptrOut), true);
break;
default:
cemuLog_log(LogType::Force, "/dev/ccr_nfc: Unsupported IOCTL requestId");
cemu_assert_suspicious();
result = IOS_ERROR_INVALID;
break;
}
}
iosu::kernel::IOS_ResourceReply(cmd, static_cast<IOS_ERROR>(result));
}
else
{
cemuLog_log(LogType::Force, "/dev/ccr_nfc: Unsupported IPC cmdId");
cemu_assert_suspicious();
iosu::kernel::IOS_ResourceReply(cmd, IOS_ERROR_INVALID);
}
}
}
class : public ::IOSUModule
{
void SystemLaunch() override
{
sCCRNFCMsgQueue = iosu::kernel::IOS_CreateMessageQueue(sCCRNFCMsgQueueMsgBuffer.GetPtr(), sCCRNFCMsgQueueMsgBuffer.GetCount());
cemu_assert(!IOS_ResultIsError(static_cast<IOS_ERROR>(sCCRNFCMsgQueue)));
IOS_ERROR error = iosu::kernel::IOS_RegisterResourceManager("/dev/ccr_nfc", sCCRNFCMsgQueue);
cemu_assert(!IOS_ResultIsError(error));
sCCRNFCThread = std::thread(CCRNFCThread);
}
void SystemExit() override
{
if (sCCRNFCMsgQueue < 0)
{
return;
}
iosu::kernel::IOS_SendMessage(sCCRNFCMsgQueue, 0xf00dd00d, 0);
sCCRNFCThread.join();
iosu::kernel::IOS_DestroyMessageQueue(sCCRNFCMsgQueue);
sCCRNFCMsgQueue = -1;
}
} sIOSUModuleCCRNFC;
IOSUModule* GetModule()
{
return &sIOSUModuleCCRNFC;
}
}
}

View File

@ -0,0 +1,31 @@
#pragma once
#include "Cafe/IOSU/iosu_types_common.h"
#define CCR_NFC_ERROR (-0x2F001E)
#define CCR_NFC_INVALID_LOCKED_SECRET (-0x2F0029)
#define CCR_NFC_INVALID_UNFIXED_INFOS (-0x2F002A)
namespace iosu
{
namespace ccr_nfc
{
struct CCRNFCCryptData
{
uint32 version;
uint32 dataSize;
uint32 seedOffset;
uint32 keyGenSaltOffset;
uint32 uuidOffset;
uint32 unfixedInfosOffset;
uint32 unfixedInfosSize;
uint32 lockedSecretOffset;
uint32 lockedSecretSize;
uint32 unfixedInfosHmacOffset;
uint32 lockedSecretHmacOffset;
uint8 data[540];
};
static_assert(sizeof(CCRNFCCryptData) == 0x248);
IOSUModule* GetModule();
}
}

View File

@ -511,6 +511,8 @@ namespace iosu
return CallHandler_GetBlackList(fpdClient, vecIn, numVecIn, vecOut, numVecOut); return CallHandler_GetBlackList(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
case FPD_REQUEST_ID::GetFriendListEx: case FPD_REQUEST_ID::GetFriendListEx:
return CallHandler_GetFriendListEx(fpdClient, vecIn, numVecIn, vecOut, numVecOut); return CallHandler_GetFriendListEx(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
case FPD_REQUEST_ID::UpdateCommentAsync:
return CallHandler_UpdateCommentAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
case FPD_REQUEST_ID::UpdatePreferenceAsync: case FPD_REQUEST_ID::UpdatePreferenceAsync:
return CallHandler_UpdatePreferenceAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut); return CallHandler_UpdatePreferenceAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
case FPD_REQUEST_ID::AddFriendRequestByPlayRecordAsync: case FPD_REQUEST_ID::AddFriendRequestByPlayRecordAsync:
@ -719,18 +721,23 @@ namespace iosu
nnResult CallHandler_GetMyComment(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut) nnResult CallHandler_GetMyComment(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
{ {
static constexpr uint32 MY_COMMENT_LENGTH = 0x12; // are comments utf16? Buffer length is 0x24
if(numVecIn != 0 || numVecOut != 1) if(numVecIn != 0 || numVecOut != 1)
return FPResult_InvalidIPCParam; return FPResult_InvalidIPCParam;
if(vecOut->size != MY_COMMENT_LENGTH*sizeof(uint16be))
{
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
return FPResult_InvalidIPCParam;
}
std::basic_string<uint16be> myComment; std::basic_string<uint16be> myComment;
myComment.resize(MY_COMMENT_LENGTH); if(g_fpd.nexFriendSession)
memcpy(vecOut->basePhys.GetPtr(), myComment.data(), MY_COMMENT_LENGTH*sizeof(uint16be)); {
return 0; if(vecOut->size != MY_COMMENT_LENGTH * sizeof(uint16be))
{
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
return FPResult_InvalidIPCParam;
}
nexComment myNexComment;
g_fpd.nexFriendSession->getMyComment(myNexComment);
myComment = StringHelpers::FromUtf8(myNexComment.commentString);
}
myComment.insert(0, 1, '\0');
memcpy(vecOut->basePhys.GetPtr(), myComment.c_str(), MY_COMMENT_LENGTH * sizeof(uint16be));
return FPResult_Ok;
} }
nnResult CallHandler_GetMyPreference(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut) nnResult CallHandler_GetMyPreference(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
@ -1143,6 +1150,36 @@ namespace iosu
return FPResult_Ok; return FPResult_Ok;
} }
nnResult CallHandler_UpdateCommentAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
{
std::unique_lock _l(g_fpd.mtxFriendSession);
if (numVecIn != 1 || numVecOut != 0)
return FPResult_InvalidIPCParam;
if (!g_fpd.nexFriendSession)
return FPResult_RequestFailed;
uint32 messageLength = vecIn[0].size / sizeof(uint16be);
DeclareInputPtr(newComment, uint16be, messageLength, 0);
if (messageLength == 0 || newComment[messageLength-1] != 0)
{
cemuLog_log(LogType::Force, "UpdateCommentAsync: Message must contain at least a null-termination character");
return FPResult_InvalidIPCParam;
}
IPCCommandBody* cmd = ServiceCallDelayCurrentResponse();
auto utf8_comment = StringHelpers::ToUtf8(newComment, messageLength);
nexComment temporaryComment;
temporaryComment.ukn0 = 0;
temporaryComment.commentString = utf8_comment;
temporaryComment.ukn1 = 0;
g_fpd.nexFriendSession->updateCommentAsync(temporaryComment, [cmd](NexFriends::RpcErrorCode result) {
if (result != NexFriends::ERR_NONE)
return ServiceCallAsyncRespond(cmd, FPResult_RequestFailed);
ServiceCallAsyncRespond(cmd, FPResult_Ok);
});
return FPResult_Ok;
}
nnResult CallHandler_UpdatePreferenceAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut) nnResult CallHandler_UpdatePreferenceAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
{ {
std::unique_lock _l(g_fpd.mtxFriendSession); std::unique_lock _l(g_fpd.mtxFriendSession);

View File

@ -212,6 +212,7 @@ namespace iosu
static const int RELATIONSHIP_FRIEND = 3; static const int RELATIONSHIP_FRIEND = 3;
static const int GAMEMODE_MAX_MESSAGE_LENGTH = 0x80; // limit includes null-terminator character, so only 0x7F actual characters can be used static const int GAMEMODE_MAX_MESSAGE_LENGTH = 0x80; // limit includes null-terminator character, so only 0x7F actual characters can be used
static const int MY_COMMENT_LENGTH = 0x12;
enum class FPD_REQUEST_ID enum class FPD_REQUEST_ID
{ {
@ -245,6 +246,7 @@ namespace iosu
CheckSettingStatusAsync = 0x7596, CheckSettingStatusAsync = 0x7596,
GetFriendListEx = 0x75F9, GetFriendListEx = 0x75F9,
GetFriendRequestListEx = 0x76C1, GetFriendRequestListEx = 0x76C1,
UpdateCommentAsync = 0x7726,
UpdatePreferenceAsync = 0x7727, UpdatePreferenceAsync = 0x7727,
RemoveFriendAsync = 0x7789, RemoveFriendAsync = 0x7789,
DeleteFriendFlagsAsync = 0x778A, DeleteFriendFlagsAsync = 0x778A,

View File

@ -23,3 +23,86 @@ void osLib_returnFromFunction64(PPCInterpreter_t* hCPU, uint64 returnValue64);
// utility functions // utility functions
#include "Cafe/OS/common/OSUtil.h" #include "Cafe/OS/common/OSUtil.h"
// va_list
struct ppc_va_list
{
uint8be gprIndex;
uint8be fprIndex;
uint8be _padding2[2];
MEMPTR<uint8be> overflow_arg_area;
MEMPTR<uint8be> reg_save_area;
};
static_assert(sizeof(ppc_va_list) == 0xC);
struct ppc_va_list_reg_storage
{
uint32be gpr_save_area[8]; // 32 bytes, r3 to r10
float64be fpr_save_area[8]; // 64 bytes, f1 to f8
ppc_va_list vargs;
uint32be padding;
};
static_assert(sizeof(ppc_va_list_reg_storage) == 0x70);
// Equivalent of va_start for PPC HLE functions. Must be called before any StackAllocator<> definitions
#define ppc_define_va_list(__gprIndex, __fprIndex) \
MPTR vaOriginalR1 = PPCInterpreter_getCurrentInstance()->gpr[1]; \
StackAllocator<ppc_va_list_reg_storage> va_list_storage; \
for(int i=3; i<=10; i++) va_list_storage->gpr_save_area[i-3] = PPCInterpreter_getCurrentInstance()->gpr[i]; \
for(int i=1; i<=8; i++) va_list_storage->fpr_save_area[i-1] = PPCInterpreter_getCurrentInstance()->fpr[i].fp0; \
va_list_storage->vargs.gprIndex = __gprIndex; \
va_list_storage->vargs.fprIndex = __fprIndex; \
va_list_storage->vargs.reg_save_area = (uint8be*)&va_list_storage; \
va_list_storage->vargs.overflow_arg_area = {vaOriginalR1 + 8}; \
ppc_va_list& vargs = va_list_storage->vargs;
enum class ppc_va_type
{
INT32 = 1,
INT64 = 2,
FLOAT_OR_DOUBLE = 3,
};
static void* _ppc_va_arg(ppc_va_list* vargs, ppc_va_type argType)
{
void* r;
switch ( argType )
{
default:
cemu_assert_suspicious();
case ppc_va_type::INT32:
if ( vargs[0].gprIndex < 8u )
{
r = &vargs->reg_save_area[4 * vargs->gprIndex];
vargs->gprIndex++;
return r;
}
r = vargs->overflow_arg_area;
vargs->overflow_arg_area += 4;
return r;
case ppc_va_type::INT64:
if ( (vargs->gprIndex & 1) != 0 )
vargs->gprIndex++;
if ( vargs->gprIndex < 8 )
{
r = &vargs->reg_save_area[4 * vargs->gprIndex];
vargs->gprIndex += 2;
return r;
}
vargs->overflow_arg_area = {(vargs->overflow_arg_area.GetMPTR()+7) & 0xFFFFFFF8};
r = vargs->overflow_arg_area;
vargs->overflow_arg_area += 8;
return r;
case ppc_va_type::FLOAT_OR_DOUBLE:
if ( vargs->fprIndex < 8 )
{
r = &vargs->reg_save_area[0x20 + 8 * vargs->fprIndex];
vargs->fprIndex++;
return r;
}
vargs->overflow_arg_area = {(vargs->overflow_arg_area.GetMPTR()+7) & 0xFFFFFFF8};
r = vargs->overflow_arg_area;
vargs->overflow_arg_area += 8;
return r;
}
}

View File

@ -1,6 +1,6 @@
#include "Cafe/OS/common/OSCommon.h" #include "Cafe/OS/common/OSCommon.h"
#include "Common/SysAllocator.h" #include "Common/SysAllocator.h"
#include "Cafe/OS/RPL/rpl.h" #include "Cafe/OS/RPL/rpl_symbol_storage.h"
#include "Cafe/OS/libs/coreinit/coreinit_Misc.h" #include "Cafe/OS/libs/coreinit/coreinit_Misc.h"
@ -69,7 +69,7 @@ sint32 ScoreStackTrace(OSThread_t* thread, MPTR sp)
return score; return score;
} }
void DebugLogStackTrace(OSThread_t* thread, MPTR sp) void DebugLogStackTrace(OSThread_t* thread, MPTR sp, bool printSymbols)
{ {
// sp might not point to a valid stackframe // sp might not point to a valid stackframe
// scan stack and evaluate which sp is most likely the beginning of the stackframe // scan stack and evaluate which sp is most likely the beginning of the stackframe
@ -107,7 +107,15 @@ void DebugLogStackTrace(OSThread_t* thread, MPTR sp)
uint32 returnAddress = 0; uint32 returnAddress = 0;
returnAddress = memory_readU32(nextStackPtr + 4); returnAddress = memory_readU32(nextStackPtr + 4);
cemuLog_log(LogType::Force, fmt::format("SP {0:08x} ReturnAddr {1:08x}", nextStackPtr, returnAddress));
RPLStoredSymbol* symbol = nullptr;
if(printSymbols)
symbol = rplSymbolStorage_getByClosestAddress(returnAddress);
if(symbol)
cemuLog_log(LogType::Force, fmt::format("SP {:08x} ReturnAddr {:08x} ({}.{}+0x{:x})", nextStackPtr, returnAddress, (const char*)symbol->libName, (const char*)symbol->symbolName, returnAddress - symbol->address));
else
cemuLog_log(LogType::Force, fmt::format("SP {:08x} ReturnAddr {:08x}", nextStackPtr, returnAddress));
currentStackPtr = nextStackPtr; currentStackPtr = nextStackPtr;
} }

View File

@ -2,8 +2,6 @@
#include "Cafe/HW/Espresso/PPCCallback.h" #include "Cafe/HW/Espresso/PPCCallback.h"
#include "Cafe/OS/libs/coreinit/coreinit_MEM_ExpHeap.h" #include "Cafe/OS/libs/coreinit/coreinit_MEM_ExpHeap.h"
void DebugLogStackTrace(OSThread_t* thread, MPTR sp);
#define EXP_HEAP_GET_FROM_FREE_BLOCKCHAIN(__blockchain__) (MEMExpHeapHead2*)((uintptr_t)__blockchain__ - offsetof(MEMExpHeapHead2, expHeapHead) - offsetof(MEMExpHeapHead40_t, chainFreeBlocks)) #define EXP_HEAP_GET_FROM_FREE_BLOCKCHAIN(__blockchain__) (MEMExpHeapHead2*)((uintptr_t)__blockchain__ - offsetof(MEMExpHeapHead2, expHeapHead) - offsetof(MEMExpHeapHead40_t, chainFreeBlocks))
namespace coreinit namespace coreinit

View File

@ -7,14 +7,9 @@
namespace coreinit namespace coreinit
{ {
sint32 ppc_vprintf(const char* formatStr, char* strOut, sint32 maxLength, ppc_va_list* vargs)
/* coreinit logging and string format */
sint32 ppcSprintf(const char* formatStr, char* strOut, sint32 maxLength, PPCInterpreter_t* hCPU, sint32 initialParamIndex)
{ {
char tempStr[4096]; char tempStr[4096];
sint32 integerParamIndex = initialParamIndex;
sint32 floatParamIndex = 0;
sint32 writeIndex = 0; sint32 writeIndex = 0;
while (*formatStr) while (*formatStr)
{ {
@ -101,8 +96,7 @@ namespace coreinit
tempFormat[(formatStr - formatStart)] = '\0'; tempFormat[(formatStr - formatStart)] = '\0';
else else
tempFormat[sizeof(tempFormat) - 1] = '\0'; tempFormat[sizeof(tempFormat) - 1] = '\0';
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU32(hCPU, integerParamIndex)); sint32 tempLen = sprintf(tempStr, tempFormat, (uint32)*(uint32be*)_ppc_va_arg(vargs, ppc_va_type::INT32));
integerParamIndex++;
for (sint32 i = 0; i < tempLen; i++) for (sint32 i = 0; i < tempLen; i++)
{ {
if (writeIndex >= maxLength) if (writeIndex >= maxLength)
@ -120,13 +114,12 @@ namespace coreinit
tempFormat[(formatStr - formatStart)] = '\0'; tempFormat[(formatStr - formatStart)] = '\0';
else else
tempFormat[sizeof(tempFormat) - 1] = '\0'; tempFormat[sizeof(tempFormat) - 1] = '\0';
MPTR strOffset = PPCInterpreter_getCallParamU32(hCPU, integerParamIndex); MPTR strOffset = *(uint32be*)_ppc_va_arg(vargs, ppc_va_type::INT32);
sint32 tempLen = 0; sint32 tempLen = 0;
if (strOffset == MPTR_NULL) if (strOffset == MPTR_NULL)
tempLen = sprintf(tempStr, "NULL"); tempLen = sprintf(tempStr, "NULL");
else else
tempLen = sprintf(tempStr, tempFormat, memory_getPointerFromVirtualOffset(strOffset)); tempLen = sprintf(tempStr, tempFormat, memory_getPointerFromVirtualOffset(strOffset));
integerParamIndex++;
for (sint32 i = 0; i < tempLen; i++) for (sint32 i = 0; i < tempLen; i++)
{ {
if (writeIndex >= maxLength) if (writeIndex >= maxLength)
@ -136,25 +129,6 @@ namespace coreinit
} }
strOut[std::min(maxLength - 1, writeIndex)] = '\0'; strOut[std::min(maxLength - 1, writeIndex)] = '\0';
} }
else if (*formatStr == 'f')
{
// float
formatStr++;
strncpy(tempFormat, formatStart, std::min((std::ptrdiff_t)sizeof(tempFormat) - 1, formatStr - formatStart));
if ((formatStr - formatStart) < sizeof(tempFormat))
tempFormat[(formatStr - formatStart)] = '\0';
else
tempFormat[sizeof(tempFormat) - 1] = '\0';
sint32 tempLen = sprintf(tempStr, tempFormat, (float)hCPU->fpr[1 + floatParamIndex].fp0);
floatParamIndex++;
for (sint32 i = 0; i < tempLen; i++)
{
if (writeIndex >= maxLength)
break;
strOut[writeIndex] = tempStr[i];
writeIndex++;
}
}
else if (*formatStr == 'c') else if (*formatStr == 'c')
{ {
// character // character
@ -164,8 +138,24 @@ namespace coreinit
tempFormat[(formatStr - formatStart)] = '\0'; tempFormat[(formatStr - formatStart)] = '\0';
else else
tempFormat[sizeof(tempFormat) - 1] = '\0'; tempFormat[sizeof(tempFormat) - 1] = '\0';
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU32(hCPU, integerParamIndex)); sint32 tempLen = sprintf(tempStr, tempFormat, (uint32)*(uint32be*)_ppc_va_arg(vargs, ppc_va_type::INT32));
integerParamIndex++; for (sint32 i = 0; i < tempLen; i++)
{
if (writeIndex >= maxLength)
break;
strOut[writeIndex] = tempStr[i];
writeIndex++;
}
}
else if (*formatStr == 'f' || *formatStr == 'g' || *formatStr == 'G')
{
formatStr++;
strncpy(tempFormat, formatStart, std::min((std::ptrdiff_t)sizeof(tempFormat) - 1, formatStr - formatStart));
if ((formatStr - formatStart) < sizeof(tempFormat))
tempFormat[(formatStr - formatStart)] = '\0';
else
tempFormat[sizeof(tempFormat) - 1] = '\0';
sint32 tempLen = sprintf(tempStr, tempFormat, (double)*(betype<double>*)_ppc_va_arg(vargs, ppc_va_type::FLOAT_OR_DOUBLE));
for (sint32 i = 0; i < tempLen; i++) for (sint32 i = 0; i < tempLen; i++)
{ {
if (writeIndex >= maxLength) if (writeIndex >= maxLength)
@ -183,8 +173,7 @@ namespace coreinit
tempFormat[(formatStr - formatStart)] = '\0'; tempFormat[(formatStr - formatStart)] = '\0';
else else
tempFormat[sizeof(tempFormat) - 1] = '\0'; tempFormat[sizeof(tempFormat) - 1] = '\0';
sint32 tempLen = sprintf(tempStr, tempFormat, (double)hCPU->fpr[1 + floatParamIndex].fp0); sint32 tempLen = sprintf(tempStr, tempFormat, (double)*(betype<double>*)_ppc_va_arg(vargs, ppc_va_type::FLOAT_OR_DOUBLE));
floatParamIndex++;
for (sint32 i = 0; i < tempLen; i++) for (sint32 i = 0; i < tempLen; i++)
{ {
if (writeIndex >= maxLength) if (writeIndex >= maxLength)
@ -196,16 +185,13 @@ namespace coreinit
else if ((formatStr[0] == 'l' && formatStr[1] == 'l' && (formatStr[2] == 'x' || formatStr[2] == 'X'))) else if ((formatStr[0] == 'l' && formatStr[1] == 'l' && (formatStr[2] == 'x' || formatStr[2] == 'X')))
{ {
formatStr += 3; formatStr += 3;
// double (64bit) // 64bit int
strncpy(tempFormat, formatStart, std::min((std::ptrdiff_t)sizeof(tempFormat) - 1, formatStr - formatStart)); strncpy(tempFormat, formatStart, std::min((std::ptrdiff_t)sizeof(tempFormat) - 1, formatStr - formatStart));
if ((formatStr - formatStart) < sizeof(tempFormat)) if ((formatStr - formatStart) < sizeof(tempFormat))
tempFormat[(formatStr - formatStart)] = '\0'; tempFormat[(formatStr - formatStart)] = '\0';
else else
tempFormat[sizeof(tempFormat) - 1] = '\0'; tempFormat[sizeof(tempFormat) - 1] = '\0';
if (integerParamIndex & 1) sint32 tempLen = sprintf(tempStr, tempFormat, (uint64)*(uint64be*)_ppc_va_arg(vargs, ppc_va_type::INT64));
integerParamIndex++;
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU64(hCPU, integerParamIndex));
integerParamIndex += 2;
for (sint32 i = 0; i < tempLen; i++) for (sint32 i = 0; i < tempLen; i++)
{ {
if (writeIndex >= maxLength) if (writeIndex >= maxLength)
@ -223,10 +209,7 @@ namespace coreinit
tempFormat[(formatStr - formatStart)] = '\0'; tempFormat[(formatStr - formatStart)] = '\0';
else else
tempFormat[sizeof(tempFormat) - 1] = '\0'; tempFormat[sizeof(tempFormat) - 1] = '\0';
if (integerParamIndex & 1) sint32 tempLen = sprintf(tempStr, tempFormat, (sint64)*(sint64be*)_ppc_va_arg(vargs, ppc_va_type::INT64));
integerParamIndex++;
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU64(hCPU, integerParamIndex));
integerParamIndex += 2;
for (sint32 i = 0; i < tempLen; i++) for (sint32 i = 0; i < tempLen; i++)
{ {
if (writeIndex >= maxLength) if (writeIndex >= maxLength)
@ -255,9 +238,12 @@ namespace coreinit
return std::min(writeIndex, maxLength - 1); return std::min(writeIndex, maxLength - 1);
} }
/* coreinit logging and string format */
sint32 __os_snprintf(char* outputStr, sint32 maxLength, const char* formatStr) sint32 __os_snprintf(char* outputStr, sint32 maxLength, const char* formatStr)
{ {
sint32 r = ppcSprintf(formatStr, outputStr, maxLength, PPCInterpreter_getCurrentInstance(), 3); ppc_define_va_list(3, 0);
sint32 r = ppc_vprintf(formatStr, outputStr, maxLength, &vargs);
return r; return r;
} }
@ -322,32 +308,40 @@ namespace coreinit
} }
} }
void OSReport(const char* format) void COSVReport(COSReportModule module, COSReportLevel level, const char* format, ppc_va_list* vargs)
{ {
char buffer[1024 * 2]; char tmpBuffer[1024];
sint32 len = ppcSprintf(format, buffer, sizeof(buffer), PPCInterpreter_getCurrentInstance(), 1); sint32 len = ppc_vprintf(format, tmpBuffer, sizeof(tmpBuffer), vargs);
WriteCafeConsole(CafeLogType::OSCONSOLE, buffer, len); WriteCafeConsole(CafeLogType::OSCONSOLE, tmpBuffer, len);
} }
void OSVReport(const char* format, MPTR vaArgs) void OSReport(const char* format)
{ {
cemu_assert_unimplemented(); ppc_define_va_list(1, 0);
COSVReport(COSReportModule::coreinit, COSReportLevel::Info, format, &vargs);
}
void OSVReport(const char* format, ppc_va_list* vargs)
{
COSVReport(COSReportModule::coreinit, COSReportLevel::Info, format, vargs);
} }
void COSWarn(int moduleId, const char* format) void COSWarn(int moduleId, const char* format)
{ {
char buffer[1024 * 2]; ppc_define_va_list(2, 0);
int prefixLen = sprintf(buffer, "[COSWarn-%d] ", moduleId); char tmpBuffer[1024];
sint32 len = ppcSprintf(format, buffer + prefixLen, sizeof(buffer) - prefixLen, PPCInterpreter_getCurrentInstance(), 2); int prefixLen = sprintf(tmpBuffer, "[COSWarn-%d] ", moduleId);
WriteCafeConsole(CafeLogType::OSCONSOLE, buffer, len + prefixLen); sint32 len = ppc_vprintf(format, tmpBuffer + prefixLen, sizeof(tmpBuffer) - prefixLen, &vargs);
WriteCafeConsole(CafeLogType::OSCONSOLE, tmpBuffer, len + prefixLen);
} }
void OSLogPrintf(int ukn1, int ukn2, int ukn3, const char* format) void OSLogPrintf(int ukn1, int ukn2, int ukn3, const char* format)
{ {
char buffer[1024 * 2]; ppc_define_va_list(4, 0);
int prefixLen = sprintf(buffer, "[OSLogPrintf-%d-%d-%d] ", ukn1, ukn2, ukn3); char tmpBuffer[1024];
sint32 len = ppcSprintf(format, buffer + prefixLen, sizeof(buffer) - prefixLen, PPCInterpreter_getCurrentInstance(), 4); int prefixLen = sprintf(tmpBuffer, "[OSLogPrintf-%d-%d-%d] ", ukn1, ukn2, ukn3);
WriteCafeConsole(CafeLogType::OSCONSOLE, buffer, len + prefixLen); sint32 len = ppc_vprintf(format, tmpBuffer + prefixLen, sizeof(tmpBuffer) - prefixLen, &vargs);
WriteCafeConsole(CafeLogType::OSCONSOLE, tmpBuffer, len + prefixLen);
} }
void OSConsoleWrite(const char* strPtr, sint32 length) void OSConsoleWrite(const char* strPtr, sint32 length)
@ -562,9 +556,11 @@ namespace coreinit
s_transitionToForeground = false; s_transitionToForeground = false;
cafeExportRegister("coreinit", __os_snprintf, LogType::Placeholder); cafeExportRegister("coreinit", __os_snprintf, LogType::Placeholder);
cafeExportRegister("coreinit", COSVReport, LogType::Placeholder);
cafeExportRegister("coreinit", COSWarn, LogType::Placeholder);
cafeExportRegister("coreinit", OSReport, LogType::Placeholder); cafeExportRegister("coreinit", OSReport, LogType::Placeholder);
cafeExportRegister("coreinit", OSVReport, LogType::Placeholder); cafeExportRegister("coreinit", OSVReport, LogType::Placeholder);
cafeExportRegister("coreinit", COSWarn, LogType::Placeholder);
cafeExportRegister("coreinit", OSLogPrintf, LogType::Placeholder); cafeExportRegister("coreinit", OSLogPrintf, LogType::Placeholder);
cafeExportRegister("coreinit", OSConsoleWrite, LogType::Placeholder); cafeExportRegister("coreinit", OSConsoleWrite, LogType::Placeholder);

View File

@ -26,5 +26,19 @@ namespace coreinit
uint32 OSDriver_Register(uint32 moduleHandle, sint32 priority, OSDriverInterface* driverCallbacks, sint32 driverId, uint32be* outUkn1, uint32be* outUkn2, uint32be* outUkn3); uint32 OSDriver_Register(uint32 moduleHandle, sint32 priority, OSDriverInterface* driverCallbacks, sint32 driverId, uint32be* outUkn1, uint32be* outUkn2, uint32be* outUkn3);
uint32 OSDriver_Deregister(uint32 moduleHandle, sint32 driverId); uint32 OSDriver_Deregister(uint32 moduleHandle, sint32 driverId);
enum class COSReportModule
{
coreinit = 0,
};
enum class COSReportLevel
{
Error = 0,
Warn = 1,
Info = 2
};
sint32 ppc_vprintf(const char* formatStr, char* strOut, sint32 maxLength, ppc_va_list* vargs);
void miscInit(); void miscInit();
}; };

View File

@ -140,7 +140,7 @@ namespace coreinit
// we are in single-core mode and the lock will never be released unless we let other threads resume work // we are in single-core mode and the lock will never be released unless we let other threads resume work
// to avoid an infinite loop we have no choice but to yield the thread even it is in an uninterruptible state // to avoid an infinite loop we have no choice but to yield the thread even it is in an uninterruptible state
if( !OSIsInterruptEnabled() ) if( !OSIsInterruptEnabled() )
cemuLog_log(LogType::APIErrors, "OSUninterruptibleSpinLock_Acquire(): Lock is occupied which requires a wait but current thread is already in an uninterruptible state (Avoid cascaded OSDisableInterrupts and/or OSUninterruptibleSpinLock)"); cemuLog_logOnce(LogType::APIErrors, "OSUninterruptibleSpinLock_Acquire(): Lock is occupied which requires a wait but current thread is already in an uninterruptible state (Avoid cascaded OSDisableInterrupts and/or OSUninterruptibleSpinLock)");
while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread)) while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread))
{ {
OSYieldThread(); OSYieldThread();

View File

@ -310,7 +310,7 @@ namespace coreinit
currentThread->mutexQueue.removeMutex(mutex); currentThread->mutexQueue.removeMutex(mutex);
mutex->owner = nullptr; mutex->owner = nullptr;
if (!mutex->threadQueue.isEmpty()) if (!mutex->threadQueue.isEmpty())
mutex->threadQueue.wakeupSingleThreadWaitQueue(true); mutex->threadQueue.wakeupSingleThreadWaitQueue(true, true);
} }
// currentThread->cancelState = currentThread->cancelState & ~0x10000; // currentThread->cancelState = currentThread->cancelState & ~0x10000;
} }

View File

@ -14,13 +14,10 @@ namespace coreinit
return coreinit::MEMAllocFromExpHeapEx(_sysHeapHandle, size, alignment); return coreinit::MEMAllocFromExpHeapEx(_sysHeapHandle, size, alignment);
} }
void export_OSAllocFromSystem(PPCInterpreter_t* hCPU) void OSFreeToSystem(void* ptr)
{ {
ppcDefineParamU32(size, 0); _sysHeapFreeCounter++;
ppcDefineParamS32(alignment, 1); coreinit::MEMFreeToExpHeap(_sysHeapHandle, ptr);
MEMPTR<void> mem = OSAllocFromSystem(size, alignment);
cemuLog_logDebug(LogType::Force, "OSAllocFromSystem(0x{:x}, {}) -> 0x{:08x}", size, alignment, mem.GetMPTR());
osLib_returnFromFunction(hCPU, mem.GetMPTR());
} }
void InitSysHeap() void InitSysHeap()
@ -34,7 +31,8 @@ namespace coreinit
void InitializeSysHeap() void InitializeSysHeap()
{ {
osLib_addFunction("coreinit", "OSAllocFromSystem", export_OSAllocFromSystem); cafeExportRegister("h264", OSAllocFromSystem, LogType::CoreinitMem);
cafeExportRegister("h264", OSFreeToSystem, LogType::CoreinitMem);
} }
} }

View File

@ -4,5 +4,8 @@ namespace coreinit
{ {
void InitSysHeap(); void InitSysHeap();
void* OSAllocFromSystem(uint32 size, uint32 alignment);
void OSFreeToSystem(void* ptr);
void InitializeSysHeap(); void InitializeSysHeap();
} }

View File

@ -758,14 +758,14 @@ namespace coreinit
} }
// returns true if thread runs on same core and has higher priority // returns true if thread runs on same core and has higher priority
bool __OSCoreShouldSwitchToThread(OSThread_t* currentThread, OSThread_t* newThread) bool __OSCoreShouldSwitchToThread(OSThread_t* currentThread, OSThread_t* newThread, bool sharedPriorityAndAffinityWorkaround)
{ {
uint32 coreIndex = OSGetCoreId(); uint32 coreIndex = OSGetCoreId();
if (!newThread->context.hasCoreAffinitySet(coreIndex)) if (!newThread->context.hasCoreAffinitySet(coreIndex))
return false; return false;
// special case: if current and new thread are running only on the same core then reschedule even if priority is equal // special case: if current and new thread are running only on the same core then reschedule even if priority is equal
// this resolves a deadlock in Just Dance 2019 where one thread would always reacquire the same mutex within it's timeslice, blocking another thread on the same core from acquiring it // this resolves a deadlock in Just Dance 2019 where one thread would always reacquire the same mutex within it's timeslice, blocking another thread on the same core from acquiring it
if ((1<<coreIndex) == newThread->context.affinity && currentThread->context.affinity == newThread->context.affinity && currentThread->effectivePriority == newThread->effectivePriority) if (sharedPriorityAndAffinityWorkaround && (1<<coreIndex) == newThread->context.affinity && currentThread->context.affinity == newThread->context.affinity && currentThread->effectivePriority == newThread->effectivePriority)
return true; return true;
// otherwise reschedule if new thread has higher priority // otherwise reschedule if new thread has higher priority
return newThread->effectivePriority < currentThread->effectivePriority; return newThread->effectivePriority < currentThread->effectivePriority;
@ -791,7 +791,7 @@ namespace coreinit
// todo - only set this once? // todo - only set this once?
thread->wakeUpTime = PPCInterpreter_getMainCoreCycleCounter(); thread->wakeUpTime = PPCInterpreter_getMainCoreCycleCounter();
// reschedule if thread has higher priority // reschedule if thread has higher priority
if (PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread)) if (PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread, false))
PPCCore_switchToSchedulerWithLock(); PPCCore_switchToSchedulerWithLock();
} }
return previousSuspendCount; return previousSuspendCount;
@ -948,7 +948,7 @@ namespace coreinit
OSThread_t* currentThread = OSGetCurrentThread(); OSThread_t* currentThread = OSGetCurrentThread();
if (currentThread && currentThread != thread) if (currentThread && currentThread != thread)
{ {
if (__OSCoreShouldSwitchToThread(currentThread, thread)) if (__OSCoreShouldSwitchToThread(currentThread, thread, false))
PPCCore_switchToSchedulerWithLock(); PPCCore_switchToSchedulerWithLock();
} }
__OSUnlockScheduler(); __OSUnlockScheduler();
@ -1608,21 +1608,3 @@ namespace coreinit
} }
} }
void coreinit_suspendThread(OSThread_t* OSThreadBE, sint32 count)
{
// for legacy source
OSThreadBE->suspendCounter += count;
}
void coreinit_resumeThread(OSThread_t* OSThreadBE, sint32 count)
{
__OSLockScheduler();
coreinit::__OSResumeThreadInternal(OSThreadBE, count);
__OSUnlockScheduler();
}
OSThread_t* coreinitThread_getCurrentThreadDepr(PPCInterpreter_t* hCPU)
{
return coreinit::__currentCoreThread[PPCInterpreter_getCoreIndex(hCPU)];
}

View File

@ -126,8 +126,8 @@ namespace coreinit
// counterparts for queueAndWait // counterparts for queueAndWait
void cancelWait(OSThread_t* thread); void cancelWait(OSThread_t* thread);
void wakeupEntireWaitQueue(bool reschedule); void wakeupEntireWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround = false);
void wakeupSingleThreadWaitQueue(bool reschedule); void wakeupSingleThreadWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround = false);
private: private:
OSThread_t* takeFirstFromQueue(size_t linkOffset) OSThread_t* takeFirstFromQueue(size_t linkOffset)
@ -611,7 +611,7 @@ namespace coreinit
// internal // internal
void __OSAddReadyThreadToRunQueue(OSThread_t* thread); void __OSAddReadyThreadToRunQueue(OSThread_t* thread);
bool __OSCoreShouldSwitchToThread(OSThread_t* currentThread, OSThread_t* newThread); bool __OSCoreShouldSwitchToThread(OSThread_t* currentThread, OSThread_t* newThread, bool sharedPriorityAndAffinityWorkaround);
void __OSQueueThreadDeallocation(OSThread_t* thread); void __OSQueueThreadDeallocation(OSThread_t* thread);
bool __OSIsThreadActive(OSThread_t* thread); bool __OSIsThreadActive(OSThread_t* thread);
@ -621,11 +621,6 @@ namespace coreinit
#pragma pack() #pragma pack()
// deprecated / clean up required // deprecated / clean up required
void coreinit_suspendThread(OSThread_t* OSThreadBE, sint32 count = 1);
void coreinit_resumeThread(OSThread_t* OSThreadBE, sint32 count = 1);
OSThread_t* coreinitThread_getCurrentThreadDepr(PPCInterpreter_t* hCPU);
extern MPTR activeThread[256]; extern MPTR activeThread[256];
extern sint32 activeThreadCount; extern sint32 activeThreadCount;

View File

@ -128,7 +128,8 @@ namespace coreinit
// counterpart for queueAndWait // counterpart for queueAndWait
// if reschedule is true then scheduler will switch to woken up thread (if it is runnable on the same core) // if reschedule is true then scheduler will switch to woken up thread (if it is runnable on the same core)
void OSThreadQueueInternal::wakeupEntireWaitQueue(bool reschedule) // sharedPriorityAndAffinityWorkaround is currently a hack/placeholder for some special cases. A proper fix likely involves handling all the nuances of thread effective priority
void OSThreadQueueInternal::wakeupEntireWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround)
{ {
cemu_assert_debug(__OSHasSchedulerLock()); cemu_assert_debug(__OSHasSchedulerLock());
bool shouldReschedule = false; bool shouldReschedule = false;
@ -139,7 +140,7 @@ namespace coreinit
thread->state = OSThread_t::THREAD_STATE::STATE_READY; thread->state = OSThread_t::THREAD_STATE::STATE_READY;
thread->currentWaitQueue = nullptr; thread->currentWaitQueue = nullptr;
coreinit::__OSAddReadyThreadToRunQueue(thread); coreinit::__OSAddReadyThreadToRunQueue(thread);
if (reschedule && thread->suspendCounter == 0 && PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread)) if (reschedule && thread->suspendCounter == 0 && PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread, sharedPriorityAndAffinityWorkaround))
shouldReschedule = true; shouldReschedule = true;
} }
if (shouldReschedule) if (shouldReschedule)
@ -148,7 +149,7 @@ namespace coreinit
// counterpart for queueAndWait // counterpart for queueAndWait
// if reschedule is true then scheduler will switch to woken up thread (if it is runnable on the same core) // if reschedule is true then scheduler will switch to woken up thread (if it is runnable on the same core)
void OSThreadQueueInternal::wakeupSingleThreadWaitQueue(bool reschedule) void OSThreadQueueInternal::wakeupSingleThreadWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround)
{ {
cemu_assert_debug(__OSHasSchedulerLock()); cemu_assert_debug(__OSHasSchedulerLock());
OSThread_t* thread = takeFirstFromQueue(offsetof(OSThread_t, waitQueueLink)); OSThread_t* thread = takeFirstFromQueue(offsetof(OSThread_t, waitQueueLink));
@ -159,7 +160,7 @@ namespace coreinit
thread->state = OSThread_t::THREAD_STATE::STATE_READY; thread->state = OSThread_t::THREAD_STATE::STATE_READY;
thread->currentWaitQueue = nullptr; thread->currentWaitQueue = nullptr;
coreinit::__OSAddReadyThreadToRunQueue(thread); coreinit::__OSAddReadyThreadToRunQueue(thread);
if (reschedule && thread->suspendCounter == 0 && PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread)) if (reschedule && thread->suspendCounter == 0 && PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread, sharedPriorityAndAffinityWorkaround))
shouldReschedule = true; shouldReschedule = true;
} }
if (shouldReschedule) if (shouldReschedule)

View File

@ -154,14 +154,6 @@ namespace GX2
return gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL; return gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL;
} }
bool GX2WriteGather_isDisplayListActive()
{
uint32 coreIndex = coreinit::OSGetCoreId();
if (gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL)
return true;
return false;
}
uint32 GX2WriteGather_getReadWriteDistance() uint32 GX2WriteGather_getReadWriteDistance()
{ {
uint32 coreIndex = sGX2MainCoreIndex; uint32 coreIndex = sGX2MainCoreIndex;

View File

@ -84,8 +84,6 @@ inline void gx2WriteGather_submit(Targs... args)
namespace GX2 namespace GX2
{ {
bool GX2WriteGather_isDisplayListActive();
uint32 GX2WriteGather_getReadWriteDistance(); uint32 GX2WriteGather_getReadWriteDistance();
void GX2WriteGather_checkAndInsertWrapAroundMark(); void GX2WriteGather_checkAndInsertWrapAroundMark();
@ -96,6 +94,8 @@ namespace GX2
void GX2CallDisplayList(MPTR addr, uint32 size); void GX2CallDisplayList(MPTR addr, uint32 size);
void GX2DirectCallDisplayList(void* addr, uint32 size); void GX2DirectCallDisplayList(void* addr, uint32 size);
bool GX2GetDisplayListWriteStatus();
void GX2Init_writeGather(); void GX2Init_writeGather();
void GX2CommandInit(); void GX2CommandInit();
void GX2CommandResetToDefaultState(); void GX2CommandResetToDefaultState();

View File

@ -291,8 +291,7 @@ void gx2Export_GX2SetDefaultState(PPCInterpreter_t* hCPU)
void _GX2ContextCreateRestoreStateDL(GX2ContextState_t* gx2ContextState) void _GX2ContextCreateRestoreStateDL(GX2ContextState_t* gx2ContextState)
{ {
// begin display list // begin display list
if (GX2::GX2WriteGather_isDisplayListActive()) cemu_assert_debug(!GX2::GX2GetDisplayListWriteStatus()); // must not already be writing to a display list
assert_dbg();
GX2::GX2BeginDisplayList((void*)gx2ContextState->loadDL_buffer, sizeof(gx2ContextState->loadDL_buffer)); GX2::GX2BeginDisplayList((void*)gx2ContextState->loadDL_buffer, sizeof(gx2ContextState->loadDL_buffer));
_GX2Context_WriteCmdRestoreState(gx2ContextState, 0); _GX2Context_WriteCmdRestoreState(gx2ContextState, 0);
uint32 displayListSize = GX2::GX2EndDisplayList((void*)gx2ContextState->loadDL_buffer); uint32 displayListSize = GX2::GX2EndDisplayList((void*)gx2ContextState->loadDL_buffer);

View File

@ -426,7 +426,7 @@ namespace GX2
} }
if((aluRegisterOffset+sizeInU32s) > 0x400) if((aluRegisterOffset+sizeInU32s) > 0x400)
{ {
cemuLog_logOnce(LogType::APIErrors, "GX2SetVertexUniformReg values are out of range (offset {} + size {} must be equal or smaller than 0x400)", aluRegisterOffset, sizeInU32s); cemuLog_logOnce(LogType::APIErrors, "GX2SetVertexUniformReg values are out of range (offset {} + size {} must be equal or smaller than 1024)", aluRegisterOffset, sizeInU32s);
} }
if( (sizeInU32s&3) != 0) if( (sizeInU32s&3) != 0)
{ {

View File

@ -1,17 +1,12 @@
#include "Cafe/OS/common/OSCommon.h" #include "Cafe/OS/common/OSCommon.h"
#include "Cafe/HW/Espresso/PPCCallback.h" #include "Cafe/HW/Espresso/PPCCallback.h"
#include "Cafe/OS/libs/h264_avc/parser/H264Parser.h" #include "Cafe/OS/libs/h264_avc/parser/H264Parser.h"
#include "Cafe/OS/libs/h264_avc/H264DecInternal.h"
#include "util/highresolutiontimer/HighResolutionTimer.h" #include "util/highresolutiontimer/HighResolutionTimer.h"
#include "Cafe/CafeSystem.h" #include "Cafe/CafeSystem.h"
#include "h264dec.h" #include "h264dec.h"
extern "C"
{
#include "../dependencies/ih264d/common/ih264_typedefs.h"
#include "../dependencies/ih264d/decoder/ih264d.h"
};
enum class H264DEC_STATUS : uint32 enum class H264DEC_STATUS : uint32
{ {
SUCCESS = 0x0, SUCCESS = 0x0,
@ -33,10 +28,35 @@ namespace H264
return false; return false;
} }
struct H264Context
{
struct
{
MEMPTR<void> ptr{ nullptr };
uint32be length{ 0 };
float64be timestamp;
}BitStream;
struct
{
MEMPTR<void> outputFunc{ nullptr };
uint8be outputPerFrame{ 0 }; // whats the default?
MEMPTR<void> userMemoryParam{ nullptr };
}Param;
// misc
uint32be sessionHandle;
// decoder state
struct
{
uint32 numFramesInFlight{0};
}decoderState;
};
uint32 H264DECMemoryRequirement(uint32 codecProfile, uint32 codecLevel, uint32 width, uint32 height, uint32be* sizeRequirementOut) uint32 H264DECMemoryRequirement(uint32 codecProfile, uint32 codecLevel, uint32 width, uint32 height, uint32be* sizeRequirementOut)
{ {
if (H264_IsBotW()) if (H264_IsBotW())
{ {
static_assert(sizeof(H264Context) < 256);
*sizeRequirementOut = 256; *sizeRequirementOut = 256;
return 0; return 0;
} }
@ -169,590 +189,47 @@ namespace H264
return H264DEC_STATUS::BAD_STREAM; return H264DEC_STATUS::BAD_STREAM;
} }
struct H264Context
{
struct
{
MEMPTR<void> ptr{ nullptr };
uint32be length{ 0 };
float64be timestamp;
}BitStream;
struct
{
MEMPTR<void> outputFunc{ nullptr };
uint8be outputPerFrame{ 0 }; // whats the default?
MEMPTR<void> userMemoryParam{ nullptr };
}Param;
// misc
uint32be sessionHandle;
};
class H264AVCDecoder
{
static void* ivd_aligned_malloc(void* ctxt, WORD32 alignment, WORD32 size)
{
#ifdef _WIN32
return _aligned_malloc(size, alignment);
#else
// alignment is atleast sizeof(void*)
alignment = std::max<WORD32>(alignment, sizeof(void*));
//smallest multiple of 2 at least as large as alignment
alignment--;
alignment |= alignment << 1;
alignment |= alignment >> 1;
alignment |= alignment >> 2;
alignment |= alignment >> 4;
alignment |= alignment >> 8;
alignment |= alignment >> 16;
alignment ^= (alignment >> 1);
void* temp;
posix_memalign(&temp, (size_t)alignment, (size_t)size);
return temp;
#endif
}
static void ivd_aligned_free(void* ctxt, void* buf)
{
#ifdef _WIN32
_aligned_free(buf);
#else
free(buf);
#endif
return;
}
public:
struct DecodeResult
{
bool frameReady{ false };
double timestamp;
void* imageOutput;
ivd_video_decode_op_t decodeOutput;
};
void Init(bool isBufferedMode)
{
ih264d_create_ip_t s_create_ip{ 0 };
ih264d_create_op_t s_create_op{ 0 };
s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ih264d_create_ip_t);
s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 1; // shared display buffer mode -> We give the decoder a list of buffers that it will use (?)
s_create_op.s_ivd_create_op_t.u4_size = sizeof(ih264d_create_op_t);
s_create_ip.s_ivd_create_ip_t.e_output_format = IV_YUV_420SP_UV;
s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
WORD32 status = ih264d_api_function(m_codecCtx, &s_create_ip, &s_create_op);
cemu_assert(!status);
m_codecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
m_codecCtx->pv_fxns = (void*)&ih264d_api_function;
m_codecCtx->u4_size = sizeof(iv_obj_t);
SetDecoderCoreCount(1);
m_isBufferedMode = isBufferedMode;
UpdateParameters(false);
m_bufferedResults.clear();
m_numDecodedFrames = 0;
m_hasBufferSizeInfo = false;
m_timestampIndex = 0;
}
void Destroy()
{
if (!m_codecCtx)
return;
ih264d_delete_ip_t s_delete_ip{ 0 };
ih264d_delete_op_t s_delete_op{ 0 };
s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ih264d_delete_ip_t);
s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ih264d_delete_op_t);
WORD32 status = ih264d_api_function(m_codecCtx, &s_delete_ip, &s_delete_op);
cemu_assert_debug(!status);
m_codecCtx = nullptr;
}
void SetDecoderCoreCount(uint32 coreCount)
{
ih264d_ctl_set_num_cores_ip_t s_set_cores_ip;
ih264d_ctl_set_num_cores_op_t s_set_cores_op;
s_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_set_cores_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES;
s_set_cores_ip.u4_num_cores = coreCount; // valid numbers are 1-4
s_set_cores_ip.u4_size = sizeof(ih264d_ctl_set_num_cores_ip_t);
s_set_cores_op.u4_size = sizeof(ih264d_ctl_set_num_cores_op_t);
IV_API_CALL_STATUS_T status = ih264d_api_function(m_codecCtx, (void *)&s_set_cores_ip, (void *)&s_set_cores_op);
cemu_assert(status == IV_SUCCESS);
}
static bool GetImageInfo(uint8* stream, uint32 length, uint32& imageWidth, uint32& imageHeight)
{
// create temporary decoder
ih264d_create_ip_t s_create_ip{ 0 };
ih264d_create_op_t s_create_op{ 0 };
s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ih264d_create_ip_t);
s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
s_create_op.s_ivd_create_op_t.u4_size = sizeof(ih264d_create_op_t);
s_create_ip.s_ivd_create_ip_t.e_output_format = IV_YUV_420SP_UV;
s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
iv_obj_t* ctx = nullptr;
WORD32 status = ih264d_api_function(ctx, &s_create_ip, &s_create_op);
cemu_assert_debug(!status);
if (status != IV_SUCCESS)
return false;
ctx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
ctx->pv_fxns = (void*)&ih264d_api_function;
ctx->u4_size = sizeof(iv_obj_t);
// set header-only mode
ih264d_ctl_set_config_ip_t s_h264d_ctl_ip{ 0 };
ih264d_ctl_set_config_op_t s_h264d_ctl_op{ 0 };
ivd_ctl_set_config_ip_t* ps_ctl_ip = &s_h264d_ctl_ip.s_ivd_ctl_set_config_ip_t;
ivd_ctl_set_config_op_t* ps_ctl_op = &s_h264d_ctl_op.s_ivd_ctl_set_config_op_t;
ps_ctl_ip->u4_disp_wd = 0;
ps_ctl_ip->e_frm_skip_mode = IVD_SKIP_NONE;
ps_ctl_ip->e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
ps_ctl_ip->e_vid_dec_mode = IVD_DECODE_HEADER;
ps_ctl_ip->e_cmd = IVD_CMD_VIDEO_CTL;
ps_ctl_ip->e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
ps_ctl_ip->u4_size = sizeof(ih264d_ctl_set_config_ip_t);
ps_ctl_op->u4_size = sizeof(ih264d_ctl_set_config_op_t);
status = ih264d_api_function(ctx, &s_h264d_ctl_ip, &s_h264d_ctl_op);
cemu_assert(!status);
// decode stream
ivd_video_decode_ip_t s_dec_ip{ 0 };
ivd_video_decode_op_t s_dec_op{ 0 };
s_dec_ip.u4_size = sizeof(ivd_video_decode_ip_t);
s_dec_op.u4_size = sizeof(ivd_video_decode_op_t);
s_dec_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
s_dec_ip.pv_stream_buffer = stream;
s_dec_ip.u4_num_Bytes = length;
s_dec_ip.s_out_buffer.u4_num_bufs = 0;
s_dec_op.u4_raw_wd = 0;
s_dec_op.u4_raw_ht = 0;
status = ih264d_api_function(ctx, &s_dec_ip, &s_dec_op);
//cemu_assert(status == 0); -> This errors when not both the headers are present, but it will still set the parameters we need
bool isValid = false;
if (true)//status == 0)
{
imageWidth = s_dec_op.u4_raw_wd;
imageHeight = s_dec_op.u4_raw_ht;
cemu_assert_debug(imageWidth != 0 && imageHeight != 0);
isValid = true;
}
// destroy decoder
ih264d_delete_ip_t s_delete_ip{ 0 };
ih264d_delete_op_t s_delete_op{ 0 };
s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ih264d_delete_ip_t);
s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ih264d_delete_op_t);
status = ih264d_api_function(ctx, &s_delete_ip, &s_delete_op);
cemu_assert_debug(!status);
return isValid;
}
void Decode(void* data, uint32 length, double timestamp, void* imageOutput, DecodeResult& decodeResult)
{
if (!m_hasBufferSizeInfo)
{
uint32 numByteConsumed = 0;
if (!DetermineBufferSizes(data, length, numByteConsumed))
{
cemuLog_log(LogType::Force, "H264: Unable to determine picture size. Ignoring decode input");
decodeResult.frameReady = false;
return;
}
length -= numByteConsumed;
data = (uint8*)data + numByteConsumed;
m_hasBufferSizeInfo = true;
}
ivd_video_decode_ip_t s_dec_ip{ 0 };
ivd_video_decode_op_t s_dec_op{ 0 };
s_dec_ip.u4_size = sizeof(ivd_video_decode_ip_t);
s_dec_op.u4_size = sizeof(ivd_video_decode_op_t);
s_dec_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
// remember timestamp and associated output buffer
m_timestamps[m_timestampIndex] = timestamp;
m_imageBuffers[m_timestampIndex] = imageOutput;
s_dec_ip.u4_ts = m_timestampIndex;
m_timestampIndex = (m_timestampIndex + 1) % 64;
s_dec_ip.pv_stream_buffer = (uint8*)data;
s_dec_ip.u4_num_Bytes = length;
s_dec_ip.s_out_buffer.u4_min_out_buf_size[0] = 0;
s_dec_ip.s_out_buffer.u4_min_out_buf_size[1] = 0;
s_dec_ip.s_out_buffer.u4_num_bufs = 0;
BenchmarkTimer bt;
bt.Start();
WORD32 status = ih264d_api_function(m_codecCtx, &s_dec_ip, &s_dec_op);
if (status != 0 && (s_dec_op.u4_error_code&0xFF) == IVD_RES_CHANGED)
{
// resolution change
ResetDecoder();
m_hasBufferSizeInfo = false;
Decode(data, length, timestamp, imageOutput, decodeResult);
return;
}
else if (status != 0)
{
cemuLog_log(LogType::Force, "H264: Failed to decode frame (error 0x{:08x})", status);
decodeResult.frameReady = false;
return;
}
bt.Stop();
double decodeTime = bt.GetElapsedMilliseconds();
cemu_assert(s_dec_op.u4_frame_decoded_flag);
cemu_assert_debug(s_dec_op.u4_num_bytes_consumed == length);
cemu_assert_debug(m_isBufferedMode || s_dec_op.u4_output_present); // if buffered mode is disabled, then every input should output a frame (except for partial slices?)
if (s_dec_op.u4_output_present)
{
cemu_assert(s_dec_op.e_output_format == IV_YUV_420SP_UV);
if (H264_IsBotW())
{
if (s_dec_op.s_disp_frm_buf.u4_y_wd == 1920 && s_dec_op.s_disp_frm_buf.u4_y_ht == 1088)
s_dec_op.s_disp_frm_buf.u4_y_ht = 1080;
}
DecodeResult tmpResult;
tmpResult.frameReady = s_dec_op.u4_output_present != 0;
tmpResult.timestamp = m_timestamps[s_dec_op.u4_ts];
tmpResult.imageOutput = m_imageBuffers[s_dec_op.u4_ts];
tmpResult.decodeOutput = s_dec_op;
AddBufferedResult(tmpResult);
// transfer image to PPC output buffer and also correct stride
bt.Start();
CopyImageToResultBuffer((uint8*)s_dec_op.s_disp_frm_buf.pv_y_buf, (uint8*)s_dec_op.s_disp_frm_buf.pv_u_buf, (uint8*)m_imageBuffers[s_dec_op.u4_ts], s_dec_op);
bt.Stop();
double copyTime = bt.GetElapsedMilliseconds();
// release buffer
sint32 bufferId = -1;
for (size_t i = 0; i < m_displayBuf.size(); i++)
{
if (s_dec_op.s_disp_frm_buf.pv_y_buf >= m_displayBuf[i].data() && s_dec_op.s_disp_frm_buf.pv_y_buf < (m_displayBuf[i].data() + m_displayBuf[i].size()))
{
bufferId = (sint32)i;
break;
}
}
cemu_assert_debug(bufferId == s_dec_op.u4_disp_buf_id);
cemu_assert(bufferId >= 0);
ivd_rel_display_frame_ip_t s_video_rel_disp_ip{ 0 };
ivd_rel_display_frame_op_t s_video_rel_disp_op{ 0 };
s_video_rel_disp_ip.e_cmd = IVD_CMD_REL_DISPLAY_FRAME;
s_video_rel_disp_ip.u4_size = sizeof(ivd_rel_display_frame_ip_t);
s_video_rel_disp_op.u4_size = sizeof(ivd_rel_display_frame_op_t);
s_video_rel_disp_ip.u4_disp_buf_id = bufferId;
status = ih264d_api_function(m_codecCtx, &s_video_rel_disp_ip, &s_video_rel_disp_op);
cemu_assert(!status);
cemuLog_log(LogType::H264, "H264Bench | DecodeTime {}ms CopyTime {}ms", decodeTime, copyTime);
}
else
{
cemuLog_log(LogType::H264, "H264Bench | DecodeTime{}ms", decodeTime);
}
if (s_dec_op.u4_frame_decoded_flag)
m_numDecodedFrames++;
if (m_isBufferedMode)
{
// in buffered mode, always buffer 5 frames regardless of actual reordering and decoder latency
if (m_numDecodedFrames > 5)
GetCurrentBufferedResult(decodeResult);
}
else if(m_numDecodedFrames > 0)
GetCurrentBufferedResult(decodeResult);
// get VUI
//ih264d_ctl_get_vui_params_ip_t s_ctl_get_vui_params_ip;
//ih264d_ctl_get_vui_params_op_t s_ctl_get_vui_params_op;
//s_ctl_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
//s_ctl_get_vui_params_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_GET_VUI_PARAMS;
//s_ctl_get_vui_params_ip.u4_size = sizeof(ih264d_ctl_get_vui_params_ip_t);
//s_ctl_get_vui_params_op.u4_size = sizeof(ih264d_ctl_get_vui_params_op_t);
//status = ih264d_api_function(mCodecCtx, &s_ctl_get_vui_params_ip, &s_ctl_get_vui_params_op);
//cemu_assert(status == 0);
}
std::vector<DecodeResult> Flush()
{
std::vector<DecodeResult> results;
// set flush mode
ivd_ctl_flush_ip_t s_video_flush_ip{ 0 };
ivd_ctl_flush_op_t s_video_flush_op{ 0 };
s_video_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_video_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH;
s_video_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
s_video_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t);
WORD32 status = ih264d_api_function(m_codecCtx, &s_video_flush_ip, &s_video_flush_op);
if (status != 0)
cemuLog_log(LogType::Force, "H264Dec: Unexpected error during flush ({})", status);
// get all frames from the codec
while (true)
{
ivd_video_decode_ip_t s_dec_ip{ 0 };
ivd_video_decode_op_t s_dec_op{ 0 };
s_dec_ip.u4_size = sizeof(ivd_video_decode_ip_t);
s_dec_op.u4_size = sizeof(ivd_video_decode_op_t);
s_dec_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
s_dec_ip.pv_stream_buffer = NULL;
s_dec_ip.u4_num_Bytes = 0;
s_dec_ip.s_out_buffer.u4_min_out_buf_size[0] = 0;
s_dec_ip.s_out_buffer.u4_min_out_buf_size[1] = 0;
s_dec_ip.s_out_buffer.u4_num_bufs = 0;
status = ih264d_api_function(m_codecCtx, &s_dec_ip, &s_dec_op);
if (status != 0)
break;
cemu_assert_debug(s_dec_op.u4_output_present != 0); // should never be zero?
if(s_dec_op.u4_output_present == 0)
continue;
if (H264_IsBotW())
{
if (s_dec_op.s_disp_frm_buf.u4_y_wd == 1920 && s_dec_op.s_disp_frm_buf.u4_y_ht == 1088)
s_dec_op.s_disp_frm_buf.u4_y_ht = 1080;
}
DecodeResult tmpResult;
tmpResult.frameReady = s_dec_op.u4_output_present != 0;
tmpResult.timestamp = m_timestamps[s_dec_op.u4_ts];
tmpResult.imageOutput = m_imageBuffers[s_dec_op.u4_ts];
tmpResult.decodeOutput = s_dec_op;
AddBufferedResult(tmpResult);
CopyImageToResultBuffer((uint8*)s_dec_op.s_disp_frm_buf.pv_y_buf, (uint8*)s_dec_op.s_disp_frm_buf.pv_u_buf, (uint8*)m_imageBuffers[s_dec_op.u4_ts], s_dec_op);
}
results = std::move(m_bufferedResults);
return results;
}
void CopyImageToResultBuffer(uint8* yIn, uint8* uvIn, uint8* bufOut, ivd_video_decode_op_t& decodeInfo)
{
uint32 imageWidth = decodeInfo.s_disp_frm_buf.u4_y_wd;
uint32 imageHeight = decodeInfo.s_disp_frm_buf.u4_y_ht;
size_t inputStride = decodeInfo.s_disp_frm_buf.u4_y_strd;
size_t outputStride = (imageWidth + 0xFF) & ~0xFF;
// copy Y
uint8* yOut = bufOut;
for (uint32 row = 0; row < imageHeight; row++)
{
memcpy(yOut, yIn, imageWidth);
yIn += inputStride;
yOut += outputStride;
}
// copy UV
uint8* uvOut = bufOut + outputStride * imageHeight;
for (uint32 row = 0; row < imageHeight/2; row++)
{
memcpy(uvOut, uvIn, imageWidth);
uvIn += inputStride;
uvOut += outputStride;
}
}
private:
bool DetermineBufferSizes(void* data, uint32 length, uint32& numByteConsumed)
{
numByteConsumed = 0;
UpdateParameters(true);
ivd_video_decode_ip_t s_dec_ip{ 0 };
ivd_video_decode_op_t s_dec_op{ 0 };
s_dec_ip.u4_size = sizeof(ivd_video_decode_ip_t);
s_dec_op.u4_size = sizeof(ivd_video_decode_op_t);
s_dec_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
s_dec_ip.pv_stream_buffer = (uint8*)data;
s_dec_ip.u4_num_Bytes = length;
s_dec_ip.s_out_buffer.u4_num_bufs = 0;
WORD32 status = ih264d_api_function(m_codecCtx, &s_dec_ip, &s_dec_op);
if (status != 0)
{
cemuLog_log(LogType::Force, "H264: Unable to determine buffer sizes for stream");
return false;
}
numByteConsumed = s_dec_op.u4_num_bytes_consumed;
cemu_assert(status == 0);
if (s_dec_op.u4_pic_wd == 0 || s_dec_op.u4_pic_ht == 0)
return false;
UpdateParameters(false);
ReinitBuffers();
return true;
}
void ReinitBuffers()
{
ivd_ctl_getbufinfo_ip_t s_ctl_ip{ 0 };
ivd_ctl_getbufinfo_op_t s_ctl_op{ 0 };
WORD32 outlen = 0;
s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETBUFINFO;
s_ctl_ip.u4_size = sizeof(ivd_ctl_getbufinfo_ip_t);
s_ctl_op.u4_size = sizeof(ivd_ctl_getbufinfo_op_t);
WORD32 status = ih264d_api_function(m_codecCtx, &s_ctl_ip, &s_ctl_op);
cemu_assert(!status);
// allocate
for (uint32 i = 0; i < s_ctl_op.u4_num_disp_bufs; i++)
{
m_displayBuf.emplace_back().resize(s_ctl_op.u4_min_out_buf_size[0] + s_ctl_op.u4_min_out_buf_size[1]);
}
// set
ivd_set_display_frame_ip_t s_set_display_frame_ip{ 0 }; // make sure to zero-initialize this. The codec seems to check the first 3 pointers/sizes per frame, regardless of the value of u4_num_bufs
ivd_set_display_frame_op_t s_set_display_frame_op{ 0 };
s_set_display_frame_ip.e_cmd = IVD_CMD_SET_DISPLAY_FRAME;
s_set_display_frame_ip.u4_size = sizeof(ivd_set_display_frame_ip_t);
s_set_display_frame_op.u4_size = sizeof(ivd_set_display_frame_op_t);
cemu_assert_debug(s_ctl_op.u4_min_num_out_bufs == 2);
cemu_assert_debug(s_ctl_op.u4_min_out_buf_size[0] != 0 && s_ctl_op.u4_min_out_buf_size[1] != 0);
s_set_display_frame_ip.num_disp_bufs = s_ctl_op.u4_num_disp_bufs;
for (uint32 i = 0; i < s_ctl_op.u4_num_disp_bufs; i++)
{
s_set_display_frame_ip.s_disp_buffer[i].u4_num_bufs = 2;
s_set_display_frame_ip.s_disp_buffer[i].u4_min_out_buf_size[0] = s_ctl_op.u4_min_out_buf_size[0];
s_set_display_frame_ip.s_disp_buffer[i].u4_min_out_buf_size[1] = s_ctl_op.u4_min_out_buf_size[1];
s_set_display_frame_ip.s_disp_buffer[i].pu1_bufs[0] = m_displayBuf[i].data() + 0;
s_set_display_frame_ip.s_disp_buffer[i].pu1_bufs[1] = m_displayBuf[i].data() + s_ctl_op.u4_min_out_buf_size[0];
}
status = ih264d_api_function(m_codecCtx, &s_set_display_frame_ip, &s_set_display_frame_op);
cemu_assert(!status);
// mark all as released (available)
for (uint32 i = 0; i < s_ctl_op.u4_num_disp_bufs; i++)
{
ivd_rel_display_frame_ip_t s_video_rel_disp_ip{ 0 };
ivd_rel_display_frame_op_t s_video_rel_disp_op{ 0 };
s_video_rel_disp_ip.e_cmd = IVD_CMD_REL_DISPLAY_FRAME;
s_video_rel_disp_ip.u4_size = sizeof(ivd_rel_display_frame_ip_t);
s_video_rel_disp_op.u4_size = sizeof(ivd_rel_display_frame_op_t);
s_video_rel_disp_ip.u4_disp_buf_id = i;
status = ih264d_api_function(m_codecCtx, &s_video_rel_disp_ip, &s_video_rel_disp_op);
cemu_assert(!status);
}
}
void ResetDecoder()
{
ivd_ctl_reset_ip_t s_ctl_ip;
ivd_ctl_reset_op_t s_ctl_op;
s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t);
WORD32 status = ih264d_api_function(m_codecCtx, (void*)&s_ctl_ip, (void*)&s_ctl_op);
cemu_assert_debug(status == 0);
}
void UpdateParameters(bool headerDecodeOnly)
{
ih264d_ctl_set_config_ip_t s_h264d_ctl_ip{ 0 };
ih264d_ctl_set_config_op_t s_h264d_ctl_op{ 0 };
ivd_ctl_set_config_ip_t* ps_ctl_ip = &s_h264d_ctl_ip.s_ivd_ctl_set_config_ip_t;
ivd_ctl_set_config_op_t* ps_ctl_op = &s_h264d_ctl_op.s_ivd_ctl_set_config_op_t;
ps_ctl_ip->u4_disp_wd = 0;
ps_ctl_ip->e_frm_skip_mode = IVD_SKIP_NONE;
ps_ctl_ip->e_frm_out_mode = m_isBufferedMode ? IVD_DISPLAY_FRAME_OUT : IVD_DECODE_FRAME_OUT;
ps_ctl_ip->e_vid_dec_mode = headerDecodeOnly ? IVD_DECODE_HEADER : IVD_DECODE_FRAME;
ps_ctl_ip->e_cmd = IVD_CMD_VIDEO_CTL;
ps_ctl_ip->e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
ps_ctl_ip->u4_size = sizeof(ih264d_ctl_set_config_ip_t);
ps_ctl_op->u4_size = sizeof(ih264d_ctl_set_config_op_t);
WORD32 status = ih264d_api_function(m_codecCtx, &s_h264d_ctl_ip, &s_h264d_ctl_op);
cemu_assert(status == 0);
}
/* In non-flush mode we have a delay of (at least?) 5 frames */
void AddBufferedResult(DecodeResult& decodeResult)
{
if (decodeResult.frameReady)
m_bufferedResults.emplace_back(decodeResult);
}
void GetCurrentBufferedResult(DecodeResult& decodeResult)
{
cemu_assert(!m_bufferedResults.empty());
if (m_bufferedResults.empty())
{
decodeResult.frameReady = false;
return;
}
decodeResult = m_bufferedResults.front();
m_bufferedResults.erase(m_bufferedResults.begin());
}
private:
iv_obj_t* m_codecCtx{nullptr};
bool m_hasBufferSizeInfo{ false };
bool m_isBufferedMode{ false };
double m_timestamps[64];
void* m_imageBuffers[64];
uint32 m_timestampIndex{0};
std::vector<DecodeResult> m_bufferedResults;
uint32 m_numDecodedFrames{0};
std::vector<std::vector<uint8>> m_displayBuf;
};
H264DEC_STATUS H264DECGetImageSize(uint8* stream, uint32 length, uint32 offset, uint32be* outputWidth, uint32be* outputHeight) H264DEC_STATUS H264DECGetImageSize(uint8* stream, uint32 length, uint32 offset, uint32be* outputWidth, uint32be* outputHeight)
{ {
cemu_assert(offset <= length); if(!stream || length < 4 || !outputWidth || !outputHeight)
return H264DEC_STATUS::INVALID_PARAM;
uint32 imageWidth, imageHeight; if( (offset+4) > length )
return H264DEC_STATUS::INVALID_PARAM;
if (H264AVCDecoder::GetImageInfo(stream, length, imageWidth, imageHeight)) uint8* cur = stream + offset;
uint8* end = stream + length;
cur += 2; // we access cur[-2] and cur[-1] so we need to start at offset 2
while(cur < end-2)
{ {
if (H264_IsBotW()) // check for start code
if(*cur != 1)
{ {
if (imageWidth == 1920 && imageHeight == 1088) cur++;
imageHeight = 1080; continue;
} }
*outputWidth = imageWidth; // check if this is a valid NAL header
*outputHeight = imageHeight; if(cur[-2] != 0 || cur[-1] != 0 || cur[0] != 1)
{
cur++;
continue;
}
uint8 nalHeader = cur[1];
if((nalHeader & 0x1F) != 7)
{
cur++;
continue;
}
h264State_seq_parameter_set_t psp;
bool r = h264Parser_ParseSPS(cur+2, end-cur-2, psp);
if(!r)
{
cemu_assert_suspicious(); // should not happen
return H264DEC_STATUS::BAD_STREAM;
}
*outputWidth = (psp.pic_width_in_mbs_minus1 + 1) * 16;
*outputHeight = (psp.pic_height_in_map_units_minus1 + 1) * 16; // affected by frame_mbs_only_flag?
return H264DEC_STATUS::SUCCESS;
} }
else return H264DEC_STATUS::BAD_STREAM;
{
*outputWidth = 0;
*outputHeight = 0;
return H264DEC_STATUS::BAD_STREAM;
}
return H264DEC_STATUS::SUCCESS;
} }
uint32 H264DECInitParam(uint32 workMemorySize, void* workMemory) uint32 H264DECInitParam(uint32 workMemorySize, void* workMemory)
@ -762,26 +239,28 @@ namespace H264
return 0; return 0;
} }
std::unordered_map<uint32, H264AVCDecoder*> sDecoderSessions; std::unordered_map<uint32, H264DecoderBackend*> sDecoderSessions;
std::mutex sDecoderSessionsMutex; std::mutex sDecoderSessionsMutex;
std::atomic_uint32_t sCurrentSessionHandle{ 1 }; std::atomic_uint32_t sCurrentSessionHandle{ 1 };
static H264AVCDecoder* _CreateDecoderSession(uint32& handleOut) H264DecoderBackend* CreateAVCDecoder();
static H264DecoderBackend* _CreateDecoderSession(uint32& handleOut)
{ {
std::unique_lock _lock(sDecoderSessionsMutex); std::unique_lock _lock(sDecoderSessionsMutex);
handleOut = sCurrentSessionHandle.fetch_add(1); handleOut = sCurrentSessionHandle.fetch_add(1);
H264AVCDecoder* session = new H264AVCDecoder(); H264DecoderBackend* session = CreateAVCDecoder();
sDecoderSessions.try_emplace(handleOut, session); sDecoderSessions.try_emplace(handleOut, session);
return session; return session;
} }
static H264AVCDecoder* _AcquireDecoderSession(uint32 handle) static H264DecoderBackend* _AcquireDecoderSession(uint32 handle)
{ {
std::unique_lock _lock(sDecoderSessionsMutex); std::unique_lock _lock(sDecoderSessionsMutex);
auto it = sDecoderSessions.find(handle); auto it = sDecoderSessions.find(handle);
if (it == sDecoderSessions.end()) if (it == sDecoderSessions.end())
return nullptr; return nullptr;
H264AVCDecoder* session = it->second; H264DecoderBackend* session = it->second;
if (sDecoderSessions.size() >= 5) if (sDecoderSessions.size() >= 5)
{ {
cemuLog_log(LogType::Force, "H264: Warning - more than 5 active sessions"); cemuLog_log(LogType::Force, "H264: Warning - more than 5 active sessions");
@ -790,7 +269,7 @@ namespace H264
return session; return session;
} }
static void _ReleaseDecoderSession(H264AVCDecoder* session) static void _ReleaseDecoderSession(H264DecoderBackend* session)
{ {
std::unique_lock _lock(sDecoderSessionsMutex); std::unique_lock _lock(sDecoderSessionsMutex);
@ -802,7 +281,7 @@ namespace H264
auto it = sDecoderSessions.find(handle); auto it = sDecoderSessions.find(handle);
if (it == sDecoderSessions.end()) if (it == sDecoderSessions.end())
return; return;
H264AVCDecoder* session = it->second; H264DecoderBackend* session = it->second;
session->Destroy(); session->Destroy();
delete session; delete session;
sDecoderSessions.erase(it); sDecoderSessions.erase(it);
@ -830,45 +309,44 @@ namespace H264
uint32 H264DECBegin(void* workMemory) uint32 H264DECBegin(void* workMemory)
{ {
H264Context* ctx = (H264Context*)workMemory; H264Context* ctx = (H264Context*)workMemory;
H264AVCDecoder* session = _AcquireDecoderSession(ctx->sessionHandle); H264DecoderBackend* session = _AcquireDecoderSession(ctx->sessionHandle);
if (!session) if (!session)
{ {
cemuLog_log(LogType::Force, "H264DECBegin(): Invalid session"); cemuLog_log(LogType::Force, "H264DECBegin(): Invalid session");
return 0; return 0;
} }
session->Init(ctx->Param.outputPerFrame == 0); session->Init(ctx->Param.outputPerFrame == 0);
ctx->decoderState.numFramesInFlight = 0;
_ReleaseDecoderSession(session); _ReleaseDecoderSession(session);
return 0; return 0;
} }
void H264DoFrameOutputCallback(H264Context* ctx, H264AVCDecoder::DecodeResult& decodeResult); void H264DoFrameOutputCallback(H264Context* ctx, H264DecoderBackend::DecodeResult& decodeResult);
void _async_H264DECEnd(coreinit::OSEvent* executeDoneEvent, H264AVCDecoder* session, H264Context* ctx, std::vector<H264AVCDecoder::DecodeResult>* decodeResultsOut)
{
*decodeResultsOut = session->Flush();
coreinit::OSSignalEvent(executeDoneEvent);
}
H264DEC_STATUS H264DECEnd(void* workMemory) H264DEC_STATUS H264DECEnd(void* workMemory)
{ {
H264Context* ctx = (H264Context*)workMemory; H264Context* ctx = (H264Context*)workMemory;
H264AVCDecoder* session = _AcquireDecoderSession(ctx->sessionHandle); H264DecoderBackend* session = _AcquireDecoderSession(ctx->sessionHandle);
if (!session) if (!session)
{ {
cemuLog_log(LogType::Force, "H264DECEnd(): Invalid session"); cemuLog_log(LogType::Force, "H264DECEnd(): Invalid session");
return H264DEC_STATUS::SUCCESS; return H264DEC_STATUS::SUCCESS;
} }
StackAllocator<coreinit::OSEvent> executeDoneEvent; coreinit::OSEvent* flushEvt = &session->GetFlushEvent();
coreinit::OSInitEvent(&executeDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL); coreinit::OSResetEvent(flushEvt);
std::vector<H264AVCDecoder::DecodeResult> results; session->QueueFlush();
auto asyncTask = std::async(std::launch::async, _async_H264DECEnd, executeDoneEvent.GetPointer(), session, ctx, &results); coreinit::OSWaitEvent(flushEvt);
coreinit::OSWaitEvent(&executeDoneEvent); while(true)
_ReleaseDecoderSession(session);
if (!results.empty())
{ {
for (auto& itr : results) H264DecoderBackend::DecodeResult decodeResult;
H264DoFrameOutputCallback(ctx, itr); if( !session->GetFrameOutputIfReady(decodeResult) )
break;
// todo - output all frames in a single callback?
H264DoFrameOutputCallback(ctx, decodeResult);
ctx->decoderState.numFramesInFlight--;
} }
cemu_assert_debug(ctx->decoderState.numFramesInFlight == 0); // no frames should be in flight anymore. Exact behavior is not well understood but we may have to output dummy frames if necessary
_ReleaseDecoderSession(session);
return H264DEC_STATUS::SUCCESS; return H264DEC_STATUS::SUCCESS;
} }
@ -930,7 +408,6 @@ namespace H264
return 0; return 0;
} }
struct H264DECFrameOutput struct H264DECFrameOutput
{ {
/* +0x00 */ uint32be result; /* +0x00 */ uint32be result;
@ -967,7 +444,7 @@ namespace H264
static_assert(sizeof(H264OutputCBStruct) == 12); static_assert(sizeof(H264OutputCBStruct) == 12);
void H264DoFrameOutputCallback(H264Context* ctx, H264AVCDecoder::DecodeResult& decodeResult) void H264DoFrameOutputCallback(H264Context* ctx, H264DecoderBackend::DecodeResult& decodeResult)
{ {
sint32 outputFrameCount = 1; sint32 outputFrameCount = 1;
@ -984,14 +461,14 @@ namespace H264
frameOutput->imagePtr = (uint8*)decodeResult.imageOutput; frameOutput->imagePtr = (uint8*)decodeResult.imageOutput;
frameOutput->result = 100; frameOutput->result = 100;
frameOutput->timestamp = decodeResult.timestamp; frameOutput->timestamp = decodeResult.timestamp;
frameOutput->frameWidth = decodeResult.decodeOutput.u4_pic_wd; frameOutput->frameWidth = decodeResult.frameWidth;
frameOutput->frameHeight = decodeResult.decodeOutput.u4_pic_ht; frameOutput->frameHeight = decodeResult.frameHeight;
frameOutput->bytesPerRow = (decodeResult.decodeOutput.u4_pic_wd + 0xFF) & ~0xFF; frameOutput->bytesPerRow = decodeResult.bytesPerRow;
frameOutput->cropEnable = decodeResult.decodeOutput.u1_frame_cropping_flag; frameOutput->cropEnable = decodeResult.cropEnable;
frameOutput->cropTop = decodeResult.decodeOutput.u1_frame_cropping_rect_top_ofst; frameOutput->cropTop = decodeResult.cropTop;
frameOutput->cropBottom = decodeResult.decodeOutput.u1_frame_cropping_rect_bottom_ofst; frameOutput->cropBottom = decodeResult.cropBottom;
frameOutput->cropLeft = decodeResult.decodeOutput.u1_frame_cropping_rect_left_ofst; frameOutput->cropLeft = decodeResult.cropLeft;
frameOutput->cropRight = decodeResult.decodeOutput.u1_frame_cropping_rect_right_ofst; frameOutput->cropRight = decodeResult.cropRight;
StackAllocator<H264OutputCBStruct> stack_fptrOutputData; StackAllocator<H264OutputCBStruct> stack_fptrOutputData;
stack_fptrOutputData->frameCount = outputFrameCount; stack_fptrOutputData->frameCount = outputFrameCount;
@ -1006,29 +483,41 @@ namespace H264
} }
} }
void _async_H264DECExecute(coreinit::OSEvent* executeDoneEvent, H264AVCDecoder* session, H264Context* ctx, void* imageOutput, H264AVCDecoder::DecodeResult* decodeResult)
{
session->Decode(ctx->BitStream.ptr.GetPtr(), ctx->BitStream.length, ctx->BitStream.timestamp, imageOutput, *decodeResult);
coreinit::OSSignalEvent(executeDoneEvent);
}
uint32 H264DECExecute(void* workMemory, void* imageOutput) uint32 H264DECExecute(void* workMemory, void* imageOutput)
{ {
BenchmarkTimer bt;
bt.Start();
H264Context* ctx = (H264Context*)workMemory; H264Context* ctx = (H264Context*)workMemory;
H264AVCDecoder* session = _AcquireDecoderSession(ctx->sessionHandle); H264DecoderBackend* session = _AcquireDecoderSession(ctx->sessionHandle);
if (!session) if (!session)
{ {
cemuLog_log(LogType::Force, "H264DECExecute(): Invalid session"); cemuLog_log(LogType::Force, "H264DECExecute(): Invalid session");
return 0; return 0;
} }
StackAllocator<coreinit::OSEvent> executeDoneEvent; // feed data to backend
coreinit::OSInitEvent(&executeDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL); session->QueueForDecode((uint8*)ctx->BitStream.ptr.GetPtr(), ctx->BitStream.length, ctx->BitStream.timestamp, imageOutput);
H264AVCDecoder::DecodeResult decodeResult; ctx->decoderState.numFramesInFlight++;
auto asyncTask = std::async(std::launch::async, _async_H264DECExecute, &executeDoneEvent, session, ctx, imageOutput , &decodeResult); // H264DECExecute is synchronous and will return a frame after either every call (non-buffered) or after 6 calls (buffered)
coreinit::OSWaitEvent(&executeDoneEvent); // normally frame decoding happens only during H264DECExecute, but in order to hide the latency of our CPU decoder we will decode asynchronously in buffered mode
uint32 numFramesToBuffer = (ctx->Param.outputPerFrame == 0) ? 5 : 0;
if(ctx->decoderState.numFramesInFlight > numFramesToBuffer)
{
ctx->decoderState.numFramesInFlight--;
while(true)
{
coreinit::OSEvent& evt = session->GetFrameOutputEvent();
coreinit::OSWaitEvent(&evt);
H264DecoderBackend::DecodeResult decodeResult;
if( !session->GetFrameOutputIfReady(decodeResult) )
continue;
H264DoFrameOutputCallback(ctx, decodeResult);
break;
}
}
_ReleaseDecoderSession(session); _ReleaseDecoderSession(session);
if(decodeResult.frameReady) bt.Stop();
H264DoFrameOutputCallback(ctx, decodeResult); double callTime = bt.GetElapsedMilliseconds();
cemuLog_log(LogType::H264, "H264Bench | H264DECExecute took {}ms", callTime);
return 0x80 | 100; return 0x80 | 100;
} }

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