Compare commits
365 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 023b9b38cc | |||
| 85e3575496 | |||
| 7f55c377b0 | |||
| 9893a4d918 | |||
| bed2fc8707 | |||
| 8d2f0dc707 | |||
| cb0b8442f0 | |||
| 089e385944 | |||
| 0d470b57ed | |||
| 755f45a522 | |||
| 4533769f7f | |||
| 00d9a9c44e | |||
| 35bdd5fff3 | |||
| 7707768f80 | |||
| ae19eb1e10 | |||
| a09507f271 | |||
| dfb7fc8293 | |||
| 369fcadf08 | |||
| 4bd4a95d84 | |||
| cd80cbc420 | |||
| c7c44dc238 | |||
| dd1cbd9c56 | |||
| 096644c01c | |||
| fca7d975fd | |||
| 32b4d63a5b | |||
| 09e265c116 | |||
| 36aca262e3 | |||
| d6d43e11a3 | |||
| 9d6f8e88b2 | |||
| 2754f6c883 | |||
| ef5618e486 | |||
| 9bca45aa15 | |||
| 2a9eab5e1b | |||
| 083fb8a15f | |||
| 06fa13a014 | |||
| 1ed6e3e51d | |||
| e2623d64de | |||
| 0f37756a3a | |||
| ed3f9bab11 | |||
| deafa92122 | |||
| c6458970ad | |||
| eaf2ab5289 | |||
| 7aa848080d | |||
| 55c0b55d1d | |||
| a4a106bb25 | |||
| f4e5d07619 | |||
| 70f37be9b9 | |||
| 36d48cef50 | |||
| d90c622549 | |||
| 05c8063ac1 | |||
| 689dc4a17b | |||
| 9352a0f2e6 | |||
| b1730d3c72 | |||
| bb4e676155 | |||
| 8c2411da29 | |||
| 4007142b91 | |||
| a1c355051e | |||
| d3da1e6517 | |||
| 6ffcc3d5d2 | |||
| 01b379fe20 | |||
| 195403c87c | |||
| 1bc0b673aa | |||
| 397333b2d5 | |||
| 4742627744 | |||
| 43920aa1a0 | |||
| e2ea46f6ef | |||
| 07f71e2620 | |||
| b1716a9e14 | |||
| 18000df5e9 | |||
| bb0edb53ae | |||
| 099295d7c6 | |||
| a0ed0e4e10 | |||
| ab2921121e | |||
| f84e7b4656 | |||
| dad0d076ee | |||
| 3e3294e1c2 | |||
| fc1bb93b01 | |||
| fb7da1fa11 | |||
| 9f3f615e05 | |||
| d144168442 | |||
| 3e4029b238 | |||
| b1aed2c5b7 | |||
| 0ea138fb5b | |||
| 85ed10f31f | |||
| 482c957f5d | |||
| 39edd2ff82 | |||
| 33d118509a | |||
| 1d4f813c6a | |||
| 17b9c1e171 | |||
| 05bc024260 | |||
| 4bee333d84 | |||
| c067046387 | |||
| efda6cc9ec | |||
| 8927f016e1 | |||
| 2911988b85 | |||
| ffb384463f | |||
| b54c3fba68 | |||
| b55a763618 | |||
| 8e91554e11 | |||
| 3211623192 | |||
| b02e7eea78 | |||
| 1e093767a8 | |||
| 267f3c7905 | |||
| 35872ad95b | |||
| 127b3da0f1 | |||
| ff6a5031d5 | |||
| 07e8477f5a | |||
| ef6406a666 | |||
| a14d2a6f83 | |||
| c1717b3f47 | |||
| ca8509d205 | |||
| e7f01128f1 | |||
| ecc1feff64 | |||
| 52cc7b438b | |||
| 9186f08c3c | |||
| 8497fb0a04 | |||
| 54d58130a0 | |||
| 926f3e3d3e | |||
| 9de50d6194 | |||
| 7f708e8d77 | |||
| d1de1c3bed | |||
| 21723879e7 | |||
| b2438f1fb7 | |||
| ad645c29a4 | |||
| 62ffaa730f | |||
| 8b28aa45b9 | |||
| 8366736b67 | |||
| 7ffbffe170 | |||
| 02c48a80f6 | |||
| fdbeb84168 | |||
| 81a96bafe2 | |||
| 3a7705e774 | |||
| 69bc8ea148 | |||
| 3f0cc544cf | |||
| c97cbd089b | |||
| 246740f102 | |||
| 89f89cf1df | |||
| ab795fe0e2 | |||
| ee32b17782 | |||
| 916c6cd1a0 | |||
| 57a00e01d6 | |||
| a7ee9d999f | |||
| 6935332cba | |||
| 3240d199a2 | |||
| a0883526d6 | |||
| 7c52bb2772 | |||
| 27e53990ed | |||
| b4f2ad3ff5 | |||
| 3b0650b70d | |||
| 512fb3abff | |||
| 11e7e1b8ce | |||
| 4903f40efe | |||
| 04d4b6ab80 | |||
| 02265f19d9 | |||
| 7515c502c5 | |||
| 79024bb955 | |||
| c5f8b909ec | |||
| 0193add060 | |||
| 2fba913d0b | |||
| fe6e765b2d | |||
| 47d870b11f | |||
| b86171d2b5 | |||
| 81e9cf0934 | |||
| 163f229d26 | |||
| 681ebcf4a5 | |||
| 78b2709373 | |||
| 8c17a945f7 | |||
| d146dd9d12 | |||
| 9e3c94bb3d | |||
| f7948b7b64 | |||
| 25cea2ef27 | |||
| 9a2a92673c | |||
| d7dd023409 | |||
| d373cc3d3f | |||
| e6d65bf61c | |||
| cd1d8adc49 | |||
| 09f61656e3 | |||
| 81860b4317 | |||
| b570b719de | |||
| 3d932416e3 | |||
| 7734127f9e | |||
| 3281ea935f | |||
| 217fa04080 | |||
| 3337250746 | |||
| daa31121ee | |||
| c5a3642cb6 | |||
| 86ed82cdde | |||
| 432f68ad29 | |||
| 88d3de4e85 | |||
| f055f2dcf4 | |||
| 4ff8255e4a | |||
| 4c4bc134a9 | |||
| 8e15146026 | |||
| 56960bf9f8 | |||
| b11a2a206f | |||
| cdb5dea269 | |||
| df2bd251fa | |||
| 97674bc888 | |||
| def00e8c55 | |||
| 23f874ae60 | |||
| c1748b229a | |||
| 8c03ae793e | |||
| e2de48f14b | |||
| 827082c5ac | |||
| c530532de7 | |||
| d3d9c3568e | |||
| 464aad52cd | |||
| ea4afbfc54 | |||
| 640e7db60e | |||
| f66d617107 | |||
| d35577d3ed | |||
| 39a1ffbb91 | |||
| d72ff01726 | |||
| 9a844bbf0c | |||
| 3a7a5edcea | |||
| 05c26411a3 | |||
| a4de202cbd | |||
| cfb63c68db | |||
| bafd569b47 | |||
| f8435d676f | |||
| 75d7e40113 | |||
| 4a825268d6 | |||
| 4f545e3024 | |||
| a007ac6b9c | |||
| b11b4be7cb | |||
| d3b94d64d4 | |||
| e5b981e1e4 | |||
| 60773194a0 | |||
| e7543e8b84 | |||
| 4133165607 | |||
| 5ccfaf0517 | |||
| 5cffa34288 | |||
| c0202da9ac | |||
| 7fc5ef68d2 | |||
| 014ca709c9 | |||
| 86bbfe3b1d | |||
| 1ab3bd5a5e | |||
| c1e57ad358 | |||
| 4ecedc4991 | |||
| 71b3b2a2f0 | |||
| 80cd67ed7b | |||
| 3fded314f2 | |||
| 8f1d48fda6 | |||
| 16c238e4b9 | |||
| e0fb1d3d17 | |||
| 5bbc3aef13 | |||
| 54f150b70a | |||
| 5593bed08a | |||
| 8750564bd2 | |||
| 2461c78e3f | |||
| 50fe45f1e4 | |||
| 4347dd26c6 | |||
| d7c532d889 | |||
| 474db2d8da | |||
| a85ce8ea56 | |||
| 04868ab9da | |||
| 63a0a1f826 | |||
| 9e0d6f7d54 | |||
| 13755c0903 | |||
| c3050c1b48 | |||
| 28598c9090 | |||
| 11cb4d88f0 | |||
| 4b870b28e8 | |||
| ce7c418e0c | |||
| 169b198d08 | |||
| 833306bf5e | |||
| 90d76333da | |||
| e32ce6cc69 | |||
| 190748546d | |||
| 79e289404b | |||
| a6e467cd55 | |||
| 8a87a41f2d | |||
| f02226283e | |||
| 82568412f6 | |||
| 1255196731 | |||
| 9ce5d39829 | |||
| 4540bcfaf7 | |||
| f80edad109 | |||
| aa882cdaa8 | |||
| 738b37e508 | |||
| 82a105e2f8 | |||
| d6a9ed32e6 | |||
| e3937fe8ad | |||
| c652e42492 | |||
| eacec2ae12 | |||
| b417b8562e | |||
| 45ea712d39 | |||
| f463ef7dae | |||
| 95c5b715b1 | |||
| 8bf46f48f8 | |||
| 9d7671ec3b | |||
| 5d0a051abb | |||
| 4c84bce171 | |||
| 302a735135 | |||
| d8eb37fbec | |||
| ef7d44e243 | |||
| f71140fbd9 | |||
| 0792139a5f | |||
| f1cfd9c219 | |||
| 4467fd9993 | |||
| 1462db4694 | |||
| 44af2e32a4 | |||
| 3c88547c74 | |||
| 1fe003113e | |||
| cef7aaa8ec | |||
| 005f0eb083 | |||
| b41006004b | |||
| 408a9cd50d | |||
| d2b62ae401 | |||
| 9cd698e8ad | |||
| 68f6f2671b | |||
| 6f7cb69c94 | |||
| 95ceae40e6 | |||
| 5e3695ecaa | |||
| daaf03942f | |||
| c3fbc8d2fe | |||
| 657ab0287d | |||
| eaa62aee98 | |||
| 87080e71c5 | |||
| b7c7768e0a | |||
| 644c3ce609 | |||
| ad1946b893 | |||
| 34c448bad4 | |||
| 146769f44e | |||
| ae7e9b5469 | |||
| 971b89b979 | |||
| 7f5ccd0151 | |||
| 595d55d485 | |||
| 0ed1cb7266 | |||
| 0e191c2711 | |||
| 98685d48e3 | |||
| aa89ec9214 | |||
| b94e576653 | |||
| 272916eeaf | |||
| 95cefaf993 | |||
| e146a00345 | |||
| 1a46823ec5 | |||
| 5a09fa5012 | |||
| 310b6cf4af | |||
| da8df6488d | |||
| 14ea16e499 | |||
| 22263787e3 | |||
| ff6d35f2c7 | |||
| fbd85417ff | |||
| b8c906f9d1 | |||
| 11991fbd7f | |||
| ea8d5ef5e8 | |||
| ddcd89afd4 | |||
| dfa040502a | |||
| 0e6b559c98 | |||
| 3f407417c1 | |||
| a1dd5dfba5 | |||
| da440da9f5 | |||
| 47d0d292d5 | |||
| edd54abee4 | |||
| d885dd5b64 | |||
| b9f9d0a642 | |||
| 8b9c077826 | |||
| cd4b8f037c | |||
| ac939f08a4 | |||
| 42015de49b | |||
| 4a35569921 | |||
| 8905142f43 | |||
| 7cc428ddf6 | |||
| 8e703e08df |
@@ -35,7 +35,7 @@ DESTDIR="$PWD/AppDir" ninja install
|
||||
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester
|
||||
|
||||
# Download tools needed to build an AppImage
|
||||
wget -nc https://raw.githubusercontent.com/yuzu-emu/ext-linux-bin/main/gcc/deploy-linux.sh
|
||||
wget -nc https://raw.githubusercontent.com/yuzu-emu/ext-linux-bin/main/appimage/deploy-linux.sh
|
||||
wget -nc https://raw.githubusercontent.com/yuzu-emu/AppImageKit-checkrt/old/AppRun.sh
|
||||
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so
|
||||
# Set executable bit
|
||||
|
||||
@@ -56,7 +56,6 @@ for i in package/*.exe; do
|
||||
x86_64-w64-mingw32-strip "${i}"
|
||||
done
|
||||
|
||||
pip3 install pefile
|
||||
python3 .ci/scripts/windows/scan_dll.py package/*.exe package/imageformats/*.dll "package/"
|
||||
|
||||
# copy FFmpeg libraries
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$VulkanSDKVer = "1.3.250.1"
|
||||
$ExeFile = "VulkanSDK-$VulkanSDKVer-Installer.exe"
|
||||
$Uri = "https://sdk.lunarg.com/sdk/download/$VulkanSDKVer/windows/$ExeFile"
|
||||
$Destination = "./$ExeFile"
|
||||
|
||||
echo "Downloading Vulkan SDK $VulkanSDKVer from $Uri"
|
||||
$WebClient = New-Object System.Net.WebClient
|
||||
$WebClient.DownloadFile($Uri, $Destination)
|
||||
echo "Finished downloading $ExeFile"
|
||||
|
||||
$VULKAN_SDK = "C:/VulkanSDK/$VulkanSDKVer"
|
||||
$Arguments = "--root `"$VULKAN_SDK`" --accept-licenses --default-answer --confirm-command install"
|
||||
|
||||
echo "Installing Vulkan SDK $VulkanSDKVer"
|
||||
$InstallProcess = Start-Process -FilePath $Destination -NoNewWindow -PassThru -Wait -ArgumentList $Arguments
|
||||
$ExitCode = $InstallProcess.ExitCode
|
||||
|
||||
if ($ExitCode -ne 0) {
|
||||
echo "Error installing Vulkan SDK $VulkanSDKVer (Error: $ExitCode)"
|
||||
Exit $ExitCode
|
||||
}
|
||||
|
||||
echo "Finished installing Vulkan SDK $VulkanSDKVer"
|
||||
|
||||
if ("$env:GITHUB_ACTIONS" -eq "true") {
|
||||
echo "VULKAN_SDK=$VULKAN_SDK" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
echo "$VULKAN_SDK/Bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
}
|
||||
@@ -7,9 +7,12 @@ parameters:
|
||||
version: ''
|
||||
|
||||
steps:
|
||||
- script: choco install vulkan-sdk
|
||||
displayName: 'Install vulkan-sdk'
|
||||
- script: refreshenv && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw /GA /Gr /Ob2" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DYUZU_ENABLE_LTO=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
|
||||
- task: Powershell@2
|
||||
displayName: 'Install Vulkan SDK'
|
||||
inputs:
|
||||
targetType: 'filePath'
|
||||
filePath: './.ci/scripts/windows/install-vulkan-sdk.ps1'
|
||||
- script: refreshenv && glslangValidator --version && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DYUZU_ENABLE_LTO=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
|
||||
displayName: 'Configure CMake'
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build'
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@
|
||||
|
||||
[codespell]
|
||||
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
|
||||
ignore-words-list = aci,allright,ba,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,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
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
name: 'yuzu-android-build'
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [ "*" ]
|
||||
|
||||
jobs:
|
||||
android:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'yuzu-emu/yuzu-android' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Set up cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
~/.ccache
|
||||
key: ${{ runner.os }}-android-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-android-
|
||||
- name: Query tag name
|
||||
uses: olegtarasov/get-tag@v2.1.2
|
||||
id: tagName
|
||||
- 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/build.sh
|
||||
- name: Copy and sign artifacts
|
||||
env:
|
||||
ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
|
||||
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||
ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
|
||||
run: ./.ci/scripts/android/upload.sh
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: android
|
||||
path: artifacts/
|
||||
# release steps
|
||||
release-android:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [android]
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
- name: Query tag name
|
||||
uses: olegtarasov/get-tag@v2.1.2
|
||||
id: tagName
|
||||
- name: Create release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ steps.tagName.outputs.tag }}
|
||||
release_name: ${{ steps.tagName.outputs.tag }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
- name: Upload artifacts
|
||||
uses: alexellis/upload-assets@0.2.3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
asset_paths: '["./**/*.apk","./**/*.aab"]'
|
||||
@@ -0,0 +1,218 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// Note: This is a GitHub Actions script
|
||||
// It is not meant to be executed directly on your machine without modifications
|
||||
|
||||
const fs = require("fs");
|
||||
// which label to check for changes
|
||||
const CHANGE_LABEL = 'android-merge';
|
||||
// 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);
|
||||
|
||||
async function checkBaseChanges(github, context) {
|
||||
// query the commit date of the latest commit on this branch
|
||||
const query = `query($owner:String!, $name:String!, $ref:String!) {
|
||||
repository(name:$name, owner:$owner) {
|
||||
ref(qualifiedName:$ref) {
|
||||
target {
|
||||
... on Commit { id pushedDate oid }
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
const variables = {
|
||||
owner: context.repo.owner,
|
||||
name: context.repo.repo,
|
||||
ref: 'refs/heads/master',
|
||||
};
|
||||
const result = await github.graphql(query, variables);
|
||||
const pushedAt = result.repository.ref.target.pushedDate;
|
||||
console.log(`Last commit pushed at ${pushedAt}.`);
|
||||
const delta = new Date() - new Date(pushedAt);
|
||||
if (delta <= DETECTION_TIME_FRAME) {
|
||||
console.info('New changes detected, triggering a new build.');
|
||||
return true;
|
||||
}
|
||||
console.info('No new changes detected.');
|
||||
return false;
|
||||
}
|
||||
|
||||
async function checkAndroidChanges(github, context) {
|
||||
if (checkBaseChanges(github, context)) return true;
|
||||
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++) {
|
||||
let pull = pulls[i];
|
||||
if (new Date() - new Date(pull.headRepository.pushedAt) <= DETECTION_TIME_FRAME) {
|
||||
console.info(`${pull.number} updated at ${pull.headRepository.pushedAt}`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
console.info("No changes detected in any tagged pull requests.");
|
||||
return false;
|
||||
}
|
||||
|
||||
async function tagAndPush(github, owner, repo, execa, commit=false) {
|
||||
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;
|
||||
const lastTag = tagList[0] ? tagList[0].name : 'dummy-0';
|
||||
const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
|
||||
const channel = repo.split('-')[1];
|
||||
const newTag = `${channel}-${tagNumber + 1}`;
|
||||
console.log(`New tag: ${newTag}`);
|
||||
if (commit) {
|
||||
let channelName = channel[0].toUpperCase() + channel.slice(1);
|
||||
console.info(`Committing pending commit as ${channelName} #${tagNumber + 1}`);
|
||||
await execa("git", ['commit', '-m', `${channelName} #${tagNumber + 1}`]);
|
||||
}
|
||||
console.info('Pushing tags to GitHub ...');
|
||||
await execa("git", ['tag', newTag]);
|
||||
await execa("git", ['remote', 'add', 'target', `https://${altToken}@github.com/${owner}/${repo}.git`]);
|
||||
await execa("git", ['push', 'target', 'master', '-f']);
|
||||
await execa("git", ['push', 'target', 'master', '--tags']);
|
||||
console.info('Successfully pushed new changes.');
|
||||
}
|
||||
|
||||
async function generateReadme(pulls, context, mergeResults, execa) {
|
||||
let baseUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/`;
|
||||
let output =
|
||||
"| Pull Request | Commit | Title | Author | Merged? |\n|----|----|----|----|----|\n";
|
||||
for (let pull of pulls) {
|
||||
let pr = pull.number;
|
||||
let result = mergeResults[pr];
|
||||
output += `| [${pr}](${baseUrl}/pull/${pr}) | [\`${result.rev || "N/A"}\`](${baseUrl}/pull/${pr}/files) | ${pull.title} | [${pull.author.login}](https://github.com/${pull.author.login}/) | ${result.success ? "Yes" : "No"} |\n`;
|
||||
}
|
||||
output +=
|
||||
"\n\nEnd of merge log. You can find the original README.md below the break.\n\n-----\n\n";
|
||||
output += fs.readFileSync("./README.md");
|
||||
fs.writeFileSync("./README.md", output);
|
||||
await execa("git", ["add", "README.md"]);
|
||||
}
|
||||
|
||||
async function fetchPullRequests(pulls, repoUrl, execa) {
|
||||
console.log("::group::Fetch pull requests");
|
||||
for (let pull of pulls) {
|
||||
let pr = pull.number;
|
||||
console.info(`Fetching PR ${pr} ...`);
|
||||
await execa("git", [
|
||||
"fetch",
|
||||
"-f",
|
||||
"--no-recurse-submodules",
|
||||
repoUrl,
|
||||
`pull/${pr}/head:pr-${pr}`,
|
||||
]);
|
||||
}
|
||||
console.log("::endgroup::");
|
||||
}
|
||||
|
||||
async function mergePullRequests(pulls, execa) {
|
||||
let mergeResults = {};
|
||||
console.log("::group::Merge pull requests");
|
||||
await execa("git", ["config", "--global", "user.name", "yuzubot"]);
|
||||
await execa("git", [
|
||||
"config",
|
||||
"--global",
|
||||
"user.email",
|
||||
"yuzu\x40yuzu-emu\x2eorg", // prevent email harvesters from scraping the address
|
||||
]);
|
||||
let hasFailed = false;
|
||||
for (let pull of pulls) {
|
||||
let pr = pull.number;
|
||||
console.info(`Merging PR ${pr} ...`);
|
||||
try {
|
||||
const process1 = execa("git", [
|
||||
"merge",
|
||||
"--squash",
|
||||
"--no-edit",
|
||||
`pr-${pr}`,
|
||||
]);
|
||||
process1.stdout.pipe(process.stdout);
|
||||
await process1;
|
||||
|
||||
const process2 = execa("git", ["commit", "-m", `Merge PR ${pr}`]);
|
||||
process2.stdout.pipe(process.stdout);
|
||||
await process2;
|
||||
|
||||
const process3 = await execa("git", ["rev-parse", "--short", `pr-${pr}`]);
|
||||
mergeResults[pr] = {
|
||||
success: true,
|
||||
rev: process3.stdout,
|
||||
};
|
||||
} catch (err) {
|
||||
console.log(
|
||||
`::error title=#${pr} not merged::Failed to merge pull request: ${pr}: ${err}`
|
||||
);
|
||||
mergeResults[pr] = { success: false };
|
||||
hasFailed = true;
|
||||
await execa("git", ["reset", "--hard"]);
|
||||
}
|
||||
}
|
||||
console.log("::endgroup::");
|
||||
if (hasFailed) {
|
||||
throw 'There are merge failures. Aborting!';
|
||||
}
|
||||
return mergeResults;
|
||||
}
|
||||
|
||||
async function mergebot(github, context, execa) {
|
||||
const query = `query ($owner:String!, $name:String!, $label:String!) {
|
||||
repository(name:$name, owner:$owner) {
|
||||
pullRequests(labels: [$label], states: OPEN, first: 100) {
|
||||
nodes {
|
||||
number title author { login }
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
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;
|
||||
let displayList = [];
|
||||
for (let i = 0; i < pulls.length; i++) {
|
||||
let pull = pulls[i];
|
||||
displayList.push({ PR: pull.number, Title: pull.title });
|
||||
}
|
||||
console.info("The following pull requests will be merged:");
|
||||
console.table(displayList);
|
||||
await fetchPullRequests(pulls, "https://github.com/yuzu-emu/yuzu", execa);
|
||||
const mergeResults = await mergePullRequests(pulls, execa);
|
||||
await generateReadme(pulls, context, mergeResults, execa);
|
||||
await tagAndPush(github, context.repo.owner, `${context.repo.repo}-android`, execa, true);
|
||||
}
|
||||
|
||||
module.exports.mergebot = mergebot;
|
||||
module.exports.checkAndroidChanges = checkAndroidChanges;
|
||||
module.exports.tagAndPush = tagAndPush;
|
||||
module.exports.checkBaseChanges = checkBaseChanges;
|
||||
@@ -0,0 +1,57 @@
|
||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
name: yuzu-android-publish
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '37 0 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
android:
|
||||
description: 'Whether to trigger an Android build (true/false/auto)'
|
||||
required: false
|
||||
default: 'true'
|
||||
|
||||
jobs:
|
||||
android:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.inputs.android != 'false' && github.repository == 'yuzu-emu/yuzu' }}
|
||||
steps:
|
||||
# this checkout is required to make sure the GitHub Actions scripts are available
|
||||
- uses: actions/checkout@v3
|
||||
name: Pre-checkout
|
||||
with:
|
||||
submodules: false
|
||||
- uses: actions/github-script@v6
|
||||
id: check-changes
|
||||
name: 'Check for new changes'
|
||||
env:
|
||||
# 24 hours
|
||||
DETECTION_TIME_FRAME: 86400000
|
||||
with:
|
||||
script: |
|
||||
if (context.payload.inputs && context.payload.inputs.android === 'true') return true;
|
||||
const checkAndroidChanges = require('./.github/workflows/android-merge.js').checkAndroidChanges;
|
||||
return checkAndroidChanges(github, context);
|
||||
- run: npm install execa@5
|
||||
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
||||
- uses: actions/checkout@v3
|
||||
name: Checkout
|
||||
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
||||
with:
|
||||
path: 'yuzu-merge'
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
token: ${{ secrets.ALT_GITHUB_TOKEN }}
|
||||
- uses: actions/github-script@v5
|
||||
name: 'Check and merge Android changes'
|
||||
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
||||
env:
|
||||
ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }}
|
||||
with:
|
||||
script: |
|
||||
const execa = require("execa");
|
||||
const mergebot = require('./.github/workflows/android-merge.js').mergebot;
|
||||
process.chdir('${{ github.workspace }}/yuzu-merge');
|
||||
mergebot(github, context, execa);
|
||||
@@ -73,6 +73,10 @@ jobs:
|
||||
needs: format
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- name: Set up cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
@@ -81,22 +85,22 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-msvc-
|
||||
- name: Install dependencies
|
||||
# due to how chocolatey works, only cmd.exe is supported here
|
||||
shell: cmd
|
||||
shell: pwsh
|
||||
run: |
|
||||
choco install vulkan-sdk wget
|
||||
call refreshenv
|
||||
wget https://github.com/mbitsnbites/buildcache/releases/download/v0.27.6/buildcache-windows.zip
|
||||
7z x buildcache-windows.zip
|
||||
copy buildcache\bin\buildcache.exe C:\ProgramData\chocolatey\bin
|
||||
rmdir buildcache
|
||||
echo %PATH% >> %GITHUB_PATH%
|
||||
$ErrorActionPreference = "Stop"
|
||||
$BuildCacheVer = "v0.28.4"
|
||||
$File = "buildcache-windows.zip"
|
||||
$Uri = "https://github.com/mbitsnbites/buildcache/releases/download/$BuildCacheVer/$File"
|
||||
$WebClient = New-Object System.Net.WebClient
|
||||
$WebClient.DownloadFile($Uri, $File)
|
||||
7z x $File
|
||||
$CurrentDir = Convert-Path .
|
||||
echo "$CurrentDir/buildcache/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
- name: Install Vulkan SDK
|
||||
shell: pwsh
|
||||
run: .\.ci\scripts\windows\install-vulkan-sdk.ps1
|
||||
- name: Set up MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- name: Configure
|
||||
env:
|
||||
CC: cl.exe
|
||||
@@ -129,11 +133,12 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
distribution: 'temurin'
|
||||
- name: Set up cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
@@ -151,7 +156,6 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
||||
git -C ./externals/vcpkg/ fetch --all --unshallow
|
||||
- name: Build
|
||||
run: ./.ci/scripts/android/build.sh
|
||||
- name: Copy and sign artifacts
|
||||
|
||||
+1
-1
@@ -56,5 +56,5 @@
|
||||
path = externals/nx_tzdb/tzdb_to_nx
|
||||
url = https://github.com/lat9nq/tzdb_to_nx.git
|
||||
[submodule "VulkanMemoryAllocator"]
|
||||
path = externals/vma/VulkanMemoryAllocator
|
||||
path = externals/VulkanMemoryAllocator
|
||||
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||
|
||||
+36
-3
@@ -63,6 +63,18 @@ option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" OFF)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
|
||||
|
||||
set(DEFAULT_ENABLE_OPENSSL ON)
|
||||
if (ANDROID OR WIN32 OR APPLE)
|
||||
# - Windows defaults to the Schannel backend.
|
||||
# - macOS defaults to the SecureTransport backend.
|
||||
# - Android currently has no SSL backend as the NDK doesn't include any SSL
|
||||
# library; a proper 'native' backend would have to go through Java.
|
||||
# But you can force builds for those platforms to use OpenSSL if you have
|
||||
# your own copy of it.
|
||||
set(DEFAULT_ENABLE_OPENSSL OFF)
|
||||
endif()
|
||||
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
||||
|
||||
# On Android, fetch and compile libcxx before doing anything else
|
||||
if (ANDROID)
|
||||
set(CMAKE_SKIP_INSTALL_RULES ON)
|
||||
@@ -124,6 +136,22 @@ if (YUZU_USE_BUNDLED_VCPKG)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
set(VCPKG_DOWNLOADS_PATH ${PROJECT_SOURCE_DIR}/externals/vcpkg/downloads)
|
||||
set(NASM_VERSION "2.16.01")
|
||||
set(NASM_DESTINATION_PATH ${VCPKG_DOWNLOADS_PATH}/nasm-${NASM_VERSION}-win64.zip)
|
||||
set(NASM_DOWNLOAD_URL "https://github.com/yuzu-emu/ext-windows-bin/raw/master/nasm/nasm-${NASM_VERSION}-win64.zip")
|
||||
|
||||
if (NOT EXISTS ${NASM_DESTINATION_PATH})
|
||||
file(DOWNLOAD ${NASM_DOWNLOAD_URL} ${NASM_DESTINATION_PATH} SHOW_PROGRESS STATUS NASM_STATUS)
|
||||
|
||||
if (NOT NASM_STATUS EQUAL 0)
|
||||
# Warn and not fail since vcpkg is supposed to download this package for us in the first place
|
||||
message(WARNING "External nasm vcpkg package download from ${NASM_DOWNLOAD_URL} failed with status ${NASM_STATUS}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (YUZU_TESTS)
|
||||
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
|
||||
endif()
|
||||
@@ -277,15 +305,16 @@ find_package(Boost 1.79.0 REQUIRED context)
|
||||
find_package(enet 1.3 MODULE)
|
||||
find_package(fmt 9 REQUIRED)
|
||||
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||
find_package(LLVM MODULE COMPONENTS Demangle)
|
||||
find_package(LLVM 17 MODULE COMPONENTS Demangle)
|
||||
find_package(lz4 REQUIRED)
|
||||
find_package(nlohmann_json 3.8 REQUIRED)
|
||||
find_package(Opus 1.3 MODULE)
|
||||
find_package(VulkanMemoryAllocator CONFIG)
|
||||
find_package(ZLIB 1.2 REQUIRED)
|
||||
find_package(zstd 1.5 REQUIRED)
|
||||
|
||||
if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
||||
find_package(Vulkan 1.3.246 REQUIRED)
|
||||
find_package(Vulkan 1.3.256 REQUIRED)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LIBUSB)
|
||||
@@ -322,6 +351,10 @@ if (MINGW)
|
||||
find_library(MSWSOCK_LIBRARY mswsock REQUIRED)
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENSSL)
|
||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||
endif()
|
||||
|
||||
# Please consider this as a stub
|
||||
if(ENABLE_QT6 AND Qt6_LOCATION)
|
||||
list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}")
|
||||
@@ -489,7 +522,7 @@ if (ENABLE_SDL2)
|
||||
if (YUZU_USE_BUNDLED_SDL2)
|
||||
# Detect toolchain and platform
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64)
|
||||
set(SDL2_VER "SDL2-2.28.0")
|
||||
set(SDL2_VER "SDL2-2.28.1")
|
||||
else()
|
||||
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.")
|
||||
endif()
|
||||
|
||||
@@ -40,7 +40,7 @@ It is written in C++ with portability in mind, and we actively maintain builds f
|
||||
|
||||
The emulator is capable of running most commercial games at full speed, provided you meet the [necessary hardware requirements](https://yuzu-emu.org/help/quickstart/#hardware-requirements).
|
||||
|
||||
For a full list of games yuzu support, please visit our [Compatibility page](https://yuzu-emu.org/game/)
|
||||
For a full list of games yuzu supports, please visit our [Compatibility page](https://yuzu-emu.org/game/).
|
||||
|
||||
Check out our [website](https://yuzu-emu.org/) for the latest news on exciting features, monthly progress reports, and more!
|
||||
|
||||
|
||||
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+264
-239
File diff suppressed because it is too large
Load Diff
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+251
-227
File diff suppressed because it is too large
Load Diff
Vendored
+250
-226
File diff suppressed because it is too large
Load Diff
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+422
-371
File diff suppressed because it is too large
Load Diff
Vendored
+277
-254
File diff suppressed because it is too large
Load Diff
Vendored
+265
-242
File diff suppressed because it is too large
Load Diff
Vendored
+250
-226
File diff suppressed because it is too large
Load Diff
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+308
-285
File diff suppressed because it is too large
Load Diff
Vendored
+249
-226
File diff suppressed because it is too large
Load Diff
Vendored
+273
-249
File diff suppressed because it is too large
Load Diff
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+251
-228
File diff suppressed because it is too large
Load Diff
Vendored
+248
-225
File diff suppressed because it is too large
Load Diff
Vendored
+1404
-1320
File diff suppressed because it is too large
Load Diff
Vendored
+1065
-982
File diff suppressed because it is too large
Load Diff
Vendored
+251
-227
File diff suppressed because it is too large
Load Diff
Vendored
+250
-226
File diff suppressed because it is too large
Load Diff
Vendored
+3
-3
@@ -144,9 +144,9 @@ endif()
|
||||
add_subdirectory(nx_tzdb)
|
||||
|
||||
# VMA
|
||||
add_library(vma vma/vma.cpp)
|
||||
target_include_directories(vma PUBLIC ./vma/VulkanMemoryAllocator/include)
|
||||
target_link_libraries(vma PRIVATE Vulkan::Headers)
|
||||
if (NOT TARGET GPUOpen::VulkanMemoryAllocator)
|
||||
add_subdirectory(VulkanMemoryAllocator)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET LLVM::Demangle)
|
||||
add_library(demangle demangle/ItaniumDemangle.cpp)
|
||||
|
||||
Vendored
+1
-1
Submodule externals/SDL updated: 491fba1d06...116a5344ff
Vendored
+1
-1
Submodule externals/Vulkan-Headers updated: 63af1cf1ee...ed857118e2
+1
Submodule externals/VulkanMemoryAllocator added at 9b0fc3e7b0
+90
-81
@@ -20,9 +20,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::itanium_demangle;
|
||||
@@ -81,8 +79,8 @@ struct DumpVisitor {
|
||||
}
|
||||
|
||||
void printStr(const char *S) { fprintf(stderr, "%s", S); }
|
||||
void print(StringView SV) {
|
||||
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin());
|
||||
void print(std::string_view SV) {
|
||||
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.data());
|
||||
}
|
||||
void print(const Node *N) {
|
||||
if (N)
|
||||
@@ -90,14 +88,6 @@ struct DumpVisitor {
|
||||
else
|
||||
printStr("<null>");
|
||||
}
|
||||
void print(NodeOrString NS) {
|
||||
if (NS.isNode())
|
||||
print(NS.asNode());
|
||||
else if (NS.isString())
|
||||
print(NS.asString());
|
||||
else
|
||||
printStr("NodeOrString()");
|
||||
}
|
||||
void print(NodeArray A) {
|
||||
++Depth;
|
||||
printStr("{");
|
||||
@@ -116,13 +106,11 @@ struct DumpVisitor {
|
||||
// Overload used when T is exactly 'bool', not merely convertible to 'bool'.
|
||||
void print(bool B) { printStr(B ? "true" : "false"); }
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<std::is_unsigned<T>::value>::type print(T N) {
|
||||
template <class T> std::enable_if_t<std::is_unsigned<T>::value> print(T N) {
|
||||
fprintf(stderr, "%llu", (unsigned long long)N);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<std::is_signed<T>::value>::type print(T N) {
|
||||
template <class T> std::enable_if_t<std::is_signed<T>::value> print(T N) {
|
||||
fprintf(stderr, "%lld", (long long)N);
|
||||
}
|
||||
|
||||
@@ -185,6 +173,50 @@ struct DumpVisitor {
|
||||
return printStr("TemplateParamKind::Template");
|
||||
}
|
||||
}
|
||||
void print(Node::Prec P) {
|
||||
switch (P) {
|
||||
case Node::Prec::Primary:
|
||||
return printStr("Node::Prec::Primary");
|
||||
case Node::Prec::Postfix:
|
||||
return printStr("Node::Prec::Postfix");
|
||||
case Node::Prec::Unary:
|
||||
return printStr("Node::Prec::Unary");
|
||||
case Node::Prec::Cast:
|
||||
return printStr("Node::Prec::Cast");
|
||||
case Node::Prec::PtrMem:
|
||||
return printStr("Node::Prec::PtrMem");
|
||||
case Node::Prec::Multiplicative:
|
||||
return printStr("Node::Prec::Multiplicative");
|
||||
case Node::Prec::Additive:
|
||||
return printStr("Node::Prec::Additive");
|
||||
case Node::Prec::Shift:
|
||||
return printStr("Node::Prec::Shift");
|
||||
case Node::Prec::Spaceship:
|
||||
return printStr("Node::Prec::Spaceship");
|
||||
case Node::Prec::Relational:
|
||||
return printStr("Node::Prec::Relational");
|
||||
case Node::Prec::Equality:
|
||||
return printStr("Node::Prec::Equality");
|
||||
case Node::Prec::And:
|
||||
return printStr("Node::Prec::And");
|
||||
case Node::Prec::Xor:
|
||||
return printStr("Node::Prec::Xor");
|
||||
case Node::Prec::Ior:
|
||||
return printStr("Node::Prec::Ior");
|
||||
case Node::Prec::AndIf:
|
||||
return printStr("Node::Prec::AndIf");
|
||||
case Node::Prec::OrIf:
|
||||
return printStr("Node::Prec::OrIf");
|
||||
case Node::Prec::Conditional:
|
||||
return printStr("Node::Prec::Conditional");
|
||||
case Node::Prec::Assign:
|
||||
return printStr("Node::Prec::Assign");
|
||||
case Node::Prec::Comma:
|
||||
return printStr("Node::Prec::Comma");
|
||||
case Node::Prec::Default:
|
||||
return printStr("Node::Prec::Default");
|
||||
}
|
||||
}
|
||||
|
||||
void newLine() {
|
||||
printStr("\n");
|
||||
@@ -334,36 +366,21 @@ public:
|
||||
|
||||
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
|
||||
|
||||
char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
|
||||
size_t *N, int *Status) {
|
||||
if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
|
||||
if (Status)
|
||||
*Status = demangle_invalid_args;
|
||||
char *llvm::itaniumDemangle(std::string_view MangledName) {
|
||||
if (MangledName.empty())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int InternalStatus = demangle_success;
|
||||
Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
|
||||
OutputStream S;
|
||||
|
||||
Demangler Parser(MangledName.data(),
|
||||
MangledName.data() + MangledName.length());
|
||||
Node *AST = Parser.parse();
|
||||
if (!AST)
|
||||
return nullptr;
|
||||
|
||||
if (AST == nullptr)
|
||||
InternalStatus = demangle_invalid_mangled_name;
|
||||
else if (!initializeOutputStream(Buf, N, S, 1024))
|
||||
InternalStatus = demangle_memory_alloc_failure;
|
||||
else {
|
||||
assert(Parser.ForwardTemplateRefs.empty());
|
||||
AST->print(S);
|
||||
S += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
Buf = S.getBuffer();
|
||||
}
|
||||
|
||||
if (Status)
|
||||
*Status = InternalStatus;
|
||||
return InternalStatus == demangle_success ? Buf : nullptr;
|
||||
OutputBuffer OB;
|
||||
assert(Parser.ForwardTemplateRefs.empty());
|
||||
AST->print(OB);
|
||||
OB += '\0';
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
ItaniumPartialDemangler::ItaniumPartialDemangler()
|
||||
@@ -396,14 +413,12 @@ bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
|
||||
}
|
||||
|
||||
static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
RootNode->print(S);
|
||||
S += '\0';
|
||||
OutputBuffer OB(Buf, N);
|
||||
RootNode->print(OB);
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||
@@ -417,8 +432,8 @@ char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||
case Node::KAbiTagAttr:
|
||||
Name = static_cast<const AbiTagAttr *>(Name)->Base;
|
||||
continue;
|
||||
case Node::KStdQualifiedName:
|
||||
Name = static_cast<const StdQualifiedName *>(Name)->Child;
|
||||
case Node::KModuleEntity:
|
||||
Name = static_cast<const ModuleEntity *>(Name)->Name;
|
||||
continue;
|
||||
case Node::KNestedName:
|
||||
Name = static_cast<const NestedName *>(Name)->Name;
|
||||
@@ -441,9 +456,7 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||
return nullptr;
|
||||
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
OutputBuffer OB(Buf, N);
|
||||
|
||||
KeepGoingLocalFunction:
|
||||
while (true) {
|
||||
@@ -458,27 +471,27 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||
break;
|
||||
}
|
||||
|
||||
if (Name->getKind() == Node::KModuleEntity)
|
||||
Name = static_cast<const ModuleEntity *>(Name)->Name;
|
||||
|
||||
switch (Name->getKind()) {
|
||||
case Node::KStdQualifiedName:
|
||||
S += "std";
|
||||
break;
|
||||
case Node::KNestedName:
|
||||
static_cast<const NestedName *>(Name)->Qual->print(S);
|
||||
static_cast<const NestedName *>(Name)->Qual->print(OB);
|
||||
break;
|
||||
case Node::KLocalName: {
|
||||
auto *LN = static_cast<const LocalName *>(Name);
|
||||
LN->Encoding->print(S);
|
||||
S += "::";
|
||||
LN->Encoding->print(OB);
|
||||
OB += "::";
|
||||
Name = LN->Entity;
|
||||
goto KeepGoingLocalFunction;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
S += '\0';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
|
||||
@@ -494,17 +507,15 @@ char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
|
||||
return nullptr;
|
||||
NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
OutputBuffer OB(Buf, N);
|
||||
|
||||
S += '(';
|
||||
Params.printWithComma(S);
|
||||
S += ')';
|
||||
S += '\0';
|
||||
OB += '(';
|
||||
Params.printWithComma(OB);
|
||||
OB += ')';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||
@@ -512,18 +523,16 @@ char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||
if (!isFunction())
|
||||
return nullptr;
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
OutputBuffer OB(Buf, N);
|
||||
|
||||
if (const Node *Ret =
|
||||
static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
|
||||
Ret->print(S);
|
||||
Ret->print(OB);
|
||||
|
||||
S += '\0';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
|
||||
@@ -563,8 +572,8 @@ bool ItaniumPartialDemangler::isCtorOrDtor() const {
|
||||
case Node::KNestedName:
|
||||
N = static_cast<const NestedName *>(N)->Name;
|
||||
break;
|
||||
case Node::KStdQualifiedName:
|
||||
N = static_cast<const StdQualifiedName *>(N)->Child;
|
||||
case Node::KModuleEntity:
|
||||
N = static_cast<const ModuleEntity *>(N)->Name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+32
-5
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace llvm {
|
||||
/// This is a llvm local version of __cxa_demangle. Other than the name and
|
||||
@@ -29,9 +30,10 @@ enum : int {
|
||||
demangle_success = 0,
|
||||
};
|
||||
|
||||
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
int *status);
|
||||
|
||||
/// Returns a non-NULL pointer to a NUL-terminated C style string
|
||||
/// that should be explicitly freed, if successful. Otherwise, may return
|
||||
/// nullptr if mangled_name is not a valid mangling or is nullptr.
|
||||
char *itaniumDemangle(std::string_view mangled_name);
|
||||
|
||||
enum MSDemangleFlags {
|
||||
MSDF_None = 0,
|
||||
@@ -40,10 +42,34 @@ enum MSDemangleFlags {
|
||||
MSDF_NoCallingConvention = 1 << 2,
|
||||
MSDF_NoReturnType = 1 << 3,
|
||||
MSDF_NoMemberType = 1 << 4,
|
||||
MSDF_NoVariableType = 1 << 5,
|
||||
};
|
||||
char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
|
||||
/// Demangles the Microsoft symbol pointed at by mangled_name and returns it.
|
||||
/// Returns a pointer to the start of a null-terminated demangled string on
|
||||
/// success, or nullptr on error.
|
||||
/// If n_read is non-null and demangling was successful, it receives how many
|
||||
/// bytes of the input string were consumed.
|
||||
/// status receives one of the demangle_ enum entries above if it's not nullptr.
|
||||
/// Flags controls various details of the demangled representation.
|
||||
char *microsoftDemangle(std::string_view mangled_name, size_t *n_read,
|
||||
int *status, MSDemangleFlags Flags = MSDF_None);
|
||||
|
||||
// Demangles a Rust v0 mangled symbol.
|
||||
char *rustDemangle(std::string_view MangledName);
|
||||
|
||||
// Demangles a D mangled symbol.
|
||||
char *dlangDemangle(std::string_view MangledName);
|
||||
|
||||
/// Attempt to demangle a string using different demangling schemes.
|
||||
/// The function uses heuristics to determine which demangling scheme to use.
|
||||
/// \param MangledName - reference to string to demangle.
|
||||
/// \returns - the demangled string, or a copy of the input string if no
|
||||
/// demangling occurred.
|
||||
std::string demangle(std::string_view MangledName);
|
||||
|
||||
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result);
|
||||
|
||||
/// "Partial" demangler. This supports demangling a string into an AST
|
||||
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
||||
/// properties or partially printing the demangled name.
|
||||
@@ -59,7 +85,7 @@ struct ItaniumPartialDemangler {
|
||||
bool partialDemangle(const char *MangledName);
|
||||
|
||||
/// Just print the entire mangled name into Buf. Buf and N behave like the
|
||||
/// second and third parameters to itaniumDemangle.
|
||||
/// second and third parameters to __cxa_demangle.
|
||||
char *finishDemangle(char *Buf, size_t *N) const;
|
||||
|
||||
/// Get the base name of a function. This doesn't include trailing template
|
||||
@@ -95,6 +121,7 @@ struct ItaniumPartialDemangler {
|
||||
bool isSpecialName() const;
|
||||
|
||||
~ItaniumPartialDemangler();
|
||||
|
||||
private:
|
||||
void *RootNode;
|
||||
void *Context;
|
||||
|
||||
+2
-2
@@ -13,8 +13,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEMANGLE_COMPILER_H
|
||||
#define LLVM_DEMANGLE_COMPILER_H
|
||||
#ifndef LLVM_DEMANGLE_DEMANGLECONFIG_H
|
||||
#define LLVM_DEMANGLE_DEMANGLECONFIG_H
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
|
||||
+1920
-1990
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
||||
//===--- ItaniumNodes.def ------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Define the demangler's node names
|
||||
|
||||
#ifndef NODE
|
||||
#error Define NODE to handle nodes
|
||||
#endif
|
||||
|
||||
NODE(NodeArrayNode)
|
||||
NODE(DotSuffix)
|
||||
NODE(VendorExtQualType)
|
||||
NODE(QualType)
|
||||
NODE(ConversionOperatorType)
|
||||
NODE(PostfixQualifiedType)
|
||||
NODE(ElaboratedTypeSpefType)
|
||||
NODE(NameType)
|
||||
NODE(AbiTagAttr)
|
||||
NODE(EnableIfAttr)
|
||||
NODE(ObjCProtoName)
|
||||
NODE(PointerType)
|
||||
NODE(ReferenceType)
|
||||
NODE(PointerToMemberType)
|
||||
NODE(ArrayType)
|
||||
NODE(FunctionType)
|
||||
NODE(NoexceptSpec)
|
||||
NODE(DynamicExceptionSpec)
|
||||
NODE(FunctionEncoding)
|
||||
NODE(LiteralOperator)
|
||||
NODE(SpecialName)
|
||||
NODE(CtorVtableSpecialName)
|
||||
NODE(QualifiedName)
|
||||
NODE(NestedName)
|
||||
NODE(LocalName)
|
||||
NODE(ModuleName)
|
||||
NODE(ModuleEntity)
|
||||
NODE(VectorType)
|
||||
NODE(PixelVectorType)
|
||||
NODE(BinaryFPType)
|
||||
NODE(BitIntType)
|
||||
NODE(SyntheticTemplateParamName)
|
||||
NODE(TypeTemplateParamDecl)
|
||||
NODE(NonTypeTemplateParamDecl)
|
||||
NODE(TemplateTemplateParamDecl)
|
||||
NODE(TemplateParamPackDecl)
|
||||
NODE(ParameterPack)
|
||||
NODE(TemplateArgumentPack)
|
||||
NODE(ParameterPackExpansion)
|
||||
NODE(TemplateArgs)
|
||||
NODE(ForwardTemplateReference)
|
||||
NODE(NameWithTemplateArgs)
|
||||
NODE(GlobalQualifiedName)
|
||||
NODE(ExpandedSpecialSubstitution)
|
||||
NODE(SpecialSubstitution)
|
||||
NODE(CtorDtorName)
|
||||
NODE(DtorName)
|
||||
NODE(UnnamedTypeName)
|
||||
NODE(ClosureTypeName)
|
||||
NODE(StructuredBindingName)
|
||||
NODE(BinaryExpr)
|
||||
NODE(ArraySubscriptExpr)
|
||||
NODE(PostfixExpr)
|
||||
NODE(ConditionalExpr)
|
||||
NODE(MemberExpr)
|
||||
NODE(SubobjectExpr)
|
||||
NODE(EnclosingExpr)
|
||||
NODE(CastExpr)
|
||||
NODE(SizeofParamPackExpr)
|
||||
NODE(CallExpr)
|
||||
NODE(NewExpr)
|
||||
NODE(DeleteExpr)
|
||||
NODE(PrefixExpr)
|
||||
NODE(FunctionParam)
|
||||
NODE(ConversionExpr)
|
||||
NODE(PointerToMemberConversionExpr)
|
||||
NODE(InitListExpr)
|
||||
NODE(FoldExpr)
|
||||
NODE(ThrowExpr)
|
||||
NODE(BoolExpr)
|
||||
NODE(StringLiteral)
|
||||
NODE(LambdaExpr)
|
||||
NODE(EnumLiteral)
|
||||
NODE(IntegerLiteral)
|
||||
NODE(FloatLiteral)
|
||||
NODE(DoubleLiteral)
|
||||
NODE(LongDoubleLiteral)
|
||||
NODE(BracedExpr)
|
||||
NODE(BracedRangeExpr)
|
||||
|
||||
#undef NODE
|
||||
+14
-18
@@ -1,5 +1,5 @@
|
||||
//===--- StringView.h -------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
//===--- StringView.h ----------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
@@ -8,6 +8,9 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// FIXME: Use std::string_view instead when we support C++17.
|
||||
// There are two copies of this file in the source tree. The one under
|
||||
// libcxxabi is the original and the one under llvm is the copy. Use
|
||||
// cp-to-llvm.sh to update the copy. See README.txt for more details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -15,7 +18,6 @@
|
||||
#define DEMANGLE_STRINGVIEW_H
|
||||
|
||||
#include "DemangleConfig.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
@@ -37,29 +39,23 @@ public:
|
||||
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
|
||||
StringView() : First(nullptr), Last(nullptr) {}
|
||||
|
||||
StringView substr(size_t From) const {
|
||||
return StringView(begin() + From, size() - From);
|
||||
StringView substr(size_t Pos, size_t Len = npos) const {
|
||||
assert(Pos <= size());
|
||||
if (Len > size() - Pos)
|
||||
Len = size() - Pos;
|
||||
return StringView(begin() + Pos, Len);
|
||||
}
|
||||
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
size_t FindBegin = std::min(From, size());
|
||||
// Avoid calling memchr with nullptr.
|
||||
if (FindBegin < size()) {
|
||||
if (From < size()) {
|
||||
// Just forward to memchr, which is faster than a hand-rolled loop.
|
||||
if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
|
||||
if (const void *P = ::memchr(First + From, C, size() - From))
|
||||
return size_t(static_cast<const char *>(P) - First);
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
StringView substr(size_t From, size_t To) const {
|
||||
if (To >= size())
|
||||
To = size() - 1;
|
||||
if (From >= size())
|
||||
From = size() - 1;
|
||||
return StringView(First + From, First + To);
|
||||
}
|
||||
|
||||
StringView dropFront(size_t N = 1) const {
|
||||
if (N >= size())
|
||||
N = size();
|
||||
@@ -106,7 +102,7 @@ public:
|
||||
bool startsWith(StringView Str) const {
|
||||
if (Str.size() > size())
|
||||
return false;
|
||||
return std::equal(Str.begin(), Str.end(), begin());
|
||||
return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
|
||||
}
|
||||
|
||||
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
|
||||
@@ -119,7 +115,7 @@ public:
|
||||
|
||||
inline bool operator==(const StringView &LHS, const StringView &RHS) {
|
||||
return LHS.size() == RHS.size() &&
|
||||
std::equal(LHS.begin(), LHS.end(), RHS.begin());
|
||||
std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//===--- StringViewExtras.h ----------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// There are two copies of this file in the source tree. The one under
|
||||
// libcxxabi is the original and the one under llvm is the copy. Use
|
||||
// cp-to-llvm.sh to update the copy. See README.txt for more details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DEMANGLE_STRINGVIEW_H
|
||||
#define DEMANGLE_STRINGVIEW_H
|
||||
|
||||
#include "DemangleConfig.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
inline bool starts_with(std::string_view self, char C) noexcept {
|
||||
return !self.empty() && *self.begin() == C;
|
||||
}
|
||||
|
||||
inline bool starts_with(std::string_view haystack,
|
||||
std::string_view needle) noexcept {
|
||||
if (needle.size() > haystack.size())
|
||||
return false;
|
||||
haystack.remove_suffix(haystack.size() - needle.size());
|
||||
return haystack == needle;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
+111
-97
@@ -1,5 +1,5 @@
|
||||
//===--- Utility.h ----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
//===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
@@ -7,70 +7,83 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Provide some utility classes for use in the demangler(s).
|
||||
// Provide some utility classes for use in the demangler.
|
||||
// There are two copies of this file in the source tree. The one in libcxxabi
|
||||
// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
|
||||
// the copy. See README.txt for more details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DEMANGLE_UTILITY_H
|
||||
#define DEMANGLE_UTILITY_H
|
||||
|
||||
#include "StringView.h"
|
||||
#include "DemangleConfig.h"
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
#include <string_view>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
// Stream that AST nodes write their string representation into after the AST
|
||||
// has been parsed.
|
||||
class OutputStream {
|
||||
char *Buffer;
|
||||
size_t CurrentPosition;
|
||||
size_t BufferCapacity;
|
||||
class OutputBuffer {
|
||||
char *Buffer = nullptr;
|
||||
size_t CurrentPosition = 0;
|
||||
size_t BufferCapacity = 0;
|
||||
|
||||
// Ensure there is at least n more positions in buffer.
|
||||
// Ensure there are at least N more positions in the buffer.
|
||||
void grow(size_t N) {
|
||||
if (N + CurrentPosition >= BufferCapacity) {
|
||||
size_t Need = N + CurrentPosition;
|
||||
if (Need > BufferCapacity) {
|
||||
// Reduce the number of reallocations, with a bit of hysteresis. The
|
||||
// number here is chosen so the first allocation will more-than-likely not
|
||||
// allocate more than 1K.
|
||||
Need += 1024 - 32;
|
||||
BufferCapacity *= 2;
|
||||
if (BufferCapacity < N + CurrentPosition)
|
||||
BufferCapacity = N + CurrentPosition;
|
||||
if (BufferCapacity < Need)
|
||||
BufferCapacity = Need;
|
||||
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
||||
if (Buffer == nullptr)
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void writeUnsigned(uint64_t N, bool isNeg = false) {
|
||||
// Handle special case...
|
||||
if (N == 0) {
|
||||
*this << '0';
|
||||
return;
|
||||
}
|
||||
OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
|
||||
std::array<char, 21> Temp;
|
||||
char *TempPtr = Temp.data() + Temp.size();
|
||||
|
||||
char Temp[21];
|
||||
char *TempPtr = std::end(Temp);
|
||||
|
||||
while (N) {
|
||||
*--TempPtr = '0' + char(N % 10);
|
||||
// Output at least one character.
|
||||
do {
|
||||
*--TempPtr = char('0' + N % 10);
|
||||
N /= 10;
|
||||
}
|
||||
} while (N);
|
||||
|
||||
// Add negative sign...
|
||||
// Add negative sign.
|
||||
if (isNeg)
|
||||
*--TempPtr = '-';
|
||||
this->operator<<(StringView(TempPtr, std::end(Temp)));
|
||||
|
||||
return operator+=(
|
||||
std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
|
||||
}
|
||||
|
||||
public:
|
||||
OutputStream(char *StartBuf, size_t Size)
|
||||
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
|
||||
OutputStream() = default;
|
||||
void reset(char *Buffer_, size_t BufferCapacity_) {
|
||||
CurrentPosition = 0;
|
||||
Buffer = Buffer_;
|
||||
BufferCapacity = BufferCapacity_;
|
||||
OutputBuffer(char *StartBuf, size_t Size)
|
||||
: Buffer(StartBuf), BufferCapacity(Size) {}
|
||||
OutputBuffer(char *StartBuf, size_t *SizePtr)
|
||||
: OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
|
||||
OutputBuffer() = default;
|
||||
// Non-copyable
|
||||
OutputBuffer(const OutputBuffer &) = delete;
|
||||
OutputBuffer &operator=(const OutputBuffer &) = delete;
|
||||
|
||||
operator std::string_view() const {
|
||||
return std::string_view(Buffer, CurrentPosition);
|
||||
}
|
||||
|
||||
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
|
||||
@@ -78,115 +91,116 @@ public:
|
||||
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
|
||||
unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
|
||||
|
||||
OutputStream &operator+=(StringView R) {
|
||||
size_t Size = R.size();
|
||||
if (Size == 0)
|
||||
return *this;
|
||||
grow(Size);
|
||||
std::memmove(Buffer + CurrentPosition, R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
/// When zero, we're printing template args and '>' needs to be parenthesized.
|
||||
/// Use a counter so we can simply increment inside parentheses.
|
||||
unsigned GtIsGt = 1;
|
||||
|
||||
bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
|
||||
|
||||
void printOpen(char Open = '(') {
|
||||
GtIsGt++;
|
||||
*this += Open;
|
||||
}
|
||||
void printClose(char Close = ')') {
|
||||
GtIsGt--;
|
||||
*this += Close;
|
||||
}
|
||||
|
||||
OutputBuffer &operator+=(std::string_view R) {
|
||||
if (size_t Size = R.size()) {
|
||||
grow(Size);
|
||||
std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator+=(char C) {
|
||||
OutputBuffer &operator+=(char C) {
|
||||
grow(1);
|
||||
Buffer[CurrentPosition++] = C;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(StringView R) { return (*this += R); }
|
||||
OutputBuffer &prepend(std::string_view R) {
|
||||
size_t Size = R.size();
|
||||
|
||||
OutputStream &operator<<(char C) { return (*this += C); }
|
||||
grow(Size);
|
||||
std::memmove(Buffer + Size, Buffer, CurrentPosition);
|
||||
std::memcpy(Buffer, &*R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
|
||||
OutputStream &operator<<(long long N) {
|
||||
if (N < 0)
|
||||
writeUnsigned(static_cast<unsigned long long>(-N), true);
|
||||
else
|
||||
writeUnsigned(static_cast<unsigned long long>(N));
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned long long N) {
|
||||
writeUnsigned(N, false);
|
||||
return *this;
|
||||
OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
|
||||
|
||||
OutputBuffer &operator<<(char C) { return (*this += C); }
|
||||
|
||||
OutputBuffer &operator<<(long long N) {
|
||||
return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
|
||||
}
|
||||
|
||||
OutputStream &operator<<(long N) {
|
||||
OutputBuffer &operator<<(unsigned long long N) {
|
||||
return writeUnsigned(N, false);
|
||||
}
|
||||
|
||||
OutputBuffer &operator<<(long N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned long N) {
|
||||
OutputBuffer &operator<<(unsigned long N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(int N) {
|
||||
OutputBuffer &operator<<(int N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned int N) {
|
||||
OutputBuffer &operator<<(unsigned int N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
void insert(size_t Pos, const char *S, size_t N) {
|
||||
assert(Pos <= CurrentPosition);
|
||||
if (N == 0)
|
||||
return;
|
||||
grow(N);
|
||||
std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
|
||||
std::memcpy(Buffer + Pos, S, N);
|
||||
CurrentPosition += N;
|
||||
}
|
||||
|
||||
size_t getCurrentPosition() const { return CurrentPosition; }
|
||||
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
||||
|
||||
char back() const {
|
||||
return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
|
||||
assert(CurrentPosition);
|
||||
return Buffer[CurrentPosition - 1];
|
||||
}
|
||||
|
||||
bool empty() const { return CurrentPosition == 0; }
|
||||
|
||||
char *getBuffer() { return Buffer; }
|
||||
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
|
||||
size_t getBufferCapacity() { return BufferCapacity; }
|
||||
size_t getBufferCapacity() const { return BufferCapacity; }
|
||||
};
|
||||
|
||||
template <class T> class SwapAndRestore {
|
||||
T &Restore;
|
||||
T OriginalValue;
|
||||
bool ShouldRestore = true;
|
||||
template <class T> class ScopedOverride {
|
||||
T &Loc;
|
||||
T Original;
|
||||
|
||||
public:
|
||||
SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
|
||||
ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
|
||||
|
||||
SwapAndRestore(T &Restore_, T NewVal)
|
||||
: Restore(Restore_), OriginalValue(Restore) {
|
||||
Restore = std::move(NewVal);
|
||||
}
|
||||
~SwapAndRestore() {
|
||||
if (ShouldRestore)
|
||||
Restore = std::move(OriginalValue);
|
||||
ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
|
||||
Loc_ = std::move(NewVal);
|
||||
}
|
||||
~ScopedOverride() { Loc = std::move(Original); }
|
||||
|
||||
void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
|
||||
|
||||
void restoreNow(bool Force) {
|
||||
if (!Force && !ShouldRestore)
|
||||
return;
|
||||
|
||||
Restore = std::move(OriginalValue);
|
||||
ShouldRestore = false;
|
||||
}
|
||||
|
||||
SwapAndRestore(const SwapAndRestore &) = delete;
|
||||
SwapAndRestore &operator=(const SwapAndRestore &) = delete;
|
||||
ScopedOverride(const ScopedOverride &) = delete;
|
||||
ScopedOverride &operator=(const ScopedOverride &) = delete;
|
||||
};
|
||||
|
||||
inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
|
||||
size_t InitSize) {
|
||||
size_t BufferSize;
|
||||
if (Buf == nullptr) {
|
||||
Buf = static_cast<char *>(std::malloc(InitSize));
|
||||
if (Buf == nullptr)
|
||||
return false;
|
||||
BufferSize = InitSize;
|
||||
} else
|
||||
BufferSize = *N;
|
||||
|
||||
S.reset(Buf, BufferSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-1
Submodule externals/vma/VulkanMemoryAllocator deleted from 0aa3989b8f
@@ -35,6 +35,7 @@ if (MSVC)
|
||||
# /volatile:iso - Use strict standards-compliant volatile semantics.
|
||||
# /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates
|
||||
# /Zc:inline - Let codegen omit inline functions in object files
|
||||
# /Zc:preprocessor - Enable standards-conforming preprocessor
|
||||
# /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null
|
||||
# /GT - Supports fiber safety for data allocated using static thread-local storage
|
||||
add_compile_options(
|
||||
@@ -48,6 +49,7 @@ if (MSVC)
|
||||
/volatile:iso
|
||||
/Zc:externConstexpr
|
||||
/Zc:inline
|
||||
/Zc:preprocessor
|
||||
/Zc:throwingNew
|
||||
/GT
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
android:label="@string/app_name_suffixed"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:allowBackup="true"
|
||||
android:hasFragileUserData="true"
|
||||
android:hasFragileUserData="false"
|
||||
android:supportsRtl="true"
|
||||
android:isGame="true"
|
||||
android:localeConfig="@xml/locales_config"
|
||||
@@ -54,6 +54,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<activity
|
||||
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
|
||||
android:theme="@style/Theme.Yuzu.Main"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="userLandscape"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"
|
||||
|
||||
@@ -34,11 +34,14 @@ import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.databinding.ActivityEmulationBinding
|
||||
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.Settings
|
||||
import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
|
||||
@@ -47,6 +50,7 @@ import org.yuzu.yuzu_emu.utils.InputHandler
|
||||
import org.yuzu.yuzu_emu.utils.MemoryUtil
|
||||
import org.yuzu.yuzu_emu.utils.NfcReader
|
||||
import org.yuzu.yuzu_emu.utils.ThemeHelper
|
||||
import java.text.NumberFormat
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
@@ -106,17 +110,26 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
inputHandler = InputHandler()
|
||||
inputHandler.initialize()
|
||||
|
||||
val memoryUtil = MemoryUtil(this)
|
||||
if (memoryUtil.isLessThan(8, MemoryUtil.Gb)) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
getString(
|
||||
R.string.device_memory_inadequate,
|
||||
memoryUtil.getDeviceRAM(),
|
||||
"8 ${getString(R.string.memory_gigabyte)}"
|
||||
),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) {
|
||||
if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.Gb)) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
getString(
|
||||
R.string.device_memory_inadequate,
|
||||
MemoryUtil.getDeviceRAM(),
|
||||
getString(
|
||||
R.string.memory_formatted,
|
||||
NumberFormat.getInstance().format(MemoryUtil.REQUIRED_MEMORY),
|
||||
getString(R.string.memory_gigabyte)
|
||||
)
|
||||
),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
preferences.edit()
|
||||
.putBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, true)
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
|
||||
// Start a foreground service to prevent the app from getting killed in the background
|
||||
|
||||
@@ -12,6 +12,7 @@ import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.CardHomeOptionBinding
|
||||
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
||||
import org.yuzu.yuzu_emu.model.HomeSetting
|
||||
|
||||
class HomeSettingAdapter(private val activity: AppCompatActivity, var options: List<HomeSetting>) :
|
||||
@@ -34,7 +35,14 @@ class HomeSettingAdapter(private val activity: AppCompatActivity, var options: L
|
||||
|
||||
override fun onClick(view: View) {
|
||||
val holder = view.tag as HomeOptionViewHolder
|
||||
holder.option.onClick.invoke()
|
||||
if (holder.option.isEnabled.invoke()) {
|
||||
holder.option.onClick.invoke()
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
holder.option.disabledTitleId,
|
||||
holder.option.disabledMessageId
|
||||
).show(activity.supportFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
|
||||
inner class HomeOptionViewHolder(val binding: CardHomeOptionBinding) :
|
||||
@@ -65,6 +73,12 @@ class HomeSettingAdapter(private val activity: AppCompatActivity, var options: L
|
||||
R.drawable.premium_background
|
||||
)
|
||||
}
|
||||
|
||||
if (!option.isEnabled.invoke()) {
|
||||
binding.optionTitle.alpha = 0.5f
|
||||
binding.optionDescription.alpha = 0.5f
|
||||
binding.optionIcon.alpha = 0.5f
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+53
-16
@@ -110,25 +110,38 @@ class Settings {
|
||||
const val SECTION_THEME = "Theme"
|
||||
const val SECTION_DEBUG = "Debug"
|
||||
|
||||
const val PREF_OVERLAY_INIT = "OverlayInit"
|
||||
const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown"
|
||||
|
||||
const val PREF_OVERLAY_VERSION = "OverlayVersion"
|
||||
const val PREF_LANDSCAPE_OVERLAY_VERSION = "LandscapeOverlayVersion"
|
||||
const val PREF_PORTRAIT_OVERLAY_VERSION = "PortraitOverlayVersion"
|
||||
const val PREF_FOLDABLE_OVERLAY_VERSION = "FoldableOverlayVersion"
|
||||
val overlayLayoutPrefs = listOf(
|
||||
PREF_LANDSCAPE_OVERLAY_VERSION,
|
||||
PREF_PORTRAIT_OVERLAY_VERSION,
|
||||
PREF_FOLDABLE_OVERLAY_VERSION
|
||||
)
|
||||
|
||||
const val PREF_CONTROL_SCALE = "controlScale"
|
||||
const val PREF_CONTROL_OPACITY = "controlOpacity"
|
||||
const val PREF_TOUCH_ENABLED = "isTouchEnabled"
|
||||
const val PREF_BUTTON_TOGGLE_0 = "buttonToggle0"
|
||||
const val PREF_BUTTON_TOGGLE_1 = "buttonToggle1"
|
||||
const val PREF_BUTTON_TOGGLE_2 = "buttonToggle2"
|
||||
const val PREF_BUTTON_TOGGLE_3 = "buttonToggle3"
|
||||
const val PREF_BUTTON_TOGGLE_4 = "buttonToggle4"
|
||||
const val PREF_BUTTON_TOGGLE_5 = "buttonToggle5"
|
||||
const val PREF_BUTTON_TOGGLE_6 = "buttonToggle6"
|
||||
const val PREF_BUTTON_TOGGLE_7 = "buttonToggle7"
|
||||
const val PREF_BUTTON_TOGGLE_8 = "buttonToggle8"
|
||||
const val PREF_BUTTON_TOGGLE_9 = "buttonToggle9"
|
||||
const val PREF_BUTTON_TOGGLE_10 = "buttonToggle10"
|
||||
const val PREF_BUTTON_TOGGLE_11 = "buttonToggle11"
|
||||
const val PREF_BUTTON_TOGGLE_12 = "buttonToggle12"
|
||||
const val PREF_BUTTON_TOGGLE_13 = "buttonToggle13"
|
||||
const val PREF_BUTTON_TOGGLE_14 = "buttonToggle14"
|
||||
const val PREF_BUTTON_A = "buttonToggle0"
|
||||
const val PREF_BUTTON_B = "buttonToggle1"
|
||||
const val PREF_BUTTON_X = "buttonToggle2"
|
||||
const val PREF_BUTTON_Y = "buttonToggle3"
|
||||
const val PREF_BUTTON_L = "buttonToggle4"
|
||||
const val PREF_BUTTON_R = "buttonToggle5"
|
||||
const val PREF_BUTTON_ZL = "buttonToggle6"
|
||||
const val PREF_BUTTON_ZR = "buttonToggle7"
|
||||
const val PREF_BUTTON_PLUS = "buttonToggle8"
|
||||
const val PREF_BUTTON_MINUS = "buttonToggle9"
|
||||
const val PREF_BUTTON_DPAD = "buttonToggle10"
|
||||
const val PREF_STICK_L = "buttonToggle11"
|
||||
const val PREF_STICK_R = "buttonToggle12"
|
||||
const val PREF_BUTTON_STICK_L = "buttonToggle13"
|
||||
const val PREF_BUTTON_STICK_R = "buttonToggle14"
|
||||
const val PREF_BUTTON_HOME = "buttonToggle15"
|
||||
const val PREF_BUTTON_SCREENSHOT = "buttonToggle16"
|
||||
|
||||
const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
|
||||
const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
|
||||
@@ -143,6 +156,30 @@ class Settings {
|
||||
|
||||
private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap()
|
||||
|
||||
val overlayPreferences = listOf(
|
||||
PREF_OVERLAY_VERSION,
|
||||
PREF_CONTROL_SCALE,
|
||||
PREF_CONTROL_OPACITY,
|
||||
PREF_TOUCH_ENABLED,
|
||||
PREF_BUTTON_A,
|
||||
PREF_BUTTON_B,
|
||||
PREF_BUTTON_X,
|
||||
PREF_BUTTON_Y,
|
||||
PREF_BUTTON_L,
|
||||
PREF_BUTTON_R,
|
||||
PREF_BUTTON_ZL,
|
||||
PREF_BUTTON_ZR,
|
||||
PREF_BUTTON_PLUS,
|
||||
PREF_BUTTON_MINUS,
|
||||
PREF_BUTTON_DPAD,
|
||||
PREF_STICK_L,
|
||||
PREF_STICK_R,
|
||||
PREF_BUTTON_HOME,
|
||||
PREF_BUTTON_SCREENSHOT,
|
||||
PREF_BUTTON_STICK_L,
|
||||
PREF_BUTTON_STICK_R
|
||||
)
|
||||
|
||||
const val LayoutOption_Unspecified = 0
|
||||
const val LayoutOption_MobilePortrait = 4
|
||||
const val LayoutOption_MobileLandscape = 5
|
||||
|
||||
@@ -212,9 +212,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
}
|
||||
if (!isInFoldableLayout) {
|
||||
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
binding.surfaceInputOverlay.orientation = InputOverlay.PORTRAIT
|
||||
binding.surfaceInputOverlay.layout = InputOverlay.PORTRAIT
|
||||
} else {
|
||||
binding.surfaceInputOverlay.orientation = InputOverlay.LANDSCAPE
|
||||
binding.surfaceInputOverlay.layout = InputOverlay.LANDSCAPE
|
||||
}
|
||||
}
|
||||
if (!binding.surfaceInputOverlay.isInEditMode) {
|
||||
@@ -260,7 +260,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
.remove(Settings.PREF_CONTROL_SCALE)
|
||||
.remove(Settings.PREF_CONTROL_OPACITY)
|
||||
.apply()
|
||||
binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.resetButtonPlacement() }
|
||||
binding.surfaceInputOverlay.post {
|
||||
binding.surfaceInputOverlay.resetLayoutVisibilityAndPlacement()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateShowFpsOverlay() {
|
||||
@@ -337,7 +339,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
binding.inGameMenu.layoutParams.height = it.bounds.bottom
|
||||
|
||||
isInFoldableLayout = true
|
||||
binding.surfaceInputOverlay.orientation = InputOverlay.FOLDABLE
|
||||
binding.surfaceInputOverlay.layout = InputOverlay.FOLDABLE
|
||||
refreshInputOverlay()
|
||||
}
|
||||
}
|
||||
@@ -410,9 +412,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
R.id.menu_toggle_controls -> {
|
||||
val preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
val optionsArray = BooleanArray(15)
|
||||
for (i in 0..14) {
|
||||
optionsArray[i] = preferences.getBoolean("buttonToggle$i", i < 13)
|
||||
val optionsArray = BooleanArray(Settings.overlayPreferences.size)
|
||||
Settings.overlayPreferences.forEachIndexed { i, _ ->
|
||||
optionsArray[i] = preferences.getBoolean("buttonToggle$i", i < 15)
|
||||
}
|
||||
|
||||
val dialog = MaterialAlertDialogBuilder(requireContext())
|
||||
@@ -436,7 +438,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
|
||||
.setOnClickListener {
|
||||
val isChecked = !optionsArray[0]
|
||||
for (i in 0..14) {
|
||||
Settings.overlayPreferences.forEachIndexed { i, _ ->
|
||||
optionsArray[i] = isChecked
|
||||
dialog.listView.setItemChecked(i, isChecked)
|
||||
preferences.edit()
|
||||
|
||||
@@ -73,102 +73,113 @@ class HomeSettingsFragment : Fragment() {
|
||||
HomeSetting(
|
||||
R.string.advanced_settings,
|
||||
R.string.settings_description,
|
||||
R.drawable.ic_settings
|
||||
) { SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") }
|
||||
R.drawable.ic_settings,
|
||||
{ SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.open_user_folder,
|
||||
R.string.open_user_folder_description,
|
||||
R.drawable.ic_folder_open
|
||||
) { openFileManager() }
|
||||
R.drawable.ic_folder_open,
|
||||
{ openFileManager() }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.preferences_theme,
|
||||
R.string.theme_and_color_description,
|
||||
R.drawable.ic_palette
|
||||
) { SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") }
|
||||
)
|
||||
|
||||
if (GpuDriverHelper.supportsCustomDriverLoading()) {
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_gpu_driver,
|
||||
R.string.install_gpu_driver_description,
|
||||
R.drawable.ic_exit
|
||||
) { driverInstaller() }
|
||||
R.drawable.ic_palette,
|
||||
{ SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") }
|
||||
)
|
||||
}
|
||||
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_gpu_driver,
|
||||
R.string.install_gpu_driver_description,
|
||||
R.drawable.ic_exit,
|
||||
{ driverInstaller() },
|
||||
{ GpuDriverHelper.supportsCustomDriverLoading() },
|
||||
R.string.custom_driver_not_supported,
|
||||
R.string.custom_driver_not_supported_description
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_amiibo_keys,
|
||||
R.string.install_amiibo_keys_description,
|
||||
R.drawable.ic_nfc
|
||||
) { mainActivity.getAmiiboKey.launch(arrayOf("*/*")) }
|
||||
R.drawable.ic_nfc,
|
||||
{ mainActivity.getAmiiboKey.launch(arrayOf("*/*")) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_game_content,
|
||||
R.string.install_game_content_description,
|
||||
R.drawable.ic_system_update_alt
|
||||
) { mainActivity.installGameUpdate.launch(arrayOf("*/*")) }
|
||||
R.drawable.ic_system_update_alt,
|
||||
{ mainActivity.installGameUpdate.launch(arrayOf("*/*")) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.select_games_folder,
|
||||
R.string.select_games_folder_description,
|
||||
R.drawable.ic_add
|
||||
) {
|
||||
mainActivity.getGamesDirectory.launch(
|
||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
|
||||
)
|
||||
}
|
||||
R.drawable.ic_add,
|
||||
{
|
||||
mainActivity.getGamesDirectory.launch(
|
||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.manage_save_data,
|
||||
R.string.import_export_saves_description,
|
||||
R.drawable.ic_save
|
||||
) {
|
||||
ImportExportSavesFragment().show(
|
||||
parentFragmentManager,
|
||||
ImportExportSavesFragment.TAG
|
||||
)
|
||||
}
|
||||
R.drawable.ic_save,
|
||||
{
|
||||
ImportExportSavesFragment().show(
|
||||
parentFragmentManager,
|
||||
ImportExportSavesFragment.TAG
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_prod_keys,
|
||||
R.string.install_prod_keys_description,
|
||||
R.drawable.ic_unlock
|
||||
) { mainActivity.getProdKey.launch(arrayOf("*/*")) }
|
||||
R.drawable.ic_unlock,
|
||||
{ mainActivity.getProdKey.launch(arrayOf("*/*")) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_firmware,
|
||||
R.string.install_firmware_description,
|
||||
R.drawable.ic_firmware
|
||||
) { mainActivity.getFirmware.launch(arrayOf("application/zip")) }
|
||||
R.drawable.ic_firmware,
|
||||
{ mainActivity.getFirmware.launch(arrayOf("application/zip")) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.share_log,
|
||||
R.string.share_log_description,
|
||||
R.drawable.ic_log
|
||||
) { shareLog() }
|
||||
R.drawable.ic_log,
|
||||
{ shareLog() }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.about,
|
||||
R.string.about_description,
|
||||
R.drawable.ic_info_outline
|
||||
) {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()
|
||||
?.navigate(R.id.action_homeSettingsFragment_to_aboutFragment)
|
||||
}
|
||||
R.drawable.ic_info_outline,
|
||||
{
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()
|
||||
?.navigate(R.id.action_homeSettingsFragment_to_aboutFragment)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -178,12 +189,13 @@ class HomeSettingsFragment : Fragment() {
|
||||
HomeSetting(
|
||||
R.string.get_early_access,
|
||||
R.string.get_early_access_description,
|
||||
R.drawable.ic_diamond
|
||||
) {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()
|
||||
?.navigate(R.id.action_homeSettingsFragment_to_earlyAccessFragment)
|
||||
}
|
||||
R.drawable.ic_diamond,
|
||||
{
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()
|
||||
?.navigate(R.id.action_homeSettingsFragment_to_earlyAccessFragment)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,5 +7,8 @@ data class HomeSetting(
|
||||
val titleId: Int,
|
||||
val descriptionId: Int,
|
||||
val iconId: Int,
|
||||
val onClick: () -> Unit
|
||||
val onClick: () -> Unit,
|
||||
val isEnabled: () -> Boolean = { true },
|
||||
val disabledTitleId: Int = 0,
|
||||
val disabledMessageId: Int = 0
|
||||
)
|
||||
|
||||
@@ -51,15 +51,23 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
private lateinit var windowInsets: WindowInsets
|
||||
|
||||
var orientation = LANDSCAPE
|
||||
var layout = LANDSCAPE
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
|
||||
windowInsets = rootWindowInsets
|
||||
|
||||
if (!preferences.getBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", false)) {
|
||||
defaultOverlay()
|
||||
val overlayVersion = preferences.getInt(Settings.PREF_OVERLAY_VERSION, 0)
|
||||
if (overlayVersion != OVERLAY_VERSION) {
|
||||
resetAllLayouts()
|
||||
} else {
|
||||
val layoutIndex = overlayLayouts.indexOf(layout)
|
||||
val currentLayoutVersion =
|
||||
preferences.getInt(Settings.overlayLayoutPrefs[layoutIndex], 0)
|
||||
if (currentLayoutVersion != overlayLayoutVersions[layoutIndex]) {
|
||||
resetCurrentLayout()
|
||||
}
|
||||
}
|
||||
|
||||
// Load the controls.
|
||||
@@ -266,10 +274,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) {
|
||||
// Persist button position by saving new place.
|
||||
saveControlPosition(
|
||||
buttonBeingConfigured!!.buttonId,
|
||||
buttonBeingConfigured!!.prefId,
|
||||
buttonBeingConfigured!!.bounds.centerX(),
|
||||
buttonBeingConfigured!!.bounds.centerY(),
|
||||
orientation
|
||||
layout
|
||||
)
|
||||
buttonBeingConfigured = null
|
||||
}
|
||||
@@ -299,10 +307,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
MotionEvent.ACTION_POINTER_UP -> if (dpadBeingConfigured === dpad) {
|
||||
// Persist button position by saving new place.
|
||||
saveControlPosition(
|
||||
dpadBeingConfigured!!.upId,
|
||||
Settings.PREF_BUTTON_DPAD,
|
||||
dpadBeingConfigured!!.bounds.centerX(),
|
||||
dpadBeingConfigured!!.bounds.centerY(),
|
||||
orientation
|
||||
layout
|
||||
)
|
||||
dpadBeingConfigured = null
|
||||
}
|
||||
@@ -330,10 +338,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_POINTER_UP -> if (joystickBeingConfigured != null) {
|
||||
saveControlPosition(
|
||||
joystickBeingConfigured!!.buttonId,
|
||||
joystickBeingConfigured!!.prefId,
|
||||
joystickBeingConfigured!!.bounds.centerX(),
|
||||
joystickBeingConfigured!!.bounds.centerY(),
|
||||
orientation
|
||||
layout
|
||||
)
|
||||
joystickBeingConfigured = null
|
||||
}
|
||||
@@ -343,9 +351,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
return true
|
||||
}
|
||||
|
||||
private fun addOverlayControls(orientation: String) {
|
||||
private fun addOverlayControls(layout: String) {
|
||||
val windowSize = getSafeScreenSize(context)
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_0, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_A, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -353,11 +361,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.facebutton_a,
|
||||
R.drawable.facebutton_a_depressed,
|
||||
ButtonType.BUTTON_A,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_A,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_1, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_B, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -365,11 +374,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.facebutton_b,
|
||||
R.drawable.facebutton_b_depressed,
|
||||
ButtonType.BUTTON_B,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_B,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_2, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_X, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -377,11 +387,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.facebutton_x,
|
||||
R.drawable.facebutton_x_depressed,
|
||||
ButtonType.BUTTON_X,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_X,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_3, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_Y, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -389,11 +400,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.facebutton_y,
|
||||
R.drawable.facebutton_y_depressed,
|
||||
ButtonType.BUTTON_Y,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_Y,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_4, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_L, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -401,11 +413,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.l_shoulder,
|
||||
R.drawable.l_shoulder_depressed,
|
||||
ButtonType.TRIGGER_L,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_L,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_5, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_R, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -413,11 +426,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.r_shoulder,
|
||||
R.drawable.r_shoulder_depressed,
|
||||
ButtonType.TRIGGER_R,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_R,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_6, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_ZL, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -425,11 +439,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.zl_trigger,
|
||||
R.drawable.zl_trigger_depressed,
|
||||
ButtonType.TRIGGER_ZL,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_ZL,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_7, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_ZR, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -437,11 +452,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.zr_trigger,
|
||||
R.drawable.zr_trigger_depressed,
|
||||
ButtonType.TRIGGER_ZR,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_ZR,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_8, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_PLUS, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -449,11 +465,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.facebutton_plus,
|
||||
R.drawable.facebutton_plus_depressed,
|
||||
ButtonType.BUTTON_PLUS,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_PLUS,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_9, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_MINUS, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -461,11 +478,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.facebutton_minus,
|
||||
R.drawable.facebutton_minus_depressed,
|
||||
ButtonType.BUTTON_MINUS,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_MINUS,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_10, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_DPAD, true)) {
|
||||
overlayDpads.add(
|
||||
initializeOverlayDpad(
|
||||
context,
|
||||
@@ -473,11 +491,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.dpad_standard,
|
||||
R.drawable.dpad_standard_cardinal_depressed,
|
||||
R.drawable.dpad_standard_diagonal_depressed,
|
||||
orientation
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_11, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_STICK_L, true)) {
|
||||
overlayJoysticks.add(
|
||||
initializeOverlayJoystick(
|
||||
context,
|
||||
@@ -487,11 +505,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.joystick_depressed,
|
||||
StickType.STICK_L,
|
||||
ButtonType.STICK_L,
|
||||
orientation
|
||||
Settings.PREF_STICK_L,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_12, true)) {
|
||||
if (preferences.getBoolean(Settings.PREF_STICK_R, true)) {
|
||||
overlayJoysticks.add(
|
||||
initializeOverlayJoystick(
|
||||
context,
|
||||
@@ -501,11 +520,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.joystick_depressed,
|
||||
StickType.STICK_R,
|
||||
ButtonType.STICK_R,
|
||||
orientation
|
||||
Settings.PREF_STICK_R,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_13, false)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_HOME, false)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -513,11 +533,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.facebutton_home,
|
||||
R.drawable.facebutton_home_depressed,
|
||||
ButtonType.BUTTON_HOME,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_HOME,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_14, false)) {
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_SCREENSHOT, false)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
@@ -525,7 +546,34 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.drawable.facebutton_screenshot,
|
||||
R.drawable.facebutton_screenshot_depressed,
|
||||
ButtonType.BUTTON_CAPTURE,
|
||||
orientation
|
||||
Settings.PREF_BUTTON_SCREENSHOT,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_STICK_L, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
windowSize,
|
||||
R.drawable.button_l3,
|
||||
R.drawable.button_l3_depressed,
|
||||
ButtonType.STICK_L,
|
||||
Settings.PREF_BUTTON_STICK_L,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
if (preferences.getBoolean(Settings.PREF_BUTTON_STICK_R, true)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
windowSize,
|
||||
R.drawable.button_r3,
|
||||
R.drawable.button_r3_depressed,
|
||||
ButtonType.STICK_R,
|
||||
Settings.PREF_BUTTON_STICK_R,
|
||||
layout
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -539,18 +587,18 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
// Add all the enabled overlay items back to the HashSet.
|
||||
if (EmulationMenuSettings.showOverlay) {
|
||||
addOverlayControls(orientation)
|
||||
addOverlayControls(layout)
|
||||
}
|
||||
invalidate()
|
||||
}
|
||||
|
||||
private fun saveControlPosition(sharedPrefsId: Int, x: Int, y: Int, orientation: String) {
|
||||
private fun saveControlPosition(prefId: String, x: Int, y: Int, layout: String) {
|
||||
val windowSize = getSafeScreenSize(context)
|
||||
val min = windowSize.first
|
||||
val max = windowSize.second
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
||||
.putFloat("$sharedPrefsId-X$orientation", (x - min.x).toFloat() / max.x)
|
||||
.putFloat("$sharedPrefsId-Y$orientation", (y - min.y).toFloat() / max.y)
|
||||
.putFloat("$prefId-X$layout", (x - min.x).toFloat() / max.x)
|
||||
.putFloat("$prefId-Y$layout", (y - min.y).toFloat() / max.y)
|
||||
.apply()
|
||||
}
|
||||
|
||||
@@ -558,19 +606,31 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
inEditMode = editMode
|
||||
}
|
||||
|
||||
private fun defaultOverlay() {
|
||||
if (!preferences.getBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", false)) {
|
||||
defaultOverlayByLayout(orientation)
|
||||
}
|
||||
|
||||
resetButtonPlacement()
|
||||
private fun resetCurrentLayout() {
|
||||
defaultOverlayByLayout(layout)
|
||||
val layoutIndex = overlayLayouts.indexOf(layout)
|
||||
preferences.edit()
|
||||
.putBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", true)
|
||||
.putInt(Settings.overlayLayoutPrefs[layoutIndex], overlayLayoutVersions[layoutIndex])
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun resetButtonPlacement() {
|
||||
defaultOverlayByLayout(orientation)
|
||||
private fun resetAllLayouts() {
|
||||
val editor = preferences.edit()
|
||||
overlayLayouts.forEachIndexed { i, layout ->
|
||||
defaultOverlayByLayout(layout)
|
||||
editor.putInt(Settings.overlayLayoutPrefs[i], overlayLayoutVersions[i])
|
||||
}
|
||||
editor.putInt(Settings.PREF_OVERLAY_VERSION, OVERLAY_VERSION)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
fun resetLayoutVisibilityAndPlacement() {
|
||||
defaultOverlayByLayout(layout)
|
||||
val editor = preferences.edit()
|
||||
Settings.overlayPreferences.forEachIndexed { _, pref ->
|
||||
editor.remove(pref)
|
||||
}
|
||||
editor.apply()
|
||||
refreshControls()
|
||||
}
|
||||
|
||||
@@ -604,7 +664,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.integer.SWITCH_STICK_R_X,
|
||||
R.integer.SWITCH_STICK_R_Y,
|
||||
R.integer.SWITCH_STICK_L_X,
|
||||
R.integer.SWITCH_STICK_L_Y
|
||||
R.integer.SWITCH_STICK_L_Y,
|
||||
R.integer.SWITCH_BUTTON_STICK_L_X,
|
||||
R.integer.SWITCH_BUTTON_STICK_L_Y,
|
||||
R.integer.SWITCH_BUTTON_STICK_R_X,
|
||||
R.integer.SWITCH_BUTTON_STICK_R_Y
|
||||
)
|
||||
|
||||
private val portraitResources = arrayOf(
|
||||
@@ -637,7 +701,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.integer.SWITCH_STICK_R_X_PORTRAIT,
|
||||
R.integer.SWITCH_STICK_R_Y_PORTRAIT,
|
||||
R.integer.SWITCH_STICK_L_X_PORTRAIT,
|
||||
R.integer.SWITCH_STICK_L_Y_PORTRAIT
|
||||
R.integer.SWITCH_STICK_L_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_STICK_L_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_STICK_L_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_STICK_R_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_STICK_R_Y_PORTRAIT
|
||||
)
|
||||
|
||||
private val foldableResources = arrayOf(
|
||||
@@ -670,139 +738,159 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
R.integer.SWITCH_STICK_R_X_FOLDABLE,
|
||||
R.integer.SWITCH_STICK_R_Y_FOLDABLE,
|
||||
R.integer.SWITCH_STICK_L_X_FOLDABLE,
|
||||
R.integer.SWITCH_STICK_L_Y_FOLDABLE
|
||||
R.integer.SWITCH_STICK_L_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_STICK_L_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_STICK_L_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_STICK_R_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_STICK_R_Y_FOLDABLE
|
||||
)
|
||||
|
||||
private fun getResourceValue(orientation: String, position: Int): Float {
|
||||
return when (orientation) {
|
||||
private fun getResourceValue(layout: String, position: Int): Float {
|
||||
return when (layout) {
|
||||
PORTRAIT -> resources.getInteger(portraitResources[position]).toFloat() / 1000
|
||||
FOLDABLE -> resources.getInteger(foldableResources[position]).toFloat() / 1000
|
||||
else -> resources.getInteger(landscapeResources[position]).toFloat() / 1000
|
||||
}
|
||||
}
|
||||
|
||||
private fun defaultOverlayByLayout(orientation: String) {
|
||||
private fun defaultOverlayByLayout(layout: String) {
|
||||
// Each value represents the position of the button in relation to the screen size without insets.
|
||||
preferences.edit()
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_A.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 0)
|
||||
"${Settings.PREF_BUTTON_A}-X$layout",
|
||||
getResourceValue(layout, 0)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_A.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 1)
|
||||
"${Settings.PREF_BUTTON_A}-Y$layout",
|
||||
getResourceValue(layout, 1)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_B.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 2)
|
||||
"${Settings.PREF_BUTTON_B}-X$layout",
|
||||
getResourceValue(layout, 2)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_B.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 3)
|
||||
"${Settings.PREF_BUTTON_B}-Y$layout",
|
||||
getResourceValue(layout, 3)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_X.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 4)
|
||||
"${Settings.PREF_BUTTON_X}-X$layout",
|
||||
getResourceValue(layout, 4)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_X.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 5)
|
||||
"${Settings.PREF_BUTTON_X}-Y$layout",
|
||||
getResourceValue(layout, 5)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_Y.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 6)
|
||||
"${Settings.PREF_BUTTON_Y}-X$layout",
|
||||
getResourceValue(layout, 6)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_Y.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 7)
|
||||
"${Settings.PREF_BUTTON_Y}-Y$layout",
|
||||
getResourceValue(layout, 7)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_ZL.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 8)
|
||||
"${Settings.PREF_BUTTON_ZL}-X$layout",
|
||||
getResourceValue(layout, 8)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_ZL.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 9)
|
||||
"${Settings.PREF_BUTTON_ZL}-Y$layout",
|
||||
getResourceValue(layout, 9)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_ZR.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 10)
|
||||
"${Settings.PREF_BUTTON_ZR}-X$layout",
|
||||
getResourceValue(layout, 10)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_ZR.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 11)
|
||||
"${Settings.PREF_BUTTON_ZR}-Y$layout",
|
||||
getResourceValue(layout, 11)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.DPAD_UP.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 12)
|
||||
"${Settings.PREF_BUTTON_DPAD}-X$layout",
|
||||
getResourceValue(layout, 12)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.DPAD_UP.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 13)
|
||||
"${Settings.PREF_BUTTON_DPAD}-Y$layout",
|
||||
getResourceValue(layout, 13)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_L.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 14)
|
||||
"${Settings.PREF_BUTTON_L}-X$layout",
|
||||
getResourceValue(layout, 14)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_L.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 15)
|
||||
"${Settings.PREF_BUTTON_L}-Y$layout",
|
||||
getResourceValue(layout, 15)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_R.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 16)
|
||||
"${Settings.PREF_BUTTON_R}-X$layout",
|
||||
getResourceValue(layout, 16)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_R.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 17)
|
||||
"${Settings.PREF_BUTTON_R}-Y$layout",
|
||||
getResourceValue(layout, 17)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_PLUS.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 18)
|
||||
"${Settings.PREF_BUTTON_PLUS}-X$layout",
|
||||
getResourceValue(layout, 18)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_PLUS.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 19)
|
||||
"${Settings.PREF_BUTTON_PLUS}-Y$layout",
|
||||
getResourceValue(layout, 19)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_MINUS.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 20)
|
||||
"${Settings.PREF_BUTTON_MINUS}-X$layout",
|
||||
getResourceValue(layout, 20)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_MINUS.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 21)
|
||||
"${Settings.PREF_BUTTON_MINUS}-Y$layout",
|
||||
getResourceValue(layout, 21)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_HOME.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 22)
|
||||
"${Settings.PREF_BUTTON_HOME}-X$layout",
|
||||
getResourceValue(layout, 22)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_HOME.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 23)
|
||||
"${Settings.PREF_BUTTON_HOME}-Y$layout",
|
||||
getResourceValue(layout, 23)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_CAPTURE.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 24)
|
||||
"${Settings.PREF_BUTTON_SCREENSHOT}-X$layout",
|
||||
getResourceValue(layout, 24)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_CAPTURE.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 25)
|
||||
"${Settings.PREF_BUTTON_SCREENSHOT}-Y$layout",
|
||||
getResourceValue(layout, 25)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.STICK_R.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 26)
|
||||
"${Settings.PREF_STICK_R}-X$layout",
|
||||
getResourceValue(layout, 26)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.STICK_R.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 27)
|
||||
"${Settings.PREF_STICK_R}-Y$layout",
|
||||
getResourceValue(layout, 27)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.STICK_L.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 28)
|
||||
"${Settings.PREF_STICK_L}-X$layout",
|
||||
getResourceValue(layout, 28)
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.STICK_L.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 29)
|
||||
"${Settings.PREF_STICK_L}-Y$layout",
|
||||
getResourceValue(layout, 29)
|
||||
)
|
||||
.putFloat(
|
||||
"${Settings.PREF_BUTTON_STICK_L}-X$layout",
|
||||
getResourceValue(layout, 30)
|
||||
)
|
||||
.putFloat(
|
||||
"${Settings.PREF_BUTTON_STICK_L}-Y$layout",
|
||||
getResourceValue(layout, 31)
|
||||
)
|
||||
.putFloat(
|
||||
"${Settings.PREF_BUTTON_STICK_R}-X$layout",
|
||||
getResourceValue(layout, 32)
|
||||
)
|
||||
.putFloat(
|
||||
"${Settings.PREF_BUTTON_STICK_R}-Y$layout",
|
||||
getResourceValue(layout, 33)
|
||||
)
|
||||
.apply()
|
||||
}
|
||||
@@ -812,12 +900,30 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Increase this number every time there is a breaking change to every overlay layout
|
||||
const val OVERLAY_VERSION = 1
|
||||
|
||||
// Increase the corresponding layout version number whenever that layout has a breaking change
|
||||
private const val LANDSCAPE_OVERLAY_VERSION = 1
|
||||
private const val PORTRAIT_OVERLAY_VERSION = 1
|
||||
private const val FOLDABLE_OVERLAY_VERSION = 1
|
||||
val overlayLayoutVersions = listOf(
|
||||
LANDSCAPE_OVERLAY_VERSION,
|
||||
PORTRAIT_OVERLAY_VERSION,
|
||||
FOLDABLE_OVERLAY_VERSION
|
||||
)
|
||||
|
||||
private val preferences: SharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
|
||||
const val LANDSCAPE = ""
|
||||
const val LANDSCAPE = "_Landscape"
|
||||
const val PORTRAIT = "_Portrait"
|
||||
const val FOLDABLE = "_Foldable"
|
||||
val overlayLayouts = listOf(
|
||||
LANDSCAPE,
|
||||
PORTRAIT,
|
||||
FOLDABLE
|
||||
)
|
||||
|
||||
/**
|
||||
* Resizes a [Bitmap] by a given scale factor
|
||||
@@ -948,6 +1054,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
* @param defaultResId The resource ID of the [Drawable] to get the [Bitmap] of (Default State).
|
||||
* @param pressedResId The resource ID of the [Drawable] to get the [Bitmap] of (Pressed State).
|
||||
* @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents.
|
||||
* @param prefId Identifier for determining where a button appears on screen.
|
||||
* @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE].
|
||||
* @return An [InputOverlayDrawableButton] with the correct drawing bounds set.
|
||||
*/
|
||||
private fun initializeOverlayButton(
|
||||
@@ -956,7 +1064,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
defaultResId: Int,
|
||||
pressedResId: Int,
|
||||
buttonId: Int,
|
||||
orientation: String
|
||||
prefId: String,
|
||||
layout: String
|
||||
): InputOverlayDrawableButton {
|
||||
// Resources handle for fetching the initial Drawable resource.
|
||||
val res = context.resources
|
||||
@@ -964,17 +1073,20 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
// SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableButton.
|
||||
val sPrefs = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
|
||||
// Decide scale based on button ID and user preference
|
||||
var scale: Float = when (buttonId) {
|
||||
ButtonType.BUTTON_HOME,
|
||||
ButtonType.BUTTON_CAPTURE,
|
||||
ButtonType.BUTTON_PLUS,
|
||||
ButtonType.BUTTON_MINUS -> 0.07f
|
||||
// Decide scale based on button preference ID and user preference
|
||||
var scale: Float = when (prefId) {
|
||||
Settings.PREF_BUTTON_HOME,
|
||||
Settings.PREF_BUTTON_SCREENSHOT,
|
||||
Settings.PREF_BUTTON_PLUS,
|
||||
Settings.PREF_BUTTON_MINUS -> 0.07f
|
||||
|
||||
ButtonType.TRIGGER_L,
|
||||
ButtonType.TRIGGER_R,
|
||||
ButtonType.TRIGGER_ZL,
|
||||
ButtonType.TRIGGER_ZR -> 0.26f
|
||||
Settings.PREF_BUTTON_L,
|
||||
Settings.PREF_BUTTON_R,
|
||||
Settings.PREF_BUTTON_ZL,
|
||||
Settings.PREF_BUTTON_ZR -> 0.26f
|
||||
|
||||
Settings.PREF_BUTTON_STICK_L,
|
||||
Settings.PREF_BUTTON_STICK_R -> 0.155f
|
||||
|
||||
else -> 0.11f
|
||||
}
|
||||
@@ -984,8 +1096,13 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
// Initialize the InputOverlayDrawableButton.
|
||||
val defaultStateBitmap = getBitmap(context, defaultResId, scale)
|
||||
val pressedStateBitmap = getBitmap(context, pressedResId, scale)
|
||||
val overlayDrawable =
|
||||
InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId)
|
||||
val overlayDrawable = InputOverlayDrawableButton(
|
||||
res,
|
||||
defaultStateBitmap,
|
||||
pressedStateBitmap,
|
||||
buttonId,
|
||||
prefId
|
||||
)
|
||||
|
||||
// Get the minimum and maximum coordinates of the screen where the button can be placed.
|
||||
val min = windowSize.first
|
||||
@@ -993,8 +1110,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
|
||||
// These were set in the input overlay configuration menu.
|
||||
val xKey = "$buttonId-X$orientation"
|
||||
val yKey = "$buttonId-Y$orientation"
|
||||
val xKey = "$prefId-X$layout"
|
||||
val yKey = "$prefId-Y$layout"
|
||||
val drawableXPercent = sPrefs.getFloat(xKey, 0f)
|
||||
val drawableYPercent = sPrefs.getFloat(yKey, 0f)
|
||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||
@@ -1029,7 +1146,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
* @param defaultResId The [Bitmap] resource ID of the default state.
|
||||
* @param pressedOneDirectionResId The [Bitmap] resource ID of the pressed state in one direction.
|
||||
* @param pressedTwoDirectionsResId The [Bitmap] resource ID of the pressed state in two directions.
|
||||
* @return the initialized [InputOverlayDrawableDpad]
|
||||
* @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE].
|
||||
* @return The initialized [InputOverlayDrawableDpad]
|
||||
*/
|
||||
private fun initializeOverlayDpad(
|
||||
context: Context,
|
||||
@@ -1037,7 +1155,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
defaultResId: Int,
|
||||
pressedOneDirectionResId: Int,
|
||||
pressedTwoDirectionsResId: Int,
|
||||
orientation: String
|
||||
layout: String
|
||||
): InputOverlayDrawableDpad {
|
||||
// Resources handle for fetching the initial Drawable resource.
|
||||
val res = context.resources
|
||||
@@ -1074,8 +1192,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
// The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay.
|
||||
// These were set in the input overlay configuration menu.
|
||||
val drawableXPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-X$orientation", 0f)
|
||||
val drawableYPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-Y$orientation", 0f)
|
||||
val drawableXPercent = sPrefs.getFloat("${Settings.PREF_BUTTON_DPAD}-X$layout", 0f)
|
||||
val drawableYPercent = sPrefs.getFloat("${Settings.PREF_BUTTON_DPAD}-Y$layout", 0f)
|
||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||
val drawableY = (drawableYPercent * max.y + min.y).toInt()
|
||||
val width = overlayDrawable.width
|
||||
@@ -1107,7 +1225,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
* @param pressedResInner Resource ID for the pressed inner image of the joystick.
|
||||
* @param joystick Identifier for which joystick this is.
|
||||
* @param button Identifier for which joystick button this is.
|
||||
* @return the initialized [InputOverlayDrawableJoystick].
|
||||
* @param prefId Identifier for determining where a button appears on screen.
|
||||
* @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE].
|
||||
* @return The initialized [InputOverlayDrawableJoystick].
|
||||
*/
|
||||
private fun initializeOverlayJoystick(
|
||||
context: Context,
|
||||
@@ -1117,7 +1237,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
pressedResInner: Int,
|
||||
joystick: Int,
|
||||
button: Int,
|
||||
orientation: String
|
||||
prefId: String,
|
||||
layout: String
|
||||
): InputOverlayDrawableJoystick {
|
||||
// Resources handle for fetching the initial Drawable resource.
|
||||
val res = context.resources
|
||||
@@ -1141,8 +1262,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
|
||||
// These were set in the input overlay configuration menu.
|
||||
val drawableXPercent = sPrefs.getFloat("$button-X$orientation", 0f)
|
||||
val drawableYPercent = sPrefs.getFloat("$button-Y$orientation", 0f)
|
||||
val drawableXPercent = sPrefs.getFloat("$prefId-X$layout", 0f)
|
||||
val drawableYPercent = sPrefs.getFloat("$prefId-Y$layout", 0f)
|
||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||
val drawableY = (drawableYPercent * max.y + min.y).toInt()
|
||||
val outerScale = 1.66f
|
||||
@@ -1168,7 +1289,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
outerRect,
|
||||
innerRect,
|
||||
joystick,
|
||||
button
|
||||
button,
|
||||
prefId
|
||||
)
|
||||
|
||||
// Need to set the image's position
|
||||
|
||||
+2
-1
@@ -24,7 +24,8 @@ class InputOverlayDrawableButton(
|
||||
res: Resources,
|
||||
defaultStateBitmap: Bitmap,
|
||||
pressedStateBitmap: Bitmap,
|
||||
val buttonId: Int
|
||||
val buttonId: Int,
|
||||
val prefId: String
|
||||
) {
|
||||
// The ID value what motion event is tracking
|
||||
var trackId: Int
|
||||
|
||||
+2
-1
@@ -37,7 +37,8 @@ class InputOverlayDrawableJoystick(
|
||||
rectOuter: Rect,
|
||||
rectInner: Rect,
|
||||
val joystickId: Int,
|
||||
val buttonId: Int
|
||||
val buttonId: Int,
|
||||
val prefId: String
|
||||
) {
|
||||
// The ID value what motion event is tracking
|
||||
var trackId = -1
|
||||
|
||||
@@ -5,35 +5,101 @@ package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import java.util.Locale
|
||||
import kotlin.math.ceil
|
||||
|
||||
class MemoryUtil(val context: Context) {
|
||||
object MemoryUtil {
|
||||
private val context get() = YuzuApplication.appContext
|
||||
|
||||
private val Long.floatForm: String
|
||||
get() = String.format(Locale.ROOT, "%.2f", this.toDouble())
|
||||
private val Float.hundredths: String
|
||||
get() = String.format(Locale.ROOT, "%.2f", this)
|
||||
|
||||
private fun bytesToSizeUnit(size: Long): String {
|
||||
return when {
|
||||
size < Kb -> "${size.floatForm} ${context.getString(R.string.memory_byte)}"
|
||||
size < Mb -> "${(size / Kb).floatForm} ${context.getString(R.string.memory_kilobyte)}"
|
||||
size < Gb -> "${(size / Mb).floatForm} ${context.getString(R.string.memory_megabyte)}"
|
||||
size < Tb -> "${(size / Gb).floatForm} ${context.getString(R.string.memory_gigabyte)}"
|
||||
size < Pb -> "${(size / Tb).floatForm} ${context.getString(R.string.memory_terabyte)}"
|
||||
size < Eb -> "${(size / Pb).floatForm} ${context.getString(R.string.memory_petabyte)}"
|
||||
else -> "${(size / Eb).floatForm} ${context.getString(R.string.memory_exabyte)}"
|
||||
// Required total system memory
|
||||
const val REQUIRED_MEMORY = 8
|
||||
|
||||
const val Kb: Float = 1024F
|
||||
const val Mb = Kb * 1024
|
||||
const val Gb = Mb * 1024
|
||||
const val Tb = Gb * 1024
|
||||
const val Pb = Tb * 1024
|
||||
const val Eb = Pb * 1024
|
||||
|
||||
private fun bytesToSizeUnit(size: Float): String =
|
||||
when {
|
||||
size < Kb -> {
|
||||
context.getString(
|
||||
R.string.memory_formatted,
|
||||
size.hundredths,
|
||||
context.getString(R.string.memory_byte)
|
||||
)
|
||||
}
|
||||
size < Mb -> {
|
||||
context.getString(
|
||||
R.string.memory_formatted,
|
||||
(size / Kb).hundredths,
|
||||
context.getString(R.string.memory_kilobyte)
|
||||
)
|
||||
}
|
||||
size < Gb -> {
|
||||
context.getString(
|
||||
R.string.memory_formatted,
|
||||
(size / Mb).hundredths,
|
||||
context.getString(R.string.memory_megabyte)
|
||||
)
|
||||
}
|
||||
size < Tb -> {
|
||||
context.getString(
|
||||
R.string.memory_formatted,
|
||||
(size / Gb).hundredths,
|
||||
context.getString(R.string.memory_gigabyte)
|
||||
)
|
||||
}
|
||||
size < Pb -> {
|
||||
context.getString(
|
||||
R.string.memory_formatted,
|
||||
(size / Tb).hundredths,
|
||||
context.getString(R.string.memory_terabyte)
|
||||
)
|
||||
}
|
||||
size < Eb -> {
|
||||
context.getString(
|
||||
R.string.memory_formatted,
|
||||
(size / Pb).hundredths,
|
||||
context.getString(R.string.memory_petabyte)
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
context.getString(
|
||||
R.string.memory_formatted,
|
||||
(size / Eb).hundredths,
|
||||
context.getString(R.string.memory_exabyte)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val totalMemory =
|
||||
with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) {
|
||||
// Devices are unlikely to have 0.5GB increments of memory so we'll just round up to account for
|
||||
// the potential error created by memInfo.totalMem
|
||||
private val totalMemory: Float
|
||||
get() {
|
||||
val memInfo = ActivityManager.MemoryInfo()
|
||||
getMemoryInfo(memInfo)
|
||||
memInfo.totalMem
|
||||
with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) {
|
||||
getMemoryInfo(memInfo)
|
||||
}
|
||||
|
||||
return ceil(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
memInfo.advertisedMem.toFloat()
|
||||
} else {
|
||||
memInfo.totalMem.toFloat()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun isLessThan(minimum: Int, size: Long): Boolean {
|
||||
return when (size) {
|
||||
fun isLessThan(minimum: Int, size: Float): Boolean =
|
||||
when (size) {
|
||||
Kb -> totalMemory < Mb && totalMemory < minimum
|
||||
Mb -> totalMemory < Gb && (totalMemory / Mb) < minimum
|
||||
Gb -> totalMemory < Tb && (totalMemory / Gb) < minimum
|
||||
@@ -42,18 +108,6 @@ class MemoryUtil(val context: Context) {
|
||||
Eb -> totalMemory / Eb < minimum
|
||||
else -> totalMemory < Kb && totalMemory < minimum
|
||||
}
|
||||
}
|
||||
|
||||
fun getDeviceRAM(): String {
|
||||
return bytesToSizeUnit(totalMemory)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val Kb: Long = 1024
|
||||
const val Mb = Kb * 1024
|
||||
const val Gb = Mb * 1024
|
||||
const val Tb = Gb * 1024
|
||||
const val Pb = Tb * 1024
|
||||
const val Eb = Pb * 1024
|
||||
}
|
||||
fun getDeviceRAM(): String = bytesToSizeUnit(totalMemory)
|
||||
}
|
||||
|
||||
@@ -150,15 +150,17 @@ void Config::ReadValues() {
|
||||
if (rng_seed_enabled) {
|
||||
Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0));
|
||||
} else {
|
||||
Settings::values.rng_seed.SetValue(std::nullopt);
|
||||
Settings::values.rng_seed.SetValue(0);
|
||||
}
|
||||
Settings::values.rng_seed_enabled.SetValue(rng_seed_enabled);
|
||||
|
||||
const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false);
|
||||
if (custom_rtc_enabled) {
|
||||
Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0);
|
||||
} else {
|
||||
Settings::values.custom_rtc = std::nullopt;
|
||||
Settings::values.custom_rtc = 0;
|
||||
}
|
||||
Settings::values.custom_rtc_enabled = custom_rtc_enabled;
|
||||
|
||||
ReadSetting("System", Settings::values.language_index);
|
||||
ReadSetting("System", Settings::values.region_index);
|
||||
@@ -167,7 +169,7 @@ void Config::ReadValues() {
|
||||
|
||||
// Core
|
||||
ReadSetting("Core", Settings::values.use_multi_core);
|
||||
ReadSetting("Core", Settings::values.use_unsafe_extended_memory_layout);
|
||||
ReadSetting("Core", Settings::values.memory_layout_mode);
|
||||
|
||||
// Cpu
|
||||
ReadSetting("Cpu", Settings::values.cpu_accuracy);
|
||||
@@ -222,14 +224,17 @@ void Config::ReadValues() {
|
||||
ReadSetting("Renderer", Settings::values.bg_blue);
|
||||
|
||||
// Use GPU accuracy normal by default on Android
|
||||
Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger(
|
||||
"Renderer", "gpu_accuracy", static_cast<u32>(Settings::GPUAccuracy::Normal)));
|
||||
Settings::values.gpu_accuracy = static_cast<Settings::GpuAccuracy>(config->GetInteger(
|
||||
"Renderer", "gpu_accuracy", static_cast<u32>(Settings::GpuAccuracy::Normal)));
|
||||
|
||||
// Use GPU default anisotropic filtering on Android
|
||||
Settings::values.max_anisotropy = config->GetInteger("Renderer", "max_anisotropy", 1);
|
||||
Settings::values.max_anisotropy =
|
||||
static_cast<Settings::AnisotropyMode>(config->GetInteger("Renderer", "max_anisotropy", 1));
|
||||
|
||||
// Disable ASTC compute by default on Android
|
||||
Settings::values.accelerate_astc = config->GetBoolean("Renderer", "accelerate_astc", false);
|
||||
Settings::values.accelerate_astc.SetValue(
|
||||
config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu
|
||||
: Settings::AstcDecodeMode::Cpu);
|
||||
|
||||
// Enable asynchronous presentation by default on Android
|
||||
Settings::values.async_presentation =
|
||||
|
||||
@@ -449,7 +449,7 @@ private:
|
||||
loader->ReadTitle(entry.title);
|
||||
loader->ReadIcon(entry.icon);
|
||||
if (loader->GetFileType() == Loader::FileType::NRO) {
|
||||
jauto loader_nro = dynamic_cast<Loader::AppLoader_NRO*>(loader.get());
|
||||
jauto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
|
||||
entry.isHomebrew = loader_nro->IsHomebrew();
|
||||
} else {
|
||||
entry.isHomebrew = false;
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="34.963dp"
|
||||
android:height="37.265dp"
|
||||
android:viewportWidth="34.963"
|
||||
android:viewportHeight="37.265">
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:pathData="M19.451,19.024A3.498,3.498 0,0 0,21.165 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L20.327,16.481L20.327,15.7L20.901,15.7c0.757,0 1.714,-0.392 1.714,-1.302C22.621,13.785 22.224,13.229 21.271,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C23.967,19.27 23.017,20.346 21.165,20.346a3.929,3.929 135,0 1,-1.998 -0.529z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="21.568"
|
||||
android:endY="33.938"
|
||||
android:startX="21.568"
|
||||
android:startY="16.14"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="17.395"
|
||||
android:endY="18.74"
|
||||
android:startX="17.395"
|
||||
android:startY="-1.296"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="17.477"
|
||||
android:centerY="19.92"
|
||||
android:gradientRadius="17.201"
|
||||
android:type="radial">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0.58" />
|
||||
<item
|
||||
android:color="#FFC6C6C6"
|
||||
android:offset="0.84" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.88" />
|
||||
<item
|
||||
android:color="#FFC2C2C2"
|
||||
android:offset="0.91" />
|
||||
<item
|
||||
android:color="#FFB5B5B5"
|
||||
android:offset="0.94" />
|
||||
<item
|
||||
android:color="#FF9E9E9E"
|
||||
android:offset="0.98" />
|
||||
<item
|
||||
android:color="#FF8F8F8F"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:pathData="m12.516,12.729l2,0l0,13.822l6.615,0l0,1.68L12.516,28.231Z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="16.829"
|
||||
android:endY="46.882"
|
||||
android:startX="16.829"
|
||||
android:startY="20.479"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
||||
@@ -0,0 +1,75 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="34.963dp"
|
||||
android:height="37.265dp"
|
||||
android:viewportWidth="34.963"
|
||||
android:viewportHeight="37.265">
|
||||
<path
|
||||
android:fillAlpha="0.3"
|
||||
android:fillColor="#151515"
|
||||
android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z"
|
||||
android:strokeAlpha="0.3" />
|
||||
<path
|
||||
android:fillAlpha="0.6"
|
||||
android:fillColor="#151515"
|
||||
android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z"
|
||||
android:strokeAlpha="0.6" />
|
||||
<path
|
||||
android:fillAlpha="0.6"
|
||||
android:pathData="M19.451,19.024A3.498,3.498 0,0 0,21.165 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L20.327,16.481L20.327,15.7L20.901,15.7c0.757,0 1.714,-0.392 1.714,-1.302C22.621,13.785 22.224,13.229 21.271,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C23.967,19.27 23.017,20.346 21.165,20.346a3.929,3.929 135,0 1,-1.998 -0.529z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="21.568"
|
||||
android:endY="33.938"
|
||||
android:startX="21.568"
|
||||
android:startY="16.14"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillAlpha="0.6"
|
||||
android:pathData="m12.516,12.729l2,0l0,13.822l6.615,0l0,1.68L12.516,28.231Z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="16.829"
|
||||
android:endY="46.882"
|
||||
android:startX="16.829"
|
||||
android:startY="20.479"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
||||
@@ -0,0 +1,128 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="34.963dp"
|
||||
android:height="37.265dp"
|
||||
android:viewportWidth="34.963"
|
||||
android:viewportHeight="37.265">
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:pathData="m10.781,12.65a19.579,19.579 0,0 1,3.596 -0.302c2.003,0 3.294,0.368 4.199,1.185a3.622,3.622 0,0 1,1.14 2.757c0,1.916 -1.206,3.175 -2.733,3.704l0,0.063c1.119,0.386 1.786,1.421 2.117,2.929 0.474,2.024 0.818,3.424 1.119,3.982l-1.924,0c-0.238,-0.407 -0.561,-1.656 -0.968,-3.466 -0.431,-2.003 -1.206,-2.757 -2.91,-2.82l-1.762,0l0,6.286l-1.873,0zM12.654,19.264l1.916,0c2.003,0 3.273,-1.098 3.273,-2.757 0,-1.873 -1.357,-2.691 -3.336,-2.712a7.649,7.649 0,0 0,-1.852 0.172z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="15.506"
|
||||
android:endY="48.977"
|
||||
android:startX="15.506"
|
||||
android:startY="19.659"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="17.395"
|
||||
android:endY="18.74"
|
||||
android:startX="17.395"
|
||||
android:startY="-1.296"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="17.477"
|
||||
android:centerY="19.92"
|
||||
android:gradientRadius="17.201"
|
||||
android:type="radial">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0.58" />
|
||||
<item
|
||||
android:color="#FFC6C6C6"
|
||||
android:offset="0.84" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.88" />
|
||||
<item
|
||||
android:color="#FFC2C2C2"
|
||||
android:offset="0.91" />
|
||||
<item
|
||||
android:color="#FFB5B5B5"
|
||||
android:offset="0.94" />
|
||||
<item
|
||||
android:color="#FF9E9E9E"
|
||||
android:offset="0.98" />
|
||||
<item
|
||||
android:color="#FF8F8F8F"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:pathData="M21.832,19.024A3.498,3.498 0,0 0,23.547 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L22.708,16.481L22.708,15.7L23.282,15.7c0.757,0 1.714,-0.392 1.714,-1.302C25.002,13.785 24.605,13.229 23.652,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C26.349,19.27 25.399,20.346 23.547,20.346a3.929,3.929 135,0 1,-1.998 -0.529z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="23.949"
|
||||
android:endY="33.938"
|
||||
android:startX="23.949"
|
||||
android:startY="16.14"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
||||
@@ -0,0 +1,75 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="34.963dp"
|
||||
android:height="37.265dp"
|
||||
android:viewportWidth="34.963"
|
||||
android:viewportHeight="37.265">
|
||||
<path
|
||||
android:fillAlpha="0.3"
|
||||
android:fillColor="#151515"
|
||||
android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z"
|
||||
android:strokeAlpha="0.3" />
|
||||
<path
|
||||
android:fillAlpha="0.6"
|
||||
android:fillColor="#151515"
|
||||
android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z"
|
||||
android:strokeAlpha="0.6" />
|
||||
<path
|
||||
android:fillAlpha="0.6"
|
||||
android:pathData="m10.781,12.65a19.579,19.579 0,0 1,3.596 -0.302c2.003,0 3.294,0.368 4.199,1.185a3.622,3.622 0,0 1,1.14 2.757c0,1.916 -1.206,3.175 -2.733,3.704l0,0.063c1.119,0.386 1.786,1.421 2.117,2.929 0.474,2.024 0.818,3.424 1.119,3.982l-1.924,0c-0.238,-0.407 -0.561,-1.656 -0.968,-3.466 -0.431,-2.003 -1.206,-2.757 -2.91,-2.82l-1.762,0l0,6.286l-1.873,0zM12.654,19.264l1.916,0c2.003,0 3.273,-1.098 3.273,-2.757 0,-1.873 -1.357,-2.691 -3.336,-2.712a7.649,7.649 0,0 0,-1.852 0.172z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="15.506"
|
||||
android:endY="48.977"
|
||||
android:startX="15.506"
|
||||
android:startY="19.659"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillAlpha="0.6"
|
||||
android:pathData="M21.832,19.024A3.498,3.498 0,0 0,23.547 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L22.708,16.481L22.708,15.7L23.282,15.7c0.757,0 1.714,-0.392 1.714,-1.302C25.002,13.785 24.605,13.229 23.652,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C26.349,19.27 25.399,20.346 23.547,20.346a3.929,3.929 135,0 1,-1.998 -0.529z"
|
||||
android:strokeAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="23.949"
|
||||
android:endY="33.938"
|
||||
android:startX="23.949"
|
||||
android:startY="16.14"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FFC3C4C5"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFC5C6C6"
|
||||
android:offset="0.03" />
|
||||
<item
|
||||
android:color="#FFC7C7C7"
|
||||
android:offset="0.19" />
|
||||
<item
|
||||
android:color="#DBB5B5B5"
|
||||
android:offset="0.44" />
|
||||
<item
|
||||
android:color="#7F878787"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
||||
@@ -235,26 +235,6 @@
|
||||
<string name="region_korea">Korea</string>
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japanisch (日本語)</string>
|
||||
<string name="language_english">Englisch</string>
|
||||
<string name="language_french">Französisch (Français)</string>
|
||||
<string name="langauge_german">Deutsch (German)</string>
|
||||
<string name="language_italian">Italienisch (Italiano)</string>
|
||||
<string name="language_spanish">Spanisch (Español)</string>
|
||||
<string name="language_chinese">Chinesisch (简体中文)</string>
|
||||
<string name="language_korean">Koreanisch (한국어)</string>
|
||||
<string name="language_dutch">Niederländisch (Nederlands)</string>
|
||||
<string name="language_portuguese">Portugiesisch (Português)</string>
|
||||
<string name="language_russian">Russisch (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanesisch (台湾)</string>
|
||||
<string name="language_british_english">Britisches Englisch</string>
|
||||
<string name="language_canadian_french">Kanadisches Französisch (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Lateinamerikanisches Spanisch (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Vereinfachtes Chinesisch (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Traditionelles Chinesisch (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Brasilianisches Portugiesisch (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
<string name="renderer_none">Keiner</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Taiwán</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japonés (日本語)</string>
|
||||
<string name="language_english">Inglés (English)</string>
|
||||
<string name="language_french">Francés (Français)</string>
|
||||
<string name="langauge_german">Alemán (deutsch)</string>
|
||||
<string name="language_italian">Italiano (Italiano)</string>
|
||||
<string name="language_spanish">Español (Español)</string>
|
||||
<string name="language_chinese">Chino (简体中文)</string>
|
||||
<string name="language_korean">Coreano (한국어)</string>
|
||||
<string name="language_dutch">Holandés (nederlands)</string>
|
||||
<string name="language_portuguese">Portugués (Português)</string>
|
||||
<string name="language_russian">Ruso (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanés (台湾)</string>
|
||||
<string name="language_british_english">Inglés británico</string>
|
||||
<string name="language_canadian_french">Francés Canadiense (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Español Latinoamericano (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Chino Simplificado (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Chino tradicional (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Portugués Brasileño (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Taïwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japonais (日本語)</string>
|
||||
<string name="language_english">Anglais</string>
|
||||
<string name="language_french">Français (Français)</string>
|
||||
<string name="langauge_german">Allemand (Deutsch)</string>
|
||||
<string name="language_italian">Italien (Italiano)</string>
|
||||
<string name="language_spanish">Espagnol (Español)</string>
|
||||
<string name="language_chinese">Chinois (简体中文)</string>
|
||||
<string name="language_korean">Coréen (한국어)</string>
|
||||
<string name="language_dutch">Néerlandais (Nederlands)</string>
|
||||
<string name="language_portuguese">Portugais (Português)</string>
|
||||
<string name="language_russian">Russe (Русский)</string>
|
||||
<string name="language_taiwanese">Taïwanais (台湾)</string>
|
||||
<string name="language_british_english">Anglais Britannique</string>
|
||||
<string name="language_canadian_french">Français canadien (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Espagnol latino-américain (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Chinois simplifié (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Chinois Traditionnel (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Portugais brésilien (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Giapponese (日本語)</string>
|
||||
<string name="language_english">Inglese (English)</string>
|
||||
<string name="language_french">Francese (Français)</string>
|
||||
<string name="langauge_german">Tedesco (Deutsch)</string>
|
||||
<string name="language_italian">Italiano (Italiano)</string>
|
||||
<string name="language_spanish">Spagnolo (Español)</string>
|
||||
<string name="language_chinese">Cinese (简体中文)</string>
|
||||
<string name="language_korean">Coreano (한국어)</string>
|
||||
<string name="language_dutch">Olandese (Nederlands)</string>
|
||||
<string name="language_portuguese">Portoghese (Português)</string>
|
||||
<string name="language_russian">Russo (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanese (台湾)</string>
|
||||
<string name="language_british_english">Inglese britannico</string>
|
||||
<string name="language_canadian_french">Francese Canadese (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Spagnolo Latino Americano (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Cinese Semplificato (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Cinese tradizionale (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Portoghese (Português)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -239,24 +239,6 @@
|
||||
<string name="region_taiwan">台湾</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">日本語</string>
|
||||
<string name="language_english">英語</string>
|
||||
<string name="language_french">フランス語 (Français)</string>
|
||||
<string name="langauge_german">ドイツ語 (Deutsch)</string>
|
||||
<string name="language_italian">イタリア語 (Italiano)</string>
|
||||
<string name="language_spanish">スペイン語 (Español)</string>
|
||||
<string name="language_chinese">中国語 (简体中文)</string>
|
||||
<string name="language_korean">韓国語 (한국어)</string>
|
||||
<string name="language_dutch">オランダ語 (Nederlands)</string>
|
||||
<string name="language_portuguese">ポルトガル語 (Português)</string>
|
||||
<string name="language_russian">ロシア語 (Русский)</string>
|
||||
<string name="language_taiwanese">台湾語 (台湾)</string>
|
||||
<string name="language_british_english">イギリス英語</string>
|
||||
<string name="language_canadian_french">フランス語(カナダ) (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">スペイン語(ラテンアメリカ) (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">中国語 (简体中文)</string>
|
||||
<string name="language_traditional_chinese">繁体字中国語 (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">ポルトガル語(ブラジル) (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">타이완</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">일본어 (日本語)</string>
|
||||
<string name="language_english">영어 (English)</string>
|
||||
<string name="language_french">프랑스어 (Français)</string>
|
||||
<string name="langauge_german">독일어(Deutsch)</string>
|
||||
<string name="language_italian">이탈리아어 (Italiano)</string>
|
||||
<string name="language_spanish">스페인어 (Español)</string>
|
||||
<string name="language_chinese">중국어 (简体中文)</string>
|
||||
<string name="language_korean">한국어 (Korean)</string>
|
||||
<string name="language_dutch">네덜란드어 (Nederlands)</string>
|
||||
<string name="language_portuguese">포르투갈어 (Português)</string>
|
||||
<string name="language_russian">러시아어 (Русский)</string>
|
||||
<string name="language_taiwanese">대만어 (台湾)</string>
|
||||
<string name="language_british_english">영어 (British English)</string>
|
||||
<string name="language_canadian_french">캐나다 프랑스어 (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">라틴 아메리카 스페인어 (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">중국어 간체 (简体中文)</string>
|
||||
<string name="language_traditional_chinese">중국어 번체 (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">브라질 포르투갈어 (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">불칸</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japansk (日本語)</string>
|
||||
<string name="language_english">Engelsk</string>
|
||||
<string name="language_french">Fransk (Français)</string>
|
||||
<string name="langauge_german">Tysk (Deutsch)</string>
|
||||
<string name="language_italian">Italiensk (Italiano)</string>
|
||||
<string name="language_spanish">Spansk (Español)</string>
|
||||
<string name="language_chinese">Kinesisk (简体中文)</string>
|
||||
<string name="language_korean">Koreansk (한국어)</string>
|
||||
<string name="language_dutch">Nederlandsk (Nederlands)</string>
|
||||
<string name="language_portuguese">Portugisisk (Português)</string>
|
||||
<string name="language_russian">Russisk (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwansk (台湾)</string>
|
||||
<string name="language_british_english">Britisk Engelsk</string>
|
||||
<string name="language_canadian_french">Kanadisk fransk (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Latinamerikansk spansk (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Forenklet kinesisk (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Tradisjonell Kinesisk (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Brasiliansk portugisisk (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Tajwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japoński (日本語)</string>
|
||||
<string name="language_english">Angielski</string>
|
||||
<string name="language_french">Francuski (Francja)</string>
|
||||
<string name="langauge_german">Niemiecki (Niemcy)</string>
|
||||
<string name="language_italian">Włoski (Włochy)</string>
|
||||
<string name="language_spanish">Hiszpański (Hiszpania)</string>
|
||||
<string name="language_chinese">Chiński (简体中文)</string>
|
||||
<string name="language_korean">Koreański (한국어)</string>
|
||||
<string name="language_dutch">Duński (Holandia)</string>
|
||||
<string name="language_portuguese">Portugalski (Portugalia)</string>
|
||||
<string name="language_russian">Rosyjski (Русский)</string>
|
||||
<string name="language_taiwanese">Tajwański (台湾)</string>
|
||||
<string name="language_british_english">Angielski Brytyjski</string>
|
||||
<string name="language_canadian_french">Francuski (Kanada)</string>
|
||||
<string name="language_latin_american_spanish">Hiszpański (Ameryka Latynoska)</string>
|
||||
<string name="language_simplified_chinese">Chiński uproszczony (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Chiński tradycyjny (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Portugalski (Brazylia)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japônes (日本語)</string>
|
||||
<string name="language_english">Português do Brasil</string>
|
||||
<string name="language_french">Francês (Français)</string>
|
||||
<string name="langauge_german">Alemão (Deutsch)</string>
|
||||
<string name="language_italian">Italiano (Italiano)</string>
|
||||
<string name="language_spanish">Espanhol (Español)</string>
|
||||
<string name="language_chinese">Mandarim (简体中文)</string>
|
||||
<string name="language_korean">Coreano (한국어)</string>
|
||||
<string name="language_dutch">Holandês (Nederlands)</string>
|
||||
<string name="language_portuguese">Português (Português)</string>
|
||||
<string name="language_russian">Russo (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanês (台湾)</string>
|
||||
<string name="language_british_english">Inglês britânico (British English)</string>
|
||||
<string name="language_canadian_french">Fracês Canadiano (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Espanhol da América Latina (Español latino-americano)</string>
|
||||
<string name="language_simplified_chinese">Chinês Simplificado (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Chinês tradicional (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Português do Brasil (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulcano</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japonês (日本語)</string>
|
||||
<string name="language_english">Inglês</string>
|
||||
<string name="language_french">Francês (Français)</string>
|
||||
<string name="langauge_german">Alemão (Deutsch)</string>
|
||||
<string name="language_italian">Italiano (Italiano)</string>
|
||||
<string name="language_spanish">Espanhol (Español)</string>
|
||||
<string name="language_chinese">Chinês simplificado (简体中文)</string>
|
||||
<string name="language_korean">Coreano (한국어)</string>
|
||||
<string name="language_dutch">Holandês (Nederlands)</string>
|
||||
<string name="language_portuguese">Português (Português)</string>
|
||||
<string name="language_russian">Russo (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanês (台湾)</string>
|
||||
<string name="language_british_english">Inglês Britânico</string>
|
||||
<string name="language_canadian_french">Fracês Canadiano (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Espanhol da América Latina (Español latino-americano)</string>
|
||||
<string name="language_simplified_chinese">Chinês Simplificado (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Chinês Tradicional (正 體 中文)</string>
|
||||
<string name="language_brazilian_portuguese">Português do Brasil (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulcano</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Тайвань</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Японский (日本語)</string>
|
||||
<string name="language_english">Английский (English)</string>
|
||||
<string name="language_french">Французский (Français)</string>
|
||||
<string name="langauge_german">Немецкий (Deutsch)</string>
|
||||
<string name="language_italian">Итальянский (Italiano)</string>
|
||||
<string name="language_spanish">Испанский (Español)</string>
|
||||
<string name="language_chinese">Китайский (简体中文)</string>
|
||||
<string name="language_korean">Корейский (한국어)</string>
|
||||
<string name="language_dutch">Голландский (Nederlands)</string>
|
||||
<string name="language_portuguese">Португальский (Português)</string>
|
||||
<string name="language_russian">Русский</string>
|
||||
<string name="language_taiwanese">Тайваньский (台湾)</string>
|
||||
<string name="language_british_english">Британский английский</string>
|
||||
<string name="language_canadian_french">Канадский французский (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Латиноамериканский испанский (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Упрощенный китайский (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Традиционный китайский (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Бразильский португальский (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">Тайвань</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Японська (日本語)</string>
|
||||
<string name="language_english">Англійська (English)</string>
|
||||
<string name="language_french">Французька (Français)</string>
|
||||
<string name="langauge_german">Німецька (Deutsch)</string>
|
||||
<string name="language_italian">Італійська (Italiano)</string>
|
||||
<string name="language_spanish">Іспанська (Español)</string>
|
||||
<string name="language_chinese">Китайскька (简体中文)</string>
|
||||
<string name="language_korean">Корейська (한국어)</string>
|
||||
<string name="language_dutch">Голландська (Nederlands)</string>
|
||||
<string name="language_portuguese">Португальська (Português)</string>
|
||||
<string name="language_russian">Російська (Русский)</string>
|
||||
<string name="language_taiwanese">Тайванська (台湾)</string>
|
||||
<string name="language_british_english">Британська англійська</string>
|
||||
<string name="language_canadian_french">Канадська французька (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Латиноамериканська іспанська (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Спрощена китайська (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Традиційна китайська (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Бразильська португальська (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">中国台湾</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">日语 (日本語)</string>
|
||||
<string name="language_english">英语 (English)</string>
|
||||
<string name="language_french">法语 (Français)</string>
|
||||
<string name="langauge_german">德语 (Deutsch)</string>
|
||||
<string name="language_italian">意大利语 (Italiano)</string>
|
||||
<string name="language_spanish">西班牙语 (Español)</string>
|
||||
<string name="language_chinese">中文 (简体中文)</string>
|
||||
<string name="language_korean">韩语 (한국어)</string>
|
||||
<string name="language_dutch">荷兰语 (Nederlands)</string>
|
||||
<string name="language_portuguese">葡萄牙语 (Português)</string>
|
||||
<string name="language_russian">俄语 (Русский)</string>
|
||||
<string name="language_taiwanese">台湾中文 (台灣)</string>
|
||||
<string name="language_british_english">英式英语</string>
|
||||
<string name="language_canadian_french">加拿大法语 (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">拉丁美洲西班牙语 (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">简体中文 (简体中文)</string>
|
||||
<string name="language_traditional_chinese">繁体中文 (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">巴西葡萄牙语 (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -241,24 +241,6 @@
|
||||
<string name="region_taiwan">台灣</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">日文 (日本語)</string>
|
||||
<string name="language_english">英文</string>
|
||||
<string name="language_french">法文 (Français)</string>
|
||||
<string name="langauge_german">德文 (Deutsch)</string>
|
||||
<string name="language_italian">義大利文 (Italiano)</string>
|
||||
<string name="language_spanish">西班牙文 (Español)</string>
|
||||
<string name="language_chinese">中文 (简体中文)</string>
|
||||
<string name="language_korean">韓文 (한국어)</string>
|
||||
<string name="language_dutch">荷蘭文 (Nederlands)</string>
|
||||
<string name="language_portuguese">葡萄牙文 (Português)</string>
|
||||
<string name="language_russian">俄文 (Русский)</string>
|
||||
<string name="language_taiwanese">台文 (台灣)</string>
|
||||
<string name="language_british_english">英式英文</string>
|
||||
<string name="language_canadian_french">加拿大法文 (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">拉丁美洲西班牙文 (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">簡體中文 (简体中文)</string>
|
||||
<string name="language_traditional_chinese">正體中文 (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">巴西葡萄牙文 (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
|
||||
@@ -205,6 +205,8 @@
|
||||
<item>@string/gamepad_d_pad</item>
|
||||
<item>@string/gamepad_left_stick</item>
|
||||
<item>@string/gamepad_right_stick</item>
|
||||
<item>L3</item>
|
||||
<item>R3</item>
|
||||
<item>@string/gamepad_home</item>
|
||||
<item>@string/gamepad_screenshot</item>
|
||||
</string-array>
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
<integer name="SWITCH_BUTTON_CAPTURE_Y">950</integer>
|
||||
<integer name="SWITCH_BUTTON_DPAD_X">260</integer>
|
||||
<integer name="SWITCH_BUTTON_DPAD_Y">790</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_L_X">870</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_L_Y">400</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_R_X">960</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_R_Y">430</integer>
|
||||
|
||||
<!-- Default SWITCH portrait layout -->
|
||||
<integer name="SWITCH_BUTTON_A_X_PORTRAIT">840</integer>
|
||||
@@ -65,6 +69,10 @@
|
||||
<integer name="SWITCH_BUTTON_CAPTURE_Y_PORTRAIT">950</integer>
|
||||
<integer name="SWITCH_BUTTON_DPAD_X_PORTRAIT">240</integer>
|
||||
<integer name="SWITCH_BUTTON_DPAD_Y_PORTRAIT">840</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_L_X_PORTRAIT">730</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_L_Y_PORTRAIT">510</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_R_X_PORTRAIT">900</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_R_Y_PORTRAIT">540</integer>
|
||||
|
||||
<!-- Default SWITCH foldable layout -->
|
||||
<integer name="SWITCH_BUTTON_A_X_FOLDABLE">840</integer>
|
||||
@@ -97,5 +105,9 @@
|
||||
<integer name="SWITCH_BUTTON_CAPTURE_Y_FOLDABLE">470</integer>
|
||||
<integer name="SWITCH_BUTTON_DPAD_X_FOLDABLE">240</integer>
|
||||
<integer name="SWITCH_BUTTON_DPAD_Y_FOLDABLE">390</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_L_X_FOLDABLE">550</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_L_Y_FOLDABLE">210</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_R_X_FOLDABLE">550</integer>
|
||||
<integer name="SWITCH_BUTTON_STICK_R_Y_FOLDABLE">280</integer>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -113,6 +113,8 @@
|
||||
<string name="install_game_content_success_install">%1$d installed successfully</string>
|
||||
<string name="install_game_content_success_overwrite">%1$d overwritten successfully</string>
|
||||
<string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
|
||||
<string name="custom_driver_not_supported">Custom drivers not supported</string>
|
||||
<string name="custom_driver_not_supported_description">Custom driver loading isn\'t currently supported for this device.\nCheck this option again in the future to see if support was added!</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">Gaia isn\'t real</string>
|
||||
@@ -230,7 +232,7 @@
|
||||
|
||||
<!-- ROM loading errors -->
|
||||
<string name="loader_error_encrypted">Your ROM is encrypted</string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[Please follow the guides to redump your <a href="https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games">game cartidges</a> or <a href="https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop">installed titles</a>.]]></string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[Please follow the guides to redump your <a href="https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards">game cartidges</a> or <a href="https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop">installed titles</a>.]]></string>
|
||||
<string name="loader_error_encrypted_keys_description"><![CDATA[Please ensure your <a href="https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys">prod.keys</a> file is installed so that games can be decrypted.]]></string>
|
||||
<string name="loader_error_video_core">An error occurred initializing the video core</string>
|
||||
<string name="loader_error_video_core_description">This is usually caused by an incompatible GPU driver. Installing a custom GPU driver may resolve this problem.</string>
|
||||
@@ -273,6 +275,7 @@
|
||||
<string name="fatal_error_message">A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs.</string>
|
||||
<string name="performance_warning">Turning off this setting will significantly reduce emulation performance! For the best experience, it is recommended that you leave this setting enabled.</string>
|
||||
<string name="device_memory_inadequate">Device RAM: %1$s\nRecommended: %2$s</string>
|
||||
<string name="memory_formatted">%1$s %2$s</string>
|
||||
|
||||
<!-- Region Names -->
|
||||
<string name="region_japan">Japan</string>
|
||||
@@ -284,24 +287,24 @@
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japanese (日本語)</string>
|
||||
<string name="language_english">English</string>
|
||||
<string name="language_french">French (Français)</string>
|
||||
<string name="langauge_german">German (Deutsch)</string>
|
||||
<string name="language_italian">Italian (Italiano)</string>
|
||||
<string name="language_spanish">Spanish (Español)</string>
|
||||
<string name="language_chinese">Chinese (简体中文)</string>
|
||||
<string name="language_korean">Korean (한국어)</string>
|
||||
<string name="language_dutch">Dutch (Nederlands)</string>
|
||||
<string name="language_portuguese">Portuguese (Português)</string>
|
||||
<string name="language_russian">Russian (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanese (台湾)</string>
|
||||
<string name="language_british_english">British English</string>
|
||||
<string name="language_canadian_french">Canadian French (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Latin American Spanish (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Simplified Chinese (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Traditional Chinese (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Brazilian Portuguese (Português do Brasil)</string>
|
||||
<string name="language_japanese" translatable="false">日本語</string>
|
||||
<string name="language_english" translatable="false">English</string>
|
||||
<string name="language_french" translatable="false">Français</string>
|
||||
<string name="langauge_german" translatable="false">Deutsch</string>
|
||||
<string name="language_italian" translatable="false">Italiano</string>
|
||||
<string name="language_spanish" translatable="false">Español</string>
|
||||
<string name="language_chinese" translatable="false">简体中文</string>
|
||||
<string name="language_korean" translatable="false">한국어</string>
|
||||
<string name="language_dutch" translatable="false">Nederlands</string>
|
||||
<string name="language_portuguese" translatable="false">Português</string>
|
||||
<string name="language_russian" translatable="false">Русский</string>
|
||||
<string name="language_taiwanese" translatable="false">台湾</string>
|
||||
<string name="language_british_english" translatable="false">British English</string>
|
||||
<string name="language_canadian_french" translatable="false">Français canadien</string>
|
||||
<string name="language_latin_american_spanish" translatable="false">Español latinoamericano</string>
|
||||
<string name="language_simplified_chinese" translatable="false">简体中文</string>
|
||||
<string name="language_traditional_chinese" translatable="false">正體中文</string>
|
||||
<string name="language_brazilian_portuguese" translatable="false">Português do Brasil</string>
|
||||
|
||||
<!-- Memory Sizes -->
|
||||
<string name="memory_byte">Byte</string>
|
||||
|
||||
@@ -32,16 +32,16 @@ struct AudioRendererParameterInternal {
|
||||
/* 0x14 */ u32 sinks;
|
||||
/* 0x18 */ u32 effects;
|
||||
/* 0x1C */ u32 perf_frames;
|
||||
/* 0x20 */ u16 voice_drop_enabled;
|
||||
/* 0x20 */ u8 voice_drop_enabled;
|
||||
/* 0x21 */ u8 unk_21;
|
||||
/* 0x22 */ u8 rendering_device;
|
||||
/* 0x23 */ ExecutionMode execution_mode;
|
||||
/* 0x24 */ u32 splitter_infos;
|
||||
/* 0x28 */ s32 splitter_destinations;
|
||||
/* 0x2C */ u32 external_context_size;
|
||||
/* 0x30 */ u32 revision;
|
||||
/* 0x34 */ char unk34[0x4];
|
||||
};
|
||||
static_assert(sizeof(AudioRendererParameterInternal) == 0x38,
|
||||
static_assert(sizeof(AudioRendererParameterInternal) == 0x34,
|
||||
"AudioRendererParameterInternal has the wrong size!");
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,9 +92,9 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) {
|
||||
if (type == Sink::StreamType::In) {
|
||||
stream->AppendBuffer(new_buffer, tmp_samples);
|
||||
} else {
|
||||
system.ApplicationMemory().ReadBlockUnsafe(buffer.samples, tmp_samples.data(),
|
||||
buffer.size);
|
||||
stream->AppendBuffer(new_buffer, tmp_samples);
|
||||
Core::Memory::CpuGuestMemory<s16, Core::Memory::GuestMemoryFlags::UnsafeRead> samples(
|
||||
system.ApplicationMemory(), buffer.samples, buffer.size / sizeof(s16));
|
||||
stream->AppendBuffer(new_buffer, samples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ constexpr std::array<u8, 3> PitchBySrcQuality = {4, 8, 4};
|
||||
template <typename T>
|
||||
static u32 DecodePcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
const DecodeArg& req) {
|
||||
std::array<T, TempBufferSize> tmp_samples{};
|
||||
constexpr s32 min{std::numeric_limits<s16>::min()};
|
||||
constexpr s32 max{std::numeric_limits<s16>::max()};
|
||||
|
||||
@@ -49,19 +48,18 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
const VAddr source{req.buffer +
|
||||
(((req.start_offset + req.offset) * channel_count) * sizeof(T))};
|
||||
const u64 size{channel_count * samples_to_decode};
|
||||
const u64 size_bytes{size * sizeof(T)};
|
||||
|
||||
memory.ReadBlockUnsafe(source, tmp_samples.data(), size_bytes);
|
||||
|
||||
Core::Memory::CpuGuestMemory<T, Core::Memory::GuestMemoryFlags::UnsafeRead> samples(
|
||||
memory, source, size);
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
for (u32 i = 0; i < samples_to_decode; i++) {
|
||||
auto sample{static_cast<s32>(tmp_samples[i * channel_count + req.target_channel] *
|
||||
auto sample{static_cast<s32>(samples[i * channel_count + req.target_channel] *
|
||||
std::numeric_limits<s16>::max())};
|
||||
out_buffer[i] = static_cast<s16>(std::clamp(sample, min, max));
|
||||
}
|
||||
} else {
|
||||
for (u32 i = 0; i < samples_to_decode; i++) {
|
||||
out_buffer[i] = tmp_samples[i * channel_count + req.target_channel];
|
||||
out_buffer[i] = samples[i * channel_count + req.target_channel];
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -74,16 +72,17 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
}
|
||||
|
||||
const VAddr source{req.buffer + ((req.start_offset + req.offset) * sizeof(T))};
|
||||
memory.ReadBlockUnsafe(source, tmp_samples.data(), samples_to_decode * sizeof(T));
|
||||
Core::Memory::CpuGuestMemory<T, Core::Memory::GuestMemoryFlags::UnsafeRead> samples(
|
||||
memory, source, samples_to_decode);
|
||||
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
for (u32 i = 0; i < samples_to_decode; i++) {
|
||||
auto sample{static_cast<s32>(tmp_samples[i * channel_count + req.target_channel] *
|
||||
auto sample{static_cast<s32>(samples[i * channel_count + req.target_channel] *
|
||||
std::numeric_limits<s16>::max())};
|
||||
out_buffer[i] = static_cast<s16>(std::clamp(sample, min, max));
|
||||
}
|
||||
} else {
|
||||
std::memcpy(out_buffer.data(), tmp_samples.data(), samples_to_decode * sizeof(s16));
|
||||
std::memcpy(out_buffer.data(), samples.data(), samples_to_decode * sizeof(s16));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -101,7 +100,6 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
*/
|
||||
static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
const DecodeArg& req) {
|
||||
std::array<u8, TempBufferSize> wavebuffer{};
|
||||
constexpr u32 SamplesPerFrame{14};
|
||||
constexpr u32 NibblesPerFrame{16};
|
||||
|
||||
@@ -139,7 +137,8 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
}
|
||||
|
||||
const auto size{std::max((samples_to_process / 8U) * SamplesPerFrame, 8U)};
|
||||
memory.ReadBlockUnsafe(req.buffer + position_in_frame / 2, wavebuffer.data(), size);
|
||||
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> wavebuffer(
|
||||
memory, req.buffer + position_in_frame / 2, size);
|
||||
|
||||
auto context{req.adpcm_context};
|
||||
auto header{context->header};
|
||||
|
||||
@@ -21,23 +21,13 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
|
||||
}
|
||||
|
||||
AuxInfo::AuxInfoDsp info{};
|
||||
auto info_ptr{&info};
|
||||
bool host_safe{(aux_info & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp))};
|
||||
memory.ReadBlockUnsafe(aux_info, &info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
|
||||
if (host_safe) [[likely]] {
|
||||
info_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(aux_info);
|
||||
} else {
|
||||
memory.ReadBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
info.read_offset = 0;
|
||||
info.write_offset = 0;
|
||||
info.total_sample_count = 0;
|
||||
|
||||
info_ptr->read_offset = 0;
|
||||
info_ptr->write_offset = 0;
|
||||
info_ptr->total_sample_count = 0;
|
||||
|
||||
if (!host_safe) [[unlikely]] {
|
||||
memory.WriteBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
memory.WriteBlockUnsafe(aux_info, &info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,17 +76,9 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
|
||||
}
|
||||
|
||||
AuxInfo::AuxInfoDsp send_info{};
|
||||
auto send_ptr = &send_info;
|
||||
bool host_safe = (send_info_ & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
|
||||
memory.ReadBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
|
||||
if (host_safe) [[likely]] {
|
||||
send_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(send_info_);
|
||||
} else {
|
||||
memory.ReadBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
|
||||
u32 target_write_offset{send_ptr->write_offset + write_offset};
|
||||
u32 target_write_offset{send_info.write_offset + write_offset};
|
||||
if (target_write_offset > count_max) {
|
||||
return 0;
|
||||
}
|
||||
@@ -105,15 +87,9 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
|
||||
u32 read_pos{0};
|
||||
while (write_count > 0) {
|
||||
u32 to_write{std::min(count_max - target_write_offset, write_count)};
|
||||
const auto write_addr = send_buffer + target_write_offset * sizeof(s32);
|
||||
bool write_safe{(write_addr & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - (write_addr + to_write * sizeof(s32)))};
|
||||
if (write_safe) [[likely]] {
|
||||
auto ptr = memory.GetPointer(write_addr);
|
||||
std::memcpy(ptr, &input[read_pos], to_write * sizeof(s32));
|
||||
} else {
|
||||
memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32),
|
||||
&input[read_pos], to_write * sizeof(s32));
|
||||
if (to_write > 0) {
|
||||
const auto write_addr = send_buffer + target_write_offset * sizeof(s32);
|
||||
memory.WriteBlockUnsafe(write_addr, &input[read_pos], to_write * sizeof(s32));
|
||||
}
|
||||
target_write_offset = (target_write_offset + to_write) % count_max;
|
||||
write_count -= to_write;
|
||||
@@ -121,13 +97,10 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
|
||||
}
|
||||
|
||||
if (update_count) {
|
||||
send_ptr->write_offset = (send_ptr->write_offset + update_count) % count_max;
|
||||
}
|
||||
|
||||
if (!host_safe) [[unlikely]] {
|
||||
memory.WriteBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
send_info.write_offset = (send_info.write_offset + update_count) % count_max;
|
||||
}
|
||||
|
||||
memory.WriteBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
return write_count_;
|
||||
}
|
||||
|
||||
@@ -174,17 +147,9 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
|
||||
}
|
||||
|
||||
AuxInfo::AuxInfoDsp return_info{};
|
||||
auto return_ptr = &return_info;
|
||||
bool host_safe = (return_info_ & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
|
||||
memory.ReadBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
|
||||
if (host_safe) [[likely]] {
|
||||
return_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(return_info_);
|
||||
} else {
|
||||
memory.ReadBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
|
||||
u32 target_read_offset{return_ptr->read_offset + read_offset};
|
||||
u32 target_read_offset{return_info.read_offset + read_offset};
|
||||
if (target_read_offset > count_max) {
|
||||
return 0;
|
||||
}
|
||||
@@ -193,15 +158,9 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
|
||||
u32 write_pos{0};
|
||||
while (read_count > 0) {
|
||||
u32 to_read{std::min(count_max - target_read_offset, read_count)};
|
||||
const auto read_addr = return_buffer + target_read_offset * sizeof(s32);
|
||||
bool read_safe{(read_addr & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - (read_addr + to_read * sizeof(s32)))};
|
||||
if (read_safe) [[likely]] {
|
||||
auto ptr = memory.GetPointer(read_addr);
|
||||
std::memcpy(&output[write_pos], ptr, to_read * sizeof(s32));
|
||||
} else {
|
||||
memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32),
|
||||
&output[write_pos], to_read * sizeof(s32));
|
||||
if (to_read > 0) {
|
||||
const auto read_addr = return_buffer + target_read_offset * sizeof(s32);
|
||||
memory.ReadBlockUnsafe(read_addr, &output[write_pos], to_read * sizeof(s32));
|
||||
}
|
||||
target_read_offset = (target_read_offset + to_read) % count_max;
|
||||
read_count -= to_read;
|
||||
@@ -209,13 +168,10 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
|
||||
}
|
||||
|
||||
if (update_count) {
|
||||
return_ptr->read_offset = (return_ptr->read_offset + update_count) % count_max;
|
||||
}
|
||||
|
||||
if (!host_safe) [[unlikely]] {
|
||||
memory.WriteBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
return_info.read_offset = (return_info.read_offset + update_count) % count_max;
|
||||
}
|
||||
|
||||
memory.WriteBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
return read_count_;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#endif
|
||||
#include "audio_core/sink/null_sink.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings_enums.h"
|
||||
|
||||
namespace AudioCore::Sink {
|
||||
namespace {
|
||||
@@ -24,7 +25,7 @@ struct SinkDetails {
|
||||
using LatencyFn = u32 (*)();
|
||||
|
||||
/// Name for this sink.
|
||||
std::string_view id;
|
||||
Settings::AudioEngine id;
|
||||
/// A method to call to construct an instance of this type of sink.
|
||||
FactoryFn factory;
|
||||
/// A method to call to list available devices.
|
||||
@@ -37,7 +38,7 @@ struct SinkDetails {
|
||||
constexpr SinkDetails sink_details[] = {
|
||||
#ifdef HAVE_CUBEB
|
||||
SinkDetails{
|
||||
"cubeb",
|
||||
Settings::AudioEngine::Cubeb,
|
||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||
return std::make_unique<CubebSink>(device_id);
|
||||
},
|
||||
@@ -47,7 +48,7 @@ constexpr SinkDetails sink_details[] = {
|
||||
#endif
|
||||
#ifdef HAVE_SDL2
|
||||
SinkDetails{
|
||||
"sdl2",
|
||||
Settings::AudioEngine::Sdl2,
|
||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||
return std::make_unique<SDLSink>(device_id);
|
||||
},
|
||||
@@ -55,46 +56,47 @@ constexpr SinkDetails sink_details[] = {
|
||||
&GetSDLLatency,
|
||||
},
|
||||
#endif
|
||||
SinkDetails{"null",
|
||||
SinkDetails{Settings::AudioEngine::Null,
|
||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||
return std::make_unique<NullSink>(device_id);
|
||||
},
|
||||
[](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }},
|
||||
};
|
||||
|
||||
const SinkDetails& GetOutputSinkDetails(std::string_view sink_id) {
|
||||
const auto find_backend{[](std::string_view id) {
|
||||
const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
|
||||
const auto find_backend{[](Settings::AudioEngine id) {
|
||||
return std::find_if(std::begin(sink_details), std::end(sink_details),
|
||||
[&id](const auto& sink_detail) { return sink_detail.id == id; });
|
||||
}};
|
||||
|
||||
auto iter = find_backend(sink_id);
|
||||
|
||||
if (sink_id == "auto") {
|
||||
if (sink_id == Settings::AudioEngine::Auto) {
|
||||
// Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which
|
||||
// causes audio issues, in that case go with SDL.
|
||||
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
|
||||
iter = find_backend("cubeb");
|
||||
iter = find_backend(Settings::AudioEngine::Cubeb);
|
||||
if (iter->latency() > TargetSampleCount * 3) {
|
||||
iter = find_backend("sdl2");
|
||||
iter = find_backend(Settings::AudioEngine::Sdl2);
|
||||
}
|
||||
#else
|
||||
iter = std::begin(sink_details);
|
||||
#endif
|
||||
LOG_INFO(Service_Audio, "Auto-selecting the {} backend", iter->id);
|
||||
LOG_INFO(Service_Audio, "Auto-selecting the {} backend",
|
||||
Settings::CanonicalizeEnum(iter->id));
|
||||
}
|
||||
|
||||
if (iter == std::end(sink_details)) {
|
||||
LOG_ERROR(Audio, "Invalid sink_id {}", sink_id);
|
||||
iter = find_backend("null");
|
||||
LOG_ERROR(Audio, "Invalid sink_id {}", Settings::CanonicalizeEnum(sink_id));
|
||||
iter = find_backend(Settings::AudioEngine::Null);
|
||||
}
|
||||
|
||||
return *iter;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
std::vector<std::string_view> GetSinkIDs() {
|
||||
std::vector<std::string_view> sink_ids(std::size(sink_details));
|
||||
std::vector<Settings::AudioEngine> GetSinkIDs() {
|
||||
std::vector<Settings::AudioEngine> sink_ids(std::size(sink_details));
|
||||
|
||||
std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids),
|
||||
[](const auto& sink) { return sink.id; });
|
||||
@@ -102,11 +104,11 @@ std::vector<std::string_view> GetSinkIDs() {
|
||||
return sink_ids;
|
||||
}
|
||||
|
||||
std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool capture) {
|
||||
std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, bool capture) {
|
||||
return GetOutputSinkDetails(sink_id).list_devices(capture);
|
||||
}
|
||||
|
||||
std::unique_ptr<Sink> CreateSinkFromID(std::string_view sink_id, std::string_view device_id) {
|
||||
std::unique_ptr<Sink> CreateSinkFromID(Settings::AudioEngine sink_id, std::string_view device_id) {
|
||||
return GetOutputSinkDetails(sink_id).factory(device_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "common/settings_enums.h"
|
||||
|
||||
namespace AudioCore {
|
||||
class AudioManager;
|
||||
@@ -19,7 +21,7 @@ class Sink;
|
||||
*
|
||||
* @return Vector of available sink names.
|
||||
*/
|
||||
std::vector<std::string_view> GetSinkIDs();
|
||||
std::vector<Settings::AudioEngine> GetSinkIDs();
|
||||
|
||||
/**
|
||||
* Gets the list of devices for a particular sink identified by the given ID.
|
||||
@@ -28,7 +30,7 @@ std::vector<std::string_view> GetSinkIDs();
|
||||
* @param capture - Get capture (input) devices, or output devices?
|
||||
* @return Vector of device names.
|
||||
*/
|
||||
std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool capture);
|
||||
std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, bool capture);
|
||||
|
||||
/**
|
||||
* Creates an audio sink identified by the given device ID.
|
||||
@@ -37,7 +39,7 @@ std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool cap
|
||||
* @param device_id - Name of the device to create.
|
||||
* @return Pointer to the created sink.
|
||||
*/
|
||||
std::unique_ptr<Sink> CreateSinkFromID(std::string_view sink_id, std::string_view device_id);
|
||||
std::unique_ptr<Sink> CreateSinkFromID(Settings::AudioEngine sink_id, std::string_view device_id);
|
||||
|
||||
} // namespace Sink
|
||||
} // namespace AudioCore
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "audio_core/sink/sink_stream.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/fixed_point.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
@@ -19,9 +20,12 @@
|
||||
namespace AudioCore::Sink {
|
||||
|
||||
void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
|
||||
if (type == StreamType::In) {
|
||||
SCOPE_EXIT({
|
||||
queue.enqueue(buffer);
|
||||
queued_buffers++;
|
||||
++queued_buffers;
|
||||
});
|
||||
|
||||
if (type == StreamType::In) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,16 +70,17 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
|
||||
static_cast<s16>(std::clamp(right_sample, min, max));
|
||||
}
|
||||
|
||||
samples = samples.subspan(0, samples.size() / system_channels * device_channels);
|
||||
samples_buffer.Push(samples.subspan(0, samples.size() / system_channels * device_channels));
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (system_channels == 2 && device_channels == 6) {
|
||||
if (system_channels == 2 && device_channels == 6) {
|
||||
// We need moar samples! Not all games will provide 6 channel audio.
|
||||
// TODO: Implement some upmixing here. Currently just passthrough, with other
|
||||
// channels left as silence.
|
||||
auto new_size = samples.size() / system_channels * device_channels;
|
||||
tmp_samples.resize_destructive(new_size);
|
||||
std::vector<s16> new_samples(samples.size() / system_channels * device_channels);
|
||||
|
||||
for (u32 read_index = 0, write_index = 0; read_index < new_size;
|
||||
for (u32 read_index = 0, write_index = 0; read_index < samples.size();
|
||||
read_index += system_channels, write_index += device_channels) {
|
||||
const auto left_sample{static_cast<s16>(std::clamp(
|
||||
static_cast<s32>(
|
||||
@@ -83,7 +88,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
|
||||
volume),
|
||||
min, max))};
|
||||
|
||||
tmp_samples[write_index + static_cast<u32>(Channels::FrontLeft)] = left_sample;
|
||||
new_samples[write_index + static_cast<u32>(Channels::FrontLeft)] = left_sample;
|
||||
|
||||
const auto right_sample{static_cast<s16>(std::clamp(
|
||||
static_cast<s32>(
|
||||
@@ -91,20 +96,21 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
|
||||
volume),
|
||||
min, max))};
|
||||
|
||||
tmp_samples[write_index + static_cast<u32>(Channels::FrontRight)] = right_sample;
|
||||
new_samples[write_index + static_cast<u32>(Channels::FrontRight)] = right_sample;
|
||||
}
|
||||
samples = std::span<s16>(tmp_samples);
|
||||
|
||||
} else if (volume != 1.0f) {
|
||||
for (u32 i = 0; i < samples.size(); i++) {
|
||||
samples_buffer.Push(new_samples);
|
||||
return;
|
||||
}
|
||||
|
||||
if (volume != 1.0f) {
|
||||
for (u32 i = 0; i < samples.size(); ++i) {
|
||||
samples[i] = static_cast<s16>(
|
||||
std::clamp(static_cast<s32>(static_cast<f32>(samples[i]) * volume), min, max));
|
||||
}
|
||||
}
|
||||
|
||||
samples_buffer.Push(samples);
|
||||
queue.enqueue(buffer);
|
||||
queued_buffers++;
|
||||
}
|
||||
|
||||
std::vector<s16> SinkStream::ReleaseBuffer(u64 num_samples) {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "common/polyfill_thread.h"
|
||||
#include "common/reader_writer_queue.h"
|
||||
#include "common/ring_buffer.h"
|
||||
#include "common/scratch_buffer.h"
|
||||
#include "common/thread.h"
|
||||
|
||||
namespace Core {
|
||||
@@ -256,8 +255,6 @@ private:
|
||||
/// Signalled when ring buffer entries are consumed
|
||||
std::condition_variable_any release_cv;
|
||||
std::mutex release_mutex;
|
||||
/// Temporary buffer for appending samples when upmixing
|
||||
Common::ScratchBuffer<s16> tmp_samples{};
|
||||
};
|
||||
|
||||
using SinkStreamPtr = std::unique_ptr<SinkStream>;
|
||||
|
||||
@@ -110,8 +110,12 @@ add_library(common STATIC
|
||||
scratch_buffer.h
|
||||
settings.cpp
|
||||
settings.h
|
||||
settings_common.cpp
|
||||
settings_common.h
|
||||
settings_enums.h
|
||||
settings_input.cpp
|
||||
settings_input.h
|
||||
settings_setting.h
|
||||
socket_types.h
|
||||
spin_lock.cpp
|
||||
spin_lock.h
|
||||
@@ -193,9 +197,16 @@ if (MSVC)
|
||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||
)
|
||||
else()
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
target_compile_options(common PRIVATE
|
||||
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>
|
||||
-fsized-deallocation
|
||||
-Werror=unreachable-code-aggressive
|
||||
)
|
||||
target_compile_definitions(common PRIVATE
|
||||
# Clang 14 and earlier have errors when explicitly instantiating Settings::Setting
|
||||
$<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,15>:CANNOT_EXPLICITLY_INSTANTIATE>
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ std::string DemangleSymbol(const std::string& mangled) {
|
||||
SCOPE_EXIT({ std::free(demangled); });
|
||||
|
||||
if (is_itanium(mangled)) {
|
||||
demangled = llvm::itaniumDemangle(mangled.c_str(), nullptr, nullptr, nullptr);
|
||||
demangled = llvm::itaniumDemangle(mangled.c_str());
|
||||
}
|
||||
|
||||
if (!demangled) {
|
||||
|
||||
@@ -30,8 +30,8 @@ DetachedTasks::~DetachedTasks() {
|
||||
void DetachedTasks::AddTask(std::function<void()> task) {
|
||||
std::unique_lock lock{instance->mutex};
|
||||
++instance->count;
|
||||
std::thread([task{std::move(task)}]() {
|
||||
task();
|
||||
std::thread([task_{std::move(task)}]() {
|
||||
task_();
|
||||
std::unique_lock thread_lock{instance->mutex};
|
||||
--instance->count;
|
||||
std::notify_all_at_thread_exit(instance->cv, std::move(thread_lock));
|
||||
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
|
||||
using namespace Common::Literals;
|
||||
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
|
||||
const auto write_limit = Settings::values.extended_logging ? 1_GiB : 100_MiB;
|
||||
const auto write_limit = Settings::values.extended_logging.GetValue() ? 1_GiB : 100_MiB;
|
||||
const bool write_limit_exceeded = bytes_written > write_limit;
|
||||
if (entry.log_level >= Level::Error || write_limit_exceeded) {
|
||||
if (write_limit_exceeded) {
|
||||
|
||||
@@ -66,6 +66,7 @@ void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page
|
||||
<< (address_space_width_in_bits - page_size_in_bits)};
|
||||
pointers.resize(num_page_table_entries);
|
||||
backing_addr.resize(num_page_table_entries);
|
||||
blocks.resize(num_page_table_entries);
|
||||
current_address_space_width_in_bits = address_space_width_in_bits;
|
||||
page_size = 1ULL << page_size_in_bits;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ struct PageTable {
|
||||
class PageInfo {
|
||||
public:
|
||||
/// Returns the page pointer
|
||||
[[nodiscard]] u8* Pointer() const noexcept {
|
||||
[[nodiscard]] uintptr_t Pointer() const noexcept {
|
||||
return ExtractPointer(raw.load(std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ struct PageTable {
|
||||
}
|
||||
|
||||
/// Returns the page pointer and attribute pair, extracted from the same atomic read
|
||||
[[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept {
|
||||
[[nodiscard]] std::pair<uintptr_t, PageType> PointerType() const noexcept {
|
||||
const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed);
|
||||
return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)};
|
||||
}
|
||||
@@ -73,13 +73,13 @@ struct PageTable {
|
||||
}
|
||||
|
||||
/// Write a page pointer and type pair atomically
|
||||
void Store(u8* pointer, PageType type) noexcept {
|
||||
raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type));
|
||||
void Store(uintptr_t pointer, PageType type) noexcept {
|
||||
raw.store(pointer | static_cast<uintptr_t>(type));
|
||||
}
|
||||
|
||||
/// Unpack a pointer from a page info raw representation
|
||||
[[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept {
|
||||
return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS));
|
||||
[[nodiscard]] static uintptr_t ExtractPointer(uintptr_t raw) noexcept {
|
||||
return raw & (~uintptr_t{0} << ATTRIBUTE_BITS);
|
||||
}
|
||||
|
||||
/// Unpack a page type from a page info raw representation
|
||||
@@ -122,6 +122,7 @@ struct PageTable {
|
||||
* corresponding attribute element is of type `Memory`.
|
||||
*/
|
||||
VirtualBuffer<PageInfo> pointers;
|
||||
VirtualBuffer<u64> blocks;
|
||||
|
||||
VirtualBuffer<u64> backing_addr;
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
return push_count;
|
||||
}
|
||||
|
||||
std::size_t Push(const std::span<T> input) {
|
||||
std::size_t Push(std::span<const T> input) {
|
||||
return Push(input.data(), input.size());
|
||||
}
|
||||
|
||||
|
||||
+41
-22
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "common/concepts.h"
|
||||
#include "common/make_unique_for_overwrite.h"
|
||||
|
||||
namespace Common {
|
||||
@@ -19,27 +18,47 @@ namespace Common {
|
||||
template <typename T>
|
||||
class ScratchBuffer {
|
||||
public:
|
||||
using iterator = T*;
|
||||
using const_iterator = const T*;
|
||||
using value_type = T;
|
||||
using element_type = T;
|
||||
using iterator_category = std::contiguous_iterator_tag;
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using iterator_concept = std::contiguous_iterator_tag;
|
||||
|
||||
ScratchBuffer() = default;
|
||||
|
||||
explicit ScratchBuffer(size_t initial_capacity)
|
||||
explicit ScratchBuffer(size_type initial_capacity)
|
||||
: last_requested_size{initial_capacity}, buffer_capacity{initial_capacity},
|
||||
buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
|
||||
|
||||
~ScratchBuffer() = default;
|
||||
ScratchBuffer(const ScratchBuffer&) = delete;
|
||||
ScratchBuffer& operator=(const ScratchBuffer&) = delete;
|
||||
ScratchBuffer(ScratchBuffer&&) = default;
|
||||
ScratchBuffer& operator=(ScratchBuffer&&) = default;
|
||||
|
||||
ScratchBuffer(ScratchBuffer&& other) noexcept {
|
||||
swap(other);
|
||||
other.last_requested_size = 0;
|
||||
other.buffer_capacity = 0;
|
||||
other.buffer.reset();
|
||||
}
|
||||
|
||||
ScratchBuffer& operator=(ScratchBuffer&& other) noexcept {
|
||||
swap(other);
|
||||
other.last_requested_size = 0;
|
||||
other.buffer_capacity = 0;
|
||||
other.buffer.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// This will only grow the buffer's capacity if size is greater than the current capacity.
|
||||
/// The previously held data will remain intact.
|
||||
void resize(size_t size) {
|
||||
void resize(size_type size) {
|
||||
if (size > buffer_capacity) {
|
||||
auto new_buffer = Common::make_unique_for_overwrite<T[]>(size);
|
||||
std::move(buffer.get(), buffer.get() + buffer_capacity, new_buffer.get());
|
||||
@@ -51,7 +70,7 @@ public:
|
||||
|
||||
/// This will only grow the buffer's capacity if size is greater than the current capacity.
|
||||
/// The previously held data will be destroyed if a reallocation occurs.
|
||||
void resize_destructive(size_t size) {
|
||||
void resize_destructive(size_type size) {
|
||||
if (size > buffer_capacity) {
|
||||
buffer_capacity = size;
|
||||
buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity);
|
||||
@@ -59,43 +78,43 @@ public:
|
||||
last_requested_size = size;
|
||||
}
|
||||
|
||||
[[nodiscard]] T* data() noexcept {
|
||||
[[nodiscard]] pointer data() noexcept {
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* data() const noexcept {
|
||||
[[nodiscard]] const_pointer data() const noexcept {
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] T* begin() noexcept {
|
||||
[[nodiscard]] iterator begin() noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* begin() const noexcept {
|
||||
[[nodiscard]] const_iterator begin() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
[[nodiscard]] T* end() noexcept {
|
||||
[[nodiscard]] iterator end() noexcept {
|
||||
return data() + last_requested_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* end() const noexcept {
|
||||
[[nodiscard]] const_iterator end() const noexcept {
|
||||
return data() + last_requested_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] T& operator[](size_t i) {
|
||||
[[nodiscard]] reference operator[](size_type i) {
|
||||
return buffer[i];
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& operator[](size_t i) const {
|
||||
[[nodiscard]] const_reference operator[](size_type i) const {
|
||||
return buffer[i];
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t size() const noexcept {
|
||||
[[nodiscard]] size_type size() const noexcept {
|
||||
return last_requested_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t capacity() const noexcept {
|
||||
[[nodiscard]] size_type capacity() const noexcept {
|
||||
return buffer_capacity;
|
||||
}
|
||||
|
||||
@@ -106,8 +125,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
size_t last_requested_size{};
|
||||
size_t buffer_capacity{};
|
||||
size_type last_requested_size{};
|
||||
size_type buffer_capacity{};
|
||||
std::unique_ptr<T[]> buffer{};
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user