summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/scripts/android/eabuild.sh21
-rw-r--r--.ci/scripts/android/mainlinebuild.sh21
-rw-r--r--.github/workflows/android-ea-play-release.yml66
-rw-r--r--.github/workflows/android-mainline-play-release.yml59
-rw-r--r--.github/workflows/android-merge.js129
-rw-r--r--.github/workflows/android-publish.yml4
-rw-r--r--dist/languages/.tx/config1
-rw-r--r--src/android/app/build.gradle.kts31
-rw-r--r--src/common/typed_address.h82
-rw-r--r--src/core/debugger/gdbstub_arch.cpp4
-rw-r--r--src/core/hle/service/hid/hid_debug_server.cpp173
-rw-r--r--src/core/hle/service/hid/hid_debug_server.h24
-rw-r--r--src/core/hle/service/hid/irs.cpp588
-rw-r--r--src/core/hle/service/hid/irs.h84
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp6
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.cpp50
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.h2
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp3
-rw-r--r--src/core/memory/cheat_engine.cpp46
-rw-r--r--src/core/memory/cheat_engine.h8
-rw-r--r--src/core/memory/dmnt_cheat_types.h2
-rw-r--r--src/core/memory/dmnt_cheat_vm.cpp74
-rw-r--r--src/core/memory/dmnt_cheat_vm.h22
-rw-r--r--src/hid_core/irsensor/image_transfer_processor.cpp5
-rw-r--r--src/hid_core/irsensor/image_transfer_processor.h4
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp2
-rw-r--r--src/hid_core/resources/npad/npad.cpp6
-rw-r--r--src/hid_core/resources/six_axis/six_axis.cpp254
-rw-r--r--src/hid_core/resources/touch_screen/touch_screen_resource.cpp8
-rw-r--r--src/video_core/host1x/host1x.cpp2
-rw-r--r--src/video_core/memory_manager.cpp17
-rw-r--r--src/video_core/memory_manager.h8
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp3
33 files changed, 967 insertions, 842 deletions
diff --git a/.ci/scripts/android/eabuild.sh b/.ci/scripts/android/eabuild.sh
new file mode 100644
index 000000000..1672f2948
--- /dev/null
+++ b/.ci/scripts/android/eabuild.sh
@@ -0,0 +1,21 @@
1#!/bin/bash -ex
2
3# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
4# SPDX-License-Identifier: GPL-3.0-or-later
5
6export NDK_CCACHE="$(which ccache)"
7ccache -s
8
9export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
10base64 --decode <<< "${EA_PLAY_ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
11export ANDROID_KEY_ALIAS="${PLAY_ANDROID_KEY_ALIAS}"
12export ANDROID_KEYSTORE_PASS="${PLAY_ANDROID_KEYSTORE_PASS}"
13export SERVICE_ACCOUNT_KEY_PATH="${GITHUB_WORKSPACE}/sa.json"
14base64 --decode <<< "${EA_SERVICE_ACCOUNT_KEY_B64}" > "${SERVICE_ACCOUNT_KEY_PATH}"
15./gradlew "publishEaReleaseBundle"
16
17ccache -s
18
19if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
20 rm "${ANDROID_KEYSTORE_FILE}"
21fi
diff --git a/.ci/scripts/android/mainlinebuild.sh b/.ci/scripts/android/mainlinebuild.sh
new file mode 100644
index 000000000..f3b89ed1c
--- /dev/null
+++ b/.ci/scripts/android/mainlinebuild.sh
@@ -0,0 +1,21 @@
1#!/bin/bash -ex
2
3# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
4# SPDX-License-Identifier: GPL-3.0-or-later
5
6export NDK_CCACHE="$(which ccache)"
7ccache -s
8
9export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
10base64 --decode <<< "${MAINLINE_PLAY_ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
11export ANDROID_KEY_ALIAS="${PLAY_ANDROID_KEY_ALIAS}"
12export ANDROID_KEYSTORE_PASS="${PLAY_ANDROID_KEYSTORE_PASS}"
13export SERVICE_ACCOUNT_KEY_PATH="${GITHUB_WORKSPACE}/sa.json"
14base64 --decode <<< "${MAINLINE_SERVICE_ACCOUNT_KEY_B64}" > "${SERVICE_ACCOUNT_KEY_PATH}"
15./gradlew "publishMainlineReleaseBundle"
16
17ccache -s
18
19if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
20 rm "${ANDROID_KEYSTORE_FILE}"
21fi
diff --git a/.github/workflows/android-ea-play-release.yml b/.github/workflows/android-ea-play-release.yml
new file mode 100644
index 000000000..0cf78279c
--- /dev/null
+++ b/.github/workflows/android-ea-play-release.yml
@@ -0,0 +1,66 @@
1# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2# SPDX-License-Identifier: GPL-2.0-or-later
3
4name: yuzu-android-ea-play-release
5
6on:
7 workflow_dispatch:
8 inputs:
9 release-track:
10 description: 'Play store release track (internal/alpha/beta/production)'
11 required: true
12 default: 'alpha'
13
14jobs:
15 android:
16 runs-on: ubuntu-latest
17 if: ${{ github.repository == 'yuzu-emu/yuzu' }}
18 steps:
19 - uses: actions/checkout@v3
20 name: Checkout
21 with:
22 fetch-depth: 0
23 submodules: true
24 token: ${{ secrets.ALT_GITHUB_TOKEN }}
25 - run: npm install execa@5
26 - uses: actions/github-script@v5
27 name: 'Merge and publish Android EA changes'
28 env:
29 ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }}
30 BUILD_EA: true
31 with:
32 script: |
33 const execa = require("execa");
34 const mergebot = require('./.github/workflows/android-merge.js').mergebot;
35 process.chdir('${{ github.workspace }}');
36 mergebot(github, context, execa);
37 - name: Get tag name
38 run: echo "GIT_TAG_NAME=$(cat tag-name.txt)" >> $GITHUB_ENV
39 - name: Set up JDK 17
40 uses: actions/setup-java@v3
41 with:
42 java-version: '17'
43 distribution: 'temurin'
44 - name: Install dependencies
45 run: |
46 sudo apt-get update
47 sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
48 - name: Build
49 run: ./.ci/scripts/android/eabuild.sh
50 env:
51 EA_PLAY_ANDROID_KEYSTORE_B64: ${{ secrets.PLAY_ANDROID_KEYSTORE_B64 }}
52 PLAY_ANDROID_KEY_ALIAS: ${{ secrets.PLAY_ANDROID_KEY_ALIAS }}
53 PLAY_ANDROID_KEYSTORE_PASS: ${{ secrets.PLAY_ANDROID_KEYSTORE_PASS }}
54 EA_SERVICE_ACCOUNT_KEY_B64: ${{ secrets.EA_SERVICE_ACCOUNT_KEY_B64 }}
55 STORE_TRACK: ${{ github.event.inputs.release-track }}
56 AUTO_VERSIONED: true
57 BUILD_EA: true
58 - name: Create release
59 uses: softprops/action-gh-release@v1
60 with:
61 tag_name: ${{ env.EA_TAG_NAME }}
62 name: ${{ env.EA_TAG_NAME }}
63 draft: false
64 prerelease: false
65 repository: yuzu/yuzu-android
66 token: ${{ secrets.ALT_GITHUB_TOKEN }}
diff --git a/.github/workflows/android-mainline-play-release.yml b/.github/workflows/android-mainline-play-release.yml
new file mode 100644
index 000000000..8255e0a40
--- /dev/null
+++ b/.github/workflows/android-mainline-play-release.yml
@@ -0,0 +1,59 @@
1# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2# SPDX-License-Identifier: GPL-2.0-or-later
3
4name: yuzu-android-mainline-play-release
5
6on:
7 workflow_dispatch:
8 inputs:
9 release-tag:
10 description: 'Tag # from yuzu-android that you want to build and publish'
11 required: true
12 default: '200'
13 release-track:
14 description: 'Play store release track (internal/alpha/beta/production)'
15 required: true
16 default: 'alpha'
17
18jobs:
19 android:
20 runs-on: ubuntu-latest
21 if: ${{ github.repository == 'yuzu-emu/yuzu' }}
22 steps:
23 - uses: actions/checkout@v3
24 name: Checkout
25 with:
26 fetch-depth: 0
27 submodules: true
28 token: ${{ secrets.ALT_GITHUB_TOKEN }}
29 - run: npm install execa@5
30 - uses: actions/github-script@v5
31 name: 'Pull mainline tag'
32 env:
33 MAINLINE_TAG: ${{ github.event.inputs.release-tag }}
34 with:
35 script: |
36 const execa = require("execa");
37 const mergebot = require('./.github/workflows/android-merge.js').getMainlineTag;
38 process.chdir('${{ github.workspace }}');
39 mergebot(execa);
40 - name: Set up JDK 17
41 uses: actions/setup-java@v3
42 with:
43 java-version: '17'
44 distribution: 'temurin'
45 - name: Install dependencies
46 run: |
47 sudo apt-get update
48 sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
49 - name: Build
50 run: |
51 echo "GIT_TAG_NAME=android-${{ github.event.inputs.releast-tag }}" >> $GITHUB_ENV
52 ./.ci/scripts/android/mainlinebuild.sh
53 env:
54 MAINLINE_PLAY_ANDROID_KEYSTORE_B64: ${{ secrets.PLAY_ANDROID_KEYSTORE_B64 }}
55 PLAY_ANDROID_KEY_ALIAS: ${{ secrets.PLAY_ANDROID_KEY_ALIAS }}
56 PLAY_ANDROID_KEYSTORE_PASS: ${{ secrets.PLAY_ANDROID_KEYSTORE_PASS }}
57 SERVICE_ACCOUNT_KEY_B64: ${{ secrets.MAINLINE_SERVICE_ACCOUNT_KEY_B64 }}
58 STORE_TRACK: ${{ github.event.inputs.release-track }}
59 AUTO_VERSIONED: true
diff --git a/.github/workflows/android-merge.js b/.github/workflows/android-merge.js
index 44ab56e44..315f81ba0 100644
--- a/.github/workflows/android-merge.js
+++ b/.github/workflows/android-merge.js
@@ -6,9 +6,12 @@
6 6
7const fs = require("fs"); 7const fs = require("fs");
8// which label to check for changes 8// which label to check for changes
9const CHANGE_LABEL = 'android-merge'; 9const CHANGE_LABEL_MAINLINE = 'android-merge';
10const CHANGE_LABEL_EA = 'android-ea-merge';
10// how far back in time should we consider the changes are "recent"? (default: 24 hours) 11// how far back in time should we consider the changes are "recent"? (default: 24 hours)
11const DETECTION_TIME_FRAME = (parseInt(process.env.DETECTION_TIME_FRAME)) || (24 * 3600 * 1000); 12const DETECTION_TIME_FRAME = (parseInt(process.env.DETECTION_TIME_FRAME)) || (24 * 3600 * 1000);
13const BUILD_EA = process.env.BUILD_EA == 'true';
14const MAINLINE_TAG = process.env.MAINLINE_TAG;
12 15
13async function checkBaseChanges(github) { 16async function checkBaseChanges(github) {
14 // query the commit date of the latest commit on this branch 17 // query the commit date of the latest commit on this branch
@@ -40,20 +43,7 @@ async function checkBaseChanges(github) {
40 43
41async function checkAndroidChanges(github) { 44async function checkAndroidChanges(github) {
42 if (checkBaseChanges(github)) return true; 45 if (checkBaseChanges(github)) return true;
43 const query = `query($owner:String!, $name:String!, $label:String!) { 46 const pulls = getPulls(github, false);
44 repository(name:$name, owner:$owner) {
45 pullRequests(labels: [$label], states: OPEN, first: 100) {
46 nodes { number headRepository { pushedAt } }
47 }
48 }
49 }`;
50 const variables = {
51 owner: 'yuzu-emu',
52 name: 'yuzu',
53 label: CHANGE_LABEL,
54 };
55 const result = await github.graphql(query, variables);
56 const pulls = result.repository.pullRequests.nodes;
57 for (let i = 0; i < pulls.length; i++) { 47 for (let i = 0; i < pulls.length; i++) {
58 let pull = pulls[i]; 48 let pull = pulls[i];
59 if (new Date() - new Date(pull.headRepository.pushedAt) <= DETECTION_TIME_FRAME) { 49 if (new Date() - new Date(pull.headRepository.pushedAt) <= DETECTION_TIME_FRAME) {
@@ -83,7 +73,13 @@ async function tagAndPush(github, owner, repo, execa, commit=false) {
83 }; 73 };
84 const tags = await github.graphql(query, variables); 74 const tags = await github.graphql(query, variables);
85 const tagList = tags.repository.refs.nodes; 75 const tagList = tags.repository.refs.nodes;
86 const lastTag = tagList[0] ? tagList[0].name : 'dummy-0'; 76 let lastTag = 'android-1';
77 for (let i = 0; i < tagList.length; ++i) {
78 if (tagList[i].name.includes('android-')) {
79 lastTag = tagList[i].name;
80 break;
81 }
82 }
87 const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0; 83 const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
88 const channel = repo.split('-')[1]; 84 const channel = repo.split('-')[1];
89 const newTag = `${channel}-${tagNumber + 1}`; 85 const newTag = `${channel}-${tagNumber + 1}`;
@@ -101,6 +97,48 @@ async function tagAndPush(github, owner, repo, execa, commit=false) {
101 console.info('Successfully pushed new changes.'); 97 console.info('Successfully pushed new changes.');
102} 98}
103 99
100async function tagAndPushEA(github, owner, repo, execa) {
101 let altToken = process.env.ALT_GITHUB_TOKEN;
102 if (!altToken) {
103 throw `Please set ALT_GITHUB_TOKEN environment variable. This token should have write access to ${owner}/${repo}.`;
104 }
105 const query = `query ($owner:String!, $name:String!) {
106 repository(name:$name, owner:$owner) {
107 refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 10) {
108 nodes { name }
109 }
110 }
111 }`;
112 const variables = {
113 owner: owner,
114 name: repo,
115 };
116 const tags = await github.graphql(query, variables);
117 const tagList = tags.repository.refs.nodes;
118 let lastTag = 'ea-1';
119 for (let i = 0; i < tagList.length; ++i) {
120 if (tagList[i].name.includes('ea-')) {
121 lastTag = tagList[i].name;
122 break;
123 }
124 }
125 const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
126 const newTag = `ea-${tagNumber + 1}`;
127 console.log(`New tag: ${newTag}`);
128 console.info('Pushing tags to GitHub ...');
129 await execa("git", ["remote", "add", "android", "https://github.com/yuzu-emu/yuzu-android.git"]);
130 await execa("git", ["fetch", "android"]);
131
132 await execa("git", ['tag', newTag]);
133 await execa("git", ['push', 'android', `${newTag}`]);
134
135 fs.writeFile('tag-name.txt', newTag, (err) => {
136 if (err) throw 'Could not write tag name to file!'
137 })
138
139 console.info('Successfully pushed new changes.');
140}
141
104async function generateReadme(pulls, context, mergeResults, execa) { 142async function generateReadme(pulls, context, mergeResults, execa) {
105 let baseUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/`; 143 let baseUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/`;
106 let output = 144 let output =
@@ -202,10 +240,7 @@ async function resetBranch(execa) {
202 } 240 }
203} 241}
204 242
205async function mergebot(github, context, execa) { 243async function getPulls(github) {
206 // Reset our local copy of master to what appears on yuzu-emu/yuzu - master
207 await resetBranch(execa);
208
209 const query = `query ($owner:String!, $name:String!, $label:String!) { 244 const query = `query ($owner:String!, $name:String!, $label:String!) {
210 repository(name:$name, owner:$owner) { 245 repository(name:$name, owner:$owner) {
211 pullRequests(labels: [$label], states: OPEN, first: 100) { 246 pullRequests(labels: [$label], states: OPEN, first: 100) {
@@ -215,13 +250,49 @@ async function mergebot(github, context, execa) {
215 } 250 }
216 } 251 }
217 }`; 252 }`;
218 const variables = { 253 const mainlineVariables = {
219 owner: 'yuzu-emu', 254 owner: 'yuzu-emu',
220 name: 'yuzu', 255 name: 'yuzu',
221 label: CHANGE_LABEL, 256 label: CHANGE_LABEL_MAINLINE,
222 }; 257 };
223 const result = await github.graphql(query, variables); 258 const mainlineResult = await github.graphql(query, mainlineVariables);
224 const pulls = result.repository.pullRequests.nodes; 259 const pulls = mainlineResult.repository.pullRequests.nodes;
260 if (BUILD_EA) {
261 const eaVariables = {
262 owner: 'yuzu-emu',
263 name: 'yuzu',
264 label: CHANGE_LABEL_EA,
265 };
266 const eaResult = await github.graphql(query, eaVariables);
267 const eaPulls = eaResult.repository.pullRequests.nodes;
268 return pulls.concat(eaPulls);
269 }
270 return pulls;
271}
272
273async function getMainlineTag(execa) {
274 console.log(`::group::Getting mainline tag android-${MAINLINE_TAG}`);
275 let hasFailed = false;
276 try {
277 await execa("git", ["remote", "add", "mainline", "https://github.com/yuzu-emu/yuzu-android.git"]);
278 await execa("git", ["fetch", "mainline", "--tags"]);
279 await execa("git", ["checkout", `tags/android-${MAINLINE_TAG}`]);
280 await execa("git", ["submodule", "update", "--init", "--recursive"]);
281 } catch (err) {
282 console.log('::error title=Failed pull tag');
283 hasFailed = true;
284 }
285 console.log("::endgroup::");
286 if (hasFailed) {
287 throw 'Failed pull mainline tag. Aborting!';
288 }
289}
290
291async function mergebot(github, context, execa) {
292 // Reset our local copy of master to what appears on yuzu-emu/yuzu - master
293 await resetBranch(execa);
294
295 const pulls = await getPulls(github);
225 let displayList = []; 296 let displayList = [];
226 for (let i = 0; i < pulls.length; i++) { 297 for (let i = 0; i < pulls.length; i++) {
227 let pull = pulls[i]; 298 let pull = pulls[i];
@@ -231,11 +302,17 @@ async function mergebot(github, context, execa) {
231 console.table(displayList); 302 console.table(displayList);
232 await fetchPullRequests(pulls, "https://github.com/yuzu-emu/yuzu", execa); 303 await fetchPullRequests(pulls, "https://github.com/yuzu-emu/yuzu", execa);
233 const mergeResults = await mergePullRequests(pulls, execa); 304 const mergeResults = await mergePullRequests(pulls, execa);
234 await generateReadme(pulls, context, mergeResults, execa); 305
235 await tagAndPush(github, 'yuzu-emu', `yuzu-android`, execa, true); 306 if (BUILD_EA) {
307 await tagAndPushEA(github, 'yuzu-emu', `yuzu-android`, execa);
308 } else {
309 await generateReadme(pulls, context, mergeResults, execa);
310 await tagAndPush(github, 'yuzu-emu', `yuzu-android`, execa, true);
311 }
236} 312}
237 313
238module.exports.mergebot = mergebot; 314module.exports.mergebot = mergebot;
239module.exports.checkAndroidChanges = checkAndroidChanges; 315module.exports.checkAndroidChanges = checkAndroidChanges;
240module.exports.tagAndPush = tagAndPush; 316module.exports.tagAndPush = tagAndPush;
241module.exports.checkBaseChanges = checkBaseChanges; 317module.exports.checkBaseChanges = checkBaseChanges;
318module.exports.getMainlineTag = getMainlineTag;
diff --git a/.github/workflows/android-publish.yml b/.github/workflows/android-publish.yml
index 68e21c2f2..61f739e96 100644
--- a/.github/workflows/android-publish.yml
+++ b/.github/workflows/android-publish.yml
@@ -1,4 +1,4 @@
1# SPDX-FileCopyrightText: 2023 yuzu Emulator Project 1# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2# SPDX-License-Identifier: GPL-2.0-or-later 2# SPDX-License-Identifier: GPL-2.0-or-later
3 3
4name: yuzu-android-publish 4name: yuzu-android-publish
@@ -16,7 +16,7 @@ on:
16jobs: 16jobs:
17 android: 17 android:
18 runs-on: ubuntu-latest 18 runs-on: ubuntu-latest
19 if: ${{ github.event.inputs.android != 'false' && github.repository == 'yuzu-emu/yuzu-android' }} 19 if: ${{ github.event.inputs.android != 'false' && github.repository == 'yuzu-emu/yuzu' }}
20 steps: 20 steps:
21 # this checkout is required to make sure the GitHub Actions scripts are available 21 # this checkout is required to make sure the GitHub Actions scripts are available
22 - uses: actions/checkout@v3 22 - uses: actions/checkout@v3
diff --git a/dist/languages/.tx/config b/dist/languages/.tx/config
index cca7b3d67..fbdfbe017 100644
--- a/dist/languages/.tx/config
+++ b/dist/languages/.tx/config
@@ -11,3 +11,4 @@ type = QT
11file_filter = ../../src/android/app/src/main/res/values-<lang>/strings.xml 11file_filter = ../../src/android/app/src/main/res/values-<lang>/strings.xml
12source_file = ../../src/android/app/src/main/res/values/strings.xml 12source_file = ../../src/android/app/src/main/res/values/strings.xml
13type = ANDROID 13type = ANDROID
14lang_map = ja_JP:ja, ko_KR:ko, pt_BR:pt-rBR, pt_PT:pt-rPT, ru_RU:ru, vi_VN:vi, zh_CN:zh-rCN, zh_TW:zh-rTW
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts
index 188ef9469..d44bb4c74 100644
--- a/src/android/app/build.gradle.kts
+++ b/src/android/app/build.gradle.kts
@@ -3,8 +3,8 @@
3 3
4import android.annotation.SuppressLint 4import android.annotation.SuppressLint
5import kotlin.collections.setOf 5import kotlin.collections.setOf
6import org.jetbrains.kotlin.konan.properties.Properties
7import org.jlleitschuh.gradle.ktlint.reporter.ReporterType 6import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
7import com.github.triplet.gradle.androidpublisher.ReleaseStatus
8 8
9plugins { 9plugins {
10 id("com.android.application") 10 id("com.android.application")
@@ -13,6 +13,7 @@ plugins {
13 kotlin("plugin.serialization") version "1.9.20" 13 kotlin("plugin.serialization") version "1.9.20"
14 id("androidx.navigation.safeargs.kotlin") 14 id("androidx.navigation.safeargs.kotlin")
15 id("org.jlleitschuh.gradle.ktlint") version "11.4.0" 15 id("org.jlleitschuh.gradle.ktlint") version "11.4.0"
16 id("com.github.triplet.play") version "3.8.6"
16} 17}
17 18
18/** 19/**
@@ -58,15 +59,7 @@ android {
58 targetSdk = 34 59 targetSdk = 34
59 versionName = getGitVersion() 60 versionName = getGitVersion()
60 61
61 // If you want to use autoVersion for the versionCode, create a property in local.properties 62 versionCode = if (System.getenv("AUTO_VERSIONED") == "true") {
62 // named "autoVersioned" and set it to "true"
63 val properties = Properties()
64 val versionProperty = try {
65 properties.load(project.rootProject.file("local.properties").inputStream())
66 properties.getProperty("autoVersioned") ?: ""
67 } catch (e: Exception) { "" }
68
69 versionCode = if (versionProperty == "true") {
70 autoVersion 63 autoVersion
71 } else { 64 } else {
72 1 65 1
@@ -221,6 +214,15 @@ ktlint {
221 } 214 }
222} 215}
223 216
217play {
218 val keyPath = System.getenv("SERVICE_ACCOUNT_KEY_PATH")
219 if (keyPath != null) {
220 serviceAccountCredentials.set(File(keyPath))
221 }
222 track.set(System.getenv("STORE_TRACK") ?: "internal")
223 releaseStatus.set(ReleaseStatus.COMPLETED)
224}
225
224dependencies { 226dependencies {
225 implementation("androidx.core:core-ktx:1.12.0") 227 implementation("androidx.core:core-ktx:1.12.0")
226 implementation("androidx.appcompat:appcompat:1.6.1") 228 implementation("androidx.appcompat:appcompat:1.6.1")
@@ -257,14 +259,13 @@ fun runGitCommand(command: List<String>): String {
257} 259}
258 260
259fun getGitVersion(): String { 261fun getGitVersion(): String {
262 val gitVersion = runGitCommand(listOf("git", "describe", "--always", "--long"))
260 val versionName = if (System.getenv("GITHUB_ACTIONS") != null) { 263 val versionName = if (System.getenv("GITHUB_ACTIONS") != null) {
261 val gitTag = System.getenv("GIT_TAG_NAME") ?: "" 264 System.getenv("GIT_TAG_NAME") ?: gitVersion
262 gitTag
263 } else { 265 } else {
264 runGitCommand(listOf("git", "describe", "--always", "--long")) 266 gitVersion
265 .replace(Regex("(-0)?-[^-]+$"), "")
266 } 267 }
267 return versionName.ifEmpty { "0.0" } 268 return versionName.replace(Regex("(-0)?-[^-]+$"), "").ifEmpty { "0.0" }
268} 269}
269 270
270fun getGitHash(): String = 271fun getGitHash(): String =
diff --git a/src/common/typed_address.h b/src/common/typed_address.h
index 64f4a07c2..d5e743583 100644
--- a/src/common/typed_address.h
+++ b/src/common/typed_address.h
@@ -186,68 +186,68 @@ static_assert(std::is_trivially_destructible_v<PhysicalAddress>);
186static_assert(std::is_trivially_destructible_v<VirtualAddress>); 186static_assert(std::is_trivially_destructible_v<VirtualAddress>);
187static_assert(std::is_trivially_destructible_v<ProcessAddress>); 187static_assert(std::is_trivially_destructible_v<ProcessAddress>);
188 188
189static_assert(Null<uint64_t> == 0); 189static_assert(Null<uint64_t> == 0U);
190static_assert(Null<PhysicalAddress> == Null<uint64_t>); 190static_assert(Null<PhysicalAddress> == Null<uint64_t>);
191static_assert(Null<VirtualAddress> == Null<uint64_t>); 191static_assert(Null<VirtualAddress> == Null<uint64_t>);
192static_assert(Null<ProcessAddress> == Null<uint64_t>); 192static_assert(Null<ProcessAddress> == Null<uint64_t>);
193 193
194// Constructor/assignment validations. 194// Constructor/assignment validations.
195static_assert([] { 195static_assert([] {
196 const PhysicalAddress a(5); 196 const PhysicalAddress a(5U);
197 PhysicalAddress b(a); 197 PhysicalAddress b(a);
198 return b; 198 return b;
199}() == PhysicalAddress(5)); 199}() == PhysicalAddress(5U));
200static_assert([] { 200static_assert([] {
201 const PhysicalAddress a(5); 201 const PhysicalAddress a(5U);
202 PhysicalAddress b(10); 202 PhysicalAddress b(10U);
203 b = a; 203 b = a;
204 return b; 204 return b;
205}() == PhysicalAddress(5)); 205}() == PhysicalAddress(5U));
206 206
207// Arithmetic validations. 207// Arithmetic validations.
208static_assert(PhysicalAddress(10) + 5 == PhysicalAddress(15)); 208static_assert(PhysicalAddress(10U) + 5U == PhysicalAddress(15U));
209static_assert(PhysicalAddress(10) - 5 == PhysicalAddress(5)); 209static_assert(PhysicalAddress(10U) - 5U == PhysicalAddress(5U));
210static_assert([] { 210static_assert([] {
211 PhysicalAddress v(10); 211 PhysicalAddress v(10U);
212 v += 5; 212 v += 5U;
213 return v; 213 return v;
214}() == PhysicalAddress(15)); 214}() == PhysicalAddress(15U));
215static_assert([] { 215static_assert([] {
216 PhysicalAddress v(10); 216 PhysicalAddress v(10U);
217 v -= 5; 217 v -= 5U;
218 return v; 218 return v;
219}() == PhysicalAddress(5)); 219}() == PhysicalAddress(5U));
220static_assert(PhysicalAddress(10)++ == PhysicalAddress(10)); 220static_assert(PhysicalAddress(10U)++ == PhysicalAddress(10U));
221static_assert(++PhysicalAddress(10) == PhysicalAddress(11)); 221static_assert(++PhysicalAddress(10U) == PhysicalAddress(11U));
222static_assert(PhysicalAddress(10)-- == PhysicalAddress(10)); 222static_assert(PhysicalAddress(10U)-- == PhysicalAddress(10U));
223static_assert(--PhysicalAddress(10) == PhysicalAddress(9)); 223static_assert(--PhysicalAddress(10U) == PhysicalAddress(9U));
224 224
225// Logical validations. 225// Logical validations.
226static_assert((PhysicalAddress(0b11111111) >> 1) == 0b01111111); 226static_assert((PhysicalAddress(0b11111111U) >> 1) == 0b01111111U);
227static_assert((PhysicalAddress(0b10101010) >> 1) == 0b01010101); 227static_assert((PhysicalAddress(0b10101010U) >> 1) == 0b01010101U);
228static_assert((PhysicalAddress(0b11111111) << 1) == 0b111111110); 228static_assert((PhysicalAddress(0b11111111U) << 1) == 0b111111110U);
229static_assert((PhysicalAddress(0b01010101) << 1) == 0b10101010); 229static_assert((PhysicalAddress(0b01010101U) << 1) == 0b10101010U);
230static_assert((PhysicalAddress(0b11111111) & 0b01010101) == 0b01010101); 230static_assert((PhysicalAddress(0b11111111U) & 0b01010101U) == 0b01010101U);
231static_assert((PhysicalAddress(0b11111111) & 0b10101010) == 0b10101010); 231static_assert((PhysicalAddress(0b11111111U) & 0b10101010U) == 0b10101010U);
232static_assert((PhysicalAddress(0b01010101) & 0b10101010) == 0b00000000); 232static_assert((PhysicalAddress(0b01010101U) & 0b10101010U) == 0b00000000U);
233static_assert((PhysicalAddress(0b00000000) | 0b01010101) == 0b01010101); 233static_assert((PhysicalAddress(0b00000000U) | 0b01010101U) == 0b01010101U);
234static_assert((PhysicalAddress(0b11111111) | 0b01010101) == 0b11111111); 234static_assert((PhysicalAddress(0b11111111U) | 0b01010101U) == 0b11111111U);
235static_assert((PhysicalAddress(0b10101010) | 0b01010101) == 0b11111111); 235static_assert((PhysicalAddress(0b10101010U) | 0b01010101U) == 0b11111111U);
236 236
237// Comparisons. 237// Comparisons.
238static_assert(PhysicalAddress(0) == PhysicalAddress(0)); 238static_assert(PhysicalAddress(0U) == PhysicalAddress(0U));
239static_assert(PhysicalAddress(0) != PhysicalAddress(1)); 239static_assert(PhysicalAddress(0U) != PhysicalAddress(1U));
240static_assert(PhysicalAddress(0) < PhysicalAddress(1)); 240static_assert(PhysicalAddress(0U) < PhysicalAddress(1U));
241static_assert(PhysicalAddress(0) <= PhysicalAddress(1)); 241static_assert(PhysicalAddress(0U) <= PhysicalAddress(1U));
242static_assert(PhysicalAddress(1) > PhysicalAddress(0)); 242static_assert(PhysicalAddress(1U) > PhysicalAddress(0U));
243static_assert(PhysicalAddress(1) >= PhysicalAddress(0)); 243static_assert(PhysicalAddress(1U) >= PhysicalAddress(0U));
244 244
245static_assert(!(PhysicalAddress(0) == PhysicalAddress(1))); 245static_assert(!(PhysicalAddress(0U) == PhysicalAddress(1U)));
246static_assert(!(PhysicalAddress(0) != PhysicalAddress(0))); 246static_assert(!(PhysicalAddress(0U) != PhysicalAddress(0U)));
247static_assert(!(PhysicalAddress(1) < PhysicalAddress(0))); 247static_assert(!(PhysicalAddress(1U) < PhysicalAddress(0U)));
248static_assert(!(PhysicalAddress(1) <= PhysicalAddress(0))); 248static_assert(!(PhysicalAddress(1U) <= PhysicalAddress(0U)));
249static_assert(!(PhysicalAddress(0) > PhysicalAddress(1))); 249static_assert(!(PhysicalAddress(0U) > PhysicalAddress(1U)));
250static_assert(!(PhysicalAddress(0) >= PhysicalAddress(1))); 250static_assert(!(PhysicalAddress(0U) >= PhysicalAddress(1U)));
251 251
252} // namespace Common 252} // namespace Common
253 253
diff --git a/src/core/debugger/gdbstub_arch.cpp b/src/core/debugger/gdbstub_arch.cpp
index f2a407dc8..452f565be 100644
--- a/src/core/debugger/gdbstub_arch.cpp
+++ b/src/core/debugger/gdbstub_arch.cpp
@@ -383,7 +383,7 @@ std::string GDBStubA32::RegRead(const Kernel::KThread* thread, size_t id) const
383 } else if (id == CPSR_REGISTER) { 383 } else if (id == CPSR_REGISTER) {
384 return ValueToHex(context.pstate); 384 return ValueToHex(context.pstate);
385 } else if (id >= D0_REGISTER && id < Q0_REGISTER) { 385 } else if (id >= D0_REGISTER && id < Q0_REGISTER) {
386 return ValueToHex(fprs[id - D0_REGISTER][0]); 386 return ValueToHex(fprs[(id - D0_REGISTER) / 2][(id - D0_REGISTER) % 2]);
387 } else if (id >= Q0_REGISTER && id < FPSCR_REGISTER) { 387 } else if (id >= Q0_REGISTER && id < FPSCR_REGISTER) {
388 return ValueToHex(fprs[id - Q0_REGISTER]); 388 return ValueToHex(fprs[id - Q0_REGISTER]);
389 } else if (id == FPSCR_REGISTER) { 389 } else if (id == FPSCR_REGISTER) {
@@ -406,7 +406,7 @@ void GDBStubA32::RegWrite(Kernel::KThread* thread, size_t id, std::string_view v
406 } else if (id == CPSR_REGISTER) { 406 } else if (id == CPSR_REGISTER) {
407 context.pstate = HexToValue<u32>(value); 407 context.pstate = HexToValue<u32>(value);
408 } else if (id >= D0_REGISTER && id < Q0_REGISTER) { 408 } else if (id >= D0_REGISTER && id < Q0_REGISTER) {
409 fprs[id - D0_REGISTER] = {HexToValue<u64>(value), 0}; 409 fprs[(id - D0_REGISTER) / 2][(id - D0_REGISTER) % 2] = HexToValue<u64>(value);
410 } else if (id >= Q0_REGISTER && id < FPSCR_REGISTER) { 410 } else if (id >= Q0_REGISTER && id < FPSCR_REGISTER) {
411 fprs[id - Q0_REGISTER] = HexToValue<u128>(value); 411 fprs[id - Q0_REGISTER] = HexToValue<u128>(value);
412 } else if (id == FPSCR_REGISTER) { 412 } else if (id == FPSCR_REGISTER) {
diff --git a/src/core/hle/service/hid/hid_debug_server.cpp b/src/core/hle/service/hid/hid_debug_server.cpp
index 610af34dd..4e2663672 100644
--- a/src/core/hle/service/hid/hid_debug_server.cpp
+++ b/src/core/hle/service/hid/hid_debug_server.cpp
@@ -3,6 +3,7 @@
3 3
4#include <algorithm> 4#include <algorithm>
5 5
6#include "core/hle/service/cmif_serialization.h"
6#include "core/hle/service/hid/hid_debug_server.h" 7#include "core/hle/service/hid/hid_debug_server.h"
7#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
8#include "hid_core/hid_types.h" 9#include "hid_core/hid_types.h"
@@ -11,7 +12,6 @@
11 12
12#include "hid_core/resources/touch_screen/gesture.h" 13#include "hid_core/resources/touch_screen/gesture.h"
13#include "hid_core/resources/touch_screen/touch_screen.h" 14#include "hid_core/resources/touch_screen/touch_screen.h"
14#include "hid_core/resources/touch_screen/touch_types.h"
15 15
16namespace Service::HID { 16namespace Service::HID {
17 17
@@ -24,14 +24,14 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
24 {0, nullptr, "DeactivateDebugPad"}, 24 {0, nullptr, "DeactivateDebugPad"},
25 {1, nullptr, "SetDebugPadAutoPilotState"}, 25 {1, nullptr, "SetDebugPadAutoPilotState"},
26 {2, nullptr, "UnsetDebugPadAutoPilotState"}, 26 {2, nullptr, "UnsetDebugPadAutoPilotState"},
27 {10, &IHidDebugServer::DeactivateTouchScreen, "DeactivateTouchScreen"}, 27 {10, C<&IHidDebugServer::DeactivateTouchScreen>, "DeactivateTouchScreen"},
28 {11, &IHidDebugServer::SetTouchScreenAutoPilotState, "SetTouchScreenAutoPilotState"}, 28 {11, C<&IHidDebugServer::SetTouchScreenAutoPilotState>, "SetTouchScreenAutoPilotState"},
29 {12, &IHidDebugServer::UnsetTouchScreenAutoPilotState, "UnsetTouchScreenAutoPilotState"}, 29 {12, C<&IHidDebugServer::UnsetTouchScreenAutoPilotState>, "UnsetTouchScreenAutoPilotState"},
30 {13, &IHidDebugServer::GetTouchScreenConfiguration, "GetTouchScreenConfiguration"}, 30 {13, C<&IHidDebugServer::GetTouchScreenConfiguration>, "GetTouchScreenConfiguration"},
31 {14, &IHidDebugServer::ProcessTouchScreenAutoTune, "ProcessTouchScreenAutoTune"}, 31 {14, C<&IHidDebugServer::ProcessTouchScreenAutoTune>, "ProcessTouchScreenAutoTune"},
32 {15, &IHidDebugServer::ForceStopTouchScreenManagement, "ForceStopTouchScreenManagement"}, 32 {15, C<&IHidDebugServer::ForceStopTouchScreenManagement>, "ForceStopTouchScreenManagement"},
33 {16, &IHidDebugServer::ForceRestartTouchScreenManagement, "ForceRestartTouchScreenManagement"}, 33 {16, C<&IHidDebugServer::ForceRestartTouchScreenManagement>, "ForceRestartTouchScreenManagement"},
34 {17, &IHidDebugServer::IsTouchScreenManaged, "IsTouchScreenManaged"}, 34 {17, C<&IHidDebugServer::IsTouchScreenManaged>, "IsTouchScreenManaged"},
35 {20, nullptr, "DeactivateMouse"}, 35 {20, nullptr, "DeactivateMouse"},
36 {21, nullptr, "SetMouseAutoPilotState"}, 36 {21, nullptr, "SetMouseAutoPilotState"},
37 {22, nullptr, "UnsetMouseAutoPilotState"}, 37 {22, nullptr, "UnsetMouseAutoPilotState"},
@@ -47,7 +47,7 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
47 {60, nullptr, "ClearNpadSystemCommonPolicy"}, 47 {60, nullptr, "ClearNpadSystemCommonPolicy"},
48 {61, nullptr, "DeactivateNpad"}, 48 {61, nullptr, "DeactivateNpad"},
49 {62, nullptr, "ForceDisconnectNpad"}, 49 {62, nullptr, "ForceDisconnectNpad"},
50 {91, &IHidDebugServer::DeactivateGesture, "DeactivateGesture"}, 50 {91, C<&IHidDebugServer::DeactivateGesture>, "DeactivateGesture"},
51 {110, nullptr, "DeactivateHomeButton"}, 51 {110, nullptr, "DeactivateHomeButton"},
52 {111, nullptr, "SetHomeButtonAutoPilotState"}, 52 {111, nullptr, "SetHomeButtonAutoPilotState"},
53 {112, nullptr, "UnsetHomeButtonAutoPilotState"}, 53 {112, nullptr, "UnsetHomeButtonAutoPilotState"},
@@ -160,169 +160,122 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
160} 160}
161 161
162IHidDebugServer::~IHidDebugServer() = default; 162IHidDebugServer::~IHidDebugServer() = default;
163void IHidDebugServer::DeactivateTouchScreen(HLERequestContext& ctx) {
164 LOG_INFO(Service_HID, "called");
165 163
166 Result result = ResultSuccess; 164Result IHidDebugServer::DeactivateTouchScreen() {
165 LOG_INFO(Service_HID, "called");
167 166
168 if (!firmware_settings->IsDeviceManaged()) { 167 if (!firmware_settings->IsDeviceManaged()) {
169 result = GetResourceManager()->GetTouchScreen()->Deactivate(); 168 R_RETURN(GetResourceManager()->GetTouchScreen()->Deactivate());
170 } 169 }
171 170
172 IPC::ResponseBuilder rb{ctx, 2}; 171 R_SUCCEED();
173 rb.Push(result);
174} 172}
175 173
176void IHidDebugServer::SetTouchScreenAutoPilotState(HLERequestContext& ctx) { 174Result IHidDebugServer::SetTouchScreenAutoPilotState(
175 InArray<TouchState, BufferAttr_HipcMapAlias> auto_pilot_buffer) {
177 AutoPilotState auto_pilot{}; 176 AutoPilotState auto_pilot{};
178 auto_pilot.count = ctx.GetReadBufferNumElements<TouchState>();
179 const auto buffer = ctx.ReadBuffer();
180 177
181 auto_pilot.count = std::min(auto_pilot.count, static_cast<u64>(auto_pilot.state.size())); 178 auto_pilot.count =
182 memcpy(auto_pilot.state.data(), buffer.data(), auto_pilot.count * sizeof(TouchState)); 179 static_cast<u64>(std::min(auto_pilot_buffer.size(), auto_pilot.state.size()));
180 memcpy(auto_pilot.state.data(), auto_pilot_buffer.data(),
181 auto_pilot.count * sizeof(TouchState));
183 182
184 LOG_INFO(Service_HID, "called, auto_pilot_count={}", auto_pilot.count); 183 LOG_INFO(Service_HID, "called, auto_pilot_count={}", auto_pilot.count);
185 184
186 const Result result = 185 R_RETURN(GetResourceManager()->GetTouchScreen()->SetTouchScreenAutoPilotState(auto_pilot));
187 GetResourceManager()->GetTouchScreen()->SetTouchScreenAutoPilotState(auto_pilot);
188
189 IPC::ResponseBuilder rb{ctx, 2};
190 rb.Push(result);
191} 186}
192 187
193void IHidDebugServer::UnsetTouchScreenAutoPilotState(HLERequestContext& ctx) { 188Result IHidDebugServer::UnsetTouchScreenAutoPilotState() {
194 LOG_INFO(Service_HID, "called"); 189 LOG_INFO(Service_HID, "called");
195 190 R_RETURN(GetResourceManager()->GetTouchScreen()->UnsetTouchScreenAutoPilotState());
196 const Result result = GetResourceManager()->GetTouchScreen()->UnsetTouchScreenAutoPilotState();
197
198 IPC::ResponseBuilder rb{ctx, 2};
199 rb.Push(result);
200} 191}
201 192
202void IHidDebugServer::GetTouchScreenConfiguration(HLERequestContext& ctx) { 193Result IHidDebugServer::GetTouchScreenConfiguration(
203 IPC::RequestParser rp{ctx}; 194 Out<Core::HID::TouchScreenConfigurationForNx> out_touchscreen_config,
204 const auto applet_resource_user_id{rp.Pop<u64>()}; 195 ClientAppletResourceUserId aruid) {
205 196 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", aruid.pid);
206 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
207 197
208 Core::HID::TouchScreenConfigurationForNx touchscreen_config{}; 198 R_TRY(GetResourceManager()->GetTouchScreen()->GetTouchScreenConfiguration(
209 const Result result = GetResourceManager()->GetTouchScreen()->GetTouchScreenConfiguration( 199 *out_touchscreen_config, aruid.pid));
210 touchscreen_config, applet_resource_user_id);
211 200
212 if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 && 201 if (out_touchscreen_config->mode != Core::HID::TouchScreenModeForNx::Heat2 &&
213 touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) { 202 out_touchscreen_config->mode != Core::HID::TouchScreenModeForNx::Finger) {
214 touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting; 203 out_touchscreen_config->mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
215 } 204 }
216 205
217 IPC::ResponseBuilder rb{ctx, 6}; 206 R_SUCCEED();
218 rb.Push(result);
219 rb.PushRaw(touchscreen_config);
220} 207}
221 208
222void IHidDebugServer::ProcessTouchScreenAutoTune(HLERequestContext& ctx) { 209Result IHidDebugServer::ProcessTouchScreenAutoTune() {
223 LOG_INFO(Service_HID, "called"); 210 LOG_INFO(Service_HID, "called");
224 211 R_RETURN(GetResourceManager()->GetTouchScreen()->ProcessTouchScreenAutoTune());
225 Result result = GetResourceManager()->GetTouchScreen()->ProcessTouchScreenAutoTune();
226
227 IPC::ResponseBuilder rb{ctx, 2};
228 rb.Push(result);
229} 212}
230 213
231void IHidDebugServer::ForceStopTouchScreenManagement(HLERequestContext& ctx) { 214Result IHidDebugServer::ForceStopTouchScreenManagement() {
232 LOG_INFO(Service_HID, "called"); 215 LOG_INFO(Service_HID, "called");
233 216
234 if (!firmware_settings->IsDeviceManaged()) { 217 if (!firmware_settings->IsDeviceManaged()) {
235 IPC::ResponseBuilder rb{ctx, 2}; 218 R_SUCCEED();
236 rb.Push(ResultSuccess);
237 return;
238 } 219 }
239 220
240 Result result = ResultSuccess;
241 bool is_touch_active{};
242 bool is_gesture_active{};
243 auto touch_screen = GetResourceManager()->GetTouchScreen(); 221 auto touch_screen = GetResourceManager()->GetTouchScreen();
244 auto gesture = GetResourceManager()->GetGesture(); 222 auto gesture = GetResourceManager()->GetGesture();
245 223
246 if (firmware_settings->IsTouchI2cManaged()) { 224 if (firmware_settings->IsTouchI2cManaged()) {
247 result = touch_screen->IsActive(is_touch_active); 225 bool is_touch_active{};
248 if (result.IsSuccess()) { 226 bool is_gesture_active{};
249 result = gesture->IsActive(is_gesture_active); 227 R_TRY(touch_screen->IsActive(is_touch_active));
250 } 228 R_TRY(gesture->IsActive(is_gesture_active));
251 if (result.IsSuccess() && is_touch_active) { 229
252 result = touch_screen->Deactivate(); 230 if (is_touch_active) {
231 R_TRY(touch_screen->Deactivate());
253 } 232 }
254 if (result.IsSuccess() && is_gesture_active) { 233 if (is_gesture_active) {
255 result = gesture->Deactivate(); 234 R_TRY(gesture->Deactivate());
256 } 235 }
257 } 236 }
258 237
259 IPC::ResponseBuilder rb{ctx, 2}; 238 R_SUCCEED();
260 rb.Push(result);
261} 239}
262 240
263void IHidDebugServer::ForceRestartTouchScreenManagement(HLERequestContext& ctx) { 241Result IHidDebugServer::ForceRestartTouchScreenManagement(u32 basic_gesture_id,
264 IPC::RequestParser rp{ctx}; 242 ClientAppletResourceUserId aruid) {
265 struct Parameters {
266 u32 basic_gesture_id;
267 INSERT_PADDING_WORDS_NOINIT(1);
268 u64 applet_resource_user_id;
269 };
270 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
271
272 const auto parameters{rp.PopRaw<Parameters>()};
273
274 LOG_INFO(Service_HID, "called, basic_gesture_id={}, applet_resource_user_id={}", 243 LOG_INFO(Service_HID, "called, basic_gesture_id={}, applet_resource_user_id={}",
275 parameters.basic_gesture_id, parameters.applet_resource_user_id); 244 basic_gesture_id, aruid.pid);
276 245
277 Result result = ResultSuccess;
278 auto touch_screen = GetResourceManager()->GetTouchScreen(); 246 auto touch_screen = GetResourceManager()->GetTouchScreen();
279 auto gesture = GetResourceManager()->GetGesture(); 247 auto gesture = GetResourceManager()->GetGesture();
280 248
281 if (firmware_settings->IsDeviceManaged() && firmware_settings->IsTouchI2cManaged()) { 249 if (firmware_settings->IsDeviceManaged() && firmware_settings->IsTouchI2cManaged()) {
282 result = gesture->Activate(); 250 R_TRY(gesture->Activate());
283 if (result.IsSuccess()) { 251 R_TRY(gesture->Activate(aruid.pid, basic_gesture_id));
284 result = 252 R_TRY(touch_screen->Activate());
285 gesture->Activate(parameters.applet_resource_user_id, parameters.basic_gesture_id); 253 R_TRY(touch_screen->Activate(aruid.pid));
286 }
287 if (result.IsSuccess()) {
288 result = touch_screen->Activate();
289 }
290 if (result.IsSuccess()) {
291 result = touch_screen->Activate(parameters.applet_resource_user_id);
292 }
293 } 254 }
294 255
295 IPC::ResponseBuilder rb{ctx, 2}; 256 R_SUCCEED();
296 rb.Push(result);
297} 257}
298 258
299void IHidDebugServer::IsTouchScreenManaged(HLERequestContext& ctx) { 259Result IHidDebugServer::IsTouchScreenManaged(Out<bool> out_is_managed) {
300 LOG_INFO(Service_HID, "called"); 260 LOG_INFO(Service_HID, "called");
301 261
302 bool is_touch_active{}; 262 bool is_touch_active{};
303 bool is_gesture_active{}; 263 bool is_gesture_active{};
264 R_TRY(GetResourceManager()->GetTouchScreen()->IsActive(is_touch_active));
265 R_TRY(GetResourceManager()->GetGesture()->IsActive(is_gesture_active));
304 266
305 Result result = GetResourceManager()->GetTouchScreen()->IsActive(is_touch_active); 267 *out_is_managed = is_touch_active || is_gesture_active;
306 if (result.IsSuccess()) { 268 R_SUCCEED();
307 result = GetResourceManager()->GetGesture()->IsActive(is_gesture_active);
308 }
309
310 IPC::ResponseBuilder rb{ctx, 3};
311 rb.Push(result);
312 rb.Push(is_touch_active | is_gesture_active);
313} 269}
314 270
315void IHidDebugServer::DeactivateGesture(HLERequestContext& ctx) { 271Result IHidDebugServer::DeactivateGesture() {
316 LOG_INFO(Service_HID, "called"); 272 LOG_INFO(Service_HID, "called");
317 273
318 Result result = ResultSuccess;
319
320 if (!firmware_settings->IsDeviceManaged()) { 274 if (!firmware_settings->IsDeviceManaged()) {
321 result = GetResourceManager()->GetGesture()->Deactivate(); 275 R_RETURN(GetResourceManager()->GetGesture()->Deactivate());
322 } 276 }
323 277
324 IPC::ResponseBuilder rb{ctx, 2}; 278 R_SUCCEED();
325 rb.Push(result);
326} 279}
327 280
328std::shared_ptr<ResourceManager> IHidDebugServer::GetResourceManager() { 281std::shared_ptr<ResourceManager> IHidDebugServer::GetResourceManager() {
diff --git a/src/core/hle/service/hid/hid_debug_server.h b/src/core/hle/service/hid/hid_debug_server.h
index 7d5b082b3..3a483f07e 100644
--- a/src/core/hle/service/hid/hid_debug_server.h
+++ b/src/core/hle/service/hid/hid_debug_server.h
@@ -3,7 +3,9 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/cmif_types.h"
6#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8#include "hid_core/resources/touch_screen/touch_types.h"
7 9
8namespace Core { 10namespace Core {
9class System; 11class System;
@@ -20,15 +22,19 @@ public:
20 ~IHidDebugServer() override; 22 ~IHidDebugServer() override;
21 23
22private: 24private:
23 void DeactivateTouchScreen(HLERequestContext& ctx); 25 Result DeactivateTouchScreen();
24 void SetTouchScreenAutoPilotState(HLERequestContext& ctx); 26 Result SetTouchScreenAutoPilotState(
25 void UnsetTouchScreenAutoPilotState(HLERequestContext& ctx); 27 InArray<TouchState, BufferAttr_HipcMapAlias> auto_pilot_buffer);
26 void GetTouchScreenConfiguration(HLERequestContext& ctx); 28 Result UnsetTouchScreenAutoPilotState();
27 void ProcessTouchScreenAutoTune(HLERequestContext& ctx); 29 Result GetTouchScreenConfiguration(
28 void ForceStopTouchScreenManagement(HLERequestContext& ctx); 30 Out<Core::HID::TouchScreenConfigurationForNx> out_touchscreen_config,
29 void ForceRestartTouchScreenManagement(HLERequestContext& ctx); 31 ClientAppletResourceUserId aruid);
30 void IsTouchScreenManaged(HLERequestContext& ctx); 32 Result ProcessTouchScreenAutoTune();
31 void DeactivateGesture(HLERequestContext& ctx); 33 Result ForceStopTouchScreenManagement();
34 Result ForceRestartTouchScreenManagement(u32 basic_gesture_id,
35 ClientAppletResourceUserId aruid);
36 Result IsTouchScreenManaged(Out<bool> out_is_managed);
37 Result DeactivateGesture();
32 38
33 std::shared_ptr<ResourceManager> GetResourceManager(); 39 std::shared_ptr<ResourceManager> GetResourceManager();
34 40
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
index 18e544f2f..7d7368ff9 100644
--- a/src/core/hle/service/hid/irs.cpp
+++ b/src/core/hle/service/hid/irs.cpp
@@ -9,6 +9,7 @@
9#include "core/hle/kernel/k_shared_memory.h" 9#include "core/hle/kernel/k_shared_memory.h"
10#include "core/hle/kernel/k_transfer_memory.h" 10#include "core/hle/kernel/k_transfer_memory.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
12#include "core/hle/service/cmif_serialization.h"
12#include "core/hle/service/hid/irs.h" 13#include "core/hle/service/hid/irs.h"
13#include "core/hle/service/ipc_helpers.h" 14#include "core/hle/service/ipc_helpers.h"
14#include "core/memory.h" 15#include "core/memory.h"
@@ -28,24 +29,24 @@ namespace Service::IRS {
28IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} { 29IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} {
29 // clang-format off 30 // clang-format off
30 static const FunctionInfo functions[] = { 31 static const FunctionInfo functions[] = {
31 {302, &IRS::ActivateIrsensor, "ActivateIrsensor"}, 32 {302, C<&IRS::ActivateIrsensor>, "ActivateIrsensor"},
32 {303, &IRS::DeactivateIrsensor, "DeactivateIrsensor"}, 33 {303, C<&IRS::DeactivateIrsensor>, "DeactivateIrsensor"},
33 {304, &IRS::GetIrsensorSharedMemoryHandle, "GetIrsensorSharedMemoryHandle"}, 34 {304, C<&IRS::GetIrsensorSharedMemoryHandle>, "GetIrsensorSharedMemoryHandle"},
34 {305, &IRS::StopImageProcessor, "StopImageProcessor"}, 35 {305, C<&IRS::StopImageProcessor>, "StopImageProcessor"},
35 {306, &IRS::RunMomentProcessor, "RunMomentProcessor"}, 36 {306, C<&IRS::RunMomentProcessor>, "RunMomentProcessor"},
36 {307, &IRS::RunClusteringProcessor, "RunClusteringProcessor"}, 37 {307, C<&IRS::RunClusteringProcessor>, "RunClusteringProcessor"},
37 {308, &IRS::RunImageTransferProcessor, "RunImageTransferProcessor"}, 38 {308, C<&IRS::RunImageTransferProcessor>, "RunImageTransferProcessor"},
38 {309, &IRS::GetImageTransferProcessorState, "GetImageTransferProcessorState"}, 39 {309, C<&IRS::GetImageTransferProcessorState>, "GetImageTransferProcessorState"},
39 {310, &IRS::RunTeraPluginProcessor, "RunTeraPluginProcessor"}, 40 {310, C<&IRS::RunTeraPluginProcessor>, "RunTeraPluginProcessor"},
40 {311, &IRS::GetNpadIrCameraHandle, "GetNpadIrCameraHandle"}, 41 {311, C<&IRS::GetNpadIrCameraHandle>, "GetNpadIrCameraHandle"},
41 {312, &IRS::RunPointingProcessor, "RunPointingProcessor"}, 42 {312, C<&IRS::RunPointingProcessor>, "RunPointingProcessor"},
42 {313, &IRS::SuspendImageProcessor, "SuspendImageProcessor"}, 43 {313, C<&IRS::SuspendImageProcessor>, "SuspendImageProcessor"},
43 {314, &IRS::CheckFirmwareVersion, "CheckFirmwareVersion"}, 44 {314, C<&IRS::CheckFirmwareVersion>, "CheckFirmwareVersion"},
44 {315, &IRS::SetFunctionLevel, "SetFunctionLevel"}, 45 {315, C<&IRS::SetFunctionLevel>, "SetFunctionLevel"},
45 {316, &IRS::RunImageTransferExProcessor, "RunImageTransferExProcessor"}, 46 {316, C<&IRS::RunImageTransferExProcessor>, "RunImageTransferExProcessor"},
46 {317, &IRS::RunIrLedProcessor, "RunIrLedProcessor"}, 47 {317, C<&IRS::RunIrLedProcessor>, "RunIrLedProcessor"},
47 {318, &IRS::StopImageProcessorAsync, "StopImageProcessorAsync"}, 48 {318, C<&IRS::StopImageProcessorAsync>, "StopImageProcessorAsync"},
48 {319, &IRS::ActivateIrsensorWithFunctionLevel, "ActivateIrsensorWithFunctionLevel"}, 49 {319, C<&IRS::ActivateIrsensorWithFunctionLevel>, "ActivateIrsensorWithFunctionLevel"},
49 }; 50 };
50 // clang-format on 51 // clang-format on
51 52
@@ -57,489 +58,292 @@ IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} {
57} 58}
58IRS::~IRS() = default; 59IRS::~IRS() = default;
59 60
60void IRS::ActivateIrsensor(HLERequestContext& ctx) { 61Result IRS::ActivateIrsensor(ClientAppletResourceUserId aruid) {
61 IPC::RequestParser rp{ctx}; 62 LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}", aruid.pid);
62 const auto applet_resource_user_id{rp.Pop<u64>()}; 63 R_SUCCEED();
63
64 LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}",
65 applet_resource_user_id);
66
67 IPC::ResponseBuilder rb{ctx, 2};
68 rb.Push(ResultSuccess);
69} 64}
70 65
71void IRS::DeactivateIrsensor(HLERequestContext& ctx) { 66Result IRS::DeactivateIrsensor(ClientAppletResourceUserId aruid) {
72 IPC::RequestParser rp{ctx}; 67 LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}", aruid.pid);
73 const auto applet_resource_user_id{rp.Pop<u64>()}; 68 R_SUCCEED();
74
75 LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}",
76 applet_resource_user_id);
77
78 IPC::ResponseBuilder rb{ctx, 2};
79 rb.Push(ResultSuccess);
80} 69}
81 70
82void IRS::GetIrsensorSharedMemoryHandle(HLERequestContext& ctx) { 71Result IRS::GetIrsensorSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory,
83 IPC::RequestParser rp{ctx}; 72 ClientAppletResourceUserId aruid) {
84 const auto applet_resource_user_id{rp.Pop<u64>()}; 73 LOG_DEBUG(Service_IRS, "called, applet_resource_user_id={}", aruid.pid);
85
86 LOG_DEBUG(Service_IRS, "called, applet_resource_user_id={}", applet_resource_user_id);
87 74
88 IPC::ResponseBuilder rb{ctx, 2, 1}; 75 *out_shared_memory = &system.Kernel().GetIrsSharedMem();
89 rb.Push(ResultSuccess); 76 R_SUCCEED();
90 rb.PushCopyObjects(&system.Kernel().GetIrsSharedMem());
91} 77}
92 78
93void IRS::StopImageProcessor(HLERequestContext& ctx) { 79Result IRS::StopImageProcessor(Core::IrSensor::IrCameraHandle camera_handle,
94 IPC::RequestParser rp{ctx}; 80 ClientAppletResourceUserId aruid) {
95 struct Parameters {
96 Core::IrSensor::IrCameraHandle camera_handle;
97 INSERT_PADDING_WORDS_NOINIT(1);
98 u64 applet_resource_user_id;
99 };
100 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
101
102 const auto parameters{rp.PopRaw<Parameters>()};
103
104 LOG_WARNING(Service_IRS, 81 LOG_WARNING(Service_IRS,
105 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", 82 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
106 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 83 camera_handle.npad_type, camera_handle.npad_id, aruid.pid);
107 parameters.applet_resource_user_id);
108
109 auto result = IsIrCameraHandleValid(parameters.camera_handle);
110 if (result.IsSuccess()) {
111 // TODO: Stop Image processor
112 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
113 Common::Input::PollingMode::Active);
114 result = ResultSuccess;
115 }
116 84
117 IPC::ResponseBuilder rb{ctx, 2}; 85 R_TRY(IsIrCameraHandleValid(camera_handle));
118 rb.Push(result);
119}
120
121void IRS::RunMomentProcessor(HLERequestContext& ctx) {
122 IPC::RequestParser rp{ctx};
123 struct Parameters {
124 Core::IrSensor::IrCameraHandle camera_handle;
125 INSERT_PADDING_WORDS_NOINIT(1);
126 u64 applet_resource_user_id;
127 Core::IrSensor::PackedMomentProcessorConfig processor_config;
128 };
129 static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size.");
130 86
131 const auto parameters{rp.PopRaw<Parameters>()}; 87 // TODO: Stop Image processor
88 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
89 Common::Input::PollingMode::Active);
90 R_SUCCEED();
91}
132 92
93Result IRS::RunMomentProcessor(
94 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
95 const Core::IrSensor::PackedMomentProcessorConfig& processor_config) {
133 LOG_WARNING(Service_IRS, 96 LOG_WARNING(Service_IRS,
134 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", 97 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
135 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 98 camera_handle.npad_type, camera_handle.npad_id, aruid.pid);
136 parameters.applet_resource_user_id);
137
138 const auto result = IsIrCameraHandleValid(parameters.camera_handle);
139
140 if (result.IsSuccess()) {
141 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
142 MakeProcessorWithCoreContext<MomentProcessor>(parameters.camera_handle, device);
143 auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle);
144 image_transfer_processor.SetConfig(parameters.processor_config);
145 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
146 Common::Input::PollingMode::IR);
147 }
148 99
149 IPC::ResponseBuilder rb{ctx, 2}; 100 R_TRY(IsIrCameraHandleValid(camera_handle));
150 rb.Push(result);
151}
152 101
153void IRS::RunClusteringProcessor(HLERequestContext& ctx) { 102 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
154 IPC::RequestParser rp{ctx}; 103 MakeProcessorWithCoreContext<MomentProcessor>(camera_handle, device);
155 struct Parameters { 104 auto& image_transfer_processor = GetProcessor<MomentProcessor>(camera_handle);
156 Core::IrSensor::IrCameraHandle camera_handle; 105 image_transfer_processor.SetConfig(processor_config);
157 INSERT_PADDING_WORDS_NOINIT(1); 106 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
158 u64 applet_resource_user_id; 107 Common::Input::PollingMode::IR);
159 Core::IrSensor::PackedClusteringProcessorConfig processor_config;
160 };
161 static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size.");
162 108
163 const auto parameters{rp.PopRaw<Parameters>()}; 109 R_SUCCEED();
110}
164 111
112Result IRS::RunClusteringProcessor(
113 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
114 const Core::IrSensor::PackedClusteringProcessorConfig& processor_config) {
165 LOG_WARNING(Service_IRS, 115 LOG_WARNING(Service_IRS,
166 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", 116 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
167 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 117 camera_handle.npad_type, camera_handle.npad_id, aruid.pid);
168 parameters.applet_resource_user_id);
169
170 auto result = IsIrCameraHandleValid(parameters.camera_handle);
171
172 if (result.IsSuccess()) {
173 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
174 MakeProcessorWithCoreContext<ClusteringProcessor>(parameters.camera_handle, device);
175 auto& image_transfer_processor =
176 GetProcessor<ClusteringProcessor>(parameters.camera_handle);
177 image_transfer_processor.SetConfig(parameters.processor_config);
178 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
179 Common::Input::PollingMode::IR);
180 }
181 118
182 IPC::ResponseBuilder rb{ctx, 2}; 119 R_TRY(IsIrCameraHandleValid(camera_handle));
183 rb.Push(result);
184}
185 120
186void IRS::RunImageTransferProcessor(HLERequestContext& ctx) { 121 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
187 IPC::RequestParser rp{ctx}; 122 MakeProcessorWithCoreContext<ClusteringProcessor>(camera_handle, device);
188 struct Parameters { 123 auto& image_transfer_processor = GetProcessor<ClusteringProcessor>(camera_handle);
189 Core::IrSensor::IrCameraHandle camera_handle; 124 image_transfer_processor.SetConfig(processor_config);
190 INSERT_PADDING_WORDS_NOINIT(1); 125 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
191 u64 applet_resource_user_id; 126 Common::Input::PollingMode::IR);
192 Core::IrSensor::PackedImageTransferProcessorConfig processor_config;
193 u32 transfer_memory_size;
194 };
195 static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size.");
196 127
197 const auto parameters{rp.PopRaw<Parameters>()}; 128 R_SUCCEED();
198 const auto t_mem_handle{ctx.GetCopyHandle(0)}; 129}
199 130
200 auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle); 131Result IRS::RunImageTransferProcessor(
132 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
133 const Core::IrSensor::PackedImageTransferProcessorConfig& processor_config,
134 u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> t_mem) {
201 135
202 if (t_mem.IsNull()) { 136 ASSERT_MSG(t_mem->GetSize() == transfer_memory_size, "t_mem has incorrect size");
203 LOG_ERROR(Service_IRS, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
204 IPC::ResponseBuilder rb{ctx, 2};
205 rb.Push(ResultUnknown);
206 return;
207 }
208
209 ASSERT_MSG(t_mem->GetSize() == parameters.transfer_memory_size, "t_mem has incorrect size");
210 137
211 LOG_INFO(Service_IRS, 138 LOG_INFO(Service_IRS,
212 "called, npad_type={}, npad_id={}, transfer_memory_size={}, transfer_memory_size={}, " 139 "called, npad_type={}, npad_id={}, transfer_memory_size={}, transfer_memory_size={}, "
213 "applet_resource_user_id={}", 140 "applet_resource_user_id={}",
214 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 141 camera_handle.npad_type, camera_handle.npad_id, transfer_memory_size, t_mem->GetSize(),
215 parameters.transfer_memory_size, t_mem->GetSize(), parameters.applet_resource_user_id); 142 aruid.pid);
216
217 const auto result = IsIrCameraHandleValid(parameters.camera_handle);
218
219 if (result.IsSuccess()) {
220 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
221 MakeProcessorWithCoreContext<ImageTransferProcessor>(parameters.camera_handle, device);
222 auto& image_transfer_processor =
223 GetProcessor<ImageTransferProcessor>(parameters.camera_handle);
224 image_transfer_processor.SetConfig(parameters.processor_config);
225 image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress());
226 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
227 Common::Input::PollingMode::IR);
228 }
229 143
230 IPC::ResponseBuilder rb{ctx, 2}; 144 R_TRY(IsIrCameraHandleValid(camera_handle));
231 rb.Push(result);
232}
233 145
234void IRS::GetImageTransferProcessorState(HLERequestContext& ctx) { 146 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
235 IPC::RequestParser rp{ctx}; 147 MakeProcessorWithCoreContext<ImageTransferProcessor>(camera_handle, device);
236 struct Parameters { 148 auto& image_transfer_processor = GetProcessor<ImageTransferProcessor>(camera_handle);
237 Core::IrSensor::IrCameraHandle camera_handle; 149 image_transfer_processor.SetConfig(processor_config);
238 INSERT_PADDING_WORDS_NOINIT(1); 150 image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress());
239 u64 applet_resource_user_id; 151 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
240 }; 152 Common::Input::PollingMode::IR);
241 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
242 153
243 const auto parameters{rp.PopRaw<Parameters>()}; 154 R_SUCCEED();
155}
244 156
157Result IRS::GetImageTransferProcessorState(
158 Out<Core::IrSensor::ImageTransferProcessorState> out_state,
159 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
160 OutBuffer<BufferAttr_HipcMapAlias> out_buffer_data) {
245 LOG_DEBUG(Service_IRS, "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", 161 LOG_DEBUG(Service_IRS, "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
246 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 162 camera_handle.npad_type, camera_handle.npad_id, aruid.pid);
247 parameters.applet_resource_user_id);
248
249 const auto result = IsIrCameraHandleValid(parameters.camera_handle);
250 if (result.IsError()) {
251 IPC::ResponseBuilder rb{ctx, 2};
252 rb.Push(result);
253 return;
254 }
255 163
256 const auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); 164 R_TRY(IsIrCameraHandleValid(camera_handle));
257 165
258 if (device.mode != Core::IrSensor::IrSensorMode::ImageTransferProcessor) { 166 const auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
259 IPC::ResponseBuilder rb{ctx, 2}; 167
260 rb.Push(InvalidProcessorState); 168 R_TRY(IsIrCameraHandleValid(camera_handle));
261 return; 169 R_UNLESS(device.mode == Core::IrSensor::IrSensorMode::ImageTransferProcessor,
262 } 170 InvalidProcessorState);
263 171
264 std::vector<u8> data{}; 172 *out_state = GetProcessor<ImageTransferProcessor>(camera_handle).GetState(out_buffer_data);
265 const auto& image_transfer_processor =
266 GetProcessor<ImageTransferProcessor>(parameters.camera_handle);
267 const auto& state = image_transfer_processor.GetState(data);
268 173
269 ctx.WriteBuffer(data); 174 R_SUCCEED();
270 IPC::ResponseBuilder rb{ctx, 6};
271 rb.Push(ResultSuccess);
272 rb.PushRaw(state);
273} 175}
274 176
275void IRS::RunTeraPluginProcessor(HLERequestContext& ctx) { 177Result IRS::RunTeraPluginProcessor(Core::IrSensor::IrCameraHandle camera_handle,
276 IPC::RequestParser rp{ctx}; 178 Core::IrSensor::PackedTeraPluginProcessorConfig processor_config,
277 struct Parameters { 179 ClientAppletResourceUserId aruid) {
278 Core::IrSensor::IrCameraHandle camera_handle; 180 LOG_WARNING(Service_IRS,
279 Core::IrSensor::PackedTeraPluginProcessorConfig processor_config; 181 "(STUBBED) called, npad_type={}, npad_id={}, mode={}, mcu_version={}.{}, "
280 INSERT_PADDING_WORDS_NOINIT(1); 182 "applet_resource_user_id={}",
281 u64 applet_resource_user_id; 183 camera_handle.npad_type, camera_handle.npad_id, processor_config.mode,
282 }; 184 processor_config.required_mcu_version.major,
283 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); 185 processor_config.required_mcu_version.minor, aruid.pid);
284 186
285 const auto parameters{rp.PopRaw<Parameters>()}; 187 R_TRY(IsIrCameraHandleValid(camera_handle));
286 188
287 LOG_WARNING( 189 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
288 Service_IRS, 190 MakeProcessor<TeraPluginProcessor>(camera_handle, device);
289 "(STUBBED) called, npad_type={}, npad_id={}, mode={}, mcu_version={}.{}, " 191 auto& image_transfer_processor = GetProcessor<TeraPluginProcessor>(camera_handle);
290 "applet_resource_user_id={}", 192 image_transfer_processor.SetConfig(processor_config);
291 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 193 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
292 parameters.processor_config.mode, parameters.processor_config.required_mcu_version.major, 194 Common::Input::PollingMode::IR);
293 parameters.processor_config.required_mcu_version.minor, parameters.applet_resource_user_id);
294
295 const auto result = IsIrCameraHandleValid(parameters.camera_handle);
296
297 if (result.IsSuccess()) {
298 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
299 MakeProcessor<TeraPluginProcessor>(parameters.camera_handle, device);
300 auto& image_transfer_processor =
301 GetProcessor<TeraPluginProcessor>(parameters.camera_handle);
302 image_transfer_processor.SetConfig(parameters.processor_config);
303 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
304 Common::Input::PollingMode::IR);
305 }
306 195
307 IPC::ResponseBuilder rb{ctx, 2}; 196 R_SUCCEED();
308 rb.Push(result);
309} 197}
310 198
311void IRS::GetNpadIrCameraHandle(HLERequestContext& ctx) { 199Result IRS::GetNpadIrCameraHandle(Out<Core::IrSensor::IrCameraHandle> out_camera_handle,
312 IPC::RequestParser rp{ctx}; 200 Core::HID::NpadIdType npad_id) {
313 const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()}; 201 R_UNLESS(HID::IsNpadIdValid(npad_id), HID::ResultInvalidNpadId);
314
315 if (npad_id > Core::HID::NpadIdType::Player8 && npad_id != Core::HID::NpadIdType::Invalid &&
316 npad_id != Core::HID::NpadIdType::Handheld) {
317 IPC::ResponseBuilder rb{ctx, 2};
318 rb.Push(Service::HID::ResultInvalidNpadId);
319 return;
320 }
321 202
322 Core::IrSensor::IrCameraHandle camera_handle{ 203 *out_camera_handle = {
323 .npad_id = static_cast<u8>(HID::NpadIdTypeToIndex(npad_id)), 204 .npad_id = static_cast<u8>(HID::NpadIdTypeToIndex(npad_id)),
324 .npad_type = Core::HID::NpadStyleIndex::None, 205 .npad_type = Core::HID::NpadStyleIndex::None,
325 }; 206 };
326 207
327 LOG_INFO(Service_IRS, "called, npad_id={}, camera_npad_id={}, camera_npad_type={}", npad_id, 208 LOG_INFO(Service_IRS, "called, npad_id={}, camera_npad_id={}, camera_npad_type={}", npad_id,
328 camera_handle.npad_id, camera_handle.npad_type); 209 out_camera_handle->npad_id, out_camera_handle->npad_type);
329 210
330 IPC::ResponseBuilder rb{ctx, 3}; 211 R_SUCCEED();
331 rb.Push(ResultSuccess);
332 rb.PushRaw(camera_handle);
333} 212}
334 213
335void IRS::RunPointingProcessor(HLERequestContext& ctx) { 214Result IRS::RunPointingProcessor(
336 IPC::RequestParser rp{ctx}; 215 Core::IrSensor::IrCameraHandle camera_handle,
337 const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; 216 const Core::IrSensor::PackedPointingProcessorConfig& processor_config,
338 const auto processor_config{rp.PopRaw<Core::IrSensor::PackedPointingProcessorConfig>()}; 217 ClientAppletResourceUserId aruid) {
339 const auto applet_resource_user_id{rp.Pop<u64>()};
340
341 LOG_WARNING( 218 LOG_WARNING(
342 Service_IRS, 219 Service_IRS,
343 "(STUBBED) called, npad_type={}, npad_id={}, mcu_version={}.{}, applet_resource_user_id={}", 220 "(STUBBED) called, npad_type={}, npad_id={}, mcu_version={}.{}, applet_resource_user_id={}",
344 camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major, 221 camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major,
345 processor_config.required_mcu_version.minor, applet_resource_user_id); 222 processor_config.required_mcu_version.minor, aruid.pid);
346 223
347 auto result = IsIrCameraHandleValid(camera_handle); 224 R_TRY(IsIrCameraHandleValid(camera_handle));
348 225
349 if (result.IsSuccess()) { 226 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
350 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle); 227 MakeProcessor<PointingProcessor>(camera_handle, device);
351 MakeProcessor<PointingProcessor>(camera_handle, device); 228 auto& image_transfer_processor = GetProcessor<PointingProcessor>(camera_handle);
352 auto& image_transfer_processor = GetProcessor<PointingProcessor>(camera_handle); 229 image_transfer_processor.SetConfig(processor_config);
353 image_transfer_processor.SetConfig(processor_config); 230 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
354 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, 231 Common::Input::PollingMode::IR);
355 Common::Input::PollingMode::IR);
356 }
357 232
358 IPC::ResponseBuilder rb{ctx, 2}; 233 R_SUCCEED();
359 rb.Push(result);
360} 234}
361 235
362void IRS::SuspendImageProcessor(HLERequestContext& ctx) { 236Result IRS::SuspendImageProcessor(Core::IrSensor::IrCameraHandle camera_handle,
363 IPC::RequestParser rp{ctx}; 237 ClientAppletResourceUserId aruid) {
364 struct Parameters {
365 Core::IrSensor::IrCameraHandle camera_handle;
366 INSERT_PADDING_WORDS_NOINIT(1);
367 u64 applet_resource_user_id;
368 };
369 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
370
371 const auto parameters{rp.PopRaw<Parameters>()};
372
373 LOG_WARNING(Service_IRS, 238 LOG_WARNING(Service_IRS,
374 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", 239 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
375 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 240 camera_handle.npad_type, camera_handle.npad_id, aruid.pid);
376 parameters.applet_resource_user_id);
377 241
378 auto result = IsIrCameraHandleValid(parameters.camera_handle); 242 R_TRY(IsIrCameraHandleValid(camera_handle));
379 if (result.IsSuccess()) {
380 // TODO: Suspend image processor
381 result = ResultSuccess;
382 }
383 243
384 IPC::ResponseBuilder rb{ctx, 2}; 244 // TODO: Suspend image processor
385 rb.Push(result);
386}
387 245
388void IRS::CheckFirmwareVersion(HLERequestContext& ctx) { 246 R_SUCCEED();
389 IPC::RequestParser rp{ctx}; 247}
390 const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
391 const auto mcu_version{rp.PopRaw<Core::IrSensor::PackedMcuVersion>()};
392 const auto applet_resource_user_id{rp.Pop<u64>()};
393 248
249Result IRS::CheckFirmwareVersion(Core::IrSensor::IrCameraHandle camera_handle,
250 Core::IrSensor::PackedMcuVersion mcu_version,
251 ClientAppletResourceUserId aruid) {
394 LOG_WARNING( 252 LOG_WARNING(
395 Service_IRS, 253 Service_IRS,
396 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}, mcu_version={}.{}", 254 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}, mcu_version={}.{}",
397 camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major, 255 camera_handle.npad_type, camera_handle.npad_id, aruid.pid, mcu_version.major,
398 mcu_version.minor); 256 mcu_version.minor);
399 257
400 auto result = IsIrCameraHandleValid(camera_handle); 258 R_TRY(IsIrCameraHandleValid(camera_handle));
401 if (result.IsSuccess()) {
402 // TODO: Check firmware version
403 result = ResultSuccess;
404 }
405 259
406 IPC::ResponseBuilder rb{ctx, 2}; 260 // TODO: Check firmware version
407 rb.Push(result);
408}
409 261
410void IRS::SetFunctionLevel(HLERequestContext& ctx) { 262 R_SUCCEED();
411 IPC::RequestParser rp{ctx}; 263}
412 const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
413 const auto function_level{rp.PopRaw<Core::IrSensor::PackedFunctionLevel>()};
414 const auto applet_resource_user_id{rp.Pop<u64>()};
415 264
265Result IRS::SetFunctionLevel(Core::IrSensor::IrCameraHandle camera_handle,
266 Core::IrSensor::PackedFunctionLevel function_level,
267 ClientAppletResourceUserId aruid) {
416 LOG_WARNING( 268 LOG_WARNING(
417 Service_IRS, 269 Service_IRS,
418 "(STUBBED) called, npad_type={}, npad_id={}, function_level={}, applet_resource_user_id={}", 270 "(STUBBED) called, npad_type={}, npad_id={}, function_level={}, applet_resource_user_id={}",
419 camera_handle.npad_type, camera_handle.npad_id, function_level.function_level, 271 camera_handle.npad_type, camera_handle.npad_id, function_level.function_level, aruid.pid);
420 applet_resource_user_id);
421 272
422 auto result = IsIrCameraHandleValid(camera_handle); 273 R_TRY(IsIrCameraHandleValid(camera_handle));
423 if (result.IsSuccess()) {
424 // TODO: Set Function level
425 result = ResultSuccess;
426 }
427 274
428 IPC::ResponseBuilder rb{ctx, 2}; 275 // TODO: Set Function level
429 rb.Push(result);
430}
431 276
432void IRS::RunImageTransferExProcessor(HLERequestContext& ctx) { 277 R_SUCCEED();
433 IPC::RequestParser rp{ctx}; 278}
434 struct Parameters {
435 Core::IrSensor::IrCameraHandle camera_handle;
436 INSERT_PADDING_WORDS_NOINIT(1);
437 u64 applet_resource_user_id;
438 Core::IrSensor::PackedImageTransferProcessorExConfig processor_config;
439 u64 transfer_memory_size;
440 };
441 static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size.");
442 279
443 const auto parameters{rp.PopRaw<Parameters>()}; 280Result IRS::RunImageTransferExProcessor(
444 const auto t_mem_handle{ctx.GetCopyHandle(0)}; 281 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
282 const Core::IrSensor::PackedImageTransferProcessorExConfig& processor_config,
283 u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> t_mem) {
445 284
446 auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle); 285 ASSERT_MSG(t_mem->GetSize() == transfer_memory_size, "t_mem has incorrect size");
447 286
448 LOG_INFO(Service_IRS, 287 LOG_INFO(Service_IRS,
449 "called, npad_type={}, npad_id={}, transfer_memory_size={}, " 288 "called, npad_type={}, npad_id={}, transfer_memory_size={}, "
450 "applet_resource_user_id={}", 289 "applet_resource_user_id={}",
451 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 290 camera_handle.npad_type, camera_handle.npad_id, transfer_memory_size, aruid.pid);
452 parameters.transfer_memory_size, parameters.applet_resource_user_id);
453
454 auto result = IsIrCameraHandleValid(parameters.camera_handle);
455
456 if (result.IsSuccess()) {
457 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
458 MakeProcessorWithCoreContext<ImageTransferProcessor>(parameters.camera_handle, device);
459 auto& image_transfer_processor =
460 GetProcessor<ImageTransferProcessor>(parameters.camera_handle);
461 image_transfer_processor.SetConfig(parameters.processor_config);
462 image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress());
463 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
464 Common::Input::PollingMode::IR);
465 }
466 291
467 IPC::ResponseBuilder rb{ctx, 2}; 292 R_TRY(IsIrCameraHandleValid(camera_handle));
468 rb.Push(result); 293
469} 294 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
295 MakeProcessorWithCoreContext<ImageTransferProcessor>(camera_handle, device);
296 auto& image_transfer_processor = GetProcessor<ImageTransferProcessor>(camera_handle);
297 image_transfer_processor.SetConfig(processor_config);
298 image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress());
299 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
300 Common::Input::PollingMode::IR);
470 301
471void IRS::RunIrLedProcessor(HLERequestContext& ctx) { 302 R_SUCCEED();
472 IPC::RequestParser rp{ctx}; 303}
473 const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
474 const auto processor_config{rp.PopRaw<Core::IrSensor::PackedIrLedProcessorConfig>()};
475 const auto applet_resource_user_id{rp.Pop<u64>()};
476 304
305Result IRS::RunIrLedProcessor(Core::IrSensor::IrCameraHandle camera_handle,
306 Core::IrSensor::PackedIrLedProcessorConfig processor_config,
307 ClientAppletResourceUserId aruid) {
477 LOG_WARNING(Service_IRS, 308 LOG_WARNING(Service_IRS,
478 "(STUBBED) called, npad_type={}, npad_id={}, light_target={}, mcu_version={}.{} " 309 "(STUBBED) called, npad_type={}, npad_id={}, light_target={}, mcu_version={}.{} "
479 "applet_resource_user_id={}", 310 "applet_resource_user_id={}",
480 camera_handle.npad_type, camera_handle.npad_id, processor_config.light_target, 311 camera_handle.npad_type, camera_handle.npad_id, processor_config.light_target,
481 processor_config.required_mcu_version.major, 312 processor_config.required_mcu_version.major,
482 processor_config.required_mcu_version.minor, applet_resource_user_id); 313 processor_config.required_mcu_version.minor, aruid.pid);
483 314
484 auto result = IsIrCameraHandleValid(camera_handle); 315 R_TRY(IsIrCameraHandleValid(camera_handle));
485 316
486 if (result.IsSuccess()) { 317 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
487 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle); 318 MakeProcessor<IrLedProcessor>(camera_handle, device);
488 MakeProcessor<IrLedProcessor>(camera_handle, device); 319 auto& image_transfer_processor = GetProcessor<IrLedProcessor>(camera_handle);
489 auto& image_transfer_processor = GetProcessor<IrLedProcessor>(camera_handle); 320 image_transfer_processor.SetConfig(processor_config);
490 image_transfer_processor.SetConfig(processor_config); 321 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
491 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, 322 Common::Input::PollingMode::IR);
492 Common::Input::PollingMode::IR);
493 }
494 323
495 IPC::ResponseBuilder rb{ctx, 2}; 324 R_SUCCEED();
496 rb.Push(result);
497} 325}
498 326
499void IRS::StopImageProcessorAsync(HLERequestContext& ctx) { 327Result IRS::StopImageProcessorAsync(Core::IrSensor::IrCameraHandle camera_handle,
500 IPC::RequestParser rp{ctx}; 328 ClientAppletResourceUserId aruid) {
501 struct Parameters {
502 Core::IrSensor::IrCameraHandle camera_handle;
503 INSERT_PADDING_WORDS_NOINIT(1);
504 u64 applet_resource_user_id;
505 };
506 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
507
508 const auto parameters{rp.PopRaw<Parameters>()};
509
510 LOG_WARNING(Service_IRS, 329 LOG_WARNING(Service_IRS,
511 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", 330 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
512 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 331 camera_handle.npad_type, camera_handle.npad_id, aruid.pid);
513 parameters.applet_resource_user_id);
514
515 auto result = IsIrCameraHandleValid(parameters.camera_handle);
516 if (result.IsSuccess()) {
517 // TODO: Stop image processor async
518 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
519 Common::Input::PollingMode::Active);
520 result = ResultSuccess;
521 }
522 332
523 IPC::ResponseBuilder rb{ctx, 2}; 333 R_TRY(IsIrCameraHandleValid(camera_handle));
524 rb.Push(result);
525}
526 334
527void IRS::ActivateIrsensorWithFunctionLevel(HLERequestContext& ctx) { 335 // TODO: Stop image processor async
528 IPC::RequestParser rp{ctx}; 336 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
529 struct Parameters { 337 Common::Input::PollingMode::Active);
530 Core::IrSensor::PackedFunctionLevel function_level;
531 INSERT_PADDING_WORDS_NOINIT(1);
532 u64 applet_resource_user_id;
533 };
534 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
535 338
536 const auto parameters{rp.PopRaw<Parameters>()}; 339 R_SUCCEED();
340}
537 341
342Result IRS::ActivateIrsensorWithFunctionLevel(Core::IrSensor::PackedFunctionLevel function_level,
343 ClientAppletResourceUserId aruid) {
538 LOG_WARNING(Service_IRS, "(STUBBED) called, function_level={}, applet_resource_user_id={}", 344 LOG_WARNING(Service_IRS, "(STUBBED) called, function_level={}, applet_resource_user_id={}",
539 parameters.function_level.function_level, parameters.applet_resource_user_id); 345 function_level.function_level, aruid.pid);
540 346 R_SUCCEED();
541 IPC::ResponseBuilder rb{ctx, 2};
542 rb.Push(ResultSuccess);
543} 347}
544 348
545Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const { 349Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const {
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h
index 06b7279ee..58dfee6c3 100644
--- a/src/core/hle/service/hid/irs.h
+++ b/src/core/hle/service/hid/irs.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
8#include "hid_core/hid_types.h" 9#include "hid_core/hid_types.h"
9#include "hid_core/irsensor/irs_types.h" 10#include "hid_core/irsensor/irs_types.h"
@@ -35,26 +36,73 @@ private:
35 }; 36 };
36 static_assert(sizeof(StatusManager) == 0x8000, "StatusManager is an invalid size"); 37 static_assert(sizeof(StatusManager) == 0x8000, "StatusManager is an invalid size");
37 38
38 void ActivateIrsensor(HLERequestContext& ctx); 39 Result ActivateIrsensor(ClientAppletResourceUserId aruid);
39 void DeactivateIrsensor(HLERequestContext& ctx); 40
40 void GetIrsensorSharedMemoryHandle(HLERequestContext& ctx); 41 Result DeactivateIrsensor(ClientAppletResourceUserId aruid);
41 void StopImageProcessor(HLERequestContext& ctx); 42
42 void RunMomentProcessor(HLERequestContext& ctx); 43 Result GetIrsensorSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory,
43 void RunClusteringProcessor(HLERequestContext& ctx); 44 ClientAppletResourceUserId aruid);
44 void RunImageTransferProcessor(HLERequestContext& ctx); 45 Result StopImageProcessor(Core::IrSensor::IrCameraHandle camera_handle,
45 void GetImageTransferProcessorState(HLERequestContext& ctx); 46 ClientAppletResourceUserId aruid);
46 void RunTeraPluginProcessor(HLERequestContext& ctx); 47
47 void GetNpadIrCameraHandle(HLERequestContext& ctx); 48 Result RunMomentProcessor(Core::IrSensor::IrCameraHandle camera_handle,
48 void RunPointingProcessor(HLERequestContext& ctx); 49 ClientAppletResourceUserId aruid,
49 void SuspendImageProcessor(HLERequestContext& ctx); 50 const Core::IrSensor::PackedMomentProcessorConfig& processor_config);
50 void CheckFirmwareVersion(HLERequestContext& ctx); 51
51 void SetFunctionLevel(HLERequestContext& ctx); 52 Result RunClusteringProcessor(
52 void RunImageTransferExProcessor(HLERequestContext& ctx); 53 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
53 void RunIrLedProcessor(HLERequestContext& ctx); 54 const Core::IrSensor::PackedClusteringProcessorConfig& processor_config);
54 void StopImageProcessorAsync(HLERequestContext& ctx); 55
55 void ActivateIrsensorWithFunctionLevel(HLERequestContext& ctx); 56 Result RunImageTransferProcessor(
57 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
58 const Core::IrSensor::PackedImageTransferProcessorConfig& processor_config,
59 u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> t_mem);
60
61 Result GetImageTransferProcessorState(
62 Out<Core::IrSensor::ImageTransferProcessorState> out_state,
63 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
64 OutBuffer<BufferAttr_HipcMapAlias> out_buffer_data);
65
66 Result RunTeraPluginProcessor(Core::IrSensor::IrCameraHandle camera_handle,
67 Core::IrSensor::PackedTeraPluginProcessorConfig processor_config,
68 ClientAppletResourceUserId aruid);
69
70 Result GetNpadIrCameraHandle(Out<Core::IrSensor::IrCameraHandle> out_camera_handle,
71 Core::HID::NpadIdType npad_id);
72
73 Result RunPointingProcessor(
74 Core::IrSensor::IrCameraHandle camera_handle,
75 const Core::IrSensor::PackedPointingProcessorConfig& processor_config,
76 ClientAppletResourceUserId aruid);
77
78 Result SuspendImageProcessor(Core::IrSensor::IrCameraHandle camera_handle,
79 ClientAppletResourceUserId aruid);
80
81 Result CheckFirmwareVersion(Core::IrSensor::IrCameraHandle camera_handle,
82 Core::IrSensor::PackedMcuVersion mcu_version,
83 ClientAppletResourceUserId aruid);
84
85 Result SetFunctionLevel(Core::IrSensor::IrCameraHandle camera_handle,
86 Core::IrSensor::PackedFunctionLevel function_level,
87 ClientAppletResourceUserId aruid);
88
89 Result RunImageTransferExProcessor(
90 Core::IrSensor::IrCameraHandle camera_handle, ClientAppletResourceUserId aruid,
91 const Core::IrSensor::PackedImageTransferProcessorExConfig& processor_config,
92 u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> t_mem);
93
94 Result RunIrLedProcessor(Core::IrSensor::IrCameraHandle camera_handle,
95 Core::IrSensor::PackedIrLedProcessorConfig processor_config,
96 ClientAppletResourceUserId aruid);
97
98 Result StopImageProcessorAsync(Core::IrSensor::IrCameraHandle camera_handle,
99 ClientAppletResourceUserId aruid);
100
101 Result ActivateIrsensorWithFunctionLevel(Core::IrSensor::PackedFunctionLevel function_level,
102 ClientAppletResourceUserId aruid);
56 103
57 Result IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const; 104 Result IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const;
105
58 Core::IrSensor::DeviceFormat& GetIrCameraSharedMemoryDeviceEntry( 106 Core::IrSensor::DeviceFormat& GetIrCameraSharedMemoryDeviceEntry(
59 const Core::IrSensor::IrCameraHandle& camera_handle); 107 const Core::IrSensor::IrCameraHandle& camera_handle);
60 108
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index e6646ba04..68fe38874 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -123,6 +123,8 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
123 vm.va_range_end = params.va_range_end; 123 vm.va_range_end = params.va_range_end;
124 } 124 }
125 125
126 const u64 max_big_page_bits = Common::Log2Ceil64(vm.va_range_end);
127
126 const auto start_pages{static_cast<u32>(vm.va_range_start >> VM::PAGE_SIZE_BITS)}; 128 const auto start_pages{static_cast<u32>(vm.va_range_start >> VM::PAGE_SIZE_BITS)};
127 const auto end_pages{static_cast<u32>(vm.va_range_split >> VM::PAGE_SIZE_BITS)}; 129 const auto end_pages{static_cast<u32>(vm.va_range_split >> VM::PAGE_SIZE_BITS)};
128 vm.small_page_allocator = std::make_shared<VM::Allocator>(start_pages, end_pages); 130 vm.small_page_allocator = std::make_shared<VM::Allocator>(start_pages, end_pages);
@@ -132,8 +134,8 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
132 static_cast<u32>((vm.va_range_end - vm.va_range_split) >> vm.big_page_size_bits)}; 134 static_cast<u32>((vm.va_range_end - vm.va_range_split) >> vm.big_page_size_bits)};
133 vm.big_page_allocator = std::make_unique<VM::Allocator>(start_big_pages, end_big_pages); 135 vm.big_page_allocator = std::make_unique<VM::Allocator>(start_big_pages, end_big_pages);
134 136
135 gmmu = std::make_shared<Tegra::MemoryManager>(system, 40, vm.big_page_size_bits, 137 gmmu = std::make_shared<Tegra::MemoryManager>(system, max_big_page_bits, vm.va_range_split,
136 VM::PAGE_SIZE_BITS); 138 vm.big_page_size_bits, VM::PAGE_SIZE_BITS);
137 system.GPU().InitAddressSpace(*gmmu); 139 system.GPU().InitAddressSpace(*gmmu);
138 vm.initialised = true; 140 vm.initialised = true;
139 141
diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp
index c720dd1f8..ba2b5c28c 100644
--- a/src/core/hle/service/nvnflinger/hardware_composer.cpp
+++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp
@@ -7,7 +7,6 @@
7#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" 7#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
8#include "core/hle/service/nvnflinger/buffer_item.h" 8#include "core/hle/service/nvnflinger/buffer_item.h"
9#include "core/hle/service/nvnflinger/buffer_item_consumer.h" 9#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
10#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
11#include "core/hle/service/nvnflinger/hardware_composer.h" 10#include "core/hle/service/nvnflinger/hardware_composer.h"
12#include "core/hle/service/nvnflinger/hwc_layer.h" 11#include "core/hle/service/nvnflinger/hwc_layer.h"
13#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" 12#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
@@ -46,31 +45,9 @@ HardwareComposer::HardwareComposer() = default;
46HardwareComposer::~HardwareComposer() = default; 45HardwareComposer::~HardwareComposer() = default;
47 46
48u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, 47u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
49 Nvidia::Devices::nvdisp_disp0& nvdisp, u32 frame_advance) { 48 Nvidia::Devices::nvdisp_disp0& nvdisp) {
50 boost::container::small_vector<HwcLayer, 2> composition_stack; 49 boost::container::small_vector<HwcLayer, 2> composition_stack;
51 50
52 m_frame_number += frame_advance;
53
54 // Release any necessary framebuffers.
55 for (auto& [layer_id, framebuffer] : m_framebuffers) {
56 if (framebuffer.release_frame_number > m_frame_number) {
57 // Not yet ready to release this framebuffer.
58 continue;
59 }
60
61 if (!framebuffer.is_acquired) {
62 // Already released.
63 continue;
64 }
65
66 if (auto* layer = display.FindLayer(layer_id); layer != nullptr) {
67 // TODO: support release fence
68 // This is needed to prevent screen tearing
69 layer->GetConsumer().ReleaseBuffer(framebuffer.item, android::Fence::NoFence());
70 framebuffer.is_acquired = false;
71 }
72 }
73
74 // Set default speed limit to 100%. 51 // Set default speed limit to 100%.
75 *out_speed_scale = 1.0f; 52 *out_speed_scale = 1.0f;
76 53
@@ -142,7 +119,30 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
142 MicroProfileFlip(); 119 MicroProfileFlip();
143 120
144 // Advance by at least one frame. 121 // Advance by at least one frame.
145 return swap_interval.value_or(1); 122 const u32 frame_advance = swap_interval.value_or(1);
123 m_frame_number += frame_advance;
124
125 // Release any necessary framebuffers.
126 for (auto& [layer_id, framebuffer] : m_framebuffers) {
127 if (framebuffer.release_frame_number > m_frame_number) {
128 // Not yet ready to release this framebuffer.
129 continue;
130 }
131
132 if (!framebuffer.is_acquired) {
133 // Already released.
134 continue;
135 }
136
137 if (auto* layer = display.FindLayer(layer_id); layer != nullptr) {
138 // TODO: support release fence
139 // This is needed to prevent screen tearing
140 layer->GetConsumer().ReleaseBuffer(framebuffer.item, android::Fence::NoFence());
141 framebuffer.is_acquired = false;
142 }
143 }
144
145 return frame_advance;
146} 146}
147 147
148void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) { 148void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) {
diff --git a/src/core/hle/service/nvnflinger/hardware_composer.h b/src/core/hle/service/nvnflinger/hardware_composer.h
index ddab94ac9..28392c512 100644
--- a/src/core/hle/service/nvnflinger/hardware_composer.h
+++ b/src/core/hle/service/nvnflinger/hardware_composer.h
@@ -27,7 +27,7 @@ public:
27 ~HardwareComposer(); 27 ~HardwareComposer();
28 28
29 u32 ComposeLocked(f32* out_speed_scale, VI::Display& display, 29 u32 ComposeLocked(f32* out_speed_scale, VI::Display& display,
30 Nvidia::Devices::nvdisp_disp0& nvdisp, u32 frame_advance); 30 Nvidia::Devices::nvdisp_disp0& nvdisp);
31 void RemoveLayerLocked(VI::Display& display, LayerId layer_id); 31 void RemoveLayerLocked(VI::Display& display, LayerId layer_id);
32 32
33private: 33private:
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index a4e848882..d8ba89d43 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -291,8 +291,7 @@ void Nvnflinger::Compose() {
291 auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd); 291 auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd);
292 ASSERT(nvdisp); 292 ASSERT(nvdisp);
293 293
294 swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp, 294 swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp);
295 swap_interval);
296 } 295 }
297} 296}
298 297
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index 96fa7fa3a..14d1a3840 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -9,6 +9,7 @@
9#include "core/core_timing.h" 9#include "core/core_timing.h"
10#include "core/hle/kernel/k_page_table.h" 10#include "core/hle/kernel/k_page_table.h"
11#include "core/hle/kernel/k_process.h" 11#include "core/hle/kernel/k_process.h"
12#include "core/hle/kernel/k_process_page_table.h"
12#include "core/hle/service/hid/hid_server.h" 13#include "core/hle/service/hid/hid_server.h"
13#include "core/hle/service/sm/sm.h" 14#include "core/hle/service/sm/sm.h"
14#include "core/memory.h" 15#include "core/memory.h"
@@ -46,12 +47,23 @@ StandardVmCallbacks::StandardVmCallbacks(System& system_, const CheatProcessMeta
46 47
47StandardVmCallbacks::~StandardVmCallbacks() = default; 48StandardVmCallbacks::~StandardVmCallbacks() = default;
48 49
49void StandardVmCallbacks::MemoryRead(VAddr address, void* data, u64 size) { 50void StandardVmCallbacks::MemoryReadUnsafe(VAddr address, void* data, u64 size) {
50 system.ApplicationMemory().ReadBlock(SanitizeAddress(address), data, size); 51 // Return zero on invalid address
52 if (!IsAddressInRange(address) || !system.ApplicationMemory().IsValidVirtualAddress(address)) {
53 std::memset(data, 0, size);
54 return;
55 }
56
57 system.ApplicationMemory().ReadBlock(address, data, size);
51} 58}
52 59
53void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size) { 60void StandardVmCallbacks::MemoryWriteUnsafe(VAddr address, const void* data, u64 size) {
54 system.ApplicationMemory().WriteBlock(SanitizeAddress(address), data, size); 61 // Skip invalid memory write address
62 if (!IsAddressInRange(address) || !system.ApplicationMemory().IsValidVirtualAddress(address)) {
63 return;
64 }
65
66 system.ApplicationMemory().WriteBlock(address, data, size);
55} 67}
56 68
57u64 StandardVmCallbacks::HidKeysDown() { 69u64 StandardVmCallbacks::HidKeysDown() {
@@ -81,21 +93,25 @@ void StandardVmCallbacks::CommandLog(std::string_view data) {
81 data.back() == '\n' ? data.substr(0, data.size() - 1) : data); 93 data.back() == '\n' ? data.substr(0, data.size() - 1) : data);
82} 94}
83 95
84VAddr StandardVmCallbacks::SanitizeAddress(VAddr in) const { 96bool StandardVmCallbacks::IsAddressInRange(VAddr in) const {
85 if ((in < metadata.main_nso_extents.base || 97 if ((in < metadata.main_nso_extents.base ||
86 in >= metadata.main_nso_extents.base + metadata.main_nso_extents.size) && 98 in >= metadata.main_nso_extents.base + metadata.main_nso_extents.size) &&
87 (in < metadata.heap_extents.base || 99 (in < metadata.heap_extents.base ||
88 in >= metadata.heap_extents.base + metadata.heap_extents.size)) { 100 in >= metadata.heap_extents.base + metadata.heap_extents.size) &&
89 LOG_ERROR(CheatEngine, 101 (in < metadata.alias_extents.base ||
102 in >= metadata.heap_extents.base + metadata.alias_extents.size) &&
103 (in < metadata.aslr_extents.base ||
104 in >= metadata.heap_extents.base + metadata.aslr_extents.size)) {
105 LOG_DEBUG(CheatEngine,
90 "Cheat attempting to access memory at invalid address={:016X}, if this " 106 "Cheat attempting to access memory at invalid address={:016X}, if this "
91 "persists, " 107 "persists, "
92 "the cheat may be incorrect. However, this may be normal early in execution if " 108 "the cheat may be incorrect. However, this may be normal early in execution if "
93 "the game has not properly set up yet.", 109 "the game has not properly set up yet.",
94 in); 110 in);
95 return 0; ///< Invalid addresses will hard crash 111 return false; ///< Invalid addresses will hard crash
96 } 112 }
97 113
98 return in; 114 return true;
99} 115}
100 116
101CheatParser::~CheatParser() = default; 117CheatParser::~CheatParser() = default;
@@ -211,16 +227,14 @@ void CheatEngine::Initialize() {
211 .base = GetInteger(page_table.GetHeapRegionStart()), 227 .base = GetInteger(page_table.GetHeapRegionStart()),
212 .size = page_table.GetHeapRegionSize(), 228 .size = page_table.GetHeapRegionSize(),
213 }; 229 };
214 230 metadata.aslr_extents = {
215 metadata.address_space_extents = {
216 .base = GetInteger(page_table.GetAddressSpaceStart()),
217 .size = page_table.GetAddressSpaceSize(),
218 };
219
220 metadata.alias_extents = {
221 .base = GetInteger(page_table.GetAliasCodeRegionStart()), 231 .base = GetInteger(page_table.GetAliasCodeRegionStart()),
222 .size = page_table.GetAliasCodeRegionSize(), 232 .size = page_table.GetAliasCodeRegionSize(),
223 }; 233 };
234 metadata.alias_extents = {
235 .base = GetInteger(page_table.GetAliasRegionStart()),
236 .size = page_table.GetAliasRegionSize(),
237 };
224 238
225 is_pending_reload.exchange(true); 239 is_pending_reload.exchange(true);
226} 240}
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h
index ced2168d1..619cabaa2 100644
--- a/src/core/memory/cheat_engine.h
+++ b/src/core/memory/cheat_engine.h
@@ -27,17 +27,17 @@ public:
27 StandardVmCallbacks(System& system_, const CheatProcessMetadata& metadata_); 27 StandardVmCallbacks(System& system_, const CheatProcessMetadata& metadata_);
28 ~StandardVmCallbacks() override; 28 ~StandardVmCallbacks() override;
29 29
30 void MemoryRead(VAddr address, void* data, u64 size) override; 30 void MemoryReadUnsafe(VAddr address, void* data, u64 size) override;
31 void MemoryWrite(VAddr address, const void* data, u64 size) override; 31 void MemoryWriteUnsafe(VAddr address, const void* data, u64 size) override;
32 u64 HidKeysDown() override; 32 u64 HidKeysDown() override;
33 void DebugLog(u8 id, u64 value) override; 33 void DebugLog(u8 id, u64 value) override;
34 void CommandLog(std::string_view data) override; 34 void CommandLog(std::string_view data) override;
35 35
36private: 36private:
37 VAddr SanitizeAddress(VAddr address) const; 37 bool IsAddressInRange(VAddr address) const;
38 38
39 const CheatProcessMetadata& metadata; 39 const CheatProcessMetadata& metadata;
40 System& system; 40 Core::System& system;
41}; 41};
42 42
43// Intermediary class that parses a text file or other disk format for storing cheats into a 43// Intermediary class that parses a text file or other disk format for storing cheats into a
diff --git a/src/core/memory/dmnt_cheat_types.h b/src/core/memory/dmnt_cheat_types.h
index c6b40e505..64c072d3d 100644
--- a/src/core/memory/dmnt_cheat_types.h
+++ b/src/core/memory/dmnt_cheat_types.h
@@ -18,7 +18,7 @@ struct CheatProcessMetadata {
18 MemoryRegionExtents main_nso_extents{}; 18 MemoryRegionExtents main_nso_extents{};
19 MemoryRegionExtents heap_extents{}; 19 MemoryRegionExtents heap_extents{};
20 MemoryRegionExtents alias_extents{}; 20 MemoryRegionExtents alias_extents{};
21 MemoryRegionExtents address_space_extents{}; 21 MemoryRegionExtents aslr_extents{};
22 std::array<u8, 0x20> main_nso_build_id{}; 22 std::array<u8, 0x20> main_nso_build_id{};
23}; 23};
24 24
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp
index 31ffc4fbb..8bc81e72d 100644
--- a/src/core/memory/dmnt_cheat_vm.cpp
+++ b/src/core/memory/dmnt_cheat_vm.cpp
@@ -322,8 +322,9 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
322 } break; 322 } break;
323 case CheatVmOpcodeType::EndConditionalBlock: { 323 case CheatVmOpcodeType::EndConditionalBlock: {
324 // 20000000 324 // 20000000
325 // There's actually nothing left to process here! 325 opcode.opcode = EndConditionalOpcode{
326 opcode.opcode = EndConditionalOpcode{}; 326 .is_else = ((first_dword >> 24) & 0xf) == 1,
327 };
327 } break; 328 } break;
328 case CheatVmOpcodeType::ControlLoop: { 329 case CheatVmOpcodeType::ControlLoop: {
329 // 300R0000 VVVVVVVV 330 // 300R0000 VVVVVVVV
@@ -555,6 +556,18 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
555 .idx = first_dword & 0xF, 556 .idx = first_dword & 0xF,
556 }; 557 };
557 } break; 558 } break;
559 case CheatVmOpcodeType::PauseProcess: {
560 /* FF0????? */
561 /* FF0 = opcode 0xFF0 */
562 /* Pauses the current process. */
563 opcode.opcode = PauseProcessOpcode{};
564 } break;
565 case CheatVmOpcodeType::ResumeProcess: {
566 /* FF0????? */
567 /* FF0 = opcode 0xFF0 */
568 /* Pauses the current process. */
569 opcode.opcode = ResumeProcessOpcode{};
570 } break;
558 case CheatVmOpcodeType::DebugLog: { 571 case CheatVmOpcodeType::DebugLog: {
559 // FFFTIX## 572 // FFFTIX##
560 // FFFTI0Ma aaaaaaaa 573 // FFFTI0Ma aaaaaaaa
@@ -621,7 +634,7 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
621 return valid; 634 return valid;
622} 635}
623 636
624void DmntCheatVm::SkipConditionalBlock() { 637void DmntCheatVm::SkipConditionalBlock(bool is_if) {
625 if (condition_depth > 0) { 638 if (condition_depth > 0) {
626 // We want to continue until we're out of the current block. 639 // We want to continue until we're out of the current block.
627 const std::size_t desired_depth = condition_depth - 1; 640 const std::size_t desired_depth = condition_depth - 1;
@@ -637,8 +650,12 @@ void DmntCheatVm::SkipConditionalBlock() {
637 // We also support nesting of conditional blocks, and Gateway does not. 650 // We also support nesting of conditional blocks, and Gateway does not.
638 if (skip_opcode.begin_conditional_block) { 651 if (skip_opcode.begin_conditional_block) {
639 condition_depth++; 652 condition_depth++;
640 } else if (std::holds_alternative<EndConditionalOpcode>(skip_opcode.opcode)) { 653 } else if (auto end_cond = std::get_if<EndConditionalOpcode>(&skip_opcode.opcode)) {
641 condition_depth--; 654 if (!end_cond->is_else) {
655 condition_depth--;
656 } else if (is_if && condition_depth - 1 == desired_depth) {
657 break;
658 }
642 } 659 }
643 } 660 }
644 } else { 661 } else {
@@ -675,6 +692,10 @@ u64 DmntCheatVm::GetCheatProcessAddress(const CheatProcessMetadata& metadata,
675 return metadata.main_nso_extents.base + rel_address; 692 return metadata.main_nso_extents.base + rel_address;
676 case MemoryAccessType::Heap: 693 case MemoryAccessType::Heap:
677 return metadata.heap_extents.base + rel_address; 694 return metadata.heap_extents.base + rel_address;
695 case MemoryAccessType::Alias:
696 return metadata.alias_extents.base + rel_address;
697 case MemoryAccessType::Aslr:
698 return metadata.aslr_extents.base + rel_address;
678 } 699 }
679} 700}
680 701
@@ -682,7 +703,6 @@ void DmntCheatVm::ResetState() {
682 registers.fill(0); 703 registers.fill(0);
683 saved_values.fill(0); 704 saved_values.fill(0);
684 loop_tops.fill(0); 705 loop_tops.fill(0);
685 static_registers.fill(0);
686 instruction_ptr = 0; 706 instruction_ptr = 0;
687 condition_depth = 0; 707 condition_depth = 0;
688 decode_success = true; 708 decode_success = true;
@@ -753,7 +773,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
753 case 2: 773 case 2:
754 case 4: 774 case 4:
755 case 8: 775 case 8:
756 callbacks->MemoryWrite(dst_address, &dst_value, store_static->bit_width); 776 callbacks->MemoryWriteUnsafe(dst_address, &dst_value, store_static->bit_width);
757 break; 777 break;
758 } 778 }
759 } else if (auto begin_cond = std::get_if<BeginConditionalOpcode>(&cur_opcode.opcode)) { 779 } else if (auto begin_cond = std::get_if<BeginConditionalOpcode>(&cur_opcode.opcode)) {
@@ -766,7 +786,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
766 case 2: 786 case 2:
767 case 4: 787 case 4:
768 case 8: 788 case 8:
769 callbacks->MemoryRead(src_address, &src_value, begin_cond->bit_width); 789 callbacks->MemoryReadUnsafe(src_address, &src_value, begin_cond->bit_width);
770 break; 790 break;
771 } 791 }
772 // Check against condition. 792 // Check against condition.
@@ -794,13 +814,18 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
794 } 814 }
795 // Skip conditional block if condition not met. 815 // Skip conditional block if condition not met.
796 if (!cond_met) { 816 if (!cond_met) {
797 SkipConditionalBlock(); 817 SkipConditionalBlock(true);
798 } 818 }
799 } else if (std::holds_alternative<EndConditionalOpcode>(cur_opcode.opcode)) { 819 } else if (auto end_cond = std::get_if<EndConditionalOpcode>(&cur_opcode.opcode)) {
800 // Decrement the condition depth. 820 if (end_cond->is_else) {
801 // We will assume, graciously, that mismatched conditional block ends are a nop. 821 /* Skip to the end of the conditional block. */
802 if (condition_depth > 0) { 822 this->SkipConditionalBlock(false);
803 condition_depth--; 823 } else {
824 /* Decrement the condition depth. */
825 /* We will assume, graciously, that mismatched conditional block ends are a nop. */
826 if (condition_depth > 0) {
827 condition_depth--;
828 }
804 } 829 }
805 } else if (auto ctrl_loop = std::get_if<ControlLoopOpcode>(&cur_opcode.opcode)) { 830 } else if (auto ctrl_loop = std::get_if<ControlLoopOpcode>(&cur_opcode.opcode)) {
806 if (ctrl_loop->start_loop) { 831 if (ctrl_loop->start_loop) {
@@ -832,8 +857,8 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
832 case 2: 857 case 2:
833 case 4: 858 case 4:
834 case 8: 859 case 8:
835 callbacks->MemoryRead(src_address, &registers[ldr_memory->reg_index], 860 callbacks->MemoryReadUnsafe(src_address, &registers[ldr_memory->reg_index],
836 ldr_memory->bit_width); 861 ldr_memory->bit_width);
837 break; 862 break;
838 } 863 }
839 } else if (auto str_static = std::get_if<StoreStaticToAddressOpcode>(&cur_opcode.opcode)) { 864 } else if (auto str_static = std::get_if<StoreStaticToAddressOpcode>(&cur_opcode.opcode)) {
@@ -849,7 +874,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
849 case 2: 874 case 2:
850 case 4: 875 case 4:
851 case 8: 876 case 8:
852 callbacks->MemoryWrite(dst_address, &dst_value, str_static->bit_width); 877 callbacks->MemoryWriteUnsafe(dst_address, &dst_value, str_static->bit_width);
853 break; 878 break;
854 } 879 }
855 // Increment register if relevant. 880 // Increment register if relevant.
@@ -908,7 +933,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
908 // Check for keypress. 933 // Check for keypress.
909 if ((begin_keypress_cond->key_mask & kDown) != begin_keypress_cond->key_mask) { 934 if ((begin_keypress_cond->key_mask & kDown) != begin_keypress_cond->key_mask) {
910 // Keys not pressed. Skip conditional block. 935 // Keys not pressed. Skip conditional block.
911 SkipConditionalBlock(); 936 SkipConditionalBlock(true);
912 } 937 }
913 } else if (auto perform_math_reg = 938 } else if (auto perform_math_reg =
914 std::get_if<PerformArithmeticRegisterOpcode>(&cur_opcode.opcode)) { 939 std::get_if<PerformArithmeticRegisterOpcode>(&cur_opcode.opcode)) {
@@ -1007,7 +1032,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
1007 case 2: 1032 case 2:
1008 case 4: 1033 case 4:
1009 case 8: 1034 case 8:
1010 callbacks->MemoryWrite(dst_address, &dst_value, str_register->bit_width); 1035 callbacks->MemoryWriteUnsafe(dst_address, &dst_value, str_register->bit_width);
1011 break; 1036 break;
1012 } 1037 }
1013 1038
@@ -1086,7 +1111,8 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
1086 case 2: 1111 case 2:
1087 case 4: 1112 case 4:
1088 case 8: 1113 case 8:
1089 callbacks->MemoryRead(cond_address, &cond_value, begin_reg_cond->bit_width); 1114 callbacks->MemoryReadUnsafe(cond_address, &cond_value,
1115 begin_reg_cond->bit_width);
1090 break; 1116 break;
1091 } 1117 }
1092 } 1118 }
@@ -1116,7 +1142,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
1116 1142
1117 // Skip conditional block if condition not met. 1143 // Skip conditional block if condition not met.
1118 if (!cond_met) { 1144 if (!cond_met) {
1119 SkipConditionalBlock(); 1145 SkipConditionalBlock(true);
1120 } 1146 }
1121 } else if (auto save_restore_reg = 1147 } else if (auto save_restore_reg =
1122 std::get_if<SaveRestoreRegisterOpcode>(&cur_opcode.opcode)) { 1148 std::get_if<SaveRestoreRegisterOpcode>(&cur_opcode.opcode)) {
@@ -1178,6 +1204,10 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
1178 // Store a register to a static register. 1204 // Store a register to a static register.
1179 static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx]; 1205 static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx];
1180 } 1206 }
1207 } else if (std::holds_alternative<PauseProcessOpcode>(cur_opcode.opcode)) {
1208 // TODO: Pause cheat process
1209 } else if (std::holds_alternative<ResumeProcessOpcode>(cur_opcode.opcode)) {
1210 // TODO: Resume cheat process
1181 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { 1211 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) {
1182 // Read value from memory. 1212 // Read value from memory.
1183 u64 log_value = 0; 1213 u64 log_value = 0;
@@ -1224,7 +1254,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
1224 case 2: 1254 case 2:
1225 case 4: 1255 case 4:
1226 case 8: 1256 case 8:
1227 callbacks->MemoryRead(val_address, &log_value, debug_log->bit_width); 1257 callbacks->MemoryReadUnsafe(val_address, &log_value, debug_log->bit_width);
1228 break; 1258 break;
1229 } 1259 }
1230 } 1260 }
diff --git a/src/core/memory/dmnt_cheat_vm.h b/src/core/memory/dmnt_cheat_vm.h
index 641cb09c4..fed6a24ad 100644
--- a/src/core/memory/dmnt_cheat_vm.h
+++ b/src/core/memory/dmnt_cheat_vm.h
@@ -42,12 +42,16 @@ enum class CheatVmOpcodeType : u32 {
42 DoubleExtendedWidth = 0xF0, 42 DoubleExtendedWidth = 0xF0,
43 43
44 // Double-extended width opcodes. 44 // Double-extended width opcodes.
45 PauseProcess = 0xFF0,
46 ResumeProcess = 0xFF1,
45 DebugLog = 0xFFF, 47 DebugLog = 0xFFF,
46}; 48};
47 49
48enum class MemoryAccessType : u32 { 50enum class MemoryAccessType : u32 {
49 MainNso = 0, 51 MainNso = 0,
50 Heap = 1, 52 Heap = 1,
53 Alias = 2,
54 Aslr = 3,
51}; 55};
52 56
53enum class ConditionalComparisonType : u32 { 57enum class ConditionalComparisonType : u32 {
@@ -131,7 +135,9 @@ struct BeginConditionalOpcode {
131 VmInt value{}; 135 VmInt value{};
132}; 136};
133 137
134struct EndConditionalOpcode {}; 138struct EndConditionalOpcode {
139 bool is_else;
140};
135 141
136struct ControlLoopOpcode { 142struct ControlLoopOpcode {
137 bool start_loop{}; 143 bool start_loop{};
@@ -222,6 +228,10 @@ struct ReadWriteStaticRegisterOpcode {
222 u32 idx{}; 228 u32 idx{};
223}; 229};
224 230
231struct PauseProcessOpcode {};
232
233struct ResumeProcessOpcode {};
234
225struct DebugLogOpcode { 235struct DebugLogOpcode {
226 u32 bit_width{}; 236 u32 bit_width{};
227 u32 log_id{}; 237 u32 log_id{};
@@ -244,8 +254,8 @@ struct CheatVmOpcode {
244 PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, 254 PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode,
245 PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, 255 PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode,
246 BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, 256 BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode,
247 SaveRestoreRegisterMaskOpcode, ReadWriteStaticRegisterOpcode, DebugLogOpcode, 257 SaveRestoreRegisterMaskOpcode, ReadWriteStaticRegisterOpcode, PauseProcessOpcode,
248 UnrecognizedInstruction> 258 ResumeProcessOpcode, DebugLogOpcode, UnrecognizedInstruction>
249 opcode{}; 259 opcode{};
250}; 260};
251 261
@@ -256,8 +266,8 @@ public:
256 public: 266 public:
257 virtual ~Callbacks(); 267 virtual ~Callbacks();
258 268
259 virtual void MemoryRead(VAddr address, void* data, u64 size) = 0; 269 virtual void MemoryReadUnsafe(VAddr address, void* data, u64 size) = 0;
260 virtual void MemoryWrite(VAddr address, const void* data, u64 size) = 0; 270 virtual void MemoryWriteUnsafe(VAddr address, const void* data, u64 size) = 0;
261 271
262 virtual u64 HidKeysDown() = 0; 272 virtual u64 HidKeysDown() = 0;
263 273
@@ -296,7 +306,7 @@ private:
296 std::array<std::size_t, NumRegisters> loop_tops{}; 306 std::array<std::size_t, NumRegisters> loop_tops{};
297 307
298 bool DecodeNextOpcode(CheatVmOpcode& out); 308 bool DecodeNextOpcode(CheatVmOpcode& out);
299 void SkipConditionalBlock(); 309 void SkipConditionalBlock(bool is_if);
300 void ResetState(); 310 void ResetState();
301 311
302 // For implementing the DebugLog opcode. 312 // For implementing the DebugLog opcode.
diff --git a/src/hid_core/irsensor/image_transfer_processor.cpp b/src/hid_core/irsensor/image_transfer_processor.cpp
index d6573f8dc..2b5a50ef6 100644
--- a/src/hid_core/irsensor/image_transfer_processor.cpp
+++ b/src/hid_core/irsensor/image_transfer_processor.cpp
@@ -145,9 +145,8 @@ void ImageTransferProcessor::SetTransferMemoryAddress(Common::ProcessAddress t_m
145} 145}
146 146
147Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( 147Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState(
148 std::vector<u8>& data) const { 148 std::span<u8> data) const {
149 const auto size = GetDataSize(current_config.trimming_format); 149 const auto size = std::min(GetDataSize(current_config.trimming_format), data.size());
150 data.resize(size);
151 system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size); 150 system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size);
152 return processor_state; 151 return processor_state;
153} 152}
diff --git a/src/hid_core/irsensor/image_transfer_processor.h b/src/hid_core/irsensor/image_transfer_processor.h
index 4e0117084..df1c9d920 100644
--- a/src/hid_core/irsensor/image_transfer_processor.h
+++ b/src/hid_core/irsensor/image_transfer_processor.h
@@ -3,6 +3,8 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <span>
7
6#include "common/typed_address.h" 8#include "common/typed_address.h"
7#include "hid_core/irsensor/irs_types.h" 9#include "hid_core/irsensor/irs_types.h"
8#include "hid_core/irsensor/processor_base.h" 10#include "hid_core/irsensor/processor_base.h"
@@ -39,7 +41,7 @@ public:
39 // Transfer memory where the image data will be stored 41 // Transfer memory where the image data will be stored
40 void SetTransferMemoryAddress(Common::ProcessAddress t_mem); 42 void SetTransferMemoryAddress(Common::ProcessAddress t_mem);
41 43
42 Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; 44 Core::IrSensor::ImageTransferProcessorState GetState(std::span<u8> data) const;
43 45
44private: 46private:
45 // This is nn::irsensor::ImageTransferProcessorConfig 47 // This is nn::irsensor::ImageTransferProcessorConfig
diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp
index 6d759298e..0dde244ef 100644
--- a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp
+++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp
@@ -57,7 +57,7 @@ Result NpadAbstractSixAxisHandler::UpdateSixAxisState() {
57 Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); 57 Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
58 for (std::size_t i = 0; i < AruidIndexMax; i++) { 58 for (std::size_t i = 0; i < AruidIndexMax; i++) {
59 auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i); 59 auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i);
60 if (data->flag.is_assigned) { 60 if (data == nullptr || !data->flag.is_assigned) {
61 continue; 61 continue;
62 } 62 }
63 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; 63 auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp
index fe3fdc5cd..053625b55 100644
--- a/src/hid_core/resources/npad/npad.cpp
+++ b/src/hid_core/resources/npad/npad.cpp
@@ -131,7 +131,7 @@ void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t c
131 131
132 auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index); 132 auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index);
133 133
134 if (!data->flag.is_assigned) { 134 if (data == nullptr || !data->flag.is_assigned) {
135 continue; 135 continue;
136 } 136 }
137 137
@@ -463,13 +463,13 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
463 std::scoped_lock lock{*applet_resource_holder.shared_mutex}; 463 std::scoped_lock lock{*applet_resource_holder.shared_mutex};
464 for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { 464 for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) {
465 const auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index); 465 const auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index);
466 const auto aruid = data->aruid;
467 466
468 if (!data->flag.is_assigned) { 467 if (data == nullptr || !data->flag.is_assigned) {
469 continue; 468 continue;
470 } 469 }
471 470
472 bool is_set{}; 471 bool is_set{};
472 const auto aruid = data->aruid;
473 npad_resource.IsSupportedNpadStyleSet(is_set, aruid); 473 npad_resource.IsSupportedNpadStyleSet(is_set, aruid);
474 // Wait until style is defined 474 // Wait until style is defined
475 if (!is_set) { 475 if (!is_set) {
diff --git a/src/hid_core/resources/six_axis/six_axis.cpp b/src/hid_core/resources/six_axis/six_axis.cpp
index abb6fd152..b407a5c76 100644
--- a/src/hid_core/resources/six_axis/six_axis.cpp
+++ b/src/hid_core/resources/six_axis/six_axis.cpp
@@ -28,142 +28,148 @@ void SixAxis::OnRelease() {}
28 28
29void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 29void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
30 std::scoped_lock shared_lock{*shared_mutex}; 30 std::scoped_lock shared_lock{*shared_mutex};
31 const u64 aruid = applet_resource->GetActiveAruid();
32 auto* data = applet_resource->GetAruidData(aruid);
33 31
34 if (data == nullptr || !data->flag.is_assigned) { 32 for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) {
35 return; 33 const auto* data = applet_resource->GetAruidDataByIndex(aruid_index);
36 }
37
38 if (!IsControllerActivated()) {
39 return;
40 }
41 34
42 for (std::size_t i = 0; i < controller_data.size(); ++i) { 35 if (data == nullptr || !data->flag.is_assigned) {
43 NpadSharedMemoryEntry& shared_memory = data->shared_memory_format->npad.npad_entry[i];
44 auto& controller = controller_data[i];
45 const auto& controller_type = controller.device->GetNpadStyleIndex();
46
47 if (controller_type == Core::HID::NpadStyleIndex::None ||
48 !controller.device->IsConnected()) {
49 continue; 36 continue;
50 } 37 }
51 38
52 const auto& motion_state = controller.device->GetMotions(); 39 if (!IsControllerActivated()) {
53 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state; 40 return;
54 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
55 auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
56 auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
57 auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
58 auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
59
60 auto& sixaxis_fullkey_lifo = shared_memory.internal_state.sixaxis_fullkey_lifo;
61 auto& sixaxis_handheld_lifo = shared_memory.internal_state.sixaxis_handheld_lifo;
62 auto& sixaxis_dual_left_lifo = shared_memory.internal_state.sixaxis_dual_left_lifo;
63 auto& sixaxis_dual_right_lifo = shared_memory.internal_state.sixaxis_dual_right_lifo;
64 auto& sixaxis_left_lifo = shared_memory.internal_state.sixaxis_left_lifo;
65 auto& sixaxis_right_lifo = shared_memory.internal_state.sixaxis_right_lifo;
66
67 // Clear previous state
68 sixaxis_fullkey_state = {};
69 sixaxis_handheld_state = {};
70 sixaxis_dual_left_state = {};
71 sixaxis_dual_right_state = {};
72 sixaxis_left_lifo_state = {};
73 sixaxis_right_lifo_state = {};
74
75 if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
76 controller.sixaxis_at_rest = true;
77 for (std::size_t e = 0; e < motion_state.size(); ++e) {
78 controller.sixaxis_at_rest =
79 controller.sixaxis_at_rest && motion_state[e].is_at_rest;
80 }
81 } 41 }
82 42
83 const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state, 43 for (std::size_t i = 0; i < controller_data.size(); ++i) {
84 const Core::HID::ControllerMotion& hid_state) { 44 NpadSharedMemoryEntry& shared_memory = data->shared_memory_format->npad.npad_entry[i];
85 using namespace std::literals::chrono_literals; 45 auto& controller = controller_data[i];
86 static constexpr Core::HID::SixAxisSensorState default_motion_state = { 46 const auto& controller_type = controller.device->GetNpadStyleIndex();
87 .delta_time = std::chrono::nanoseconds(5ms).count(), 47
88 .accel = {0, 0, -1.0f}, 48 if (!data->flag.enable_six_axis_sensor) {
89 .orientation = 49 continue;
90 { 50 }
91 Common::Vec3f{1.0f, 0, 0}, 51
92 Common::Vec3f{0, 1.0f, 0}, 52 if (controller_type == Core::HID::NpadStyleIndex::None ||
93 Common::Vec3f{0, 0, 1.0f}, 53 !controller.device->IsConnected()) {
94 }, 54 continue;
95 .attribute = {1}, 55 }
56
57 const auto& motion_state = controller.device->GetMotions();
58 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
59 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
60 auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
61 auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
62 auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
63 auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
64
65 auto& sixaxis_fullkey_lifo = shared_memory.internal_state.sixaxis_fullkey_lifo;
66 auto& sixaxis_handheld_lifo = shared_memory.internal_state.sixaxis_handheld_lifo;
67 auto& sixaxis_dual_left_lifo = shared_memory.internal_state.sixaxis_dual_left_lifo;
68 auto& sixaxis_dual_right_lifo = shared_memory.internal_state.sixaxis_dual_right_lifo;
69 auto& sixaxis_left_lifo = shared_memory.internal_state.sixaxis_left_lifo;
70 auto& sixaxis_right_lifo = shared_memory.internal_state.sixaxis_right_lifo;
71
72 // Clear previous state
73 sixaxis_fullkey_state = {};
74 sixaxis_handheld_state = {};
75 sixaxis_dual_left_state = {};
76 sixaxis_dual_right_state = {};
77 sixaxis_left_lifo_state = {};
78 sixaxis_right_lifo_state = {};
79
80 if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
81 controller.sixaxis_at_rest = true;
82 for (std::size_t e = 0; e < motion_state.size(); ++e) {
83 controller.sixaxis_at_rest =
84 controller.sixaxis_at_rest && motion_state[e].is_at_rest;
85 }
86 }
87
88 const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state,
89 const Core::HID::ControllerMotion& hid_state) {
90 using namespace std::literals::chrono_literals;
91 static constexpr Core::HID::SixAxisSensorState default_motion_state = {
92 .delta_time = std::chrono::nanoseconds(5ms).count(),
93 .accel = {0, 0, -1.0f},
94 .orientation =
95 {
96 Common::Vec3f{1.0f, 0, 0},
97 Common::Vec3f{0, 1.0f, 0},
98 Common::Vec3f{0, 0, 1.0f},
99 },
100 .attribute = {1},
101 };
102 if (!controller.sixaxis_sensor_enabled) {
103 state = default_motion_state;
104 return;
105 }
106 if (!Settings::values.motion_enabled.GetValue()) {
107 state = default_motion_state;
108 return;
109 }
110 state.attribute.is_connected.Assign(1);
111 state.delta_time = std::chrono::nanoseconds(5ms).count();
112 state.accel = hid_state.accel;
113 state.gyro = hid_state.gyro;
114 state.rotation = hid_state.rotation;
115 state.orientation = hid_state.orientation;
96 }; 116 };
97 if (!controller.sixaxis_sensor_enabled) { 117
98 state = default_motion_state; 118 switch (controller_type) {
99 return; 119 case Core::HID::NpadStyleIndex::None:
120 ASSERT(false);
121 break;
122 case Core::HID::NpadStyleIndex::Fullkey:
123 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
124 break;
125 case Core::HID::NpadStyleIndex::Handheld:
126 set_motion_state(sixaxis_handheld_state, motion_state[0]);
127 break;
128 case Core::HID::NpadStyleIndex::JoyconDual:
129 set_motion_state(sixaxis_dual_left_state, motion_state[0]);
130 set_motion_state(sixaxis_dual_right_state, motion_state[1]);
131 break;
132 case Core::HID::NpadStyleIndex::JoyconLeft:
133 set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
134 break;
135 case Core::HID::NpadStyleIndex::JoyconRight:
136 set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
137 break;
138 case Core::HID::NpadStyleIndex::Pokeball:
139 using namespace std::literals::chrono_literals;
140 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
141 sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
142 break;
143 default:
144 break;
100 } 145 }
101 if (!Settings::values.motion_enabled.GetValue()) { 146
102 state = default_motion_state; 147 sixaxis_fullkey_state.sampling_number =
103 return; 148 sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
149 sixaxis_handheld_state.sampling_number =
150 sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
151 sixaxis_dual_left_state.sampling_number =
152 sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
153 sixaxis_dual_right_state.sampling_number =
154 sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
155 sixaxis_left_lifo_state.sampling_number =
156 sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
157 sixaxis_right_lifo_state.sampling_number =
158 sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
159
160 if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
161 // This buffer only is updated on handheld on HW
162 sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state);
163 } else {
164 // Handheld doesn't update this buffer on HW
165 sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state);
104 } 166 }
105 state.attribute.is_connected.Assign(1);
106 state.delta_time = std::chrono::nanoseconds(5ms).count();
107 state.accel = hid_state.accel;
108 state.gyro = hid_state.gyro;
109 state.rotation = hid_state.rotation;
110 state.orientation = hid_state.orientation;
111 };
112
113 switch (controller_type) {
114 case Core::HID::NpadStyleIndex::None:
115 ASSERT(false);
116 break;
117 case Core::HID::NpadStyleIndex::Fullkey:
118 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
119 break;
120 case Core::HID::NpadStyleIndex::Handheld:
121 set_motion_state(sixaxis_handheld_state, motion_state[0]);
122 break;
123 case Core::HID::NpadStyleIndex::JoyconDual:
124 set_motion_state(sixaxis_dual_left_state, motion_state[0]);
125 set_motion_state(sixaxis_dual_right_state, motion_state[1]);
126 break;
127 case Core::HID::NpadStyleIndex::JoyconLeft:
128 set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
129 break;
130 case Core::HID::NpadStyleIndex::JoyconRight:
131 set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
132 break;
133 case Core::HID::NpadStyleIndex::Pokeball:
134 using namespace std::literals::chrono_literals;
135 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
136 sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
137 break;
138 default:
139 break;
140 }
141 167
142 sixaxis_fullkey_state.sampling_number = 168 sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state);
143 sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; 169 sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state);
144 sixaxis_handheld_state.sampling_number = 170 sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state);
145 sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; 171 sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state);
146 sixaxis_dual_left_state.sampling_number =
147 sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
148 sixaxis_dual_right_state.sampling_number =
149 sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
150 sixaxis_left_lifo_state.sampling_number =
151 sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
152 sixaxis_right_lifo_state.sampling_number =
153 sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
154
155 if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
156 // This buffer only is updated on handheld on HW
157 sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state);
158 } else {
159 // Handheld doesn't update this buffer on HW
160 sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state);
161 } 172 }
162
163 sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state);
164 sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state);
165 sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state);
166 sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state);
167 } 173 }
168} 174}
169 175
diff --git a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp
index 56e8e8e51..c39321915 100644
--- a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp
+++ b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp
@@ -63,7 +63,7 @@ Result TouchResource::ActivateTouch(u64 aruid) {
63 auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); 63 auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index);
64 TouchAruidData& touch_data = aruid_data[aruid_index]; 64 TouchAruidData& touch_data = aruid_data[aruid_index];
65 65
66 if (!applet_data->flag.is_assigned) { 66 if (applet_data == nullptr || !applet_data->flag.is_assigned) {
67 touch_data = {}; 67 touch_data = {};
68 continue; 68 continue;
69 } 69 }
@@ -124,7 +124,7 @@ Result TouchResource::ActivateGesture(u64 aruid, u32 basic_gesture_id) {
124 auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); 124 auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index);
125 TouchAruidData& touch_data = aruid_data[aruid_index]; 125 TouchAruidData& touch_data = aruid_data[aruid_index];
126 126
127 if (!applet_data->flag.is_assigned) { 127 if (applet_data == nullptr || !applet_data->flag.is_assigned) {
128 touch_data = {}; 128 touch_data = {};
129 continue; 129 continue;
130 } 130 }
@@ -324,7 +324,7 @@ Result TouchResource::SetTouchScreenConfiguration(
324 const auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); 324 const auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index);
325 TouchAruidData& data = aruid_data[aruid_index]; 325 TouchAruidData& data = aruid_data[aruid_index];
326 326
327 if (!applet_data->flag.is_assigned) { 327 if (applet_data == nullptr || !applet_data->flag.is_assigned) {
328 continue; 328 continue;
329 } 329 }
330 if (aruid != data.aruid) { 330 if (aruid != data.aruid) {
@@ -344,7 +344,7 @@ Result TouchResource::GetTouchScreenConfiguration(
344 const auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index); 344 const auto* applet_data = applet_resource->GetAruidDataByIndex(aruid_index);
345 const TouchAruidData& data = aruid_data[aruid_index]; 345 const TouchAruidData& data = aruid_data[aruid_index];
346 346
347 if (!applet_data->flag.is_assigned) { 347 if (applet_data == nullptr || !applet_data->flag.is_assigned) {
348 continue; 348 continue;
349 } 349 }
350 if (aruid != data.aruid) { 350 if (aruid != data.aruid) {
diff --git a/src/video_core/host1x/host1x.cpp b/src/video_core/host1x/host1x.cpp
index c4c7a5883..e923bfa22 100644
--- a/src/video_core/host1x/host1x.cpp
+++ b/src/video_core/host1x/host1x.cpp
@@ -10,7 +10,7 @@ namespace Host1x {
10 10
11Host1x::Host1x(Core::System& system_) 11Host1x::Host1x(Core::System& system_)
12 : system{system_}, syncpoint_manager{}, 12 : system{system_}, syncpoint_manager{},
13 memory_manager(system.DeviceMemory()), gmmu_manager{system, memory_manager, 32, 12}, 13 memory_manager(system.DeviceMemory()), gmmu_manager{system, memory_manager, 32, 0, 12},
14 allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {} 14 allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {}
15 15
16Host1x::~Host1x() = default; 16Host1x::~Host1x() = default;
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index a52f8e486..ffafc48ef 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -22,11 +22,12 @@ using Tegra::Memory::GuestMemoryFlags;
22std::atomic<size_t> MemoryManager::unique_identifier_generator{}; 22std::atomic<size_t> MemoryManager::unique_identifier_generator{};
23 23
24MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_, 24MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
25 u64 address_space_bits_, u64 big_page_bits_, u64 page_bits_) 25 u64 address_space_bits_, GPUVAddr split_address_, u64 big_page_bits_,
26 u64 page_bits_)
26 : system{system_}, memory{memory_}, address_space_bits{address_space_bits_}, 27 : system{system_}, memory{memory_}, address_space_bits{address_space_bits_},
27 page_bits{page_bits_}, big_page_bits{big_page_bits_}, entries{}, big_entries{}, 28 split_address{split_address_}, page_bits{page_bits_}, big_page_bits{big_page_bits_},
28 page_table{address_space_bits, address_space_bits + page_bits - 38, 29 entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38,
29 page_bits != big_page_bits ? page_bits : 0}, 30 page_bits != big_page_bits ? page_bits : 0},
30 kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add( 31 kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add(
31 1, std::memory_order_acq_rel)}, 32 1, std::memory_order_acq_rel)},
32 accumulator{std::make_unique<VideoCommon::InvalidationAccumulator>()} { 33 accumulator{std::make_unique<VideoCommon::InvalidationAccumulator>()} {
@@ -48,10 +49,10 @@ MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager&
48 entries.resize(page_table_size / 32, 0); 49 entries.resize(page_table_size / 32, 0);
49} 50}
50 51
51MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_, 52MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_,
52 u64 page_bits_) 53 GPUVAddr split_address_, u64 big_page_bits_, u64 page_bits_)
53 : MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, big_page_bits_, 54 : MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, split_address_,
54 page_bits_) {} 55 big_page_bits_, page_bits_) {}
55 56
56MemoryManager::~MemoryManager() = default; 57MemoryManager::~MemoryManager() = default;
57 58
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index c5255f36c..ac7c1472a 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -36,10 +36,11 @@ namespace Tegra {
36class MemoryManager final { 36class MemoryManager final {
37public: 37public:
38 explicit MemoryManager(Core::System& system_, u64 address_space_bits_ = 40, 38 explicit MemoryManager(Core::System& system_, u64 address_space_bits_ = 40,
39 u64 big_page_bits_ = 16, u64 page_bits_ = 12); 39 GPUVAddr split_address = 1ULL << 34, u64 big_page_bits_ = 16,
40 explicit MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
41 u64 address_space_bits_ = 40, u64 big_page_bits_ = 16,
42 u64 page_bits_ = 12); 40 u64 page_bits_ = 12);
41 explicit MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
42 u64 address_space_bits_ = 40, GPUVAddr split_address = 1ULL << 34,
43 u64 big_page_bits_ = 16, u64 page_bits_ = 12);
43 ~MemoryManager(); 44 ~MemoryManager();
44 45
45 size_t GetID() const { 46 size_t GetID() const {
@@ -192,6 +193,7 @@ private:
192 MaxwellDeviceMemoryManager& memory; 193 MaxwellDeviceMemoryManager& memory;
193 194
194 const u64 address_space_bits; 195 const u64 address_space_bits;
196 GPUVAddr split_address;
195 const u64 page_bits; 197 const u64 page_bits;
196 u64 address_space_size; 198 u64 address_space_size;
197 u64 page_size; 199 u64 page_size;
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 9d38ab812..4dbe801a9 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -73,8 +73,11 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
73 ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics")); 73 ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics"));
74 ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); 74 ui->tabWidget->addTab(audio_tab.get(), tr("Audio"));
75 ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles")); 75 ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles"));
76
76 // Only show Linux tab on Unix 77 // Only show Linux tab on Unix
78 linux_tab->setVisible(false);
77#ifdef __unix__ 79#ifdef __unix__
80 linux_tab->setVisible(true);
78 ui->tabWidget->addTab(linux_tab.get(), tr("Linux")); 81 ui->tabWidget->addTab(linux_tab.get(), tr("Linux"));
79#endif 82#endif
80 83