Compare commits
1 commit
master
...
revert-115
Author | SHA1 | Date | |
---|---|---|---|
|
42f4c8f28b |
1946 changed files with 98120 additions and 203985 deletions
|
@ -6,24 +6,10 @@
|
||||||
export NDK_CCACHE="$(which ccache)"
|
export NDK_CCACHE="$(which ccache)"
|
||||||
ccache -s
|
ccache -s
|
||||||
|
|
||||||
BUILD_FLAVOR="mainline"
|
BUILD_FLAVOR=mainline
|
||||||
|
|
||||||
BUILD_TYPE="release"
|
|
||||||
if [ "${GITHUB_REPOSITORY}" == "yuzu-emu/yuzu" ]; then
|
|
||||||
BUILD_TYPE="relWithDebInfo"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
|
|
||||||
export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
|
|
||||||
base64 --decode <<< "${ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd src/android
|
cd src/android
|
||||||
chmod +x ./gradlew
|
chmod +x ./gradlew
|
||||||
./gradlew "assemble${BUILD_FLAVOR}${BUILD_TYPE}" "bundle${BUILD_FLAVOR}${BUILD_TYPE}"
|
./gradlew "assemble${BUILD_FLAVOR}Release" "bundle${BUILD_FLAVOR}Release"
|
||||||
|
|
||||||
ccache -s
|
ccache -s
|
||||||
|
|
||||||
if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
|
|
||||||
rm "${ANDROID_KEYSTORE_FILE}"
|
|
||||||
fi
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
#!/bin/bash -ex
|
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
export NDK_CCACHE="$(which ccache)"
|
|
||||||
ccache -s
|
|
||||||
|
|
||||||
export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
|
|
||||||
base64 --decode <<< "${EA_PLAY_ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
|
|
||||||
export ANDROID_KEY_ALIAS="${PLAY_ANDROID_KEY_ALIAS}"
|
|
||||||
export ANDROID_KEYSTORE_PASS="${PLAY_ANDROID_KEYSTORE_PASS}"
|
|
||||||
export SERVICE_ACCOUNT_KEY_PATH="${GITHUB_WORKSPACE}/sa.json"
|
|
||||||
base64 --decode <<< "${EA_SERVICE_ACCOUNT_KEY_B64}" > "${SERVICE_ACCOUNT_KEY_PATH}"
|
|
||||||
./gradlew "publishEaReleaseBundle"
|
|
||||||
|
|
||||||
ccache -s
|
|
||||||
|
|
||||||
if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
|
|
||||||
rm "${ANDROID_KEYSTORE_FILE}"
|
|
||||||
fi
|
|
|
@ -1,21 +0,0 @@
|
||||||
#!/bin/bash -ex
|
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
export NDK_CCACHE="$(which ccache)"
|
|
||||||
ccache -s
|
|
||||||
|
|
||||||
export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
|
|
||||||
base64 --decode <<< "${MAINLINE_PLAY_ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
|
|
||||||
export ANDROID_KEY_ALIAS="${PLAY_ANDROID_KEY_ALIAS}"
|
|
||||||
export ANDROID_KEYSTORE_PASS="${PLAY_ANDROID_KEYSTORE_PASS}"
|
|
||||||
export SERVICE_ACCOUNT_KEY_PATH="${GITHUB_WORKSPACE}/sa.json"
|
|
||||||
base64 --decode <<< "${MAINLINE_SERVICE_ACCOUNT_KEY_B64}" > "${SERVICE_ACCOUNT_KEY_PATH}"
|
|
||||||
./gradlew "publishMainlineReleaseBundle"
|
|
||||||
|
|
||||||
ccache -s
|
|
||||||
|
|
||||||
if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
|
|
||||||
rm "${ANDROID_KEYSTORE_FILE}"
|
|
||||||
fi
|
|
|
@ -7,16 +7,21 @@
|
||||||
|
|
||||||
REV_NAME="yuzu-${GITDATE}-${GITREV}"
|
REV_NAME="yuzu-${GITDATE}-${GITREV}"
|
||||||
|
|
||||||
BUILD_FLAVOR="mainline"
|
BUILD_FLAVOR=mainline
|
||||||
|
|
||||||
BUILD_TYPE_LOWER="release"
|
cp src/android/app/build/outputs/apk/"${BUILD_FLAVOR}/release/app-${BUILD_FLAVOR}-release.apk" \
|
||||||
BUILD_TYPE_UPPER="Release"
|
|
||||||
if [ "${GITHUB_REPOSITORY}" == "yuzu-emu/yuzu" ]; then
|
|
||||||
BUILD_TYPE_LOWER="relWithDebInfo"
|
|
||||||
BUILD_TYPE_UPPER="RelWithDebInfo"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp src/android/app/build/outputs/apk/"${BUILD_FLAVOR}/${BUILD_TYPE_LOWER}/app-${BUILD_FLAVOR}-${BUILD_TYPE_LOWER}.apk" \
|
|
||||||
"artifacts/${REV_NAME}.apk"
|
"artifacts/${REV_NAME}.apk"
|
||||||
cp src/android/app/build/outputs/bundle/"${BUILD_FLAVOR}${BUILD_TYPE_UPPER}"/"app-${BUILD_FLAVOR}-${BUILD_TYPE_LOWER}.aab" \
|
cp src/android/app/build/outputs/bundle/"${BUILD_FLAVOR}Release"/"app-${BUILD_FLAVOR}-release.aab" \
|
||||||
"artifacts/${REV_NAME}.aab"
|
"artifacts/${REV_NAME}.aab"
|
||||||
|
|
||||||
|
if [ -n "${ANDROID_KEYSTORE_B64}" ]
|
||||||
|
then
|
||||||
|
echo "Signing apk..."
|
||||||
|
base64 --decode <<< "${ANDROID_KEYSTORE_B64}" > ks.jks
|
||||||
|
|
||||||
|
apksigner sign --ks ks.jks \
|
||||||
|
--ks-key-alias "${ANDROID_KEY_ALIAS}" \
|
||||||
|
--ks-pass env:ANDROID_KEYSTORE_PASS "artifacts/${REV_NAME}.apk"
|
||||||
|
else
|
||||||
|
echo "No keystore specified, not signing the APK files."
|
||||||
|
fi
|
||||||
|
|
|
@ -19,7 +19,6 @@ cmake .. \
|
||||||
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
||||||
-DENABLE_QT_TRANSLATION=ON \
|
-DENABLE_QT_TRANSLATION=ON \
|
||||||
-DUSE_DISCORD_PRESENCE=ON \
|
-DUSE_DISCORD_PRESENCE=ON \
|
||||||
-DYUZU_CRASH_DUMPS=ON \
|
|
||||||
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
||||||
-DYUZU_USE_BUNDLED_FFMPEG=ON \
|
-DYUZU_USE_BUNDLED_FFMPEG=ON \
|
||||||
-GNinja
|
-GNinja
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
|
|
||||||
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
|
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
|
||||||
GITREV="`git show -s --format='%h'`"
|
GITREV="`git show -s --format='%h'`"
|
||||||
ARTIFACTS_DIR="$PWD/artifacts"
|
ARTIFACTS_DIR="artifacts"
|
||||||
|
|
||||||
mkdir -p "${ARTIFACTS_DIR}/"
|
mkdir -p "${ARTIFACTS_DIR}/"
|
||||||
|
|
|
@ -3,35 +3,38 @@
|
||||||
# SPDX-FileCopyrightText: 2019 yuzu Emulator Project
|
# SPDX-FileCopyrightText: 2019 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
shopt -s nullglob globstar
|
if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dist/*.desktop \
|
||||||
|
dist/*.svg dist/*.xml; then
|
||||||
if git grep -nrI '\s$' src **/*.yml **/*.txt **/*.md Doxyfile .gitignore .gitmodules .ci* dist/*.desktop dist/*.svg dist/*.xml; then
|
|
||||||
echo Trailing whitespace found, aborting
|
echo Trailing whitespace found, aborting
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Default clang-format points to default 3.5 version one
|
# Default clang-format points to default 3.5 version one
|
||||||
CLANG_FORMAT="${CLANG_FORMAT:-clang-format-15}"
|
CLANG_FORMAT=${CLANG_FORMAT:-clang-format-15}
|
||||||
"$CLANG_FORMAT" --version
|
$CLANG_FORMAT --version
|
||||||
|
|
||||||
|
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
|
||||||
|
# Get list of every file modified in this pull request
|
||||||
|
files_to_lint="$(git diff --name-only --diff-filter=ACMRTUXB $TRAVIS_COMMIT_RANGE | grep '^src/[^.]*[.]\(cpp\|h\)$' || true)"
|
||||||
|
else
|
||||||
|
# Check everything for branch pushes
|
||||||
|
files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')"
|
||||||
|
fi
|
||||||
|
|
||||||
# Turn off tracing for this because it's too verbose
|
# Turn off tracing for this because it's too verbose
|
||||||
set +x
|
set +x
|
||||||
|
|
||||||
# Check everything for branch pushes
|
for f in $files_to_lint; do
|
||||||
FILES_TO_LINT="$(find src/ -name '*.cpp' -or -name '*.h')"
|
d=$(diff -u "$f" <($CLANG_FORMAT "$f") || true)
|
||||||
|
if ! [ -z "$d" ]; then
|
||||||
for f in $FILES_TO_LINT; do
|
echo "!!! $f not compliant to coding style, here is the fix:"
|
||||||
echo "$f"
|
echo "$d"
|
||||||
"$CLANG_FORMAT" -i "$f"
|
fail=1
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
DIFF=$(git -c core.fileMode=false diff)
|
set -x
|
||||||
|
|
||||||
if [ ! -z "$DIFF" ]; then
|
if [ "$fail" = 1 ]; then
|
||||||
echo "!!! Not compliant to coding style, here is the fix:"
|
|
||||||
echo "$DIFF"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd src/android
|
|
||||||
./gradlew ktlintCheck
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ ccache -s
|
||||||
mkdir build || true && cd build
|
mkdir build || true && cd build
|
||||||
cmake .. \
|
cmake .. \
|
||||||
-DBoost_USE_STATIC_LIBS=ON \
|
-DBoost_USE_STATIC_LIBS=ON \
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
|
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
|
||||||
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
|
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
|
||||||
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
|
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
|
||||||
|
@ -23,7 +23,6 @@ cmake .. \
|
||||||
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
||||||
-DYUZU_USE_BUNDLED_FFMPEG=ON \
|
-DYUZU_USE_BUNDLED_FFMPEG=ON \
|
||||||
-DYUZU_ENABLE_LTO=ON \
|
-DYUZU_ENABLE_LTO=ON \
|
||||||
-DYUZU_CRASH_DUMPS=ON \
|
|
||||||
-GNinja
|
-GNinja
|
||||||
|
|
||||||
ninja
|
ninja
|
||||||
|
@ -32,19 +31,6 @@ ccache -s
|
||||||
|
|
||||||
ctest -VV -C Release
|
ctest -VV -C Release
|
||||||
|
|
||||||
# Separate debug symbols from specified executables
|
|
||||||
for EXE in yuzu; do
|
|
||||||
EXE_PATH="bin/$EXE"
|
|
||||||
# Copy debug symbols out
|
|
||||||
objcopy --only-keep-debug $EXE_PATH $EXE_PATH.debug
|
|
||||||
# Add debug link and strip debug symbols
|
|
||||||
objcopy -g --add-gnu-debuglink=$EXE_PATH.debug $EXE_PATH $EXE_PATH.out
|
|
||||||
# Overwrite original with stripped copy
|
|
||||||
mv $EXE_PATH.out $EXE_PATH
|
|
||||||
done
|
|
||||||
# Strip debug symbols from all executables
|
|
||||||
find bin/ -type f -not -regex '.*.debug' -exec strip -g {} ';'
|
|
||||||
|
|
||||||
DESTDIR="$PWD/AppDir" ninja install
|
DESTDIR="$PWD/AppDir" ninja install
|
||||||
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester
|
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,4 @@ if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ];
|
||||||
cp "build/${APPIMAGE_NAME}" "${DIR_NAME}/yuzu-${RELEASE_NAME}.AppImage"
|
cp "build/${APPIMAGE_NAME}" "${DIR_NAME}/yuzu-${RELEASE_NAME}.AppImage"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy debug symbols to artifacts
|
|
||||||
cd build/bin
|
|
||||||
tar $COMPRESSION_FLAGS "${ARTIFACTS_DIR}/${REV_NAME}-debug.tar.xz" *.debug
|
|
||||||
cd -
|
|
||||||
|
|
||||||
. .ci/scripts/common/post-upload.sh
|
. .ci/scripts/common/post-upload.sh
|
||||||
|
|
|
@ -17,6 +17,7 @@ cmake .. \
|
||||||
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
||||||
-DENABLE_QT_TRANSLATION=ON \
|
-DENABLE_QT_TRANSLATION=ON \
|
||||||
-DUSE_CCACHE=ON \
|
-DUSE_CCACHE=ON \
|
||||||
|
-DYUZU_CRASH_DUMPS=ON \
|
||||||
-DYUZU_USE_BUNDLED_SDL2=OFF \
|
-DYUZU_USE_BUNDLED_SDL2=OFF \
|
||||||
-DYUZU_USE_EXTERNAL_SDL2=OFF \
|
-DYUZU_USE_EXTERNAL_SDL2=OFF \
|
||||||
-DYUZU_TESTS=OFF \
|
-DYUZU_TESTS=OFF \
|
||||||
|
|
|
@ -8,7 +8,17 @@ variables:
|
||||||
DisplayVersion: $[counter(variables['DisplayPrefix'], 1)]
|
DisplayVersion: $[counter(variables['DisplayPrefix'], 1)]
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
|
- stage: format
|
||||||
|
displayName: 'format'
|
||||||
|
jobs:
|
||||||
|
- job: format
|
||||||
|
displayName: 'clang'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- template: ./templates/format-check.yml
|
||||||
- stage: build
|
- stage: build
|
||||||
|
dependsOn: format
|
||||||
displayName: 'build'
|
displayName: 'build'
|
||||||
jobs:
|
jobs:
|
||||||
- job: build
|
- job: build
|
||||||
|
@ -33,6 +43,7 @@ stages:
|
||||||
cache: 'true'
|
cache: 'true'
|
||||||
version: $(DisplayVersion)
|
version: $(DisplayVersion)
|
||||||
- stage: build_win
|
- stage: build_win
|
||||||
|
dependsOn: format
|
||||||
displayName: 'build-windows'
|
displayName: 'build-windows'
|
||||||
jobs:
|
jobs:
|
||||||
- job: build
|
- job: build
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
[codespell]
|
[codespell]
|
||||||
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
|
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
|
||||||
ignore-words-list = aci,allright,ba,canonicalizations,deques,fpr,froms,hda,inout,lod,masia,nam,nax,nce,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,vas,zink
|
ignore-words-list = aci,allright,ba,canonicalizations,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,zink
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
# CRLF -> LF
|
|
||||||
90aa937593e53a5d5e070fb623b228578b0b225f
|
|
2
.github/workflows/android-build.yml
vendored
2
.github/workflows/android-build.yml
vendored
|
@ -40,11 +40,11 @@ jobs:
|
||||||
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
||||||
- name: Build
|
- name: Build
|
||||||
run: ./.ci/scripts/android/build.sh
|
run: ./.ci/scripts/android/build.sh
|
||||||
|
- name: Copy and sign artifacts
|
||||||
env:
|
env:
|
||||||
ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
|
ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
|
||||||
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||||
ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
|
ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
|
||||||
- name: Copy artifacts
|
|
||||||
run: ./.ci/scripts/android/upload.sh
|
run: ./.ci/scripts/android/upload.sh
|
||||||
- name: Upload
|
- name: Upload
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
|
|
66
.github/workflows/android-ea-play-release.yml
vendored
66
.github/workflows/android-ea-play-release.yml
vendored
|
@ -1,66 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
name: yuzu-android-ea-play-release
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
release-track:
|
|
||||||
description: 'Play store release track (internal/alpha/beta/production)'
|
|
||||||
required: true
|
|
||||||
default: 'alpha'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
android:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.repository == 'yuzu-emu/yuzu' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
name: Checkout
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
submodules: true
|
|
||||||
token: ${{ secrets.ALT_GITHUB_TOKEN }}
|
|
||||||
- run: npm install execa@5
|
|
||||||
- uses: actions/github-script@v5
|
|
||||||
name: 'Merge and publish Android EA changes'
|
|
||||||
env:
|
|
||||||
ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }}
|
|
||||||
BUILD_EA: true
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const execa = require("execa");
|
|
||||||
const mergebot = require('./.github/workflows/android-merge.js').mergebot;
|
|
||||||
process.chdir('${{ github.workspace }}');
|
|
||||||
mergebot(github, context, execa);
|
|
||||||
- name: Get tag name
|
|
||||||
run: echo "GIT_TAG_NAME=$(cat tag-name.txt)" >> $GITHUB_ENV
|
|
||||||
- name: Set up JDK 17
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: '17'
|
|
||||||
distribution: 'temurin'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
|
||||||
- name: Build
|
|
||||||
run: ./.ci/scripts/android/eabuild.sh
|
|
||||||
env:
|
|
||||||
EA_PLAY_ANDROID_KEYSTORE_B64: ${{ secrets.PLAY_ANDROID_KEYSTORE_B64 }}
|
|
||||||
PLAY_ANDROID_KEY_ALIAS: ${{ secrets.PLAY_ANDROID_KEY_ALIAS }}
|
|
||||||
PLAY_ANDROID_KEYSTORE_PASS: ${{ secrets.PLAY_ANDROID_KEYSTORE_PASS }}
|
|
||||||
EA_SERVICE_ACCOUNT_KEY_B64: ${{ secrets.EA_SERVICE_ACCOUNT_KEY_B64 }}
|
|
||||||
STORE_TRACK: ${{ github.event.inputs.release-track }}
|
|
||||||
AUTO_VERSIONED: true
|
|
||||||
BUILD_EA: true
|
|
||||||
- name: Create release
|
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
with:
|
|
||||||
tag_name: ${{ env.EA_TAG_NAME }}
|
|
||||||
name: ${{ env.EA_TAG_NAME }}
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
repository: yuzu/yuzu-android
|
|
||||||
token: ${{ secrets.ALT_GITHUB_TOKEN }}
|
|
|
@ -1,59 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
name: yuzu-android-mainline-play-release
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
release-tag:
|
|
||||||
description: 'Tag # from yuzu-android that you want to build and publish'
|
|
||||||
required: true
|
|
||||||
default: '200'
|
|
||||||
release-track:
|
|
||||||
description: 'Play store release track (internal/alpha/beta/production)'
|
|
||||||
required: true
|
|
||||||
default: 'alpha'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
android:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.repository == 'yuzu-emu/yuzu' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
name: Checkout
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
submodules: true
|
|
||||||
token: ${{ secrets.ALT_GITHUB_TOKEN }}
|
|
||||||
- run: npm install execa@5
|
|
||||||
- uses: actions/github-script@v5
|
|
||||||
name: 'Pull mainline tag'
|
|
||||||
env:
|
|
||||||
MAINLINE_TAG: ${{ github.event.inputs.release-tag }}
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const execa = require("execa");
|
|
||||||
const mergebot = require('./.github/workflows/android-merge.js').getMainlineTag;
|
|
||||||
process.chdir('${{ github.workspace }}');
|
|
||||||
mergebot(execa);
|
|
||||||
- name: Set up JDK 17
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: '17'
|
|
||||||
distribution: 'temurin'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
echo "GIT_TAG_NAME=android-${{ github.event.inputs.releast-tag }}" >> $GITHUB_ENV
|
|
||||||
./.ci/scripts/android/mainlinebuild.sh
|
|
||||||
env:
|
|
||||||
MAINLINE_PLAY_ANDROID_KEYSTORE_B64: ${{ secrets.PLAY_ANDROID_KEYSTORE_B64 }}
|
|
||||||
PLAY_ANDROID_KEY_ALIAS: ${{ secrets.PLAY_ANDROID_KEY_ALIAS }}
|
|
||||||
PLAY_ANDROID_KEYSTORE_PASS: ${{ secrets.PLAY_ANDROID_KEYSTORE_PASS }}
|
|
||||||
SERVICE_ACCOUNT_KEY_B64: ${{ secrets.MAINLINE_SERVICE_ACCOUNT_KEY_B64 }}
|
|
||||||
STORE_TRACK: ${{ github.event.inputs.release-track }}
|
|
||||||
AUTO_VERSIONED: true
|
|
164
.github/workflows/android-merge.js
vendored
164
.github/workflows/android-merge.js
vendored
|
@ -6,14 +6,11 @@
|
||||||
|
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
// which label to check for changes
|
// which label to check for changes
|
||||||
const CHANGE_LABEL_MAINLINE = 'android-merge';
|
const CHANGE_LABEL = 'android-merge';
|
||||||
const CHANGE_LABEL_EA = 'android-ea-merge';
|
|
||||||
// how far back in time should we consider the changes are "recent"? (default: 24 hours)
|
// how far back in time should we consider the changes are "recent"? (default: 24 hours)
|
||||||
const DETECTION_TIME_FRAME = (parseInt(process.env.DETECTION_TIME_FRAME)) || (24 * 3600 * 1000);
|
const DETECTION_TIME_FRAME = (parseInt(process.env.DETECTION_TIME_FRAME)) || (24 * 3600 * 1000);
|
||||||
const BUILD_EA = process.env.BUILD_EA == 'true';
|
|
||||||
const MAINLINE_TAG = process.env.MAINLINE_TAG;
|
|
||||||
|
|
||||||
async function checkBaseChanges(github) {
|
async function checkBaseChanges(github, context) {
|
||||||
// query the commit date of the latest commit on this branch
|
// query the commit date of the latest commit on this branch
|
||||||
const query = `query($owner:String!, $name:String!, $ref:String!) {
|
const query = `query($owner:String!, $name:String!, $ref:String!) {
|
||||||
repository(name:$name, owner:$owner) {
|
repository(name:$name, owner:$owner) {
|
||||||
|
@ -25,8 +22,8 @@ async function checkBaseChanges(github) {
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
const variables = {
|
const variables = {
|
||||||
owner: 'yuzu-emu',
|
owner: context.repo.owner,
|
||||||
name: 'yuzu',
|
name: context.repo.repo,
|
||||||
ref: 'refs/heads/master',
|
ref: 'refs/heads/master',
|
||||||
};
|
};
|
||||||
const result = await github.graphql(query, variables);
|
const result = await github.graphql(query, variables);
|
||||||
|
@ -41,9 +38,22 @@ async function checkBaseChanges(github) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkAndroidChanges(github) {
|
async function checkAndroidChanges(github, context) {
|
||||||
if (checkBaseChanges(github)) return true;
|
if (checkBaseChanges(github, context)) return true;
|
||||||
const pulls = getPulls(github, false);
|
const query = `query($owner:String!, $name:String!, $label:String!) {
|
||||||
|
repository(name:$name, owner:$owner) {
|
||||||
|
pullRequests(labels: [$label], states: OPEN, first: 100) {
|
||||||
|
nodes { number headRepository { pushedAt } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
const variables = {
|
||||||
|
owner: context.repo.owner,
|
||||||
|
name: context.repo.repo,
|
||||||
|
label: CHANGE_LABEL,
|
||||||
|
};
|
||||||
|
const result = await github.graphql(query, variables);
|
||||||
|
const pulls = result.repository.pullRequests.nodes;
|
||||||
for (let i = 0; i < pulls.length; i++) {
|
for (let i = 0; i < pulls.length; i++) {
|
||||||
let pull = pulls[i];
|
let pull = pulls[i];
|
||||||
if (new Date() - new Date(pull.headRepository.pushedAt) <= DETECTION_TIME_FRAME) {
|
if (new Date() - new Date(pull.headRepository.pushedAt) <= DETECTION_TIME_FRAME) {
|
||||||
|
@ -73,21 +83,15 @@ async function tagAndPush(github, owner, repo, execa, commit=false) {
|
||||||
};
|
};
|
||||||
const tags = await github.graphql(query, variables);
|
const tags = await github.graphql(query, variables);
|
||||||
const tagList = tags.repository.refs.nodes;
|
const tagList = tags.repository.refs.nodes;
|
||||||
let lastTag = 'android-1';
|
const lastTag = tagList[0] ? tagList[0].name : 'dummy-0';
|
||||||
for (let i = 0; i < tagList.length; ++i) {
|
|
||||||
if (tagList[i].name.includes('android-')) {
|
|
||||||
lastTag = tagList[i].name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
|
const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
|
||||||
const channel = repo.split('-')[1];
|
const channel = repo.split('-')[1];
|
||||||
const newTag = `${channel}-${tagNumber + 1}`;
|
const newTag = `${channel}-${tagNumber + 1}`;
|
||||||
console.log(`New tag: ${newTag}`);
|
console.log(`New tag: ${newTag}`);
|
||||||
if (commit) {
|
if (commit) {
|
||||||
let channelName = channel[0].toUpperCase() + channel.slice(1);
|
let channelName = channel[0].toUpperCase() + channel.slice(1);
|
||||||
console.info(`Committing pending commit as ${channelName} ${tagNumber + 1}`);
|
console.info(`Committing pending commit as ${channelName} #${tagNumber + 1}`);
|
||||||
await execa("git", ['commit', '-m', `${channelName} ${tagNumber + 1}`]);
|
await execa("git", ['commit', '-m', `${channelName} #${tagNumber + 1}`]);
|
||||||
}
|
}
|
||||||
console.info('Pushing tags to GitHub ...');
|
console.info('Pushing tags to GitHub ...');
|
||||||
await execa("git", ['tag', newTag]);
|
await execa("git", ['tag', newTag]);
|
||||||
|
@ -97,48 +101,6 @@ async function tagAndPush(github, owner, repo, execa, commit=false) {
|
||||||
console.info('Successfully pushed new changes.');
|
console.info('Successfully pushed new changes.');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tagAndPushEA(github, owner, repo, execa) {
|
|
||||||
let altToken = process.env.ALT_GITHUB_TOKEN;
|
|
||||||
if (!altToken) {
|
|
||||||
throw `Please set ALT_GITHUB_TOKEN environment variable. This token should have write access to ${owner}/${repo}.`;
|
|
||||||
}
|
|
||||||
const query = `query ($owner:String!, $name:String!) {
|
|
||||||
repository(name:$name, owner:$owner) {
|
|
||||||
refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 10) {
|
|
||||||
nodes { name }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
const variables = {
|
|
||||||
owner: owner,
|
|
||||||
name: repo,
|
|
||||||
};
|
|
||||||
const tags = await github.graphql(query, variables);
|
|
||||||
const tagList = tags.repository.refs.nodes;
|
|
||||||
let lastTag = 'ea-1';
|
|
||||||
for (let i = 0; i < tagList.length; ++i) {
|
|
||||||
if (tagList[i].name.includes('ea-')) {
|
|
||||||
lastTag = tagList[i].name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
|
|
||||||
const newTag = `ea-${tagNumber + 1}`;
|
|
||||||
console.log(`New tag: ${newTag}`);
|
|
||||||
console.info('Pushing tags to GitHub ...');
|
|
||||||
await execa("git", ["remote", "add", "android", "https://github.com/yuzu-emu/yuzu-android.git"]);
|
|
||||||
await execa("git", ["fetch", "android"]);
|
|
||||||
|
|
||||||
await execa("git", ['tag', newTag]);
|
|
||||||
await execa("git", ['push', 'android', `${newTag}`]);
|
|
||||||
|
|
||||||
fs.writeFile('tag-name.txt', newTag, (err) => {
|
|
||||||
if (err) throw 'Could not write tag name to file!'
|
|
||||||
})
|
|
||||||
|
|
||||||
console.info('Successfully pushed new changes.');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateReadme(pulls, context, mergeResults, execa) {
|
async function generateReadme(pulls, context, mergeResults, execa) {
|
||||||
let baseUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/`;
|
let baseUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/`;
|
||||||
let output =
|
let output =
|
||||||
|
@ -195,7 +157,7 @@ async function mergePullRequests(pulls, execa) {
|
||||||
process1.stdout.pipe(process.stdout);
|
process1.stdout.pipe(process.stdout);
|
||||||
await process1;
|
await process1;
|
||||||
|
|
||||||
const process2 = execa("git", ["commit", "-m", `Merge yuzu-emu#${pr}`]);
|
const process2 = execa("git", ["commit", "-m", `Merge PR ${pr}`]);
|
||||||
process2.stdout.pipe(process.stdout);
|
process2.stdout.pipe(process.stdout);
|
||||||
await process2;
|
await process2;
|
||||||
|
|
||||||
|
@ -220,27 +182,7 @@ async function mergePullRequests(pulls, execa) {
|
||||||
return mergeResults;
|
return mergeResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resetBranch(execa) {
|
async function mergebot(github, context, execa) {
|
||||||
console.log("::group::Reset master branch");
|
|
||||||
let hasFailed = false;
|
|
||||||
try {
|
|
||||||
await execa("git", ["remote", "add", "source", "https://github.com/yuzu-emu/yuzu.git"]);
|
|
||||||
await execa("git", ["fetch", "source"]);
|
|
||||||
const process1 = await execa("git", ["rev-parse", "source/master"]);
|
|
||||||
const headCommit = process1.stdout;
|
|
||||||
|
|
||||||
await execa("git", ["reset", "--hard", headCommit]);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(`::error title=Failed to reset master branch`);
|
|
||||||
hasFailed = true;
|
|
||||||
}
|
|
||||||
console.log("::endgroup::");
|
|
||||||
if (hasFailed) {
|
|
||||||
throw 'Failed to reset the master branch. Aborting!';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getPulls(github) {
|
|
||||||
const query = `query ($owner:String!, $name:String!, $label:String!) {
|
const query = `query ($owner:String!, $name:String!, $label:String!) {
|
||||||
repository(name:$name, owner:$owner) {
|
repository(name:$name, owner:$owner) {
|
||||||
pullRequests(labels: [$label], states: OPEN, first: 100) {
|
pullRequests(labels: [$label], states: OPEN, first: 100) {
|
||||||
|
@ -250,49 +192,13 @@ async function getPulls(github) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
const mainlineVariables = {
|
const variables = {
|
||||||
owner: 'yuzu-emu',
|
owner: context.repo.owner,
|
||||||
name: 'yuzu',
|
name: context.repo.repo,
|
||||||
label: CHANGE_LABEL_MAINLINE,
|
label: CHANGE_LABEL,
|
||||||
};
|
};
|
||||||
const mainlineResult = await github.graphql(query, mainlineVariables);
|
const result = await github.graphql(query, variables);
|
||||||
const pulls = mainlineResult.repository.pullRequests.nodes;
|
const pulls = result.repository.pullRequests.nodes;
|
||||||
if (BUILD_EA) {
|
|
||||||
const eaVariables = {
|
|
||||||
owner: 'yuzu-emu',
|
|
||||||
name: 'yuzu',
|
|
||||||
label: CHANGE_LABEL_EA,
|
|
||||||
};
|
|
||||||
const eaResult = await github.graphql(query, eaVariables);
|
|
||||||
const eaPulls = eaResult.repository.pullRequests.nodes;
|
|
||||||
return pulls.concat(eaPulls);
|
|
||||||
}
|
|
||||||
return pulls;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getMainlineTag(execa) {
|
|
||||||
console.log(`::group::Getting mainline tag android-${MAINLINE_TAG}`);
|
|
||||||
let hasFailed = false;
|
|
||||||
try {
|
|
||||||
await execa("git", ["remote", "add", "mainline", "https://github.com/yuzu-emu/yuzu-android.git"]);
|
|
||||||
await execa("git", ["fetch", "mainline", "--tags"]);
|
|
||||||
await execa("git", ["checkout", `tags/android-${MAINLINE_TAG}`]);
|
|
||||||
await execa("git", ["submodule", "update", "--init", "--recursive"]);
|
|
||||||
} catch (err) {
|
|
||||||
console.log('::error title=Failed pull tag');
|
|
||||||
hasFailed = true;
|
|
||||||
}
|
|
||||||
console.log("::endgroup::");
|
|
||||||
if (hasFailed) {
|
|
||||||
throw 'Failed pull mainline tag. Aborting!';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mergebot(github, context, execa) {
|
|
||||||
// Reset our local copy of master to what appears on yuzu-emu/yuzu - master
|
|
||||||
await resetBranch(execa);
|
|
||||||
|
|
||||||
const pulls = await getPulls(github);
|
|
||||||
let displayList = [];
|
let displayList = [];
|
||||||
for (let i = 0; i < pulls.length; i++) {
|
for (let i = 0; i < pulls.length; i++) {
|
||||||
let pull = pulls[i];
|
let pull = pulls[i];
|
||||||
|
@ -302,17 +208,11 @@ async function mergebot(github, context, execa) {
|
||||||
console.table(displayList);
|
console.table(displayList);
|
||||||
await fetchPullRequests(pulls, "https://github.com/yuzu-emu/yuzu", execa);
|
await fetchPullRequests(pulls, "https://github.com/yuzu-emu/yuzu", execa);
|
||||||
const mergeResults = await mergePullRequests(pulls, execa);
|
const mergeResults = await mergePullRequests(pulls, execa);
|
||||||
|
|
||||||
if (BUILD_EA) {
|
|
||||||
await tagAndPushEA(github, 'yuzu-emu', `yuzu-android`, execa);
|
|
||||||
} else {
|
|
||||||
await generateReadme(pulls, context, mergeResults, execa);
|
await generateReadme(pulls, context, mergeResults, execa);
|
||||||
await tagAndPush(github, 'yuzu-emu', `yuzu-android`, execa, true);
|
await tagAndPush(github, context.repo.owner, `${context.repo.repo}-android`, execa, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.mergebot = mergebot;
|
module.exports.mergebot = mergebot;
|
||||||
module.exports.checkAndroidChanges = checkAndroidChanges;
|
module.exports.checkAndroidChanges = checkAndroidChanges;
|
||||||
module.exports.tagAndPush = tagAndPush;
|
module.exports.tagAndPush = tagAndPush;
|
||||||
module.exports.checkBaseChanges = checkBaseChanges;
|
module.exports.checkBaseChanges = checkBaseChanges;
|
||||||
module.exports.getMainlineTag = getMainlineTag;
|
|
||||||
|
|
4
.github/workflows/android-publish.yml
vendored
4
.github/workflows/android-publish.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
name: yuzu-android-publish
|
name: yuzu-android-publish
|
||||||
|
@ -33,7 +33,7 @@ jobs:
|
||||||
script: |
|
script: |
|
||||||
if (context.payload.inputs && context.payload.inputs.android === 'true') return true;
|
if (context.payload.inputs && context.payload.inputs.android === 'true') return true;
|
||||||
const checkAndroidChanges = require('./.github/workflows/android-merge.js').checkAndroidChanges;
|
const checkAndroidChanges = require('./.github/workflows/android-merge.js').checkAndroidChanges;
|
||||||
return checkAndroidChanges(github);
|
return checkAndroidChanges(github, context);
|
||||||
- run: npm install execa@5
|
- run: npm install execa@5
|
||||||
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
27
.github/workflows/verify.yml
vendored
27
.github/workflows/verify.yml
vendored
|
@ -13,15 +13,13 @@ jobs:
|
||||||
format:
|
format:
|
||||||
name: 'verify format'
|
name: 'verify format'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: yuzuemu/build-environments:linux-clang-format
|
||||||
|
options: -u 1001
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: false
|
submodules: false
|
||||||
- name: set up JDK 17
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: '17'
|
|
||||||
distribution: 'temurin'
|
|
||||||
- name: 'Verify Formatting'
|
- name: 'Verify Formatting'
|
||||||
run: bash -ex ./.ci/scripts/format/script.sh
|
run: bash -ex ./.ci/scripts/format/script.sh
|
||||||
build:
|
build:
|
||||||
|
@ -70,25 +68,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.type }}
|
name: ${{ matrix.type }}
|
||||||
path: artifacts/
|
path: artifacts/
|
||||||
build-mac:
|
|
||||||
name: 'test build (macos)'
|
|
||||||
needs: format
|
|
||||||
runs-on: macos-14
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
export Qt5_DIR="$(brew --prefix qt@5)/lib/cmake"
|
|
||||||
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF
|
|
||||||
ninja
|
|
||||||
build-msvc:
|
build-msvc:
|
||||||
name: 'test build (windows, msvc)'
|
name: 'test build (windows, msvc)'
|
||||||
needs: format
|
needs: format
|
||||||
|
|
17
.gitmodules
vendored
17
.gitmodules
vendored
|
@ -4,6 +4,9 @@
|
||||||
[submodule "enet"]
|
[submodule "enet"]
|
||||||
path = externals/enet
|
path = externals/enet
|
||||||
url = https://github.com/lsalzman/enet.git
|
url = https://github.com/lsalzman/enet.git
|
||||||
|
[submodule "inih"]
|
||||||
|
path = externals/inih/inih
|
||||||
|
url = https://github.com/benhoyt/inih.git
|
||||||
[submodule "cubeb"]
|
[submodule "cubeb"]
|
||||||
path = externals/cubeb
|
path = externals/cubeb
|
||||||
url = https://github.com/mozilla/cubeb.git
|
url = https://github.com/mozilla/cubeb.git
|
||||||
|
@ -29,7 +32,7 @@
|
||||||
path = externals/xbyak
|
path = externals/xbyak
|
||||||
url = https://github.com/herumi/xbyak.git
|
url = https://github.com/herumi/xbyak.git
|
||||||
[submodule "opus"]
|
[submodule "opus"]
|
||||||
path = externals/opus
|
path = externals/opus/opus
|
||||||
url = https://github.com/xiph/opus.git
|
url = https://github.com/xiph/opus.git
|
||||||
[submodule "SDL"]
|
[submodule "SDL"]
|
||||||
path = externals/SDL
|
path = externals/SDL
|
||||||
|
@ -55,15 +58,3 @@
|
||||||
[submodule "VulkanMemoryAllocator"]
|
[submodule "VulkanMemoryAllocator"]
|
||||||
path = externals/VulkanMemoryAllocator
|
path = externals/VulkanMemoryAllocator
|
||||||
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||||
[submodule "breakpad"]
|
|
||||||
path = externals/breakpad
|
|
||||||
url = https://github.com/yuzu-emu/breakpad.git
|
|
||||||
[submodule "simpleini"]
|
|
||||||
path = externals/simpleini
|
|
||||||
url = https://github.com/brofield/simpleini.git
|
|
||||||
[submodule "oaknut"]
|
|
||||||
path = externals/oaknut
|
|
||||||
url = https://github.com/merryhime/oaknut
|
|
||||||
[submodule "Vulkan-Utility-Libraries"]
|
|
||||||
path = externals/Vulkan-Utility-Libraries
|
|
||||||
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
|
|
||||||
|
|
12
.reuse/dep5
12
.reuse/dep5
|
@ -147,15 +147,3 @@ License: GPL-3.0-or-later
|
||||||
Files: src/android/gradle/wrapper/*
|
Files: src/android/gradle/wrapper/*
|
||||||
Copyright: 2023 yuzu Emulator Project
|
Copyright: 2023 yuzu Emulator Project
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
|
|
||||||
Files: externals/stb/*
|
|
||||||
Copyright: Sean Barrett
|
|
||||||
License: MIT
|
|
||||||
|
|
||||||
Files: externals/gamemode/*
|
|
||||||
Copyright: Copyright 2017-2019 Feral Interactive
|
|
||||||
License: BSD-3-Clause
|
|
||||||
|
|
||||||
Files: src/android/app/debug.keystore
|
|
||||||
Copyright: 2023 yuzu Emulator Project
|
|
||||||
License: GPL-3.0-or-later
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modul
|
||||||
include(DownloadExternals)
|
include(DownloadExternals)
|
||||||
include(CMakeDependentOption)
|
include(CMakeDependentOption)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
# Set bundled sdl2/qt as dependent options.
|
# Set bundled sdl2/qt as dependent options.
|
||||||
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
||||||
|
@ -36,8 +37,6 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
|
||||||
|
|
||||||
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
|
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
|
||||||
|
|
||||||
option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
|
|
||||||
|
|
||||||
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
|
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
|
||||||
|
|
||||||
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
||||||
|
@ -54,7 +53,7 @@ option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android"
|
||||||
|
|
||||||
CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF)
|
CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF)
|
||||||
|
|
||||||
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF)
|
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile Windows crash dump (Minidump) support" OFF "WIN32" OFF)
|
||||||
|
|
||||||
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
|
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
|
||||||
|
|
||||||
|
@ -100,8 +99,47 @@ if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
|
||||||
DESTINATION "${vvl_lib_path}")
|
DESTINATION "${vvl_lib_path}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# On Android, fetch and compile libcxx before doing anything else
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
set(CMAKE_SKIP_INSTALL_RULES ON)
|
set(CMAKE_SKIP_INSTALL_RULES ON)
|
||||||
|
set(LLVM_VERSION "15.0.6")
|
||||||
|
|
||||||
|
# Note: even though libcxx and libcxxabi have separate releases on the project page,
|
||||||
|
# the separated releases cannot be compiled. Only in-tree builds work. Therefore we
|
||||||
|
# must fetch the source release for the entire llvm tree.
|
||||||
|
FetchContent_Declare(llvm
|
||||||
|
URL "https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-project-${LLVM_VERSION}.src.tar.xz"
|
||||||
|
URL_HASH SHA256=9d53ad04dc60cb7b30e810faf64c5ab8157dadef46c8766f67f286238256ff92
|
||||||
|
TLS_VERIFY TRUE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(llvm)
|
||||||
|
|
||||||
|
# libcxx has support for most of the range library, but it's gated behind a flag:
|
||||||
|
add_compile_definitions(_LIBCPP_ENABLE_EXPERIMENTAL)
|
||||||
|
|
||||||
|
# Disable standard header inclusion
|
||||||
|
set(ANDROID_STL "none")
|
||||||
|
|
||||||
|
# libcxxabi
|
||||||
|
set(LIBCXXABI_INCLUDE_TESTS OFF)
|
||||||
|
set(LIBCXXABI_ENABLE_SHARED FALSE)
|
||||||
|
set(LIBCXXABI_ENABLE_STATIC TRUE)
|
||||||
|
set(LIBCXXABI_LIBCXX_INCLUDES "${LIBCXX_TARGET_INCLUDE_DIRECTORY}" CACHE STRING "" FORCE)
|
||||||
|
add_subdirectory("${llvm_SOURCE_DIR}/libcxxabi" "${llvm_BINARY_DIR}/libcxxabi")
|
||||||
|
link_libraries(cxxabi_static)
|
||||||
|
|
||||||
|
# libcxx
|
||||||
|
set(LIBCXX_ABI_NAMESPACE "__ndk1" CACHE STRING "" FORCE)
|
||||||
|
set(LIBCXX_CXX_ABI "libcxxabi")
|
||||||
|
set(LIBCXX_INCLUDE_TESTS OFF)
|
||||||
|
set(LIBCXX_INCLUDE_BENCHMARKS OFF)
|
||||||
|
set(LIBCXX_INCLUDE_DOCS OFF)
|
||||||
|
set(LIBCXX_ENABLE_SHARED FALSE)
|
||||||
|
set(LIBCXX_ENABLE_STATIC TRUE)
|
||||||
|
set(LIBCXX_ENABLE_ASSERTIONS FALSE)
|
||||||
|
add_subdirectory("${llvm_SOURCE_DIR}/libcxx" "${llvm_BINARY_DIR}/libcxx")
|
||||||
|
set_target_properties(cxx-headers PROPERTIES INTERFACE_COMPILE_OPTIONS "-isystem${CMAKE_BINARY_DIR}/${LIBCXX_INSTALL_INCLUDE_DIR}")
|
||||||
|
link_libraries(cxx_static cxx-headers)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (YUZU_USE_BUNDLED_VCPKG)
|
if (YUZU_USE_BUNDLED_VCPKG)
|
||||||
|
@ -141,12 +179,12 @@ if (YUZU_USE_BUNDLED_VCPKG)
|
||||||
if (YUZU_TESTS)
|
if (YUZU_TESTS)
|
||||||
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
|
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
|
||||||
endif()
|
endif()
|
||||||
|
if (YUZU_CRASH_DUMPS)
|
||||||
|
list(APPEND VCPKG_MANIFEST_FEATURES "dbghelp")
|
||||||
|
endif()
|
||||||
if (ENABLE_WEB_SERVICE)
|
if (ENABLE_WEB_SERVICE)
|
||||||
list(APPEND VCPKG_MANIFEST_FEATURES "web-service")
|
list(APPEND VCPKG_MANIFEST_FEATURES "web-service")
|
||||||
endif()
|
endif()
|
||||||
if (ANDROID)
|
|
||||||
list(APPEND VCPKG_MANIFEST_FEATURES "android")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(${CMAKE_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake)
|
include(${CMAKE_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake)
|
||||||
elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
|
elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
|
||||||
|
@ -265,11 +303,6 @@ if (UNIX)
|
||||||
add_definitions(-DYUZU_UNIX=1)
|
add_definitions(-DYUZU_UNIX=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_arm64 AND (ANDROID OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
|
|
||||||
set(HAS_NCE 1)
|
|
||||||
add_definitions(-DHAS_NCE=1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Configure C++ standard
|
# Configure C++ standard
|
||||||
# ===========================
|
# ===========================
|
||||||
|
|
||||||
|
@ -295,23 +328,18 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||||
find_package(Boost 1.79.0 REQUIRED context)
|
find_package(Boost 1.79.0 REQUIRED context)
|
||||||
find_package(enet 1.3 MODULE)
|
find_package(enet 1.3 MODULE)
|
||||||
find_package(fmt 9 REQUIRED)
|
find_package(fmt 9 REQUIRED)
|
||||||
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
|
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||||
|
find_package(LLVM 17 MODULE COMPONENTS Demangle)
|
||||||
find_package(lz4 REQUIRED)
|
find_package(lz4 REQUIRED)
|
||||||
find_package(nlohmann_json 3.8 REQUIRED)
|
find_package(nlohmann_json 3.8 REQUIRED)
|
||||||
find_package(Opus 1.3 MODULE)
|
find_package(Opus 1.3 MODULE)
|
||||||
find_package(RenderDoc MODULE)
|
find_package(RenderDoc MODULE)
|
||||||
find_package(SimpleIni MODULE)
|
|
||||||
find_package(stb MODULE)
|
|
||||||
find_package(VulkanMemoryAllocator CONFIG)
|
find_package(VulkanMemoryAllocator CONFIG)
|
||||||
find_package(ZLIB 1.2 REQUIRED)
|
find_package(ZLIB 1.2 REQUIRED)
|
||||||
find_package(zstd 1.5 REQUIRED)
|
find_package(zstd 1.5 REQUIRED)
|
||||||
|
|
||||||
if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
||||||
find_package(VulkanHeaders 1.3.274 REQUIRED)
|
find_package(Vulkan 1.3.256 REQUIRED)
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
|
||||||
find_package(VulkanUtilityLibraries REQUIRED)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_LIBUSB)
|
if (ENABLE_LIBUSB)
|
||||||
|
@ -322,10 +350,6 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||||
find_package(xbyak 6 CONFIG)
|
find_package(xbyak 6 CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_arm64)
|
|
||||||
find_package(oaknut 2.0.1 CONFIG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||||
find_package(dynarmic 6.4.0 CONFIG)
|
find_package(dynarmic 6.4.0 CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
@ -356,10 +380,6 @@ if(ENABLE_OPENSSL)
|
||||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
find_package(gamemode 1.7 MODULE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Please consider this as a stub
|
# Please consider this as a stub
|
||||||
if(ENABLE_QT6 AND Qt6_LOCATION)
|
if(ENABLE_QT6 AND Qt6_LOCATION)
|
||||||
list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}")
|
list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}")
|
||||||
|
@ -380,9 +400,6 @@ function(set_yuzu_qt_components)
|
||||||
if (ENABLE_QT_TRANSLATION)
|
if (ENABLE_QT_TRANSLATION)
|
||||||
list(APPEND YUZU_QT_COMPONENTS2 LinguistTools)
|
list(APPEND YUZU_QT_COMPONENTS2 LinguistTools)
|
||||||
endif()
|
endif()
|
||||||
if (USE_DISCORD_PRESENCE)
|
|
||||||
list(APPEND YUZU_QT_COMPONENTS2 Network)
|
|
||||||
endif()
|
|
||||||
set(YUZU_QT_COMPONENTS ${YUZU_QT_COMPONENTS2} PARENT_SCOPE)
|
set(YUZU_QT_COMPONENTS ${YUZU_QT_COMPONENTS2} PARENT_SCOPE)
|
||||||
endfunction(set_yuzu_qt_components)
|
endfunction(set_yuzu_qt_components)
|
||||||
|
|
||||||
|
@ -570,18 +587,6 @@ if (NOT YUZU_USE_BUNDLED_FFMPEG)
|
||||||
find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32 AND YUZU_CRASH_DUMPS)
|
|
||||||
set(BREAKPAD_VER "breakpad-c89f9dd")
|
|
||||||
download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX)
|
|
||||||
|
|
||||||
set(BREAKPAD_CLIENT_INCLUDE_DIR "${BREAKPAD_PREFIX}/include")
|
|
||||||
set(BREAKPAD_CLIENT_LIBRARY "${BREAKPAD_PREFIX}/lib/libbreakpad_client.lib")
|
|
||||||
|
|
||||||
add_library(libbreakpad_client INTERFACE IMPORTED)
|
|
||||||
target_link_libraries(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_LIBRARY}")
|
|
||||||
target_include_directories(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_INCLUDE_DIR}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Prefer the -pthread flag on Linux.
|
# Prefer the -pthread flag on Linux.
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
@ -601,6 +606,13 @@ elseif (WIN32)
|
||||||
# PSAPI is the Process Status API
|
# PSAPI is the Process Status API
|
||||||
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
|
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (YUZU_CRASH_DUMPS)
|
||||||
|
find_library(DBGHELP_LIBRARY dbghelp)
|
||||||
|
if ("${DBGHELP_LIBRARY}" STREQUAL "DBGHELP_LIBRARY-NOTFOUND")
|
||||||
|
message(FATAL_ERROR "YUZU_CRASH_DUMPS enabled but dbghelp library not found")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
|
elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
|
||||||
set(PLATFORM_LIBRARIES rt)
|
set(PLATFORM_LIBRARIES rt)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2023 Alexandre Bouvier <contact@amb.tf>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
|
|
||||||
find_package(SimpleIni QUIET CONFIG)
|
|
||||||
if (SimpleIni_CONSIDERED_CONFIGS)
|
|
||||||
find_package_handle_standard_args(SimpleIni CONFIG_MODE)
|
|
||||||
else()
|
|
||||||
find_package(PkgConfig QUIET)
|
|
||||||
pkg_search_module(SIMPLEINI QUIET IMPORTED_TARGET simpleini)
|
|
||||||
find_package_handle_standard_args(SimpleIni
|
|
||||||
REQUIRED_VARS SIMPLEINI_INCLUDEDIR
|
|
||||||
VERSION_VAR SIMPLEINI_VERSION
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (SimpleIni_FOUND AND NOT TARGET SimpleIni::SimpleIni)
|
|
||||||
add_library(SimpleIni::SimpleIni ALIAS PkgConfig::SIMPLEINI)
|
|
||||||
endif()
|
|
|
@ -1,15 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
find_package(PkgConfig QUIET)
|
|
||||||
pkg_search_module(GAMEMODE QUIET IMPORTED_TARGET gamemode)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(gamemode
|
|
||||||
REQUIRED_VARS GAMEMODE_INCLUDEDIR
|
|
||||||
VERSION_VAR GAMEMODE_VERSION
|
|
||||||
)
|
|
||||||
|
|
||||||
if (gamemode_FOUND AND NOT TARGET gamemode::headers)
|
|
||||||
add_library(gamemode::headers ALIAS PkgConfig::GAMEMODE)
|
|
||||||
endif()
|
|
27
CMakeModules/Findinih.cmake
Normal file
27
CMakeModules/Findinih.cmake
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
find_package(PkgConfig QUIET)
|
||||||
|
pkg_search_module(INIH QUIET IMPORTED_TARGET inih)
|
||||||
|
if (INIReader IN_LIST inih_FIND_COMPONENTS)
|
||||||
|
pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader)
|
||||||
|
if (INIREADER_FOUND)
|
||||||
|
set(inih_INIReader_FOUND TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(inih
|
||||||
|
REQUIRED_VARS INIH_LINK_LIBRARIES
|
||||||
|
VERSION_VAR INIH_VERSION
|
||||||
|
HANDLE_COMPONENTS
|
||||||
|
)
|
||||||
|
|
||||||
|
if (inih_FOUND AND NOT TARGET inih::inih)
|
||||||
|
add_library(inih::inih ALIAS PkgConfig::INIH)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (inih_FOUND AND inih_INIReader_FOUND AND NOT TARGET inih::INIReader)
|
||||||
|
add_library(inih::INIReader ALIAS PkgConfig::INIREADER)
|
||||||
|
endif()
|
|
@ -1,31 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2023 Alexandre Bouvier <contact@amb.tf>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
find_path(stb_image_INCLUDE_DIR stb_image.h PATH_SUFFIXES stb)
|
|
||||||
find_path(stb_image_resize_INCLUDE_DIR stb_image_resize.h PATH_SUFFIXES stb)
|
|
||||||
find_path(stb_image_write_INCLUDE_DIR stb_image_write.h PATH_SUFFIXES stb)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(stb
|
|
||||||
REQUIRED_VARS
|
|
||||||
stb_image_INCLUDE_DIR
|
|
||||||
stb_image_resize_INCLUDE_DIR
|
|
||||||
stb_image_write_INCLUDE_DIR
|
|
||||||
)
|
|
||||||
|
|
||||||
if (stb_FOUND AND NOT TARGET stb::headers)
|
|
||||||
add_library(stb::headers INTERFACE IMPORTED)
|
|
||||||
set_property(TARGET stb::headers PROPERTY
|
|
||||||
INTERFACE_INCLUDE_DIRECTORIES
|
|
||||||
"${stb_image_INCLUDE_DIR}"
|
|
||||||
"${stb_image_resize_INCLUDE_DIR}"
|
|
||||||
"${stb_image_write_INCLUDE_DIR}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
mark_as_advanced(
|
|
||||||
stb_image_INCLUDE_DIR
|
|
||||||
stb_image_resize_INCLUDE_DIR
|
|
||||||
stb_image_write_INCLUDE_DIR
|
|
||||||
)
|
|
19
dist/72-yuzu-input.rules
vendored
19
dist/72-yuzu-input.rules
vendored
|
@ -1,19 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
# Allow systemd-logind to manage user access to hidraw with this file
|
|
||||||
# On most systems, this file should be installed to /etc/udev/rules.d/72-yuzu-input.rules
|
|
||||||
# Consult your distro if this is not the case
|
|
||||||
|
|
||||||
# Switch Pro Controller (USB/Bluetooth)
|
|
||||||
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="2009", MODE="0660", TAG+="uaccess"
|
|
||||||
KERNEL=="hidraw*", KERNELS=="*057e:2009*", MODE="0660", TAG+="uaccess"
|
|
||||||
|
|
||||||
# Joy-Con L (Bluetooth)
|
|
||||||
KERNEL=="hidraw*", KERNELS=="*057e:2006*", MODE="0660", TAG+="uaccess"
|
|
||||||
|
|
||||||
# Joy-Con R (Bluetooth)
|
|
||||||
KERNEL=="hidraw*", KERNELS=="*057e:2007*", MODE="0660", TAG+="uaccess"
|
|
||||||
|
|
||||||
# Joy-Con Charging Grip (USB)
|
|
||||||
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="200e", MODE="0660", TAG+="uaccess"
|
|
6
dist/languages/.tx/config
vendored
6
dist/languages/.tx/config
vendored
|
@ -6,9 +6,3 @@ file_filter = <lang>.ts
|
||||||
source_file = en.ts
|
source_file = en.ts
|
||||||
source_lang = en
|
source_lang = en
|
||||||
type = QT
|
type = QT
|
||||||
|
|
||||||
[o:yuzu-emulator:p:yuzu:r:yuzu-android]
|
|
||||||
file_filter = ../../src/android/app/src/main/res/values-<lang>/strings.xml
|
|
||||||
source_file = ../../src/android/app/src/main/res/values/strings.xml
|
|
||||||
type = ANDROID
|
|
||||||
lang_map = ja_JP:ja, ko_KR:ko, pt_BR:pt-rBR, pt_PT:pt-rPT, ru_RU:ru, vi_VN:vi, zh_CN:zh-rCN, zh_TW:zh-rTW
|
|
||||||
|
|
4501
dist/languages/ar.ts
vendored
4501
dist/languages/ar.ts
vendored
File diff suppressed because it is too large
Load diff
3695
dist/languages/ca.ts
vendored
3695
dist/languages/ca.ts
vendored
File diff suppressed because it is too large
Load diff
3659
dist/languages/cs.ts
vendored
3659
dist/languages/cs.ts
vendored
File diff suppressed because it is too large
Load diff
3442
dist/languages/da.ts
vendored
3442
dist/languages/da.ts
vendored
File diff suppressed because it is too large
Load diff
3619
dist/languages/de.ts
vendored
3619
dist/languages/de.ts
vendored
File diff suppressed because it is too large
Load diff
3458
dist/languages/el.ts
vendored
3458
dist/languages/el.ts
vendored
File diff suppressed because it is too large
Load diff
3599
dist/languages/es.ts
vendored
3599
dist/languages/es.ts
vendored
File diff suppressed because it is too large
Load diff
3540
dist/languages/fr.ts
vendored
3540
dist/languages/fr.ts
vendored
File diff suppressed because it is too large
Load diff
4590
dist/languages/hu.ts
vendored
4590
dist/languages/hu.ts
vendored
File diff suppressed because it is too large
Load diff
3751
dist/languages/id.ts
vendored
3751
dist/languages/id.ts
vendored
File diff suppressed because it is too large
Load diff
3484
dist/languages/it.ts
vendored
3484
dist/languages/it.ts
vendored
File diff suppressed because it is too large
Load diff
3673
dist/languages/ja_JP.ts
vendored
3673
dist/languages/ja_JP.ts
vendored
File diff suppressed because it is too large
Load diff
3459
dist/languages/ko_KR.ts
vendored
3459
dist/languages/ko_KR.ts
vendored
File diff suppressed because it is too large
Load diff
3459
dist/languages/nb.ts
vendored
3459
dist/languages/nb.ts
vendored
File diff suppressed because it is too large
Load diff
3459
dist/languages/nl.ts
vendored
3459
dist/languages/nl.ts
vendored
File diff suppressed because it is too large
Load diff
3452
dist/languages/pl.ts
vendored
3452
dist/languages/pl.ts
vendored
File diff suppressed because it is too large
Load diff
3743
dist/languages/pt_BR.ts
vendored
3743
dist/languages/pt_BR.ts
vendored
File diff suppressed because it is too large
Load diff
3543
dist/languages/pt_PT.ts
vendored
3543
dist/languages/pt_PT.ts
vendored
File diff suppressed because it is too large
Load diff
3540
dist/languages/ru_RU.ts
vendored
3540
dist/languages/ru_RU.ts
vendored
File diff suppressed because it is too large
Load diff
3450
dist/languages/sv.ts
vendored
3450
dist/languages/sv.ts
vendored
File diff suppressed because it is too large
Load diff
3480
dist/languages/tr_TR.ts
vendored
3480
dist/languages/tr_TR.ts
vendored
File diff suppressed because it is too large
Load diff
3457
dist/languages/uk.ts
vendored
3457
dist/languages/uk.ts
vendored
File diff suppressed because it is too large
Load diff
3457
dist/languages/vi.ts
vendored
3457
dist/languages/vi.ts
vendored
File diff suppressed because it is too large
Load diff
3457
dist/languages/vi_VN.ts
vendored
3457
dist/languages/vi_VN.ts
vendored
File diff suppressed because it is too large
Load diff
3557
dist/languages/zh_CN.ts
vendored
3557
dist/languages/zh_CN.ts
vendored
File diff suppressed because it is too large
Load diff
3736
dist/languages/zh_TW.ts
vendored
3736
dist/languages/zh_TW.ts
vendored
File diff suppressed because it is too large
Load diff
1
dist/org.yuzu_emu.yuzu.desktop
vendored
1
dist/org.yuzu_emu.yuzu.desktop
vendored
|
@ -13,4 +13,3 @@ Exec=yuzu %f
|
||||||
Categories=Game;Emulator;Qt;
|
Categories=Game;Emulator;Qt;
|
||||||
MimeType=application/x-nx-nro;application/x-nx-nso;application/x-nx-nsp;application/x-nx-xci;
|
MimeType=application/x-nx-nro;application/x-nx-nso;application/x-nx-nsp;application/x-nx-xci;
|
||||||
Keywords=Nintendo;Switch;
|
Keywords=Nintendo;Switch;
|
||||||
StartupWMClass=yuzu
|
|
||||||
|
|
4
dist/qt_themes/default/style.qss
vendored
4
dist/qt_themes/default/style.qss
vendored
|
@ -120,10 +120,6 @@ QWidget#connectedControllers {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget#closeButtons {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget#playersSupported,
|
QWidget#playersSupported,
|
||||||
QWidget#controllersSupported,
|
QWidget#controllersSupported,
|
||||||
QWidget#controllerSupported1,
|
QWidget#controllerSupported1,
|
||||||
|
|
4
dist/qt_themes/qdarkstyle/style.qss
vendored
4
dist/qt_themes/qdarkstyle/style.qss
vendored
|
@ -1380,10 +1380,6 @@ QWidget#connectedControllers {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget#closeButtons {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget#playersSupported,
|
QWidget#playersSupported,
|
||||||
QWidget#controllersSupported,
|
QWidget#controllersSupported,
|
||||||
QWidget#controllerSupported1,
|
QWidget#controllerSupported1,
|
||||||
|
|
|
@ -2305,10 +2305,6 @@ QWidget#connectedControllers {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget#closeButtons {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget#playersSupported,
|
QWidget#playersSupported,
|
||||||
QWidget#controllersSupported,
|
QWidget#controllersSupported,
|
||||||
QWidget#controllerSupported1,
|
QWidget#controllerSupported1,
|
||||||
|
|
143
externals/CMakeLists.txt
vendored
143
externals/CMakeLists.txt
vendored
|
@ -14,16 +14,11 @@ set(BUILD_SHARED_LIBS OFF)
|
||||||
# Skip install rules for all externals
|
# Skip install rules for all externals
|
||||||
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||||
|
|
||||||
# Xbyak (also used by Dynarmic, so needs to be added first)
|
# xbyak
|
||||||
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
||||||
add_subdirectory(xbyak)
|
add_subdirectory(xbyak)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Oaknut (also used by Dynarmic, so needs to be added first)
|
|
||||||
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
|
|
||||||
add_subdirectory(oaknut)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Dynarmic
|
# Dynarmic
|
||||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
||||||
set(DYNARMIC_IGNORE_ASSERTS ON)
|
set(DYNARMIC_IGNORE_ASSERTS ON)
|
||||||
|
@ -39,6 +34,11 @@ endif()
|
||||||
# Glad
|
# Glad
|
||||||
add_subdirectory(glad)
|
add_subdirectory(glad)
|
||||||
|
|
||||||
|
# inih
|
||||||
|
if (NOT TARGET inih::INIReader)
|
||||||
|
add_subdirectory(inih)
|
||||||
|
endif()
|
||||||
|
|
||||||
# mbedtls
|
# mbedtls
|
||||||
add_subdirectory(mbedtls)
|
add_subdirectory(mbedtls)
|
||||||
target_include_directories(mbedtls PUBLIC ./mbedtls/include)
|
target_include_directories(mbedtls PUBLIC ./mbedtls/include)
|
||||||
|
@ -134,10 +134,6 @@ endif()
|
||||||
|
|
||||||
# Opus
|
# Opus
|
||||||
if (NOT TARGET Opus::opus)
|
if (NOT TARGET Opus::opus)
|
||||||
set(OPUS_BUILD_TESTING OFF)
|
|
||||||
set(OPUS_BUILD_PROGRAMS OFF)
|
|
||||||
set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF)
|
|
||||||
set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF)
|
|
||||||
add_subdirectory(opus)
|
add_subdirectory(opus)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -155,11 +151,6 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
||||||
add_subdirectory(Vulkan-Headers)
|
add_subdirectory(Vulkan-Headers)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Vulkan-Utility-Libraries
|
|
||||||
if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
|
||||||
add_subdirectory(Vulkan-Utility-Libraries)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# TZDB (Time Zone Database)
|
# TZDB (Time Zone Database)
|
||||||
add_subdirectory(nx_tzdb)
|
add_subdirectory(nx_tzdb)
|
||||||
|
|
||||||
|
@ -177,16 +168,9 @@ if (NOT TARGET LLVM::Demangle)
|
||||||
add_library(LLVM::Demangle ALIAS demangle)
|
add_library(LLVM::Demangle ALIAS demangle)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(stb stb/stb_dxt.cpp)
|
add_library(stb stb/stb_dxt.cpp stb/stb_image.cpp stb/stb_image_resize.cpp)
|
||||||
target_include_directories(stb PUBLIC ./stb)
|
target_include_directories(stb PUBLIC ./stb)
|
||||||
|
|
||||||
if (NOT TARGET stb::headers)
|
|
||||||
add_library(stb::headers ALIAS stb)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(tz tz/tz/tz.cpp)
|
|
||||||
target_include_directories(tz PUBLIC ./tz)
|
|
||||||
|
|
||||||
add_library(bc_decoder bc_decoder/bc_decoder.cpp)
|
add_library(bc_decoder bc_decoder/bc_decoder.cpp)
|
||||||
target_include_directories(bc_decoder PUBLIC ./bc_decoder)
|
target_include_directories(bc_decoder PUBLIC ./bc_decoder)
|
||||||
|
|
||||||
|
@ -201,116 +185,3 @@ if (ANDROID)
|
||||||
add_subdirectory(libadrenotools)
|
add_subdirectory(libadrenotools)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE AND NOT TARGET gamemode::headers)
|
|
||||||
add_library(gamemode INTERFACE)
|
|
||||||
target_include_directories(gamemode INTERFACE gamemode)
|
|
||||||
add_library(gamemode::headers ALIAS gamemode)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Breakpad
|
|
||||||
# https://github.com/microsoft/vcpkg/blob/master/ports/breakpad/CMakeLists.txt
|
|
||||||
if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client)
|
|
||||||
set(BREAKPAD_WIN32_DEFINES
|
|
||||||
NOMINMAX
|
|
||||||
UNICODE
|
|
||||||
WIN32_LEAN_AND_MEAN
|
|
||||||
_CRT_SECURE_NO_WARNINGS
|
|
||||||
_CRT_SECURE_NO_DEPRECATE
|
|
||||||
_CRT_NONSTDC_NO_DEPRECATE
|
|
||||||
)
|
|
||||||
|
|
||||||
# libbreakpad
|
|
||||||
add_library(libbreakpad STATIC)
|
|
||||||
file(GLOB_RECURSE LIBBREAKPAD_SOURCES breakpad/src/processor/*.cc)
|
|
||||||
file(GLOB_RECURSE LIBDISASM_SOURCES breakpad/src/third_party/libdisasm/*.c)
|
|
||||||
list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "_unittest|_selftest|synth_minidump|/tests|/testdata|/solaris|microdump_stackwalk|minidump_dump|minidump_stackwalk")
|
|
||||||
if (WIN32)
|
|
||||||
list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/linux|/mac|/android")
|
|
||||||
target_compile_definitions(libbreakpad PRIVATE ${BREAKPAD_WIN32_DEFINES})
|
|
||||||
target_include_directories(libbreakpad PRIVATE "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/include")
|
|
||||||
elseif (APPLE)
|
|
||||||
list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/linux|/windows|/android")
|
|
||||||
else()
|
|
||||||
list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/mac|/windows|/android")
|
|
||||||
endif()
|
|
||||||
target_sources(libbreakpad PRIVATE ${LIBBREAKPAD_SOURCES} ${LIBDISASM_SOURCES})
|
|
||||||
target_include_directories(libbreakpad
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/third_party/libdisasm
|
|
||||||
)
|
|
||||||
|
|
||||||
# libbreakpad_client
|
|
||||||
add_library(libbreakpad_client STATIC)
|
|
||||||
file(GLOB LIBBREAKPAD_COMMON_SOURCES breakpad/src/common/*.cc breakpad/src/common/*.c breakpad/src/client/*.cc)
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/windows/*.cc breakpad/src/common/windows/*.cc)
|
|
||||||
list(FILTER LIBBREAKPAD_COMMON_SOURCES EXCLUDE REGEX "language.cc|path_helper.cc|stabs_to_module.cc|stabs_reader.cc|minidump_file_writer.cc")
|
|
||||||
target_include_directories(libbreakpad_client PRIVATE "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/include")
|
|
||||||
target_compile_definitions(libbreakpad_client PRIVATE ${BREAKPAD_WIN32_DEFINES})
|
|
||||||
elseif (APPLE)
|
|
||||||
target_compile_definitions(libbreakpad_client PRIVATE HAVE_MACH_O_NLIST_H)
|
|
||||||
file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/mac/*.cc breakpad/src/common/mac/*.cc)
|
|
||||||
list(APPEND LIBBREAKPAD_CLIENT_SOURCES breakpad/src/common/mac/MachIPC.mm)
|
|
||||||
else()
|
|
||||||
target_compile_definitions(libbreakpad_client PUBLIC -DHAVE_A_OUT_H)
|
|
||||||
file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/linux/*.cc breakpad/src/common/linux/*.cc)
|
|
||||||
endif()
|
|
||||||
list(APPEND LIBBREAKPAD_CLIENT_SOURCES ${LIBBREAKPAD_COMMON_SOURCES})
|
|
||||||
list(FILTER LIBBREAKPAD_CLIENT_SOURCES EXCLUDE REGEX "/sender|/tests|/unittests|/testcases|_unittest|_test")
|
|
||||||
target_sources(libbreakpad_client PRIVATE ${LIBBREAKPAD_CLIENT_SOURCES})
|
|
||||||
target_include_directories(libbreakpad_client PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src)
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
target_link_libraries(libbreakpad_client PRIVATE wininet.lib)
|
|
||||||
elseif (APPLE)
|
|
||||||
find_library(CoreFoundation_FRAMEWORK CoreFoundation)
|
|
||||||
target_link_libraries(libbreakpad_client PRIVATE ${CoreFoundation_FRAMEWORK})
|
|
||||||
else()
|
|
||||||
find_library(PTHREAD_LIBRARIES pthread)
|
|
||||||
target_compile_definitions(libbreakpad_client PRIVATE HAVE_GETCONTEXT=1)
|
|
||||||
if (PTHREAD_LIBRARIES)
|
|
||||||
target_link_libraries(libbreakpad_client PRIVATE ${PTHREAD_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Host tools for symbol processing
|
|
||||||
if (LINUX)
|
|
||||||
find_package(ZLIB REQUIRED)
|
|
||||||
|
|
||||||
add_executable(minidump_stackwalk breakpad/src/processor/minidump_stackwalk.cc)
|
|
||||||
target_link_libraries(minidump_stackwalk PRIVATE libbreakpad libbreakpad_client)
|
|
||||||
|
|
||||||
add_executable(dump_syms
|
|
||||||
breakpad/src/common/dwarf_cfi_to_module.cc
|
|
||||||
breakpad/src/common/dwarf_cu_to_module.cc
|
|
||||||
breakpad/src/common/dwarf_line_to_module.cc
|
|
||||||
breakpad/src/common/dwarf_range_list_handler.cc
|
|
||||||
breakpad/src/common/language.cc
|
|
||||||
breakpad/src/common/module.cc
|
|
||||||
breakpad/src/common/path_helper.cc
|
|
||||||
breakpad/src/common/stabs_reader.cc
|
|
||||||
breakpad/src/common/stabs_to_module.cc
|
|
||||||
breakpad/src/common/dwarf/bytereader.cc
|
|
||||||
breakpad/src/common/dwarf/dwarf2diehandler.cc
|
|
||||||
breakpad/src/common/dwarf/dwarf2reader.cc
|
|
||||||
breakpad/src/common/dwarf/elf_reader.cc
|
|
||||||
breakpad/src/common/linux/crc32.cc
|
|
||||||
breakpad/src/common/linux/dump_symbols.cc
|
|
||||||
breakpad/src/common/linux/elf_symbols_to_module.cc
|
|
||||||
breakpad/src/common/linux/elfutils.cc
|
|
||||||
breakpad/src/common/linux/file_id.cc
|
|
||||||
breakpad/src/common/linux/linux_libc_support.cc
|
|
||||||
breakpad/src/common/linux/memory_mapped_file.cc
|
|
||||||
breakpad/src/common/linux/safe_readlink.cc
|
|
||||||
breakpad/src/tools/linux/dump_syms/dump_syms.cc)
|
|
||||||
target_link_libraries(dump_syms PRIVATE libbreakpad_client ZLIB::ZLIB)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# SimpleIni
|
|
||||||
if (NOT TARGET SimpleIni::SimpleIni)
|
|
||||||
add_subdirectory(simpleini)
|
|
||||||
endif()
|
|
||||||
|
|
2
externals/SDL
vendored
2
externals/SDL
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit cc016b0046d563287f0aa9f09b958b5e70d43696
|
Subproject commit 031912c4b6c5db80b443f04aa56fec3e4e645153
|
2
externals/Vulkan-Headers
vendored
2
externals/Vulkan-Headers
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 80207f9da86423ce33aff8328a792fd715f3c08f
|
Subproject commit ed857118e243fdc0f3a100f00ac9919e874cfe63
|
1
externals/Vulkan-Utility-Libraries
vendored
1
externals/Vulkan-Utility-Libraries
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 524f8910d0e4a5f2ec5961996b23e5b74b95cb1d
|
|
2
externals/VulkanMemoryAllocator
vendored
2
externals/VulkanMemoryAllocator
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 2f382df218d7e8516dee3b3caccb819a62b571a2
|
Subproject commit 9b0fc3e7b02afe97895eb3e945fe800c3a7485ac
|
1
externals/breakpad
vendored
1
externals/breakpad
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit c89f9dddc793f19910ef06c13e4fd240da4e7a59
|
|
2
externals/cpp-httplib
vendored
2
externals/cpp-httplib
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit a609330e4c6374f741d3b369269f7848255e1954
|
Subproject commit 6d963fbe8d415399d65e94db7910bbd22fe3741c
|
2
externals/cpp-jwt
vendored
2
externals/cpp-jwt
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 10ef5735d842b31025f1257ae78899f50a40fb14
|
Subproject commit e12ef06218596b52d9b5d6e1639484866a8e7067
|
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit ba8192d89078af51ae6f97c9352e3683612cdff1
|
Subproject commit 7da378033a7764f955516f75194856d87bbcd7a5
|
2
externals/ffmpeg/ffmpeg
vendored
2
externals/ffmpeg/ffmpeg
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 9c1294eaddb88cb0e044c675ccae059a85fc9c6c
|
Subproject commit 6b6b9e593dd4d3aaf75f48d40a13ef03bdef9fdb
|
376
externals/gamemode/gamemode_client.h
vendored
376
externals/gamemode/gamemode_client.h
vendored
|
@ -1,376 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2017-2019, Feral Interactive
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of Feral Interactive nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef CLIENT_GAMEMODE_H
|
|
||||||
#define CLIENT_GAMEMODE_H
|
|
||||||
/*
|
|
||||||
* GameMode supports the following client functions
|
|
||||||
* Requests are refcounted in the daemon
|
|
||||||
*
|
|
||||||
* int gamemode_request_start() - Request gamemode starts
|
|
||||||
* 0 if the request was sent successfully
|
|
||||||
* -1 if the request failed
|
|
||||||
*
|
|
||||||
* int gamemode_request_end() - Request gamemode ends
|
|
||||||
* 0 if the request was sent successfully
|
|
||||||
* -1 if the request failed
|
|
||||||
*
|
|
||||||
* GAMEMODE_AUTO can be defined to make the above two functions apply during static init and
|
|
||||||
* destruction, as appropriate. In this configuration, errors will be printed to stderr
|
|
||||||
*
|
|
||||||
* int gamemode_query_status() - Query the current status of gamemode
|
|
||||||
* 0 if gamemode is inactive
|
|
||||||
* 1 if gamemode is active
|
|
||||||
* 2 if gamemode is active and this client is registered
|
|
||||||
* -1 if the query failed
|
|
||||||
*
|
|
||||||
* int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process
|
|
||||||
* 0 if the request was sent successfully
|
|
||||||
* -1 if the request failed
|
|
||||||
* -2 if the request was rejected
|
|
||||||
*
|
|
||||||
* int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process
|
|
||||||
* 0 if the request was sent successfully
|
|
||||||
* -1 if the request failed
|
|
||||||
* -2 if the request was rejected
|
|
||||||
*
|
|
||||||
* int gamemode_query_status_for(pid_t pid) - Query status of gamemode for another process
|
|
||||||
* 0 if gamemode is inactive
|
|
||||||
* 1 if gamemode is active
|
|
||||||
* 2 if gamemode is active and this client is registered
|
|
||||||
* -1 if the query failed
|
|
||||||
*
|
|
||||||
* const char* gamemode_error_string() - Get an error string
|
|
||||||
* returns a string describing any of the above errors
|
|
||||||
*
|
|
||||||
* Note: All the above requests can be blocking - dbus requests can and will block while the daemon
|
|
||||||
* handles the request. It is not recommended to make these calls in performance critical code
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
static char internal_gamemode_client_error_string[512] = { 0 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load libgamemode dynamically to dislodge us from most dependencies.
|
|
||||||
* This allows clients to link and/or use this regardless of runtime.
|
|
||||||
* See SDL2 for an example of the reasoning behind this in terms of
|
|
||||||
* dynamic versioning as well.
|
|
||||||
*/
|
|
||||||
static volatile int internal_libgamemode_loaded = 1;
|
|
||||||
|
|
||||||
/* Typedefs for the functions to load */
|
|
||||||
typedef int (*api_call_return_int)(void);
|
|
||||||
typedef const char *(*api_call_return_cstring)(void);
|
|
||||||
typedef int (*api_call_pid_return_int)(pid_t);
|
|
||||||
|
|
||||||
/* Storage for functors */
|
|
||||||
static api_call_return_int REAL_internal_gamemode_request_start = NULL;
|
|
||||||
static api_call_return_int REAL_internal_gamemode_request_end = NULL;
|
|
||||||
static api_call_return_int REAL_internal_gamemode_query_status = NULL;
|
|
||||||
static api_call_return_cstring REAL_internal_gamemode_error_string = NULL;
|
|
||||||
static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL;
|
|
||||||
static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL;
|
|
||||||
static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal helper to perform the symbol binding safely.
|
|
||||||
*
|
|
||||||
* Returns 0 on success and -1 on failure
|
|
||||||
*/
|
|
||||||
__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(
|
|
||||||
void *handle, const char *name, void **out_func, size_t func_size, bool required)
|
|
||||||
{
|
|
||||||
void *symbol_lookup = NULL;
|
|
||||||
char *dl_error = NULL;
|
|
||||||
|
|
||||||
/* Safely look up the symbol */
|
|
||||||
symbol_lookup = dlsym(handle, name);
|
|
||||||
dl_error = dlerror();
|
|
||||||
if (required && (dl_error || !symbol_lookup)) {
|
|
||||||
snprintf(internal_gamemode_client_error_string,
|
|
||||||
sizeof(internal_gamemode_client_error_string),
|
|
||||||
"dlsym failed - %s",
|
|
||||||
dl_error);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Have the symbol correctly, copy it to make it usable */
|
|
||||||
memcpy(out_func, &symbol_lookup, func_size);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads libgamemode and needed functions
|
|
||||||
*
|
|
||||||
* Returns 0 on success and -1 on failure
|
|
||||||
*/
|
|
||||||
__attribute__((always_inline)) static inline int internal_load_libgamemode(void)
|
|
||||||
{
|
|
||||||
/* We start at 1, 0 is a success and -1 is a fail */
|
|
||||||
if (internal_libgamemode_loaded != 1) {
|
|
||||||
return internal_libgamemode_loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Anonymous struct type to define our bindings */
|
|
||||||
struct binding {
|
|
||||||
const char *name;
|
|
||||||
void **functor;
|
|
||||||
size_t func_size;
|
|
||||||
bool required;
|
|
||||||
} bindings[] = {
|
|
||||||
{ "real_gamemode_request_start",
|
|
||||||
(void **)&REAL_internal_gamemode_request_start,
|
|
||||||
sizeof(REAL_internal_gamemode_request_start),
|
|
||||||
true },
|
|
||||||
{ "real_gamemode_request_end",
|
|
||||||
(void **)&REAL_internal_gamemode_request_end,
|
|
||||||
sizeof(REAL_internal_gamemode_request_end),
|
|
||||||
true },
|
|
||||||
{ "real_gamemode_query_status",
|
|
||||||
(void **)&REAL_internal_gamemode_query_status,
|
|
||||||
sizeof(REAL_internal_gamemode_query_status),
|
|
||||||
false },
|
|
||||||
{ "real_gamemode_error_string",
|
|
||||||
(void **)&REAL_internal_gamemode_error_string,
|
|
||||||
sizeof(REAL_internal_gamemode_error_string),
|
|
||||||
true },
|
|
||||||
{ "real_gamemode_request_start_for",
|
|
||||||
(void **)&REAL_internal_gamemode_request_start_for,
|
|
||||||
sizeof(REAL_internal_gamemode_request_start_for),
|
|
||||||
false },
|
|
||||||
{ "real_gamemode_request_end_for",
|
|
||||||
(void **)&REAL_internal_gamemode_request_end_for,
|
|
||||||
sizeof(REAL_internal_gamemode_request_end_for),
|
|
||||||
false },
|
|
||||||
{ "real_gamemode_query_status_for",
|
|
||||||
(void **)&REAL_internal_gamemode_query_status_for,
|
|
||||||
sizeof(REAL_internal_gamemode_query_status_for),
|
|
||||||
false },
|
|
||||||
};
|
|
||||||
|
|
||||||
void *libgamemode = NULL;
|
|
||||||
|
|
||||||
/* Try and load libgamemode */
|
|
||||||
libgamemode = dlopen("libgamemode.so.0", RTLD_NOW);
|
|
||||||
if (!libgamemode) {
|
|
||||||
/* Attempt to load unversioned library for compatibility with older
|
|
||||||
* versions (as of writing, there are no ABI changes between the two -
|
|
||||||
* this may need to change if ever ABI-breaking changes are made) */
|
|
||||||
libgamemode = dlopen("libgamemode.so", RTLD_NOW);
|
|
||||||
if (!libgamemode) {
|
|
||||||
snprintf(internal_gamemode_client_error_string,
|
|
||||||
sizeof(internal_gamemode_client_error_string),
|
|
||||||
"dlopen failed - %s",
|
|
||||||
dlerror());
|
|
||||||
internal_libgamemode_loaded = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attempt to bind all symbols */
|
|
||||||
for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) {
|
|
||||||
struct binding *binder = &bindings[i];
|
|
||||||
|
|
||||||
if (internal_bind_libgamemode_symbol(libgamemode,
|
|
||||||
binder->name,
|
|
||||||
binder->functor,
|
|
||||||
binder->func_size,
|
|
||||||
binder->required)) {
|
|
||||||
internal_libgamemode_loaded = -1;
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Success */
|
|
||||||
internal_libgamemode_loaded = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect to the real libgamemode
|
|
||||||
*/
|
|
||||||
__attribute__((always_inline)) static inline const char *gamemode_error_string(void)
|
|
||||||
{
|
|
||||||
/* If we fail to load the system gamemode, or we have an error string already, return our error
|
|
||||||
* string instead of diverting to the system version */
|
|
||||||
if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
|
|
||||||
return internal_gamemode_client_error_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assert for static analyser that the function is not NULL */
|
|
||||||
assert(REAL_internal_gamemode_error_string != NULL);
|
|
||||||
|
|
||||||
return REAL_internal_gamemode_error_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect to the real libgamemode
|
|
||||||
* Allow automatically requesting game mode
|
|
||||||
* Also prints errors as they happen.
|
|
||||||
*/
|
|
||||||
#ifdef GAMEMODE_AUTO
|
|
||||||
__attribute__((constructor))
|
|
||||||
#else
|
|
||||||
__attribute__((always_inline)) static inline
|
|
||||||
#endif
|
|
||||||
int gamemode_request_start(void)
|
|
||||||
{
|
|
||||||
/* Need to load gamemode */
|
|
||||||
if (internal_load_libgamemode() < 0) {
|
|
||||||
#ifdef GAMEMODE_AUTO
|
|
||||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assert for static analyser that the function is not NULL */
|
|
||||||
assert(REAL_internal_gamemode_request_start != NULL);
|
|
||||||
|
|
||||||
if (REAL_internal_gamemode_request_start() < 0) {
|
|
||||||
#ifdef GAMEMODE_AUTO
|
|
||||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Redirect to the real libgamemode */
|
|
||||||
#ifdef GAMEMODE_AUTO
|
|
||||||
__attribute__((destructor))
|
|
||||||
#else
|
|
||||||
__attribute__((always_inline)) static inline
|
|
||||||
#endif
|
|
||||||
int gamemode_request_end(void)
|
|
||||||
{
|
|
||||||
/* Need to load gamemode */
|
|
||||||
if (internal_load_libgamemode() < 0) {
|
|
||||||
#ifdef GAMEMODE_AUTO
|
|
||||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assert for static analyser that the function is not NULL */
|
|
||||||
assert(REAL_internal_gamemode_request_end != NULL);
|
|
||||||
|
|
||||||
if (REAL_internal_gamemode_request_end() < 0) {
|
|
||||||
#ifdef GAMEMODE_AUTO
|
|
||||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Redirect to the real libgamemode */
|
|
||||||
__attribute__((always_inline)) static inline int gamemode_query_status(void)
|
|
||||||
{
|
|
||||||
/* Need to load gamemode */
|
|
||||||
if (internal_load_libgamemode() < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REAL_internal_gamemode_query_status == NULL) {
|
|
||||||
snprintf(internal_gamemode_client_error_string,
|
|
||||||
sizeof(internal_gamemode_client_error_string),
|
|
||||||
"gamemode_query_status missing (older host?)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return REAL_internal_gamemode_query_status();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Redirect to the real libgamemode */
|
|
||||||
__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
|
|
||||||
{
|
|
||||||
/* Need to load gamemode */
|
|
||||||
if (internal_load_libgamemode() < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REAL_internal_gamemode_request_start_for == NULL) {
|
|
||||||
snprintf(internal_gamemode_client_error_string,
|
|
||||||
sizeof(internal_gamemode_client_error_string),
|
|
||||||
"gamemode_request_start_for missing (older host?)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return REAL_internal_gamemode_request_start_for(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Redirect to the real libgamemode */
|
|
||||||
__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid)
|
|
||||||
{
|
|
||||||
/* Need to load gamemode */
|
|
||||||
if (internal_load_libgamemode() < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REAL_internal_gamemode_request_end_for == NULL) {
|
|
||||||
snprintf(internal_gamemode_client_error_string,
|
|
||||||
sizeof(internal_gamemode_client_error_string),
|
|
||||||
"gamemode_request_end_for missing (older host?)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return REAL_internal_gamemode_request_end_for(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Redirect to the real libgamemode */
|
|
||||||
__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid)
|
|
||||||
{
|
|
||||||
/* Need to load gamemode */
|
|
||||||
if (internal_load_libgamemode() < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REAL_internal_gamemode_query_status_for == NULL) {
|
|
||||||
snprintf(internal_gamemode_client_error_string,
|
|
||||||
sizeof(internal_gamemode_client_error_string),
|
|
||||||
"gamemode_query_status_for missing (older host?)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return REAL_internal_gamemode_query_status_for(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CLIENT_GAMEMODE_H
|
|
13
externals/inih/CMakeLists.txt
vendored
Normal file
13
externals/inih/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# SPDX-FileCopyrightText: 2014 Gui Andrade <admin@archshift.com>
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
add_library(inih
|
||||||
|
inih/ini.c
|
||||||
|
inih/ini.h
|
||||||
|
inih/cpp/INIReader.cpp
|
||||||
|
inih/cpp/INIReader.h
|
||||||
|
)
|
||||||
|
|
||||||
|
create_target_directory_groups(inih)
|
||||||
|
target_include_directories(inih INTERFACE inih/cpp)
|
||||||
|
add_library(inih::INIReader ALIAS inih)
|
1
externals/inih/inih
vendored
Submodule
1
externals/inih/inih
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 1e80a47dffbda813604f0913e2ad68c7054c14e4
|
7
externals/libusb/CMakeLists.txt
vendored
7
externals/libusb/CMakeLists.txt
vendored
|
@ -49,6 +49,11 @@ if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") OR APPLE)
|
||||||
|
|
||||||
set(LIBUSB_INCLUDE_DIRS "${LIBUSB_SRC_DIR}/libusb" CACHE PATH "libusb headers path" FORCE)
|
set(LIBUSB_INCLUDE_DIRS "${LIBUSB_SRC_DIR}/libusb" CACHE PATH "libusb headers path" FORCE)
|
||||||
|
|
||||||
|
# MINGW: causes "externals/libusb/libusb/libusb/os/windows_winusb.c:1427:2: error: conversion to non-scalar type requested", so cannot statically link it for now.
|
||||||
|
if (NOT MINGW)
|
||||||
|
set(LIBUSB_CFLAGS "-DGUID_DEVINTERFACE_USB_DEVICE=\\(GUID\\){0xA5DCBF10,0x6530,0x11D2,{0x90,0x1F,0x00,0xC0,0x4F,0xB9,0x51,0xED}}")
|
||||||
|
endif()
|
||||||
|
|
||||||
make_directory("${LIBUSB_PREFIX}")
|
make_directory("${LIBUSB_PREFIX}")
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
|
@ -141,6 +146,8 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
target_include_directories(usb BEFORE PRIVATE libusb/msvc)
|
target_include_directories(usb BEFORE PRIVATE libusb/msvc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Works around other libraries providing their own definition of USB GUIDs (e.g. SDL2)
|
||||||
|
target_compile_definitions(usb PRIVATE "-DGUID_DEVINTERFACE_USB_DEVICE=(GUID){ 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}}")
|
||||||
else()
|
else()
|
||||||
target_include_directories(usb
|
target_include_directories(usb
|
||||||
# turns out other projects also have "config.h", so make sure the
|
# turns out other projects also have "config.h", so make sure the
|
||||||
|
|
2
externals/libusb/libusb
vendored
2
externals/libusb/libusb
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit c060e9ce30ac2e3ffb49d94209c4dae77b6642f7
|
Subproject commit c6a35c56016ea2ab2f19115d2ea1e85e0edae155
|
4
externals/nx_tzdb/CMakeLists.txt
vendored
4
externals/nx_tzdb/CMakeLists.txt
vendored
|
@ -27,12 +27,12 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR ANDROID)
|
||||||
set(CAN_BUILD_NX_TZDB false)
|
set(CAN_BUILD_NX_TZDB false)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(NX_TZDB_VERSION "221202")
|
set(NX_TZDB_VERSION "220816")
|
||||||
set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
|
set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
|
||||||
|
|
||||||
set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")
|
set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")
|
||||||
|
|
||||||
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR})
|
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ARCHIVE})
|
||||||
set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
|
set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
|
||||||
|
|
||||||
message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")
|
message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")
|
||||||
|
|
4
externals/nx_tzdb/NxTzdbCreateHeader.cmake
vendored
4
externals/nx_tzdb/NxTzdbCreateHeader.cmake
vendored
|
@ -11,10 +11,6 @@ execute_process(
|
||||||
WORKING_DIRECTORY ${ZONE_PATH}
|
WORKING_DIRECTORY ${ZONE_PATH}
|
||||||
OUTPUT_VARIABLE FILE_LIST)
|
OUTPUT_VARIABLE FILE_LIST)
|
||||||
|
|
||||||
if (NOT FILE_LIST)
|
|
||||||
message(FATAL_ERROR "No timezone files found in directory ${ZONE_PATH}, did the download fail?")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(DIRECTORY_NAME ${HEADER_NAME})
|
set(DIRECTORY_NAME ${HEADER_NAME})
|
||||||
|
|
||||||
set(FILE_DATA "")
|
set(FILE_DATA "")
|
||||||
|
|
2
externals/nx_tzdb/tzdb_to_nx
vendored
2
externals/nx_tzdb/tzdb_to_nx
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 97929690234f2b4add36b33657fe3fe09bd57dfd
|
Subproject commit 212afa2394a74226dcf1b7996a570aae17debb69
|
1
externals/oaknut
vendored
1
externals/oaknut
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 9d091109deb445bc6e9289c6195a282b7c993d49
|
|
1
externals/opus
vendored
1
externals/opus
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 101a71e03bbf860aaafb7090a0e440675cb27660
|
|
259
externals/opus/CMakeLists.txt
vendored
Normal file
259
externals/opus/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 yuzu Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.8)
|
||||||
|
|
||||||
|
project(opus)
|
||||||
|
|
||||||
|
option(OPUS_STACK_PROTECTOR "Use stack protection" OFF)
|
||||||
|
option(OPUS_USE_ALLOCA "Use alloca for stack arrays (on non-C99 compilers)" OFF)
|
||||||
|
option(OPUS_CUSTOM_MODES "Enable non-Opus modes, e.g. 44.1 kHz & 2^n frames" OFF)
|
||||||
|
option(OPUS_FIXED_POINT "Compile as fixed-point (for machines without a fast enough FPU)" OFF)
|
||||||
|
option(OPUS_ENABLE_FLOAT_API "Compile with the floating point API (for machines with float library" ON)
|
||||||
|
|
||||||
|
include(opus/opus_functions.cmake)
|
||||||
|
|
||||||
|
if(OPUS_STACK_PROTECTOR)
|
||||||
|
if(NOT MSVC) # GC on by default on MSVC
|
||||||
|
check_and_set_flag(STACK_PROTECTION_STRONG -fstack-protector-strong)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(MSVC)
|
||||||
|
check_and_set_flag(BUFFER_SECURITY_CHECK /GS-)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(opus
|
||||||
|
# CELT sources
|
||||||
|
opus/celt/bands.c
|
||||||
|
opus/celt/celt.c
|
||||||
|
opus/celt/celt_decoder.c
|
||||||
|
opus/celt/celt_encoder.c
|
||||||
|
opus/celt/celt_lpc.c
|
||||||
|
opus/celt/cwrs.c
|
||||||
|
opus/celt/entcode.c
|
||||||
|
opus/celt/entdec.c
|
||||||
|
opus/celt/entenc.c
|
||||||
|
opus/celt/kiss_fft.c
|
||||||
|
opus/celt/laplace.c
|
||||||
|
opus/celt/mathops.c
|
||||||
|
opus/celt/mdct.c
|
||||||
|
opus/celt/modes.c
|
||||||
|
opus/celt/pitch.c
|
||||||
|
opus/celt/quant_bands.c
|
||||||
|
opus/celt/rate.c
|
||||||
|
opus/celt/vq.c
|
||||||
|
|
||||||
|
# SILK sources
|
||||||
|
opus/silk/A2NLSF.c
|
||||||
|
opus/silk/CNG.c
|
||||||
|
opus/silk/HP_variable_cutoff.c
|
||||||
|
opus/silk/LPC_analysis_filter.c
|
||||||
|
opus/silk/LPC_fit.c
|
||||||
|
opus/silk/LPC_inv_pred_gain.c
|
||||||
|
opus/silk/LP_variable_cutoff.c
|
||||||
|
opus/silk/NLSF2A.c
|
||||||
|
opus/silk/NLSF_VQ.c
|
||||||
|
opus/silk/NLSF_VQ_weights_laroia.c
|
||||||
|
opus/silk/NLSF_decode.c
|
||||||
|
opus/silk/NLSF_del_dec_quant.c
|
||||||
|
opus/silk/NLSF_encode.c
|
||||||
|
opus/silk/NLSF_stabilize.c
|
||||||
|
opus/silk/NLSF_unpack.c
|
||||||
|
opus/silk/NSQ.c
|
||||||
|
opus/silk/NSQ_del_dec.c
|
||||||
|
opus/silk/PLC.c
|
||||||
|
opus/silk/VAD.c
|
||||||
|
opus/silk/VQ_WMat_EC.c
|
||||||
|
opus/silk/ana_filt_bank_1.c
|
||||||
|
opus/silk/biquad_alt.c
|
||||||
|
opus/silk/bwexpander.c
|
||||||
|
opus/silk/bwexpander_32.c
|
||||||
|
opus/silk/check_control_input.c
|
||||||
|
opus/silk/code_signs.c
|
||||||
|
opus/silk/control_SNR.c
|
||||||
|
opus/silk/control_audio_bandwidth.c
|
||||||
|
opus/silk/control_codec.c
|
||||||
|
opus/silk/dec_API.c
|
||||||
|
opus/silk/decode_core.c
|
||||||
|
opus/silk/decode_frame.c
|
||||||
|
opus/silk/decode_indices.c
|
||||||
|
opus/silk/decode_parameters.c
|
||||||
|
opus/silk/decode_pitch.c
|
||||||
|
opus/silk/decode_pulses.c
|
||||||
|
opus/silk/decoder_set_fs.c
|
||||||
|
opus/silk/enc_API.c
|
||||||
|
opus/silk/encode_indices.c
|
||||||
|
opus/silk/encode_pulses.c
|
||||||
|
opus/silk/gain_quant.c
|
||||||
|
opus/silk/init_decoder.c
|
||||||
|
opus/silk/init_encoder.c
|
||||||
|
opus/silk/inner_prod_aligned.c
|
||||||
|
opus/silk/interpolate.c
|
||||||
|
opus/silk/lin2log.c
|
||||||
|
opus/silk/log2lin.c
|
||||||
|
opus/silk/pitch_est_tables.c
|
||||||
|
opus/silk/process_NLSFs.c
|
||||||
|
opus/silk/quant_LTP_gains.c
|
||||||
|
opus/silk/resampler.c
|
||||||
|
opus/silk/resampler_down2.c
|
||||||
|
opus/silk/resampler_down2_3.c
|
||||||
|
opus/silk/resampler_private_AR2.c
|
||||||
|
opus/silk/resampler_private_IIR_FIR.c
|
||||||
|
opus/silk/resampler_private_down_FIR.c
|
||||||
|
opus/silk/resampler_private_up2_HQ.c
|
||||||
|
opus/silk/resampler_rom.c
|
||||||
|
opus/silk/shell_coder.c
|
||||||
|
opus/silk/sigm_Q15.c
|
||||||
|
opus/silk/sort.c
|
||||||
|
opus/silk/stereo_LR_to_MS.c
|
||||||
|
opus/silk/stereo_MS_to_LR.c
|
||||||
|
opus/silk/stereo_decode_pred.c
|
||||||
|
opus/silk/stereo_encode_pred.c
|
||||||
|
opus/silk/stereo_find_predictor.c
|
||||||
|
opus/silk/stereo_quant_pred.c
|
||||||
|
opus/silk/sum_sqr_shift.c
|
||||||
|
opus/silk/table_LSF_cos.c
|
||||||
|
opus/silk/tables_LTP.c
|
||||||
|
opus/silk/tables_NLSF_CB_NB_MB.c
|
||||||
|
opus/silk/tables_NLSF_CB_WB.c
|
||||||
|
opus/silk/tables_gain.c
|
||||||
|
opus/silk/tables_other.c
|
||||||
|
opus/silk/tables_pitch_lag.c
|
||||||
|
opus/silk/tables_pulses_per_block.c
|
||||||
|
|
||||||
|
# Opus sources
|
||||||
|
opus/src/analysis.c
|
||||||
|
opus/src/mapping_matrix.c
|
||||||
|
opus/src/mlp.c
|
||||||
|
opus/src/mlp_data.c
|
||||||
|
opus/src/opus.c
|
||||||
|
opus/src/opus_decoder.c
|
||||||
|
opus/src/opus_encoder.c
|
||||||
|
opus/src/opus_multistream.c
|
||||||
|
opus/src/opus_multistream_decoder.c
|
||||||
|
opus/src/opus_multistream_encoder.c
|
||||||
|
opus/src/opus_projection_decoder.c
|
||||||
|
opus/src/opus_projection_encoder.c
|
||||||
|
opus/src/repacketizer.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
target_sources(opus PRIVATE opus/silk/debug.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (OPUS_FIXED_POINT)
|
||||||
|
target_sources(opus PRIVATE
|
||||||
|
opus/silk/fixed/LTP_analysis_filter_FIX.c
|
||||||
|
opus/silk/fixed/LTP_scale_ctrl_FIX.c
|
||||||
|
opus/silk/fixed/apply_sine_window_FIX.c
|
||||||
|
opus/silk/fixed/autocorr_FIX.c
|
||||||
|
opus/silk/fixed/burg_modified_FIX.c
|
||||||
|
opus/silk/fixed/corrMatrix_FIX.c
|
||||||
|
opus/silk/fixed/encode_frame_FIX.c
|
||||||
|
opus/silk/fixed/find_LPC_FIX.c
|
||||||
|
opus/silk/fixed/find_LTP_FIX.c
|
||||||
|
opus/silk/fixed/find_pitch_lags_FIX.c
|
||||||
|
opus/silk/fixed/find_pred_coefs_FIX.c
|
||||||
|
opus/silk/fixed/k2a_FIX.c
|
||||||
|
opus/silk/fixed/k2a_Q16_FIX.c
|
||||||
|
opus/silk/fixed/noise_shape_analysis_FIX.c
|
||||||
|
opus/silk/fixed/pitch_analysis_core_FIX.c
|
||||||
|
opus/silk/fixed/prefilter_FIX.c
|
||||||
|
opus/silk/fixed/process_gains_FIX.c
|
||||||
|
opus/silk/fixed/regularize_correlations_FIX.c
|
||||||
|
opus/silk/fixed/residual_energy16_FIX.c
|
||||||
|
opus/silk/fixed/residual_energy_FIX.c
|
||||||
|
opus/silk/fixed/schur64_FIX.c
|
||||||
|
opus/silk/fixed/schur_FIX.c
|
||||||
|
opus/silk/fixed/solve_LS_FIX.c
|
||||||
|
opus/silk/fixed/vector_ops_FIX.c
|
||||||
|
opus/silk/fixed/warped_autocorrelation_FIX.c
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
target_sources(opus PRIVATE
|
||||||
|
opus/silk/float/LPC_analysis_filter_FLP.c
|
||||||
|
opus/silk/float/LPC_inv_pred_gain_FLP.c
|
||||||
|
opus/silk/float/LTP_analysis_filter_FLP.c
|
||||||
|
opus/silk/float/LTP_scale_ctrl_FLP.c
|
||||||
|
opus/silk/float/apply_sine_window_FLP.c
|
||||||
|
opus/silk/float/autocorrelation_FLP.c
|
||||||
|
opus/silk/float/burg_modified_FLP.c
|
||||||
|
opus/silk/float/bwexpander_FLP.c
|
||||||
|
opus/silk/float/corrMatrix_FLP.c
|
||||||
|
opus/silk/float/encode_frame_FLP.c
|
||||||
|
opus/silk/float/energy_FLP.c
|
||||||
|
opus/silk/float/find_LPC_FLP.c
|
||||||
|
opus/silk/float/find_LTP_FLP.c
|
||||||
|
opus/silk/float/find_pitch_lags_FLP.c
|
||||||
|
opus/silk/float/find_pred_coefs_FLP.c
|
||||||
|
opus/silk/float/inner_product_FLP.c
|
||||||
|
opus/silk/float/k2a_FLP.c
|
||||||
|
opus/silk/float/noise_shape_analysis_FLP.c
|
||||||
|
opus/silk/float/pitch_analysis_core_FLP.c
|
||||||
|
opus/silk/float/process_gains_FLP.c
|
||||||
|
opus/silk/float/regularize_correlations_FLP.c
|
||||||
|
opus/silk/float/residual_energy_FLP.c
|
||||||
|
opus/silk/float/scale_copy_vector_FLP.c
|
||||||
|
opus/silk/float/scale_vector_FLP.c
|
||||||
|
opus/silk/float/schur_FLP.c
|
||||||
|
opus/silk/float/sort_FLP.c
|
||||||
|
opus/silk/float/warped_autocorrelation_FLP.c
|
||||||
|
opus/silk/float/wrappers_FLP.c
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(opus PRIVATE OPUS_BUILD ENABLE_HARDENING)
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
if(MINGW)
|
||||||
|
target_compile_definitions(opus PRIVATE _FORTIFY_SOURCE=0)
|
||||||
|
else()
|
||||||
|
target_compile_definitions(opus PRIVATE _FORTIFY_SOURCE=2)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# It is strongly recommended to uncomment one of these VAR_ARRAYS: Use C99
|
||||||
|
# variable-length arrays for stack allocation USE_ALLOCA: Use alloca() for stack
|
||||||
|
# allocation If none is defined, then the fallback is a non-threadsafe global
|
||||||
|
# array
|
||||||
|
if(OPUS_USE_ALLOCA OR MSVC)
|
||||||
|
target_compile_definitions(opus PRIVATE USE_ALLOCA)
|
||||||
|
else()
|
||||||
|
target_compile_definitions(opus PRIVATE VAR_ARRAYS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OPUS_CUSTOM_MODES)
|
||||||
|
target_compile_definitions(opus PRIVATE CUSTOM_MODES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT OPUS_ENABLE_FLOAT_API)
|
||||||
|
target_compile_definitions(opus PRIVATE DISABLE_FLOAT_API)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(opus
|
||||||
|
PUBLIC
|
||||||
|
-DOPUS_VERSION="\\"1.3.1\\""
|
||||||
|
|
||||||
|
PRIVATE
|
||||||
|
# Use C99 intrinsics to speed up float-to-int conversion
|
||||||
|
HAVE_LRINTF
|
||||||
|
)
|
||||||
|
|
||||||
|
if (FIXED_POINT)
|
||||||
|
target_compile_definitions(opus PRIVATE -DFIXED_POINT=1 -DDISABLE_FLOAT_API)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(opus
|
||||||
|
PUBLIC
|
||||||
|
opus/include
|
||||||
|
|
||||||
|
PRIVATE
|
||||||
|
opus/celt
|
||||||
|
opus/silk
|
||||||
|
opus/silk/fixed
|
||||||
|
opus/silk/float
|
||||||
|
opus/src
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(Opus::opus ALIAS opus)
|
1
externals/opus/opus
vendored
Submodule
1
externals/opus/opus
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit ad8fe90db79b7d2a135e3dfd2ed6631b0c5662ab
|
1
externals/simpleini
vendored
1
externals/simpleini
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 382ddbb4b92c0b26aa1b32cefba2002119a5b1f2
|
|
7529
externals/stb/stb_image.cpp
vendored
Normal file
7529
externals/stb/stb_image.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
7221
externals/stb/stb_image.h
vendored
7221
externals/stb/stb_image.h
vendored
File diff suppressed because it is too large
Load diff
2282
externals/stb/stb_image_resize.cpp
vendored
Normal file
2282
externals/stb/stb_image_resize.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
2214
externals/stb/stb_image_resize.h
vendored
2214
externals/stb/stb_image_resize.h
vendored
File diff suppressed because it is too large
Load diff
1724
externals/stb/stb_image_write.h
vendored
1724
externals/stb/stb_image_write.h
vendored
File diff suppressed because it is too large
Load diff
1636
externals/tz/tz/tz.cpp
vendored
1636
externals/tz/tz/tz.cpp
vendored
File diff suppressed because it is too large
Load diff
81
externals/tz/tz/tz.h
vendored
81
externals/tz/tz/tz.h
vendored
|
@ -1,81 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-FileCopyrightText: 1996 Arthur David Olson
|
|
||||||
// SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <limits>
|
|
||||||
#include <span>
|
|
||||||
#include <array>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
namespace Tz {
|
|
||||||
using u8 = uint8_t;
|
|
||||||
using s8 = int8_t;
|
|
||||||
using u16 = uint16_t;
|
|
||||||
using s16 = int16_t;
|
|
||||||
using u32 = uint32_t;
|
|
||||||
using s32 = int32_t;
|
|
||||||
using u64 = uint64_t;
|
|
||||||
using s64 = int64_t;
|
|
||||||
|
|
||||||
constexpr size_t TZ_MAX_TIMES = 1000;
|
|
||||||
constexpr size_t TZ_MAX_TYPES = 128;
|
|
||||||
constexpr size_t TZ_MAX_CHARS = 50;
|
|
||||||
constexpr size_t MY_TZNAME_MAX = 255;
|
|
||||||
constexpr size_t TZNAME_MAXIMUM = 255;
|
|
||||||
constexpr size_t TZ_MAX_LEAPS = 50;
|
|
||||||
constexpr s64 TIME_T_MAX = std::numeric_limits<s64>::max();
|
|
||||||
constexpr s64 TIME_T_MIN = std::numeric_limits<s64>::min();
|
|
||||||
constexpr size_t CHARS_EXTRA = 3;
|
|
||||||
constexpr size_t MAX_ZONE_CHARS = std::max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof("UTC"));
|
|
||||||
constexpr size_t MAX_TZNAME_CHARS = 2 * (MY_TZNAME_MAX + 1);
|
|
||||||
|
|
||||||
struct ttinfo {
|
|
||||||
s32 tt_utoff;
|
|
||||||
bool tt_isdst;
|
|
||||||
s32 tt_desigidx;
|
|
||||||
bool tt_ttisstd;
|
|
||||||
bool tt_ttisut;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(ttinfo) == 0x10, "ttinfo has the wrong size!");
|
|
||||||
|
|
||||||
struct Rule {
|
|
||||||
s32 timecnt;
|
|
||||||
s32 typecnt;
|
|
||||||
s32 charcnt;
|
|
||||||
bool goback;
|
|
||||||
bool goahead;
|
|
||||||
std::array <u8, 0x2> padding0;
|
|
||||||
std::array<s64, TZ_MAX_TIMES> ats;
|
|
||||||
std::array<u8, TZ_MAX_TIMES> types;
|
|
||||||
std::array<ttinfo, TZ_MAX_TYPES> ttis;
|
|
||||||
std::array<char, std::max(MAX_ZONE_CHARS, MAX_TZNAME_CHARS)> chars;
|
|
||||||
s32 defaulttype;
|
|
||||||
std::array <u8, 0x12C4> padding1;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(Rule) == 0x4000, "Rule has the wrong size!");
|
|
||||||
|
|
||||||
struct CalendarTimeInternal {
|
|
||||||
s32 tm_sec;
|
|
||||||
s32 tm_min;
|
|
||||||
s32 tm_hour;
|
|
||||||
s32 tm_mday;
|
|
||||||
s32 tm_mon;
|
|
||||||
s32 tm_year;
|
|
||||||
s32 tm_wday;
|
|
||||||
s32 tm_yday;
|
|
||||||
s32 tm_isdst;
|
|
||||||
std::array<char, 16> tm_zone;
|
|
||||||
s32 tm_utoff;
|
|
||||||
s32 time_index;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has the wrong size!");
|
|
||||||
|
|
||||||
s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary);
|
|
||||||
|
|
||||||
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep);
|
|
||||||
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp);
|
|
||||||
|
|
||||||
} // namespace Tz
|
|
2
externals/vcpkg
vendored
2
externals/vcpkg
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit a42af01b72c28a8e1d7b48107b33e4f286a55ef6
|
Subproject commit cbf56573a987527b39272e88cbdd11389b78c6e4
|
|
@ -21,7 +21,7 @@ if (MSVC)
|
||||||
# Avoid windows.h from including some usually unused libs like winsocks.h, since this might cause some redefinition errors.
|
# Avoid windows.h from including some usually unused libs like winsocks.h, since this might cause some redefinition errors.
|
||||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||||
|
|
||||||
# Ensure that projects are built with Unicode support.
|
# Ensure that projects build with Unicode support.
|
||||||
add_definitions(-DUNICODE -D_UNICODE)
|
add_definitions(-DUNICODE -D_UNICODE)
|
||||||
|
|
||||||
# /W4 - Level 4 warnings
|
# /W4 - Level 4 warnings
|
||||||
|
@ -54,11 +54,11 @@ if (MSVC)
|
||||||
/GT
|
/GT
|
||||||
|
|
||||||
# Modules
|
# Modules
|
||||||
/experimental:module- # Explicitly disable module support due to conflicts with precompiled headers.
|
/experimental:module- # Disable module support explicitly due to conflicts with precompiled headers
|
||||||
|
|
||||||
# External headers diagnostics
|
# External headers diagnostics
|
||||||
/external:anglebrackets # Treats all headers included by #include <header>, where the header file is enclosed in angle brackets (< >), as external headers
|
/external:anglebrackets # Treats all headers included by #include <header>, where the header file is enclosed in angle brackets (< >), as external headers
|
||||||
/external:W0 # Sets the default warning level to 0 for external headers, effectively disabling warnings for them.
|
/external:W0 # Sets the default warning level to 0 for external headers, effectively turning off warnings for external headers
|
||||||
|
|
||||||
# Warnings
|
# Warnings
|
||||||
/W4
|
/W4
|
||||||
|
@ -121,7 +121,6 @@ else()
|
||||||
-Wno-attributes
|
-Wno-attributes
|
||||||
-Wno-invalid-offsetof
|
-Wno-invalid-offsetof
|
||||||
-Wno-unused-parameter
|
-Wno-unused-parameter
|
||||||
-Wno-missing-field-initializers
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang
|
if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang
|
||||||
|
@ -186,10 +185,8 @@ add_subdirectory(common)
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
add_subdirectory(audio_core)
|
add_subdirectory(audio_core)
|
||||||
add_subdirectory(video_core)
|
add_subdirectory(video_core)
|
||||||
add_subdirectory(hid_core)
|
|
||||||
add_subdirectory(network)
|
add_subdirectory(network)
|
||||||
add_subdirectory(input_common)
|
add_subdirectory(input_common)
|
||||||
add_subdirectory(frontend_common)
|
|
||||||
add_subdirectory(shader_recompiler)
|
add_subdirectory(shader_recompiler)
|
||||||
|
|
||||||
if (YUZU_ROOM)
|
if (YUZU_ROOM)
|
||||||
|
|
|
@ -3,17 +3,16 @@
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import kotlin.collections.setOf
|
import kotlin.collections.setOf
|
||||||
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
|
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
|
||||||
import com.github.triplet.gradle.androidpublisher.ReleaseStatus
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("org.jetbrains.kotlin.android")
|
id("org.jetbrains.kotlin.android")
|
||||||
id("kotlin-parcelize")
|
id("kotlin-parcelize")
|
||||||
kotlin("plugin.serialization") version "1.9.20"
|
kotlin("plugin.serialization") version "1.8.21"
|
||||||
id("androidx.navigation.safeargs.kotlin")
|
id("androidx.navigation.safeargs.kotlin")
|
||||||
id("org.jlleitschuh.gradle.ktlint") version "11.4.0"
|
id("org.jlleitschuh.gradle.ktlint") version "11.4.0"
|
||||||
id("com.github.triplet.play") version "3.8.6"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +27,7 @@ android {
|
||||||
namespace = "org.yuzu.yuzu_emu"
|
namespace = "org.yuzu.yuzu_emu"
|
||||||
|
|
||||||
compileSdkVersion = "android-34"
|
compileSdkVersion = "android-34"
|
||||||
ndkVersion = "26.1.10909125"
|
ndkVersion = "25.2.9519653"
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
|
@ -48,10 +47,6 @@ android {
|
||||||
jniLibs.useLegacyPackaging = true
|
jniLibs.useLegacyPackaging = true
|
||||||
}
|
}
|
||||||
|
|
||||||
androidResources {
|
|
||||||
generateLocaleConfig = true
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO If this is ever modified, change application_id in strings.xml
|
// TODO If this is ever modified, change application_id in strings.xml
|
||||||
applicationId = "org.yuzu.yuzu_emu"
|
applicationId = "org.yuzu.yuzu_emu"
|
||||||
|
@ -59,7 +54,15 @@ android {
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionName = getGitVersion()
|
versionName = getGitVersion()
|
||||||
|
|
||||||
versionCode = if (System.getenv("AUTO_VERSIONED") == "true") {
|
// If you want to use autoVersion for the versionCode, create a property in local.properties
|
||||||
|
// named "autoVersioned" and set it to "true"
|
||||||
|
val properties = Properties()
|
||||||
|
val versionProperty = try {
|
||||||
|
properties.load(project.rootProject.file("local.properties").inputStream())
|
||||||
|
properties.getProperty("autoVersioned") ?: ""
|
||||||
|
} catch (e: Exception) { "" }
|
||||||
|
|
||||||
|
versionCode = if (versionProperty == "true") {
|
||||||
autoVersion
|
autoVersion
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
|
@ -75,8 +78,8 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
|
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
|
||||||
signingConfigs {
|
|
||||||
if (keystoreFile != null) {
|
if (keystoreFile != null) {
|
||||||
|
signingConfigs {
|
||||||
create("release") {
|
create("release") {
|
||||||
storeFile = file(keystoreFile)
|
storeFile = file(keystoreFile)
|
||||||
storePassword = System.getenv("ANDROID_KEYSTORE_PASS")
|
storePassword = System.getenv("ANDROID_KEYSTORE_PASS")
|
||||||
|
@ -84,12 +87,6 @@ android {
|
||||||
keyPassword = System.getenv("ANDROID_KEYSTORE_PASS")
|
keyPassword = System.getenv("ANDROID_KEYSTORE_PASS")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
create("default") {
|
|
||||||
storeFile = file("$projectDir/debug.keystore")
|
|
||||||
storePassword = "android"
|
|
||||||
keyAlias = "androiddebugkey"
|
|
||||||
keyPassword = "android"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define build types, which are orthogonal to product flavors.
|
// Define build types, which are orthogonal to product flavors.
|
||||||
|
@ -100,7 +97,7 @@ android {
|
||||||
signingConfig = if (keystoreFile != null) {
|
signingConfig = if (keystoreFile != null) {
|
||||||
signingConfigs.getByName("release")
|
signingConfigs.getByName("release")
|
||||||
} else {
|
} else {
|
||||||
signingConfigs.getByName("default")
|
signingConfigs.getByName("debug")
|
||||||
}
|
}
|
||||||
|
|
||||||
resValue("string", "app_name_suffixed", "yuzu")
|
resValue("string", "app_name_suffixed", "yuzu")
|
||||||
|
@ -117,7 +114,7 @@ android {
|
||||||
register("relWithDebInfo") {
|
register("relWithDebInfo") {
|
||||||
isDefault = true
|
isDefault = true
|
||||||
resValue("string", "app_name_suffixed", "yuzu Debug Release")
|
resValue("string", "app_name_suffixed", "yuzu Debug Release")
|
||||||
signingConfig = signingConfigs.getByName("default")
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
isDebuggable = true
|
isDebuggable = true
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
|
@ -132,7 +129,6 @@ android {
|
||||||
// Signed by debug key disallowing distribution on Play Store.
|
// Signed by debug key disallowing distribution on Play Store.
|
||||||
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
||||||
debug {
|
debug {
|
||||||
signingConfig = signingConfigs.getByName("default")
|
|
||||||
resValue("string", "app_name_suffixed", "yuzu Debug")
|
resValue("string", "app_name_suffixed", "yuzu Debug")
|
||||||
isDebuggable = true
|
isDebuggable = true
|
||||||
isJniDebuggable = true
|
isJniDebuggable = true
|
||||||
|
@ -174,8 +170,7 @@ android {
|
||||||
"-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
|
"-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
|
||||||
"-DYUZU_USE_BUNDLED_VCPKG=ON",
|
"-DYUZU_USE_BUNDLED_VCPKG=ON",
|
||||||
"-DYUZU_USE_BUNDLED_FFMPEG=ON",
|
"-DYUZU_USE_BUNDLED_FFMPEG=ON",
|
||||||
"-DYUZU_ENABLE_LTO=ON",
|
"-DYUZU_ENABLE_LTO=ON"
|
||||||
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
abiFilters("arm64-v8a", "x86_64")
|
abiFilters("arm64-v8a", "x86_64")
|
||||||
|
@ -188,15 +183,8 @@ tasks.create<Delete>("ktlintReset") {
|
||||||
delete(File(buildDir.path + File.separator + "intermediates/ktLint"))
|
delete(File(buildDir.path + File.separator + "intermediates/ktLint"))
|
||||||
}
|
}
|
||||||
|
|
||||||
val showFormatHelp = {
|
|
||||||
logger.lifecycle(
|
|
||||||
"If this check fails, please try running \"gradlew ktlintFormat\" for automatic " +
|
|
||||||
"codestyle fixes"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
tasks.getByPath("ktlintKotlinScriptCheck").doFirst { showFormatHelp.invoke() }
|
|
||||||
tasks.getByPath("ktlintMainSourceSetCheck").doFirst { showFormatHelp.invoke() }
|
|
||||||
tasks.getByPath("loadKtlintReporters").dependsOn("ktlintReset")
|
tasks.getByPath("loadKtlintReporters").dependsOn("ktlintReset")
|
||||||
|
tasks.getByPath("preBuild").dependsOn("ktlintCheck")
|
||||||
|
|
||||||
ktlint {
|
ktlint {
|
||||||
version.set("0.47.1")
|
version.set("0.47.1")
|
||||||
|
@ -214,69 +202,93 @@ ktlint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
play {
|
|
||||||
val keyPath = System.getenv("SERVICE_ACCOUNT_KEY_PATH")
|
|
||||||
if (keyPath != null) {
|
|
||||||
serviceAccountCredentials.set(File(keyPath))
|
|
||||||
}
|
|
||||||
track.set(System.getenv("STORE_TRACK") ?: "internal")
|
|
||||||
releaseStatus.set(ReleaseStatus.COMPLETED)
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.12.0")
|
implementation("androidx.core:core-ktx:1.10.1")
|
||||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
implementation("androidx.recyclerview:recyclerview:1.3.1")
|
implementation("androidx.recyclerview:recyclerview:1.3.0")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.fragment:fragment-ktx:1.6.1")
|
implementation("androidx.fragment:fragment-ktx:1.6.0")
|
||||||
implementation("androidx.documentfile:documentfile:1.0.1")
|
implementation("androidx.documentfile:documentfile:1.0.1")
|
||||||
implementation("com.google.android.material:material:1.9.0")
|
implementation("com.google.android.material:material:1.9.0")
|
||||||
implementation("androidx.preference:preference-ktx:1.2.1")
|
implementation("androidx.preference:preference:1.2.0")
|
||||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
|
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
|
||||||
implementation("io.coil-kt:coil:2.2.2")
|
implementation("io.coil-kt:coil:2.2.2")
|
||||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||||
implementation("androidx.window:window:1.2.0-beta03")
|
implementation("androidx.window:window:1.2.0-beta03")
|
||||||
|
implementation("org.ini4j:ini4j:0.5.4")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.4")
|
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
|
||||||
implementation("info.debatty:java-string-similarity:2.0.0")
|
implementation("info.debatty:java-string-similarity:2.0.0")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runGitCommand(command: List<String>): String {
|
fun getGitVersion(): String {
|
||||||
return try {
|
var versionName = "0.0"
|
||||||
ProcessBuilder(command)
|
|
||||||
|
try {
|
||||||
|
versionName = ProcessBuilder("git", "describe", "--always", "--long")
|
||||||
.directory(project.rootDir)
|
.directory(project.rootDir)
|
||||||
.redirectOutput(ProcessBuilder.Redirect.PIPE)
|
.redirectOutput(ProcessBuilder.Redirect.PIPE)
|
||||||
.redirectError(ProcessBuilder.Redirect.PIPE)
|
.redirectError(ProcessBuilder.Redirect.PIPE)
|
||||||
.start().inputStream.bufferedReader().use { it.readText() }
|
.start().inputStream.bufferedReader().use { it.readText() }
|
||||||
.trim()
|
.trim()
|
||||||
|
.replace(Regex("(-0)?-[^-]+$"), "")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.error("Cannot find git")
|
logger.error("Cannot find git, defaulting to dummy version number")
|
||||||
""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (System.getenv("GITHUB_ACTIONS") != null) {
|
||||||
|
val gitTag = System.getenv("GIT_TAG_NAME")
|
||||||
|
versionName = gitTag ?: versionName
|
||||||
|
}
|
||||||
|
|
||||||
|
return versionName
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGitVersion(): String {
|
fun getGitHash(): String {
|
||||||
val gitVersion = runGitCommand(
|
try {
|
||||||
listOf(
|
val processBuilder = ProcessBuilder("git", "rev-parse", "--short", "HEAD")
|
||||||
"git",
|
processBuilder.directory(project.rootDir)
|
||||||
"describe",
|
val process = processBuilder.start()
|
||||||
"--always",
|
val inputStream = process.inputStream
|
||||||
"--long"
|
val errorStream = process.errorStream
|
||||||
)
|
process.waitFor()
|
||||||
).replace(Regex("(-0)?-[^-]+$"), "")
|
|
||||||
val versionName = if (System.getenv("GITHUB_ACTIONS") != null) {
|
return if (process.exitValue() == 0) {
|
||||||
System.getenv("GIT_TAG_NAME") ?: gitVersion
|
inputStream.bufferedReader()
|
||||||
|
.use { it.readText().trim() } // return the value of gitHash
|
||||||
} else {
|
} else {
|
||||||
gitVersion
|
val errorMessage = errorStream.bufferedReader().use { it.readText().trim() }
|
||||||
|
logger.error("Error running git command: $errorMessage")
|
||||||
|
"dummy-hash" // return a dummy hash value in case of an error
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("$e: Cannot find git, defaulting to dummy build hash")
|
||||||
|
return "dummy-hash" // return a dummy hash value in case of an error
|
||||||
}
|
}
|
||||||
return versionName.ifEmpty { "0.0" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGitHash(): String =
|
fun getBranch(): String {
|
||||||
runGitCommand(listOf("git", "rev-parse", "--short", "HEAD")).ifEmpty { "dummy-hash" }
|
try {
|
||||||
|
val processBuilder = ProcessBuilder("git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||||
|
processBuilder.directory(project.rootDir)
|
||||||
|
val process = processBuilder.start()
|
||||||
|
val inputStream = process.inputStream
|
||||||
|
val errorStream = process.errorStream
|
||||||
|
process.waitFor()
|
||||||
|
|
||||||
fun getBranch(): String =
|
return if (process.exitValue() == 0) {
|
||||||
runGitCommand(listOf("git", "rev-parse", "--abbrev-ref", "HEAD")).ifEmpty { "dummy-hash" }
|
inputStream.bufferedReader()
|
||||||
|
.use { it.readText().trim() } // return the value of gitHash
|
||||||
|
} else {
|
||||||
|
val errorMessage = errorStream.bufferedReader().use { it.readText().trim() }
|
||||||
|
logger.error("Error running git command: $errorMessage")
|
||||||
|
"dummy-hash" // return a dummy hash value in case of an error
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("$e: Cannot find git, defaulting to dummy build hash")
|
||||||
|
return "dummy-hash" // return a dummy hash value in case of an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
|
@ -12,9 +12,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
<uses-feature android:name="android.hardware.vulkan.version" android:version="0x401000" android:required="true" />
|
<uses-feature android:name="android.hardware.vulkan.version" android:version="0x401000" android:required="true" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||||
<uses-permission android:name="android.permission.NFC" />
|
<uses-permission android:name="android.permission.NFC" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name="org.yuzu.yuzu_emu.YuzuApplication"
|
android:name="org.yuzu.yuzu_emu.YuzuApplication"
|
||||||
|
@ -25,14 +26,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:isGame="true"
|
android:isGame="true"
|
||||||
android:appCategory="game"
|
android:appCategory="game"
|
||||||
|
android:localeConfig="@xml/locales_config"
|
||||||
android:banner="@drawable/tv_banner"
|
android:banner="@drawable/tv_banner"
|
||||||
|
android:extractNativeLibs="true"
|
||||||
android:fullBackupContent="@xml/data_extraction_rules"
|
android:fullBackupContent="@xml/data_extraction_rules"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules_api_31"
|
android:dataExtractionRules="@xml/data_extraction_rules_api_31"
|
||||||
android:enableOnBackInvokedCallback="true">
|
android:enableOnBackInvokedCallback="true">
|
||||||
|
|
||||||
<meta-data android:name="android.game_mode_config"
|
|
||||||
android:resource="@xml/game_mode_config" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.yuzu.yuzu_emu.ui.main.MainActivity"
|
android:name="org.yuzu.yuzu_emu.ui.main.MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -79,6 +79,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
android:resource="@xml/nfc_tech_filter" />
|
android:resource="@xml/nfc_tech_filter" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<service android:name="org.yuzu.yuzu_emu.utils.ForegroundService" android:foregroundServiceType="specialUse">
|
||||||
|
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="Keep emulation running in background"/>
|
||||||
|
</service>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".features.DocumentProvider"
|
android:name=".features.DocumentProvider"
|
||||||
android:authorities="${applicationId}.user"
|
android:authorities="${applicationId}.user"
|
||||||
|
|
|
@ -3,30 +3,61 @@
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu
|
package org.yuzu.yuzu_emu
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.net.Uri
|
import android.os.Bundle
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
import org.yuzu.yuzu_emu.YuzuApplication.Companion.appContext
|
||||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||||
import org.yuzu.yuzu_emu.fragments.CoreErrorDialogFragment
|
import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath
|
||||||
import org.yuzu.yuzu_emu.utils.DocumentsTree
|
import org.yuzu.yuzu_emu.utils.FileUtil.exists
|
||||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
import org.yuzu.yuzu_emu.utils.FileUtil.getFileSize
|
||||||
|
import org.yuzu.yuzu_emu.utils.FileUtil.isDirectory
|
||||||
|
import org.yuzu.yuzu_emu.utils.FileUtil.openContentUri
|
||||||
import org.yuzu.yuzu_emu.utils.Log
|
import org.yuzu.yuzu_emu.utils.Log
|
||||||
import org.yuzu.yuzu_emu.model.InstallResult
|
import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
|
||||||
import org.yuzu.yuzu_emu.model.Patch
|
|
||||||
import org.yuzu.yuzu_emu.model.GameVerificationResult
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which contains methods that interact
|
* Class which contains methods that interact
|
||||||
* with the native side of the Yuzu code.
|
* with the native side of the Yuzu code.
|
||||||
*/
|
*/
|
||||||
object NativeLibrary {
|
object NativeLibrary {
|
||||||
|
/**
|
||||||
|
* Default controller id for each device
|
||||||
|
*/
|
||||||
|
const val Player1Device = 0
|
||||||
|
const val Player2Device = 1
|
||||||
|
const val Player3Device = 2
|
||||||
|
const val Player4Device = 3
|
||||||
|
const val Player5Device = 4
|
||||||
|
const val Player6Device = 5
|
||||||
|
const val Player7Device = 6
|
||||||
|
const val Player8Device = 7
|
||||||
|
const val ConsoleDevice = 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller type for each device
|
||||||
|
*/
|
||||||
|
const val ProController = 3
|
||||||
|
const val Handheld = 4
|
||||||
|
const val JoyconDual = 5
|
||||||
|
const val JoyconLeft = 6
|
||||||
|
const val JoyconRight = 7
|
||||||
|
const val GameCube = 8
|
||||||
|
const val Pokeball = 9
|
||||||
|
const val NES = 10
|
||||||
|
const val SNES = 11
|
||||||
|
const val N64 = 12
|
||||||
|
const val SegaGenesis = 13
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var sEmulationActivity = WeakReference<EmulationActivity?>(null)
|
var sEmulationActivity = WeakReference<EmulationActivity?>(null)
|
||||||
|
|
||||||
|
@ -41,74 +72,187 @@ object NativeLibrary {
|
||||||
@Keep
|
@Keep
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun openContentUri(path: String?, openmode: String?): Int {
|
fun openContentUri(path: String?, openmode: String?): Int {
|
||||||
return if (DocumentsTree.isNativePath(path!!)) {
|
return if (isNativePath(path!!)) {
|
||||||
YuzuApplication.documentsTree!!.openContentUri(path, openmode)
|
YuzuApplication.documentsTree!!.openContentUri(path, openmode)
|
||||||
} else {
|
} else {
|
||||||
FileUtil.openContentUri(path, openmode)
|
openContentUri(appContext, path, openmode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getSize(path: String?): Long {
|
fun getSize(path: String?): Long {
|
||||||
return if (DocumentsTree.isNativePath(path!!)) {
|
return if (isNativePath(path!!)) {
|
||||||
YuzuApplication.documentsTree!!.getFileSize(path)
|
YuzuApplication.documentsTree!!.getFileSize(path)
|
||||||
} else {
|
} else {
|
||||||
FileUtil.getFileSize(path)
|
getFileSize(appContext, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun exists(path: String?): Boolean {
|
fun exists(path: String?): Boolean {
|
||||||
return if (DocumentsTree.isNativePath(path!!)) {
|
return if (isNativePath(path!!)) {
|
||||||
YuzuApplication.documentsTree!!.exists(path)
|
YuzuApplication.documentsTree!!.exists(path)
|
||||||
} else {
|
} else {
|
||||||
FileUtil.exists(path, suppressLog = true)
|
exists(appContext, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isDirectory(path: String?): Boolean {
|
fun isDirectory(path: String?): Boolean {
|
||||||
return if (DocumentsTree.isNativePath(path!!)) {
|
return if (isNativePath(path!!)) {
|
||||||
YuzuApplication.documentsTree!!.isDirectory(path)
|
YuzuApplication.documentsTree!!.isDirectory(path)
|
||||||
} else {
|
} else {
|
||||||
FileUtil.isDirectory(path)
|
isDirectory(appContext, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Keep
|
/**
|
||||||
@JvmStatic
|
* Returns true if pro controller isn't available and handheld is
|
||||||
fun getParentDirectory(path: String): String =
|
*/
|
||||||
if (DocumentsTree.isNativePath(path)) {
|
external fun isHandheldOnly(): Boolean
|
||||||
YuzuApplication.documentsTree!!.getParentDirectory(path)
|
|
||||||
} else {
|
|
||||||
path
|
|
||||||
}
|
|
||||||
|
|
||||||
@Keep
|
/**
|
||||||
@JvmStatic
|
* Changes controller type for a specific device.
|
||||||
fun getFilename(path: String): String =
|
*
|
||||||
if (DocumentsTree.isNativePath(path)) {
|
* @param Device The input descriptor of the gamepad.
|
||||||
YuzuApplication.documentsTree!!.getFilename(path)
|
* @param Type The NpadStyleIndex of the gamepad.
|
||||||
} else {
|
*/
|
||||||
FileUtil.getFilename(Uri.parse(path))
|
external fun setDeviceType(Device: Int, Type: Int): Boolean
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Handles event when a gamepad is connected.
|
||||||
|
*
|
||||||
|
* @param Device The input descriptor of the gamepad.
|
||||||
|
*/
|
||||||
|
external fun onGamePadConnectEvent(Device: Int): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles event when a gamepad is disconnected.
|
||||||
|
*
|
||||||
|
* @param Device The input descriptor of the gamepad.
|
||||||
|
*/
|
||||||
|
external fun onGamePadDisconnectEvent(Device: Int): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles button press events for a gamepad.
|
||||||
|
*
|
||||||
|
* @param Device The input descriptor of the gamepad.
|
||||||
|
* @param Button Key code identifying which button was pressed.
|
||||||
|
* @param Action Mask identifying which action is happening (button pressed down, or button released).
|
||||||
|
* @return If we handled the button press.
|
||||||
|
*/
|
||||||
|
external fun onGamePadButtonEvent(Device: Int, Button: Int, Action: Int): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles joystick movement events.
|
||||||
|
*
|
||||||
|
* @param Device The device ID of the gamepad.
|
||||||
|
* @param Axis The axis ID
|
||||||
|
* @param x_axis The value of the x-axis represented by the given ID.
|
||||||
|
* @param y_axis The value of the y-axis represented by the given ID.
|
||||||
|
*/
|
||||||
|
external fun onGamePadJoystickEvent(
|
||||||
|
Device: Int,
|
||||||
|
Axis: Int,
|
||||||
|
x_axis: Float,
|
||||||
|
y_axis: Float
|
||||||
|
): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles motion events.
|
||||||
|
*
|
||||||
|
* @param delta_timestamp The finger id corresponding to this event
|
||||||
|
* @param gyro_x,gyro_y,gyro_z The value of the accelerometer sensor.
|
||||||
|
* @param accel_x,accel_y,accel_z The value of the y-axis
|
||||||
|
*/
|
||||||
|
external fun onGamePadMotionEvent(
|
||||||
|
Device: Int,
|
||||||
|
delta_timestamp: Long,
|
||||||
|
gyro_x: Float,
|
||||||
|
gyro_y: Float,
|
||||||
|
gyro_z: Float,
|
||||||
|
accel_x: Float,
|
||||||
|
accel_y: Float,
|
||||||
|
accel_z: Float
|
||||||
|
): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals and load a nfc tag
|
||||||
|
*
|
||||||
|
* @param data Byte array containing all the data from a nfc tag
|
||||||
|
*/
|
||||||
|
external fun onReadNfcTag(data: ByteArray?): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes current loaded nfc tag
|
||||||
|
*/
|
||||||
|
external fun onRemoveNfcTag(): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles touch press events.
|
||||||
|
*
|
||||||
|
* @param finger_id The finger id corresponding to this event
|
||||||
|
* @param x_axis The value of the x-axis.
|
||||||
|
* @param y_axis The value of the y-axis.
|
||||||
|
*/
|
||||||
|
external fun onTouchPressed(finger_id: Int, x_axis: Float, y_axis: Float)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles touch movement.
|
||||||
|
*
|
||||||
|
* @param x_axis The value of the instantaneous x-axis.
|
||||||
|
* @param y_axis The value of the instantaneous y-axis.
|
||||||
|
*/
|
||||||
|
external fun onTouchMoved(finger_id: Int, x_axis: Float, y_axis: Float)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles touch release events.
|
||||||
|
*
|
||||||
|
* @param finger_id The finger id corresponding to this event
|
||||||
|
*/
|
||||||
|
external fun onTouchReleased(finger_id: Int)
|
||||||
|
|
||||||
|
external fun reloadSettings()
|
||||||
|
|
||||||
|
external fun initGameIni(gameID: String?)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the embedded icon within the given ROM.
|
||||||
|
*
|
||||||
|
* @param filename the file path to the ROM.
|
||||||
|
* @return a byte array containing the JPEG data for the icon.
|
||||||
|
*/
|
||||||
|
external fun getIcon(filename: String): ByteArray
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the embedded title of the given ISO/ROM.
|
||||||
|
*
|
||||||
|
* @param filename The file path to the ISO/ROM.
|
||||||
|
* @return the embedded title of the ISO/ROM.
|
||||||
|
*/
|
||||||
|
external fun getTitle(filename: String): String
|
||||||
|
|
||||||
|
external fun getDescription(filename: String): String
|
||||||
|
|
||||||
|
external fun getGameId(filename: String): String
|
||||||
|
|
||||||
|
external fun getRegions(filename: String): String
|
||||||
|
|
||||||
|
external fun getCompany(filename: String): String
|
||||||
|
|
||||||
|
external fun isHomebrew(filename: String): Boolean
|
||||||
|
|
||||||
external fun setAppDirectory(directory: String)
|
external fun setAppDirectory(directory: String)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs a nsp or xci file to nand
|
* Installs a nsp or xci file to nand
|
||||||
* @param filename String representation of file uri
|
* @param filename String representation of file uri
|
||||||
* @return int representation of [InstallResult]
|
* @param extension Lowercase string representation of file extension without "."
|
||||||
*/
|
*/
|
||||||
external fun installFileToNand(
|
external fun installFileToNand(filename: String, extension: String): Int
|
||||||
filename: String,
|
|
||||||
callback: (max: Long, progress: Long) -> Boolean
|
|
||||||
): Int
|
|
||||||
|
|
||||||
external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean
|
|
||||||
|
|
||||||
external fun initializeGpuDriver(
|
external fun initializeGpuDriver(
|
||||||
hookLibDir: String?,
|
hookLibDir: String?,
|
||||||
|
@ -119,12 +263,19 @@ object NativeLibrary {
|
||||||
|
|
||||||
external fun reloadKeys(): Boolean
|
external fun reloadKeys(): Boolean
|
||||||
|
|
||||||
external fun initializeSystem(reload: Boolean)
|
external fun initializeEmulation()
|
||||||
|
|
||||||
|
external fun defaultCPUCore(): Int
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins emulation.
|
* Begins emulation.
|
||||||
*/
|
*/
|
||||||
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
|
external fun run(path: String?)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begins emulation from the specified savestate.
|
||||||
|
*/
|
||||||
|
external fun run(path: String?, savestatePath: String?, deleteSavestate: Boolean)
|
||||||
|
|
||||||
// Surface Handling
|
// Surface Handling
|
||||||
external fun surfaceChanged(surf: Surface?)
|
external fun surfaceChanged(surf: Surface?)
|
||||||
|
@ -146,6 +297,11 @@ object NativeLibrary {
|
||||||
*/
|
*/
|
||||||
external fun stopEmulation()
|
external fun stopEmulation()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the in-memory ROM metadata cache.
|
||||||
|
*/
|
||||||
|
external fun resetRomMetadata()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if emulation is running (or is paused).
|
* Returns true if emulation is running (or is paused).
|
||||||
*/
|
*/
|
||||||
|
@ -162,18 +318,9 @@ object NativeLibrary {
|
||||||
external fun getPerfStats(): DoubleArray
|
external fun getPerfStats(): DoubleArray
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current CPU backend.
|
* Notifies the core emulation that the orientation has changed.
|
||||||
*/
|
*/
|
||||||
external fun getCpuBackend(): String
|
external fun notifyOrientationChange(layout_option: Int, rotation: Int)
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current GPU Driver.
|
|
||||||
*/
|
|
||||||
external fun getGpuDriver(): String
|
|
||||||
|
|
||||||
external fun applySettings()
|
|
||||||
|
|
||||||
external fun logSettings()
|
|
||||||
|
|
||||||
enum class CoreError {
|
enum class CoreError {
|
||||||
ErrorSystemFiles,
|
ErrorSystemFiles,
|
||||||
|
@ -181,13 +328,46 @@ object NativeLibrary {
|
||||||
ErrorUnknown
|
ErrorUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
var coreErrorAlertResult = false
|
private var coreErrorAlertResult = false
|
||||||
val coreErrorAlertLock = Object()
|
private val coreErrorAlertLock = Object()
|
||||||
|
|
||||||
|
class CoreErrorDialogFragment : DialogFragment() {
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
val title = requireArguments().serializable<String>("title")
|
||||||
|
val message = requireArguments().serializable<String>("message")
|
||||||
|
|
||||||
|
return MaterialAlertDialogBuilder(requireActivity())
|
||||||
|
.setTitle(title)
|
||||||
|
.setMessage(message)
|
||||||
|
.setPositiveButton(R.string.continue_button, null)
|
||||||
|
.setNegativeButton(R.string.abort_button) { _: DialogInterface?, _: Int ->
|
||||||
|
coreErrorAlertResult = false
|
||||||
|
synchronized(coreErrorAlertLock) { coreErrorAlertLock.notify() }
|
||||||
|
}
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDismiss(dialog: DialogInterface) {
|
||||||
|
coreErrorAlertResult = true
|
||||||
|
synchronized(coreErrorAlertLock) { coreErrorAlertLock.notify() }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance(title: String?, message: String?): CoreErrorDialogFragment {
|
||||||
|
val frag = CoreErrorDialogFragment()
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString("title", title)
|
||||||
|
args.putString("message", message)
|
||||||
|
frag.arguments = args
|
||||||
|
return frag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun onCoreErrorImpl(title: String, message: String) {
|
private fun onCoreErrorImpl(title: String, message: String) {
|
||||||
val emulationActivity = sEmulationActivity.get()
|
val emulationActivity = sEmulationActivity.get()
|
||||||
if (emulationActivity == null) {
|
if (emulationActivity == null) {
|
||||||
Log.error("[NativeLibrary] EmulationActivity not present")
|
error("[NativeLibrary] EmulationActivity not present")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +383,7 @@ object NativeLibrary {
|
||||||
fun onCoreError(error: CoreError?, details: String): Boolean {
|
fun onCoreError(error: CoreError?, details: String): Boolean {
|
||||||
val emulationActivity = sEmulationActivity.get()
|
val emulationActivity = sEmulationActivity.get()
|
||||||
if (emulationActivity == null) {
|
if (emulationActivity == null) {
|
||||||
Log.error("[NativeLibrary] EmulationActivity not present")
|
error("[NativeLibrary] EmulationActivity not present")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +414,7 @@ object NativeLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the AlertDialog on the main thread.
|
// Show the AlertDialog on the main thread.
|
||||||
emulationActivity.runOnUiThread { onCoreErrorImpl(title, message) }
|
emulationActivity.runOnUiThread(Runnable { onCoreErrorImpl(title, message) })
|
||||||
|
|
||||||
// Wait for the lock to notify that it is complete.
|
// Wait for the lock to notify that it is complete.
|
||||||
synchronized(coreErrorAlertLock) { coreErrorAlertLock.wait() }
|
synchronized(coreErrorAlertLock) { coreErrorAlertLock.wait() }
|
||||||
|
@ -298,12 +478,12 @@ object NativeLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setEmulationActivity(emulationActivity: EmulationActivity?) {
|
fun setEmulationActivity(emulationActivity: EmulationActivity?) {
|
||||||
Log.debug("[NativeLibrary] Registering EmulationActivity.")
|
Log.verbose("[NativeLibrary] Registering EmulationActivity.")
|
||||||
sEmulationActivity = WeakReference(emulationActivity)
|
sEmulationActivity = WeakReference(emulationActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearEmulationActivity() {
|
fun clearEmulationActivity() {
|
||||||
Log.debug("[NativeLibrary] Unregistering EmulationActivity.")
|
Log.verbose("[NativeLibrary] Unregistering EmulationActivity.")
|
||||||
sEmulationActivity.clear()
|
sEmulationActivity.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,12 +499,6 @@ object NativeLibrary {
|
||||||
sEmulationActivity.get()!!.onEmulationStopped(status)
|
sEmulationActivity.get()!!.onEmulationStopped(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Keep
|
|
||||||
@JvmStatic
|
|
||||||
fun onProgramChanged(programIndex: Int) {
|
|
||||||
sEmulationActivity.get()!!.onProgramChanged(programIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs the Yuzu version, Android version and, CPU.
|
* Logs the Yuzu version, Android version and, CPU.
|
||||||
*/
|
*/
|
||||||
|
@ -348,115 +522,55 @@ object NativeLibrary {
|
||||||
external fun initializeEmptyUserDirectory()
|
external fun initializeEmptyUserDirectory()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the launch path for a given applet. It is the caller's responsibility to also
|
* Button type for use in onTouchEvent
|
||||||
* set the system's current applet ID before trying to launch the nca given by this function.
|
|
||||||
*
|
|
||||||
* @param id The applet entry ID
|
|
||||||
* @return The applet's launch path
|
|
||||||
*/
|
*/
|
||||||
external fun getAppletLaunchPath(id: Long): String
|
object ButtonType {
|
||||||
|
const val BUTTON_A = 0
|
||||||
|
const val BUTTON_B = 1
|
||||||
|
const val BUTTON_X = 2
|
||||||
|
const val BUTTON_Y = 3
|
||||||
|
const val STICK_L = 4
|
||||||
|
const val STICK_R = 5
|
||||||
|
const val TRIGGER_L = 6
|
||||||
|
const val TRIGGER_R = 7
|
||||||
|
const val TRIGGER_ZL = 8
|
||||||
|
const val TRIGGER_ZR = 9
|
||||||
|
const val BUTTON_PLUS = 10
|
||||||
|
const val BUTTON_MINUS = 11
|
||||||
|
const val DPAD_LEFT = 12
|
||||||
|
const val DPAD_UP = 13
|
||||||
|
const val DPAD_RIGHT = 14
|
||||||
|
const val DPAD_DOWN = 15
|
||||||
|
const val BUTTON_SL = 16
|
||||||
|
const val BUTTON_SR = 17
|
||||||
|
const val BUTTON_HOME = 18
|
||||||
|
const val BUTTON_CAPTURE = 19
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the system's current applet ID before launching.
|
* Stick type for use in onTouchEvent
|
||||||
*
|
|
||||||
* @param appletId One of the ids in the Service::AM::Applets::AppletId enum
|
|
||||||
*/
|
*/
|
||||||
external fun setCurrentAppletId(appletId: Int)
|
object StickType {
|
||||||
|
const val STICK_L = 0
|
||||||
|
const val STICK_R = 1
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the cabinet mode for launching the cabinet applet.
|
* Button states
|
||||||
*
|
|
||||||
* @param cabinetMode One of the modes that corresponds to the enum in Service::NFP::CabinetMode
|
|
||||||
*/
|
*/
|
||||||
external fun setCabinetMode(cabinetMode: Int)
|
object ButtonState {
|
||||||
|
const val RELEASED = 0
|
||||||
|
const val PRESSED = 1
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether NAND contents are available and valid.
|
* Result from installFileToNand
|
||||||
*
|
|
||||||
* @return 'true' if firmware is available
|
|
||||||
*/
|
*/
|
||||||
external fun isFirmwareAvailable(): Boolean
|
object InstallFileToNandResult {
|
||||||
|
const val Success = 0
|
||||||
/**
|
const val SuccessFileOverwritten = 1
|
||||||
* Checks the PatchManager for any addons that are available
|
const val Error = 2
|
||||||
*
|
const val ErrorBaseGame = 3
|
||||||
* @param path Path to game file. Can be a [Uri].
|
const val ErrorFilenameExtension = 4
|
||||||
* @param programId String representation of a game's program ID
|
}
|
||||||
* @return Array of available patches
|
|
||||||
*/
|
|
||||||
external fun getPatchesForFile(path: String, programId: String): Array<Patch>?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes an update for a given [programId]
|
|
||||||
* @param programId String representation of a game's program ID
|
|
||||||
*/
|
|
||||||
external fun removeUpdate(programId: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all DLC for a [programId]
|
|
||||||
* @param programId String representation of a game's program ID
|
|
||||||
*/
|
|
||||||
external fun removeDLC(programId: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a mod installed for a given [programId]
|
|
||||||
* @param programId String representation of a game's program ID
|
|
||||||
* @param name The name of a mod as given by [getPatchesForFile]. This corresponds with the name
|
|
||||||
* of the mod's directory in a game's load folder.
|
|
||||||
*/
|
|
||||||
external fun removeMod(programId: String, name: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies all installed content
|
|
||||||
* @param callback UI callback for verification progress. Return true in the callback to cancel.
|
|
||||||
* @return Array of content that failed verification. Successful if empty.
|
|
||||||
*/
|
|
||||||
external fun verifyInstalledContents(
|
|
||||||
callback: (max: Long, progress: Long) -> Boolean
|
|
||||||
): Array<String>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies the contents of a game
|
|
||||||
* @param path String path to a game
|
|
||||||
* @param callback UI callback for verification progress. Return true in the callback to cancel.
|
|
||||||
* @return Int that is meant to be converted to a [GameVerificationResult]
|
|
||||||
*/
|
|
||||||
external fun verifyGameContents(
|
|
||||||
path: String,
|
|
||||||
callback: (max: Long, progress: Long) -> Boolean
|
|
||||||
): Int
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the save location for a specific game
|
|
||||||
*
|
|
||||||
* @param programId String representation of a game's program ID
|
|
||||||
* @return Save data path that may not exist yet
|
|
||||||
*/
|
|
||||||
external fun getSavePath(programId: String): String
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the root save directory for the default profile as either
|
|
||||||
* /user/save/account/<user id raw string> or /user/save/000...000/<user id>
|
|
||||||
*
|
|
||||||
* @param future If true, returns the /user/save/account/... directory
|
|
||||||
* @return Save data path that may not exist yet
|
|
||||||
*/
|
|
||||||
external fun getDefaultProfileSaveDataRoot(future: Boolean): String
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a file to the manual filesystem provider in our EmulationSession instance
|
|
||||||
* @param path Path to the file we're adding. Can be a string representation of a [Uri] or
|
|
||||||
* a normal path
|
|
||||||
*/
|
|
||||||
external fun addFileToFilesystemProvider(path: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears all files added to the manual filesystem provider in our EmulationSession instance
|
|
||||||
*/
|
|
||||||
external fun clearFilesystemProvider()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if all necessary keys are present for decryption
|
|
||||||
*/
|
|
||||||
external fun areKeysPresent(): Boolean
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,26 @@ import android.app.Application
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.yuzu.yuzu_emu.features.input.NativeInput
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
import org.yuzu.yuzu_emu.utils.DocumentsTree
|
import org.yuzu.yuzu_emu.utils.DocumentsTree
|
||||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
import org.yuzu.yuzu_emu.utils.Log
|
|
||||||
|
|
||||||
fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
|
fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
|
||||||
|
|
||||||
class YuzuApplication : Application() {
|
class YuzuApplication : Application() {
|
||||||
private fun createNotificationChannels() {
|
private fun createNotificationChannels() {
|
||||||
|
val emulationChannel = NotificationChannel(
|
||||||
|
getString(R.string.emulation_notification_channel_id),
|
||||||
|
getString(R.string.emulation_notification_channel_name),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
)
|
||||||
|
emulationChannel.description = getString(
|
||||||
|
R.string.emulation_notification_channel_description
|
||||||
|
)
|
||||||
|
emulationChannel.setSound(null, null)
|
||||||
|
emulationChannel.vibrationPattern = null
|
||||||
|
|
||||||
val noticeChannel = NotificationChannel(
|
val noticeChannel = NotificationChannel(
|
||||||
getString(R.string.notice_notification_channel_id),
|
getString(R.string.notice_notification_channel_id),
|
||||||
getString(R.string.notice_notification_channel_name),
|
getString(R.string.notice_notification_channel_name),
|
||||||
|
@ -29,6 +38,7 @@ class YuzuApplication : Application() {
|
||||||
// Register the channel with the system; you can't change the importance
|
// Register the channel with the system; you can't change the importance
|
||||||
// or other notification behaviors after this
|
// or other notification behaviors after this
|
||||||
val notificationManager = getSystemService(NotificationManager::class.java)
|
val notificationManager = getSystemService(NotificationManager::class.java)
|
||||||
|
notificationManager.createNotificationChannel(emulationChannel)
|
||||||
notificationManager.createNotificationChannel(noticeChannel)
|
notificationManager.createNotificationChannel(noticeChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,10 +47,8 @@ class YuzuApplication : Application() {
|
||||||
application = this
|
application = this
|
||||||
documentsTree = DocumentsTree()
|
documentsTree = DocumentsTree()
|
||||||
DirectoryInitialization.start()
|
DirectoryInitialization.start()
|
||||||
GpuDriverHelper.initializeDriverParameters()
|
GpuDriverHelper.initializeDriverParameters(applicationContext)
|
||||||
NativeInput.reloadInputDevices()
|
|
||||||
NativeLibrary.logDeviceInfo()
|
NativeLibrary.logDeviceInfo()
|
||||||
Log.logDeviceInfo()
|
|
||||||
|
|
||||||
createNotificationChannels()
|
createNotificationChannels()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
package org.yuzu.yuzu_emu.activities
|
package org.yuzu.yuzu_emu.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.app.PictureInPictureParams
|
import android.app.PictureInPictureParams
|
||||||
import android.app.RemoteAction
|
import android.app.RemoteAction
|
||||||
|
@ -39,18 +40,16 @@ import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.databinding.ActivityEmulationBinding
|
import org.yuzu.yuzu_emu.databinding.ActivityEmulationBinding
|
||||||
import org.yuzu.yuzu_emu.features.input.NativeInput
|
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
import org.yuzu.yuzu_emu.model.EmulationViewModel
|
import org.yuzu.yuzu_emu.model.EmulationViewModel
|
||||||
import org.yuzu.yuzu_emu.model.Game
|
import org.yuzu.yuzu_emu.model.Game
|
||||||
|
import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
|
||||||
|
import org.yuzu.yuzu_emu.utils.ForegroundService
|
||||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||||
import org.yuzu.yuzu_emu.utils.Log
|
|
||||||
import org.yuzu.yuzu_emu.utils.MemoryUtil
|
import org.yuzu.yuzu_emu.utils.MemoryUtil
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
|
||||||
import org.yuzu.yuzu_emu.utils.NfcReader
|
import org.yuzu.yuzu_emu.utils.NfcReader
|
||||||
import org.yuzu.yuzu_emu.utils.ParamPackage
|
|
||||||
import org.yuzu.yuzu_emu.utils.ThemeHelper
|
import org.yuzu.yuzu_emu.utils.ThemeHelper
|
||||||
import java.text.NumberFormat
|
import java.text.NumberFormat
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
@ -58,8 +57,11 @@ import kotlin.math.roundToInt
|
||||||
class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
private lateinit var binding: ActivityEmulationBinding
|
private lateinit var binding: ActivityEmulationBinding
|
||||||
|
|
||||||
|
private var controllerMappingHelper: ControllerMappingHelper? = null
|
||||||
|
|
||||||
var isActivityRecreated = false
|
var isActivityRecreated = false
|
||||||
private lateinit var nfcReader: NfcReader
|
private lateinit var nfcReader: NfcReader
|
||||||
|
private lateinit var inputHandler: InputHandler
|
||||||
|
|
||||||
private val gyro = FloatArray(3)
|
private val gyro = FloatArray(3)
|
||||||
private val accel = FloatArray(3)
|
private val accel = FloatArray(3)
|
||||||
|
@ -73,39 +75,17 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
|
|
||||||
private val emulationViewModel: EmulationViewModel by viewModels()
|
private val emulationViewModel: EmulationViewModel by viewModels()
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
stopForegroundService(this)
|
||||||
|
emulationViewModel.clear()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
Log.gameLaunched = true
|
|
||||||
ThemeHelper.setTheme(this)
|
ThemeHelper.setTheme(this)
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
InputHandler.updateControllerData()
|
|
||||||
val players = NativeConfig.getInputSettings(true)
|
|
||||||
var hasConfiguredControllers = false
|
|
||||||
players.forEach {
|
|
||||||
if (it.hasMapping()) {
|
|
||||||
hasConfiguredControllers = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasConfiguredControllers && InputHandler.androidControllers.isNotEmpty()) {
|
|
||||||
var params: ParamPackage? = null
|
|
||||||
for (controller in InputHandler.registeredControllers) {
|
|
||||||
if (controller.get("port", -1) == 0) {
|
|
||||||
params = controller
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params != null) {
|
|
||||||
NativeInput.updateMappingsWithDefault(
|
|
||||||
0,
|
|
||||||
params,
|
|
||||||
params.get("display", getString(R.string.unknown))
|
|
||||||
)
|
|
||||||
NativeConfig.saveGlobalConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding = ActivityEmulationBinding.inflate(layoutInflater)
|
binding = ActivityEmulationBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
@ -115,6 +95,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
|
|
||||||
isActivityRecreated = savedInstanceState != null
|
isActivityRecreated = savedInstanceState != null
|
||||||
|
|
||||||
|
controllerMappingHelper = ControllerMappingHelper()
|
||||||
|
|
||||||
// Set these options now so that the SurfaceView the game renders into is the right size.
|
// Set these options now so that the SurfaceView the game renders into is the right size.
|
||||||
enableFullscreenImmersive()
|
enableFullscreenImmersive()
|
||||||
|
|
||||||
|
@ -123,9 +105,12 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
nfcReader = NfcReader(this)
|
nfcReader = NfcReader(this)
|
||||||
nfcReader.initialize()
|
nfcReader.initialize()
|
||||||
|
|
||||||
|
inputHandler = InputHandler()
|
||||||
|
inputHandler.initialize()
|
||||||
|
|
||||||
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||||
if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) {
|
if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) {
|
||||||
if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.totalMemory)) {
|
if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.Gb)) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this,
|
this,
|
||||||
getString(
|
getString(
|
||||||
|
@ -144,6 +129,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start a foreground service to prevent the app from getting killed in the background
|
||||||
|
val startIntent = Intent(this, ForegroundService::class.java)
|
||||||
|
startForegroundService(startIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||||
|
@ -173,7 +162,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
nfcReader.startScanning()
|
nfcReader.startScanning()
|
||||||
startMotionSensorListener()
|
startMotionSensorListener()
|
||||||
InputHandler.updateControllerData()
|
|
||||||
|
|
||||||
buildPictureInPictureParams()
|
buildPictureInPictureParams()
|
||||||
}
|
}
|
||||||
|
@ -186,7 +174,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
|
|
||||||
override fun onUserLeaveHint() {
|
override fun onUserLeaveHint() {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||||
if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) {
|
if (BooleanSetting.PICTURE_IN_PICTURE.boolean && !isInPictureInPictureMode) {
|
||||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||||
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
|
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
|
||||||
|
@ -198,7 +186,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
setIntent(intent)
|
setIntent(intent)
|
||||||
nfcReader.onNewIntent(intent)
|
nfcReader.onNewIntent(intent)
|
||||||
InputHandler.updateControllerData()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||||
|
@ -208,11 +195,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
return super.dispatchKeyEvent(event)
|
return super.dispatchKeyEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emulationViewModel.drawerOpen.value) {
|
return inputHandler.dispatchKeyEvent(event)
|
||||||
return super.dispatchKeyEvent(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
return InputHandler.dispatchKeyEvent(event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
||||||
|
@ -222,16 +205,12 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
return super.dispatchGenericMotionEvent(event)
|
return super.dispatchGenericMotionEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emulationViewModel.drawerOpen.value) {
|
|
||||||
return super.dispatchGenericMotionEvent(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't attempt to do anything if we are disconnecting a device.
|
// Don't attempt to do anything if we are disconnecting a device.
|
||||||
if (event.actionMasked == MotionEvent.ACTION_CANCEL) {
|
if (event.actionMasked == MotionEvent.ACTION_CANCEL) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return InputHandler.dispatchGenericMotionEvent(event)
|
return inputHandler.dispatchGenericMotionEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSensorChanged(event: SensorEvent) {
|
override fun onSensorChanged(event: SensorEvent) {
|
||||||
|
@ -271,8 +250,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
}
|
}
|
||||||
val deltaTimestamp = (event.timestamp - motionTimestamp) / 1000
|
val deltaTimestamp = (event.timestamp - motionTimestamp) / 1000
|
||||||
motionTimestamp = event.timestamp
|
motionTimestamp = event.timestamp
|
||||||
NativeInput.onDeviceMotionEvent(
|
NativeLibrary.onGamePadMotionEvent(
|
||||||
NativeInput.Player1Device,
|
NativeLibrary.Player1Device,
|
||||||
deltaTimestamp,
|
deltaTimestamp,
|
||||||
gyro[0],
|
gyro[0],
|
||||||
gyro[1],
|
gyro[1],
|
||||||
|
@ -281,8 +260,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
accel[1],
|
accel[1],
|
||||||
accel[2]
|
accel[2]
|
||||||
)
|
)
|
||||||
NativeInput.onDeviceMotionEvent(
|
NativeLibrary.onGamePadMotionEvent(
|
||||||
NativeInput.ConsoleDevice,
|
NativeLibrary.ConsoleDevice,
|
||||||
deltaTimestamp,
|
deltaTimestamp,
|
||||||
gyro[0],
|
gyro[0],
|
||||||
gyro[1],
|
gyro[1],
|
||||||
|
@ -307,7 +286,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
|
|
||||||
private fun PictureInPictureParams.Builder.getPictureInPictureAspectBuilder():
|
private fun PictureInPictureParams.Builder.getPictureInPictureAspectBuilder():
|
||||||
PictureInPictureParams.Builder {
|
PictureInPictureParams.Builder {
|
||||||
val aspectRatio = when (IntSetting.RENDERER_ASPECT_RATIO.getInt()) {
|
val aspectRatio = when (IntSetting.RENDERER_ASPECT_RATIO.int) {
|
||||||
0 -> Rational(16, 9)
|
0 -> Rational(16, 9)
|
||||||
1 -> Rational(4, 3)
|
1 -> Rational(4, 3)
|
||||||
2 -> Rational(21, 9)
|
2 -> Rational(21, 9)
|
||||||
|
@ -354,7 +333,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
pictureInPictureActions.add(pauseRemoteAction)
|
pictureInPictureActions.add(pauseRemoteAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BooleanSetting.AUDIO_MUTED.getBoolean()) {
|
if (BooleanSetting.AUDIO_MUTED.boolean) {
|
||||||
val unmuteIcon = Icon.createWithResource(
|
val unmuteIcon = Icon.createWithResource(
|
||||||
this@EmulationActivity,
|
this@EmulationActivity,
|
||||||
R.drawable.ic_pip_unmute
|
R.drawable.ic_pip_unmute
|
||||||
|
@ -396,10 +375,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
val isEmulationActive = emulationViewModel.emulationStarted.value &&
|
|
||||||
!emulationViewModel.isEmulationStopping.value
|
|
||||||
pictureInPictureParamsBuilder.setAutoEnterEnabled(
|
pictureInPictureParamsBuilder.setAutoEnterEnabled(
|
||||||
BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive
|
BooleanSetting.PICTURE_IN_PICTURE.boolean
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
||||||
|
@ -413,13 +390,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
if (!NativeLibrary.isPaused()) NativeLibrary.pauseEmulation()
|
if (!NativeLibrary.isPaused()) NativeLibrary.pauseEmulation()
|
||||||
}
|
}
|
||||||
if (intent.action == actionUnmute) {
|
if (intent.action == actionUnmute) {
|
||||||
if (BooleanSetting.AUDIO_MUTED.getBoolean()) {
|
if (BooleanSetting.AUDIO_MUTED.boolean) BooleanSetting.AUDIO_MUTED.setBoolean(false)
|
||||||
BooleanSetting.AUDIO_MUTED.setBoolean(false)
|
|
||||||
}
|
|
||||||
} else if (intent.action == actionMute) {
|
} else if (intent.action == actionMute) {
|
||||||
if (!BooleanSetting.AUDIO_MUTED.getBoolean()) {
|
if (!BooleanSetting.AUDIO_MUTED.boolean) BooleanSetting.AUDIO_MUTED.setBoolean(true)
|
||||||
BooleanSetting.AUDIO_MUTED.setBoolean(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
buildPictureInPictureParams()
|
buildPictureInPictureParams()
|
||||||
}
|
}
|
||||||
|
@ -450,9 +423,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
}
|
}
|
||||||
// Always resume audio, since there is no UI button
|
// Always resume audio, since there is no UI button
|
||||||
if (BooleanSetting.AUDIO_MUTED.getBoolean()) {
|
if (BooleanSetting.AUDIO_MUTED.boolean) BooleanSetting.AUDIO_MUTED.setBoolean(false)
|
||||||
BooleanSetting.AUDIO_MUTED.setBoolean(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,14 +432,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEmulationStopped(status: Int) {
|
fun onEmulationStopped(status: Int) {
|
||||||
if (status == 0 && emulationViewModel.programChanged.value == -1) {
|
if (status == 0) {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
emulationViewModel.setEmulationStopped(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onProgramChanged(programIndex: Int) {
|
|
||||||
emulationViewModel.setProgramChanged(programIndex)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startMotionSensorListener() {
|
private fun startMotionSensorListener() {
|
||||||
|
@ -497,6 +463,12 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||||
activity.startActivity(launcher)
|
activity.startActivity(launcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun stopForegroundService(activity: Activity) {
|
||||||
|
val startIntent = Intent(activity, ForegroundService::class.java)
|
||||||
|
startIntent.action = ForegroundService.ACTION_STOP
|
||||||
|
activity.startForegroundService(startIntent)
|
||||||
|
}
|
||||||
|
|
||||||
private fun areCoordinatesOutside(view: View?, x: Float, y: Float): Boolean {
|
private fun areCoordinatesOutside(view: View?, x: Float, y: Float): Boolean {
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.adapters
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
|
||||||
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic adapter that implements an [AsyncDifferConfig] and covers some of the basic boilerplate
|
|
||||||
* code used in every [RecyclerView].
|
|
||||||
* Type assigned to [Model] must inherit from [Object] in order to be compared properly.
|
|
||||||
* @param exact Decides whether each item will be compared by reference or by their contents
|
|
||||||
*/
|
|
||||||
abstract class AbstractDiffAdapter<Model : Any, Holder : AbstractViewHolder<Model>>(
|
|
||||||
exact: Boolean = true
|
|
||||||
) : ListAdapter<Model, Holder>(AsyncDifferConfig.Builder(DiffCallback<Model>(exact)).build()) {
|
|
||||||
override fun onBindViewHolder(holder: Holder, position: Int) =
|
|
||||||
holder.bind(currentList[position])
|
|
||||||
|
|
||||||
private class DiffCallback<Model>(val exact: Boolean) : DiffUtil.ItemCallback<Model>() {
|
|
||||||
override fun areItemsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean {
|
|
||||||
if (exact) {
|
|
||||||
return oldItem === newItem
|
|
||||||
}
|
|
||||||
return oldItem == newItem
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("DiffUtilEquals")
|
|
||||||
override fun areContentsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean {
|
|
||||||
return oldItem == newItem
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.adapters
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic list class meant to take care of basic lists
|
|
||||||
* @param currentList The list to show initially
|
|
||||||
*/
|
|
||||||
abstract class AbstractListAdapter<Model : Any, Holder : AbstractViewHolder<Model>>(
|
|
||||||
open var currentList: List<Model>
|
|
||||||
) : RecyclerView.Adapter<Holder>() {
|
|
||||||
override fun onBindViewHolder(holder: Holder, position: Int) =
|
|
||||||
holder.bind(currentList[position])
|
|
||||||
|
|
||||||
override fun getItemCount(): Int = currentList.size
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an item to [currentList] and notifies the underlying adapter of the change. If no parameter
|
|
||||||
* is passed in for position, [item] is added to the end of the list. Invokes [callback] last.
|
|
||||||
* @param item The item to add to the list
|
|
||||||
* @param position Index where [item] will be added
|
|
||||||
* @param callback Lambda that's called at the end of the list changes and has the added list
|
|
||||||
* position passed in as a parameter
|
|
||||||
*/
|
|
||||||
open fun addItem(item: Model, position: Int = -1, callback: ((position: Int) -> Unit)? = null) {
|
|
||||||
val newList = currentList.toMutableList()
|
|
||||||
val positionToUpdate: Int
|
|
||||||
if (position == -1) {
|
|
||||||
newList.add(item)
|
|
||||||
currentList = newList
|
|
||||||
positionToUpdate = currentList.size - 1
|
|
||||||
} else {
|
|
||||||
newList.add(position, item)
|
|
||||||
currentList = newList
|
|
||||||
positionToUpdate = position
|
|
||||||
}
|
|
||||||
onItemAdded(positionToUpdate, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun onItemAdded(position: Int, callback: ((Int) -> Unit)? = null) {
|
|
||||||
notifyItemInserted(position)
|
|
||||||
callback?.invoke(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces the [item] at [position] in the [currentList] and notifies the underlying adapter
|
|
||||||
* of the change. Invokes [callback] last.
|
|
||||||
* @param item New list item
|
|
||||||
* @param position Index where [item] will replace the existing list item
|
|
||||||
* @param callback Lambda that's called at the end of the list changes and has the changed list
|
|
||||||
* position passed in as a parameter
|
|
||||||
*/
|
|
||||||
fun changeItem(item: Model, position: Int, callback: ((position: Int) -> Unit)? = null) {
|
|
||||||
val newList = currentList.toMutableList()
|
|
||||||
newList[position] = item
|
|
||||||
currentList = newList
|
|
||||||
onItemChanged(position, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun onItemChanged(position: Int, callback: ((Int) -> Unit)? = null) {
|
|
||||||
notifyItemChanged(position)
|
|
||||||
callback?.invoke(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the list item at [position] in [currentList] and notifies the underlying adapter
|
|
||||||
* of the change. Invokes [callback] last.
|
|
||||||
* @param position Index where the list item will be removed
|
|
||||||
* @param callback Lambda that's called at the end of the list changes and has the removed list
|
|
||||||
* position passed in as a parameter
|
|
||||||
*/
|
|
||||||
fun removeItem(position: Int, callback: ((position: Int) -> Unit)? = null) {
|
|
||||||
val newList = currentList.toMutableList()
|
|
||||||
newList.removeAt(position)
|
|
||||||
currentList = newList
|
|
||||||
onItemRemoved(position, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun onItemRemoved(position: Int, callback: ((Int) -> Unit)? = null) {
|
|
||||||
notifyItemRemoved(position)
|
|
||||||
callback?.invoke(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces [currentList] with [newList] and notifies the underlying adapter of the change.
|
|
||||||
* @param newList The new list to replace [currentList]
|
|
||||||
*/
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
|
||||||
open fun replaceList(newList: List<Model>) {
|
|
||||||
currentList = newList
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.adapters
|
|
||||||
|
|
||||||
import org.yuzu.yuzu_emu.model.SelectableItem
|
|
||||||
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic list class meant to take care of single selection UI updates
|
|
||||||
* @param currentList The list to show initially
|
|
||||||
* @param defaultSelection The default selection to use if no list items are selected by
|
|
||||||
* [SelectableItem.selected] or if the currently selected item is removed from the list
|
|
||||||
*/
|
|
||||||
abstract class AbstractSingleSelectionList<
|
|
||||||
Model : SelectableItem,
|
|
||||||
Holder : AbstractViewHolder<Model>
|
|
||||||
>(
|
|
||||||
final override var currentList: List<Model>,
|
|
||||||
private val defaultSelection: DefaultSelection = DefaultSelection.Start
|
|
||||||
) : AbstractListAdapter<Model, Holder>(currentList) {
|
|
||||||
var selectedItem = getDefaultSelection()
|
|
||||||
|
|
||||||
init {
|
|
||||||
findSelectedItem()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the selection state of the [SelectableItem] that was selected and the previously selected
|
|
||||||
* item and notifies the underlying adapter of the change for those items. Invokes [callback] last.
|
|
||||||
* Does nothing if [position] is the same as the currently selected item.
|
|
||||||
* @param position Index of the item that was selected
|
|
||||||
* @param callback Lambda that's called at the end of the list changes and has the selected list
|
|
||||||
* position passed in as a parameter
|
|
||||||
*/
|
|
||||||
fun selectItem(position: Int, callback: ((position: Int) -> Unit)? = null) {
|
|
||||||
if (position == selectedItem) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val previouslySelectedItem = selectedItem
|
|
||||||
selectedItem = position
|
|
||||||
if (currentList.indices.contains(selectedItem)) {
|
|
||||||
currentList[selectedItem].onSelectionStateChanged(true)
|
|
||||||
}
|
|
||||||
if (currentList.indices.contains(previouslySelectedItem)) {
|
|
||||||
currentList[previouslySelectedItem].onSelectionStateChanged(false)
|
|
||||||
}
|
|
||||||
onItemChanged(previouslySelectedItem)
|
|
||||||
onItemChanged(selectedItem)
|
|
||||||
callback?.invoke(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a given item from the list and notifies the underlying adapter of the change. If the
|
|
||||||
* currently selected item was the item that was removed, the item at the position provided
|
|
||||||
* by [defaultSelection] will be made the new selection. Invokes [callback] last.
|
|
||||||
* @param position Index of the item that was removed
|
|
||||||
* @param callback Lambda that's called at the end of the list changes and has the removed and
|
|
||||||
* selected list positions passed in as parameters
|
|
||||||
*/
|
|
||||||
fun removeSelectableItem(
|
|
||||||
position: Int,
|
|
||||||
callback: ((removedPosition: Int, selectedPosition: Int) -> Unit)?
|
|
||||||
) {
|
|
||||||
removeItem(position)
|
|
||||||
if (position == selectedItem) {
|
|
||||||
selectedItem = getDefaultSelection()
|
|
||||||
currentList[selectedItem].onSelectionStateChanged(true)
|
|
||||||
onItemChanged(selectedItem)
|
|
||||||
} else if (position < selectedItem) {
|
|
||||||
selectedItem--
|
|
||||||
}
|
|
||||||
callback?.invoke(position, selectedItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addItem(item: Model, position: Int, callback: ((Int) -> Unit)?) {
|
|
||||||
super.addItem(item, position, callback)
|
|
||||||
if (position <= selectedItem && position != -1) {
|
|
||||||
selectedItem++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun replaceList(newList: List<Model>) {
|
|
||||||
super.replaceList(newList)
|
|
||||||
findSelectedItem()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findSelectedItem() {
|
|
||||||
for (i in currentList.indices) {
|
|
||||||
if (currentList[i].selected) {
|
|
||||||
selectedItem = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getDefaultSelection(): Int =
|
|
||||||
when (defaultSelection) {
|
|
||||||
DefaultSelection.Start -> currentList.indices.first
|
|
||||||
DefaultSelection.End -> currentList.indices.last
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class DefaultSelection { Start, End }
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.adapters
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding
|
|
||||||
import org.yuzu.yuzu_emu.model.Patch
|
|
||||||
import org.yuzu.yuzu_emu.model.AddonViewModel
|
|
||||||
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
|
|
||||||
|
|
||||||
class AddonAdapter(val addonViewModel: AddonViewModel) :
|
|
||||||
AbstractDiffAdapter<Patch, AddonAdapter.AddonViewHolder>() {
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder {
|
|
||||||
ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
|
||||||
.also { return AddonViewHolder(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class AddonViewHolder(val binding: ListItemAddonBinding) :
|
|
||||||
AbstractViewHolder<Patch>(binding) {
|
|
||||||
override fun bind(model: Patch) {
|
|
||||||
binding.root.setOnClickListener {
|
|
||||||
binding.addonCheckbox.isChecked = !binding.addonCheckbox.isChecked
|
|
||||||
}
|
|
||||||
binding.title.text = model.name
|
|
||||||
binding.version.text = model.version
|
|
||||||
binding.addonCheckbox.setOnCheckedChangeListener { _, checked ->
|
|
||||||
model.enabled = checked
|
|
||||||
}
|
|
||||||
binding.addonCheckbox.isChecked = model.enabled
|
|
||||||
binding.buttonDelete.setOnClickListener {
|
|
||||||
addonViewModel.setAddonToDelete(model)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue