mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-25 18:46:55 +01:00
Merge branch 'refs/heads/main' into loadaudio
# Conflicts: # src/gui/GeneralSettings2.cpp
This commit is contained in:
commit
ac5c44d2cf
@ -15,6 +15,7 @@ BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterExternBlock: true
|
||||
|
9
.github/getversion.cpp
vendored
9
.github/getversion.cpp
vendored
@ -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;
|
||||
}
|
91
.github/workflows/build.yml
vendored
91
.github/workflows/build.yml
vendored
@ -3,10 +3,10 @@ name: Build Cemu
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
deploymode:
|
||||
next_version_major:
|
||||
required: false
|
||||
type: string
|
||||
experimentalversion:
|
||||
next_version_minor:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
@ -24,30 +24,17 @@ jobs:
|
||||
submodules: "recursive"
|
||||
fetch-depth: 0
|
||||
|
||||
- name: "Fetch full history for vcpkg submodule"
|
||||
run: |
|
||||
cd dependencies/vcpkg
|
||||
git fetch --unshallow
|
||||
|
||||
- name: Setup release mode parameters (for deploy)
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
- name: Setup release mode parameters
|
||||
run: |
|
||||
echo "BUILD_MODE=release" >> $GITHUB_ENV
|
||||
echo "BUILD_FLAGS=" >> $GITHUB_ENV
|
||||
echo "Build mode is release"
|
||||
|
||||
- name: Setup debug mode parameters (for continous build)
|
||||
if: ${{ inputs.deploymode != 'release' }}
|
||||
- name: Setup build flags for version
|
||||
if: ${{ inputs.next_version_major != '' }}
|
||||
run: |
|
||||
echo "BUILD_MODE=debug" >> $GITHUB_ENV
|
||||
echo "BUILD_FLAGS=" >> $GITHUB_ENV
|
||||
echo "Build mode is debug"
|
||||
|
||||
- name: Setup version for experimental
|
||||
if: ${{ inputs.experimentalversion != '' }}
|
||||
run: |
|
||||
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
|
||||
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
|
||||
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
|
||||
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"
|
||||
run: |
|
||||
@ -86,12 +73,10 @@ jobs:
|
||||
cmake --build build
|
||||
|
||||
- name: Prepare artifact
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
run: mv bin/Cemu_release bin/Cemu
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
with:
|
||||
name: cemu-bin-linux-x64
|
||||
path: ./bin/Cemu
|
||||
@ -133,29 +118,17 @@ jobs:
|
||||
with:
|
||||
submodules: "recursive"
|
||||
|
||||
- name: "Fetch full history for vcpkg submodule"
|
||||
run: |
|
||||
cd dependencies/vcpkg
|
||||
git fetch --unshallow
|
||||
|
||||
- name: Setup release mode parameters (for deploy)
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
- name: Setup release mode parameters
|
||||
run: |
|
||||
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 mode is release"
|
||||
|
||||
- name: Setup debug mode parameters (for continous build)
|
||||
if: ${{ inputs.deploymode != 'release' }}
|
||||
- name: Setup build flags for version
|
||||
if: ${{ inputs.next_version_major != '' }}
|
||||
run: |
|
||||
echo "BUILD_MODE=debug" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||
echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||
echo "Build mode is debug"
|
||||
- name: Setup version for experimental
|
||||
if: ${{ inputs.experimentalversion != '' }}
|
||||
run: |
|
||||
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
|
||||
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
|
||||
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
|
||||
|
||||
- name: "Setup cmake"
|
||||
uses: jwlawson/actions-setup-cmake@v2
|
||||
@ -194,52 +167,45 @@ jobs:
|
||||
cmake --build . --config ${{ env.BUILD_MODE }}
|
||||
|
||||
- name: Prepare artifact
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
run: Rename-Item bin/Cemu_release.exe Cemu.exe
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
with:
|
||||
name: cemu-bin-windows-x64
|
||||
path: ./bin/Cemu.exe
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-12
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- name: "Checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
|
||||
- name: "Fetch full history for vcpkg submodule"
|
||||
run: |
|
||||
cd dependencies/vcpkg
|
||||
git fetch --unshallow
|
||||
|
||||
- name: Setup release mode parameters (for deploy)
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
- name: Setup release mode parameters
|
||||
run: |
|
||||
echo "BUILD_MODE=release" >> $GITHUB_ENV
|
||||
echo "BUILD_FLAGS=" >> $GITHUB_ENV
|
||||
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
|
||||
if: ${{ inputs.experimentalversion != '' }}
|
||||
- name: Setup build flags for version
|
||||
if: ${{ inputs.next_version_major != '' }}
|
||||
run: |
|
||||
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
|
||||
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
|
||||
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
|
||||
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"
|
||||
run: |
|
||||
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"
|
||||
uses: jwlawson/actions-setup-cmake@v2
|
||||
@ -270,9 +236,8 @@ jobs:
|
||||
cd build
|
||||
cmake .. ${{ env.BUILD_FLAGS }} \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \
|
||||
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
|
||||
-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
|
||||
|
||||
- name: "Build Cemu"
|
||||
@ -280,7 +245,6 @@ jobs:
|
||||
cmake --build build
|
||||
|
||||
- name: Prepare artifact
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
run: |
|
||||
mkdir bin/Cemu_app
|
||||
mv bin/Cemu_release.app bin/Cemu_app/Cemu.app
|
||||
@ -294,7 +258,6 @@ jobs:
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ inputs.deploymode == 'release' }}
|
||||
with:
|
||||
name: cemu-bin-macos-x64
|
||||
path: ./bin/Cemu.dmg
|
||||
|
3
.github/workflows/build_check.yml
vendored
3
.github/workflows/build_check.yml
vendored
@ -16,6 +16,3 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/build.yml
|
||||
with:
|
||||
deploymode: release
|
||||
experimentalversion: 999999
|
||||
|
@ -1,20 +1,83 @@
|
||||
name: Deploy experimental release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
changelog0:
|
||||
description: 'Enter the changelog lines for this release. Each line is a feature / bullet point. Do not use dash.'
|
||||
required: true
|
||||
type: string
|
||||
changelog1:
|
||||
description: 'Feature 2'
|
||||
required: false
|
||||
type: string
|
||||
changelog2:
|
||||
description: 'Feature 3'
|
||||
required: false
|
||||
type: string
|
||||
changelog3:
|
||||
description: 'Feature 4'
|
||||
required: false
|
||||
type: string
|
||||
changelog4:
|
||||
description: 'Feature 5'
|
||||
required: false
|
||||
type: string
|
||||
changelog5:
|
||||
description: 'Feature 6'
|
||||
required: false
|
||||
type: string
|
||||
changelog6:
|
||||
description: 'Feature 7'
|
||||
required: false
|
||||
type: string
|
||||
changelog7:
|
||||
description: 'Feature 8'
|
||||
required: false
|
||||
type: string
|
||||
changelog8:
|
||||
description: 'Feature 9'
|
||||
required: false
|
||||
type: string
|
||||
changelog9:
|
||||
description: 'Feature 10'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
calculate-version:
|
||||
name: Calculate Version
|
||||
uses: ./.github/workflows/determine_release_version.yml
|
||||
call-release-build:
|
||||
uses: ./.github/workflows/build.yml
|
||||
needs: calculate-version
|
||||
with:
|
||||
deploymode: release
|
||||
experimentalversion: ${{ github.run_number }}
|
||||
next_version_major: ${{ needs.calculate-version.outputs.next_version_major }}
|
||||
next_version_minor: ${{ needs.calculate-version.outputs.next_version_minor }}
|
||||
deploy:
|
||||
name: Deploy experimental release
|
||||
runs-on: ubuntu-22.04
|
||||
needs: call-release-build
|
||||
needs: [call-release-build, calculate-version]
|
||||
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
|
||||
with:
|
||||
name: cemu-bin-linux-x64
|
||||
@ -40,15 +103,13 @@ jobs:
|
||||
mkdir upload
|
||||
sudo apt install zip
|
||||
|
||||
- name: Get version
|
||||
- name: Set version dependent vars
|
||||
run: |
|
||||
echo "Experimental version: ${{ github.run_number }}"
|
||||
ls
|
||||
gcc -o getversion .github/getversion.cpp
|
||||
./getversion
|
||||
echo "Cemu CI version: $(./getversion)"
|
||||
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)-${{ github.run_number }}" >> $GITHUB_ENV
|
||||
echo "CEMU_VERSION=$(./getversion)-${{ github.run_number }}" >> $GITHUB_ENV
|
||||
echo "Version: ${{ needs.calculate-version.outputs.next_version }}"
|
||||
echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}"
|
||||
echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}"
|
||||
echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
|
||||
echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Create release from windows-bin
|
||||
run: |
|
||||
@ -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
|
||||
tar xvzf ghr.tar.gz; rm ghr.tar.gz
|
||||
echo "[INFO] Release tag: v${{ env.CEMU_VERSION }}"
|
||||
ghr_v0.15.0_linux_amd64/ghr -prerelease -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }} (Experimental)" -b "Cemu experimental release" "v${{ env.CEMU_VERSION }}" ./upload
|
||||
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
|
||||
|
74
.github/workflows/determine_release_version.yml
vendored
Normal file
74
.github/workflows/determine_release_version.yml
vendored
Normal 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
4
.gitmodules
vendored
@ -9,10 +9,12 @@
|
||||
[submodule "dependencies/vcpkg"]
|
||||
path = dependencies/vcpkg
|
||||
url = https://github.com/microsoft/vcpkg
|
||||
shallow = true
|
||||
shallow = false
|
||||
[submodule "dependencies/Vulkan-Headers"]
|
||||
path = dependencies/Vulkan-Headers
|
||||
url = https://github.com/KhronosGroup/Vulkan-Headers
|
||||
shallow = true
|
||||
[submodule "dependencies/imgui"]
|
||||
path = dependencies/imgui
|
||||
url = https://github.com/ocornut/imgui
|
||||
shallow = true
|
||||
|
50
BUILD.md
50
BUILD.md
@ -16,10 +16,10 @@
|
||||
- [Compiling Errors](#compiling-errors)
|
||||
- [Building Errors](#building-errors)
|
||||
- [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 Dependencies](#installing-dependencies)
|
||||
- [Build Cemu using CMake and Clang](#build-cemu-using-cmake-and-clang)
|
||||
- [Installing Tool Dependencies](#installing-tool-dependencies)
|
||||
- [Installing Library Dependencies](#installing-library-dependencies)
|
||||
- [Build Cemu using CMake](#build-cemu-using-cmake)
|
||||
- [Updating Cemu and source code](#updating-cemu-and-source-code)
|
||||
|
||||
## 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`
|
||||
|
||||
#### 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
|
||||
|
||||
@ -141,31 +141,41 @@ If you are getting a different error than any of the errors listed above, you ma
|
||||
|
||||
## macOS
|
||||
|
||||
To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and
|
||||
below, built in LLVM, and Xcode LLVM don't support the C++20 feature set required. The OpenGL graphics
|
||||
API isn't support on macOS, Vulkan must be used. Additionally 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
|
||||
To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and below
|
||||
don't support the C++20 feature set required, so either install LLVM from Homebrew or make sure that
|
||||
you have a recent enough version of Xcode. Xcode 15 is known to work. The OpenGL graphics API isn't
|
||||
supported on macOS, so Vulkan must be used through the Molten-VK compatibility layer.
|
||||
|
||||
### Installing brew
|
||||
|
||||
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`
|
||||
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`
|
||||
5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`.
|
||||
|
||||
|
@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.21.1)
|
||||
|
||||
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)
|
||||
set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
|
||||
|
||||
if (EXPERIMENTAL_VERSION)
|
||||
add_definitions(-DEMULATOR_VERSION_MINOR=${EXPERIMENTAL_VERSION})
|
||||
# used by CI script to set version:
|
||||
set(EMULATOR_VERSION_MAJOR "0" CACHE STRING "")
|
||||
set(EMULATOR_VERSION_MINOR "0" CACHE STRING "")
|
||||
set(EMULATOR_VERSION_PATCH "0" CACHE STRING "")
|
||||
|
||||
execute_process(
|
||||
COMMAND git log --format=%h -1
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
@ -13,9 +15,26 @@ if (EXPERIMENTAL_VERSION)
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
add_definitions(-DEMULATOR_HASH=${GIT_HASH})
|
||||
endif()
|
||||
|
||||
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)
|
||||
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux")
|
||||
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_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)
|
||||
|
||||
# enable link time optimization for release builds
|
||||
@ -69,6 +92,7 @@ endif()
|
||||
|
||||
if (APPLE)
|
||||
enable_language(OBJC OBJCXX)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0")
|
||||
endif()
|
||||
|
||||
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.
@ -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.
|
12
dependencies/ih264d/CMakeLists.txt
vendored
12
dependencies/ih264d/CMakeLists.txt
vendored
@ -117,7 +117,13 @@ add_library (ih264d
|
||||
"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")
|
||||
include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES})
|
||||
target_sources(ih264d PRIVATE
|
||||
@ -140,7 +146,7 @@ target_sources(ih264d PRIVATE
|
||||
"decoder/x86/ih264d_function_selector_sse42.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 )
|
||||
set(LIBAVCDEC_ARM_INCLUDES "common/armv8" "decoder/arm")
|
||||
include_directories("common/" "decoder/" ${LIBAVCDEC_ARM_INCLUDES})
|
||||
@ -178,7 +184,7 @@ target_sources(ih264d PRIVATE
|
||||
)
|
||||
target_compile_options(ih264d PRIVATE -DARMV8)
|
||||
else()
|
||||
message(FATAL_ERROR "ih264d unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
message(FATAL_ERROR "ih264d unknown architecture: ${IH264D_ARCHITECTURE}")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
|
2
dependencies/vcpkg
vendored
2
dependencies/vcpkg
vendored
@ -1 +1 @@
|
||||
Subproject commit cbf4a6641528cee6f172328984576f51698de726
|
||||
Subproject commit a4275b7eee79fb24ec2e135481ef5fce8b41c339
|
@ -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)
|
13
dependencies/vcpkg_overlay_ports/sdl2/deps.patch
vendored
13
dependencies/vcpkg_overlay_ports/sdl2/deps.patch
vendored
@ -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)
|
137
dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake
vendored
137
dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake
vendored
@ -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")
|
8
dependencies/vcpkg_overlay_ports/sdl2/usage
vendored
8
dependencies/vcpkg_overlay_ports/sdl2/usage
vendored
@ -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>
|
||||
)
|
68
dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json
vendored
68
dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json
vendored
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
@ -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})
|
@ -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")
|
9
dependencies/vcpkg_overlay_ports/tiff/usage
vendored
9
dependencies/vcpkg_overlay_ports/tiff/usage
vendored
@ -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
|
@ -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)
|
67
dependencies/vcpkg_overlay_ports/tiff/vcpkg.json
vendored
67
dependencies/vcpkg_overlay_ports/tiff/vcpkg.json
vendored
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -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})
|
||||
|
@ -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
|
||||
|
@ -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})
|
@ -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}/../..")
|
@ -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)
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
@ -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)
|
@ -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")
|
@ -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>
|
||||
)
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
@ -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})
|
@ -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")
|
@ -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
|
@ -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)
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
@ -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)
|
@ -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")
|
@ -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>
|
||||
)
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
@ -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})
|
@ -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")
|
@ -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
|
@ -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)
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
6
dist/linux/appimage.sh
vendored
6
dist/linux/appimage.sh
vendored
@ -10,6 +10,8 @@ curl -sSfL https://github.com"$(curl https://github.com/probonopd/go-appimage/re
|
||||
chmod a+x mkappimage.AppImage
|
||||
curl -sSfLO "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/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
|
||||
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 \
|
||||
-i "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.png \
|
||||
-e "${GITHUB_WORKSPACE}"/AppDir/usr/bin/Cemu \
|
||||
--plugin gtk
|
||||
--plugin gtk \
|
||||
--plugin checkrt
|
||||
|
||||
if ! GITVERSION="$(git rev-parse --short HEAD 2>/dev/null)"; then
|
||||
GITVERSION=experimental
|
||||
@ -47,7 +50,6 @@ fi
|
||||
echo "Cemu Version Cemu-${GITVERSION}"
|
||||
|
||||
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
|
||||
VERSION="${GITVERSION}" ./mkappimage.AppImage --appimage-extract-and-run "${GITHUB_WORKSPACE}"/AppDir
|
||||
|
||||
|
@ -56,6 +56,12 @@ add_executable(CemuBin
|
||||
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)
|
||||
target_sources(CemuBin PRIVATE
|
||||
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_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 -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()
|
||||
|
||||
set_target_properties(CemuBin PROPERTIES
|
||||
|
@ -218,6 +218,8 @@ add_library(CemuCafe
|
||||
HW/SI/SI.cpp
|
||||
HW/SI/si.h
|
||||
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/iosu_fsa.cpp
|
||||
IOSU/fsa/iosu_fsa.h
|
||||
@ -372,12 +374,24 @@ add_library(CemuCafe
|
||||
OS/libs/gx2/GX2_Texture.h
|
||||
OS/libs/gx2/GX2_TilingAperture.cpp
|
||||
OS/libs/h264_avc/H264Dec.cpp
|
||||
OS/libs/h264_avc/H264DecBackendAVC.cpp
|
||||
OS/libs/h264_avc/h264dec.h
|
||||
OS/libs/h264_avc/H264DecInternal.h
|
||||
OS/libs/h264_avc/parser
|
||||
OS/libs/h264_avc/parser/H264Parser.cpp
|
||||
OS/libs/h264_avc/parser/H264Parser.h
|
||||
OS/libs/mic/mic.cpp
|
||||
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/nlibcurlDebug.hpp
|
||||
OS/libs/nlibcurl/nlibcurl.h
|
||||
@ -445,14 +459,22 @@ add_library(CemuCafe
|
||||
OS/libs/nsyshid/AttachDefaultBackends.cpp
|
||||
OS/libs/nsyshid/Whitelist.cpp
|
||||
OS/libs/nsyshid/Whitelist.h
|
||||
OS/libs/nsyshid/BackendEmulated.cpp
|
||||
OS/libs/nsyshid/BackendEmulated.h
|
||||
OS/libs/nsyshid/BackendLibusb.cpp
|
||||
OS/libs/nsyshid/BackendLibusb.h
|
||||
OS/libs/nsyshid/BackendWindowsHID.cpp
|
||||
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.h
|
||||
OS/libs/nsysnet/nsysnet.cpp
|
||||
OS/libs/nsysnet/nsysnet.h
|
||||
OS/libs/ntag/ntag.cpp
|
||||
OS/libs/ntag/ntag.h
|
||||
OS/libs/padscore/padscore.cpp
|
||||
OS/libs/padscore/padscore.h
|
||||
OS/libs/proc_ui/proc_ui.cpp
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "Cafe/IOSU/legacy/iosu_boss.h"
|
||||
#include "Cafe/IOSU/legacy/iosu_nim.h"
|
||||
#include "Cafe/IOSU/PDM/iosu_pdm.h"
|
||||
#include "Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.h"
|
||||
|
||||
// IOSU initializer functions
|
||||
#include "Cafe/IOSU/kernel/iosu_kernel.h"
|
||||
@ -51,6 +52,8 @@
|
||||
#include "Cafe/OS/libs/gx2/GX2.h"
|
||||
#include "Cafe/OS/libs/gx2/GX2_Misc.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_pdm/nn_pdm.h"
|
||||
#include "Cafe/OS/libs/nn_cmpt/nn_cmpt.h"
|
||||
@ -533,6 +536,7 @@ namespace CafeSystem
|
||||
iosu::acp::GetModule(),
|
||||
iosu::fpd::GetModule(),
|
||||
iosu::pdm::GetModule(),
|
||||
iosu::ccr_nfc::GetModule(),
|
||||
};
|
||||
|
||||
// initialize all subsystems which are persistent and don't depend on a game running
|
||||
@ -587,6 +591,8 @@ namespace CafeSystem
|
||||
H264::Initialize();
|
||||
snd_core::Initialize();
|
||||
mic::Initialize();
|
||||
nfc::Initialize();
|
||||
ntag::Initialize();
|
||||
// init hardware register interfaces
|
||||
HW_SI::Initialize();
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
#include "../fsc.h"
|
||||
|
||||
// path parser and utility class for Wii U paths
|
||||
// optimized to be allocation-free for common path lengths
|
||||
class FSCPath
|
||||
@ -119,8 +121,6 @@ public:
|
||||
template<typename F>
|
||||
class FSAFileTree
|
||||
{
|
||||
public:
|
||||
|
||||
private:
|
||||
|
||||
enum NODETYPE : uint8
|
||||
@ -133,6 +133,7 @@ private:
|
||||
{
|
||||
std::string name;
|
||||
std::vector<node_t*> subnodes;
|
||||
size_t fileSize;
|
||||
F* custom;
|
||||
NODETYPE type;
|
||||
};
|
||||
@ -179,13 +180,54 @@ private:
|
||||
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:
|
||||
FSAFileTree()
|
||||
{
|
||||
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);
|
||||
if (p.GetNodeCount() == 0)
|
||||
@ -196,6 +238,7 @@ public:
|
||||
return false; // node already exists
|
||||
// add file node
|
||||
node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1));
|
||||
fileNode->fileSize = fileSize;
|
||||
fileNode->custom = custom;
|
||||
return true;
|
||||
}
|
||||
@ -214,6 +257,20 @@ public:
|
||||
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)
|
||||
{
|
||||
FSCPath p(path);
|
||||
|
@ -212,4 +212,4 @@ bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTarg
|
||||
|
||||
// redirect device
|
||||
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);
|
||||
|
@ -11,7 +11,7 @@ struct RedirectEntry
|
||||
|
||||
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
|
||||
RedirectEntry* existingEntry;
|
||||
@ -24,7 +24,7 @@ void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& t
|
||||
delete existingEntry;
|
||||
}
|
||||
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
|
||||
redirectTree.addFile(virtualSourcePath, entry);
|
||||
redirectTree.addFile(virtualSourcePath, fileSize, entry);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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);
|
||||
|
||||
FSCVirtualFile* dirIterator;
|
||||
|
||||
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR) && redirectTree.getDirectory(path, dirIterator))
|
||||
return dirIterator;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -830,7 +830,7 @@ void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, bool isAOC
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -501,8 +501,6 @@ void debugger_createPPCStateSnapshot(PPCInterpreter_t* hCPU)
|
||||
debuggerState.debugSession.ppcSnapshot.cr[i] = hCPU->cr[i];
|
||||
}
|
||||
|
||||
void DebugLogStackTrace(OSThread_t* thread, MPTR sp);
|
||||
|
||||
void debugger_enterTW(PPCInterpreter_t* hCPU)
|
||||
{
|
||||
// handle logging points
|
||||
|
@ -212,11 +212,12 @@ static void PPCInterpreter_SUBF(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)
|
||||
PPC_OPC_TEMPL3_XO();
|
||||
hCPU->gpr[rD] = ~hCPU->gpr[rA] + hCPU->gpr[rB] + 1;
|
||||
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~hCPU->gpr[rA], hCPU->gpr[rB], hCPU->gpr[rD]));
|
||||
uint32 result = ~hCPU->gpr[rA] + hCPU->gpr[rB] + 1;
|
||||
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~hCPU->gpr[rA], hCPU->gpr[rB], result));
|
||||
hCPU->gpr[rD] = result;
|
||||
if (opHasRC())
|
||||
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
|
||||
PPCInterpreter_nextInstruction(hCPU);
|
||||
|
@ -90,7 +90,7 @@ uint8* PPCInterpreterGetStackPointer()
|
||||
return memory_getPointerFromVirtualOffset(PPCInterpreter_getCurrentInstance()->gpr[1]);
|
||||
}
|
||||
|
||||
uint8* PPCInterpreterGetAndModifyStackPointer(sint32 offset)
|
||||
uint8* PPCInterpreter_PushAndReturnStackPointer(sint32 offset)
|
||||
{
|
||||
PPCInterpreter_t* hCPU = PPCInterpreter_getCurrentInstance();
|
||||
uint8* result = memory_getPointerFromVirtualOffset(hCPU->gpr[1] - offset);
|
||||
|
@ -5,8 +5,28 @@ struct PPCCoreCallbackData_t
|
||||
{
|
||||
sint32 gprCount = 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
|
||||
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>
|
||||
uint32 PPCCoreCallback(MPTR function, PPCCoreCallbackData_t& data, T currentArg, TArgs... args)
|
||||
{
|
||||
cemu_assert_debug(data.gprCount <= 8);
|
||||
cemu_assert_debug(data.floatCount <= 8);
|
||||
// TODO float arguments on stack
|
||||
cemu_assert_debug(data.floatCount < 8);
|
||||
|
||||
PPCInterpreter_t* hCPU = PPCInterpreter_getCurrentInstance();
|
||||
if constexpr (std::is_pointer_v<T>)
|
||||
{
|
||||
hCPU->gpr[3 + data.gprCount] = MEMPTR(currentArg).GetMPTR();
|
||||
data.gprCount++;
|
||||
_PPCCoreCallback_writeGPRArg(data, hCPU, MEMPTR(currentArg).GetMPTR());
|
||||
}
|
||||
else if constexpr (std::is_base_of_v<MEMPTRBase, std::remove_reference_t<T>>)
|
||||
{
|
||||
hCPU->gpr[3 + data.gprCount] = currentArg.GetMPTR();
|
||||
data.gprCount++;
|
||||
_PPCCoreCallback_writeGPRArg(data, hCPU, currentArg.GetMPTR());
|
||||
}
|
||||
else if constexpr (std::is_reference_v<T>)
|
||||
{
|
||||
hCPU->gpr[3 + data.gprCount] = MEMPTR(¤tArg).GetMPTR();
|
||||
data.gprCount++;
|
||||
_PPCCoreCallback_writeGPRArg(data, hCPU, MEMPTR(¤tArg).GetMPTR());
|
||||
}
|
||||
else if constexpr(std::is_enum_v<T>)
|
||||
{
|
||||
@ -53,8 +71,7 @@ uint32 PPCCoreCallback(MPTR function, PPCCoreCallbackData_t& data, T currentArg,
|
||||
}
|
||||
else
|
||||
{
|
||||
hCPU->gpr[3 + data.gprCount] = (uint32)currentArg;
|
||||
data.gprCount++;
|
||||
_PPCCoreCallback_writeGPRArg(data, hCPU, (uint32)currentArg);
|
||||
}
|
||||
|
||||
return PPCCoreCallback(function, data, args...);
|
||||
|
@ -213,7 +213,7 @@ void PPCTimer_start();
|
||||
// core info and control
|
||||
extern uint32 ppcThreadQuantum;
|
||||
|
||||
uint8* PPCInterpreterGetAndModifyStackPointer(sint32 offset);
|
||||
uint8* PPCInterpreter_PushAndReturnStackPointer(sint32 offset);
|
||||
uint8* PPCInterpreterGetStackPointer();
|
||||
void PPCInterpreterModifyStackPointer(sint32 offset);
|
||||
|
||||
|
@ -524,7 +524,7 @@ void LatteSHRC_UpdateGSBaseHash(uint8* geometryShaderPtr, uint32 geometryShaderS
|
||||
// update hash from geometry shader data
|
||||
uint64 gsHash1 = 0;
|
||||
uint64 gsHash2 = 0;
|
||||
_calculateShaderProgramHash((uint32*)geometryShaderPtr, geometryShaderSize, &hashCacheVS, &gsHash1, &gsHash2);
|
||||
_calculateShaderProgramHash((uint32*)geometryShaderPtr, geometryShaderSize, &hashCacheGS, &gsHash1, &gsHash2);
|
||||
// get geometry shader
|
||||
uint64 gsHash = gsHash1 + gsHash2;
|
||||
gsHash += (uint64)_activeVertexShader->ringParameterCount;
|
||||
|
@ -235,6 +235,9 @@ void LatteTexture_InitSliceAndMipInfo(LatteTexture* texture)
|
||||
// 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)
|
||||
{
|
||||
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
|
||||
for (sint32 swap = 0; swap < 2; swap++)
|
||||
{
|
||||
|
@ -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.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)
|
||||
{
|
||||
// seen in Giana Sisters: Twisted Dreams
|
||||
@ -496,3 +506,5 @@ void LatteDecompiler_emitAttributeDecodeGLSL(LatteDecompilerShader* shaderContex
|
||||
cemu_assert_debug(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,16 +23,13 @@ bool RendererShaderGL::loadBinary()
|
||||
cemu_assert_debug(m_baseHash != 0);
|
||||
uint64 h1, h2;
|
||||
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
|
||||
sint32 fileSize = 0;
|
||||
std::vector<uint8> cacheFileData;
|
||||
if (!s_programBinaryCache->GetFile({h1, h2 }, cacheFileData))
|
||||
return false;
|
||||
if (fileSize < sizeof(uint32))
|
||||
{
|
||||
if (cacheFileData.size() <= sizeof(uint32))
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 shaderBinFormat = *(uint32*)(cacheFileData.data() + 0);
|
||||
uint32 shaderBinFormat = *(uint32*)(cacheFileData.data());
|
||||
|
||||
m_program = glCreateProgram();
|
||||
glProgramBinary(m_program, shaderBinFormat, cacheFileData.data()+4, cacheFileData.size()-4);
|
||||
|
@ -12,9 +12,9 @@ uint32 RendererShader::GeneratePrecompiledCacheId()
|
||||
v += (uint32)(*s);
|
||||
s++;
|
||||
}
|
||||
v += (EMULATOR_VERSION_LEAD * 1000000u);
|
||||
v += (EMULATOR_VERSION_MAJOR * 10000u);
|
||||
v += (EMULATOR_VERSION_MINOR * 100u);
|
||||
v += (EMULATOR_VERSION_MAJOR * 1000000u);
|
||||
v += (EMULATOR_VERSION_MINOR * 10000u);
|
||||
v += (EMULATOR_VERSION_PATCH * 100u);
|
||||
|
||||
// settings that can influence shaders
|
||||
v += (uint32)g_current_game_profile->GetAccurateShaderMul() * 133;
|
||||
|
@ -146,8 +146,17 @@ void SwapchainInfoVk::Create()
|
||||
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;
|
||||
hasDefinedSwapchainImage = false;
|
||||
|
||||
m_queueDepth = 0;
|
||||
}
|
||||
|
||||
void SwapchainInfoVk::Cleanup()
|
||||
@ -177,6 +186,12 @@ void SwapchainInfoVk::Cleanup()
|
||||
m_swapchainFramebuffers.clear();
|
||||
|
||||
|
||||
if (m_imageAvailableFence)
|
||||
{
|
||||
WaitAvailableFence();
|
||||
vkDestroyFence(m_logicalDevice, m_imageAvailableFence, nullptr);
|
||||
m_imageAvailableFence = nullptr;
|
||||
}
|
||||
if (m_swapchain)
|
||||
{
|
||||
vkDestroySwapchainKHR(m_logicalDevice, m_swapchain, nullptr);
|
||||
@ -189,6 +204,18 @@ bool SwapchainInfoVk::IsValid() const
|
||||
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 ret = m_currentSemaphore;
|
||||
@ -198,8 +225,10 @@ VkSemaphore SwapchainInfoVk::ConsumeAcquireSemaphore()
|
||||
|
||||
bool SwapchainInfoVk::AcquireImage()
|
||||
{
|
||||
ResetAvailableFence();
|
||||
|
||||
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)
|
||||
m_shouldRecreate = true;
|
||||
if (result == VK_TIMEOUT)
|
||||
@ -216,6 +245,7 @@ bool SwapchainInfoVk::AcquireImage()
|
||||
return false;
|
||||
}
|
||||
m_currentSemaphore = acquireSemaphore;
|
||||
m_awaitableFence = m_imageAvailableFence;
|
||||
m_acquireIndex = (m_acquireIndex + 1) % m_swapchainImages.size();
|
||||
|
||||
return true;
|
||||
@ -319,6 +349,7 @@ VkExtent2D SwapchainInfoVk::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& cap
|
||||
|
||||
VkPresentModeKHR SwapchainInfoVk::ChoosePresentMode(const std::vector<VkPresentModeKHR>& modes)
|
||||
{
|
||||
m_maxQueued = 0;
|
||||
const auto vsyncState = (VSync)GetConfig().vsync.GetValue();
|
||||
if (vsyncState == VSync::MAILBOX)
|
||||
{
|
||||
@ -345,6 +376,7 @@ VkPresentModeKHR SwapchainInfoVk::ChoosePresentMode(const std::vector<VkPresentM
|
||||
return VK_PRESENT_MODE_FIFO_KHR;
|
||||
}
|
||||
|
||||
m_maxQueued = 1;
|
||||
return VK_PRESENT_MODE_FIFO_KHR;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,9 @@ struct SwapchainInfoVk
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
void WaitAvailableFence();
|
||||
void ResetAvailableFence() const;
|
||||
|
||||
bool AcquireImage();
|
||||
// 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)
|
||||
@ -68,6 +71,9 @@ struct SwapchainInfoVk
|
||||
VkSwapchainKHR m_swapchain{};
|
||||
Vector2i m_desiredExtent{};
|
||||
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)
|
||||
@ -81,6 +87,8 @@ struct SwapchainInfoVk
|
||||
private:
|
||||
uint32 m_acquireIndex = 0;
|
||||
std::vector<VkSemaphore> m_acquireSemaphores; // indexed by m_acquireIndex
|
||||
VkFence m_imageAvailableFence{};
|
||||
VkFence m_awaitableFence = VK_NULL_HANDLE;
|
||||
VkSemaphore m_currentSemaphore = VK_NULL_HANDLE;
|
||||
|
||||
std::array<uint32, 2> m_swapchainQueueFamilyIndices;
|
||||
|
@ -188,6 +188,9 @@ VKFUNC_DEVICE(vkCmdPipelineBarrier2KHR);
|
||||
VKFUNC_DEVICE(vkCmdBeginRenderingKHR);
|
||||
VKFUNC_DEVICE(vkCmdEndRenderingKHR);
|
||||
|
||||
// khr_present_wait
|
||||
VKFUNC_DEVICE(vkWaitForPresentKHR);
|
||||
|
||||
// transform feedback extension
|
||||
VKFUNC_DEVICE(vkCmdBindTransformFeedbackBuffersEXT);
|
||||
VKFUNC_DEVICE(vkCmdBeginTransformFeedbackEXT);
|
||||
|
@ -826,7 +826,7 @@ void PipelineCompiler::InitDepthStencilState()
|
||||
|
||||
depthStencilState.front.reference = stencilRefFront;
|
||||
depthStencilState.front.compareMask = stencilCompareMaskFront;
|
||||
depthStencilState.front.writeMask = stencilWriteMaskBack;
|
||||
depthStencilState.front.writeMask = stencilWriteMaskFront;
|
||||
depthStencilState.front.compareOp = vkDepthCompareTable[(size_t)frontStencilFunc];
|
||||
depthStencilState.front.depthFailOp = stencilOpTable[(size_t)frontStencilZFail];
|
||||
depthStencilState.front.failOp = stencilOpTable[(size_t)frontStencilFail];
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "Cafe/HW/Latte/Core/LatteBufferCache.h"
|
||||
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
|
||||
#include "Cafe/HW/Latte/Core/LatteOverlay.h"
|
||||
|
||||
#include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h"
|
||||
|
||||
@ -29,6 +30,7 @@
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/intl.h> // for localization
|
||||
|
||||
#ifndef VK_API_VERSION_MAJOR
|
||||
#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_EXTERNAL_MEMORY_HOST_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 =
|
||||
@ -123,7 +127,7 @@ std::vector<VulkanRenderer::DeviceInfo> VulkanRenderer::GetDevices()
|
||||
VkApplicationInfo app_info{};
|
||||
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
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.engineVersion = app_info.applicationVersion;
|
||||
app_info.apiVersion = apiVersion;
|
||||
@ -250,12 +254,24 @@ void VulkanRenderer::GetDeviceFeatures()
|
||||
pcc.pNext = prevStruct;
|
||||
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{};
|
||||
physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
physicalDeviceFeatures2.pNext = prevStruct;
|
||||
|
||||
vkGetPhysicalDeviceFeatures2(m_physicalDevice, &physicalDeviceFeatures2);
|
||||
|
||||
cemuLog_log(LogType::Force, "Vulkan: present_wait extension: {}", (pwf.presentWait && pidf.presentId) ? "supported" : "unsupported");
|
||||
|
||||
/* Get Vulkan device properties and limits */
|
||||
VkPhysicalDeviceFloatControlsPropertiesKHR pfcp{};
|
||||
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");
|
||||
// if async shader compilation is enabled show warning message
|
||||
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)
|
||||
{
|
||||
@ -337,7 +353,7 @@ VulkanRenderer::VulkanRenderer()
|
||||
VkApplicationInfo app_info{};
|
||||
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
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.engineVersion = app_info.applicationVersion;
|
||||
app_info.apiVersion = apiVersion;
|
||||
@ -488,6 +504,24 @@ VulkanRenderer::VulkanRenderer()
|
||||
customBorderColorFeature.customBorderColors = 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;
|
||||
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);
|
||||
if (m_featureControl.deviceExtensions.shader_float_controls)
|
||||
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{};
|
||||
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.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
|
||||
info.deviceExtensions.present_wait = isExtensionAvailable(VK_KHR_PRESENT_WAIT_EXTENSION_NAME) && isExtensionAvailable(VK_KHR_PRESENT_ID_EXTENSION_NAME);
|
||||
|
||||
// check for framedebuggers
|
||||
info.debugMarkersSupported = false;
|
||||
@ -2198,6 +2237,8 @@ void VulkanRenderer::GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isD
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
// RGBA formats
|
||||
@ -2439,6 +2480,11 @@ void VulkanRenderer::GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isD
|
||||
// used by Color Splash and Resident Evil
|
||||
formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UINT; // todo - should we use ABGR format?
|
||||
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:
|
||||
cemuLog_log(LogType::Force, "Unsupported color texture format {:04x}", (uint32)format);
|
||||
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);
|
||||
}
|
||||
|
||||
const size_t currentFrameCmdBufferID = GetCurrentCommandBufferId();
|
||||
|
||||
VkSemaphore presentSemaphore = chainInfo.m_presentSemaphores[chainInfo.swapchainImageIndex];
|
||||
SubmitCommandBuffer(presentSemaphore); // submit all command and signal semaphore
|
||||
|
||||
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 = {};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
presentInfo.swapchainCount = 1;
|
||||
@ -2700,6 +2756,24 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
|
||||
presentInfo.waitSemaphoreCount = 1;
|
||||
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);
|
||||
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)
|
||||
chainInfo.m_shouldRecreate = true;
|
||||
|
||||
if(result >= 0)
|
||||
{
|
||||
chainInfo.m_queueDepth++;
|
||||
chainInfo.m_presentId++;
|
||||
}
|
||||
|
||||
chainInfo.hasDefinedSwapchainImage = false;
|
||||
|
||||
chainInfo.swapchainImageIndex = -1;
|
||||
|
@ -450,6 +450,7 @@ private:
|
||||
bool synchronization2 = false; // VK_KHR_synchronization2
|
||||
bool dynamic_rendering = false; // VK_KHR_dynamic_rendering
|
||||
bool shader_float_controls = false; // VK_KHR_shader_float_controls
|
||||
bool present_wait = false; // VK_KHR_present_wait
|
||||
}deviceExtensions;
|
||||
|
||||
struct
|
||||
@ -635,6 +636,7 @@ private:
|
||||
|
||||
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_commandBufferIDOfPrevFrame = 0;
|
||||
std::array<VkFence, kCommandBufferPoolSize> m_cmd_buffer_fences;
|
||||
std::array<VkCommandBuffer, kCommandBufferPoolSize> m_commandBuffers;
|
||||
std::array<VkSemaphore, kCommandBufferPoolSize> m_commandBufferSemaphores;
|
||||
|
406
src/Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.cpp
Normal file
406
src/Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
31
src/Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.h
Normal file
31
src/Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.h
Normal 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();
|
||||
}
|
||||
}
|
@ -511,6 +511,8 @@ namespace iosu
|
||||
return CallHandler_GetBlackList(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
||||
case FPD_REQUEST_ID::GetFriendListEx:
|
||||
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:
|
||||
return CallHandler_UpdatePreferenceAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
|
||||
case FPD_REQUEST_ID::AddFriendRequestByPlayRecordAsync:
|
||||
@ -719,18 +721,23 @@ namespace iosu
|
||||
|
||||
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)
|
||||
return FPResult_InvalidIPCParam;
|
||||
std::basic_string<uint16be> myComment;
|
||||
if(g_fpd.nexFriendSession)
|
||||
{
|
||||
if(vecOut->size != MY_COMMENT_LENGTH * sizeof(uint16be))
|
||||
{
|
||||
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
|
||||
return FPResult_InvalidIPCParam;
|
||||
}
|
||||
std::basic_string<uint16be> myComment;
|
||||
myComment.resize(MY_COMMENT_LENGTH);
|
||||
memcpy(vecOut->basePhys.GetPtr(), myComment.data(), MY_COMMENT_LENGTH*sizeof(uint16be));
|
||||
return 0;
|
||||
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)
|
||||
@ -1143,6 +1150,36 @@ namespace iosu
|
||||
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)
|
||||
{
|
||||
std::unique_lock _l(g_fpd.mtxFriendSession);
|
||||
|
@ -212,6 +212,7 @@ namespace iosu
|
||||
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 MY_COMMENT_LENGTH = 0x12;
|
||||
|
||||
enum class FPD_REQUEST_ID
|
||||
{
|
||||
@ -245,6 +246,7 @@ namespace iosu
|
||||
CheckSettingStatusAsync = 0x7596,
|
||||
GetFriendListEx = 0x75F9,
|
||||
GetFriendRequestListEx = 0x76C1,
|
||||
UpdateCommentAsync = 0x7726,
|
||||
UpdatePreferenceAsync = 0x7727,
|
||||
RemoveFriendAsync = 0x7789,
|
||||
DeleteFriendFlagsAsync = 0x778A,
|
||||
|
@ -23,3 +23,86 @@ void osLib_returnFromFunction64(PPCInterpreter_t* hCPU, uint64 returnValue64);
|
||||
|
||||
// utility functions
|
||||
#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;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#include "Cafe/OS/common/OSCommon.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"
|
||||
|
||||
@ -69,7 +69,7 @@ sint32 ScoreStackTrace(OSThread_t* thread, MPTR sp)
|
||||
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
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
#include "Cafe/HW/Espresso/PPCCallback.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))
|
||||
|
||||
namespace coreinit
|
||||
|
@ -7,14 +7,9 @@
|
||||
|
||||
namespace coreinit
|
||||
{
|
||||
|
||||
/* coreinit logging and string format */
|
||||
|
||||
sint32 ppcSprintf(const char* formatStr, char* strOut, sint32 maxLength, PPCInterpreter_t* hCPU, sint32 initialParamIndex)
|
||||
sint32 ppc_vprintf(const char* formatStr, char* strOut, sint32 maxLength, ppc_va_list* vargs)
|
||||
{
|
||||
char tempStr[4096];
|
||||
sint32 integerParamIndex = initialParamIndex;
|
||||
sint32 floatParamIndex = 0;
|
||||
sint32 writeIndex = 0;
|
||||
while (*formatStr)
|
||||
{
|
||||
@ -101,8 +96,7 @@ namespace coreinit
|
||||
tempFormat[(formatStr - formatStart)] = '\0';
|
||||
else
|
||||
tempFormat[sizeof(tempFormat) - 1] = '\0';
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU32(hCPU, integerParamIndex));
|
||||
integerParamIndex++;
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, (uint32)*(uint32be*)_ppc_va_arg(vargs, ppc_va_type::INT32));
|
||||
for (sint32 i = 0; i < tempLen; i++)
|
||||
{
|
||||
if (writeIndex >= maxLength)
|
||||
@ -120,13 +114,12 @@ namespace coreinit
|
||||
tempFormat[(formatStr - formatStart)] = '\0';
|
||||
else
|
||||
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;
|
||||
if (strOffset == MPTR_NULL)
|
||||
tempLen = sprintf(tempStr, "NULL");
|
||||
else
|
||||
tempLen = sprintf(tempStr, tempFormat, memory_getPointerFromVirtualOffset(strOffset));
|
||||
integerParamIndex++;
|
||||
for (sint32 i = 0; i < tempLen; i++)
|
||||
{
|
||||
if (writeIndex >= maxLength)
|
||||
@ -136,25 +129,6 @@ namespace coreinit
|
||||
}
|
||||
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')
|
||||
{
|
||||
// character
|
||||
@ -164,8 +138,24 @@ namespace coreinit
|
||||
tempFormat[(formatStr - formatStart)] = '\0';
|
||||
else
|
||||
tempFormat[sizeof(tempFormat) - 1] = '\0';
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU32(hCPU, integerParamIndex));
|
||||
integerParamIndex++;
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, (uint32)*(uint32be*)_ppc_va_arg(vargs, ppc_va_type::INT32));
|
||||
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++)
|
||||
{
|
||||
if (writeIndex >= maxLength)
|
||||
@ -183,8 +173,7 @@ namespace coreinit
|
||||
tempFormat[(formatStr - formatStart)] = '\0';
|
||||
else
|
||||
tempFormat[sizeof(tempFormat) - 1] = '\0';
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, (double)hCPU->fpr[1 + floatParamIndex].fp0);
|
||||
floatParamIndex++;
|
||||
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++)
|
||||
{
|
||||
if (writeIndex >= maxLength)
|
||||
@ -196,16 +185,13 @@ namespace coreinit
|
||||
else if ((formatStr[0] == 'l' && formatStr[1] == 'l' && (formatStr[2] == 'x' || formatStr[2] == 'X')))
|
||||
{
|
||||
formatStr += 3;
|
||||
// double (64bit)
|
||||
// 64bit int
|
||||
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';
|
||||
if (integerParamIndex & 1)
|
||||
integerParamIndex++;
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU64(hCPU, integerParamIndex));
|
||||
integerParamIndex += 2;
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, (uint64)*(uint64be*)_ppc_va_arg(vargs, ppc_va_type::INT64));
|
||||
for (sint32 i = 0; i < tempLen; i++)
|
||||
{
|
||||
if (writeIndex >= maxLength)
|
||||
@ -223,10 +209,7 @@ namespace coreinit
|
||||
tempFormat[(formatStr - formatStart)] = '\0';
|
||||
else
|
||||
tempFormat[sizeof(tempFormat) - 1] = '\0';
|
||||
if (integerParamIndex & 1)
|
||||
integerParamIndex++;
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, PPCInterpreter_getCallParamU64(hCPU, integerParamIndex));
|
||||
integerParamIndex += 2;
|
||||
sint32 tempLen = sprintf(tempStr, tempFormat, (sint64)*(sint64be*)_ppc_va_arg(vargs, ppc_va_type::INT64));
|
||||
for (sint32 i = 0; i < tempLen; i++)
|
||||
{
|
||||
if (writeIndex >= maxLength)
|
||||
@ -255,9 +238,12 @@ namespace coreinit
|
||||
return std::min(writeIndex, maxLength - 1);
|
||||
}
|
||||
|
||||
/* coreinit logging and string format */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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];
|
||||
sint32 len = ppcSprintf(format, buffer, sizeof(buffer), PPCInterpreter_getCurrentInstance(), 1);
|
||||
WriteCafeConsole(CafeLogType::OSCONSOLE, buffer, len);
|
||||
char tmpBuffer[1024];
|
||||
sint32 len = ppc_vprintf(format, tmpBuffer, sizeof(tmpBuffer), vargs);
|
||||
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)
|
||||
{
|
||||
char buffer[1024 * 2];
|
||||
int prefixLen = sprintf(buffer, "[COSWarn-%d] ", moduleId);
|
||||
sint32 len = ppcSprintf(format, buffer + prefixLen, sizeof(buffer) - prefixLen, PPCInterpreter_getCurrentInstance(), 2);
|
||||
WriteCafeConsole(CafeLogType::OSCONSOLE, buffer, len + prefixLen);
|
||||
ppc_define_va_list(2, 0);
|
||||
char tmpBuffer[1024];
|
||||
int prefixLen = sprintf(tmpBuffer, "[COSWarn-%d] ", moduleId);
|
||||
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)
|
||||
{
|
||||
char buffer[1024 * 2];
|
||||
int prefixLen = sprintf(buffer, "[OSLogPrintf-%d-%d-%d] ", ukn1, ukn2, ukn3);
|
||||
sint32 len = ppcSprintf(format, buffer + prefixLen, sizeof(buffer) - prefixLen, PPCInterpreter_getCurrentInstance(), 4);
|
||||
WriteCafeConsole(CafeLogType::OSCONSOLE, buffer, len + prefixLen);
|
||||
ppc_define_va_list(4, 0);
|
||||
char tmpBuffer[1024];
|
||||
int prefixLen = sprintf(tmpBuffer, "[OSLogPrintf-%d-%d-%d] ", ukn1, ukn2, ukn3);
|
||||
sint32 len = ppc_vprintf(format, tmpBuffer + prefixLen, sizeof(tmpBuffer) - prefixLen, &vargs);
|
||||
WriteCafeConsole(CafeLogType::OSCONSOLE, tmpBuffer, len + prefixLen);
|
||||
}
|
||||
|
||||
void OSConsoleWrite(const char* strPtr, sint32 length)
|
||||
@ -562,9 +556,11 @@ namespace coreinit
|
||||
s_transitionToForeground = false;
|
||||
|
||||
cafeExportRegister("coreinit", __os_snprintf, LogType::Placeholder);
|
||||
|
||||
cafeExportRegister("coreinit", COSVReport, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", COSWarn, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSReport, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSVReport, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", COSWarn, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSLogPrintf, LogType::Placeholder);
|
||||
cafeExportRegister("coreinit", OSConsoleWrite, LogType::Placeholder);
|
||||
|
||||
|
@ -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_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();
|
||||
};
|
@ -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
|
||||
// to avoid an infinite loop we have no choice but to yield the thread even it is in an uninterruptible state
|
||||
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))
|
||||
{
|
||||
OSYieldThread();
|
||||
|
@ -310,7 +310,7 @@ namespace coreinit
|
||||
currentThread->mutexQueue.removeMutex(mutex);
|
||||
mutex->owner = nullptr;
|
||||
if (!mutex->threadQueue.isEmpty())
|
||||
mutex->threadQueue.wakeupSingleThreadWaitQueue(true);
|
||||
mutex->threadQueue.wakeupSingleThreadWaitQueue(true, true);
|
||||
}
|
||||
// currentThread->cancelState = currentThread->cancelState & ~0x10000;
|
||||
}
|
||||
|
@ -14,13 +14,10 @@ namespace coreinit
|
||||
return coreinit::MEMAllocFromExpHeapEx(_sysHeapHandle, size, alignment);
|
||||
}
|
||||
|
||||
void export_OSAllocFromSystem(PPCInterpreter_t* hCPU)
|
||||
void OSFreeToSystem(void* ptr)
|
||||
{
|
||||
ppcDefineParamU32(size, 0);
|
||||
ppcDefineParamS32(alignment, 1);
|
||||
MEMPTR<void> mem = OSAllocFromSystem(size, alignment);
|
||||
cemuLog_logDebug(LogType::Force, "OSAllocFromSystem(0x{:x}, {}) -> 0x{:08x}", size, alignment, mem.GetMPTR());
|
||||
osLib_returnFromFunction(hCPU, mem.GetMPTR());
|
||||
_sysHeapFreeCounter++;
|
||||
coreinit::MEMFreeToExpHeap(_sysHeapHandle, ptr);
|
||||
}
|
||||
|
||||
void InitSysHeap()
|
||||
@ -34,7 +31,8 @@ namespace coreinit
|
||||
|
||||
void InitializeSysHeap()
|
||||
{
|
||||
osLib_addFunction("coreinit", "OSAllocFromSystem", export_OSAllocFromSystem);
|
||||
cafeExportRegister("h264", OSAllocFromSystem, LogType::CoreinitMem);
|
||||
cafeExportRegister("h264", OSFreeToSystem, LogType::CoreinitMem);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,5 +4,8 @@ namespace coreinit
|
||||
{
|
||||
void InitSysHeap();
|
||||
|
||||
void* OSAllocFromSystem(uint32 size, uint32 alignment);
|
||||
void OSFreeToSystem(void* ptr);
|
||||
|
||||
void InitializeSysHeap();
|
||||
}
|
@ -758,14 +758,14 @@ namespace coreinit
|
||||
}
|
||||
|
||||
// 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();
|
||||
if (!newThread->context.hasCoreAffinitySet(coreIndex))
|
||||
return false;
|
||||
// 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
|
||||
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;
|
||||
// otherwise reschedule if new thread has higher priority
|
||||
return newThread->effectivePriority < currentThread->effectivePriority;
|
||||
@ -791,7 +791,7 @@ namespace coreinit
|
||||
// todo - only set this once?
|
||||
thread->wakeUpTime = PPCInterpreter_getMainCoreCycleCounter();
|
||||
// reschedule if thread has higher priority
|
||||
if (PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread))
|
||||
if (PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread, false))
|
||||
PPCCore_switchToSchedulerWithLock();
|
||||
}
|
||||
return previousSuspendCount;
|
||||
@ -948,7 +948,7 @@ namespace coreinit
|
||||
OSThread_t* currentThread = OSGetCurrentThread();
|
||||
if (currentThread && currentThread != thread)
|
||||
{
|
||||
if (__OSCoreShouldSwitchToThread(currentThread, thread))
|
||||
if (__OSCoreShouldSwitchToThread(currentThread, thread, false))
|
||||
PPCCore_switchToSchedulerWithLock();
|
||||
}
|
||||
__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)];
|
||||
}
|
||||
|
@ -126,8 +126,8 @@ namespace coreinit
|
||||
|
||||
// counterparts for queueAndWait
|
||||
void cancelWait(OSThread_t* thread);
|
||||
void wakeupEntireWaitQueue(bool reschedule);
|
||||
void wakeupSingleThreadWaitQueue(bool reschedule);
|
||||
void wakeupEntireWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround = false);
|
||||
void wakeupSingleThreadWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround = false);
|
||||
|
||||
private:
|
||||
OSThread_t* takeFirstFromQueue(size_t linkOffset)
|
||||
@ -611,7 +611,7 @@ namespace coreinit
|
||||
|
||||
// internal
|
||||
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);
|
||||
|
||||
bool __OSIsThreadActive(OSThread_t* thread);
|
||||
@ -621,11 +621,6 @@ namespace coreinit
|
||||
#pragma pack()
|
||||
|
||||
// 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 sint32 activeThreadCount;
|
||||
|
||||
|
@ -128,7 +128,8 @@ namespace coreinit
|
||||
|
||||
// counterpart for queueAndWait
|
||||
// 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());
|
||||
bool shouldReschedule = false;
|
||||
@ -139,7 +140,7 @@ namespace coreinit
|
||||
thread->state = OSThread_t::THREAD_STATE::STATE_READY;
|
||||
thread->currentWaitQueue = nullptr;
|
||||
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;
|
||||
}
|
||||
if (shouldReschedule)
|
||||
@ -148,7 +149,7 @@ namespace coreinit
|
||||
|
||||
// counterpart for queueAndWait
|
||||
// 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());
|
||||
OSThread_t* thread = takeFirstFromQueue(offsetof(OSThread_t, waitQueueLink));
|
||||
@ -159,7 +160,7 @@ namespace coreinit
|
||||
thread->state = OSThread_t::THREAD_STATE::STATE_READY;
|
||||
thread->currentWaitQueue = nullptr;
|
||||
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;
|
||||
}
|
||||
if (shouldReschedule)
|
||||
|
@ -154,14 +154,6 @@ namespace GX2
|
||||
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 coreIndex = sGX2MainCoreIndex;
|
||||
|
@ -84,8 +84,6 @@ inline void gx2WriteGather_submit(Targs... args)
|
||||
|
||||
namespace GX2
|
||||
{
|
||||
|
||||
bool GX2WriteGather_isDisplayListActive();
|
||||
uint32 GX2WriteGather_getReadWriteDistance();
|
||||
void GX2WriteGather_checkAndInsertWrapAroundMark();
|
||||
|
||||
@ -96,6 +94,8 @@ namespace GX2
|
||||
void GX2CallDisplayList(MPTR addr, uint32 size);
|
||||
void GX2DirectCallDisplayList(void* addr, uint32 size);
|
||||
|
||||
bool GX2GetDisplayListWriteStatus();
|
||||
|
||||
void GX2Init_writeGather();
|
||||
void GX2CommandInit();
|
||||
void GX2CommandResetToDefaultState();
|
||||
|
@ -291,8 +291,7 @@ void gx2Export_GX2SetDefaultState(PPCInterpreter_t* hCPU)
|
||||
void _GX2ContextCreateRestoreStateDL(GX2ContextState_t* gx2ContextState)
|
||||
{
|
||||
// begin display list
|
||||
if (GX2::GX2WriteGather_isDisplayListActive())
|
||||
assert_dbg();
|
||||
cemu_assert_debug(!GX2::GX2GetDisplayListWriteStatus()); // must not already be writing to a display list
|
||||
GX2::GX2BeginDisplayList((void*)gx2ContextState->loadDL_buffer, sizeof(gx2ContextState->loadDL_buffer));
|
||||
_GX2Context_WriteCmdRestoreState(gx2ContextState, 0);
|
||||
uint32 displayListSize = GX2::GX2EndDisplayList((void*)gx2ContextState->loadDL_buffer);
|
||||
|
@ -426,7 +426,7 @@ namespace GX2
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
@ -1,17 +1,12 @@
|
||||
#include "Cafe/OS/common/OSCommon.h"
|
||||
#include "Cafe/HW/Espresso/PPCCallback.h"
|
||||
#include "Cafe/OS/libs/h264_avc/parser/H264Parser.h"
|
||||
#include "Cafe/OS/libs/h264_avc/H264DecInternal.h"
|
||||
#include "util/highresolutiontimer/HighResolutionTimer.h"
|
||||
#include "Cafe/CafeSystem.h"
|
||||
|
||||
#include "h264dec.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "../dependencies/ih264d/common/ih264_typedefs.h"
|
||||
#include "../dependencies/ih264d/decoder/ih264d.h"
|
||||
};
|
||||
|
||||
enum class H264DEC_STATUS : uint32
|
||||
{
|
||||
SUCCESS = 0x0,
|
||||
@ -33,10 +28,35 @@ namespace H264
|
||||
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)
|
||||
{
|
||||
if (H264_IsBotW())
|
||||
{
|
||||
static_assert(sizeof(H264Context) < 256);
|
||||
*sizeRequirementOut = 256;
|
||||
return 0;
|
||||
}
|
||||
@ -169,591 +189,48 @@ namespace H264
|
||||
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)
|
||||
{
|
||||
cemu_assert(offset <= length);
|
||||
|
||||
uint32 imageWidth, imageHeight;
|
||||
|
||||
if (H264AVCDecoder::GetImageInfo(stream, length, imageWidth, imageHeight))
|
||||
if(!stream || length < 4 || !outputWidth || !outputHeight)
|
||||
return H264DEC_STATUS::INVALID_PARAM;
|
||||
if( (offset+4) > length )
|
||||
return H264DEC_STATUS::INVALID_PARAM;
|
||||
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)
|
||||
imageHeight = 1080;
|
||||
cur++;
|
||||
continue;
|
||||
}
|
||||
*outputWidth = imageWidth;
|
||||
*outputHeight = imageHeight;
|
||||
}
|
||||
else
|
||||
// check if this is a valid NAL header
|
||||
if(cur[-2] != 0 || cur[-1] != 0 || cur[0] != 1)
|
||||
{
|
||||
*outputWidth = 0;
|
||||
*outputHeight = 0;
|
||||
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;
|
||||
}
|
||||
return H264DEC_STATUS::BAD_STREAM;
|
||||
}
|
||||
|
||||
uint32 H264DECInitParam(uint32 workMemorySize, void* workMemory)
|
||||
{
|
||||
@ -762,26 +239,28 @@ namespace H264
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unordered_map<uint32, H264AVCDecoder*> sDecoderSessions;
|
||||
std::unordered_map<uint32, H264DecoderBackend*> sDecoderSessions;
|
||||
std::mutex sDecoderSessionsMutex;
|
||||
std::atomic_uint32_t sCurrentSessionHandle{ 1 };
|
||||
|
||||
static H264AVCDecoder* _CreateDecoderSession(uint32& handleOut)
|
||||
H264DecoderBackend* CreateAVCDecoder();
|
||||
|
||||
static H264DecoderBackend* _CreateDecoderSession(uint32& handleOut)
|
||||
{
|
||||
std::unique_lock _lock(sDecoderSessionsMutex);
|
||||
handleOut = sCurrentSessionHandle.fetch_add(1);
|
||||
H264AVCDecoder* session = new H264AVCDecoder();
|
||||
H264DecoderBackend* session = CreateAVCDecoder();
|
||||
sDecoderSessions.try_emplace(handleOut, session);
|
||||
return session;
|
||||
}
|
||||
|
||||
static H264AVCDecoder* _AcquireDecoderSession(uint32 handle)
|
||||
static H264DecoderBackend* _AcquireDecoderSession(uint32 handle)
|
||||
{
|
||||
std::unique_lock _lock(sDecoderSessionsMutex);
|
||||
auto it = sDecoderSessions.find(handle);
|
||||
if (it == sDecoderSessions.end())
|
||||
return nullptr;
|
||||
H264AVCDecoder* session = it->second;
|
||||
H264DecoderBackend* session = it->second;
|
||||
if (sDecoderSessions.size() >= 5)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "H264: Warning - more than 5 active sessions");
|
||||
@ -790,7 +269,7 @@ namespace H264
|
||||
return session;
|
||||
}
|
||||
|
||||
static void _ReleaseDecoderSession(H264AVCDecoder* session)
|
||||
static void _ReleaseDecoderSession(H264DecoderBackend* session)
|
||||
{
|
||||
std::unique_lock _lock(sDecoderSessionsMutex);
|
||||
|
||||
@ -802,7 +281,7 @@ namespace H264
|
||||
auto it = sDecoderSessions.find(handle);
|
||||
if (it == sDecoderSessions.end())
|
||||
return;
|
||||
H264AVCDecoder* session = it->second;
|
||||
H264DecoderBackend* session = it->second;
|
||||
session->Destroy();
|
||||
delete session;
|
||||
sDecoderSessions.erase(it);
|
||||
@ -830,45 +309,44 @@ namespace H264
|
||||
uint32 H264DECBegin(void* workMemory)
|
||||
{
|
||||
H264Context* ctx = (H264Context*)workMemory;
|
||||
H264AVCDecoder* session = _AcquireDecoderSession(ctx->sessionHandle);
|
||||
H264DecoderBackend* session = _AcquireDecoderSession(ctx->sessionHandle);
|
||||
if (!session)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "H264DECBegin(): Invalid session");
|
||||
return 0;
|
||||
}
|
||||
session->Init(ctx->Param.outputPerFrame == 0);
|
||||
ctx->decoderState.numFramesInFlight = 0;
|
||||
_ReleaseDecoderSession(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void H264DoFrameOutputCallback(H264Context* ctx, H264AVCDecoder::DecodeResult& decodeResult);
|
||||
|
||||
void _async_H264DECEnd(coreinit::OSEvent* executeDoneEvent, H264AVCDecoder* session, H264Context* ctx, std::vector<H264AVCDecoder::DecodeResult>* decodeResultsOut)
|
||||
{
|
||||
*decodeResultsOut = session->Flush();
|
||||
coreinit::OSSignalEvent(executeDoneEvent);
|
||||
}
|
||||
void H264DoFrameOutputCallback(H264Context* ctx, H264DecoderBackend::DecodeResult& decodeResult);
|
||||
|
||||
H264DEC_STATUS H264DECEnd(void* workMemory)
|
||||
{
|
||||
H264Context* ctx = (H264Context*)workMemory;
|
||||
H264AVCDecoder* session = _AcquireDecoderSession(ctx->sessionHandle);
|
||||
H264DecoderBackend* session = _AcquireDecoderSession(ctx->sessionHandle);
|
||||
if (!session)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "H264DECEnd(): Invalid session");
|
||||
return H264DEC_STATUS::SUCCESS;
|
||||
}
|
||||
StackAllocator<coreinit::OSEvent> executeDoneEvent;
|
||||
coreinit::OSInitEvent(&executeDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
||||
std::vector<H264AVCDecoder::DecodeResult> results;
|
||||
auto asyncTask = std::async(std::launch::async, _async_H264DECEnd, executeDoneEvent.GetPointer(), session, ctx, &results);
|
||||
coreinit::OSWaitEvent(&executeDoneEvent);
|
||||
_ReleaseDecoderSession(session);
|
||||
if (!results.empty())
|
||||
coreinit::OSEvent* flushEvt = &session->GetFlushEvent();
|
||||
coreinit::OSResetEvent(flushEvt);
|
||||
session->QueueFlush();
|
||||
coreinit::OSWaitEvent(flushEvt);
|
||||
while(true)
|
||||
{
|
||||
for (auto& itr : results)
|
||||
H264DoFrameOutputCallback(ctx, itr);
|
||||
H264DecoderBackend::DecodeResult decodeResult;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -930,7 +408,6 @@ namespace H264
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct H264DECFrameOutput
|
||||
{
|
||||
/* +0x00 */ uint32be result;
|
||||
@ -967,7 +444,7 @@ namespace H264
|
||||
|
||||
static_assert(sizeof(H264OutputCBStruct) == 12);
|
||||
|
||||
void H264DoFrameOutputCallback(H264Context* ctx, H264AVCDecoder::DecodeResult& decodeResult)
|
||||
void H264DoFrameOutputCallback(H264Context* ctx, H264DecoderBackend::DecodeResult& decodeResult)
|
||||
{
|
||||
sint32 outputFrameCount = 1;
|
||||
|
||||
@ -984,14 +461,14 @@ namespace H264
|
||||
frameOutput->imagePtr = (uint8*)decodeResult.imageOutput;
|
||||
frameOutput->result = 100;
|
||||
frameOutput->timestamp = decodeResult.timestamp;
|
||||
frameOutput->frameWidth = decodeResult.decodeOutput.u4_pic_wd;
|
||||
frameOutput->frameHeight = decodeResult.decodeOutput.u4_pic_ht;
|
||||
frameOutput->bytesPerRow = (decodeResult.decodeOutput.u4_pic_wd + 0xFF) & ~0xFF;
|
||||
frameOutput->cropEnable = decodeResult.decodeOutput.u1_frame_cropping_flag;
|
||||
frameOutput->cropTop = decodeResult.decodeOutput.u1_frame_cropping_rect_top_ofst;
|
||||
frameOutput->cropBottom = decodeResult.decodeOutput.u1_frame_cropping_rect_bottom_ofst;
|
||||
frameOutput->cropLeft = decodeResult.decodeOutput.u1_frame_cropping_rect_left_ofst;
|
||||
frameOutput->cropRight = decodeResult.decodeOutput.u1_frame_cropping_rect_right_ofst;
|
||||
frameOutput->frameWidth = decodeResult.frameWidth;
|
||||
frameOutput->frameHeight = decodeResult.frameHeight;
|
||||
frameOutput->bytesPerRow = decodeResult.bytesPerRow;
|
||||
frameOutput->cropEnable = decodeResult.cropEnable;
|
||||
frameOutput->cropTop = decodeResult.cropTop;
|
||||
frameOutput->cropBottom = decodeResult.cropBottom;
|
||||
frameOutput->cropLeft = decodeResult.cropLeft;
|
||||
frameOutput->cropRight = decodeResult.cropRight;
|
||||
|
||||
StackAllocator<H264OutputCBStruct> stack_fptrOutputData;
|
||||
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)
|
||||
{
|
||||
BenchmarkTimer bt;
|
||||
bt.Start();
|
||||
H264Context* ctx = (H264Context*)workMemory;
|
||||
H264AVCDecoder* session = _AcquireDecoderSession(ctx->sessionHandle);
|
||||
H264DecoderBackend* session = _AcquireDecoderSession(ctx->sessionHandle);
|
||||
if (!session)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "H264DECExecute(): Invalid session");
|
||||
return 0;
|
||||
}
|
||||
StackAllocator<coreinit::OSEvent> executeDoneEvent;
|
||||
coreinit::OSInitEvent(&executeDoneEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_MANUAL);
|
||||
H264AVCDecoder::DecodeResult decodeResult;
|
||||
auto asyncTask = std::async(std::launch::async, _async_H264DECExecute, &executeDoneEvent, session, ctx, imageOutput , &decodeResult);
|
||||
coreinit::OSWaitEvent(&executeDoneEvent);
|
||||
_ReleaseDecoderSession(session);
|
||||
if(decodeResult.frameReady)
|
||||
// feed data to backend
|
||||
session->QueueForDecode((uint8*)ctx->BitStream.ptr.GetPtr(), ctx->BitStream.length, ctx->BitStream.timestamp, imageOutput);
|
||||
ctx->decoderState.numFramesInFlight++;
|
||||
// H264DECExecute is synchronous and will return a frame after either every call (non-buffered) or after 6 calls (buffered)
|
||||
// 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);
|
||||
bt.Stop();
|
||||
double callTime = bt.GetElapsedMilliseconds();
|
||||
cemuLog_log(LogType::H264, "H264Bench | H264DECExecute took {}ms", callTime);
|
||||
return 0x80 | 100;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user