diff options
Diffstat (limited to 'src')
110 files changed, 4184 insertions, 861 deletions
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index 53aafa08c..06e59d1ac 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts | |||
| @@ -188,8 +188,15 @@ tasks.create<Delete>("ktlintReset") { | |||
| 188 | delete(File(buildDir.path + File.separator + "intermediates/ktLint")) | 188 | delete(File(buildDir.path + File.separator + "intermediates/ktLint")) |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | val showFormatHelp = { | ||
| 192 | logger.lifecycle( | ||
| 193 | "If this check fails, please try running \"gradlew ktlintFormat\" for automatic " + | ||
| 194 | "codestyle fixes" | ||
| 195 | ) | ||
| 196 | } | ||
| 197 | tasks.getByPath("ktlintKotlinScriptCheck").doFirst { showFormatHelp.invoke() } | ||
| 198 | tasks.getByPath("ktlintMainSourceSetCheck").doFirst { showFormatHelp.invoke() } | ||
| 191 | tasks.getByPath("loadKtlintReporters").dependsOn("ktlintReset") | 199 | tasks.getByPath("loadKtlintReporters").dependsOn("ktlintReset") |
| 192 | tasks.getByPath("preBuild").dependsOn("ktlintCheck") | ||
| 193 | 200 | ||
| 194 | ktlint { | 201 | ktlint { |
| 195 | version.set("0.47.1") | 202 | version.set("0.47.1") |
| @@ -228,71 +235,33 @@ dependencies { | |||
| 228 | implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") | 235 | implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") |
| 229 | } | 236 | } |
| 230 | 237 | ||
| 231 | fun getGitVersion(): String { | 238 | fun runGitCommand(command: List<String>): String { |
| 232 | var versionName = "0.0" | 239 | return try { |
| 233 | 240 | ProcessBuilder(command) | |
| 234 | try { | ||
| 235 | versionName = ProcessBuilder("git", "describe", "--always", "--long") | ||
| 236 | .directory(project.rootDir) | 241 | .directory(project.rootDir) |
| 237 | .redirectOutput(ProcessBuilder.Redirect.PIPE) | 242 | .redirectOutput(ProcessBuilder.Redirect.PIPE) |
| 238 | .redirectError(ProcessBuilder.Redirect.PIPE) | 243 | .redirectError(ProcessBuilder.Redirect.PIPE) |
| 239 | .start().inputStream.bufferedReader().use { it.readText() } | 244 | .start().inputStream.bufferedReader().use { it.readText() } |
| 240 | .trim() | 245 | .trim() |
| 241 | .replace(Regex("(-0)?-[^-]+$"), "") | ||
| 242 | } catch (e: Exception) { | 246 | } catch (e: Exception) { |
| 243 | logger.error("Cannot find git, defaulting to dummy version number") | 247 | logger.error("Cannot find git") |
| 248 | "" | ||
| 244 | } | 249 | } |
| 245 | |||
| 246 | if (System.getenv("GITHUB_ACTIONS") != null) { | ||
| 247 | val gitTag = System.getenv("GIT_TAG_NAME") | ||
| 248 | versionName = gitTag ?: versionName | ||
| 249 | } | ||
| 250 | |||
| 251 | return versionName | ||
| 252 | } | 250 | } |
| 253 | 251 | ||
| 254 | fun getGitHash(): String { | 252 | fun getGitVersion(): String { |
| 255 | try { | 253 | val versionName = if (System.getenv("GITHUB_ACTIONS") != null) { |
| 256 | val processBuilder = ProcessBuilder("git", "rev-parse", "--short", "HEAD") | 254 | val gitTag = System.getenv("GIT_TAG_NAME") ?: "" |
| 257 | processBuilder.directory(project.rootDir) | 255 | gitTag |
| 258 | val process = processBuilder.start() | 256 | } else { |
| 259 | val inputStream = process.inputStream | 257 | runGitCommand(listOf("git", "describe", "--always", "--long")) |
| 260 | val errorStream = process.errorStream | 258 | .replace(Regex("(-0)?-[^-]+$"), "") |
| 261 | process.waitFor() | ||
| 262 | |||
| 263 | return if (process.exitValue() == 0) { | ||
| 264 | inputStream.bufferedReader() | ||
| 265 | .use { it.readText().trim() } // return the value of gitHash | ||
| 266 | } else { | ||
| 267 | val errorMessage = errorStream.bufferedReader().use { it.readText().trim() } | ||
| 268 | logger.error("Error running git command: $errorMessage") | ||
| 269 | "dummy-hash" // return a dummy hash value in case of an error | ||
| 270 | } | ||
| 271 | } catch (e: Exception) { | ||
| 272 | logger.error("$e: Cannot find git, defaulting to dummy build hash") | ||
| 273 | return "dummy-hash" // return a dummy hash value in case of an error | ||
| 274 | } | 259 | } |
| 260 | return versionName.ifEmpty { "0.0" } | ||
| 275 | } | 261 | } |
| 276 | 262 | ||
| 277 | fun getBranch(): String { | 263 | fun getGitHash(): String = |
| 278 | try { | 264 | runGitCommand(listOf("git", "rev-parse", "--short", "HEAD")).ifEmpty { "dummy-hash" } |
| 279 | val processBuilder = ProcessBuilder("git", "rev-parse", "--abbrev-ref", "HEAD") | 265 | |
| 280 | processBuilder.directory(project.rootDir) | 266 | fun getBranch(): String = |
| 281 | val process = processBuilder.start() | 267 | runGitCommand(listOf("git", "rev-parse", "--abbrev-ref", "HEAD")).ifEmpty { "dummy-hash" } |
| 282 | val inputStream = process.inputStream | ||
| 283 | val errorStream = process.errorStream | ||
| 284 | process.waitFor() | ||
| 285 | |||
| 286 | return if (process.exitValue() == 0) { | ||
| 287 | inputStream.bufferedReader() | ||
| 288 | .use { it.readText().trim() } // return the value of gitHash | ||
| 289 | } else { | ||
| 290 | val errorMessage = errorStream.bufferedReader().use { it.readText().trim() } | ||
| 291 | logger.error("Error running git command: $errorMessage") | ||
| 292 | "dummy-hash" // return a dummy hash value in case of an error | ||
| 293 | } | ||
| 294 | } catch (e: Exception) { | ||
| 295 | logger.error("$e: Cannot find git, defaulting to dummy build hash") | ||
| 296 | return "dummy-hash" // return a dummy hash value in case of an error | ||
| 297 | } | ||
| 298 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractDiffAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractDiffAdapter.kt new file mode 100644 index 000000000..f006f9e3d --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractDiffAdapter.kt | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.adapters | ||
| 5 | |||
| 6 | import android.annotation.SuppressLint | ||
| 7 | import androidx.recyclerview.widget.AsyncDifferConfig | ||
| 8 | import androidx.recyclerview.widget.DiffUtil | ||
| 9 | import androidx.recyclerview.widget.ListAdapter | ||
| 10 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 11 | import androidx.recyclerview.widget.RecyclerView | ||
| 12 | |||
| 13 | /** | ||
| 14 | * Generic adapter that implements an [AsyncDifferConfig] and covers some of the basic boilerplate | ||
| 15 | * code used in every [RecyclerView]. | ||
| 16 | * Type assigned to [Model] must inherit from [Object] in order to be compared properly. | ||
| 17 | */ | ||
| 18 | abstract class AbstractDiffAdapter<Model : Any, Holder : AbstractViewHolder<Model>> : | ||
| 19 | ListAdapter<Model, Holder>(AsyncDifferConfig.Builder(DiffCallback<Model>()).build()) { | ||
| 20 | override fun onBindViewHolder(holder: Holder, position: Int) = | ||
| 21 | holder.bind(currentList[position]) | ||
| 22 | |||
| 23 | private class DiffCallback<Model> : DiffUtil.ItemCallback<Model>() { | ||
| 24 | override fun areItemsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean { | ||
| 25 | return oldItem === newItem | ||
| 26 | } | ||
| 27 | |||
| 28 | @SuppressLint("DiffUtilEquals") | ||
| 29 | override fun areContentsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean { | ||
| 30 | return oldItem == newItem | ||
| 31 | } | ||
| 32 | } | ||
| 33 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractListAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractListAdapter.kt new file mode 100644 index 000000000..3dfee3d0c --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractListAdapter.kt | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.adapters | ||
| 5 | |||
| 6 | import android.annotation.SuppressLint | ||
| 7 | import androidx.recyclerview.widget.RecyclerView | ||
| 8 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 9 | |||
| 10 | /** | ||
| 11 | * Generic list class meant to take care of basic lists | ||
| 12 | * @param currentList The list to show initially | ||
| 13 | */ | ||
| 14 | abstract class AbstractListAdapter<Model : Any, Holder : AbstractViewHolder<Model>>( | ||
| 15 | open var currentList: List<Model> | ||
| 16 | ) : RecyclerView.Adapter<Holder>() { | ||
| 17 | override fun onBindViewHolder(holder: Holder, position: Int) = | ||
| 18 | holder.bind(currentList[position]) | ||
| 19 | |||
| 20 | override fun getItemCount(): Int = currentList.size | ||
| 21 | |||
| 22 | /** | ||
| 23 | * Adds an item to [currentList] and notifies the underlying adapter of the change. If no parameter | ||
| 24 | * is passed in for position, [item] is added to the end of the list. Invokes [callback] last. | ||
| 25 | * @param item The item to add to the list | ||
| 26 | * @param position Index where [item] will be added | ||
| 27 | * @param callback Lambda that's called at the end of the list changes and has the added list | ||
| 28 | * position passed in as a parameter | ||
| 29 | */ | ||
| 30 | open fun addItem(item: Model, position: Int = -1, callback: ((position: Int) -> Unit)? = null) { | ||
| 31 | val newList = currentList.toMutableList() | ||
| 32 | val positionToUpdate: Int | ||
| 33 | if (position == -1) { | ||
| 34 | newList.add(item) | ||
| 35 | currentList = newList | ||
| 36 | positionToUpdate = currentList.size - 1 | ||
| 37 | } else { | ||
| 38 | newList.add(position, item) | ||
| 39 | currentList = newList | ||
| 40 | positionToUpdate = position | ||
| 41 | } | ||
| 42 | onItemAdded(positionToUpdate, callback) | ||
| 43 | } | ||
| 44 | |||
| 45 | protected fun onItemAdded(position: Int, callback: ((Int) -> Unit)? = null) { | ||
| 46 | notifyItemInserted(position) | ||
| 47 | callback?.invoke(position) | ||
| 48 | } | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Replaces the [item] at [position] in the [currentList] and notifies the underlying adapter | ||
| 52 | * of the change. Invokes [callback] last. | ||
| 53 | * @param item New list item | ||
| 54 | * @param position Index where [item] will replace the existing list item | ||
| 55 | * @param callback Lambda that's called at the end of the list changes and has the changed list | ||
| 56 | * position passed in as a parameter | ||
| 57 | */ | ||
| 58 | fun changeItem(item: Model, position: Int, callback: ((position: Int) -> Unit)? = null) { | ||
| 59 | val newList = currentList.toMutableList() | ||
| 60 | newList[position] = item | ||
| 61 | currentList = newList | ||
| 62 | onItemChanged(position, callback) | ||
| 63 | } | ||
| 64 | |||
| 65 | protected fun onItemChanged(position: Int, callback: ((Int) -> Unit)? = null) { | ||
| 66 | notifyItemChanged(position) | ||
| 67 | callback?.invoke(position) | ||
| 68 | } | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Removes the list item at [position] in [currentList] and notifies the underlying adapter | ||
| 72 | * of the change. Invokes [callback] last. | ||
| 73 | * @param position Index where the list item will be removed | ||
| 74 | * @param callback Lambda that's called at the end of the list changes and has the removed list | ||
| 75 | * position passed in as a parameter | ||
| 76 | */ | ||
| 77 | fun removeItem(position: Int, callback: ((position: Int) -> Unit)? = null) { | ||
| 78 | val newList = currentList.toMutableList() | ||
| 79 | newList.removeAt(position) | ||
| 80 | currentList = newList | ||
| 81 | onItemRemoved(position, callback) | ||
| 82 | } | ||
| 83 | |||
| 84 | protected fun onItemRemoved(position: Int, callback: ((Int) -> Unit)? = null) { | ||
| 85 | notifyItemRemoved(position) | ||
| 86 | callback?.invoke(position) | ||
| 87 | } | ||
| 88 | |||
| 89 | /** | ||
| 90 | * Replaces [currentList] with [newList] and notifies the underlying adapter of the change. | ||
| 91 | * @param newList The new list to replace [currentList] | ||
| 92 | */ | ||
| 93 | @SuppressLint("NotifyDataSetChanged") | ||
| 94 | open fun replaceList(newList: List<Model>) { | ||
| 95 | currentList = newList | ||
| 96 | notifyDataSetChanged() | ||
| 97 | } | ||
| 98 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractSingleSelectionList.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractSingleSelectionList.kt new file mode 100644 index 000000000..52163f9d7 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractSingleSelectionList.kt | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.adapters | ||
| 5 | |||
| 6 | import org.yuzu.yuzu_emu.model.SelectableItem | ||
| 7 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 8 | |||
| 9 | /** | ||
| 10 | * Generic list class meant to take care of single selection UI updates | ||
| 11 | * @param currentList The list to show initially | ||
| 12 | * @param defaultSelection The default selection to use if no list items are selected by | ||
| 13 | * [SelectableItem.selected] or if the currently selected item is removed from the list | ||
| 14 | */ | ||
| 15 | abstract class AbstractSingleSelectionList< | ||
| 16 | Model : SelectableItem, | ||
| 17 | Holder : AbstractViewHolder<Model> | ||
| 18 | >( | ||
| 19 | final override var currentList: List<Model>, | ||
| 20 | private val defaultSelection: DefaultSelection = DefaultSelection.Start | ||
| 21 | ) : AbstractListAdapter<Model, Holder>(currentList) { | ||
| 22 | var selectedItem = getDefaultSelection() | ||
| 23 | |||
| 24 | init { | ||
| 25 | findSelectedItem() | ||
| 26 | } | ||
| 27 | |||
| 28 | /** | ||
| 29 | * Changes the selection state of the [SelectableItem] that was selected and the previously selected | ||
| 30 | * item and notifies the underlying adapter of the change for those items. Invokes [callback] last. | ||
| 31 | * Does nothing if [position] is the same as the currently selected item. | ||
| 32 | * @param position Index of the item that was selected | ||
| 33 | * @param callback Lambda that's called at the end of the list changes and has the selected list | ||
| 34 | * position passed in as a parameter | ||
| 35 | */ | ||
| 36 | fun selectItem(position: Int, callback: ((position: Int) -> Unit)? = null) { | ||
| 37 | if (position == selectedItem) { | ||
| 38 | return | ||
| 39 | } | ||
| 40 | |||
| 41 | val previouslySelectedItem = selectedItem | ||
| 42 | selectedItem = position | ||
| 43 | if (currentList.indices.contains(selectedItem)) { | ||
| 44 | currentList[selectedItem].onSelectionStateChanged(true) | ||
| 45 | } | ||
| 46 | if (currentList.indices.contains(previouslySelectedItem)) { | ||
| 47 | currentList[previouslySelectedItem].onSelectionStateChanged(false) | ||
| 48 | } | ||
| 49 | onItemChanged(previouslySelectedItem) | ||
| 50 | onItemChanged(selectedItem) | ||
| 51 | callback?.invoke(position) | ||
| 52 | } | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Removes a given item from the list and notifies the underlying adapter of the change. If the | ||
| 56 | * currently selected item was the item that was removed, the item at the position provided | ||
| 57 | * by [defaultSelection] will be made the new selection. Invokes [callback] last. | ||
| 58 | * @param position Index of the item that was removed | ||
| 59 | * @param callback Lambda that's called at the end of the list changes and has the removed and | ||
| 60 | * selected list positions passed in as parameters | ||
| 61 | */ | ||
| 62 | fun removeSelectableItem( | ||
| 63 | position: Int, | ||
| 64 | callback: ((removedPosition: Int, selectedPosition: Int) -> Unit)? | ||
| 65 | ) { | ||
| 66 | removeItem(position) | ||
| 67 | if (position == selectedItem) { | ||
| 68 | selectedItem = getDefaultSelection() | ||
| 69 | currentList[selectedItem].onSelectionStateChanged(true) | ||
| 70 | onItemChanged(selectedItem) | ||
| 71 | } else if (position < selectedItem) { | ||
| 72 | selectedItem-- | ||
| 73 | } | ||
| 74 | callback?.invoke(position, selectedItem) | ||
| 75 | } | ||
| 76 | |||
| 77 | override fun addItem(item: Model, position: Int, callback: ((Int) -> Unit)?) { | ||
| 78 | super.addItem(item, position, callback) | ||
| 79 | if (position <= selectedItem && position != -1) { | ||
| 80 | selectedItem++ | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | override fun replaceList(newList: List<Model>) { | ||
| 85 | super.replaceList(newList) | ||
| 86 | findSelectedItem() | ||
| 87 | } | ||
| 88 | |||
| 89 | private fun findSelectedItem() { | ||
| 90 | for (i in currentList.indices) { | ||
| 91 | if (currentList[i].selected) { | ||
| 92 | selectedItem = i | ||
| 93 | break | ||
| 94 | } | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | private fun getDefaultSelection(): Int = | ||
| 99 | when (defaultSelection) { | ||
| 100 | DefaultSelection.Start -> currentList.indices.first | ||
| 101 | DefaultSelection.End -> currentList.indices.last | ||
| 102 | } | ||
| 103 | |||
| 104 | enum class DefaultSelection { Start, End } | ||
| 105 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt index 15c7ca3c9..94c151325 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt | |||
| @@ -5,48 +5,28 @@ package org.yuzu.yuzu_emu.adapters | |||
| 5 | 5 | ||
| 6 | import android.view.LayoutInflater | 6 | import android.view.LayoutInflater |
| 7 | import android.view.ViewGroup | 7 | import android.view.ViewGroup |
| 8 | import androidx.recyclerview.widget.AsyncDifferConfig | ||
| 9 | import androidx.recyclerview.widget.DiffUtil | ||
| 10 | import androidx.recyclerview.widget.ListAdapter | ||
| 11 | import androidx.recyclerview.widget.RecyclerView | ||
| 12 | import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding | 8 | import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding |
| 13 | import org.yuzu.yuzu_emu.model.Addon | 9 | import org.yuzu.yuzu_emu.model.Addon |
| 10 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 14 | 11 | ||
| 15 | class AddonAdapter : ListAdapter<Addon, AddonAdapter.AddonViewHolder>( | 12 | class AddonAdapter : AbstractDiffAdapter<Addon, AddonAdapter.AddonViewHolder>() { |
| 16 | AsyncDifferConfig.Builder(DiffCallback()).build() | ||
| 17 | ) { | ||
| 18 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder { | 13 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder { |
| 19 | ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 14 | ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 20 | .also { return AddonViewHolder(it) } | 15 | .also { return AddonViewHolder(it) } |
| 21 | } | 16 | } |
| 22 | 17 | ||
| 23 | override fun getItemCount(): Int = currentList.size | ||
| 24 | |||
| 25 | override fun onBindViewHolder(holder: AddonViewHolder, position: Int) = | ||
| 26 | holder.bind(currentList[position]) | ||
| 27 | |||
| 28 | inner class AddonViewHolder(val binding: ListItemAddonBinding) : | 18 | inner class AddonViewHolder(val binding: ListItemAddonBinding) : |
| 29 | RecyclerView.ViewHolder(binding.root) { | 19 | AbstractViewHolder<Addon>(binding) { |
| 30 | fun bind(addon: Addon) { | 20 | override fun bind(model: Addon) { |
| 31 | binding.root.setOnClickListener { | 21 | binding.root.setOnClickListener { |
| 32 | binding.addonSwitch.isChecked = !binding.addonSwitch.isChecked | 22 | binding.addonSwitch.isChecked = !binding.addonSwitch.isChecked |
| 33 | } | 23 | } |
| 34 | binding.title.text = addon.title | 24 | binding.title.text = model.title |
| 35 | binding.version.text = addon.version | 25 | binding.version.text = model.version |
| 36 | binding.addonSwitch.setOnCheckedChangeListener { _, checked -> | 26 | binding.addonSwitch.setOnCheckedChangeListener { _, checked -> |
| 37 | addon.enabled = checked | 27 | model.enabled = checked |
| 38 | } | 28 | } |
| 39 | binding.addonSwitch.isChecked = addon.enabled | 29 | binding.addonSwitch.isChecked = model.enabled |
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | private class DiffCallback : DiffUtil.ItemCallback<Addon>() { | ||
| 44 | override fun areItemsTheSame(oldItem: Addon, newItem: Addon): Boolean { | ||
| 45 | return oldItem == newItem | ||
| 46 | } | ||
| 47 | |||
| 48 | override fun areContentsTheSame(oldItem: Addon, newItem: Addon): Boolean { | ||
| 49 | return oldItem == newItem | ||
| 50 | } | 30 | } |
| 51 | } | 31 | } |
| 52 | } | 32 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AppletAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AppletAdapter.kt index 4a05c5be9..41d7f72b8 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AppletAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AppletAdapter.kt | |||
| @@ -4,13 +4,11 @@ | |||
| 4 | package org.yuzu.yuzu_emu.adapters | 4 | package org.yuzu.yuzu_emu.adapters |
| 5 | 5 | ||
| 6 | import android.view.LayoutInflater | 6 | import android.view.LayoutInflater |
| 7 | import android.view.View | ||
| 8 | import android.view.ViewGroup | 7 | import android.view.ViewGroup |
| 9 | import android.widget.Toast | 8 | import android.widget.Toast |
| 10 | import androidx.core.content.res.ResourcesCompat | 9 | import androidx.core.content.res.ResourcesCompat |
| 11 | import androidx.fragment.app.FragmentActivity | 10 | import androidx.fragment.app.FragmentActivity |
| 12 | import androidx.navigation.findNavController | 11 | import androidx.navigation.findNavController |
| 13 | import androidx.recyclerview.widget.RecyclerView | ||
| 14 | import org.yuzu.yuzu_emu.HomeNavigationDirections | 12 | import org.yuzu.yuzu_emu.HomeNavigationDirections |
| 15 | import org.yuzu.yuzu_emu.NativeLibrary | 13 | import org.yuzu.yuzu_emu.NativeLibrary |
| 16 | import org.yuzu.yuzu_emu.R | 14 | import org.yuzu.yuzu_emu.R |
| @@ -19,72 +17,58 @@ import org.yuzu.yuzu_emu.databinding.CardSimpleOutlinedBinding | |||
| 19 | import org.yuzu.yuzu_emu.model.Applet | 17 | import org.yuzu.yuzu_emu.model.Applet |
| 20 | import org.yuzu.yuzu_emu.model.AppletInfo | 18 | import org.yuzu.yuzu_emu.model.AppletInfo |
| 21 | import org.yuzu.yuzu_emu.model.Game | 19 | import org.yuzu.yuzu_emu.model.Game |
| 20 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 22 | 21 | ||
| 23 | class AppletAdapter(val activity: FragmentActivity, var applets: List<Applet>) : | 22 | class AppletAdapter(val activity: FragmentActivity, applets: List<Applet>) : |
| 24 | RecyclerView.Adapter<AppletAdapter.AppletViewHolder>(), | 23 | AbstractListAdapter<Applet, AppletAdapter.AppletViewHolder>(applets) { |
| 25 | View.OnClickListener { | ||
| 26 | |||
| 27 | override fun onCreateViewHolder( | 24 | override fun onCreateViewHolder( |
| 28 | parent: ViewGroup, | 25 | parent: ViewGroup, |
| 29 | viewType: Int | 26 | viewType: Int |
| 30 | ): AppletAdapter.AppletViewHolder { | 27 | ): AppletAdapter.AppletViewHolder { |
| 31 | CardSimpleOutlinedBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 28 | CardSimpleOutlinedBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 32 | .apply { root.setOnClickListener(this@AppletAdapter) } | ||
| 33 | .also { return AppletViewHolder(it) } | 29 | .also { return AppletViewHolder(it) } |
| 34 | } | 30 | } |
| 35 | 31 | ||
| 36 | override fun onBindViewHolder(holder: AppletViewHolder, position: Int) = | ||
| 37 | holder.bind(applets[position]) | ||
| 38 | |||
| 39 | override fun getItemCount(): Int = applets.size | ||
| 40 | |||
| 41 | override fun onClick(view: View) { | ||
| 42 | val applet = (view.tag as AppletViewHolder).applet | ||
| 43 | val appletPath = NativeLibrary.getAppletLaunchPath(applet.appletInfo.entryId) | ||
| 44 | if (appletPath.isEmpty()) { | ||
| 45 | Toast.makeText( | ||
| 46 | YuzuApplication.appContext, | ||
| 47 | R.string.applets_error_applet, | ||
| 48 | Toast.LENGTH_SHORT | ||
| 49 | ).show() | ||
| 50 | return | ||
| 51 | } | ||
| 52 | |||
| 53 | if (applet.appletInfo == AppletInfo.Cabinet) { | ||
| 54 | view.findNavController() | ||
| 55 | .navigate(R.id.action_appletLauncherFragment_to_cabinetLauncherDialogFragment) | ||
| 56 | return | ||
| 57 | } | ||
| 58 | |||
| 59 | NativeLibrary.setCurrentAppletId(applet.appletInfo.appletId) | ||
| 60 | val appletGame = Game( | ||
| 61 | title = YuzuApplication.appContext.getString(applet.titleId), | ||
| 62 | path = appletPath | ||
| 63 | ) | ||
| 64 | val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame) | ||
| 65 | view.findNavController().navigate(action) | ||
| 66 | } | ||
| 67 | |||
| 68 | inner class AppletViewHolder(val binding: CardSimpleOutlinedBinding) : | 32 | inner class AppletViewHolder(val binding: CardSimpleOutlinedBinding) : |
| 69 | RecyclerView.ViewHolder(binding.root) { | 33 | AbstractViewHolder<Applet>(binding) { |
| 70 | lateinit var applet: Applet | 34 | override fun bind(model: Applet) { |
| 71 | 35 | binding.title.setText(model.titleId) | |
| 72 | init { | 36 | binding.description.setText(model.descriptionId) |
| 73 | itemView.tag = this | ||
| 74 | } | ||
| 75 | |||
| 76 | fun bind(applet: Applet) { | ||
| 77 | this.applet = applet | ||
| 78 | |||
| 79 | binding.title.setText(applet.titleId) | ||
| 80 | binding.description.setText(applet.descriptionId) | ||
| 81 | binding.icon.setImageDrawable( | 37 | binding.icon.setImageDrawable( |
| 82 | ResourcesCompat.getDrawable( | 38 | ResourcesCompat.getDrawable( |
| 83 | binding.icon.context.resources, | 39 | binding.icon.context.resources, |
| 84 | applet.iconId, | 40 | model.iconId, |
| 85 | binding.icon.context.theme | 41 | binding.icon.context.theme |
| 86 | ) | 42 | ) |
| 87 | ) | 43 | ) |
| 44 | |||
| 45 | binding.root.setOnClickListener { onClick(model) } | ||
| 46 | } | ||
| 47 | |||
| 48 | fun onClick(applet: Applet) { | ||
| 49 | val appletPath = NativeLibrary.getAppletLaunchPath(applet.appletInfo.entryId) | ||
| 50 | if (appletPath.isEmpty()) { | ||
| 51 | Toast.makeText( | ||
| 52 | binding.root.context, | ||
| 53 | R.string.applets_error_applet, | ||
| 54 | Toast.LENGTH_SHORT | ||
| 55 | ).show() | ||
| 56 | return | ||
| 57 | } | ||
| 58 | |||
| 59 | if (applet.appletInfo == AppletInfo.Cabinet) { | ||
| 60 | binding.root.findNavController() | ||
| 61 | .navigate(R.id.action_appletLauncherFragment_to_cabinetLauncherDialogFragment) | ||
| 62 | return | ||
| 63 | } | ||
| 64 | |||
| 65 | NativeLibrary.setCurrentAppletId(applet.appletInfo.appletId) | ||
| 66 | val appletGame = Game( | ||
| 67 | title = YuzuApplication.appContext.getString(applet.titleId), | ||
| 68 | path = appletPath | ||
| 69 | ) | ||
| 70 | val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame) | ||
| 71 | binding.root.findNavController().navigate(action) | ||
| 88 | } | 72 | } |
| 89 | } | 73 | } |
| 90 | } | 74 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/CabinetLauncherDialogAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/CabinetLauncherDialogAdapter.kt index e7b7c0f2f..a56137148 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/CabinetLauncherDialogAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/CabinetLauncherDialogAdapter.kt | |||
| @@ -4,12 +4,10 @@ | |||
| 4 | package org.yuzu.yuzu_emu.adapters | 4 | package org.yuzu.yuzu_emu.adapters |
| 5 | 5 | ||
| 6 | import android.view.LayoutInflater | 6 | import android.view.LayoutInflater |
| 7 | import android.view.View | ||
| 8 | import android.view.ViewGroup | 7 | import android.view.ViewGroup |
| 9 | import androidx.core.content.res.ResourcesCompat | 8 | import androidx.core.content.res.ResourcesCompat |
| 10 | import androidx.fragment.app.Fragment | 9 | import androidx.fragment.app.Fragment |
| 11 | import androidx.navigation.fragment.findNavController | 10 | import androidx.navigation.fragment.findNavController |
| 12 | import androidx.recyclerview.widget.RecyclerView | ||
| 13 | import org.yuzu.yuzu_emu.HomeNavigationDirections | 11 | import org.yuzu.yuzu_emu.HomeNavigationDirections |
| 14 | import org.yuzu.yuzu_emu.NativeLibrary | 12 | import org.yuzu.yuzu_emu.NativeLibrary |
| 15 | import org.yuzu.yuzu_emu.R | 13 | import org.yuzu.yuzu_emu.R |
| @@ -19,54 +17,43 @@ import org.yuzu.yuzu_emu.model.CabinetMode | |||
| 19 | import org.yuzu.yuzu_emu.adapters.CabinetLauncherDialogAdapter.CabinetModeViewHolder | 17 | import org.yuzu.yuzu_emu.adapters.CabinetLauncherDialogAdapter.CabinetModeViewHolder |
| 20 | import org.yuzu.yuzu_emu.model.AppletInfo | 18 | import org.yuzu.yuzu_emu.model.AppletInfo |
| 21 | import org.yuzu.yuzu_emu.model.Game | 19 | import org.yuzu.yuzu_emu.model.Game |
| 20 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 22 | 21 | ||
| 23 | class CabinetLauncherDialogAdapter(val fragment: Fragment) : | 22 | class CabinetLauncherDialogAdapter(val fragment: Fragment) : |
| 24 | RecyclerView.Adapter<CabinetModeViewHolder>(), | 23 | AbstractListAdapter<CabinetMode, CabinetModeViewHolder>( |
| 25 | View.OnClickListener { | 24 | CabinetMode.values().copyOfRange(1, CabinetMode.entries.size).toList() |
| 26 | private val cabinetModes = CabinetMode.values().copyOfRange(1, CabinetMode.values().size) | 25 | ) { |
| 27 | 26 | ||
| 28 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CabinetModeViewHolder { | 27 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CabinetModeViewHolder { |
| 29 | DialogListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 28 | DialogListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 30 | .apply { root.setOnClickListener(this@CabinetLauncherDialogAdapter) } | ||
| 31 | .also { return CabinetModeViewHolder(it) } | 29 | .also { return CabinetModeViewHolder(it) } |
| 32 | } | 30 | } |
| 33 | 31 | ||
| 34 | override fun getItemCount(): Int = cabinetModes.size | ||
| 35 | |||
| 36 | override fun onBindViewHolder(holder: CabinetModeViewHolder, position: Int) = | ||
| 37 | holder.bind(cabinetModes[position]) | ||
| 38 | |||
| 39 | override fun onClick(view: View) { | ||
| 40 | val mode = (view.tag as CabinetModeViewHolder).cabinetMode | ||
| 41 | val appletPath = NativeLibrary.getAppletLaunchPath(AppletInfo.Cabinet.entryId) | ||
| 42 | NativeLibrary.setCurrentAppletId(AppletInfo.Cabinet.appletId) | ||
| 43 | NativeLibrary.setCabinetMode(mode.id) | ||
| 44 | val appletGame = Game( | ||
| 45 | title = YuzuApplication.appContext.getString(R.string.cabinet_applet), | ||
| 46 | path = appletPath | ||
| 47 | ) | ||
| 48 | val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame) | ||
| 49 | fragment.findNavController().navigate(action) | ||
| 50 | } | ||
| 51 | |||
| 52 | inner class CabinetModeViewHolder(val binding: DialogListItemBinding) : | 32 | inner class CabinetModeViewHolder(val binding: DialogListItemBinding) : |
| 53 | RecyclerView.ViewHolder(binding.root) { | 33 | AbstractViewHolder<CabinetMode>(binding) { |
| 54 | lateinit var cabinetMode: CabinetMode | 34 | override fun bind(model: CabinetMode) { |
| 55 | |||
| 56 | init { | ||
| 57 | itemView.tag = this | ||
| 58 | } | ||
| 59 | |||
| 60 | fun bind(cabinetMode: CabinetMode) { | ||
| 61 | this.cabinetMode = cabinetMode | ||
| 62 | binding.icon.setImageDrawable( | 35 | binding.icon.setImageDrawable( |
| 63 | ResourcesCompat.getDrawable( | 36 | ResourcesCompat.getDrawable( |
| 64 | binding.icon.context.resources, | 37 | binding.icon.context.resources, |
| 65 | cabinetMode.iconId, | 38 | model.iconId, |
| 66 | binding.icon.context.theme | 39 | binding.icon.context.theme |
| 67 | ) | 40 | ) |
| 68 | ) | 41 | ) |
| 69 | binding.title.setText(cabinetMode.titleId) | 42 | binding.title.setText(model.titleId) |
| 43 | |||
| 44 | binding.root.setOnClickListener { onClick(model) } | ||
| 45 | } | ||
| 46 | |||
| 47 | private fun onClick(mode: CabinetMode) { | ||
| 48 | val appletPath = NativeLibrary.getAppletLaunchPath(AppletInfo.Cabinet.entryId) | ||
| 49 | NativeLibrary.setCurrentAppletId(AppletInfo.Cabinet.appletId) | ||
| 50 | NativeLibrary.setCabinetMode(mode.id) | ||
| 51 | val appletGame = Game( | ||
| 52 | title = YuzuApplication.appContext.getString(R.string.cabinet_applet), | ||
| 53 | path = appletPath | ||
| 54 | ) | ||
| 55 | val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame) | ||
| 56 | fragment.findNavController().navigate(action) | ||
| 70 | } | 57 | } |
| 71 | } | 58 | } |
| 72 | } | 59 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt index d290a656c..d6f17cf29 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt | |||
| @@ -7,65 +7,39 @@ import android.text.TextUtils | |||
| 7 | import android.view.LayoutInflater | 7 | import android.view.LayoutInflater |
| 8 | import android.view.View | 8 | import android.view.View |
| 9 | import android.view.ViewGroup | 9 | import android.view.ViewGroup |
| 10 | import androidx.recyclerview.widget.AsyncDifferConfig | ||
| 11 | import androidx.recyclerview.widget.DiffUtil | ||
| 12 | import androidx.recyclerview.widget.ListAdapter | ||
| 13 | import androidx.recyclerview.widget.RecyclerView | ||
| 14 | import org.yuzu.yuzu_emu.R | ||
| 15 | import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding | 10 | import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding |
| 11 | import org.yuzu.yuzu_emu.features.settings.model.StringSetting | ||
| 12 | import org.yuzu.yuzu_emu.model.Driver | ||
| 16 | import org.yuzu.yuzu_emu.model.DriverViewModel | 13 | import org.yuzu.yuzu_emu.model.DriverViewModel |
| 17 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper | 14 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder |
| 18 | import org.yuzu.yuzu_emu.utils.GpuDriverMetadata | ||
| 19 | 15 | ||
| 20 | class DriverAdapter(private val driverViewModel: DriverViewModel) : | 16 | class DriverAdapter(private val driverViewModel: DriverViewModel) : |
| 21 | ListAdapter<Pair<String, GpuDriverMetadata>, DriverAdapter.DriverViewHolder>( | 17 | AbstractSingleSelectionList<Driver, DriverAdapter.DriverViewHolder>( |
| 22 | AsyncDifferConfig.Builder(DiffCallback()).build() | 18 | driverViewModel.driverList.value |
| 23 | ) { | 19 | ) { |
| 24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DriverViewHolder { | 20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DriverViewHolder { |
| 25 | val binding = | 21 | CardDriverOptionBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 26 | CardDriverOptionBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 22 | .also { return DriverViewHolder(it) } |
| 27 | return DriverViewHolder(binding) | ||
| 28 | } | ||
| 29 | |||
| 30 | override fun getItemCount(): Int = currentList.size | ||
| 31 | |||
| 32 | override fun onBindViewHolder(holder: DriverViewHolder, position: Int) = | ||
| 33 | holder.bind(currentList[position]) | ||
| 34 | |||
| 35 | private fun onSelectDriver(position: Int) { | ||
| 36 | driverViewModel.setSelectedDriverIndex(position) | ||
| 37 | notifyItemChanged(driverViewModel.previouslySelectedDriver) | ||
| 38 | notifyItemChanged(driverViewModel.selectedDriver) | ||
| 39 | } | ||
| 40 | |||
| 41 | private fun onDeleteDriver(driverData: Pair<String, GpuDriverMetadata>, position: Int) { | ||
| 42 | if (driverViewModel.selectedDriver > position) { | ||
| 43 | driverViewModel.setSelectedDriverIndex(driverViewModel.selectedDriver - 1) | ||
| 44 | } | ||
| 45 | if (GpuDriverHelper.customDriverSettingData == driverData.second) { | ||
| 46 | driverViewModel.setSelectedDriverIndex(0) | ||
| 47 | } | ||
| 48 | driverViewModel.driversToDelete.add(driverData.first) | ||
| 49 | driverViewModel.removeDriver(driverData) | ||
| 50 | notifyItemRemoved(position) | ||
| 51 | notifyItemChanged(driverViewModel.selectedDriver) | ||
| 52 | } | 23 | } |
| 53 | 24 | ||
| 54 | inner class DriverViewHolder(val binding: CardDriverOptionBinding) : | 25 | inner class DriverViewHolder(val binding: CardDriverOptionBinding) : |
| 55 | RecyclerView.ViewHolder(binding.root) { | 26 | AbstractViewHolder<Driver>(binding) { |
| 56 | private lateinit var driverData: Pair<String, GpuDriverMetadata> | 27 | override fun bind(model: Driver) { |
| 57 | |||
| 58 | fun bind(driverData: Pair<String, GpuDriverMetadata>) { | ||
| 59 | this.driverData = driverData | ||
| 60 | val driver = driverData.second | ||
| 61 | |||
| 62 | binding.apply { | 28 | binding.apply { |
| 63 | radioButton.isChecked = driverViewModel.selectedDriver == bindingAdapterPosition | 29 | radioButton.isChecked = model.selected |
| 64 | root.setOnClickListener { | 30 | root.setOnClickListener { |
| 65 | onSelectDriver(bindingAdapterPosition) | 31 | selectItem(bindingAdapterPosition) { |
| 32 | driverViewModel.onDriverSelected(it) | ||
| 33 | driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global) | ||
| 34 | } | ||
| 66 | } | 35 | } |
| 67 | buttonDelete.setOnClickListener { | 36 | buttonDelete.setOnClickListener { |
| 68 | onDeleteDriver(driverData, bindingAdapterPosition) | 37 | removeSelectableItem( |
| 38 | bindingAdapterPosition | ||
| 39 | ) { removedPosition: Int, selectedPosition: Int -> | ||
| 40 | driverViewModel.onDriverRemoved(removedPosition, selectedPosition) | ||
| 41 | driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global) | ||
| 42 | } | ||
| 69 | } | 43 | } |
| 70 | 44 | ||
| 71 | // Delay marquee by 3s | 45 | // Delay marquee by 3s |
| @@ -80,38 +54,19 @@ class DriverAdapter(private val driverViewModel: DriverViewModel) : | |||
| 80 | }, | 54 | }, |
| 81 | 3000 | 55 | 3000 |
| 82 | ) | 56 | ) |
| 83 | if (driver.name == null) { | 57 | title.text = model.title |
| 84 | title.setText(R.string.system_gpu_driver) | 58 | version.text = model.version |
| 85 | description.text = "" | 59 | description.text = model.description |
| 86 | version.text = "" | 60 | if (model.description.isNotEmpty()) { |
| 87 | version.visibility = View.GONE | ||
| 88 | description.visibility = View.GONE | ||
| 89 | buttonDelete.visibility = View.GONE | ||
| 90 | } else { | ||
| 91 | title.text = driver.name | ||
| 92 | version.text = driver.version | ||
| 93 | description.text = driver.description | ||
| 94 | version.visibility = View.VISIBLE | 61 | version.visibility = View.VISIBLE |
| 95 | description.visibility = View.VISIBLE | 62 | description.visibility = View.VISIBLE |
| 96 | buttonDelete.visibility = View.VISIBLE | 63 | buttonDelete.visibility = View.VISIBLE |
| 64 | } else { | ||
| 65 | version.visibility = View.GONE | ||
| 66 | description.visibility = View.GONE | ||
| 67 | buttonDelete.visibility = View.GONE | ||
| 97 | } | 68 | } |
| 98 | } | 69 | } |
| 99 | } | 70 | } |
| 100 | } | 71 | } |
| 101 | |||
| 102 | private class DiffCallback : DiffUtil.ItemCallback<Pair<String, GpuDriverMetadata>>() { | ||
| 103 | override fun areItemsTheSame( | ||
| 104 | oldItem: Pair<String, GpuDriverMetadata>, | ||
| 105 | newItem: Pair<String, GpuDriverMetadata> | ||
| 106 | ): Boolean { | ||
| 107 | return oldItem.first == newItem.first | ||
| 108 | } | ||
| 109 | |||
| 110 | override fun areContentsTheSame( | ||
| 111 | oldItem: Pair<String, GpuDriverMetadata>, | ||
| 112 | newItem: Pair<String, GpuDriverMetadata> | ||
| 113 | ): Boolean { | ||
| 114 | return oldItem.second == newItem.second | ||
| 115 | } | ||
| 116 | } | ||
| 117 | } | 72 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt index ab657a7b9..3d8f0bda8 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt | |||
| @@ -8,19 +8,14 @@ import android.text.TextUtils | |||
| 8 | import android.view.LayoutInflater | 8 | import android.view.LayoutInflater |
| 9 | import android.view.ViewGroup | 9 | import android.view.ViewGroup |
| 10 | import androidx.fragment.app.FragmentActivity | 10 | import androidx.fragment.app.FragmentActivity |
| 11 | import androidx.recyclerview.widget.AsyncDifferConfig | ||
| 12 | import androidx.recyclerview.widget.DiffUtil | ||
| 13 | import androidx.recyclerview.widget.ListAdapter | ||
| 14 | import androidx.recyclerview.widget.RecyclerView | ||
| 15 | import org.yuzu.yuzu_emu.databinding.CardFolderBinding | 11 | import org.yuzu.yuzu_emu.databinding.CardFolderBinding |
| 16 | import org.yuzu.yuzu_emu.fragments.GameFolderPropertiesDialogFragment | 12 | import org.yuzu.yuzu_emu.fragments.GameFolderPropertiesDialogFragment |
| 17 | import org.yuzu.yuzu_emu.model.GameDir | 13 | import org.yuzu.yuzu_emu.model.GameDir |
| 18 | import org.yuzu.yuzu_emu.model.GamesViewModel | 14 | import org.yuzu.yuzu_emu.model.GamesViewModel |
| 15 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 19 | 16 | ||
| 20 | class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesViewModel) : | 17 | class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesViewModel) : |
| 21 | ListAdapter<GameDir, FolderAdapter.FolderViewHolder>( | 18 | AbstractDiffAdapter<GameDir, FolderAdapter.FolderViewHolder>() { |
| 22 | AsyncDifferConfig.Builder(DiffCallback()).build() | ||
| 23 | ) { | ||
| 24 | override fun onCreateViewHolder( | 19 | override fun onCreateViewHolder( |
| 25 | parent: ViewGroup, | 20 | parent: ViewGroup, |
| 26 | viewType: Int | 21 | viewType: Int |
| @@ -29,18 +24,11 @@ class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesVie | |||
| 29 | .also { return FolderViewHolder(it) } | 24 | .also { return FolderViewHolder(it) } |
| 30 | } | 25 | } |
| 31 | 26 | ||
| 32 | override fun onBindViewHolder(holder: FolderAdapter.FolderViewHolder, position: Int) = | ||
| 33 | holder.bind(currentList[position]) | ||
| 34 | |||
| 35 | inner class FolderViewHolder(val binding: CardFolderBinding) : | 27 | inner class FolderViewHolder(val binding: CardFolderBinding) : |
| 36 | RecyclerView.ViewHolder(binding.root) { | 28 | AbstractViewHolder<GameDir>(binding) { |
| 37 | private lateinit var gameDir: GameDir | 29 | override fun bind(model: GameDir) { |
| 38 | |||
| 39 | fun bind(gameDir: GameDir) { | ||
| 40 | this.gameDir = gameDir | ||
| 41 | |||
| 42 | binding.apply { | 30 | binding.apply { |
| 43 | path.text = Uri.parse(gameDir.uriString).path | 31 | path.text = Uri.parse(model.uriString).path |
| 44 | path.postDelayed( | 32 | path.postDelayed( |
| 45 | { | 33 | { |
| 46 | path.isSelected = true | 34 | path.isSelected = true |
| @@ -50,7 +38,7 @@ class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesVie | |||
| 50 | ) | 38 | ) |
| 51 | 39 | ||
| 52 | buttonEdit.setOnClickListener { | 40 | buttonEdit.setOnClickListener { |
| 53 | GameFolderPropertiesDialogFragment.newInstance(this@FolderViewHolder.gameDir) | 41 | GameFolderPropertiesDialogFragment.newInstance(model) |
| 54 | .show( | 42 | .show( |
| 55 | activity.supportFragmentManager, | 43 | activity.supportFragmentManager, |
| 56 | GameFolderPropertiesDialogFragment.TAG | 44 | GameFolderPropertiesDialogFragment.TAG |
| @@ -58,19 +46,9 @@ class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesVie | |||
| 58 | } | 46 | } |
| 59 | 47 | ||
| 60 | buttonDelete.setOnClickListener { | 48 | buttonDelete.setOnClickListener { |
| 61 | gamesViewModel.removeFolder(this@FolderViewHolder.gameDir) | 49 | gamesViewModel.removeFolder(model) |
| 62 | } | 50 | } |
| 63 | } | 51 | } |
| 64 | } | 52 | } |
| 65 | } | 53 | } |
| 66 | |||
| 67 | private class DiffCallback : DiffUtil.ItemCallback<GameDir>() { | ||
| 68 | override fun areItemsTheSame(oldItem: GameDir, newItem: GameDir): Boolean { | ||
| 69 | return oldItem == newItem | ||
| 70 | } | ||
| 71 | |||
| 72 | override fun areContentsTheSame(oldItem: GameDir, newItem: GameDir): Boolean { | ||
| 73 | return oldItem == newItem | ||
| 74 | } | ||
| 75 | } | ||
| 76 | } | 54 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt index a578f0de8..e26c2e0ab 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt | |||
| @@ -9,7 +9,6 @@ import android.graphics.drawable.LayerDrawable | |||
| 9 | import android.net.Uri | 9 | import android.net.Uri |
| 10 | import android.text.TextUtils | 10 | import android.text.TextUtils |
| 11 | import android.view.LayoutInflater | 11 | import android.view.LayoutInflater |
| 12 | import android.view.View | ||
| 13 | import android.view.ViewGroup | 12 | import android.view.ViewGroup |
| 14 | import android.widget.ImageView | 13 | import android.widget.ImageView |
| 15 | import android.widget.Toast | 14 | import android.widget.Toast |
| @@ -25,10 +24,6 @@ import androidx.lifecycle.ViewModelProvider | |||
| 25 | import androidx.lifecycle.lifecycleScope | 24 | import androidx.lifecycle.lifecycleScope |
| 26 | import androidx.navigation.findNavController | 25 | import androidx.navigation.findNavController |
| 27 | import androidx.preference.PreferenceManager | 26 | import androidx.preference.PreferenceManager |
| 28 | import androidx.recyclerview.widget.AsyncDifferConfig | ||
| 29 | import androidx.recyclerview.widget.DiffUtil | ||
| 30 | import androidx.recyclerview.widget.ListAdapter | ||
| 31 | import androidx.recyclerview.widget.RecyclerView | ||
| 32 | import kotlinx.coroutines.Dispatchers | 27 | import kotlinx.coroutines.Dispatchers |
| 33 | import kotlinx.coroutines.launch | 28 | import kotlinx.coroutines.launch |
| 34 | import kotlinx.coroutines.withContext | 29 | import kotlinx.coroutines.withContext |
| @@ -36,122 +31,26 @@ import org.yuzu.yuzu_emu.HomeNavigationDirections | |||
| 36 | import org.yuzu.yuzu_emu.R | 31 | import org.yuzu.yuzu_emu.R |
| 37 | import org.yuzu.yuzu_emu.YuzuApplication | 32 | import org.yuzu.yuzu_emu.YuzuApplication |
| 38 | import org.yuzu.yuzu_emu.activities.EmulationActivity | 33 | import org.yuzu.yuzu_emu.activities.EmulationActivity |
| 39 | import org.yuzu.yuzu_emu.adapters.GameAdapter.GameViewHolder | ||
| 40 | import org.yuzu.yuzu_emu.databinding.CardGameBinding | 34 | import org.yuzu.yuzu_emu.databinding.CardGameBinding |
| 41 | import org.yuzu.yuzu_emu.model.Game | 35 | import org.yuzu.yuzu_emu.model.Game |
| 42 | import org.yuzu.yuzu_emu.model.GamesViewModel | 36 | import org.yuzu.yuzu_emu.model.GamesViewModel |
| 43 | import org.yuzu.yuzu_emu.utils.GameIconUtils | 37 | import org.yuzu.yuzu_emu.utils.GameIconUtils |
| 38 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 44 | 39 | ||
| 45 | class GameAdapter(private val activity: AppCompatActivity) : | 40 | class GameAdapter(private val activity: AppCompatActivity) : |
| 46 | ListAdapter<Game, GameViewHolder>(AsyncDifferConfig.Builder(DiffCallback()).build()), | 41 | AbstractDiffAdapter<Game, GameAdapter.GameViewHolder>() { |
| 47 | View.OnClickListener, | ||
| 48 | View.OnLongClickListener { | ||
| 49 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder { | 42 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder { |
| 50 | // Create a new view. | 43 | CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 51 | val binding = CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 44 | .also { return GameViewHolder(it) } |
| 52 | binding.cardGame.setOnClickListener(this) | ||
| 53 | binding.cardGame.setOnLongClickListener(this) | ||
| 54 | |||
| 55 | // Use that view to create a ViewHolder. | ||
| 56 | return GameViewHolder(binding) | ||
| 57 | } | ||
| 58 | |||
| 59 | override fun onBindViewHolder(holder: GameViewHolder, position: Int) = | ||
| 60 | holder.bind(currentList[position]) | ||
| 61 | |||
| 62 | override fun getItemCount(): Int = currentList.size | ||
| 63 | |||
| 64 | /** | ||
| 65 | * Launches the game that was clicked on. | ||
| 66 | * | ||
| 67 | * @param view The card representing the game the user wants to play. | ||
| 68 | */ | ||
| 69 | override fun onClick(view: View) { | ||
| 70 | val holder = view.tag as GameViewHolder | ||
| 71 | |||
| 72 | val gameExists = DocumentFile.fromSingleUri( | ||
| 73 | YuzuApplication.appContext, | ||
| 74 | Uri.parse(holder.game.path) | ||
| 75 | )?.exists() == true | ||
| 76 | if (!gameExists) { | ||
| 77 | Toast.makeText( | ||
| 78 | YuzuApplication.appContext, | ||
| 79 | R.string.loader_error_file_not_found, | ||
| 80 | Toast.LENGTH_LONG | ||
| 81 | ).show() | ||
| 82 | |||
| 83 | ViewModelProvider(activity)[GamesViewModel::class.java].reloadGames(true) | ||
| 84 | return | ||
| 85 | } | ||
| 86 | |||
| 87 | val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 88 | preferences.edit() | ||
| 89 | .putLong( | ||
| 90 | holder.game.keyLastPlayedTime, | ||
| 91 | System.currentTimeMillis() | ||
| 92 | ) | ||
| 93 | .apply() | ||
| 94 | |||
| 95 | val openIntent = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply { | ||
| 96 | action = Intent.ACTION_VIEW | ||
| 97 | data = Uri.parse(holder.game.path) | ||
| 98 | } | ||
| 99 | |||
| 100 | activity.lifecycleScope.launch { | ||
| 101 | withContext(Dispatchers.IO) { | ||
| 102 | val layerDrawable = ResourcesCompat.getDrawable( | ||
| 103 | YuzuApplication.appContext.resources, | ||
| 104 | R.drawable.shortcut, | ||
| 105 | null | ||
| 106 | ) as LayerDrawable | ||
| 107 | layerDrawable.setDrawableByLayerId( | ||
| 108 | R.id.shortcut_foreground, | ||
| 109 | GameIconUtils.getGameIcon(activity, holder.game) | ||
| 110 | .toDrawable(YuzuApplication.appContext.resources) | ||
| 111 | ) | ||
| 112 | val inset = YuzuApplication.appContext.resources | ||
| 113 | .getDimensionPixelSize(R.dimen.icon_inset) | ||
| 114 | layerDrawable.setLayerInset(1, inset, inset, inset, inset) | ||
| 115 | val shortcut = | ||
| 116 | ShortcutInfoCompat.Builder(YuzuApplication.appContext, holder.game.path) | ||
| 117 | .setShortLabel(holder.game.title) | ||
| 118 | .setIcon( | ||
| 119 | IconCompat.createWithAdaptiveBitmap( | ||
| 120 | layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888) | ||
| 121 | ) | ||
| 122 | ) | ||
| 123 | .setIntent(openIntent) | ||
| 124 | .build() | ||
| 125 | ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game, true) | ||
| 130 | view.findNavController().navigate(action) | ||
| 131 | } | ||
| 132 | |||
| 133 | override fun onLongClick(view: View): Boolean { | ||
| 134 | val holder = view.tag as GameViewHolder | ||
| 135 | val action = HomeNavigationDirections.actionGlobalPerGamePropertiesFragment(holder.game) | ||
| 136 | view.findNavController().navigate(action) | ||
| 137 | return true | ||
| 138 | } | 45 | } |
| 139 | 46 | ||
| 140 | inner class GameViewHolder(val binding: CardGameBinding) : | 47 | inner class GameViewHolder(val binding: CardGameBinding) : |
| 141 | RecyclerView.ViewHolder(binding.root) { | 48 | AbstractViewHolder<Game>(binding) { |
| 142 | lateinit var game: Game | 49 | override fun bind(model: Game) { |
| 143 | |||
| 144 | init { | ||
| 145 | binding.cardGame.tag = this | ||
| 146 | } | ||
| 147 | |||
| 148 | fun bind(game: Game) { | ||
| 149 | this.game = game | ||
| 150 | |||
| 151 | binding.imageGameScreen.scaleType = ImageView.ScaleType.CENTER_CROP | 50 | binding.imageGameScreen.scaleType = ImageView.ScaleType.CENTER_CROP |
| 152 | GameIconUtils.loadGameIcon(game, binding.imageGameScreen) | 51 | GameIconUtils.loadGameIcon(model, binding.imageGameScreen) |
| 153 | 52 | ||
| 154 | binding.textGameTitle.text = game.title.replace("[\\t\\n\\r]+".toRegex(), " ") | 53 | binding.textGameTitle.text = model.title.replace("[\\t\\n\\r]+".toRegex(), " ") |
| 155 | 54 | ||
| 156 | binding.textGameTitle.postDelayed( | 55 | binding.textGameTitle.postDelayed( |
| 157 | { | 56 | { |
| @@ -160,16 +59,79 @@ class GameAdapter(private val activity: AppCompatActivity) : | |||
| 160 | }, | 59 | }, |
| 161 | 3000 | 60 | 3000 |
| 162 | ) | 61 | ) |
| 62 | |||
| 63 | binding.cardGame.setOnClickListener { onClick(model) } | ||
| 64 | binding.cardGame.setOnLongClickListener { onLongClick(model) } | ||
| 163 | } | 65 | } |
| 164 | } | ||
| 165 | 66 | ||
| 166 | private class DiffCallback : DiffUtil.ItemCallback<Game>() { | 67 | fun onClick(game: Game) { |
| 167 | override fun areItemsTheSame(oldItem: Game, newItem: Game): Boolean { | 68 | val gameExists = DocumentFile.fromSingleUri( |
| 168 | return oldItem == newItem | 69 | YuzuApplication.appContext, |
| 70 | Uri.parse(game.path) | ||
| 71 | )?.exists() == true | ||
| 72 | if (!gameExists) { | ||
| 73 | Toast.makeText( | ||
| 74 | YuzuApplication.appContext, | ||
| 75 | R.string.loader_error_file_not_found, | ||
| 76 | Toast.LENGTH_LONG | ||
| 77 | ).show() | ||
| 78 | |||
| 79 | ViewModelProvider(activity)[GamesViewModel::class.java].reloadGames(true) | ||
| 80 | return | ||
| 81 | } | ||
| 82 | |||
| 83 | val preferences = | ||
| 84 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 85 | preferences.edit() | ||
| 86 | .putLong( | ||
| 87 | game.keyLastPlayedTime, | ||
| 88 | System.currentTimeMillis() | ||
| 89 | ) | ||
| 90 | .apply() | ||
| 91 | |||
| 92 | val openIntent = | ||
| 93 | Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply { | ||
| 94 | action = Intent.ACTION_VIEW | ||
| 95 | data = Uri.parse(game.path) | ||
| 96 | } | ||
| 97 | |||
| 98 | activity.lifecycleScope.launch { | ||
| 99 | withContext(Dispatchers.IO) { | ||
| 100 | val layerDrawable = ResourcesCompat.getDrawable( | ||
| 101 | YuzuApplication.appContext.resources, | ||
| 102 | R.drawable.shortcut, | ||
| 103 | null | ||
| 104 | ) as LayerDrawable | ||
| 105 | layerDrawable.setDrawableByLayerId( | ||
| 106 | R.id.shortcut_foreground, | ||
| 107 | GameIconUtils.getGameIcon(activity, game) | ||
| 108 | .toDrawable(YuzuApplication.appContext.resources) | ||
| 109 | ) | ||
| 110 | val inset = YuzuApplication.appContext.resources | ||
| 111 | .getDimensionPixelSize(R.dimen.icon_inset) | ||
| 112 | layerDrawable.setLayerInset(1, inset, inset, inset, inset) | ||
| 113 | val shortcut = | ||
| 114 | ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path) | ||
| 115 | .setShortLabel(game.title) | ||
| 116 | .setIcon( | ||
| 117 | IconCompat.createWithAdaptiveBitmap( | ||
| 118 | layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888) | ||
| 119 | ) | ||
| 120 | ) | ||
| 121 | .setIntent(openIntent) | ||
| 122 | .build() | ||
| 123 | ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | val action = HomeNavigationDirections.actionGlobalEmulationActivity(game, true) | ||
| 128 | binding.root.findNavController().navigate(action) | ||
| 169 | } | 129 | } |
| 170 | 130 | ||
| 171 | override fun areContentsTheSame(oldItem: Game, newItem: Game): Boolean { | 131 | fun onLongClick(game: Game): Boolean { |
| 172 | return oldItem == newItem | 132 | val action = HomeNavigationDirections.actionGlobalPerGamePropertiesFragment(game) |
| 133 | binding.root.findNavController().navigate(action) | ||
| 134 | return true | ||
| 173 | } | 135 | } |
| 174 | } | 136 | } |
| 175 | } | 137 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GamePropertiesAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GamePropertiesAdapter.kt index 95841d786..0046d5314 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GamePropertiesAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GamePropertiesAdapter.kt | |||
| @@ -12,23 +12,22 @@ import androidx.lifecycle.Lifecycle | |||
| 12 | import androidx.lifecycle.LifecycleOwner | 12 | import androidx.lifecycle.LifecycleOwner |
| 13 | import androidx.lifecycle.lifecycleScope | 13 | import androidx.lifecycle.lifecycleScope |
| 14 | import androidx.lifecycle.repeatOnLifecycle | 14 | import androidx.lifecycle.repeatOnLifecycle |
| 15 | import androidx.recyclerview.widget.RecyclerView | ||
| 16 | import kotlinx.coroutines.launch | 15 | import kotlinx.coroutines.launch |
| 17 | import org.yuzu.yuzu_emu.databinding.CardInstallableIconBinding | 16 | import org.yuzu.yuzu_emu.databinding.CardInstallableIconBinding |
| 18 | import org.yuzu.yuzu_emu.databinding.CardSimpleOutlinedBinding | 17 | import org.yuzu.yuzu_emu.databinding.CardSimpleOutlinedBinding |
| 19 | import org.yuzu.yuzu_emu.model.GameProperty | 18 | import org.yuzu.yuzu_emu.model.GameProperty |
| 20 | import org.yuzu.yuzu_emu.model.InstallableProperty | 19 | import org.yuzu.yuzu_emu.model.InstallableProperty |
| 21 | import org.yuzu.yuzu_emu.model.SubmenuProperty | 20 | import org.yuzu.yuzu_emu.model.SubmenuProperty |
| 21 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 22 | 22 | ||
| 23 | class GamePropertiesAdapter( | 23 | class GamePropertiesAdapter( |
| 24 | private val viewLifecycle: LifecycleOwner, | 24 | private val viewLifecycle: LifecycleOwner, |
| 25 | private var properties: List<GameProperty> | 25 | private var properties: List<GameProperty> |
| 26 | ) : | 26 | ) : AbstractListAdapter<GameProperty, AbstractViewHolder<GameProperty>>(properties) { |
| 27 | RecyclerView.Adapter<GamePropertiesAdapter.GamePropertyViewHolder>() { | ||
| 28 | override fun onCreateViewHolder( | 27 | override fun onCreateViewHolder( |
| 29 | parent: ViewGroup, | 28 | parent: ViewGroup, |
| 30 | viewType: Int | 29 | viewType: Int |
| 31 | ): GamePropertyViewHolder { | 30 | ): AbstractViewHolder<GameProperty> { |
| 32 | val inflater = LayoutInflater.from(parent.context) | 31 | val inflater = LayoutInflater.from(parent.context) |
| 33 | return when (viewType) { | 32 | return when (viewType) { |
| 34 | PropertyType.Submenu.ordinal -> { | 33 | PropertyType.Submenu.ordinal -> { |
| @@ -51,11 +50,6 @@ class GamePropertiesAdapter( | |||
| 51 | } | 50 | } |
| 52 | } | 51 | } |
| 53 | 52 | ||
| 54 | override fun getItemCount(): Int = properties.size | ||
| 55 | |||
| 56 | override fun onBindViewHolder(holder: GamePropertyViewHolder, position: Int) = | ||
| 57 | holder.bind(properties[position]) | ||
| 58 | |||
| 59 | override fun getItemViewType(position: Int): Int { | 53 | override fun getItemViewType(position: Int): Int { |
| 60 | return when (properties[position]) { | 54 | return when (properties[position]) { |
| 61 | is SubmenuProperty -> PropertyType.Submenu.ordinal | 55 | is SubmenuProperty -> PropertyType.Submenu.ordinal |
| @@ -63,14 +57,10 @@ class GamePropertiesAdapter( | |||
| 63 | } | 57 | } |
| 64 | } | 58 | } |
| 65 | 59 | ||
| 66 | sealed class GamePropertyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { | ||
| 67 | abstract fun bind(property: GameProperty) | ||
| 68 | } | ||
| 69 | |||
| 70 | inner class SubmenuPropertyViewHolder(val binding: CardSimpleOutlinedBinding) : | 60 | inner class SubmenuPropertyViewHolder(val binding: CardSimpleOutlinedBinding) : |
| 71 | GamePropertyViewHolder(binding.root) { | 61 | AbstractViewHolder<GameProperty>(binding) { |
| 72 | override fun bind(property: GameProperty) { | 62 | override fun bind(model: GameProperty) { |
| 73 | val submenuProperty = property as SubmenuProperty | 63 | val submenuProperty = model as SubmenuProperty |
| 74 | 64 | ||
| 75 | binding.root.setOnClickListener { | 65 | binding.root.setOnClickListener { |
| 76 | submenuProperty.action.invoke() | 66 | submenuProperty.action.invoke() |
| @@ -108,9 +98,9 @@ class GamePropertiesAdapter( | |||
| 108 | } | 98 | } |
| 109 | 99 | ||
| 110 | inner class InstallablePropertyViewHolder(val binding: CardInstallableIconBinding) : | 100 | inner class InstallablePropertyViewHolder(val binding: CardInstallableIconBinding) : |
| 111 | GamePropertyViewHolder(binding.root) { | 101 | AbstractViewHolder<GameProperty>(binding) { |
| 112 | override fun bind(property: GameProperty) { | 102 | override fun bind(model: GameProperty) { |
| 113 | val installableProperty = property as InstallableProperty | 103 | val installableProperty = model as InstallableProperty |
| 114 | 104 | ||
| 115 | binding.title.setText(installableProperty.titleId) | 105 | binding.title.setText(installableProperty.titleId) |
| 116 | binding.description.setText(installableProperty.descriptionId) | 106 | binding.description.setText(installableProperty.descriptionId) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/HomeSettingAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/HomeSettingAdapter.kt index 58ce343f4..b512845d5 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/HomeSettingAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/HomeSettingAdapter.kt | |||
| @@ -14,69 +14,37 @@ import androidx.lifecycle.Lifecycle | |||
| 14 | import androidx.lifecycle.LifecycleOwner | 14 | import androidx.lifecycle.LifecycleOwner |
| 15 | import androidx.lifecycle.lifecycleScope | 15 | import androidx.lifecycle.lifecycleScope |
| 16 | import androidx.lifecycle.repeatOnLifecycle | 16 | import androidx.lifecycle.repeatOnLifecycle |
| 17 | import androidx.recyclerview.widget.RecyclerView | ||
| 18 | import kotlinx.coroutines.launch | 17 | import kotlinx.coroutines.launch |
| 19 | import org.yuzu.yuzu_emu.R | 18 | import org.yuzu.yuzu_emu.R |
| 20 | import org.yuzu.yuzu_emu.databinding.CardHomeOptionBinding | 19 | import org.yuzu.yuzu_emu.databinding.CardHomeOptionBinding |
| 21 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment | 20 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment |
| 22 | import org.yuzu.yuzu_emu.model.HomeSetting | 21 | import org.yuzu.yuzu_emu.model.HomeSetting |
| 22 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 23 | 23 | ||
| 24 | class HomeSettingAdapter( | 24 | class HomeSettingAdapter( |
| 25 | private val activity: AppCompatActivity, | 25 | private val activity: AppCompatActivity, |
| 26 | private val viewLifecycle: LifecycleOwner, | 26 | private val viewLifecycle: LifecycleOwner, |
| 27 | var options: List<HomeSetting> | 27 | options: List<HomeSetting> |
| 28 | ) : | 28 | ) : AbstractListAdapter<HomeSetting, HomeSettingAdapter.HomeOptionViewHolder>(options) { |
| 29 | RecyclerView.Adapter<HomeSettingAdapter.HomeOptionViewHolder>(), | ||
| 30 | View.OnClickListener { | ||
| 31 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeOptionViewHolder { | 29 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeOptionViewHolder { |
| 32 | val binding = | 30 | CardHomeOptionBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 33 | CardHomeOptionBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 31 | .also { return HomeOptionViewHolder(it) } |
| 34 | binding.root.setOnClickListener(this) | ||
| 35 | return HomeOptionViewHolder(binding) | ||
| 36 | } | ||
| 37 | |||
| 38 | override fun getItemCount(): Int { | ||
| 39 | return options.size | ||
| 40 | } | ||
| 41 | |||
| 42 | override fun onBindViewHolder(holder: HomeOptionViewHolder, position: Int) { | ||
| 43 | holder.bind(options[position]) | ||
| 44 | } | ||
| 45 | |||
| 46 | override fun onClick(view: View) { | ||
| 47 | val holder = view.tag as HomeOptionViewHolder | ||
| 48 | if (holder.option.isEnabled.invoke()) { | ||
| 49 | holder.option.onClick.invoke() | ||
| 50 | } else { | ||
| 51 | MessageDialogFragment.newInstance( | ||
| 52 | activity, | ||
| 53 | titleId = holder.option.disabledTitleId, | ||
| 54 | descriptionId = holder.option.disabledMessageId | ||
| 55 | ).show(activity.supportFragmentManager, MessageDialogFragment.TAG) | ||
| 56 | } | ||
| 57 | } | 32 | } |
| 58 | 33 | ||
| 59 | inner class HomeOptionViewHolder(val binding: CardHomeOptionBinding) : | 34 | inner class HomeOptionViewHolder(val binding: CardHomeOptionBinding) : |
| 60 | RecyclerView.ViewHolder(binding.root) { | 35 | AbstractViewHolder<HomeSetting>(binding) { |
| 61 | lateinit var option: HomeSetting | 36 | override fun bind(model: HomeSetting) { |
| 62 | 37 | binding.optionTitle.text = activity.resources.getString(model.titleId) | |
| 63 | init { | 38 | binding.optionDescription.text = activity.resources.getString(model.descriptionId) |
| 64 | itemView.tag = this | ||
| 65 | } | ||
| 66 | |||
| 67 | fun bind(option: HomeSetting) { | ||
| 68 | this.option = option | ||
| 69 | binding.optionTitle.text = activity.resources.getString(option.titleId) | ||
| 70 | binding.optionDescription.text = activity.resources.getString(option.descriptionId) | ||
| 71 | binding.optionIcon.setImageDrawable( | 39 | binding.optionIcon.setImageDrawable( |
| 72 | ResourcesCompat.getDrawable( | 40 | ResourcesCompat.getDrawable( |
| 73 | activity.resources, | 41 | activity.resources, |
| 74 | option.iconId, | 42 | model.iconId, |
| 75 | activity.theme | 43 | activity.theme |
| 76 | ) | 44 | ) |
| 77 | ) | 45 | ) |
| 78 | 46 | ||
| 79 | when (option.titleId) { | 47 | when (model.titleId) { |
| 80 | R.string.get_early_access -> | 48 | R.string.get_early_access -> |
| 81 | binding.optionLayout.background = | 49 | binding.optionLayout.background = |
| 82 | ContextCompat.getDrawable( | 50 | ContextCompat.getDrawable( |
| @@ -85,7 +53,7 @@ class HomeSettingAdapter( | |||
| 85 | ) | 53 | ) |
| 86 | } | 54 | } |
| 87 | 55 | ||
| 88 | if (!option.isEnabled.invoke()) { | 56 | if (!model.isEnabled.invoke()) { |
| 89 | binding.optionTitle.alpha = 0.5f | 57 | binding.optionTitle.alpha = 0.5f |
| 90 | binding.optionDescription.alpha = 0.5f | 58 | binding.optionDescription.alpha = 0.5f |
| 91 | binding.optionIcon.alpha = 0.5f | 59 | binding.optionIcon.alpha = 0.5f |
| @@ -93,7 +61,7 @@ class HomeSettingAdapter( | |||
| 93 | 61 | ||
| 94 | viewLifecycle.lifecycleScope.launch { | 62 | viewLifecycle.lifecycleScope.launch { |
| 95 | viewLifecycle.repeatOnLifecycle(Lifecycle.State.CREATED) { | 63 | viewLifecycle.repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 96 | option.details.collect { updateOptionDetails(it) } | 64 | model.details.collect { updateOptionDetails(it) } |
| 97 | } | 65 | } |
| 98 | } | 66 | } |
| 99 | binding.optionDetail.postDelayed( | 67 | binding.optionDetail.postDelayed( |
| @@ -103,6 +71,20 @@ class HomeSettingAdapter( | |||
| 103 | }, | 71 | }, |
| 104 | 3000 | 72 | 3000 |
| 105 | ) | 73 | ) |
| 74 | |||
| 75 | binding.root.setOnClickListener { onClick(model) } | ||
| 76 | } | ||
| 77 | |||
| 78 | private fun onClick(model: HomeSetting) { | ||
| 79 | if (model.isEnabled.invoke()) { | ||
| 80 | model.onClick.invoke() | ||
| 81 | } else { | ||
| 82 | MessageDialogFragment.newInstance( | ||
| 83 | activity, | ||
| 84 | titleId = model.disabledTitleId, | ||
| 85 | descriptionId = model.disabledMessageId | ||
| 86 | ).show(activity.supportFragmentManager, MessageDialogFragment.TAG) | ||
| 87 | } | ||
| 106 | } | 88 | } |
| 107 | 89 | ||
| 108 | private fun updateOptionDetails(detailString: String) { | 90 | private fun updateOptionDetails(detailString: String) { |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/InstallableAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/InstallableAdapter.kt index e960fbaab..4218c4e52 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/InstallableAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/InstallableAdapter.kt | |||
| @@ -6,43 +6,33 @@ package org.yuzu.yuzu_emu.adapters | |||
| 6 | import android.view.LayoutInflater | 6 | import android.view.LayoutInflater |
| 7 | import android.view.View | 7 | import android.view.View |
| 8 | import android.view.ViewGroup | 8 | import android.view.ViewGroup |
| 9 | import androidx.recyclerview.widget.RecyclerView | ||
| 10 | import org.yuzu.yuzu_emu.databinding.CardInstallableBinding | 9 | import org.yuzu.yuzu_emu.databinding.CardInstallableBinding |
| 11 | import org.yuzu.yuzu_emu.model.Installable | 10 | import org.yuzu.yuzu_emu.model.Installable |
| 11 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 12 | 12 | ||
| 13 | class InstallableAdapter(private val installables: List<Installable>) : | 13 | class InstallableAdapter(installables: List<Installable>) : |
| 14 | RecyclerView.Adapter<InstallableAdapter.InstallableViewHolder>() { | 14 | AbstractListAdapter<Installable, InstallableAdapter.InstallableViewHolder>(installables) { |
| 15 | override fun onCreateViewHolder( | 15 | override fun onCreateViewHolder( |
| 16 | parent: ViewGroup, | 16 | parent: ViewGroup, |
| 17 | viewType: Int | 17 | viewType: Int |
| 18 | ): InstallableAdapter.InstallableViewHolder { | 18 | ): InstallableAdapter.InstallableViewHolder { |
| 19 | val binding = | 19 | CardInstallableBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 20 | CardInstallableBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 20 | .also { return InstallableViewHolder(it) } |
| 21 | return InstallableViewHolder(binding) | ||
| 22 | } | 21 | } |
| 23 | 22 | ||
| 24 | override fun getItemCount(): Int = installables.size | ||
| 25 | |||
| 26 | override fun onBindViewHolder(holder: InstallableAdapter.InstallableViewHolder, position: Int) = | ||
| 27 | holder.bind(installables[position]) | ||
| 28 | |||
| 29 | inner class InstallableViewHolder(val binding: CardInstallableBinding) : | 23 | inner class InstallableViewHolder(val binding: CardInstallableBinding) : |
| 30 | RecyclerView.ViewHolder(binding.root) { | 24 | AbstractViewHolder<Installable>(binding) { |
| 31 | lateinit var installable: Installable | 25 | override fun bind(model: Installable) { |
| 32 | 26 | binding.title.setText(model.titleId) | |
| 33 | fun bind(installable: Installable) { | 27 | binding.description.setText(model.descriptionId) |
| 34 | this.installable = installable | ||
| 35 | |||
| 36 | binding.title.setText(installable.titleId) | ||
| 37 | binding.description.setText(installable.descriptionId) | ||
| 38 | 28 | ||
| 39 | if (installable.install != null) { | 29 | if (model.install != null) { |
| 40 | binding.buttonInstall.visibility = View.VISIBLE | 30 | binding.buttonInstall.visibility = View.VISIBLE |
| 41 | binding.buttonInstall.setOnClickListener { installable.install.invoke() } | 31 | binding.buttonInstall.setOnClickListener { model.install.invoke() } |
| 42 | } | 32 | } |
| 43 | if (installable.export != null) { | 33 | if (model.export != null) { |
| 44 | binding.buttonExport.visibility = View.VISIBLE | 34 | binding.buttonExport.visibility = View.VISIBLE |
| 45 | binding.buttonExport.setOnClickListener { installable.export.invoke() } | 35 | binding.buttonExport.setOnClickListener { model.export.invoke() } |
| 46 | } | 36 | } |
| 47 | } | 37 | } |
| 48 | } | 38 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/LicenseAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/LicenseAdapter.kt index bc6ff1364..38bb1f96f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/LicenseAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/LicenseAdapter.kt | |||
| @@ -7,49 +7,33 @@ import android.view.LayoutInflater | |||
| 7 | import android.view.View | 7 | import android.view.View |
| 8 | import android.view.ViewGroup | 8 | import android.view.ViewGroup |
| 9 | import androidx.appcompat.app.AppCompatActivity | 9 | import androidx.appcompat.app.AppCompatActivity |
| 10 | import androidx.recyclerview.widget.RecyclerView | ||
| 11 | import androidx.recyclerview.widget.RecyclerView.ViewHolder | ||
| 12 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 13 | import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding | 10 | import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding |
| 14 | import org.yuzu.yuzu_emu.fragments.LicenseBottomSheetDialogFragment | 11 | import org.yuzu.yuzu_emu.fragments.LicenseBottomSheetDialogFragment |
| 15 | import org.yuzu.yuzu_emu.model.License | 12 | import org.yuzu.yuzu_emu.model.License |
| 13 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 16 | 14 | ||
| 17 | class LicenseAdapter(private val activity: AppCompatActivity, var licenses: List<License>) : | 15 | class LicenseAdapter(private val activity: AppCompatActivity, licenses: List<License>) : |
| 18 | RecyclerView.Adapter<LicenseAdapter.LicenseViewHolder>(), | 16 | AbstractListAdapter<License, LicenseAdapter.LicenseViewHolder>(licenses) { |
| 19 | View.OnClickListener { | ||
| 20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LicenseViewHolder { | 17 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LicenseViewHolder { |
| 21 | val binding = | 18 | ListItemSettingBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 22 | ListItemSettingBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 19 | .also { return LicenseViewHolder(it) } |
| 23 | binding.root.setOnClickListener(this) | ||
| 24 | return LicenseViewHolder(binding) | ||
| 25 | } | 20 | } |
| 26 | 21 | ||
| 27 | override fun getItemCount(): Int = licenses.size | 22 | inner class LicenseViewHolder(val binding: ListItemSettingBinding) : |
| 23 | AbstractViewHolder<License>(binding) { | ||
| 24 | override fun bind(model: License) { | ||
| 25 | binding.apply { | ||
| 26 | textSettingName.text = root.context.getString(model.titleId) | ||
| 27 | textSettingDescription.text = root.context.getString(model.descriptionId) | ||
| 28 | textSettingValue.visibility = View.GONE | ||
| 28 | 29 | ||
| 29 | override fun onBindViewHolder(holder: LicenseViewHolder, position: Int) { | 30 | root.setOnClickListener { onClick(model) } |
| 30 | holder.bind(licenses[position]) | 31 | } |
| 31 | } | ||
| 32 | |||
| 33 | override fun onClick(view: View) { | ||
| 34 | val license = (view.tag as LicenseViewHolder).license | ||
| 35 | LicenseBottomSheetDialogFragment.newInstance(license) | ||
| 36 | .show(activity.supportFragmentManager, LicenseBottomSheetDialogFragment.TAG) | ||
| 37 | } | ||
| 38 | |||
| 39 | inner class LicenseViewHolder(val binding: ListItemSettingBinding) : ViewHolder(binding.root) { | ||
| 40 | lateinit var license: License | ||
| 41 | |||
| 42 | init { | ||
| 43 | itemView.tag = this | ||
| 44 | } | 32 | } |
| 45 | 33 | ||
| 46 | fun bind(license: License) { | 34 | private fun onClick(license: License) { |
| 47 | this.license = license | 35 | LicenseBottomSheetDialogFragment.newInstance(license) |
| 48 | 36 | .show(activity.supportFragmentManager, LicenseBottomSheetDialogFragment.TAG) | |
| 49 | val context = YuzuApplication.appContext | ||
| 50 | binding.textSettingName.text = context.getString(license.titleId) | ||
| 51 | binding.textSettingDescription.text = context.getString(license.descriptionId) | ||
| 52 | binding.textSettingValue.visibility = View.GONE | ||
| 53 | } | 37 | } |
| 54 | } | 38 | } |
| 55 | } | 39 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/SetupAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/SetupAdapter.kt index 6b46d359e..02118e1a8 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/SetupAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/SetupAdapter.kt | |||
| @@ -10,7 +10,6 @@ import android.view.ViewGroup | |||
| 10 | import androidx.appcompat.app.AppCompatActivity | 10 | import androidx.appcompat.app.AppCompatActivity |
| 11 | import androidx.core.content.res.ResourcesCompat | 11 | import androidx.core.content.res.ResourcesCompat |
| 12 | import androidx.lifecycle.ViewModelProvider | 12 | import androidx.lifecycle.ViewModelProvider |
| 13 | import androidx.recyclerview.widget.RecyclerView | ||
| 14 | import com.google.android.material.button.MaterialButton | 13 | import com.google.android.material.button.MaterialButton |
| 15 | import org.yuzu.yuzu_emu.databinding.PageSetupBinding | 14 | import org.yuzu.yuzu_emu.databinding.PageSetupBinding |
| 16 | import org.yuzu.yuzu_emu.model.HomeViewModel | 15 | import org.yuzu.yuzu_emu.model.HomeViewModel |
| @@ -18,31 +17,19 @@ import org.yuzu.yuzu_emu.model.SetupCallback | |||
| 18 | import org.yuzu.yuzu_emu.model.SetupPage | 17 | import org.yuzu.yuzu_emu.model.SetupPage |
| 19 | import org.yuzu.yuzu_emu.model.StepState | 18 | import org.yuzu.yuzu_emu.model.StepState |
| 20 | import org.yuzu.yuzu_emu.utils.ViewUtils | 19 | import org.yuzu.yuzu_emu.utils.ViewUtils |
| 20 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | ||
| 21 | 21 | ||
| 22 | class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) : | 22 | class SetupAdapter(val activity: AppCompatActivity, pages: List<SetupPage>) : |
| 23 | RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() { | 23 | AbstractListAdapter<SetupPage, SetupAdapter.SetupPageViewHolder>(pages) { |
| 24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SetupPageViewHolder { | 24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SetupPageViewHolder { |
| 25 | val binding = PageSetupBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 25 | PageSetupBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 26 | return SetupPageViewHolder(binding) | 26 | .also { return SetupPageViewHolder(it) } |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | override fun getItemCount(): Int = pages.size | ||
| 30 | |||
| 31 | override fun onBindViewHolder(holder: SetupPageViewHolder, position: Int) = | ||
| 32 | holder.bind(pages[position]) | ||
| 33 | |||
| 34 | inner class SetupPageViewHolder(val binding: PageSetupBinding) : | 29 | inner class SetupPageViewHolder(val binding: PageSetupBinding) : |
| 35 | RecyclerView.ViewHolder(binding.root), SetupCallback { | 30 | AbstractViewHolder<SetupPage>(binding), SetupCallback { |
| 36 | lateinit var page: SetupPage | 31 | override fun bind(model: SetupPage) { |
| 37 | 32 | if (model.stepCompleted.invoke() == StepState.COMPLETE) { | |
| 38 | init { | ||
| 39 | itemView.tag = this | ||
| 40 | } | ||
| 41 | |||
| 42 | fun bind(page: SetupPage) { | ||
| 43 | this.page = page | ||
| 44 | |||
| 45 | if (page.stepCompleted.invoke() == StepState.COMPLETE) { | ||
| 46 | binding.buttonAction.visibility = View.INVISIBLE | 33 | binding.buttonAction.visibility = View.INVISIBLE |
| 47 | binding.textConfirmation.visibility = View.VISIBLE | 34 | binding.textConfirmation.visibility = View.VISIBLE |
| 48 | } | 35 | } |
| @@ -50,31 +37,31 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) | |||
| 50 | binding.icon.setImageDrawable( | 37 | binding.icon.setImageDrawable( |
| 51 | ResourcesCompat.getDrawable( | 38 | ResourcesCompat.getDrawable( |
| 52 | activity.resources, | 39 | activity.resources, |
| 53 | page.iconId, | 40 | model.iconId, |
| 54 | activity.theme | 41 | activity.theme |
| 55 | ) | 42 | ) |
| 56 | ) | 43 | ) |
| 57 | binding.textTitle.text = activity.resources.getString(page.titleId) | 44 | binding.textTitle.text = activity.resources.getString(model.titleId) |
| 58 | binding.textDescription.text = | 45 | binding.textDescription.text = |
| 59 | Html.fromHtml(activity.resources.getString(page.descriptionId), 0) | 46 | Html.fromHtml(activity.resources.getString(model.descriptionId), 0) |
| 60 | 47 | ||
| 61 | binding.buttonAction.apply { | 48 | binding.buttonAction.apply { |
| 62 | text = activity.resources.getString(page.buttonTextId) | 49 | text = activity.resources.getString(model.buttonTextId) |
| 63 | if (page.buttonIconId != 0) { | 50 | if (model.buttonIconId != 0) { |
| 64 | icon = ResourcesCompat.getDrawable( | 51 | icon = ResourcesCompat.getDrawable( |
| 65 | activity.resources, | 52 | activity.resources, |
| 66 | page.buttonIconId, | 53 | model.buttonIconId, |
| 67 | activity.theme | 54 | activity.theme |
| 68 | ) | 55 | ) |
| 69 | } | 56 | } |
| 70 | iconGravity = | 57 | iconGravity = |
| 71 | if (page.leftAlignedIcon) { | 58 | if (model.leftAlignedIcon) { |
| 72 | MaterialButton.ICON_GRAVITY_START | 59 | MaterialButton.ICON_GRAVITY_START |
| 73 | } else { | 60 | } else { |
| 74 | MaterialButton.ICON_GRAVITY_END | 61 | MaterialButton.ICON_GRAVITY_END |
| 75 | } | 62 | } |
| 76 | setOnClickListener { | 63 | setOnClickListener { |
| 77 | page.buttonAction.invoke(this@SetupPageViewHolder) | 64 | model.buttonAction.invoke(this@SetupPageViewHolder) |
| 78 | } | 65 | } |
| 79 | } | 66 | } |
| 80 | } | 67 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AboutFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AboutFragment.kt index a1620fbb7..5b5f800c1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AboutFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AboutFragment.kt | |||
| @@ -76,8 +76,8 @@ class AboutFragment : Fragment() { | |||
| 76 | binding.root.findNavController().navigate(R.id.action_aboutFragment_to_licensesFragment) | 76 | binding.root.findNavController().navigate(R.id.action_aboutFragment_to_licensesFragment) |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | binding.textBuildHash.text = BuildConfig.GIT_HASH | 79 | binding.textVersionName.text = BuildConfig.VERSION_NAME |
| 80 | binding.buttonBuildHash.setOnClickListener { | 80 | binding.textVersionName.setOnClickListener { |
| 81 | val clipBoard = | 81 | val clipBoard = |
| 82 | requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager | 82 | requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager |
| 83 | val clip = ClipData.newPlainText(getString(R.string.build), BuildConfig.GIT_HASH) | 83 | val clip = ClipData.newPlainText(getString(R.string.build), BuildConfig.GIT_HASH) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt index cc71254dc..9dabb9c41 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.fragments | 4 | package org.yuzu.yuzu_emu.fragments |
| 5 | 5 | ||
| 6 | import android.annotation.SuppressLint | ||
| 6 | import android.os.Bundle | 7 | import android.os.Bundle |
| 7 | import android.view.LayoutInflater | 8 | import android.view.LayoutInflater |
| 8 | import android.view.View | 9 | import android.view.View |
| @@ -13,20 +14,26 @@ import androidx.core.view.WindowInsetsCompat | |||
| 13 | import androidx.core.view.updatePadding | 14 | import androidx.core.view.updatePadding |
| 14 | import androidx.fragment.app.Fragment | 15 | import androidx.fragment.app.Fragment |
| 15 | import androidx.fragment.app.activityViewModels | 16 | import androidx.fragment.app.activityViewModels |
| 17 | import androidx.lifecycle.Lifecycle | ||
| 16 | import androidx.lifecycle.lifecycleScope | 18 | import androidx.lifecycle.lifecycleScope |
| 19 | import androidx.lifecycle.repeatOnLifecycle | ||
| 17 | import androidx.navigation.findNavController | 20 | import androidx.navigation.findNavController |
| 18 | import androidx.navigation.fragment.navArgs | 21 | import androidx.navigation.fragment.navArgs |
| 19 | import androidx.recyclerview.widget.GridLayoutManager | 22 | import androidx.recyclerview.widget.GridLayoutManager |
| 20 | import com.google.android.material.transition.MaterialSharedAxis | 23 | import com.google.android.material.transition.MaterialSharedAxis |
| 21 | import kotlinx.coroutines.flow.collectLatest | 24 | import kotlinx.coroutines.Dispatchers |
| 22 | import kotlinx.coroutines.launch | 25 | import kotlinx.coroutines.launch |
| 26 | import kotlinx.coroutines.withContext | ||
| 23 | import org.yuzu.yuzu_emu.R | 27 | import org.yuzu.yuzu_emu.R |
| 24 | import org.yuzu.yuzu_emu.adapters.DriverAdapter | 28 | import org.yuzu.yuzu_emu.adapters.DriverAdapter |
| 25 | import org.yuzu.yuzu_emu.databinding.FragmentDriverManagerBinding | 29 | import org.yuzu.yuzu_emu.databinding.FragmentDriverManagerBinding |
| 30 | import org.yuzu.yuzu_emu.features.settings.model.StringSetting | ||
| 31 | import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver | ||
| 26 | import org.yuzu.yuzu_emu.model.DriverViewModel | 32 | import org.yuzu.yuzu_emu.model.DriverViewModel |
| 27 | import org.yuzu.yuzu_emu.model.HomeViewModel | 33 | import org.yuzu.yuzu_emu.model.HomeViewModel |
| 28 | import org.yuzu.yuzu_emu.utils.FileUtil | 34 | import org.yuzu.yuzu_emu.utils.FileUtil |
| 29 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper | 35 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper |
| 36 | import org.yuzu.yuzu_emu.utils.NativeConfig | ||
| 30 | import java.io.File | 37 | import java.io.File |
| 31 | import java.io.IOException | 38 | import java.io.IOException |
| 32 | 39 | ||
| @@ -55,12 +62,43 @@ class DriverManagerFragment : Fragment() { | |||
| 55 | return binding.root | 62 | return binding.root |
| 56 | } | 63 | } |
| 57 | 64 | ||
| 65 | // This is using the correct scope, lint is just acting up | ||
| 66 | @SuppressLint("UnsafeRepeatOnLifecycleDetector") | ||
| 58 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 67 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 59 | super.onViewCreated(view, savedInstanceState) | 68 | super.onViewCreated(view, savedInstanceState) |
| 60 | homeViewModel.setNavigationVisibility(visible = false, animated = true) | 69 | homeViewModel.setNavigationVisibility(visible = false, animated = true) |
| 61 | homeViewModel.setStatusBarShadeVisibility(visible = false) | 70 | homeViewModel.setStatusBarShadeVisibility(visible = false) |
| 62 | 71 | ||
| 63 | driverViewModel.onOpenDriverManager(args.game) | 72 | driverViewModel.onOpenDriverManager(args.game) |
| 73 | if (NativeConfig.isPerGameConfigLoaded()) { | ||
| 74 | binding.toolbarDrivers.inflateMenu(R.menu.menu_driver_manager) | ||
| 75 | driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global) | ||
| 76 | binding.toolbarDrivers.setOnMenuItemClickListener { | ||
| 77 | when (it.itemId) { | ||
| 78 | R.id.menu_driver_clear -> { | ||
| 79 | StringSetting.DRIVER_PATH.global = true | ||
| 80 | driverViewModel.updateDriverList() | ||
| 81 | (binding.listDrivers.adapter as DriverAdapter) | ||
| 82 | .replaceList(driverViewModel.driverList.value) | ||
| 83 | driverViewModel.showClearButton(false) | ||
| 84 | true | ||
| 85 | } | ||
| 86 | |||
| 87 | else -> false | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | viewLifecycleOwner.lifecycleScope.apply { | ||
| 92 | launch { | ||
| 93 | repeatOnLifecycle(Lifecycle.State.STARTED) { | ||
| 94 | driverViewModel.showClearButton.collect { | ||
| 95 | binding.toolbarDrivers.menu | ||
| 96 | .findItem(R.id.menu_driver_clear).isVisible = it | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
| 101 | } | ||
| 64 | 102 | ||
| 65 | if (!driverViewModel.isInteractionAllowed.value) { | 103 | if (!driverViewModel.isInteractionAllowed.value) { |
| 66 | DriversLoadingDialogFragment().show( | 104 | DriversLoadingDialogFragment().show( |
| @@ -85,25 +123,6 @@ class DriverManagerFragment : Fragment() { | |||
| 85 | adapter = DriverAdapter(driverViewModel) | 123 | adapter = DriverAdapter(driverViewModel) |
| 86 | } | 124 | } |
| 87 | 125 | ||
| 88 | viewLifecycleOwner.lifecycleScope.apply { | ||
| 89 | launch { | ||
| 90 | driverViewModel.driverList.collectLatest { | ||
| 91 | (binding.listDrivers.adapter as DriverAdapter).submitList(it) | ||
| 92 | } | ||
| 93 | } | ||
| 94 | launch { | ||
| 95 | driverViewModel.newDriverInstalled.collect { | ||
| 96 | if (_binding != null && it) { | ||
| 97 | (binding.listDrivers.adapter as DriverAdapter).apply { | ||
| 98 | notifyItemChanged(driverViewModel.previouslySelectedDriver) | ||
| 99 | notifyItemChanged(driverViewModel.selectedDriver) | ||
| 100 | driverViewModel.setNewDriverInstalled(false) | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | setInsets() | 126 | setInsets() |
| 108 | } | 127 | } |
| 109 | 128 | ||
| @@ -160,7 +179,7 @@ class DriverManagerFragment : Fragment() { | |||
| 160 | false | 179 | false |
| 161 | ) { | 180 | ) { |
| 162 | val driverPath = | 181 | val driverPath = |
| 163 | "${GpuDriverHelper.driverStoragePath}/${FileUtil.getFilename(result)}" | 182 | "${GpuDriverHelper.driverStoragePath}${FileUtil.getFilename(result)}" |
| 164 | val driverFile = File(driverPath) | 183 | val driverFile = File(driverPath) |
| 165 | 184 | ||
| 166 | // Ignore file exceptions when a user selects an invalid zip | 185 | // Ignore file exceptions when a user selects an invalid zip |
| @@ -177,12 +196,21 @@ class DriverManagerFragment : Fragment() { | |||
| 177 | 196 | ||
| 178 | val driverData = GpuDriverHelper.getMetadataFromZip(driverFile) | 197 | val driverData = GpuDriverHelper.getMetadataFromZip(driverFile) |
| 179 | val driverInList = | 198 | val driverInList = |
| 180 | driverViewModel.driverList.value.firstOrNull { it.second == driverData } | 199 | driverViewModel.driverData.firstOrNull { it.second == driverData } |
| 181 | if (driverInList != null) { | 200 | if (driverInList != null) { |
| 182 | return@newInstance getString(R.string.driver_already_installed) | 201 | return@newInstance getString(R.string.driver_already_installed) |
| 183 | } else { | 202 | } else { |
| 184 | driverViewModel.addDriver(Pair(driverPath, driverData)) | 203 | driverViewModel.onDriverAdded(Pair(driverPath, driverData)) |
| 185 | driverViewModel.setNewDriverInstalled(true) | 204 | withContext(Dispatchers.Main) { |
| 205 | if (_binding != null) { | ||
| 206 | val adapter = binding.listDrivers.adapter as DriverAdapter | ||
| 207 | adapter.addItem(driverData.toDriver()) | ||
| 208 | adapter.selectItem(adapter.currentList.indices.last) | ||
| 209 | driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global) | ||
| 210 | binding.listDrivers | ||
| 211 | .smoothScrollToPosition(adapter.currentList.indices.last) | ||
| 212 | } | ||
| 213 | } | ||
| 186 | } | 214 | } |
| 187 | return@newInstance Any() | 215 | return@newInstance Any() |
| 188 | }.show(childFragmentManager, IndeterminateProgressDialogFragment.TAG) | 216 | }.show(childFragmentManager, IndeterminateProgressDialogFragment.TAG) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Driver.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Driver.kt new file mode 100644 index 000000000..de342212a --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Driver.kt | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | import org.yuzu.yuzu_emu.utils.GpuDriverMetadata | ||
| 7 | |||
| 8 | data class Driver( | ||
| 9 | override var selected: Boolean, | ||
| 10 | val title: String, | ||
| 11 | val version: String = "", | ||
| 12 | val description: String = "" | ||
| 13 | ) : SelectableItem { | ||
| 14 | override fun onSelectionStateChanged(selected: Boolean) { | ||
| 15 | this.selected = selected | ||
| 16 | } | ||
| 17 | |||
| 18 | companion object { | ||
| 19 | fun GpuDriverMetadata.toDriver(selected: Boolean = false): Driver = | ||
| 20 | Driver( | ||
| 21 | selected, | ||
| 22 | this.name ?: "", | ||
| 23 | this.version ?: "", | ||
| 24 | this.description ?: "" | ||
| 25 | ) | ||
| 26 | } | ||
| 27 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt index 76accf8f3..15ae3a42b 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt | |||
| @@ -9,6 +9,7 @@ import kotlinx.coroutines.Dispatchers | |||
| 9 | import kotlinx.coroutines.flow.MutableStateFlow | 9 | import kotlinx.coroutines.flow.MutableStateFlow |
| 10 | import kotlinx.coroutines.flow.SharingStarted | 10 | import kotlinx.coroutines.flow.SharingStarted |
| 11 | import kotlinx.coroutines.flow.StateFlow | 11 | import kotlinx.coroutines.flow.StateFlow |
| 12 | import kotlinx.coroutines.flow.asStateFlow | ||
| 12 | import kotlinx.coroutines.flow.combine | 13 | import kotlinx.coroutines.flow.combine |
| 13 | import kotlinx.coroutines.flow.stateIn | 14 | import kotlinx.coroutines.flow.stateIn |
| 14 | import kotlinx.coroutines.launch | 15 | import kotlinx.coroutines.launch |
| @@ -17,11 +18,10 @@ import org.yuzu.yuzu_emu.R | |||
| 17 | import org.yuzu.yuzu_emu.YuzuApplication | 18 | import org.yuzu.yuzu_emu.YuzuApplication |
| 18 | import org.yuzu.yuzu_emu.features.settings.model.StringSetting | 19 | import org.yuzu.yuzu_emu.features.settings.model.StringSetting |
| 19 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 20 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile |
| 20 | import org.yuzu.yuzu_emu.utils.FileUtil | 21 | import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver |
| 21 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper | 22 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper |
| 22 | import org.yuzu.yuzu_emu.utils.GpuDriverMetadata | 23 | import org.yuzu.yuzu_emu.utils.GpuDriverMetadata |
| 23 | import org.yuzu.yuzu_emu.utils.NativeConfig | 24 | import org.yuzu.yuzu_emu.utils.NativeConfig |
| 24 | import java.io.BufferedOutputStream | ||
| 25 | import java.io.File | 25 | import java.io.File |
| 26 | 26 | ||
| 27 | class DriverViewModel : ViewModel() { | 27 | class DriverViewModel : ViewModel() { |
| @@ -38,97 +38,81 @@ class DriverViewModel : ViewModel() { | |||
| 38 | !loading && ready && !deleting | 38 | !loading && ready && !deleting |
| 39 | }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), initialValue = false) | 39 | }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), initialValue = false) |
| 40 | 40 | ||
| 41 | private val _driverList = MutableStateFlow(GpuDriverHelper.getDrivers()) | 41 | var driverData = GpuDriverHelper.getDrivers() |
| 42 | val driverList: StateFlow<MutableList<Pair<String, GpuDriverMetadata>>> get() = _driverList | ||
| 43 | 42 | ||
| 44 | var previouslySelectedDriver = 0 | 43 | private val _driverList = MutableStateFlow(emptyList<Driver>()) |
| 45 | var selectedDriver = -1 | 44 | val driverList: StateFlow<List<Driver>> get() = _driverList |
| 46 | 45 | ||
| 47 | // Used for showing which driver is currently installed within the driver manager card | 46 | // Used for showing which driver is currently installed within the driver manager card |
| 48 | private val _selectedDriverTitle = MutableStateFlow("") | 47 | private val _selectedDriverTitle = MutableStateFlow("") |
| 49 | val selectedDriverTitle: StateFlow<String> get() = _selectedDriverTitle | 48 | val selectedDriverTitle: StateFlow<String> get() = _selectedDriverTitle |
| 50 | 49 | ||
| 51 | private val _newDriverInstalled = MutableStateFlow(false) | 50 | private val _showClearButton = MutableStateFlow(false) |
| 52 | val newDriverInstalled: StateFlow<Boolean> get() = _newDriverInstalled | 51 | val showClearButton = _showClearButton.asStateFlow() |
| 53 | 52 | ||
| 54 | val driversToDelete = mutableListOf<String>() | 53 | private val driversToDelete = mutableListOf<String>() |
| 55 | 54 | ||
| 56 | init { | 55 | init { |
| 57 | val currentDriverMetadata = GpuDriverHelper.installedCustomDriverData | 56 | updateDriverList() |
| 58 | findSelectedDriver(currentDriverMetadata) | 57 | updateDriverNameForGame(null) |
| 59 | 58 | } | |
| 60 | // If a user had installed a driver before the manager was implemented, this zips | ||
| 61 | // the installed driver to UserData/gpu_drivers/CustomDriver.zip so that it can | ||
| 62 | // be indexed and exported as expected. | ||
| 63 | if (selectedDriver == -1) { | ||
| 64 | val driverToSave = | ||
| 65 | File(GpuDriverHelper.driverStoragePath, "CustomDriver.zip") | ||
| 66 | driverToSave.createNewFile() | ||
| 67 | FileUtil.zipFromInternalStorage( | ||
| 68 | File(GpuDriverHelper.driverInstallationPath!!), | ||
| 69 | GpuDriverHelper.driverInstallationPath!!, | ||
| 70 | BufferedOutputStream(driverToSave.outputStream()) | ||
| 71 | ) | ||
| 72 | _driverList.value.add(Pair(driverToSave.path, currentDriverMetadata)) | ||
| 73 | setSelectedDriverIndex(_driverList.value.size - 1) | ||
| 74 | } | ||
| 75 | 59 | ||
| 76 | // If a user had installed a driver before the config was reworked to be multiplatform, | 60 | fun reloadDriverData() { |
| 77 | // we have save the path of the previously selected driver to the new setting. | 61 | _areDriversLoading.value = true |
| 78 | if (StringSetting.DRIVER_PATH.getString(true).isEmpty() && selectedDriver > 0 && | 62 | driverData = GpuDriverHelper.getDrivers() |
| 79 | StringSetting.DRIVER_PATH.global | 63 | updateDriverList() |
| 80 | ) { | 64 | _areDriversLoading.value = false |
| 81 | StringSetting.DRIVER_PATH.setString(_driverList.value[selectedDriver].first) | 65 | } |
| 82 | NativeConfig.saveGlobalConfig() | 66 | |
| 83 | } else { | 67 | fun updateDriverList() { |
| 84 | findSelectedDriver(GpuDriverHelper.customDriverSettingData) | 68 | val selectedDriver = GpuDriverHelper.customDriverSettingData |
| 69 | val newDriverList = mutableListOf( | ||
| 70 | Driver( | ||
| 71 | selectedDriver == GpuDriverMetadata(), | ||
| 72 | YuzuApplication.appContext.getString(R.string.system_gpu_driver) | ||
| 73 | ) | ||
| 74 | ) | ||
| 75 | driverData.forEach { | ||
| 76 | newDriverList.add(it.second.toDriver(it.second == selectedDriver)) | ||
| 85 | } | 77 | } |
| 86 | updateDriverNameForGame(null) | 78 | _driverList.value = newDriverList |
| 87 | } | 79 | } |
| 88 | 80 | ||
| 89 | fun setSelectedDriverIndex(value: Int) { | 81 | fun onOpenDriverManager(game: Game?) { |
| 90 | if (selectedDriver != -1) { | 82 | if (game != null) { |
| 91 | previouslySelectedDriver = selectedDriver | 83 | SettingsFile.loadCustomConfig(game) |
| 92 | } | 84 | } |
| 93 | selectedDriver = value | 85 | updateDriverList() |
| 94 | } | 86 | } |
| 95 | 87 | ||
| 96 | fun setNewDriverInstalled(value: Boolean) { | 88 | fun showClearButton(value: Boolean) { |
| 97 | _newDriverInstalled.value = value | 89 | _showClearButton.value = value |
| 98 | } | 90 | } |
| 99 | 91 | ||
| 100 | fun addDriver(driverData: Pair<String, GpuDriverMetadata>) { | 92 | fun onDriverSelected(position: Int) { |
| 101 | val driverIndex = _driverList.value.indexOfFirst { it == driverData } | 93 | if (position == 0) { |
| 102 | if (driverIndex == -1) { | 94 | StringSetting.DRIVER_PATH.setString("") |
| 103 | _driverList.value.add(driverData) | ||
| 104 | setSelectedDriverIndex(_driverList.value.size - 1) | ||
| 105 | _selectedDriverTitle.value = driverData.second.name | ||
| 106 | ?: YuzuApplication.appContext.getString(R.string.system_gpu_driver) | ||
| 107 | } else { | 95 | } else { |
| 108 | setSelectedDriverIndex(driverIndex) | 96 | StringSetting.DRIVER_PATH.setString(driverData[position - 1].first) |
| 109 | } | 97 | } |
| 110 | } | 98 | } |
| 111 | 99 | ||
| 112 | fun removeDriver(driverData: Pair<String, GpuDriverMetadata>) { | 100 | fun onDriverRemoved(removedPosition: Int, selectedPosition: Int) { |
| 113 | _driverList.value.remove(driverData) | 101 | driversToDelete.add(driverData[removedPosition - 1].first) |
| 102 | driverData.removeAt(removedPosition - 1) | ||
| 103 | onDriverSelected(selectedPosition) | ||
| 114 | } | 104 | } |
| 115 | 105 | ||
| 116 | fun onOpenDriverManager(game: Game?) { | 106 | fun onDriverAdded(driver: Pair<String, GpuDriverMetadata>) { |
| 117 | if (game != null) { | 107 | if (driversToDelete.contains(driver.first)) { |
| 118 | SettingsFile.loadCustomConfig(game) | 108 | driversToDelete.remove(driver.first) |
| 119 | } | ||
| 120 | |||
| 121 | val driverPath = StringSetting.DRIVER_PATH.getString() | ||
| 122 | if (driverPath.isEmpty()) { | ||
| 123 | setSelectedDriverIndex(0) | ||
| 124 | } else { | ||
| 125 | findSelectedDriver(GpuDriverHelper.getMetadataFromZip(File(driverPath))) | ||
| 126 | } | 109 | } |
| 110 | driverData.add(driver) | ||
| 111 | onDriverSelected(driverData.size) | ||
| 127 | } | 112 | } |
| 128 | 113 | ||
| 129 | fun onCloseDriverManager(game: Game?) { | 114 | fun onCloseDriverManager(game: Game?) { |
| 130 | _isDeletingDrivers.value = true | 115 | _isDeletingDrivers.value = true |
| 131 | StringSetting.DRIVER_PATH.setString(driverList.value[selectedDriver].first) | ||
| 132 | updateDriverNameForGame(game) | 116 | updateDriverNameForGame(game) |
| 133 | if (game == null) { | 117 | if (game == null) { |
| 134 | NativeConfig.saveGlobalConfig() | 118 | NativeConfig.saveGlobalConfig() |
| @@ -181,20 +165,6 @@ class DriverViewModel : ViewModel() { | |||
| 181 | } | 165 | } |
| 182 | } | 166 | } |
| 183 | 167 | ||
| 184 | private fun findSelectedDriver(currentDriverMetadata: GpuDriverMetadata) { | ||
| 185 | if (driverList.value.size == 1) { | ||
| 186 | setSelectedDriverIndex(0) | ||
| 187 | return | ||
| 188 | } | ||
| 189 | |||
| 190 | driverList.value.forEachIndexed { i: Int, driver: Pair<String, GpuDriverMetadata> -> | ||
| 191 | if (driver.second == currentDriverMetadata) { | ||
| 192 | setSelectedDriverIndex(i) | ||
| 193 | return | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | fun updateDriverNameForGame(game: Game?) { | 168 | fun updateDriverNameForGame(game: Game?) { |
| 199 | if (!GpuDriverHelper.supportsCustomDriverLoading()) { | 169 | if (!GpuDriverHelper.supportsCustomDriverLoading()) { |
| 200 | return | 170 | return |
| @@ -217,7 +187,6 @@ class DriverViewModel : ViewModel() { | |||
| 217 | 187 | ||
| 218 | private fun setDriverReady() { | 188 | private fun setDriverReady() { |
| 219 | _isDriverReady.value = true | 189 | _isDriverReady.value = true |
| 220 | _selectedDriverTitle.value = GpuDriverHelper.customDriverSettingData.name | 190 | updateName() |
| 221 | ?: YuzuApplication.appContext.getString(R.string.system_gpu_driver) | ||
| 222 | } | 191 | } |
| 223 | } | 192 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SelectableItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SelectableItem.kt new file mode 100644 index 000000000..11c22d323 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SelectableItem.kt | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | interface SelectableItem { | ||
| 7 | var selected: Boolean | ||
| 8 | fun onSelectionStateChanged(selected: Boolean) | ||
| 9 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index 622ae996e..644289e25 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt | |||
| @@ -41,6 +41,7 @@ import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment | |||
| 41 | import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment | 41 | import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment |
| 42 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment | 42 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment |
| 43 | import org.yuzu.yuzu_emu.model.AddonViewModel | 43 | import org.yuzu.yuzu_emu.model.AddonViewModel |
| 44 | import org.yuzu.yuzu_emu.model.DriverViewModel | ||
| 44 | import org.yuzu.yuzu_emu.model.GamesViewModel | 45 | import org.yuzu.yuzu_emu.model.GamesViewModel |
| 45 | import org.yuzu.yuzu_emu.model.HomeViewModel | 46 | import org.yuzu.yuzu_emu.model.HomeViewModel |
| 46 | import org.yuzu.yuzu_emu.model.TaskState | 47 | import org.yuzu.yuzu_emu.model.TaskState |
| @@ -58,6 +59,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 58 | private val gamesViewModel: GamesViewModel by viewModels() | 59 | private val gamesViewModel: GamesViewModel by viewModels() |
| 59 | private val taskViewModel: TaskViewModel by viewModels() | 60 | private val taskViewModel: TaskViewModel by viewModels() |
| 60 | private val addonViewModel: AddonViewModel by viewModels() | 61 | private val addonViewModel: AddonViewModel by viewModels() |
| 62 | private val driverViewModel: DriverViewModel by viewModels() | ||
| 61 | 63 | ||
| 62 | override var themeId: Int = 0 | 64 | override var themeId: Int = 0 |
| 63 | 65 | ||
| @@ -689,6 +691,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 689 | NativeLibrary.initializeSystem(true) | 691 | NativeLibrary.initializeSystem(true) |
| 690 | NativeConfig.initializeGlobalConfig() | 692 | NativeConfig.initializeGlobalConfig() |
| 691 | gamesViewModel.reloadGames(false) | 693 | gamesViewModel.reloadGames(false) |
| 694 | driverViewModel.reloadDriverData() | ||
| 692 | 695 | ||
| 693 | return@newInstance getString(R.string.user_data_import_success) | 696 | return@newInstance getString(R.string.user_data_import_success) |
| 694 | }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) | 697 | }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt index 685272288..a8f9dcc34 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt | |||
| @@ -62,9 +62,6 @@ object GpuDriverHelper { | |||
| 62 | ?.sortedByDescending { it: Pair<String, GpuDriverMetadata> -> it.second.name } | 62 | ?.sortedByDescending { it: Pair<String, GpuDriverMetadata> -> it.second.name } |
| 63 | ?.distinct() | 63 | ?.distinct() |
| 64 | ?.toMutableList() ?: mutableListOf() | 64 | ?.toMutableList() ?: mutableListOf() |
| 65 | |||
| 66 | // TODO: Get system driver information | ||
| 67 | drivers.add(0, Pair("", GpuDriverMetadata())) | ||
| 68 | return drivers | 65 | return drivers |
| 69 | } | 66 | } |
| 70 | 67 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/viewholder/AbstractViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/viewholder/AbstractViewHolder.kt new file mode 100644 index 000000000..7101ad434 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/viewholder/AbstractViewHolder.kt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.viewholder | ||
| 5 | |||
| 6 | import androidx.recyclerview.widget.RecyclerView | ||
| 7 | import androidx.viewbinding.ViewBinding | ||
| 8 | import org.yuzu.yuzu_emu.adapters.AbstractDiffAdapter | ||
| 9 | import org.yuzu.yuzu_emu.adapters.AbstractListAdapter | ||
| 10 | |||
| 11 | /** | ||
| 12 | * [RecyclerView.ViewHolder] meant to work together with a [AbstractDiffAdapter] or a | ||
| 13 | * [AbstractListAdapter] so we can run [bind] on each list item without needing a manual hookup. | ||
| 14 | */ | ||
| 15 | abstract class AbstractViewHolder<Model>(binding: ViewBinding) : | ||
| 16 | RecyclerView.ViewHolder(binding.root) { | ||
| 17 | abstract fun bind(model: Model) | ||
| 18 | } | ||
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 136c8dee6..e436622e0 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp | |||
| @@ -410,8 +410,8 @@ void EmulationSession::OnGamepadConnectEvent([[maybe_unused]] int index) { | |||
| 410 | jauto handheld = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); | 410 | jauto handheld = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); |
| 411 | 411 | ||
| 412 | if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) { | 412 | if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) { |
| 413 | handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); | 413 | handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey); |
| 414 | controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); | 414 | controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey); |
| 415 | handheld->Disconnect(); | 415 | handheld->Disconnect(); |
| 416 | } | 416 | } |
| 417 | } | 417 | } |
diff --git a/src/android/app/src/main/res/layout-w600dp/fragment_about.xml b/src/android/app/src/main/res/layout-w600dp/fragment_about.xml index a26ffbc73..655e49219 100644 --- a/src/android/app/src/main/res/layout-w600dp/fragment_about.xml +++ b/src/android/app/src/main/res/layout-w600dp/fragment_about.xml | |||
| @@ -147,7 +147,7 @@ | |||
| 147 | android:layout_marginHorizontal="20dp" /> | 147 | android:layout_marginHorizontal="20dp" /> |
| 148 | 148 | ||
| 149 | <LinearLayout | 149 | <LinearLayout |
| 150 | android:id="@+id/button_build_hash" | 150 | android:id="@+id/button_version_name" |
| 151 | android:layout_width="match_parent" | 151 | android:layout_width="match_parent" |
| 152 | android:layout_height="wrap_content" | 152 | android:layout_height="wrap_content" |
| 153 | android:background="?attr/selectableItemBackground" | 153 | android:background="?attr/selectableItemBackground" |
| @@ -164,7 +164,7 @@ | |||
| 164 | android:textAlignment="viewStart" /> | 164 | android:textAlignment="viewStart" /> |
| 165 | 165 | ||
| 166 | <com.google.android.material.textview.MaterialTextView | 166 | <com.google.android.material.textview.MaterialTextView |
| 167 | android:id="@+id/text_build_hash" | 167 | android:id="@+id/text_version_name" |
| 168 | style="@style/TextAppearance.Material3.BodyMedium" | 168 | style="@style/TextAppearance.Material3.BodyMedium" |
| 169 | android:layout_width="match_parent" | 169 | android:layout_width="match_parent" |
| 170 | android:layout_height="wrap_content" | 170 | android:layout_height="wrap_content" |
diff --git a/src/android/app/src/main/res/layout/fragment_about.xml b/src/android/app/src/main/res/layout/fragment_about.xml index a24f5230e..38090fa50 100644 --- a/src/android/app/src/main/res/layout/fragment_about.xml +++ b/src/android/app/src/main/res/layout/fragment_about.xml | |||
| @@ -148,7 +148,7 @@ | |||
| 148 | android:layout_marginHorizontal="20dp" /> | 148 | android:layout_marginHorizontal="20dp" /> |
| 149 | 149 | ||
| 150 | <LinearLayout | 150 | <LinearLayout |
| 151 | android:id="@+id/button_build_hash" | 151 | android:id="@+id/button_version_name" |
| 152 | android:layout_width="match_parent" | 152 | android:layout_width="match_parent" |
| 153 | android:layout_height="wrap_content" | 153 | android:layout_height="wrap_content" |
| 154 | android:paddingVertical="16dp" | 154 | android:paddingVertical="16dp" |
| @@ -165,7 +165,7 @@ | |||
| 165 | android:text="@string/build" /> | 165 | android:text="@string/build" /> |
| 166 | 166 | ||
| 167 | <com.google.android.material.textview.MaterialTextView | 167 | <com.google.android.material.textview.MaterialTextView |
| 168 | android:id="@+id/text_build_hash" | 168 | android:id="@+id/text_version_name" |
| 169 | style="@style/TextAppearance.Material3.BodyMedium" | 169 | style="@style/TextAppearance.Material3.BodyMedium" |
| 170 | android:layout_width="match_parent" | 170 | android:layout_width="match_parent" |
| 171 | android:layout_height="wrap_content" | 171 | android:layout_height="wrap_content" |
diff --git a/src/android/app/src/main/res/menu/menu_driver_manager.xml b/src/android/app/src/main/res/menu/menu_driver_manager.xml new file mode 100644 index 000000000..dee5d57b6 --- /dev/null +++ b/src/android/app/src/main/res/menu/menu_driver_manager.xml | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <menu xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | xmlns:app="http://schemas.android.com/apk/res-auto"> | ||
| 4 | |||
| 5 | <item | ||
| 6 | android:id="@+id/menu_driver_clear" | ||
| 7 | android:icon="@drawable/ic_clear" | ||
| 8 | android:title="@string/clear" | ||
| 9 | app:showAsAction="always" /> | ||
| 10 | |||
| 11 | </menu> | ||
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 0deea9c58..a249dc5f7 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h | |||
| @@ -64,7 +64,7 @@ public: | |||
| 64 | return [this] { ShutdownThreadFunction(); }; | 64 | return [this] { ShutdownThreadFunction(); }; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | void PreemptSingleCore(bool from_running_enviroment = true); | 67 | void PreemptSingleCore(bool from_running_environment = true); |
| 68 | 68 | ||
| 69 | std::size_t CurrentCore() const { | 69 | std::size_t CurrentCore() const { |
| 70 | return current_core.load(); | 70 | return current_core.load(); |
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index 66e46c4ba..4051ed4af 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp | |||
| @@ -559,28 +559,28 @@ void GDBStub::HandleVCont(std::string_view command, std::vector<DebuggerAction>& | |||
| 559 | } | 559 | } |
| 560 | 560 | ||
| 561 | constexpr std::array<std::pair<const char*, Kernel::Svc::MemoryState>, 22> MemoryStateNames{{ | 561 | constexpr std::array<std::pair<const char*, Kernel::Svc::MemoryState>, 22> MemoryStateNames{{ |
| 562 | {"----- Free -----", Kernel::Svc::MemoryState::Free}, | 562 | {"----- Free ------", Kernel::Svc::MemoryState::Free}, |
| 563 | {"Io ", Kernel::Svc::MemoryState::Io}, | 563 | {"Io ", Kernel::Svc::MemoryState::Io}, |
| 564 | {"Static ", Kernel::Svc::MemoryState::Static}, | 564 | {"Static ", Kernel::Svc::MemoryState::Static}, |
| 565 | {"Code ", Kernel::Svc::MemoryState::Code}, | 565 | {"Code ", Kernel::Svc::MemoryState::Code}, |
| 566 | {"CodeData ", Kernel::Svc::MemoryState::CodeData}, | 566 | {"CodeData ", Kernel::Svc::MemoryState::CodeData}, |
| 567 | {"Normal ", Kernel::Svc::MemoryState::Normal}, | 567 | {"Normal ", Kernel::Svc::MemoryState::Normal}, |
| 568 | {"Shared ", Kernel::Svc::MemoryState::Shared}, | 568 | {"Shared ", Kernel::Svc::MemoryState::Shared}, |
| 569 | {"AliasCode ", Kernel::Svc::MemoryState::AliasCode}, | 569 | {"AliasCode ", Kernel::Svc::MemoryState::AliasCode}, |
| 570 | {"AliasCodeData ", Kernel::Svc::MemoryState::AliasCodeData}, | 570 | {"AliasCodeData ", Kernel::Svc::MemoryState::AliasCodeData}, |
| 571 | {"Ipc ", Kernel::Svc::MemoryState::Ipc}, | 571 | {"Ipc ", Kernel::Svc::MemoryState::Ipc}, |
| 572 | {"Stack ", Kernel::Svc::MemoryState::Stack}, | 572 | {"Stack ", Kernel::Svc::MemoryState::Stack}, |
| 573 | {"ThreadLocal ", Kernel::Svc::MemoryState::ThreadLocal}, | 573 | {"ThreadLocal ", Kernel::Svc::MemoryState::ThreadLocal}, |
| 574 | {"Transfered ", Kernel::Svc::MemoryState::Transfered}, | 574 | {"Transferred ", Kernel::Svc::MemoryState::Transferred}, |
| 575 | {"SharedTransfered", Kernel::Svc::MemoryState::SharedTransfered}, | 575 | {"SharedTransferred", Kernel::Svc::MemoryState::SharedTransferred}, |
| 576 | {"SharedCode ", Kernel::Svc::MemoryState::SharedCode}, | 576 | {"SharedCode ", Kernel::Svc::MemoryState::SharedCode}, |
| 577 | {"Inaccessible ", Kernel::Svc::MemoryState::Inaccessible}, | 577 | {"Inaccessible ", Kernel::Svc::MemoryState::Inaccessible}, |
| 578 | {"NonSecureIpc ", Kernel::Svc::MemoryState::NonSecureIpc}, | 578 | {"NonSecureIpc ", Kernel::Svc::MemoryState::NonSecureIpc}, |
| 579 | {"NonDeviceIpc ", Kernel::Svc::MemoryState::NonDeviceIpc}, | 579 | {"NonDeviceIpc ", Kernel::Svc::MemoryState::NonDeviceIpc}, |
| 580 | {"Kernel ", Kernel::Svc::MemoryState::Kernel}, | 580 | {"Kernel ", Kernel::Svc::MemoryState::Kernel}, |
| 581 | {"GeneratedCode ", Kernel::Svc::MemoryState::GeneratedCode}, | 581 | {"GeneratedCode ", Kernel::Svc::MemoryState::GeneratedCode}, |
| 582 | {"CodeOut ", Kernel::Svc::MemoryState::CodeOut}, | 582 | {"CodeOut ", Kernel::Svc::MemoryState::CodeOut}, |
| 583 | {"Coverage ", Kernel::Svc::MemoryState::Coverage}, | 583 | {"Coverage ", Kernel::Svc::MemoryState::Coverage}, |
| 584 | }}; | 584 | }}; |
| 585 | 585 | ||
| 586 | static constexpr const char* GetMemoryStateName(Kernel::Svc::MemoryState state) { | 586 | static constexpr const char* GetMemoryStateName(Kernel::Svc::MemoryState state) { |
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 34fe23b6a..e04d884ba 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp | |||
| @@ -47,7 +47,7 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac | |||
| 47 | // Connect controllers based on the following priority list from highest to lowest priority: | 47 | // Connect controllers based on the following priority list from highest to lowest priority: |
| 48 | // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld | 48 | // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld |
| 49 | if (parameters.allow_pro_controller) { | 49 | if (parameters.allow_pro_controller) { |
| 50 | controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); | 50 | controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey); |
| 51 | controller->Connect(true); | 51 | controller->Connect(true); |
| 52 | } else if (parameters.allow_dual_joycons) { | 52 | } else if (parameters.allow_dual_joycons) { |
| 53 | controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual); | 53 | controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual); |
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h index ef3f61321..d2b7e9a66 100644 --- a/src/core/hle/kernel/k_memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h | |||
| @@ -81,12 +81,12 @@ enum class KMemoryState : u32 { | |||
| 81 | 81 | ||
| 82 | ThreadLocal = static_cast<u32>(Svc::MemoryState::ThreadLocal) | FlagLinearMapped, | 82 | ThreadLocal = static_cast<u32>(Svc::MemoryState::ThreadLocal) | FlagLinearMapped, |
| 83 | 83 | ||
| 84 | Transfered = static_cast<u32>(Svc::MemoryState::Transfered) | FlagsMisc | | 84 | Transferred = static_cast<u32>(Svc::MemoryState::Transferred) | FlagsMisc | |
| 85 | FlagCanAlignedDeviceMap | FlagCanChangeAttribute | FlagCanUseIpc | | 85 | FlagCanAlignedDeviceMap | FlagCanChangeAttribute | FlagCanUseIpc | |
| 86 | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc, | 86 | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc, |
| 87 | 87 | ||
| 88 | SharedTransfered = static_cast<u32>(Svc::MemoryState::SharedTransfered) | FlagsMisc | | 88 | SharedTransferred = static_cast<u32>(Svc::MemoryState::SharedTransferred) | FlagsMisc | |
| 89 | FlagCanAlignedDeviceMap | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc, | 89 | FlagCanAlignedDeviceMap | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc, |
| 90 | 90 | ||
| 91 | SharedCode = static_cast<u32>(Svc::MemoryState::SharedCode) | FlagMapped | | 91 | SharedCode = static_cast<u32>(Svc::MemoryState::SharedCode) | FlagMapped | |
| 92 | FlagReferenceCounted | FlagLinearMapped | FlagCanUseNonSecureIpc | | 92 | FlagReferenceCounted | FlagLinearMapped | FlagCanUseNonSecureIpc | |
| @@ -130,8 +130,8 @@ static_assert(static_cast<u32>(KMemoryState::AliasCodeData) == 0x0FFFBD09); | |||
| 130 | static_assert(static_cast<u32>(KMemoryState::Ipc) == 0x045C3C0A); | 130 | static_assert(static_cast<u32>(KMemoryState::Ipc) == 0x045C3C0A); |
| 131 | static_assert(static_cast<u32>(KMemoryState::Stack) == 0x045C3C0B); | 131 | static_assert(static_cast<u32>(KMemoryState::Stack) == 0x045C3C0B); |
| 132 | static_assert(static_cast<u32>(KMemoryState::ThreadLocal) == 0x0400000C); | 132 | static_assert(static_cast<u32>(KMemoryState::ThreadLocal) == 0x0400000C); |
| 133 | static_assert(static_cast<u32>(KMemoryState::Transfered) == 0x055C3C0D); | 133 | static_assert(static_cast<u32>(KMemoryState::Transferred) == 0x055C3C0D); |
| 134 | static_assert(static_cast<u32>(KMemoryState::SharedTransfered) == 0x045C380E); | 134 | static_assert(static_cast<u32>(KMemoryState::SharedTransferred) == 0x045C380E); |
| 135 | static_assert(static_cast<u32>(KMemoryState::SharedCode) == 0x0440380F); | 135 | static_assert(static_cast<u32>(KMemoryState::SharedCode) == 0x0440380F); |
| 136 | static_assert(static_cast<u32>(KMemoryState::Inaccessible) == 0x00000010); | 136 | static_assert(static_cast<u32>(KMemoryState::Inaccessible) == 0x00000010); |
| 137 | static_assert(static_cast<u32>(KMemoryState::NonSecureIpc) == 0x045C3811); | 137 | static_assert(static_cast<u32>(KMemoryState::NonSecureIpc) == 0x045C3811); |
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 8c1549559..73fbda331 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp | |||
| @@ -486,8 +486,8 @@ KProcessAddress KPageTableBase::GetRegionAddress(Svc::MemoryState state) const { | |||
| 486 | case Svc::MemoryState::Shared: | 486 | case Svc::MemoryState::Shared: |
| 487 | case Svc::MemoryState::AliasCode: | 487 | case Svc::MemoryState::AliasCode: |
| 488 | case Svc::MemoryState::AliasCodeData: | 488 | case Svc::MemoryState::AliasCodeData: |
| 489 | case Svc::MemoryState::Transfered: | 489 | case Svc::MemoryState::Transferred: |
| 490 | case Svc::MemoryState::SharedTransfered: | 490 | case Svc::MemoryState::SharedTransferred: |
| 491 | case Svc::MemoryState::SharedCode: | 491 | case Svc::MemoryState::SharedCode: |
| 492 | case Svc::MemoryState::GeneratedCode: | 492 | case Svc::MemoryState::GeneratedCode: |
| 493 | case Svc::MemoryState::CodeOut: | 493 | case Svc::MemoryState::CodeOut: |
| @@ -522,8 +522,8 @@ size_t KPageTableBase::GetRegionSize(Svc::MemoryState state) const { | |||
| 522 | case Svc::MemoryState::Shared: | 522 | case Svc::MemoryState::Shared: |
| 523 | case Svc::MemoryState::AliasCode: | 523 | case Svc::MemoryState::AliasCode: |
| 524 | case Svc::MemoryState::AliasCodeData: | 524 | case Svc::MemoryState::AliasCodeData: |
| 525 | case Svc::MemoryState::Transfered: | 525 | case Svc::MemoryState::Transferred: |
| 526 | case Svc::MemoryState::SharedTransfered: | 526 | case Svc::MemoryState::SharedTransferred: |
| 527 | case Svc::MemoryState::SharedCode: | 527 | case Svc::MemoryState::SharedCode: |
| 528 | case Svc::MemoryState::GeneratedCode: | 528 | case Svc::MemoryState::GeneratedCode: |
| 529 | case Svc::MemoryState::CodeOut: | 529 | case Svc::MemoryState::CodeOut: |
| @@ -564,8 +564,8 @@ bool KPageTableBase::CanContain(KProcessAddress addr, size_t size, Svc::MemorySt | |||
| 564 | case Svc::MemoryState::AliasCodeData: | 564 | case Svc::MemoryState::AliasCodeData: |
| 565 | case Svc::MemoryState::Stack: | 565 | case Svc::MemoryState::Stack: |
| 566 | case Svc::MemoryState::ThreadLocal: | 566 | case Svc::MemoryState::ThreadLocal: |
| 567 | case Svc::MemoryState::Transfered: | 567 | case Svc::MemoryState::Transferred: |
| 568 | case Svc::MemoryState::SharedTransfered: | 568 | case Svc::MemoryState::SharedTransferred: |
| 569 | case Svc::MemoryState::SharedCode: | 569 | case Svc::MemoryState::SharedCode: |
| 570 | case Svc::MemoryState::GeneratedCode: | 570 | case Svc::MemoryState::GeneratedCode: |
| 571 | case Svc::MemoryState::CodeOut: | 571 | case Svc::MemoryState::CodeOut: |
diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp index 0e2e11743..cbb1b02bb 100644 --- a/src/core/hle/kernel/k_transfer_memory.cpp +++ b/src/core/hle/kernel/k_transfer_memory.cpp | |||
| @@ -76,8 +76,8 @@ Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPer | |||
| 76 | 76 | ||
| 77 | // Map the memory. | 77 | // Map the memory. |
| 78 | const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) | 78 | const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) |
| 79 | ? KMemoryState::Transfered | 79 | ? KMemoryState::Transferred |
| 80 | : KMemoryState::SharedTransfered; | 80 | : KMemoryState::SharedTransferred; |
| 81 | R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( | 81 | R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( |
| 82 | address, *m_page_group, state, KMemoryPermission::UserReadWrite)); | 82 | address, *m_page_group, state, KMemoryPermission::UserReadWrite)); |
| 83 | 83 | ||
| @@ -96,8 +96,8 @@ Result KTransferMemory::Unmap(KProcessAddress address, size_t size) { | |||
| 96 | 96 | ||
| 97 | // Unmap the memory. | 97 | // Unmap the memory. |
| 98 | const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) | 98 | const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) |
| 99 | ? KMemoryState::Transfered | 99 | ? KMemoryState::Transferred |
| 100 | : KMemoryState::SharedTransfered; | 100 | : KMemoryState::SharedTransferred; |
| 101 | R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state)); | 101 | R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state)); |
| 102 | 102 | ||
| 103 | // Mark ourselves as unmapped. | 103 | // Mark ourselves as unmapped. |
diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp index 1f97121b3..671bca23f 100644 --- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp +++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp | |||
| @@ -90,7 +90,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add | |||
| 90 | // Verify that the mapping is in range. | 90 | // Verify that the mapping is in range. |
| 91 | R_UNLESS(GetCurrentProcess(system.Kernel()) | 91 | R_UNLESS(GetCurrentProcess(system.Kernel()) |
| 92 | .GetPageTable() | 92 | .GetPageTable() |
| 93 | .CanContain(address, size, KMemoryState::Transfered), | 93 | .CanContain(address, size, KMemoryState::Transferred), |
| 94 | ResultInvalidMemoryRegion); | 94 | ResultInvalidMemoryRegion); |
| 95 | 95 | ||
| 96 | // Map the transfer memory. | 96 | // Map the transfer memory. |
| @@ -117,7 +117,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a | |||
| 117 | // Verify that the mapping is in range. | 117 | // Verify that the mapping is in range. |
| 118 | R_UNLESS(GetCurrentProcess(system.Kernel()) | 118 | R_UNLESS(GetCurrentProcess(system.Kernel()) |
| 119 | .GetPageTable() | 119 | .GetPageTable() |
| 120 | .CanContain(address, size, KMemoryState::Transfered), | 120 | .CanContain(address, size, KMemoryState::Transferred), |
| 121 | ResultInvalidMemoryRegion); | 121 | ResultInvalidMemoryRegion); |
| 122 | 122 | ||
| 123 | // Unmap the transfer memory. | 123 | // Unmap the transfer memory. |
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index 50de02e36..ab432ea78 100644 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h | |||
| @@ -27,8 +27,8 @@ enum class MemoryState : u32 { | |||
| 27 | Ipc = 0x0A, | 27 | Ipc = 0x0A, |
| 28 | Stack = 0x0B, | 28 | Stack = 0x0B, |
| 29 | ThreadLocal = 0x0C, | 29 | ThreadLocal = 0x0C, |
| 30 | Transfered = 0x0D, | 30 | Transferred = 0x0D, |
| 31 | SharedTransfered = 0x0E, | 31 | SharedTransferred = 0x0E, |
| 32 | SharedCode = 0x0F, | 32 | SharedCode = 0x0F, |
| 33 | Inaccessible = 0x10, | 33 | Inaccessible = 0x10, |
| 34 | NonSecureIpc = 0x11, | 34 | NonSecureIpc = 0x11, |
diff --git a/src/core/hle/service/am/applets/applet_profile_select.h b/src/core/hle/service/am/applets/applet_profile_select.h index 369f9250f..673eed516 100644 --- a/src/core/hle/service/am/applets/applet_profile_select.h +++ b/src/core/hle/service/am/applets/applet_profile_select.h | |||
| @@ -76,7 +76,7 @@ struct UiSettingsDisplayOptions { | |||
| 76 | bool is_system_or_launcher; | 76 | bool is_system_or_launcher; |
| 77 | bool is_registration_permitted; | 77 | bool is_registration_permitted; |
| 78 | bool show_skip_button; | 78 | bool show_skip_button; |
| 79 | bool aditional_select; | 79 | bool additional_select; |
| 80 | bool show_user_selector; | 80 | bool show_user_selector; |
| 81 | bool is_unqualified_user_selectable; | 81 | bool is_unqualified_user_selectable; |
| 82 | }; | 82 | }; |
diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp index 96b225d5f..261fc204c 100644 --- a/src/core/hle/service/caps/caps_manager.cpp +++ b/src/core/hle/service/caps/caps_manager.cpp | |||
| @@ -85,7 +85,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, Albu | |||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, | 87 | Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, |
| 88 | ContentType contex_type, s64 start_posix_time, | 88 | ContentType content_type, s64 start_posix_time, |
| 89 | s64 end_posix_time, u64 aruid) const { | 89 | s64 end_posix_time, u64 aruid) const { |
| 90 | if (!is_mounted) { | 90 | if (!is_mounted) { |
| 91 | return ResultIsNotMounted; | 91 | return ResultIsNotMounted; |
| @@ -94,7 +94,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& ou | |||
| 94 | std::vector<ApplicationAlbumEntry> album_entries; | 94 | std::vector<ApplicationAlbumEntry> album_entries; |
| 95 | const auto start_date = ConvertToAlbumDateTime(start_posix_time); | 95 | const auto start_date = ConvertToAlbumDateTime(start_posix_time); |
| 96 | const auto end_date = ConvertToAlbumDateTime(end_posix_time); | 96 | const auto end_date = ConvertToAlbumDateTime(end_posix_time); |
| 97 | const auto result = GetAlbumFileList(album_entries, contex_type, start_date, end_date, aruid); | 97 | const auto result = GetAlbumFileList(album_entries, content_type, start_date, end_date, aruid); |
| 98 | 98 | ||
| 99 | if (result.IsError()) { | 99 | if (result.IsError()) { |
| 100 | return result; | 100 | return result; |
| @@ -113,14 +113,14 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& ou | |||
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, | 115 | Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, |
| 116 | ContentType contex_type, AlbumFileDateTime start_date, | 116 | ContentType content_type, AlbumFileDateTime start_date, |
| 117 | AlbumFileDateTime end_date, u64 aruid) const { | 117 | AlbumFileDateTime end_date, u64 aruid) const { |
| 118 | if (!is_mounted) { | 118 | if (!is_mounted) { |
| 119 | return ResultIsNotMounted; | 119 | return ResultIsNotMounted; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | for (auto& [file_id, path] : album_files) { | 122 | for (auto& [file_id, path] : album_files) { |
| 123 | if (file_id.type != contex_type) { | 123 | if (file_id.type != content_type) { |
| 124 | continue; | 124 | continue; |
| 125 | } | 125 | } |
| 126 | if (file_id.date > start_date) { | 126 | if (file_id.date > start_date) { |
| @@ -139,7 +139,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_en | |||
| 139 | .hash{}, | 139 | .hash{}, |
| 140 | .datetime = file_id.date, | 140 | .datetime = file_id.date, |
| 141 | .storage = file_id.storage, | 141 | .storage = file_id.storage, |
| 142 | .content = contex_type, | 142 | .content = content_type, |
| 143 | .unknown = 1, | 143 | .unknown = 1, |
| 144 | }; | 144 | }; |
| 145 | out_entries.push_back(entry); | 145 | out_entries.push_back(entry); |
diff --git a/src/core/hle/service/caps/caps_manager.h b/src/core/hle/service/caps/caps_manager.h index e20c70c7b..6fd34f589 100644 --- a/src/core/hle/service/caps/caps_manager.h +++ b/src/core/hle/service/caps/caps_manager.h | |||
| @@ -45,10 +45,10 @@ public: | |||
| 45 | Result GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage, | 45 | Result GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage, |
| 46 | u8 flags) const; | 46 | u8 flags) const; |
| 47 | Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, | 47 | Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, |
| 48 | ContentType contex_type, s64 start_posix_time, s64 end_posix_time, | 48 | ContentType content_type, s64 start_posix_time, s64 end_posix_time, |
| 49 | u64 aruid) const; | 49 | u64 aruid) const; |
| 50 | Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, | 50 | Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, |
| 51 | ContentType contex_type, AlbumFileDateTime start_date, | 51 | ContentType content_type, AlbumFileDateTime start_date, |
| 52 | AlbumFileDateTime end_date, u64 aruid) const; | 52 | AlbumFileDateTime end_date, u64 aruid) const; |
| 53 | Result GetAutoSavingStorage(bool& out_is_autosaving) const; | 53 | Result GetAutoSavingStorage(bool& out_is_autosaving) const; |
| 54 | Result LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output, | 54 | Result LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output, |
diff --git a/src/core/hle/service/caps/caps_result.h b/src/core/hle/service/caps/caps_result.h index c65e5fb9a..179ae4840 100644 --- a/src/core/hle/service/caps/caps_result.h +++ b/src/core/hle/service/caps/caps_result.h | |||
| @@ -12,7 +12,7 @@ constexpr Result ResultUnknown5(ErrorModule::Capture, 5); | |||
| 12 | constexpr Result ResultUnknown6(ErrorModule::Capture, 6); | 12 | constexpr Result ResultUnknown6(ErrorModule::Capture, 6); |
| 13 | constexpr Result ResultUnknown7(ErrorModule::Capture, 7); | 13 | constexpr Result ResultUnknown7(ErrorModule::Capture, 7); |
| 14 | constexpr Result ResultOutOfRange(ErrorModule::Capture, 8); | 14 | constexpr Result ResultOutOfRange(ErrorModule::Capture, 8); |
| 15 | constexpr Result ResulInvalidTimestamp(ErrorModule::Capture, 12); | 15 | constexpr Result ResultInvalidTimestamp(ErrorModule::Capture, 12); |
| 16 | constexpr Result ResultInvalidStorage(ErrorModule::Capture, 13); | 16 | constexpr Result ResultInvalidStorage(ErrorModule::Capture, 13); |
| 17 | constexpr Result ResultInvalidFileContents(ErrorModule::Capture, 14); | 17 | constexpr Result ResultInvalidFileContents(ErrorModule::Capture, 14); |
| 18 | constexpr Result ResultIsNotMounted(ErrorModule::Capture, 21); | 18 | constexpr Result ResultIsNotMounted(ErrorModule::Capture, 21); |
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index 0507b14e7..aeb849efa 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp | |||
| @@ -131,7 +131,7 @@ private: | |||
| 131 | u8 is_favorite; | 131 | u8 is_favorite; |
| 132 | u8 same_app; | 132 | u8 same_app; |
| 133 | u8 same_app_played; | 133 | u8 same_app_played; |
| 134 | u8 arbitary_app_played; | 134 | u8 arbitrary_app_played; |
| 135 | u64 group_id; | 135 | u64 group_id; |
| 136 | }; | 136 | }; |
| 137 | static_assert(sizeof(SizedFriendFilter) == 0x10, "SizedFriendFilter is an invalid size"); | 137 | static_assert(sizeof(SizedFriendFilter) == 0x10, "SizedFriendFilter is an invalid size"); |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index fc8a3ab66..fc03a0a5f 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -18,23 +18,23 @@ namespace Service::HID { | |||
| 18 | 18 | ||
| 19 | void LoopProcess(Core::System& system) { | 19 | void LoopProcess(Core::System& system) { |
| 20 | auto server_manager = std::make_unique<ServerManager>(system); | 20 | auto server_manager = std::make_unique<ServerManager>(system); |
| 21 | std::shared_ptr<ResourceManager> resouce_manager = std::make_shared<ResourceManager>(system); | 21 | std::shared_ptr<ResourceManager> resource_manager = std::make_shared<ResourceManager>(system); |
| 22 | std::shared_ptr<HidFirmwareSettings> firmware_settings = | 22 | std::shared_ptr<HidFirmwareSettings> firmware_settings = |
| 23 | std::make_shared<HidFirmwareSettings>(); | 23 | std::make_shared<HidFirmwareSettings>(); |
| 24 | 24 | ||
| 25 | // TODO: Remove this hack until this service is emulated properly. | 25 | // TODO: Remove this hack until this service is emulated properly. |
| 26 | const auto process_list = system.Kernel().GetProcessList(); | 26 | const auto process_list = system.Kernel().GetProcessList(); |
| 27 | if (!process_list.empty()) { | 27 | if (!process_list.empty()) { |
| 28 | resouce_manager->Initialize(); | 28 | resource_manager->Initialize(); |
| 29 | resouce_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true); | 29 | resource_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | server_manager->RegisterNamedService( | 32 | server_manager->RegisterNamedService( |
| 33 | "hid", std::make_shared<IHidServer>(system, resouce_manager, firmware_settings)); | 33 | "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); |
| 34 | server_manager->RegisterNamedService( | 34 | server_manager->RegisterNamedService( |
| 35 | "hid:dbg", std::make_shared<IHidDebugServer>(system, resouce_manager)); | 35 | "hid:dbg", std::make_shared<IHidDebugServer>(system, resource_manager)); |
| 36 | server_manager->RegisterNamedService( | 36 | server_manager->RegisterNamedService( |
| 37 | "hid:sys", std::make_shared<IHidSystemServer>(system, resouce_manager)); | 37 | "hid:sys", std::make_shared<IHidSystemServer>(system, resource_manager)); |
| 38 | 38 | ||
| 39 | server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system)); | 39 | server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system)); |
| 40 | 40 | ||
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 74898888a..1951da33b 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -1498,7 +1498,7 @@ void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { | |||
| 1498 | bool check_device_index = false; | 1498 | bool check_device_index = false; |
| 1499 | 1499 | ||
| 1500 | switch (vibration_device_handle.npad_type) { | 1500 | switch (vibration_device_handle.npad_type) { |
| 1501 | case Core::HID::NpadStyleIndex::ProController: | 1501 | case Core::HID::NpadStyleIndex::Fullkey: |
| 1502 | case Core::HID::NpadStyleIndex::Handheld: | 1502 | case Core::HID::NpadStyleIndex::Handheld: |
| 1503 | case Core::HID::NpadStyleIndex::JoyconDual: | 1503 | case Core::HID::NpadStyleIndex::JoyconDual: |
| 1504 | case Core::HID::NpadStyleIndex::JoyconLeft: | 1504 | case Core::HID::NpadStyleIndex::JoyconLeft: |
diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index 46f503d38..c903ee8b8 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp | |||
| @@ -67,7 +67,7 @@ HidBus::~HidBus() { | |||
| 67 | void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) { | 67 | void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) { |
| 68 | if (is_hidbus_enabled) { | 68 | if (is_hidbus_enabled) { |
| 69 | for (std::size_t i = 0; i < devices.size(); ++i) { | 69 | for (std::size_t i = 0; i < devices.size(); ++i) { |
| 70 | if (!devices[i].is_device_initializated) { | 70 | if (!devices[i].is_device_initialized) { |
| 71 | continue; | 71 | continue; |
| 72 | } | 72 | } |
| 73 | auto& device = devices[i].device; | 73 | auto& device = devices[i].device; |
| @@ -213,7 +213,7 @@ void HidBus::Initialize(HLERequestContext& ctx) { | |||
| 213 | 213 | ||
| 214 | if (bus_handle_.internal_index == 0 && Settings::values.enable_ring_controller) { | 214 | if (bus_handle_.internal_index == 0 && Settings::values.enable_ring_controller) { |
| 215 | MakeDevice<RingController>(bus_handle_); | 215 | MakeDevice<RingController>(bus_handle_); |
| 216 | devices[device_index.value()].is_device_initializated = true; | 216 | devices[device_index.value()].is_device_initialized = true; |
| 217 | devices[device_index.value()].device->ActivateDevice(); | 217 | devices[device_index.value()].device->ActivateDevice(); |
| 218 | cur_entry.is_in_focus = true; | 218 | cur_entry.is_in_focus = true; |
| 219 | cur_entry.is_connected = true; | 219 | cur_entry.is_connected = true; |
| @@ -222,7 +222,7 @@ void HidBus::Initialize(HLERequestContext& ctx) { | |||
| 222 | cur_entry.is_polling_mode = false; | 222 | cur_entry.is_polling_mode = false; |
| 223 | } else { | 223 | } else { |
| 224 | MakeDevice<HidbusStubbed>(bus_handle_); | 224 | MakeDevice<HidbusStubbed>(bus_handle_); |
| 225 | devices[device_index.value()].is_device_initializated = true; | 225 | devices[device_index.value()].is_device_initialized = true; |
| 226 | cur_entry.is_in_focus = true; | 226 | cur_entry.is_in_focus = true; |
| 227 | cur_entry.is_connected = false; | 227 | cur_entry.is_connected = false; |
| 228 | cur_entry.is_connected_result = ResultSuccess; | 228 | cur_entry.is_connected_result = ResultSuccess; |
| @@ -261,7 +261,7 @@ void HidBus::Finalize(HLERequestContext& ctx) { | |||
| 261 | const auto entry_index = devices[device_index.value()].handle.internal_index; | 261 | const auto entry_index = devices[device_index.value()].handle.internal_index; |
| 262 | auto& cur_entry = hidbus_status.entries[entry_index]; | 262 | auto& cur_entry = hidbus_status.entries[entry_index]; |
| 263 | auto& device = devices[device_index.value()].device; | 263 | auto& device = devices[device_index.value()].device; |
| 264 | devices[device_index.value()].is_device_initializated = false; | 264 | devices[device_index.value()].is_device_initialized = false; |
| 265 | device->DeactivateDevice(); | 265 | device->DeactivateDevice(); |
| 266 | 266 | ||
| 267 | cur_entry.is_in_focus = true; | 267 | cur_entry.is_in_focus = true; |
diff --git a/src/core/hle/service/hid/hidbus.h b/src/core/hle/service/hid/hidbus.h index 05f62f634..03d9f6863 100644 --- a/src/core/hle/service/hid/hidbus.h +++ b/src/core/hle/service/hid/hidbus.h | |||
| @@ -89,7 +89,7 @@ private: | |||
| 89 | static_assert(sizeof(HidbusStatusManager) <= 0x1000, "HidbusStatusManager is an invalid size"); | 89 | static_assert(sizeof(HidbusStatusManager) <= 0x1000, "HidbusStatusManager is an invalid size"); |
| 90 | 90 | ||
| 91 | struct HidbusDevice { | 91 | struct HidbusDevice { |
| 92 | bool is_device_initializated{}; | 92 | bool is_device_initialized{}; |
| 93 | BusHandle handle{}; | 93 | BusHandle handle{}; |
| 94 | std::unique_ptr<HidbusBase> device{nullptr}; | 94 | std::unique_ptr<HidbusBase> device{nullptr}; |
| 95 | }; | 95 | }; |
diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp index 39df77e43..3f38ceb03 100644 --- a/src/core/hle/service/hle_ipc.cpp +++ b/src/core/hle/service/hle_ipc.cpp | |||
| @@ -181,22 +181,22 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { | |||
| 181 | } | 181 | } |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | buffer_x_desciptors.reserve(command_header->num_buf_x_descriptors); | 184 | buffer_x_descriptors.reserve(command_header->num_buf_x_descriptors); |
| 185 | buffer_a_desciptors.reserve(command_header->num_buf_a_descriptors); | 185 | buffer_a_descriptors.reserve(command_header->num_buf_a_descriptors); |
| 186 | buffer_b_desciptors.reserve(command_header->num_buf_b_descriptors); | 186 | buffer_b_descriptors.reserve(command_header->num_buf_b_descriptors); |
| 187 | buffer_w_desciptors.reserve(command_header->num_buf_w_descriptors); | 187 | buffer_w_descriptors.reserve(command_header->num_buf_w_descriptors); |
| 188 | 188 | ||
| 189 | for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) { | 189 | for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) { |
| 190 | buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); | 190 | buffer_x_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); |
| 191 | } | 191 | } |
| 192 | for (u32 i = 0; i < command_header->num_buf_a_descriptors; ++i) { | 192 | for (u32 i = 0; i < command_header->num_buf_a_descriptors; ++i) { |
| 193 | buffer_a_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 193 | buffer_a_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 194 | } | 194 | } |
| 195 | for (u32 i = 0; i < command_header->num_buf_b_descriptors; ++i) { | 195 | for (u32 i = 0; i < command_header->num_buf_b_descriptors; ++i) { |
| 196 | buffer_b_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 196 | buffer_b_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 197 | } | 197 | } |
| 198 | for (u32 i = 0; i < command_header->num_buf_w_descriptors; ++i) { | 198 | for (u32 i = 0; i < command_header->num_buf_w_descriptors; ++i) { |
| 199 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 199 | buffer_w_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; | 202 | const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; |
| @@ -246,7 +246,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { | |||
| 246 | IPC::CommandHeader::BufferDescriptorCFlag::InlineDescriptor) { | 246 | IPC::CommandHeader::BufferDescriptorCFlag::InlineDescriptor) { |
| 247 | if (command_header->buf_c_descriptor_flags == | 247 | if (command_header->buf_c_descriptor_flags == |
| 248 | IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { | 248 | IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { |
| 249 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | 249 | buffer_c_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); |
| 250 | } else { | 250 | } else { |
| 251 | u32 num_buf_c_descriptors = | 251 | u32 num_buf_c_descriptors = |
| 252 | static_cast<u32>(command_header->buf_c_descriptor_flags.Value()) - 2; | 252 | static_cast<u32>(command_header->buf_c_descriptor_flags.Value()) - 2; |
| @@ -256,7 +256,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { | |||
| 256 | ASSERT(num_buf_c_descriptors < 14); | 256 | ASSERT(num_buf_c_descriptors < 14); |
| 257 | 257 | ||
| 258 | for (u32 i = 0; i < num_buf_c_descriptors; ++i) { | 258 | for (u32 i = 0; i < num_buf_c_descriptors; ++i) { |
| 259 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | 259 | buffer_c_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); |
| 260 | } | 260 | } |
| 261 | } | 261 | } |
| 262 | } | 262 | } |
diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h index 40d86943e..440737db5 100644 --- a/src/core/hle/service/hle_ipc.h +++ b/src/core/hle/service/hle_ipc.h | |||
| @@ -232,19 +232,19 @@ public: | |||
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | [[nodiscard]] const std::vector<IPC::BufferDescriptorX>& BufferDescriptorX() const { | 234 | [[nodiscard]] const std::vector<IPC::BufferDescriptorX>& BufferDescriptorX() const { |
| 235 | return buffer_x_desciptors; | 235 | return buffer_x_descriptors; |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorA() const { | 238 | [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorA() const { |
| 239 | return buffer_a_desciptors; | 239 | return buffer_a_descriptors; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorB() const { | 242 | [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorB() const { |
| 243 | return buffer_b_desciptors; | 243 | return buffer_b_descriptors; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | [[nodiscard]] const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const { | 246 | [[nodiscard]] const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const { |
| 247 | return buffer_c_desciptors; | 247 | return buffer_c_descriptors; |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | [[nodiscard]] const IPC::DomainMessageHeader& GetDomainMessageHeader() const { | 250 | [[nodiscard]] const IPC::DomainMessageHeader& GetDomainMessageHeader() const { |
| @@ -406,11 +406,11 @@ private: | |||
| 406 | std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; | 406 | std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; |
| 407 | std::optional<IPC::DataPayloadHeader> data_payload_header; | 407 | std::optional<IPC::DataPayloadHeader> data_payload_header; |
| 408 | std::optional<IPC::DomainMessageHeader> domain_message_header; | 408 | std::optional<IPC::DomainMessageHeader> domain_message_header; |
| 409 | std::vector<IPC::BufferDescriptorX> buffer_x_desciptors; | 409 | std::vector<IPC::BufferDescriptorX> buffer_x_descriptors; |
| 410 | std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors; | 410 | std::vector<IPC::BufferDescriptorABW> buffer_a_descriptors; |
| 411 | std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors; | 411 | std::vector<IPC::BufferDescriptorABW> buffer_b_descriptors; |
| 412 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; | 412 | std::vector<IPC::BufferDescriptorABW> buffer_w_descriptors; |
| 413 | std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; | 413 | std::vector<IPC::BufferDescriptorC> buffer_c_descriptors; |
| 414 | 414 | ||
| 415 | u32_le command{}; | 415 | u32_le command{}; |
| 416 | u64 pid{}; | 416 | u64 pid{}; |
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp index 9556e9193..4274a92c9 100644 --- a/src/core/hle/service/nfc/common/amiibo_crypto.cpp +++ b/src/core/hle/service/nfc/common/amiibo_crypto.cpp | |||
| @@ -19,7 +19,7 @@ namespace Service::NFP::AmiiboCrypto { | |||
| 19 | bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { | 19 | bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { |
| 20 | const auto& amiibo_data = ntag_file.user_memory; | 20 | const auto& amiibo_data = ntag_file.user_memory; |
| 21 | LOG_DEBUG(Service_NFP, "uuid_lock=0x{0:x}", ntag_file.static_lock); | 21 | LOG_DEBUG(Service_NFP, "uuid_lock=0x{0:x}", ntag_file.static_lock); |
| 22 | LOG_DEBUG(Service_NFP, "compability_container=0x{0:x}", ntag_file.compability_container); | 22 | LOG_DEBUG(Service_NFP, "compatibility_container=0x{0:x}", ntag_file.compatibility_container); |
| 23 | LOG_DEBUG(Service_NFP, "write_count={}", static_cast<u16>(amiibo_data.write_counter)); | 23 | LOG_DEBUG(Service_NFP, "write_count={}", static_cast<u16>(amiibo_data.write_counter)); |
| 24 | 24 | ||
| 25 | LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo_data.model_info.character_id); | 25 | LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo_data.model_info.character_id); |
| @@ -49,7 +49,7 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { | |||
| 49 | if (ntag_file.static_lock != 0xE00F) { | 49 | if (ntag_file.static_lock != 0xE00F) { |
| 50 | return false; | 50 | return false; |
| 51 | } | 51 | } |
| 52 | if (ntag_file.compability_container != 0xEEFF10F1U) { | 52 | if (ntag_file.compatibility_container != 0xEEFF10F1U) { |
| 53 | return false; | 53 | return false; |
| 54 | } | 54 | } |
| 55 | if (amiibo_data.model_info.tag_type != NFC::PackedTagType::Type2) { | 55 | if (amiibo_data.model_info.tag_type != NFC::PackedTagType::Type2) { |
| @@ -78,7 +78,7 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { | |||
| 78 | encoded_data.uid_crc_check2 = nfc_data.uuid_crc_check2; | 78 | encoded_data.uid_crc_check2 = nfc_data.uuid_crc_check2; |
| 79 | encoded_data.internal_number = nfc_data.internal_number; | 79 | encoded_data.internal_number = nfc_data.internal_number; |
| 80 | encoded_data.static_lock = nfc_data.static_lock; | 80 | encoded_data.static_lock = nfc_data.static_lock; |
| 81 | encoded_data.compability_container = nfc_data.compability_container; | 81 | encoded_data.compatibility_container = nfc_data.compatibility_container; |
| 82 | encoded_data.hmac_data = nfc_data.user_memory.hmac_data; | 82 | encoded_data.hmac_data = nfc_data.user_memory.hmac_data; |
| 83 | encoded_data.constant_value = nfc_data.user_memory.constant_value; | 83 | encoded_data.constant_value = nfc_data.user_memory.constant_value; |
| 84 | encoded_data.write_counter = nfc_data.user_memory.write_counter; | 84 | encoded_data.write_counter = nfc_data.user_memory.write_counter; |
| @@ -112,7 +112,7 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { | |||
| 112 | nfc_data.uuid_crc_check2 = encoded_data.uid_crc_check2; | 112 | nfc_data.uuid_crc_check2 = encoded_data.uid_crc_check2; |
| 113 | nfc_data.internal_number = encoded_data.internal_number; | 113 | nfc_data.internal_number = encoded_data.internal_number; |
| 114 | nfc_data.static_lock = encoded_data.static_lock; | 114 | nfc_data.static_lock = encoded_data.static_lock; |
| 115 | nfc_data.compability_container = encoded_data.compability_container; | 115 | nfc_data.compatibility_container = encoded_data.compatibility_container; |
| 116 | nfc_data.user_memory.hmac_data = encoded_data.hmac_data; | 116 | nfc_data.user_memory.hmac_data = encoded_data.hmac_data; |
| 117 | nfc_data.user_memory.constant_value = encoded_data.constant_value; | 117 | nfc_data.user_memory.constant_value = encoded_data.constant_value; |
| 118 | nfc_data.user_memory.write_counter = encoded_data.write_counter; | 118 | nfc_data.user_memory.write_counter = encoded_data.write_counter; |
| @@ -257,7 +257,7 @@ void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& ou | |||
| 257 | out_data.uid_crc_check2 = in_data.uid_crc_check2; | 257 | out_data.uid_crc_check2 = in_data.uid_crc_check2; |
| 258 | out_data.internal_number = in_data.internal_number; | 258 | out_data.internal_number = in_data.internal_number; |
| 259 | out_data.static_lock = in_data.static_lock; | 259 | out_data.static_lock = in_data.static_lock; |
| 260 | out_data.compability_container = in_data.compability_container; | 260 | out_data.compatibility_container = in_data.compatibility_container; |
| 261 | 261 | ||
| 262 | out_data.constant_value = in_data.constant_value; | 262 | out_data.constant_value = in_data.constant_value; |
| 263 | out_data.write_counter = in_data.write_counter; | 263 | out_data.write_counter = in_data.write_counter; |
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index b37fb6da3..31cc87acc 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -75,7 +75,7 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { | |||
| 75 | return; | 75 | return; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | if (!is_initalized) { | 78 | if (!is_initialized) { |
| 79 | return; | 79 | return; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| @@ -207,7 +207,7 @@ void NfcDevice::Initialize() { | |||
| 207 | return; | 207 | return; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | is_initalized = npad_device->AddNfcHandle(); | 210 | is_initialized = npad_device->AddNfcHandle(); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | void NfcDevice::Finalize() { | 213 | void NfcDevice::Finalize() { |
| @@ -226,7 +226,7 @@ void NfcDevice::Finalize() { | |||
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | device_state = DeviceState::Unavailable; | 228 | device_state = DeviceState::Unavailable; |
| 229 | is_initalized = false; | 229 | is_initialized = false; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) { | 232 | Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) { |
diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h index d8efe25ec..15f9b25da 100644 --- a/src/core/hle/service/nfc/common/device.h +++ b/src/core/hle/service/nfc/common/device.h | |||
| @@ -126,7 +126,7 @@ private: | |||
| 126 | Kernel::KEvent* deactivate_event = nullptr; | 126 | Kernel::KEvent* deactivate_event = nullptr; |
| 127 | Kernel::KEvent* availability_change_event = nullptr; | 127 | Kernel::KEvent* availability_change_event = nullptr; |
| 128 | 128 | ||
| 129 | bool is_initalized{}; | 129 | bool is_initialized{}; |
| 130 | NfcProtocol allowed_protocols{}; | 130 | NfcProtocol allowed_protocols{}; |
| 131 | DeviceState device_state{DeviceState::Unavailable}; | 131 | DeviceState device_state{DeviceState::Unavailable}; |
| 132 | 132 | ||
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index f96d21220..2505eb551 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h | |||
| @@ -243,12 +243,12 @@ static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid si | |||
| 243 | struct NTAG215File { | 243 | struct NTAG215File { |
| 244 | u8 uid_crc_check2; | 244 | u8 uid_crc_check2; |
| 245 | u8 internal_number; | 245 | u8 internal_number; |
| 246 | u16 static_lock; // Set defined pages as read only | 246 | u16 static_lock; // Set defined pages as read only |
| 247 | u32 compability_container; // Defines available memory | 247 | u32 compatibility_container; // Defines available memory |
| 248 | HashData hmac_data; // Hash | 248 | HashData hmac_data; // Hash |
| 249 | u8 constant_value; // Must be A5 | 249 | u8 constant_value; // Must be A5 |
| 250 | u16_be write_counter; // Number of times the amiibo has been written? | 250 | u16_be write_counter; // Number of times the amiibo has been written? |
| 251 | u8 amiibo_version; // Amiibo file version | 251 | u8 amiibo_version; // Amiibo file version |
| 252 | AmiiboSettings settings; | 252 | AmiiboSettings settings; |
| 253 | Service::Mii::Ver3StoreData owner_mii; // Mii data | 253 | Service::Mii::Ver3StoreData owner_mii; // Mii data |
| 254 | u64_be application_id; // Game id | 254 | u64_be application_id; // Game id |
| @@ -278,7 +278,7 @@ struct EncryptedNTAG215File { | |||
| 278 | u8 uuid_crc_check2; | 278 | u8 uuid_crc_check2; |
| 279 | u8 internal_number; | 279 | u8 internal_number; |
| 280 | u16 static_lock; // Set defined pages as read only | 280 | u16 static_lock; // Set defined pages as read only |
| 281 | u32 compability_container; // Defines available memory | 281 | u32 compatibility_container; // Defines available memory |
| 282 | EncryptedAmiiboFile user_memory; // Writable data | 282 | EncryptedAmiiboFile user_memory; // Writable data |
| 283 | u32 dynamic_lock; // Dynamic lock | 283 | u32 dynamic_lock; // Dynamic lock |
| 284 | u32 CFG0; // Defines memory protected by password | 284 | u32 CFG0; // Defines memory protected by password |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 932997e75..79a21683d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -90,7 +90,7 @@ private: | |||
| 90 | u64_le align; | 90 | u64_le align; |
| 91 | }; | 91 | }; |
| 92 | }; | 92 | }; |
| 93 | static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); | 93 | static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitializeEx is incorrect size"); |
| 94 | 94 | ||
| 95 | struct IoctlFreeSpace { | 95 | struct IoctlFreeSpace { |
| 96 | u64_le offset{}; | 96 | u64_le offset{}; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 61a2df121..3e0c96456 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -15,7 +15,7 @@ namespace Service::Nvidia::Devices { | |||
| 15 | nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_) | 15 | nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_) |
| 16 | : nvdevice{system_}, events_interface{events_interface_} { | 16 | : nvdevice{system_}, events_interface{events_interface_} { |
| 17 | error_notifier_event = events_interface.CreateEvent("CtrlGpuErrorNotifier"); | 17 | error_notifier_event = events_interface.CreateEvent("CtrlGpuErrorNotifier"); |
| 18 | unknown_event = events_interface.CreateEvent("CtrlGpuUknownEvent"); | 18 | unknown_event = events_interface.CreateEvent("CtrlGpuUnknownEvent"); |
| 19 | } | 19 | } |
| 20 | nvhost_ctrl_gpu::~nvhost_ctrl_gpu() { | 20 | nvhost_ctrl_gpu::~nvhost_ctrl_gpu() { |
| 21 | events_interface.FreeEvent(error_notifier_event); | 21 | events_interface.FreeEvent(error_notifier_event); |
diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h index 0e2f47075..38f35e79f 100644 --- a/src/core/hle/service/nvdrv/nvdata.h +++ b/src/core/hle/service/nvdrv/nvdata.h | |||
| @@ -51,7 +51,7 @@ enum class NvResult : u32 { | |||
| 51 | DispNoDisplaysAttached = 0x20003, | 51 | DispNoDisplaysAttached = 0x20003, |
| 52 | DispModeNotSupported = 0x20004, | 52 | DispModeNotSupported = 0x20004, |
| 53 | DispNotFound = 0x20005, | 53 | DispNotFound = 0x20005, |
| 54 | DispAttachDissallowed = 0x20006, | 54 | DispAttachDisallowed = 0x20006, |
| 55 | DispTypeNotSupported = 0x20007, | 55 | DispTypeNotSupported = 0x20007, |
| 56 | DispAuthenticationFailed = 0x20008, | 56 | DispAuthenticationFailed = 0x20008, |
| 57 | DispNotAttached = 0x20009, | 57 | DispNotAttached = 0x20009, |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index aa8aaa2d9..0469110e8 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -223,7 +223,8 @@ Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 | |||
| 223 | return VI::ResultNotFound; | 223 | return VI::ResultNotFound; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | return display->GetVSyncEvent(out_vsync_event); | 226 | *out_vsync_event = display->GetVSyncEvent(); |
| 227 | return ResultSuccess; | ||
| 227 | } | 228 | } |
| 228 | 229 | ||
| 229 | VI::Display* Nvnflinger::FindDisplay(u64 display_id) { | 230 | VI::Display* Nvnflinger::FindDisplay(u64 display_id) { |
diff --git a/src/core/hle/service/pcv/pcv.cpp b/src/core/hle/service/pcv/pcv.cpp index c13ffa6f6..3d0f2aeb7 100644 --- a/src/core/hle/service/pcv/pcv.cpp +++ b/src/core/hle/service/pcv/pcv.cpp | |||
| @@ -54,8 +54,8 @@ public: | |||
| 54 | 54 | ||
| 55 | class IClkrstSession final : public ServiceFramework<IClkrstSession> { | 55 | class IClkrstSession final : public ServiceFramework<IClkrstSession> { |
| 56 | public: | 56 | public: |
| 57 | explicit IClkrstSession(Core::System& system_, DeviceCode deivce_code_) | 57 | explicit IClkrstSession(Core::System& system_, DeviceCode device_code_) |
| 58 | : ServiceFramework{system_, "IClkrstSession"}, deivce_code(deivce_code_) { | 58 | : ServiceFramework{system_, "IClkrstSession"}, device_code(device_code_) { |
| 59 | // clang-format off | 59 | // clang-format off |
| 60 | static const FunctionInfo functions[] = { | 60 | static const FunctionInfo functions[] = { |
| 61 | {0, nullptr, "SetClockEnabled"}, | 61 | {0, nullptr, "SetClockEnabled"}, |
| @@ -93,7 +93,7 @@ private: | |||
| 93 | rb.Push<u32>(clock_rate); | 93 | rb.Push<u32>(clock_rate); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | DeviceCode deivce_code; | 96 | DeviceCode device_code; |
| 97 | u32 clock_rate{}; | 97 | u32 clock_rate{}; |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| @@ -118,9 +118,9 @@ private: | |||
| 118 | void OpenSession(HLERequestContext& ctx) { | 118 | void OpenSession(HLERequestContext& ctx) { |
| 119 | IPC::RequestParser rp{ctx}; | 119 | IPC::RequestParser rp{ctx}; |
| 120 | const auto device_code = static_cast<DeviceCode>(rp.Pop<u32>()); | 120 | const auto device_code = static_cast<DeviceCode>(rp.Pop<u32>()); |
| 121 | const auto unkonwn_input = rp.Pop<u32>(); | 121 | const auto unknown_input = rp.Pop<u32>(); |
| 122 | 122 | ||
| 123 | LOG_DEBUG(Service_PCV, "called, device_code={}, input={}", device_code, unkonwn_input); | 123 | LOG_DEBUG(Service_PCV, "called, device_code={}, input={}", device_code, unknown_input); |
| 124 | 124 | ||
| 125 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 125 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 126 | rb.Push(ResultSuccess); | 126 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/set/system_settings.cpp b/src/core/hle/service/set/system_settings.cpp index 2723417ad..5977429b2 100644 --- a/src/core/hle/service/set/system_settings.cpp +++ b/src/core/hle/service/set/system_settings.cpp | |||
| @@ -28,7 +28,7 @@ SystemSettings DefaultSystemSettings() { | |||
| 28 | .cmu_mode = CmuMode::None, | 28 | .cmu_mode = CmuMode::None, |
| 29 | .tv_underscan = {}, | 29 | .tv_underscan = {}, |
| 30 | .tv_gama = 1.0f, | 30 | .tv_gama = 1.0f, |
| 31 | .constrast_ratio = 0.5f, | 31 | .contrast_ratio = 0.5f, |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | settings.initial_launch_settings_packed = { | 34 | settings.initial_launch_settings_packed = { |
diff --git a/src/core/hle/service/set/system_settings.h b/src/core/hle/service/set/system_settings.h index ded2906ad..6ec9e71e7 100644 --- a/src/core/hle/service/set/system_settings.h +++ b/src/core/hle/service/set/system_settings.h | |||
| @@ -208,7 +208,7 @@ struct TvSettings { | |||
| 208 | CmuMode cmu_mode; | 208 | CmuMode cmu_mode; |
| 209 | u32 tv_underscan; | 209 | u32 tv_underscan; |
| 210 | f32 tv_gama; | 210 | f32 tv_gama; |
| 211 | f32 constrast_ratio; | 211 | f32 contrast_ratio; |
| 212 | }; | 212 | }; |
| 213 | static_assert(sizeof(TvSettings) == 0x20, "TvSettings is an invalid size"); | 213 | static_assert(sizeof(TvSettings) == 0x20, "TvSettings is an invalid size"); |
| 214 | 214 | ||
| @@ -341,7 +341,7 @@ struct SystemSettings { | |||
| 341 | std::array<u8, 0x3C> reserved_09934; | 341 | std::array<u8, 0x3C> reserved_09934; |
| 342 | 342 | ||
| 343 | // nn::settings::system::ErrorReportSharePermission | 343 | // nn::settings::system::ErrorReportSharePermission |
| 344 | ErrorReportSharePermission error_report_share_permssion; | 344 | ErrorReportSharePermission error_report_share_permission; |
| 345 | 345 | ||
| 346 | std::array<u8, 0x3C> reserved_09974; | 346 | std::array<u8, 0x3C> reserved_09974; |
| 347 | 347 | ||
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index f7ad6193e..af9348522 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp | |||
| @@ -721,10 +721,10 @@ void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) { | |||
| 721 | SetSaveNeeded(); | 721 | SetSaveNeeded(); |
| 722 | 722 | ||
| 723 | LOG_INFO(Service_SET, | 723 | LOG_INFO(Service_SET, |
| 724 | "called, flags={}, cmu_mode={}, constrast_ratio={}, hdmi_content_type={}, " | 724 | "called, flags={}, cmu_mode={}, contrast_ratio={}, hdmi_content_type={}, " |
| 725 | "rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}", | 725 | "rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}", |
| 726 | m_system_settings.tv_settings.flags.raw, m_system_settings.tv_settings.cmu_mode, | 726 | m_system_settings.tv_settings.flags.raw, m_system_settings.tv_settings.cmu_mode, |
| 727 | m_system_settings.tv_settings.constrast_ratio, | 727 | m_system_settings.tv_settings.contrast_ratio, |
| 728 | m_system_settings.tv_settings.hdmi_content_type, | 728 | m_system_settings.tv_settings.hdmi_content_type, |
| 729 | m_system_settings.tv_settings.rgb_range, m_system_settings.tv_settings.tv_gama, | 729 | m_system_settings.tv_settings.rgb_range, m_system_settings.tv_settings.tv_gama, |
| 730 | m_system_settings.tv_settings.tv_resolution, | 730 | m_system_settings.tv_settings.tv_resolution, |
| @@ -870,10 +870,10 @@ void ISystemSettingsServer::GetInitialLaunchSettings(HLERequestContext& ctx) { | |||
| 870 | 870 | ||
| 871 | void ISystemSettingsServer::SetInitialLaunchSettings(HLERequestContext& ctx) { | 871 | void ISystemSettingsServer::SetInitialLaunchSettings(HLERequestContext& ctx) { |
| 872 | IPC::RequestParser rp{ctx}; | 872 | IPC::RequestParser rp{ctx}; |
| 873 | auto inital_launch_settings = rp.PopRaw<InitialLaunchSettings>(); | 873 | auto initial_launch_settings = rp.PopRaw<InitialLaunchSettings>(); |
| 874 | 874 | ||
| 875 | m_system_settings.initial_launch_settings_packed.flags = inital_launch_settings.flags; | 875 | m_system_settings.initial_launch_settings_packed.flags = initial_launch_settings.flags; |
| 876 | m_system_settings.initial_launch_settings_packed.timestamp = inital_launch_settings.timestamp; | 876 | m_system_settings.initial_launch_settings_packed.timestamp = initial_launch_settings.timestamp; |
| 877 | SetSaveNeeded(); | 877 | SetSaveNeeded(); |
| 878 | 878 | ||
| 879 | LOG_INFO(Service_SET, "called, flags={}, timestamp={}", | 879 | LOG_INFO(Service_SET, "called, flags={}, timestamp={}", |
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 71ce9be50..e2d9cd98a 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -71,18 +71,7 @@ size_t Display::GetNumLayers() const { | |||
| 71 | return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); }); | 71 | return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); }); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) { | 74 | Kernel::KReadableEvent* Display::GetVSyncEvent() { |
| 75 | if (got_vsync_event) { | ||
| 76 | return ResultPermissionDenied; | ||
| 77 | } | ||
| 78 | |||
| 79 | got_vsync_event = true; | ||
| 80 | |||
| 81 | *out_vsync_event = GetVSyncEventUnchecked(); | ||
| 82 | return ResultSuccess; | ||
| 83 | } | ||
| 84 | |||
| 85 | Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() { | ||
| 86 | return &vsync_event->GetReadableEvent(); | 75 | return &vsync_event->GetReadableEvent(); |
| 87 | } | 76 | } |
| 88 | 77 | ||
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 1d9360b96..7e68ee79b 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h | |||
| @@ -74,16 +74,8 @@ public: | |||
| 74 | 74 | ||
| 75 | std::size_t GetNumLayers() const; | 75 | std::size_t GetNumLayers() const; |
| 76 | 76 | ||
| 77 | /** | ||
| 78 | * Gets the internal vsync event. | ||
| 79 | * | ||
| 80 | * @returns The internal Vsync event if it has not yet been retrieved, | ||
| 81 | * VI::ResultPermissionDenied otherwise. | ||
| 82 | */ | ||
| 83 | [[nodiscard]] Result GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event); | ||
| 84 | |||
| 85 | /// Gets the internal vsync event. | 77 | /// Gets the internal vsync event. |
| 86 | Kernel::KReadableEvent* GetVSyncEventUnchecked(); | 78 | Kernel::KReadableEvent* GetVSyncEvent(); |
| 87 | 79 | ||
| 88 | /// Signals the internal vsync event. | 80 | /// Signals the internal vsync event. |
| 89 | void SignalVSyncEvent(); | 81 | void SignalVSyncEvent(); |
| @@ -104,7 +96,6 @@ public: | |||
| 104 | /// Resets the display for a new connection. | 96 | /// Resets the display for a new connection. |
| 105 | void Reset() { | 97 | void Reset() { |
| 106 | layers.clear(); | 98 | layers.clear(); |
| 107 | got_vsync_event = false; | ||
| 108 | } | 99 | } |
| 109 | 100 | ||
| 110 | /// Attempts to find a layer with the given ID. | 101 | /// Attempts to find a layer with the given ID. |
| @@ -133,7 +124,6 @@ private: | |||
| 133 | 124 | ||
| 134 | std::vector<std::unique_ptr<Layer>> layers; | 125 | std::vector<std::unique_ptr<Layer>> layers; |
| 135 | Kernel::KEvent* vsync_event{}; | 126 | Kernel::KEvent* vsync_event{}; |
| 136 | bool got_vsync_event{false}; | ||
| 137 | }; | 127 | }; |
| 138 | 128 | ||
| 139 | } // namespace Service::VI | 129 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 9ab8788e3..39d5be90d 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -343,8 +343,8 @@ private: | |||
| 343 | 343 | ||
| 344 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | 344 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { |
| 345 | public: | 345 | public: |
| 346 | explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_) | 346 | explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) |
| 347 | : ServiceFramework{system_, "IManagerDisplayService"}, nv_flinger{nv_flinger_} { | 347 | : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} { |
| 348 | // clang-format off | 348 | // clang-format off |
| 349 | static const FunctionInfo functions[] = { | 349 | static const FunctionInfo functions[] = { |
| 350 | {200, nullptr, "AllocateProcessHeapBlock"}, | 350 | {200, nullptr, "AllocateProcessHeapBlock"}, |
| @@ -440,7 +440,7 @@ private: | |||
| 440 | IPC::RequestParser rp{ctx}; | 440 | IPC::RequestParser rp{ctx}; |
| 441 | const u64 display = rp.Pop<u64>(); | 441 | const u64 display = rp.Pop<u64>(); |
| 442 | 442 | ||
| 443 | const Result rc = nv_flinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; | 443 | const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; |
| 444 | 444 | ||
| 445 | IPC::ResponseBuilder rb{ctx, 2}; | 445 | IPC::ResponseBuilder rb{ctx, 2}; |
| 446 | rb.Push(rc); | 446 | rb.Push(rc); |
| @@ -457,7 +457,7 @@ private: | |||
| 457 | "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", | 457 | "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", |
| 458 | unknown, display, aruid); | 458 | unknown, display, aruid); |
| 459 | 459 | ||
| 460 | const auto layer_id = nv_flinger.CreateLayer(display); | 460 | const auto layer_id = nvnflinger.CreateLayer(display); |
| 461 | if (!layer_id) { | 461 | if (!layer_id) { |
| 462 | LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); | 462 | LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); |
| 463 | IPC::ResponseBuilder rb{ctx, 2}; | 463 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -494,14 +494,14 @@ private: | |||
| 494 | rb.Push(ResultSuccess); | 494 | rb.Push(ResultSuccess); |
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | Nvnflinger::Nvnflinger& nv_flinger; | 497 | Nvnflinger::Nvnflinger& nvnflinger; |
| 498 | }; | 498 | }; |
| 499 | 499 | ||
| 500 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | 500 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { |
| 501 | public: | 501 | public: |
| 502 | IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | 502 | IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, |
| 503 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) | 503 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) |
| 504 | : ServiceFramework{system_, "IApplicationDisplayService"}, nv_flinger{nv_flinger_}, | 504 | : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, |
| 505 | hos_binder_driver_server{hos_binder_driver_server_} { | 505 | hos_binder_driver_server{hos_binder_driver_server_} { |
| 506 | 506 | ||
| 507 | static const FunctionInfo functions[] = { | 507 | static const FunctionInfo functions[] = { |
| @@ -564,7 +564,7 @@ private: | |||
| 564 | 564 | ||
| 565 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 565 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 566 | rb.Push(ResultSuccess); | 566 | rb.Push(ResultSuccess); |
| 567 | rb.PushIpcInterface<ISystemDisplayService>(system, nv_flinger); | 567 | rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger); |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | void GetManagerDisplayService(HLERequestContext& ctx) { | 570 | void GetManagerDisplayService(HLERequestContext& ctx) { |
| @@ -572,7 +572,7 @@ private: | |||
| 572 | 572 | ||
| 573 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 573 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 574 | rb.Push(ResultSuccess); | 574 | rb.Push(ResultSuccess); |
| 575 | rb.PushIpcInterface<IManagerDisplayService>(system, nv_flinger); | 575 | rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger); |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | void GetIndirectDisplayTransactionService(HLERequestContext& ctx) { | 578 | void GetIndirectDisplayTransactionService(HLERequestContext& ctx) { |
| @@ -607,7 +607,7 @@ private: | |||
| 607 | 607 | ||
| 608 | ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); | 608 | ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); |
| 609 | 609 | ||
| 610 | const auto display_id = nv_flinger.OpenDisplay(name); | 610 | const auto display_id = nvnflinger.OpenDisplay(name); |
| 611 | if (!display_id) { | 611 | if (!display_id) { |
| 612 | LOG_ERROR(Service_VI, "Display not found! display_name={}", name); | 612 | LOG_ERROR(Service_VI, "Display not found! display_name={}", name); |
| 613 | IPC::ResponseBuilder rb{ctx, 2}; | 613 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -624,7 +624,7 @@ private: | |||
| 624 | IPC::RequestParser rp{ctx}; | 624 | IPC::RequestParser rp{ctx}; |
| 625 | const u64 display_id = rp.Pop<u64>(); | 625 | const u64 display_id = rp.Pop<u64>(); |
| 626 | 626 | ||
| 627 | const Result rc = nv_flinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; | 627 | const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; |
| 628 | 628 | ||
| 629 | IPC::ResponseBuilder rb{ctx, 2}; | 629 | IPC::ResponseBuilder rb{ctx, 2}; |
| 630 | rb.Push(rc); | 630 | rb.Push(rc); |
| @@ -703,7 +703,7 @@ private: | |||
| 703 | 703 | ||
| 704 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); | 704 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); |
| 705 | 705 | ||
| 706 | const auto display_id = nv_flinger.OpenDisplay(display_name); | 706 | const auto display_id = nvnflinger.OpenDisplay(display_name); |
| 707 | if (!display_id) { | 707 | if (!display_id) { |
| 708 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | 708 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); |
| 709 | IPC::ResponseBuilder rb{ctx, 2}; | 709 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -711,7 +711,7 @@ private: | |||
| 711 | return; | 711 | return; |
| 712 | } | 712 | } |
| 713 | 713 | ||
| 714 | const auto buffer_queue_id = nv_flinger.FindBufferQueueId(*display_id, layer_id); | 714 | const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); |
| 715 | if (!buffer_queue_id) { | 715 | if (!buffer_queue_id) { |
| 716 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | 716 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); |
| 717 | IPC::ResponseBuilder rb{ctx, 2}; | 717 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -719,7 +719,7 @@ private: | |||
| 719 | return; | 719 | return; |
| 720 | } | 720 | } |
| 721 | 721 | ||
| 722 | nv_flinger.OpenLayer(layer_id); | 722 | nvnflinger.OpenLayer(layer_id); |
| 723 | 723 | ||
| 724 | android::OutputParcel parcel; | 724 | android::OutputParcel parcel; |
| 725 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | 725 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); |
| @@ -737,7 +737,7 @@ private: | |||
| 737 | 737 | ||
| 738 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); | 738 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); |
| 739 | 739 | ||
| 740 | nv_flinger.CloseLayer(layer_id); | 740 | nvnflinger.CloseLayer(layer_id); |
| 741 | 741 | ||
| 742 | IPC::ResponseBuilder rb{ctx, 2}; | 742 | IPC::ResponseBuilder rb{ctx, 2}; |
| 743 | rb.Push(ResultSuccess); | 743 | rb.Push(ResultSuccess); |
| @@ -753,7 +753,7 @@ private: | |||
| 753 | 753 | ||
| 754 | // TODO(Subv): What's the difference between a Stray and a Managed layer? | 754 | // TODO(Subv): What's the difference between a Stray and a Managed layer? |
| 755 | 755 | ||
| 756 | const auto layer_id = nv_flinger.CreateLayer(display_id); | 756 | const auto layer_id = nvnflinger.CreateLayer(display_id); |
| 757 | if (!layer_id) { | 757 | if (!layer_id) { |
| 758 | LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | 758 | LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); |
| 759 | IPC::ResponseBuilder rb{ctx, 2}; | 759 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -761,7 +761,7 @@ private: | |||
| 761 | return; | 761 | return; |
| 762 | } | 762 | } |
| 763 | 763 | ||
| 764 | const auto buffer_queue_id = nv_flinger.FindBufferQueueId(display_id, *layer_id); | 764 | const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); |
| 765 | if (!buffer_queue_id) { | 765 | if (!buffer_queue_id) { |
| 766 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | 766 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); |
| 767 | IPC::ResponseBuilder rb{ctx, 2}; | 767 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -785,7 +785,7 @@ private: | |||
| 785 | const u64 layer_id = rp.Pop<u64>(); | 785 | const u64 layer_id = rp.Pop<u64>(); |
| 786 | 786 | ||
| 787 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); | 787 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); |
| 788 | nv_flinger.DestroyLayer(layer_id); | 788 | nvnflinger.DestroyLayer(layer_id); |
| 789 | 789 | ||
| 790 | IPC::ResponseBuilder rb{ctx, 2}; | 790 | IPC::ResponseBuilder rb{ctx, 2}; |
| 791 | rb.Push(ResultSuccess); | 791 | rb.Push(ResultSuccess); |
| @@ -798,7 +798,7 @@ private: | |||
| 798 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | 798 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); |
| 799 | 799 | ||
| 800 | Kernel::KReadableEvent* vsync_event{}; | 800 | Kernel::KReadableEvent* vsync_event{}; |
| 801 | const auto result = nv_flinger.FindVsyncEvent(&vsync_event, display_id); | 801 | const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id); |
| 802 | if (result != ResultSuccess) { | 802 | if (result != ResultSuccess) { |
| 803 | if (result == ResultNotFound) { | 803 | if (result == ResultNotFound) { |
| 804 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | 804 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); |
| @@ -808,6 +808,12 @@ private: | |||
| 808 | rb.Push(result); | 808 | rb.Push(result); |
| 809 | return; | 809 | return; |
| 810 | } | 810 | } |
| 811 | if (vsync_event_fetched) { | ||
| 812 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 813 | rb.Push(VI::ResultPermissionDenied); | ||
| 814 | return; | ||
| 815 | } | ||
| 816 | vsync_event_fetched = true; | ||
| 811 | 817 | ||
| 812 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 818 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 813 | rb.Push(ResultSuccess); | 819 | rb.Push(ResultSuccess); |
| @@ -899,8 +905,9 @@ private: | |||
| 899 | } | 905 | } |
| 900 | } | 906 | } |
| 901 | 907 | ||
| 902 | Nvnflinger::Nvnflinger& nv_flinger; | 908 | Nvnflinger::Nvnflinger& nvnflinger; |
| 903 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | 909 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; |
| 910 | bool vsync_event_fetched{false}; | ||
| 904 | }; | 911 | }; |
| 905 | 912 | ||
| 906 | static bool IsValidServiceAccess(Permission permission, Policy policy) { | 913 | static bool IsValidServiceAccess(Permission permission, Policy policy) { |
| @@ -916,7 +923,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) { | |||
| 916 | } | 923 | } |
| 917 | 924 | ||
| 918 | void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, | 925 | void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, |
| 919 | Nvnflinger::Nvnflinger& nv_flinger, | 926 | Nvnflinger::Nvnflinger& nvnflinger, |
| 920 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, | 927 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, |
| 921 | Permission permission) { | 928 | Permission permission) { |
| 922 | IPC::RequestParser rp{ctx}; | 929 | IPC::RequestParser rp{ctx}; |
| @@ -931,19 +938,19 @@ void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, | |||
| 931 | 938 | ||
| 932 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 939 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 933 | rb.Push(ResultSuccess); | 940 | rb.Push(ResultSuccess); |
| 934 | rb.PushIpcInterface<IApplicationDisplayService>(system, nv_flinger, hos_binder_driver_server); | 941 | rb.PushIpcInterface<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server); |
| 935 | } | 942 | } |
| 936 | 943 | ||
| 937 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nv_flinger, | 944 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, |
| 938 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { | 945 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { |
| 939 | auto server_manager = std::make_unique<ServerManager>(system); | 946 | auto server_manager = std::make_unique<ServerManager>(system); |
| 940 | 947 | ||
| 941 | server_manager->RegisterNamedService( | 948 | server_manager->RegisterNamedService( |
| 942 | "vi:m", std::make_shared<VI_M>(system, nv_flinger, hos_binder_driver_server)); | 949 | "vi:m", std::make_shared<VI_M>(system, nvnflinger, hos_binder_driver_server)); |
| 943 | server_manager->RegisterNamedService( | 950 | server_manager->RegisterNamedService( |
| 944 | "vi:s", std::make_shared<VI_S>(system, nv_flinger, hos_binder_driver_server)); | 951 | "vi:s", std::make_shared<VI_S>(system, nvnflinger, hos_binder_driver_server)); |
| 945 | server_manager->RegisterNamedService( | 952 | server_manager->RegisterNamedService( |
| 946 | "vi:u", std::make_shared<VI_U>(system, nv_flinger, hos_binder_driver_server)); | 953 | "vi:u", std::make_shared<VI_U>(system, nvnflinger, hos_binder_driver_server)); |
| 947 | ServerManager::RunServer(std::move(server_manager)); | 954 | ServerManager::RunServer(std::move(server_manager)); |
| 948 | } | 955 | } |
| 949 | 956 | ||
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index a35b62f97..ee4bcbcfa 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h | |||
| @@ -48,7 +48,7 @@ void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, | |||
| 48 | Permission permission); | 48 | Permission permission); |
| 49 | } // namespace detail | 49 | } // namespace detail |
| 50 | 50 | ||
| 51 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nv_flinger, | 51 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, |
| 52 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | 52 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); |
| 53 | 53 | ||
| 54 | } // namespace Service::VI | 54 | } // namespace Service::VI |
diff --git a/src/hid_core/CMakeLists.txt b/src/hid_core/CMakeLists.txt index cce4e6857..aa85502b5 100644 --- a/src/hid_core/CMakeLists.txt +++ b/src/hid_core/CMakeLists.txt | |||
| @@ -36,6 +36,30 @@ add_library(hid_core STATIC | |||
| 36 | irsensor/processor_base.h | 36 | irsensor/processor_base.h |
| 37 | irsensor/tera_plugin_processor.cpp | 37 | irsensor/tera_plugin_processor.cpp |
| 38 | irsensor/tera_plugin_processor.h | 38 | irsensor/tera_plugin_processor.h |
| 39 | resources/abstracted_pad/abstract_battery_handler.cpp | ||
| 40 | resources/abstracted_pad/abstract_battery_handler.h | ||
| 41 | resources/abstracted_pad/abstract_button_handler.cpp | ||
| 42 | resources/abstracted_pad/abstract_button_handler.h | ||
| 43 | resources/abstracted_pad/abstract_ir_sensor_handler.cpp | ||
| 44 | resources/abstracted_pad/abstract_ir_sensor_handler.h | ||
| 45 | resources/abstracted_pad/abstract_led_handler.cpp | ||
| 46 | resources/abstracted_pad/abstract_led_handler.h | ||
| 47 | resources/abstracted_pad/abstract_mcu_handler.cpp | ||
| 48 | resources/abstracted_pad/abstract_mcu_handler.h | ||
| 49 | resources/abstracted_pad/abstract_nfc_handler.cpp | ||
| 50 | resources/abstracted_pad/abstract_nfc_handler.h | ||
| 51 | resources/abstracted_pad/abstract_pad.cpp | ||
| 52 | resources/abstracted_pad/abstract_pad.h | ||
| 53 | resources/abstracted_pad/abstract_pad_holder.cpp | ||
| 54 | resources/abstracted_pad/abstract_pad_holder.h | ||
| 55 | resources/abstracted_pad/abstract_palma_handler.cpp | ||
| 56 | resources/abstracted_pad/abstract_palma_handler.h | ||
| 57 | resources/abstracted_pad/abstract_properties_handler.cpp | ||
| 58 | resources/abstracted_pad/abstract_properties_handler.h | ||
| 59 | resources/abstracted_pad/abstract_sixaxis_handler.cpp | ||
| 60 | resources/abstracted_pad/abstract_sixaxis_handler.h | ||
| 61 | resources/abstracted_pad/abstract_vibration_handler.cpp | ||
| 62 | resources/abstracted_pad/abstract_vibration_handler.h | ||
| 39 | resources/debug_pad/debug_pad.cpp | 63 | resources/debug_pad/debug_pad.cpp |
| 40 | resources/debug_pad/debug_pad.h | 64 | resources/debug_pad/debug_pad.h |
| 41 | resources/debug_pad/debug_pad_types.h | 65 | resources/debug_pad/debug_pad_types.h |
| @@ -56,6 +80,8 @@ add_library(hid_core STATIC | |||
| 56 | resources/npad/npad_resource.cpp | 80 | resources/npad/npad_resource.cpp |
| 57 | resources/npad/npad_resource.h | 81 | resources/npad/npad_resource.h |
| 58 | resources/npad/npad_types.h | 82 | resources/npad/npad_types.h |
| 83 | resources/npad/npad_vibration.cpp | ||
| 84 | resources/npad/npad_vibration.h | ||
| 59 | resources/palma/palma.cpp | 85 | resources/palma/palma.cpp |
| 60 | resources/palma/palma.h | 86 | resources/palma/palma.h |
| 61 | resources/six_axis/console_six_axis.cpp | 87 | resources/six_axis/console_six_axis.cpp |
| @@ -78,6 +104,14 @@ add_library(hid_core STATIC | |||
| 78 | resources/touch_screen/touch_types.h | 104 | resources/touch_screen/touch_types.h |
| 79 | resources/unique_pad/unique_pad.cpp | 105 | resources/unique_pad/unique_pad.cpp |
| 80 | resources/unique_pad/unique_pad.h | 106 | resources/unique_pad/unique_pad.h |
| 107 | resources/vibration/gc_vibration_device.h | ||
| 108 | resources/vibration/gc_vibration_device.cpp | ||
| 109 | resources/vibration/n64_vibration_device.h | ||
| 110 | resources/vibration/n64_vibration_device.cpp | ||
| 111 | resources/vibration/vibration_base.h | ||
| 112 | resources/vibration/vibration_base.cpp | ||
| 113 | resources/vibration/vibration_device.h | ||
| 114 | resources/vibration/vibration_device.cpp | ||
| 81 | resources/applet_resource.cpp | 115 | resources/applet_resource.cpp |
| 82 | resources/applet_resource.h | 116 | resources/applet_resource.h |
| 83 | resources/controller_base.cpp | 117 | resources/controller_base.cpp |
diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index 3d2d1e9f9..a6a96935d 100644 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp | |||
| @@ -27,7 +27,7 @@ EmulatedController::~EmulatedController() = default; | |||
| 27 | NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { | 27 | NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { |
| 28 | switch (type) { | 28 | switch (type) { |
| 29 | case Settings::ControllerType::ProController: | 29 | case Settings::ControllerType::ProController: |
| 30 | return NpadStyleIndex::ProController; | 30 | return NpadStyleIndex::Fullkey; |
| 31 | case Settings::ControllerType::DualJoyconDetached: | 31 | case Settings::ControllerType::DualJoyconDetached: |
| 32 | return NpadStyleIndex::JoyconDual; | 32 | return NpadStyleIndex::JoyconDual; |
| 33 | case Settings::ControllerType::LeftJoycon: | 33 | case Settings::ControllerType::LeftJoycon: |
| @@ -49,13 +49,13 @@ NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerTyp | |||
| 49 | case Settings::ControllerType::SegaGenesis: | 49 | case Settings::ControllerType::SegaGenesis: |
| 50 | return NpadStyleIndex::SegaGenesis; | 50 | return NpadStyleIndex::SegaGenesis; |
| 51 | default: | 51 | default: |
| 52 | return NpadStyleIndex::ProController; | 52 | return NpadStyleIndex::Fullkey; |
| 53 | } | 53 | } |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) { | 56 | Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) { |
| 57 | switch (type) { | 57 | switch (type) { |
| 58 | case NpadStyleIndex::ProController: | 58 | case NpadStyleIndex::Fullkey: |
| 59 | return Settings::ControllerType::ProController; | 59 | return Settings::ControllerType::ProController; |
| 60 | case NpadStyleIndex::JoyconDual: | 60 | case NpadStyleIndex::JoyconDual: |
| 61 | return Settings::ControllerType::DualJoyconDetached; | 61 | return Settings::ControllerType::DualJoyconDetached; |
| @@ -106,7 +106,7 @@ void EmulatedController::ReloadFromSettings() { | |||
| 106 | SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); | 106 | SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); |
| 107 | original_npad_type = npad_type; | 107 | original_npad_type = npad_type; |
| 108 | } else { | 108 | } else { |
| 109 | SetNpadStyleIndex(NpadStyleIndex::ProController); | 109 | SetNpadStyleIndex(NpadStyleIndex::Fullkey); |
| 110 | original_npad_type = npad_type; | 110 | original_npad_type = npad_type; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| @@ -1073,7 +1073,7 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback | |||
| 1073 | .body = GetNpadColor(controller.color_values[index].body), | 1073 | .body = GetNpadColor(controller.color_values[index].body), |
| 1074 | .button = GetNpadColor(controller.color_values[index].buttons), | 1074 | .button = GetNpadColor(controller.color_values[index].buttons), |
| 1075 | }; | 1075 | }; |
| 1076 | if (npad_type == NpadStyleIndex::ProController) { | 1076 | if (npad_type == NpadStyleIndex::Fullkey) { |
| 1077 | controller.colors_state.left = { | 1077 | controller.colors_state.left = { |
| 1078 | .body = GetNpadColor(controller.color_values[index].left_grip), | 1078 | .body = GetNpadColor(controller.color_values[index].left_grip), |
| 1079 | .button = GetNpadColor(controller.color_values[index].buttons), | 1079 | .button = GetNpadColor(controller.color_values[index].buttons), |
| @@ -1356,7 +1356,7 @@ bool EmulatedController::HasNfc() const { | |||
| 1356 | switch (npad_type) { | 1356 | switch (npad_type) { |
| 1357 | case NpadStyleIndex::JoyconRight: | 1357 | case NpadStyleIndex::JoyconRight: |
| 1358 | case NpadStyleIndex::JoyconDual: | 1358 | case NpadStyleIndex::JoyconDual: |
| 1359 | case NpadStyleIndex::ProController: | 1359 | case NpadStyleIndex::Fullkey: |
| 1360 | case NpadStyleIndex::Handheld: | 1360 | case NpadStyleIndex::Handheld: |
| 1361 | break; | 1361 | break; |
| 1362 | default: | 1362 | default: |
| @@ -1548,7 +1548,7 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) | |||
| 1548 | // Fallback Fullkey controllers to Pro controllers | 1548 | // Fallback Fullkey controllers to Pro controllers |
| 1549 | if (IsControllerFullkey() && supported_style_tag.fullkey) { | 1549 | if (IsControllerFullkey() && supported_style_tag.fullkey) { |
| 1550 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); | 1550 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); |
| 1551 | SetNpadStyleIndex(NpadStyleIndex::ProController); | 1551 | SetNpadStyleIndex(NpadStyleIndex::Fullkey); |
| 1552 | Connect(); | 1552 | Connect(); |
| 1553 | return; | 1553 | return; |
| 1554 | } | 1554 | } |
| @@ -1556,13 +1556,13 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) | |||
| 1556 | // Fallback Dual joycon controllers to Pro controllers | 1556 | // Fallback Dual joycon controllers to Pro controllers |
| 1557 | if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) { | 1557 | if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) { |
| 1558 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); | 1558 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); |
| 1559 | SetNpadStyleIndex(NpadStyleIndex::ProController); | 1559 | SetNpadStyleIndex(NpadStyleIndex::Fullkey); |
| 1560 | Connect(); | 1560 | Connect(); |
| 1561 | return; | 1561 | return; |
| 1562 | } | 1562 | } |
| 1563 | 1563 | ||
| 1564 | // Fallback Pro controllers to Dual joycon | 1564 | // Fallback Pro controllers to Dual joycon |
| 1565 | if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) { | 1565 | if (npad_type == NpadStyleIndex::Fullkey && supported_style_tag.joycon_dual) { |
| 1566 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type); | 1566 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type); |
| 1567 | SetNpadStyleIndex(NpadStyleIndex::JoyconDual); | 1567 | SetNpadStyleIndex(NpadStyleIndex::JoyconDual); |
| 1568 | Connect(); | 1568 | Connect(); |
| @@ -1577,7 +1577,7 @@ bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const { | |||
| 1577 | std::scoped_lock lock{mutex}; | 1577 | std::scoped_lock lock{mutex}; |
| 1578 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | 1578 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; |
| 1579 | switch (type) { | 1579 | switch (type) { |
| 1580 | case NpadStyleIndex::ProController: | 1580 | case NpadStyleIndex::Fullkey: |
| 1581 | case NpadStyleIndex::GameCube: | 1581 | case NpadStyleIndex::GameCube: |
| 1582 | case NpadStyleIndex::NES: | 1582 | case NpadStyleIndex::NES: |
| 1583 | case NpadStyleIndex::SNES: | 1583 | case NpadStyleIndex::SNES: |
| @@ -1593,7 +1593,7 @@ bool EmulatedController::IsControllerSupported(bool use_temporary_value) const { | |||
| 1593 | std::scoped_lock lock{mutex}; | 1593 | std::scoped_lock lock{mutex}; |
| 1594 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | 1594 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; |
| 1595 | switch (type) { | 1595 | switch (type) { |
| 1596 | case NpadStyleIndex::ProController: | 1596 | case NpadStyleIndex::Fullkey: |
| 1597 | return supported_style_tag.fullkey.As<bool>(); | 1597 | return supported_style_tag.fullkey.As<bool>(); |
| 1598 | case NpadStyleIndex::Handheld: | 1598 | case NpadStyleIndex::Handheld: |
| 1599 | return supported_style_tag.handheld.As<bool>(); | 1599 | return supported_style_tag.handheld.As<bool>(); |
diff --git a/src/hid_core/hid_types.h b/src/hid_core/hid_types.h index a81ed6af0..2c3f02f34 100644 --- a/src/hid_core/hid_types.h +++ b/src/hid_core/hid_types.h | |||
| @@ -220,6 +220,7 @@ enum class NpadIdType : u32 { | |||
| 220 | }; | 220 | }; |
| 221 | 221 | ||
| 222 | enum class NpadInterfaceType : u8 { | 222 | enum class NpadInterfaceType : u8 { |
| 223 | None = 0, | ||
| 223 | Bluetooth = 1, | 224 | Bluetooth = 1, |
| 224 | Rail = 2, | 225 | Rail = 2, |
| 225 | Usb = 3, | 226 | Usb = 3, |
| @@ -229,7 +230,7 @@ enum class NpadInterfaceType : u8 { | |||
| 229 | // This is nn::hid::NpadStyleIndex | 230 | // This is nn::hid::NpadStyleIndex |
| 230 | enum class NpadStyleIndex : u8 { | 231 | enum class NpadStyleIndex : u8 { |
| 231 | None = 0, | 232 | None = 0, |
| 232 | ProController = 3, | 233 | Fullkey = 3, |
| 233 | Handheld = 4, | 234 | Handheld = 4, |
| 234 | HandheldNES = 4, | 235 | HandheldNES = 4, |
| 235 | JoyconDual = 5, | 236 | JoyconDual = 5, |
diff --git a/src/hid_core/hid_util.h b/src/hid_core/hid_util.h index 94ff2d23a..397a87472 100644 --- a/src/hid_core/hid_util.h +++ b/src/hid_core/hid_util.h | |||
| @@ -42,7 +42,7 @@ constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& hand | |||
| 42 | 42 | ||
| 43 | constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) { | 43 | constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) { |
| 44 | switch (handle.npad_type) { | 44 | switch (handle.npad_type) { |
| 45 | case Core::HID::NpadStyleIndex::ProController: | 45 | case Core::HID::NpadStyleIndex::Fullkey: |
| 46 | case Core::HID::NpadStyleIndex::Handheld: | 46 | case Core::HID::NpadStyleIndex::Handheld: |
| 47 | case Core::HID::NpadStyleIndex::JoyconDual: | 47 | case Core::HID::NpadStyleIndex::JoyconDual: |
| 48 | case Core::HID::NpadStyleIndex::JoyconLeft: | 48 | case Core::HID::NpadStyleIndex::JoyconLeft: |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp new file mode 100644 index 000000000..62fbbb0a7 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "hid_core/hid_result.h" | ||
| 6 | #include "hid_core/hid_util.h" | ||
| 7 | #include "hid_core/resources/abstracted_pad/abstract_battery_handler.h" | ||
| 8 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 9 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 10 | #include "hid_core/resources/applet_resource.h" | ||
| 11 | #include "hid_core/resources/npad/npad_types.h" | ||
| 12 | #include "hid_core/resources/shared_memory_format.h" | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | |||
| 16 | NpadAbstractBatteryHandler::NpadAbstractBatteryHandler() {} | ||
| 17 | |||
| 18 | NpadAbstractBatteryHandler::~NpadAbstractBatteryHandler() = default; | ||
| 19 | |||
| 20 | void NpadAbstractBatteryHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 21 | abstract_pad_holder = holder; | ||
| 22 | } | ||
| 23 | |||
| 24 | void NpadAbstractBatteryHandler::SetAppletResource(AppletResourceHolder* applet_resource) { | ||
| 25 | applet_resource_holder = applet_resource; | ||
| 26 | } | ||
| 27 | |||
| 28 | void NpadAbstractBatteryHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 29 | properties_handler = handler; | ||
| 30 | } | ||
| 31 | |||
| 32 | Result NpadAbstractBatteryHandler::IncrementRefCounter() { | ||
| 33 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 34 | return ResultNpadHandlerOverflow; | ||
| 35 | } | ||
| 36 | ref_counter++; | ||
| 37 | return ResultSuccess; | ||
| 38 | } | ||
| 39 | |||
| 40 | Result NpadAbstractBatteryHandler::DecrementRefCounter() { | ||
| 41 | if (ref_counter == 0) { | ||
| 42 | return ResultNpadHandlerNotInitialized; | ||
| 43 | } | ||
| 44 | ref_counter--; | ||
| 45 | return ResultSuccess; | ||
| 46 | } | ||
| 47 | |||
| 48 | Result NpadAbstractBatteryHandler::UpdateBatteryState(u64 aruid) { | ||
| 49 | const auto npad_index = NpadIdTypeToIndex(properties_handler->GetNpadId()); | ||
| 50 | AruidData* aruid_data = applet_resource_holder->applet_resource->GetAruidData(aruid); | ||
| 51 | if (aruid_data == nullptr) { | ||
| 52 | return ResultSuccess; | ||
| 53 | } | ||
| 54 | |||
| 55 | auto& npad_internal_state = | ||
| 56 | aruid_data->shared_memory_format->npad.npad_entry[npad_index].internal_state; | ||
| 57 | auto& system_properties = npad_internal_state.system_properties; | ||
| 58 | |||
| 59 | system_properties.is_charging_joy_dual.Assign(dual_battery.is_charging); | ||
| 60 | system_properties.is_powered_joy_dual.Assign(dual_battery.is_powered); | ||
| 61 | system_properties.is_charging_joy_left.Assign(left_battery.is_charging); | ||
| 62 | system_properties.is_powered_joy_left.Assign(left_battery.is_powered); | ||
| 63 | system_properties.is_charging_joy_right.Assign(right_battery.is_charging); | ||
| 64 | system_properties.is_powered_joy_right.Assign(right_battery.is_powered); | ||
| 65 | |||
| 66 | npad_internal_state.battery_level_dual = dual_battery.battery_level; | ||
| 67 | npad_internal_state.battery_level_left = left_battery.battery_level; | ||
| 68 | npad_internal_state.battery_level_right = right_battery.battery_level; | ||
| 69 | |||
| 70 | return ResultSuccess; | ||
| 71 | } | ||
| 72 | |||
| 73 | void NpadAbstractBatteryHandler::UpdateBatteryState() { | ||
| 74 | if (ref_counter == 0) { | ||
| 75 | return; | ||
| 76 | } | ||
| 77 | has_new_battery_data = GetNewBatteryState(); | ||
| 78 | } | ||
| 79 | |||
| 80 | bool NpadAbstractBatteryHandler::GetNewBatteryState() { | ||
| 81 | bool has_changed = false; | ||
| 82 | Core::HID::NpadPowerInfo new_dual_battery_state{}; | ||
| 83 | Core::HID::NpadPowerInfo new_left_battery_state{}; | ||
| 84 | Core::HID::NpadPowerInfo new_right_battery_state{}; | ||
| 85 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 86 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 87 | |||
| 88 | for (std::size_t i = 0; i < count; i++) { | ||
| 89 | auto* abstract_pad = abstract_pads[i]; | ||
| 90 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 91 | continue; | ||
| 92 | } | ||
| 93 | const auto power_info = abstract_pad->power_info; | ||
| 94 | if (power_info.battery_level > Core::HID::NpadBatteryLevel::Full) { | ||
| 95 | // Abort | ||
| 96 | continue; | ||
| 97 | } | ||
| 98 | |||
| 99 | const auto style = abstract_pad->assignment_style; | ||
| 100 | |||
| 101 | if (style.is_external_assigned || style.is_handheld_assigned) { | ||
| 102 | new_dual_battery_state = power_info; | ||
| 103 | } | ||
| 104 | if (style.is_external_left_assigned || style.is_handheld_left_assigned) { | ||
| 105 | new_left_battery_state = power_info; | ||
| 106 | } | ||
| 107 | if (style.is_external_right_assigned || style.is_handheld_right_assigned) { | ||
| 108 | new_right_battery_state = power_info; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (abstract_pad->internal_flags.is_battery_low_ovln_required) { | ||
| 112 | if (abstract_pad->interface_type == Core::HID::NpadInterfaceType::Rail) { | ||
| 113 | // TODO | ||
| 114 | } | ||
| 115 | abstract_pad->internal_flags.is_battery_low_ovln_required.Assign(false); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | if (dual_battery.battery_level != new_dual_battery_state.battery_level || | ||
| 120 | dual_battery.is_charging != new_dual_battery_state.is_charging || | ||
| 121 | dual_battery.is_powered != new_dual_battery_state.is_powered) { | ||
| 122 | has_changed = true; | ||
| 123 | dual_battery = new_dual_battery_state; | ||
| 124 | } | ||
| 125 | |||
| 126 | if (left_battery.battery_level != new_left_battery_state.battery_level || | ||
| 127 | left_battery.is_charging != new_left_battery_state.is_charging || | ||
| 128 | left_battery.is_powered != new_left_battery_state.is_powered) { | ||
| 129 | has_changed = true; | ||
| 130 | left_battery = new_left_battery_state; | ||
| 131 | } | ||
| 132 | |||
| 133 | if (right_battery.battery_level != new_right_battery_state.battery_level || | ||
| 134 | right_battery.is_charging != new_right_battery_state.is_charging || | ||
| 135 | right_battery.is_powered != new_right_battery_state.is_powered) { | ||
| 136 | has_changed = true; | ||
| 137 | right_battery = new_right_battery_state; | ||
| 138 | } | ||
| 139 | |||
| 140 | return has_changed; | ||
| 141 | } | ||
| 142 | |||
| 143 | void NpadAbstractBatteryHandler::UpdateCoreBatteryState() { | ||
| 144 | if (ref_counter == 0) { | ||
| 145 | return; | ||
| 146 | } | ||
| 147 | if (!has_new_battery_data) { | ||
| 148 | return; | ||
| 149 | } | ||
| 150 | |||
| 151 | UpdateBatteryState(0); | ||
| 152 | } | ||
| 153 | |||
| 154 | void NpadAbstractBatteryHandler::InitializeBatteryState(u64 aruid) { | ||
| 155 | UpdateBatteryState(aruid); | ||
| 156 | } | ||
| 157 | |||
| 158 | bool NpadAbstractBatteryHandler::HasBattery() const { | ||
| 159 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 160 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 161 | |||
| 162 | for (std::size_t i = 0; i < count; i++) { | ||
| 163 | const auto* abstract_pad = abstract_pads[i]; | ||
| 164 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 165 | continue; | ||
| 166 | } | ||
| 167 | return abstract_pad->disabled_feature_set.has_fullkey_battery || | ||
| 168 | abstract_pad->disabled_feature_set.has_left_right_joy_battery; | ||
| 169 | } | ||
| 170 | |||
| 171 | return false; | ||
| 172 | } | ||
| 173 | |||
| 174 | void NpadAbstractBatteryHandler::HasLeftRightBattery(bool& has_left, bool& has_right) const { | ||
| 175 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 176 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 177 | |||
| 178 | has_left = false; | ||
| 179 | has_right = false; | ||
| 180 | |||
| 181 | for (std::size_t i = 0; i < count; i++) { | ||
| 182 | const auto* abstract_pad = abstract_pads[i]; | ||
| 183 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 184 | continue; | ||
| 185 | } | ||
| 186 | if (!abstract_pad->disabled_feature_set.has_fullkey_battery && | ||
| 187 | !abstract_pad->disabled_feature_set.has_left_right_joy_battery) { | ||
| 188 | continue; | ||
| 189 | } | ||
| 190 | has_left = abstract_pad->assignment_style.is_external_left_assigned || | ||
| 191 | abstract_pad->assignment_style.is_handheld_left_assigned; | ||
| 192 | has_right = abstract_pad->assignment_style.is_external_right_assigned || | ||
| 193 | abstract_pad->assignment_style.is_handheld_right_assigned; | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h new file mode 100644 index 000000000..85ac5eb72 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | struct AppletResourceHolder; | ||
| 12 | class NpadAbstractedPadHolder; | ||
| 13 | class NpadAbstractPropertiesHandler; | ||
| 14 | |||
| 15 | /// Handles Npad request from HID interfaces | ||
| 16 | class NpadAbstractBatteryHandler final { | ||
| 17 | public: | ||
| 18 | explicit NpadAbstractBatteryHandler(); | ||
| 19 | ~NpadAbstractBatteryHandler(); | ||
| 20 | |||
| 21 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 22 | void SetAppletResource(AppletResourceHolder* applet_resource); | ||
| 23 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 24 | |||
| 25 | Result IncrementRefCounter(); | ||
| 26 | Result DecrementRefCounter(); | ||
| 27 | |||
| 28 | Result UpdateBatteryState(u64 aruid); | ||
| 29 | void UpdateBatteryState(); | ||
| 30 | bool GetNewBatteryState(); | ||
| 31 | void UpdateCoreBatteryState(); | ||
| 32 | void InitializeBatteryState(u64 aruid); | ||
| 33 | |||
| 34 | bool HasBattery() const; | ||
| 35 | void HasLeftRightBattery(bool& has_left, bool& has_right) const; | ||
| 36 | |||
| 37 | private: | ||
| 38 | AppletResourceHolder* applet_resource_holder{nullptr}; | ||
| 39 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 40 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 41 | |||
| 42 | s32 ref_counter{}; | ||
| 43 | Core::HID::NpadPowerInfo dual_battery{}; | ||
| 44 | Core::HID::NpadPowerInfo left_battery{}; | ||
| 45 | Core::HID::NpadPowerInfo right_battery{}; | ||
| 46 | bool has_new_battery_data{}; | ||
| 47 | }; | ||
| 48 | |||
| 49 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp new file mode 100644 index 000000000..587169433 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp | |||
| @@ -0,0 +1,199 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/hid_util.h" | ||
| 6 | #include "hid_core/resources/abstracted_pad/abstract_button_handler.h" | ||
| 7 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 8 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 9 | #include "hid_core/resources/applet_resource.h" | ||
| 10 | #include "hid_core/resources/npad/npad_resource.h" | ||
| 11 | #include "hid_core/resources/npad/npad_types.h" | ||
| 12 | #include "hid_core/resources/shared_memory_format.h" | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | |||
| 16 | NpadAbstractButtonHandler::NpadAbstractButtonHandler() {} | ||
| 17 | |||
| 18 | NpadAbstractButtonHandler::~NpadAbstractButtonHandler() = default; | ||
| 19 | |||
| 20 | void NpadAbstractButtonHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 21 | abstract_pad_holder = holder; | ||
| 22 | } | ||
| 23 | |||
| 24 | void NpadAbstractButtonHandler::SetAppletResource(AppletResourceHolder* applet_resource) { | ||
| 25 | applet_resource_holder = applet_resource; | ||
| 26 | } | ||
| 27 | |||
| 28 | void NpadAbstractButtonHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 29 | properties_handler = handler; | ||
| 30 | } | ||
| 31 | |||
| 32 | Result NpadAbstractButtonHandler::IncrementRefCounter() { | ||
| 33 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 34 | return ResultNpadHandlerOverflow; | ||
| 35 | } | ||
| 36 | ref_counter++; | ||
| 37 | return ResultSuccess; | ||
| 38 | } | ||
| 39 | |||
| 40 | Result NpadAbstractButtonHandler::DecrementRefCounter() { | ||
| 41 | if (ref_counter == 0) { | ||
| 42 | return ResultNpadHandlerNotInitialized; | ||
| 43 | } | ||
| 44 | ref_counter--; | ||
| 45 | return ResultSuccess; | ||
| 46 | } | ||
| 47 | |||
| 48 | Result NpadAbstractButtonHandler::UpdateAllButtonWithHomeProtection(u64 aruid) { | ||
| 49 | const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); | ||
| 50 | auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid); | ||
| 51 | |||
| 52 | if (data == nullptr) { | ||
| 53 | return ResultSuccess; | ||
| 54 | } | ||
| 55 | |||
| 56 | auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; | ||
| 57 | UpdateButtonLifo(npad_entry, aruid); | ||
| 58 | |||
| 59 | bool is_home_button_protection_enabled{}; | ||
| 60 | const auto result = applet_resource_holder->shared_npad_resource->GetHomeProtectionEnabled( | ||
| 61 | is_home_button_protection_enabled, aruid, npad_id); | ||
| 62 | |||
| 63 | if (result.IsError()) { | ||
| 64 | return ResultSuccess; | ||
| 65 | } | ||
| 66 | |||
| 67 | npad_entry.internal_state.button_properties.is_home_button_protection_enabled.Assign( | ||
| 68 | is_home_button_protection_enabled); | ||
| 69 | |||
| 70 | return ResultSuccess; | ||
| 71 | } | ||
| 72 | |||
| 73 | void NpadAbstractButtonHandler::UpdateAllButtonLifo() { | ||
| 74 | Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); | ||
| 75 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 76 | auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i); | ||
| 77 | auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; | ||
| 78 | UpdateButtonLifo(npad_entry, data->aruid); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | void NpadAbstractButtonHandler::UpdateCoreBatteryState() { | ||
| 83 | Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); | ||
| 84 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 85 | auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i); | ||
| 86 | auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; | ||
| 87 | UpdateButtonLifo(npad_entry, data->aruid); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | void NpadAbstractButtonHandler::UpdateButtonState(u64 aruid) { | ||
| 92 | Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); | ||
| 93 | auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid); | ||
| 94 | if (data == nullptr) { | ||
| 95 | return; | ||
| 96 | } | ||
| 97 | auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; | ||
| 98 | UpdateButtonLifo(npad_entry, aruid); | ||
| 99 | } | ||
| 100 | |||
| 101 | Result NpadAbstractButtonHandler::SetHomeProtection(bool is_enabled, u64 aruid) { | ||
| 102 | const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); | ||
| 103 | auto result = applet_resource_holder->shared_npad_resource->SetHomeProtectionEnabled( | ||
| 104 | aruid, npad_id, is_enabled); | ||
| 105 | if (result.IsError()) { | ||
| 106 | return result; | ||
| 107 | } | ||
| 108 | |||
| 109 | auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid); | ||
| 110 | if (data == nullptr) { | ||
| 111 | return ResultSuccess; | ||
| 112 | } | ||
| 113 | |||
| 114 | bool is_home_protection_enabled{}; | ||
| 115 | result = applet_resource_holder->shared_npad_resource->GetHomeProtectionEnabled( | ||
| 116 | is_home_protection_enabled, aruid, npad_id); | ||
| 117 | if (result.IsError()) { | ||
| 118 | return ResultSuccess; | ||
| 119 | } | ||
| 120 | |||
| 121 | auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; | ||
| 122 | npad_entry.internal_state.button_properties.is_home_button_protection_enabled.Assign( | ||
| 123 | is_home_protection_enabled); | ||
| 124 | return ResultSuccess; | ||
| 125 | } | ||
| 126 | |||
| 127 | bool NpadAbstractButtonHandler::IsButtonPressedOnConsoleMode() { | ||
| 128 | return is_button_pressed_on_console_mode; | ||
| 129 | } | ||
| 130 | |||
| 131 | void NpadAbstractButtonHandler::EnableCenterClamp() { | ||
| 132 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 133 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 134 | |||
| 135 | for (std::size_t i = 0; i < count; i++) { | ||
| 136 | auto* abstract_pad = abstract_pads[i]; | ||
| 137 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 138 | continue; | ||
| 139 | } | ||
| 140 | abstract_pad->internal_flags.use_center_clamp.Assign(true); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | void NpadAbstractButtonHandler::UpdateButtonLifo(NpadSharedMemoryEntry& shared_memory, u64 aruid) { | ||
| 145 | auto* npad_resource = applet_resource_holder->shared_npad_resource; | ||
| 146 | Core::HID::NpadStyleTag style_tag = {properties_handler->GetStyleSet(aruid)}; | ||
| 147 | style_tag.system_ext.Assign(npad_resource->GetActiveData()->GetNpadSystemExtState()); | ||
| 148 | |||
| 149 | UpdateNpadFullkeyLifo(style_tag, 0, aruid, shared_memory); | ||
| 150 | UpdateHandheldLifo(style_tag, 1, aruid, shared_memory); | ||
| 151 | UpdateJoyconDualLifo(style_tag, 2, aruid, shared_memory); | ||
| 152 | UpdateJoyconLeftLifo(style_tag, 3, aruid, shared_memory); | ||
| 153 | UpdateJoyconRightLifo(style_tag, 4, aruid, shared_memory); | ||
| 154 | UpdatePalmaLifo(style_tag, 5, aruid, shared_memory); | ||
| 155 | UpdateSystemExtLifo(style_tag, 6, aruid, shared_memory); | ||
| 156 | } | ||
| 157 | |||
| 158 | void NpadAbstractButtonHandler::UpdateNpadFullkeyLifo(Core::HID::NpadStyleTag style_tag, | ||
| 159 | int style_index, u64 aruid, | ||
| 160 | NpadSharedMemoryEntry& shared_memory) { | ||
| 161 | // TODO | ||
| 162 | } | ||
| 163 | |||
| 164 | void NpadAbstractButtonHandler::UpdateHandheldLifo(Core::HID::NpadStyleTag style_tag, | ||
| 165 | int style_index, u64 aruid, | ||
| 166 | NpadSharedMemoryEntry& shared_memory) { | ||
| 167 | // TODO | ||
| 168 | } | ||
| 169 | |||
| 170 | void NpadAbstractButtonHandler::UpdateJoyconDualLifo(Core::HID::NpadStyleTag style_tag, | ||
| 171 | int style_index, u64 aruid, | ||
| 172 | NpadSharedMemoryEntry& shared_memory) { | ||
| 173 | // TODO | ||
| 174 | } | ||
| 175 | |||
| 176 | void NpadAbstractButtonHandler::UpdateJoyconLeftLifo(Core::HID::NpadStyleTag style_tag, | ||
| 177 | int style_index, u64 aruid, | ||
| 178 | NpadSharedMemoryEntry& shared_memory) { | ||
| 179 | // TODO | ||
| 180 | } | ||
| 181 | |||
| 182 | void NpadAbstractButtonHandler::UpdateJoyconRightLifo(Core::HID::NpadStyleTag style_tag, | ||
| 183 | int style_index, u64 aruid, | ||
| 184 | NpadSharedMemoryEntry& shared_memory) { | ||
| 185 | // TODO | ||
| 186 | } | ||
| 187 | |||
| 188 | void NpadAbstractButtonHandler::UpdateSystemExtLifo(Core::HID::NpadStyleTag style_tag, | ||
| 189 | int style_index, u64 aruid, | ||
| 190 | NpadSharedMemoryEntry& shared_memory) { | ||
| 191 | // TODO | ||
| 192 | } | ||
| 193 | |||
| 194 | void NpadAbstractButtonHandler::UpdatePalmaLifo(Core::HID::NpadStyleTag style_tag, int style_index, | ||
| 195 | u64 aruid, NpadSharedMemoryEntry& shared_memory) { | ||
| 196 | // TODO | ||
| 197 | } | ||
| 198 | |||
| 199 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.h b/src/hid_core/resources/abstracted_pad/abstract_button_handler.h new file mode 100644 index 000000000..01eafe96d --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.h | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | struct NpadSharedMemoryEntry; | ||
| 12 | |||
| 13 | struct AppletResourceHolder; | ||
| 14 | class NpadAbstractedPadHolder; | ||
| 15 | class NpadAbstractPropertiesHandler; | ||
| 16 | |||
| 17 | /// Handles Npad request from HID interfaces | ||
| 18 | class NpadAbstractButtonHandler final { | ||
| 19 | public: | ||
| 20 | explicit NpadAbstractButtonHandler(); | ||
| 21 | ~NpadAbstractButtonHandler(); | ||
| 22 | |||
| 23 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 24 | void SetAppletResource(AppletResourceHolder* applet_resource); | ||
| 25 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 26 | |||
| 27 | Result IncrementRefCounter(); | ||
| 28 | Result DecrementRefCounter(); | ||
| 29 | |||
| 30 | Result UpdateAllButtonWithHomeProtection(u64 aruid); | ||
| 31 | |||
| 32 | void UpdateAllButtonLifo(); | ||
| 33 | void UpdateCoreBatteryState(); | ||
| 34 | void UpdateButtonState(u64 aruid); | ||
| 35 | |||
| 36 | Result SetHomeProtection(bool is_enabled, u64 aruid); | ||
| 37 | bool IsButtonPressedOnConsoleMode(); | ||
| 38 | void EnableCenterClamp(); | ||
| 39 | |||
| 40 | void UpdateButtonLifo(NpadSharedMemoryEntry& shared_memory, u64 aruid); | ||
| 41 | |||
| 42 | void UpdateNpadFullkeyLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, | ||
| 43 | NpadSharedMemoryEntry& shared_memory); | ||
| 44 | void UpdateHandheldLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, | ||
| 45 | NpadSharedMemoryEntry& shared_memory); | ||
| 46 | void UpdateJoyconDualLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, | ||
| 47 | NpadSharedMemoryEntry& shared_memory); | ||
| 48 | void UpdateJoyconLeftLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, | ||
| 49 | NpadSharedMemoryEntry& shared_memory); | ||
| 50 | void UpdateJoyconRightLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, | ||
| 51 | NpadSharedMemoryEntry& shared_memory); | ||
| 52 | void UpdateSystemExtLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, | ||
| 53 | NpadSharedMemoryEntry& shared_memory); | ||
| 54 | void UpdatePalmaLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid, | ||
| 55 | NpadSharedMemoryEntry& shared_memory); | ||
| 56 | |||
| 57 | private: | ||
| 58 | struct GcTrigger { | ||
| 59 | float left; | ||
| 60 | float right; | ||
| 61 | }; | ||
| 62 | |||
| 63 | AppletResourceHolder* applet_resource_holder{nullptr}; | ||
| 64 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 65 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 66 | |||
| 67 | s32 ref_counter{}; | ||
| 68 | |||
| 69 | bool is_button_pressed_on_console_mode{}; | ||
| 70 | |||
| 71 | u64 gc_sampling_number{}; | ||
| 72 | GcTrigger gc_trigger_state{}; | ||
| 73 | }; | ||
| 74 | |||
| 75 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp new file mode 100644 index 000000000..d4e4181bf --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_event.h" | ||
| 5 | #include "core/hle/kernel/k_readable_event.h" | ||
| 6 | #include "hid_core/hid_result.h" | ||
| 7 | #include "hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h" | ||
| 8 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 9 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 10 | #include "hid_core/resources/npad/npad_types.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | NpadAbstractIrSensorHandler::NpadAbstractIrSensorHandler() {} | ||
| 15 | |||
| 16 | NpadAbstractIrSensorHandler::~NpadAbstractIrSensorHandler() = default; | ||
| 17 | |||
| 18 | void NpadAbstractIrSensorHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 19 | abstract_pad_holder = holder; | ||
| 20 | } | ||
| 21 | |||
| 22 | void NpadAbstractIrSensorHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 23 | properties_handler = handler; | ||
| 24 | } | ||
| 25 | |||
| 26 | Result NpadAbstractIrSensorHandler::IncrementRefCounter() { | ||
| 27 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 28 | return ResultNpadHandlerOverflow; | ||
| 29 | } | ||
| 30 | ref_counter++; | ||
| 31 | return ResultSuccess; | ||
| 32 | } | ||
| 33 | |||
| 34 | Result NpadAbstractIrSensorHandler::DecrementRefCounter() { | ||
| 35 | if (ref_counter == 0) { | ||
| 36 | return ResultNpadHandlerNotInitialized; | ||
| 37 | } | ||
| 38 | ref_counter--; | ||
| 39 | return ResultSuccess; | ||
| 40 | } | ||
| 41 | |||
| 42 | void NpadAbstractIrSensorHandler::UpdateIrSensorState() { | ||
| 43 | const auto previous_state = sensor_state; | ||
| 44 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 45 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 46 | |||
| 47 | if (count == 0) { | ||
| 48 | sensor_state = NpadIrSensorState::Disabled; | ||
| 49 | if (sensor_state == previous_state) { | ||
| 50 | return; | ||
| 51 | } | ||
| 52 | ir_sensor_event->Signal(); | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | bool is_found{}; | ||
| 57 | for (std::size_t i = 0; i < count; i++) { | ||
| 58 | auto* abstract_pad = abstract_pads[i]; | ||
| 59 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 60 | continue; | ||
| 61 | } | ||
| 62 | if (!abstract_pad->disabled_feature_set.has_bluetooth_address) { | ||
| 63 | continue; | ||
| 64 | } | ||
| 65 | is_found = true; | ||
| 66 | xcd_handle = abstract_pad->xcd_handle; | ||
| 67 | } | ||
| 68 | |||
| 69 | if (is_found) { | ||
| 70 | if (sensor_state == NpadIrSensorState::Active) { | ||
| 71 | return; | ||
| 72 | } | ||
| 73 | sensor_state = NpadIrSensorState::Available; | ||
| 74 | if (sensor_state == previous_state) { | ||
| 75 | return; | ||
| 76 | } | ||
| 77 | ir_sensor_event->Signal(); | ||
| 78 | return; | ||
| 79 | } | ||
| 80 | |||
| 81 | sensor_state = NpadIrSensorState::Unavailable; | ||
| 82 | if (sensor_state == previous_state) { | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 | ir_sensor_event->Signal(); | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | Result NpadAbstractIrSensorHandler::ActivateIrSensor(bool is_enabled) { | ||
| 91 | if (sensor_state == NpadIrSensorState::Unavailable) { | ||
| 92 | return ResultIrSensorIsNotReady; | ||
| 93 | } | ||
| 94 | if (is_enabled && sensor_state == NpadIrSensorState::Available) { | ||
| 95 | sensor_state = NpadIrSensorState::Active; | ||
| 96 | } else { | ||
| 97 | if (is_enabled) { | ||
| 98 | return ResultSuccess; | ||
| 99 | } | ||
| 100 | if (sensor_state != NpadIrSensorState::Active) { | ||
| 101 | return ResultSuccess; | ||
| 102 | } | ||
| 103 | sensor_state = NpadIrSensorState::Available; | ||
| 104 | } | ||
| 105 | ir_sensor_event->Signal(); | ||
| 106 | return ResultSuccess; | ||
| 107 | } | ||
| 108 | |||
| 109 | Result NpadAbstractIrSensorHandler::GetIrSensorEventHandle(Kernel::KReadableEvent** out_event) { | ||
| 110 | *out_event = &ir_sensor_event->GetReadableEvent(); | ||
| 111 | return ResultSuccess; | ||
| 112 | } | ||
| 113 | |||
| 114 | Result NpadAbstractIrSensorHandler::GetXcdHandleForNpadWithIrSensor(u64& handle) const { | ||
| 115 | if (sensor_state < NpadIrSensorState::Available) { | ||
| 116 | return ResultIrSensorIsNotReady; | ||
| 117 | } | ||
| 118 | handle = xcd_handle; | ||
| 119 | return ResultSuccess; | ||
| 120 | } | ||
| 121 | |||
| 122 | NpadIrSensorState NpadAbstractIrSensorHandler::GetSensorState() const { | ||
| 123 | return sensor_state; | ||
| 124 | } | ||
| 125 | |||
| 126 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h new file mode 100644 index 000000000..fe8e005af --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | class KEvent; | ||
| 12 | class KReadableEvent; | ||
| 13 | } // namespace Kernel | ||
| 14 | |||
| 15 | enum class NpadIrSensorState : u32 { | ||
| 16 | Disabled, | ||
| 17 | Unavailable, | ||
| 18 | Available, | ||
| 19 | Active, | ||
| 20 | }; | ||
| 21 | |||
| 22 | namespace Service::HID { | ||
| 23 | class NpadAbstractedPadHolder; | ||
| 24 | class NpadAbstractPropertiesHandler; | ||
| 25 | |||
| 26 | /// Handles Npad request from HID interfaces | ||
| 27 | class NpadAbstractIrSensorHandler final { | ||
| 28 | public: | ||
| 29 | explicit NpadAbstractIrSensorHandler(); | ||
| 30 | ~NpadAbstractIrSensorHandler(); | ||
| 31 | |||
| 32 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 33 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 34 | |||
| 35 | Result IncrementRefCounter(); | ||
| 36 | Result DecrementRefCounter(); | ||
| 37 | |||
| 38 | void UpdateIrSensorState(); | ||
| 39 | Result ActivateIrSensor(bool param_2); | ||
| 40 | |||
| 41 | Result GetIrSensorEventHandle(Kernel::KReadableEvent** out_event); | ||
| 42 | |||
| 43 | Result GetXcdHandleForNpadWithIrSensor(u64& handle) const; | ||
| 44 | |||
| 45 | NpadIrSensorState GetSensorState() const; | ||
| 46 | |||
| 47 | private: | ||
| 48 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 49 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 50 | |||
| 51 | s32 ref_counter{}; | ||
| 52 | Kernel::KEvent* ir_sensor_event{nullptr}; | ||
| 53 | u64 xcd_handle{}; | ||
| 54 | NpadIrSensorState sensor_state{}; | ||
| 55 | }; | ||
| 56 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp new file mode 100644 index 000000000..0b2bfe88d --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "hid_core/hid_result.h" | ||
| 6 | #include "hid_core/hid_util.h" | ||
| 7 | #include "hid_core/resources/abstracted_pad/abstract_led_handler.h" | ||
| 8 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 9 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 10 | #include "hid_core/resources/applet_resource.h" | ||
| 11 | #include "hid_core/resources/npad/npad_types.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | NpadAbstractLedHandler::NpadAbstractLedHandler() {} | ||
| 16 | |||
| 17 | NpadAbstractLedHandler::~NpadAbstractLedHandler() = default; | ||
| 18 | |||
| 19 | void NpadAbstractLedHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 20 | abstract_pad_holder = holder; | ||
| 21 | } | ||
| 22 | |||
| 23 | void NpadAbstractLedHandler::SetAppletResource(AppletResourceHolder* applet_resource) { | ||
| 24 | applet_resource_holder = applet_resource; | ||
| 25 | } | ||
| 26 | |||
| 27 | void NpadAbstractLedHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 28 | properties_handler = handler; | ||
| 29 | } | ||
| 30 | |||
| 31 | Result NpadAbstractLedHandler::IncrementRefCounter() { | ||
| 32 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 33 | return ResultNpadHandlerOverflow; | ||
| 34 | } | ||
| 35 | ref_counter++; | ||
| 36 | return ResultSuccess; | ||
| 37 | } | ||
| 38 | |||
| 39 | Result NpadAbstractLedHandler::DecrementRefCounter() { | ||
| 40 | if (ref_counter == 0) { | ||
| 41 | return ResultNpadHandlerNotInitialized; | ||
| 42 | } | ||
| 43 | ref_counter--; | ||
| 44 | return ResultSuccess; | ||
| 45 | } | ||
| 46 | |||
| 47 | void NpadAbstractLedHandler::SetNpadLedHandlerLedPattern() { | ||
| 48 | const auto npad_id = properties_handler->GetNpadId(); | ||
| 49 | |||
| 50 | switch (npad_id) { | ||
| 51 | case Core::HID::NpadIdType::Player1: | ||
| 52 | left_pattern = Core::HID::LedPattern{1, 0, 0, 0}; | ||
| 53 | break; | ||
| 54 | case Core::HID::NpadIdType::Player2: | ||
| 55 | left_pattern = Core::HID::LedPattern{1, 1, 0, 0}; | ||
| 56 | break; | ||
| 57 | case Core::HID::NpadIdType::Player3: | ||
| 58 | left_pattern = Core::HID::LedPattern{1, 1, 1, 0}; | ||
| 59 | break; | ||
| 60 | case Core::HID::NpadIdType::Player4: | ||
| 61 | left_pattern = Core::HID::LedPattern{1, 1, 1, 1}; | ||
| 62 | break; | ||
| 63 | case Core::HID::NpadIdType::Player5: | ||
| 64 | left_pattern = Core::HID::LedPattern{1, 0, 0, 1}; | ||
| 65 | break; | ||
| 66 | case Core::HID::NpadIdType::Player6: | ||
| 67 | left_pattern = Core::HID::LedPattern{1, 0, 1, 0}; | ||
| 68 | break; | ||
| 69 | case Core::HID::NpadIdType::Player7: | ||
| 70 | left_pattern = Core::HID::LedPattern{1, 0, 1, 1}; | ||
| 71 | break; | ||
| 72 | case Core::HID::NpadIdType::Player8: | ||
| 73 | left_pattern = Core::HID::LedPattern{0, 1, 1, 0}; | ||
| 74 | break; | ||
| 75 | case Core::HID::NpadIdType::Other: | ||
| 76 | case Core::HID::NpadIdType::Handheld: | ||
| 77 | left_pattern = Core::HID::LedPattern{0, 0, 0, 0}; | ||
| 78 | break; | ||
| 79 | default: | ||
| 80 | ASSERT_MSG(false, "Invalid npad id type"); | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | |||
| 84 | switch (npad_id) { | ||
| 85 | case Core::HID::NpadIdType::Player1: | ||
| 86 | right_pattern = Core::HID::LedPattern{0, 0, 0, 1}; | ||
| 87 | break; | ||
| 88 | case Core::HID::NpadIdType::Player2: | ||
| 89 | right_pattern = Core::HID::LedPattern{0, 1, 1, 1}; | ||
| 90 | break; | ||
| 91 | case Core::HID::NpadIdType::Player3: | ||
| 92 | right_pattern = Core::HID::LedPattern{0, 1, 1, 1}; | ||
| 93 | break; | ||
| 94 | case Core::HID::NpadIdType::Player4: | ||
| 95 | right_pattern = Core::HID::LedPattern{1, 1, 1, 1}; | ||
| 96 | break; | ||
| 97 | case Core::HID::NpadIdType::Player5: | ||
| 98 | right_pattern = Core::HID::LedPattern{1, 0, 0, 1}; | ||
| 99 | break; | ||
| 100 | case Core::HID::NpadIdType::Player6: | ||
| 101 | right_pattern = Core::HID::LedPattern{0, 1, 0, 1}; | ||
| 102 | break; | ||
| 103 | case Core::HID::NpadIdType::Player7: | ||
| 104 | right_pattern = Core::HID::LedPattern{1, 1, 0, 1}; | ||
| 105 | break; | ||
| 106 | case Core::HID::NpadIdType::Player8: | ||
| 107 | right_pattern = Core::HID::LedPattern{0, 1, 1, 0}; | ||
| 108 | break; | ||
| 109 | case Core::HID::NpadIdType::Other: | ||
| 110 | case Core::HID::NpadIdType::Handheld: | ||
| 111 | right_pattern = Core::HID::LedPattern{0, 0, 0, 0}; | ||
| 112 | break; | ||
| 113 | default: | ||
| 114 | ASSERT_MSG(false, "Invalid npad id type"); | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | void NpadAbstractLedHandler::SetLedBlinkingDevice(Core::HID::LedPattern pattern) { | ||
| 120 | led_blinking = pattern; | ||
| 121 | } | ||
| 122 | |||
| 123 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.h b/src/hid_core/resources/abstracted_pad/abstract_led_handler.h new file mode 100644 index 000000000..09528129b --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | struct AppletResourceHolder; | ||
| 12 | class NpadAbstractedPadHolder; | ||
| 13 | class NpadAbstractPropertiesHandler; | ||
| 14 | |||
| 15 | /// Handles Npad request from HID interfaces | ||
| 16 | class NpadAbstractLedHandler final { | ||
| 17 | public: | ||
| 18 | explicit NpadAbstractLedHandler(); | ||
| 19 | ~NpadAbstractLedHandler(); | ||
| 20 | |||
| 21 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 22 | void SetAppletResource(AppletResourceHolder* applet_resource); | ||
| 23 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 24 | |||
| 25 | Result IncrementRefCounter(); | ||
| 26 | Result DecrementRefCounter(); | ||
| 27 | |||
| 28 | void SetNpadLedHandlerLedPattern(); | ||
| 29 | |||
| 30 | void SetLedBlinkingDevice(Core::HID::LedPattern pattern); | ||
| 31 | |||
| 32 | private: | ||
| 33 | AppletResourceHolder* applet_resource_holder{nullptr}; | ||
| 34 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 35 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 36 | |||
| 37 | s32 ref_counter{}; | ||
| 38 | Core::HID::LedPattern led_blinking{0, 0, 0, 0}; | ||
| 39 | Core::HID::LedPattern left_pattern{0, 0, 0, 0}; | ||
| 40 | Core::HID::LedPattern right_pattern{0, 0, 0, 0}; | ||
| 41 | u64 led_interval{}; | ||
| 42 | }; | ||
| 43 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp new file mode 100644 index 000000000..6f35bd95c --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/abstracted_pad/abstract_mcu_handler.h" | ||
| 6 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 7 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 8 | #include "hid_core/resources/npad/npad_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | NpadAbstractMcuHandler::NpadAbstractMcuHandler() {} | ||
| 13 | |||
| 14 | NpadAbstractMcuHandler::~NpadAbstractMcuHandler() = default; | ||
| 15 | |||
| 16 | void NpadAbstractMcuHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 17 | abstract_pad_holder = holder; | ||
| 18 | } | ||
| 19 | |||
| 20 | void NpadAbstractMcuHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 21 | properties_handler = handler; | ||
| 22 | } | ||
| 23 | |||
| 24 | Result NpadAbstractMcuHandler::IncrementRefCounter() { | ||
| 25 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 26 | return ResultNpadHandlerOverflow; | ||
| 27 | } | ||
| 28 | ref_counter++; | ||
| 29 | return ResultSuccess; | ||
| 30 | } | ||
| 31 | |||
| 32 | Result NpadAbstractMcuHandler::DecrementRefCounter() { | ||
| 33 | if (ref_counter == 0) { | ||
| 34 | return ResultNpadHandlerNotInitialized; | ||
| 35 | } | ||
| 36 | ref_counter--; | ||
| 37 | return ResultSuccess; | ||
| 38 | } | ||
| 39 | |||
| 40 | void NpadAbstractMcuHandler::UpdateMcuState() { | ||
| 41 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 42 | const std::size_t count = properties_handler->GetAbstractedPads(abstract_pads); | ||
| 43 | |||
| 44 | if (count == 0) { | ||
| 45 | mcu_holder = {}; | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | for (std::size_t i = 0; i < count; i++) { | ||
| 50 | auto* abstract_pad = abstract_pads[i]; | ||
| 51 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 52 | continue; | ||
| 53 | } | ||
| 54 | if (!abstract_pad->disabled_feature_set.has_left_joy_rail_bus) { | ||
| 55 | if (!abstract_pad->disabled_feature_set.has_left_joy_six_axis_sensor && | ||
| 56 | !abstract_pad->disabled_feature_set.has_right_joy_six_axis_sensor) { | ||
| 57 | continue; | ||
| 58 | } | ||
| 59 | if (mcu_holder[1].state != NpadMcuState::Active) { | ||
| 60 | mcu_holder[1].state = NpadMcuState::Available; | ||
| 61 | } | ||
| 62 | mcu_holder[1].abstracted_pad = abstract_pad; | ||
| 63 | continue; | ||
| 64 | } | ||
| 65 | if (mcu_holder[0].state != NpadMcuState::Active) { | ||
| 66 | mcu_holder[0].state = NpadMcuState::Available; | ||
| 67 | } | ||
| 68 | mcu_holder[0].abstracted_pad = abstract_pad; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | Result NpadAbstractMcuHandler::GetAbstractedPad(IAbstractedPad** data, u32 mcu_index) { | ||
| 73 | if (mcu_holder[mcu_index].state == NpadMcuState::None || | ||
| 74 | mcu_holder[mcu_index].abstracted_pad == nullptr) { | ||
| 75 | return ResultMcuIsNotReady; | ||
| 76 | } | ||
| 77 | *data = mcu_holder[mcu_index].abstracted_pad; | ||
| 78 | return ResultSuccess; | ||
| 79 | } | ||
| 80 | |||
| 81 | NpadMcuState NpadAbstractMcuHandler::GetMcuState(u32 mcu_index) { | ||
| 82 | return mcu_holder[mcu_index].state; | ||
| 83 | } | ||
| 84 | |||
| 85 | Result NpadAbstractMcuHandler::SetMcuState(bool is_enabled, u32 mcu_index) { | ||
| 86 | NpadMcuState& state = mcu_holder[mcu_index].state; | ||
| 87 | |||
| 88 | if (state == NpadMcuState::None) { | ||
| 89 | return ResultMcuIsNotReady; | ||
| 90 | } | ||
| 91 | |||
| 92 | if ((is_enabled) && (state == NpadMcuState::Available)) { | ||
| 93 | state = NpadMcuState::Active; | ||
| 94 | return ResultSuccess; | ||
| 95 | } | ||
| 96 | |||
| 97 | if (is_enabled) { | ||
| 98 | return ResultSuccess; | ||
| 99 | } | ||
| 100 | if (state != NpadMcuState::Active) { | ||
| 101 | return ResultSuccess; | ||
| 102 | } | ||
| 103 | |||
| 104 | state = NpadMcuState::Available; | ||
| 105 | return ResultSuccess; | ||
| 106 | } | ||
| 107 | |||
| 108 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h new file mode 100644 index 000000000..9902dd03a --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | struct IAbstractedPad; | ||
| 12 | class NpadAbstractedPadHolder; | ||
| 13 | class NpadAbstractPropertiesHandler; | ||
| 14 | |||
| 15 | enum class NpadMcuState : u32 { | ||
| 16 | None, | ||
| 17 | Available, | ||
| 18 | Active, | ||
| 19 | }; | ||
| 20 | |||
| 21 | struct NpadMcuHolder { | ||
| 22 | NpadMcuState state; | ||
| 23 | INSERT_PADDING_BYTES(0x4); | ||
| 24 | IAbstractedPad* abstracted_pad; | ||
| 25 | }; | ||
| 26 | static_assert(sizeof(NpadMcuHolder) == 0x10, "NpadMcuHolder is an invalid size"); | ||
| 27 | |||
| 28 | /// Handles Npad request from HID interfaces | ||
| 29 | class NpadAbstractMcuHandler final { | ||
| 30 | public: | ||
| 31 | explicit NpadAbstractMcuHandler(); | ||
| 32 | ~NpadAbstractMcuHandler(); | ||
| 33 | |||
| 34 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 35 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 36 | |||
| 37 | Result IncrementRefCounter(); | ||
| 38 | Result DecrementRefCounter(); | ||
| 39 | |||
| 40 | void UpdateMcuState(); | ||
| 41 | Result GetAbstractedPad(IAbstractedPad** data, u32 mcu_index); | ||
| 42 | NpadMcuState GetMcuState(u32 mcu_index); | ||
| 43 | Result SetMcuState(bool is_enabled, u32 mcu_index); | ||
| 44 | |||
| 45 | private: | ||
| 46 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 47 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 48 | |||
| 49 | s32 ref_counter{}; | ||
| 50 | std::array<NpadMcuHolder, 2> mcu_holder{}; | ||
| 51 | }; | ||
| 52 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp new file mode 100644 index 000000000..bd9b79333 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_event.h" | ||
| 5 | #include "core/hle/kernel/k_readable_event.h" | ||
| 6 | #include "hid_core/hid_result.h" | ||
| 7 | #include "hid_core/resources/abstracted_pad/abstract_nfc_handler.h" | ||
| 8 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 9 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 10 | #include "hid_core/resources/npad/npad_types.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | NpadAbstractNfcHandler::NpadAbstractNfcHandler() {} | ||
| 15 | |||
| 16 | NpadAbstractNfcHandler::~NpadAbstractNfcHandler() = default; | ||
| 17 | |||
| 18 | void NpadAbstractNfcHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 19 | abstract_pad_holder = holder; | ||
| 20 | } | ||
| 21 | |||
| 22 | void NpadAbstractNfcHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 23 | properties_handler = handler; | ||
| 24 | } | ||
| 25 | |||
| 26 | Result NpadAbstractNfcHandler::IncrementRefCounter() { | ||
| 27 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 28 | return ResultNpadHandlerOverflow; | ||
| 29 | } | ||
| 30 | ref_counter++; | ||
| 31 | return ResultSuccess; | ||
| 32 | } | ||
| 33 | |||
| 34 | Result NpadAbstractNfcHandler::DecrementRefCounter() { | ||
| 35 | if (ref_counter == 0) { | ||
| 36 | return ResultNpadHandlerNotInitialized; | ||
| 37 | } | ||
| 38 | ref_counter--; | ||
| 39 | return ResultSuccess; | ||
| 40 | } | ||
| 41 | |||
| 42 | void NpadAbstractNfcHandler::UpdateNfcState() { | ||
| 43 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 44 | const std::size_t count = properties_handler->GetAbstractedPads(abstract_pads); | ||
| 45 | |||
| 46 | if (count == 0) { | ||
| 47 | if (sensor_state == NpadNfcState::Active) { | ||
| 48 | nfc_activate_event->Signal(); | ||
| 49 | } | ||
| 50 | if (sensor_state == NpadNfcState::Unavailable) { | ||
| 51 | return; | ||
| 52 | } | ||
| 53 | sensor_state = NpadNfcState::Unavailable; | ||
| 54 | input_event->Signal(); | ||
| 55 | return; | ||
| 56 | } | ||
| 57 | |||
| 58 | bool is_found{}; | ||
| 59 | for (std::size_t i = 0; i < count; i++) { | ||
| 60 | auto* abstract_pad = abstract_pads[i]; | ||
| 61 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 62 | continue; | ||
| 63 | } | ||
| 64 | if (!abstract_pad->disabled_feature_set.has_nfc) { | ||
| 65 | continue; | ||
| 66 | } | ||
| 67 | is_found = true; | ||
| 68 | xcd_handle = 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | if (is_found) { | ||
| 72 | if (sensor_state == NpadNfcState::Active) { | ||
| 73 | return; | ||
| 74 | } | ||
| 75 | if (sensor_state == NpadNfcState::Available) { | ||
| 76 | return; | ||
| 77 | } | ||
| 78 | sensor_state = NpadNfcState::Available; | ||
| 79 | input_event->Signal(); | ||
| 80 | return; | ||
| 81 | } | ||
| 82 | |||
| 83 | if (sensor_state == NpadNfcState::Active) { | ||
| 84 | nfc_activate_event->Signal(); | ||
| 85 | } | ||
| 86 | if (sensor_state == NpadNfcState::Unavailable) { | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | sensor_state = NpadNfcState::Unavailable; | ||
| 90 | input_event->Signal(); | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | bool NpadAbstractNfcHandler::HasNfcSensor() { | ||
| 95 | return sensor_state != NpadNfcState::Unavailable; | ||
| 96 | } | ||
| 97 | |||
| 98 | bool NpadAbstractNfcHandler::IsNfcActivated() { | ||
| 99 | return sensor_state == NpadNfcState::Active; | ||
| 100 | } | ||
| 101 | |||
| 102 | Result NpadAbstractNfcHandler::GetAcquireNfcActivateEventHandle( | ||
| 103 | Kernel::KReadableEvent** out_event) { | ||
| 104 | *out_event = &nfc_activate_event->GetReadableEvent(); | ||
| 105 | return ResultSuccess; | ||
| 106 | } | ||
| 107 | |||
| 108 | void NpadAbstractNfcHandler::SetInputEvent(Kernel::KEvent* event) { | ||
| 109 | input_event = event; | ||
| 110 | } | ||
| 111 | |||
| 112 | Result NpadAbstractNfcHandler::ActivateNfc(bool is_enabled) { | ||
| 113 | if (sensor_state == NpadNfcState::Active) { | ||
| 114 | return ResultNfcIsNotReady; | ||
| 115 | } | ||
| 116 | |||
| 117 | NpadNfcState new_state = NpadNfcState::Available; | ||
| 118 | if (is_enabled) { | ||
| 119 | new_state = NpadNfcState::Active; | ||
| 120 | } | ||
| 121 | if (sensor_state != new_state) { | ||
| 122 | sensor_state = new_state; | ||
| 123 | nfc_activate_event->Signal(); | ||
| 124 | } | ||
| 125 | return ResultSuccess; | ||
| 126 | } | ||
| 127 | |||
| 128 | Result NpadAbstractNfcHandler::GetXcdHandleWithNfc(u64& out_xcd_handle) const { | ||
| 129 | if (sensor_state == NpadNfcState::Unavailable) { | ||
| 130 | return ResultNfcIsNotReady; | ||
| 131 | } | ||
| 132 | if (xcd_handle == 0) { | ||
| 133 | return ResultNfcXcdHandleIsNotInitialized; | ||
| 134 | } | ||
| 135 | |||
| 136 | out_xcd_handle = xcd_handle; | ||
| 137 | return ResultSuccess; | ||
| 138 | } | ||
| 139 | |||
| 140 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h new file mode 100644 index 000000000..0702722a6 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | class KReadableEvent; | ||
| 12 | } | ||
| 13 | |||
| 14 | enum class NpadNfcState : u32 { | ||
| 15 | Unavailable, | ||
| 16 | Available, | ||
| 17 | Active, | ||
| 18 | }; | ||
| 19 | |||
| 20 | namespace Service::HID { | ||
| 21 | class NpadAbstractedPadHolder; | ||
| 22 | class NpadAbstractPropertiesHandler; | ||
| 23 | |||
| 24 | /// Handles Npad request from HID interfaces | ||
| 25 | class NpadAbstractNfcHandler final { | ||
| 26 | public: | ||
| 27 | explicit NpadAbstractNfcHandler(); | ||
| 28 | ~NpadAbstractNfcHandler(); | ||
| 29 | |||
| 30 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 31 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 32 | |||
| 33 | Result IncrementRefCounter(); | ||
| 34 | Result DecrementRefCounter(); | ||
| 35 | |||
| 36 | void UpdateNfcState(); | ||
| 37 | bool HasNfcSensor(); | ||
| 38 | bool IsNfcActivated(); | ||
| 39 | |||
| 40 | Result GetAcquireNfcActivateEventHandle(Kernel::KReadableEvent** out_event); | ||
| 41 | void SetInputEvent(Kernel::KEvent* event); | ||
| 42 | |||
| 43 | Result ActivateNfc(bool is_enabled); | ||
| 44 | |||
| 45 | Result GetXcdHandleWithNfc(u64& out_xcd_handle) const; | ||
| 46 | |||
| 47 | private: | ||
| 48 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 49 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 50 | |||
| 51 | s32 ref_counter{}; | ||
| 52 | Kernel::KEvent* nfc_activate_event{nullptr}; | ||
| 53 | Kernel::KEvent* input_event{nullptr}; | ||
| 54 | u64 xcd_handle{}; | ||
| 55 | NpadNfcState sensor_state{NpadNfcState::Unavailable}; | ||
| 56 | }; | ||
| 57 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp new file mode 100644 index 000000000..2c7691d7c --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/abstracted_pad/abstract_pad.h" | ||
| 6 | #include "hid_core/resources/applet_resource.h" | ||
| 7 | #include "hid_core/resources/npad/npad_types.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | AbstractPad::AbstractPad() {} | ||
| 12 | |||
| 13 | AbstractPad::~AbstractPad() = default; | ||
| 14 | |||
| 15 | void AbstractPad::SetExternals(AppletResourceHolder* applet_resource, | ||
| 16 | CaptureButtonResource* capture_button_resource, | ||
| 17 | HomeButtonResource* home_button_resource, | ||
| 18 | SixAxisResource* sixaxis_resource, PalmaResource* palma_resource, | ||
| 19 | VibrationHandler* vibration) { | ||
| 20 | applet_resource_holder = applet_resource; | ||
| 21 | |||
| 22 | properties_handler.SetAppletResource(applet_resource_holder); | ||
| 23 | properties_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 24 | |||
| 25 | led_handler.SetAppletResource(applet_resource_holder); | ||
| 26 | led_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 27 | led_handler.SetPropertiesHandler(&properties_handler); | ||
| 28 | |||
| 29 | ir_sensor_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 30 | ir_sensor_handler.SetPropertiesHandler(&properties_handler); | ||
| 31 | |||
| 32 | nfc_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 33 | nfc_handler.SetPropertiesHandler(&properties_handler); | ||
| 34 | |||
| 35 | mcu_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 36 | mcu_handler.SetPropertiesHandler(&properties_handler); | ||
| 37 | |||
| 38 | std::array<NpadVibrationDevice*, 2> vibration_devices{&vibration_left, &vibration_right}; | ||
| 39 | vibration_handler.SetAppletResource(applet_resource_holder); | ||
| 40 | vibration_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 41 | vibration_handler.SetPropertiesHandler(&properties_handler); | ||
| 42 | vibration_handler.SetN64Vibration(&vibration_n64); | ||
| 43 | vibration_handler.SetVibration(vibration_devices); | ||
| 44 | vibration_handler.SetGcVibration(&vibration_gc); | ||
| 45 | |||
| 46 | sixaxis_handler.SetAppletResource(applet_resource_holder); | ||
| 47 | sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 48 | sixaxis_handler.SetPropertiesHandler(&properties_handler); | ||
| 49 | sixaxis_handler.SetSixaxisResource(sixaxis_resource); | ||
| 50 | |||
| 51 | button_handler.SetAppletResource(applet_resource_holder); | ||
| 52 | button_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 53 | button_handler.SetPropertiesHandler(&properties_handler); | ||
| 54 | |||
| 55 | battery_handler.SetAppletResource(applet_resource_holder); | ||
| 56 | battery_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 57 | battery_handler.SetPropertiesHandler(&properties_handler); | ||
| 58 | |||
| 59 | palma_handler.SetAbstractPadHolder(&abstract_pad_holder); | ||
| 60 | palma_handler.SetPropertiesHandler(&properties_handler); | ||
| 61 | palma_handler.SetPalmaResource(palma_resource); | ||
| 62 | } | ||
| 63 | |||
| 64 | void AbstractPad::SetNpadId(Core::HID::NpadIdType npad_id) { | ||
| 65 | properties_handler.SetNpadId(npad_id); | ||
| 66 | } | ||
| 67 | |||
| 68 | Result AbstractPad::Activate() { | ||
| 69 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 70 | return ResultNpadHandlerOverflow; | ||
| 71 | } | ||
| 72 | |||
| 73 | if (ref_counter != 0) { | ||
| 74 | ref_counter++; | ||
| 75 | return ResultSuccess; | ||
| 76 | } | ||
| 77 | |||
| 78 | std::size_t stage = 0; | ||
| 79 | Result result = ResultSuccess; | ||
| 80 | |||
| 81 | if (result.IsSuccess()) { | ||
| 82 | stage++; | ||
| 83 | result = properties_handler.IncrementRefCounter(); | ||
| 84 | } | ||
| 85 | if (result.IsSuccess()) { | ||
| 86 | stage++; | ||
| 87 | result = led_handler.IncrementRefCounter(); | ||
| 88 | } | ||
| 89 | if (result.IsSuccess()) { | ||
| 90 | stage++; | ||
| 91 | result = ir_sensor_handler.IncrementRefCounter(); | ||
| 92 | } | ||
| 93 | if (result.IsSuccess()) { | ||
| 94 | stage++; | ||
| 95 | result = mcu_handler.IncrementRefCounter(); | ||
| 96 | } | ||
| 97 | if (result.IsSuccess()) { | ||
| 98 | stage++; | ||
| 99 | result = nfc_handler.IncrementRefCounter(); | ||
| 100 | } | ||
| 101 | if (result.IsSuccess()) { | ||
| 102 | stage++; | ||
| 103 | result = vibration_handler.IncrementRefCounter(); | ||
| 104 | } | ||
| 105 | if (result.IsSuccess()) { | ||
| 106 | stage++; | ||
| 107 | result = sixaxis_handler.IncrementRefCounter(); | ||
| 108 | } | ||
| 109 | if (result.IsSuccess()) { | ||
| 110 | stage++; | ||
| 111 | result = button_handler.IncrementRefCounter(); | ||
| 112 | } | ||
| 113 | if (result.IsSuccess()) { | ||
| 114 | stage++; | ||
| 115 | result = battery_handler.IncrementRefCounter(); | ||
| 116 | } | ||
| 117 | if (result.IsSuccess()) { | ||
| 118 | stage++; | ||
| 119 | result = palma_handler.IncrementRefCounter(); | ||
| 120 | } | ||
| 121 | |||
| 122 | if (result.IsSuccess()) { | ||
| 123 | ref_counter++; | ||
| 124 | return result; | ||
| 125 | } | ||
| 126 | |||
| 127 | if (stage > 9) { | ||
| 128 | battery_handler.DecrementRefCounter(); | ||
| 129 | } | ||
| 130 | if (stage > 8) { | ||
| 131 | button_handler.DecrementRefCounter(); | ||
| 132 | } | ||
| 133 | if (stage > 7) { | ||
| 134 | sixaxis_handler.DecrementRefCounter(); | ||
| 135 | } | ||
| 136 | if (stage > 6) { | ||
| 137 | vibration_handler.DecrementRefCounter(); | ||
| 138 | } | ||
| 139 | if (stage > 5) { | ||
| 140 | nfc_handler.DecrementRefCounter(); | ||
| 141 | } | ||
| 142 | if (stage > 4) { | ||
| 143 | mcu_handler.DecrementRefCounter(); | ||
| 144 | } | ||
| 145 | if (stage > 3) { | ||
| 146 | ir_sensor_handler.DecrementRefCounter(); | ||
| 147 | } | ||
| 148 | if (stage > 2) { | ||
| 149 | led_handler.DecrementRefCounter(); | ||
| 150 | } | ||
| 151 | if (stage > 1) { | ||
| 152 | properties_handler.DecrementRefCounter(); | ||
| 153 | } | ||
| 154 | return result; | ||
| 155 | } | ||
| 156 | |||
| 157 | Result AbstractPad::Deactivate() { | ||
| 158 | if (ref_counter == 0) { | ||
| 159 | return ResultNpadResourceNotInitialized; | ||
| 160 | } | ||
| 161 | |||
| 162 | ref_counter--; | ||
| 163 | battery_handler.DecrementRefCounter(); | ||
| 164 | button_handler.DecrementRefCounter(); | ||
| 165 | sixaxis_handler.DecrementRefCounter(); | ||
| 166 | vibration_handler.DecrementRefCounter(); | ||
| 167 | nfc_handler.DecrementRefCounter(); | ||
| 168 | ir_sensor_handler.DecrementRefCounter(); | ||
| 169 | mcu_handler.DecrementRefCounter(); | ||
| 170 | led_handler.DecrementRefCounter(); | ||
| 171 | properties_handler.DecrementRefCounter(); | ||
| 172 | palma_handler.DecrementRefCounter(); | ||
| 173 | |||
| 174 | return ResultSuccess; | ||
| 175 | } | ||
| 176 | |||
| 177 | Result AbstractPad::ActivateNpad(u64 aruid) { | ||
| 178 | Result result = ResultSuccess; | ||
| 179 | if (result.IsSuccess()) { | ||
| 180 | result = properties_handler.ActivateNpadUnknown0x88(aruid); | ||
| 181 | } | ||
| 182 | if (result.IsSuccess()) { | ||
| 183 | result = sixaxis_handler.UpdateSixAxisState2(aruid); | ||
| 184 | } | ||
| 185 | if (result.IsSuccess()) { | ||
| 186 | result = battery_handler.UpdateBatteryState(aruid); | ||
| 187 | } | ||
| 188 | return result; | ||
| 189 | } | ||
| 190 | |||
| 191 | NpadAbstractedPadHolder* AbstractPad::GetAbstractedPadHolder() { | ||
| 192 | return &abstract_pad_holder; | ||
| 193 | } | ||
| 194 | |||
| 195 | NpadAbstractPropertiesHandler* AbstractPad::GetAbstractPropertiesHandler() { | ||
| 196 | return &properties_handler; | ||
| 197 | } | ||
| 198 | |||
| 199 | NpadAbstractLedHandler* AbstractPad::GetAbstractLedHandler() { | ||
| 200 | return &led_handler; | ||
| 201 | } | ||
| 202 | |||
| 203 | NpadAbstractIrSensorHandler* AbstractPad::GetAbstractIrSensorHandler() { | ||
| 204 | return &ir_sensor_handler; | ||
| 205 | } | ||
| 206 | |||
| 207 | NpadAbstractMcuHandler* AbstractPad::GetAbstractMcuHandler() { | ||
| 208 | return &mcu_handler; | ||
| 209 | } | ||
| 210 | |||
| 211 | NpadAbstractNfcHandler* AbstractPad::GetAbstractNfcHandler() { | ||
| 212 | return &nfc_handler; | ||
| 213 | } | ||
| 214 | |||
| 215 | NpadAbstractVibrationHandler* AbstractPad::GetAbstractVibrationHandler() { | ||
| 216 | return &vibration_handler; | ||
| 217 | } | ||
| 218 | |||
| 219 | NpadAbstractSixAxisHandler* AbstractPad::GetAbstractSixAxisHandler() { | ||
| 220 | return &sixaxis_handler; | ||
| 221 | } | ||
| 222 | |||
| 223 | NpadAbstractButtonHandler* AbstractPad::GetAbstractButtonHandler() { | ||
| 224 | return &button_handler; | ||
| 225 | } | ||
| 226 | |||
| 227 | NpadAbstractBatteryHandler* AbstractPad::GetAbstractBatteryHandler() { | ||
| 228 | return &battery_handler; | ||
| 229 | } | ||
| 230 | |||
| 231 | NpadN64VibrationDevice* AbstractPad::GetN64VibrationDevice() { | ||
| 232 | return &vibration_n64; | ||
| 233 | } | ||
| 234 | |||
| 235 | NpadVibrationDevice* AbstractPad::GetVibrationDevice(Core::HID::DeviceIndex device_index) { | ||
| 236 | if (device_index == Core::HID::DeviceIndex::Right) { | ||
| 237 | return &vibration_right; | ||
| 238 | } | ||
| 239 | return &vibration_left; | ||
| 240 | } | ||
| 241 | |||
| 242 | void AbstractPad::GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list) { | ||
| 243 | list.emplace_back(&vibration_left); | ||
| 244 | list.emplace_back(&vibration_right); | ||
| 245 | } | ||
| 246 | |||
| 247 | NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() { | ||
| 248 | return &vibration_gc; | ||
| 249 | } | ||
| 250 | |||
| 251 | Core::HID::NpadIdType AbstractPad::GetLastActiveNpad() { | ||
| 252 | return properties_handler.GetNpadId(); | ||
| 253 | } | ||
| 254 | |||
| 255 | void AbstractPad::UpdateInterfaceType() { | ||
| 256 | if (interface_type != properties_handler.GetInterfaceType()) { | ||
| 257 | Update(); | ||
| 258 | } | ||
| 259 | battery_handler.UpdateBatteryState(); | ||
| 260 | } | ||
| 261 | |||
| 262 | void AbstractPad::Update() { | ||
| 263 | properties_handler.UpdateDeviceType(); | ||
| 264 | led_handler.SetNpadLedHandlerLedPattern(); | ||
| 265 | vibration_handler.UpdateVibrationState(); | ||
| 266 | sixaxis_handler.UpdateSixAxisState(); | ||
| 267 | nfc_handler.UpdateNfcState(); | ||
| 268 | ir_sensor_handler.UpdateIrSensorState(); | ||
| 269 | mcu_handler.UpdateMcuState(); | ||
| 270 | palma_handler.UpdatePalmaState(); | ||
| 271 | battery_handler.UpdateBatteryState(); | ||
| 272 | button_handler.EnableCenterClamp(); | ||
| 273 | |||
| 274 | interface_type = properties_handler.GetInterfaceType(); | ||
| 275 | |||
| 276 | std::scoped_lock lock{*applet_resource_holder->shared_mutex}; | ||
| 277 | properties_handler.UpdateAllDeviceProperties(); | ||
| 278 | battery_handler.UpdateCoreBatteryState(); | ||
| 279 | button_handler.UpdateCoreBatteryState(); | ||
| 280 | } | ||
| 281 | |||
| 282 | void AbstractPad::UpdatePadState() { | ||
| 283 | button_handler.UpdateAllButtonLifo(); | ||
| 284 | sixaxis_handler.UpdateSixAxisState(); | ||
| 285 | battery_handler.UpdateCoreBatteryState(); | ||
| 286 | } | ||
| 287 | |||
| 288 | void AbstractPad::EnableAppletToGetInput(u64 aruid) { | ||
| 289 | button_handler.UpdateButtonState(aruid); | ||
| 290 | sixaxis_handler.UpdateSixAxisState(aruid); | ||
| 291 | battery_handler.UpdateBatteryState(aruid); | ||
| 292 | } | ||
| 293 | |||
| 294 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.h b/src/hid_core/resources/abstracted_pad/abstract_pad.h new file mode 100644 index 000000000..cbdf84af7 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.h | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "hid_core/hid_types.h" | ||
| 12 | #include "hid_core/resources/applet_resource.h" | ||
| 13 | #include "hid_core/resources/npad/npad_types.h" | ||
| 14 | |||
| 15 | #include "hid_core/resources/abstracted_pad/abstract_battery_handler.h" | ||
| 16 | #include "hid_core/resources/abstracted_pad/abstract_button_handler.h" | ||
| 17 | #include "hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h" | ||
| 18 | #include "hid_core/resources/abstracted_pad/abstract_led_handler.h" | ||
| 19 | #include "hid_core/resources/abstracted_pad/abstract_mcu_handler.h" | ||
| 20 | #include "hid_core/resources/abstracted_pad/abstract_nfc_handler.h" | ||
| 21 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 22 | #include "hid_core/resources/abstracted_pad/abstract_palma_handler.h" | ||
| 23 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 24 | #include "hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h" | ||
| 25 | #include "hid_core/resources/abstracted_pad/abstract_vibration_handler.h" | ||
| 26 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 27 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 28 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 29 | |||
| 30 | namespace Service::HID { | ||
| 31 | class AppletResource; | ||
| 32 | class SixAxisResource; | ||
| 33 | class PalmaResource; | ||
| 34 | class NPadResource; | ||
| 35 | class AbstractPad; | ||
| 36 | class NpadLastActiveHandler; | ||
| 37 | class NpadIrNfcHandler; | ||
| 38 | class UniquePads; | ||
| 39 | class NpadPalmaHandler; | ||
| 40 | class FirmwareResource; | ||
| 41 | class NpadVibration; | ||
| 42 | class NpadHighestBattery; | ||
| 43 | class NpadGcVibration; | ||
| 44 | |||
| 45 | class CaptureButtonResource; | ||
| 46 | class HomeButtonResource; | ||
| 47 | class VibrationHandler; | ||
| 48 | |||
| 49 | struct HandheldConfig; | ||
| 50 | |||
| 51 | /// Handles Npad request from HID interfaces | ||
| 52 | class AbstractPad final { | ||
| 53 | public: | ||
| 54 | explicit AbstractPad(); | ||
| 55 | ~AbstractPad(); | ||
| 56 | |||
| 57 | void SetExternals(AppletResourceHolder* applet_resource, | ||
| 58 | CaptureButtonResource* capture_button_resource, | ||
| 59 | HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, | ||
| 60 | PalmaResource* palma_resource, VibrationHandler* vibration); | ||
| 61 | void SetNpadId(Core::HID::NpadIdType npad_id); | ||
| 62 | |||
| 63 | Result Activate(); | ||
| 64 | Result Deactivate(); | ||
| 65 | |||
| 66 | Result ActivateNpad(u64 aruid); | ||
| 67 | |||
| 68 | NpadAbstractedPadHolder* GetAbstractedPadHolder(); | ||
| 69 | NpadAbstractPropertiesHandler* GetAbstractPropertiesHandler(); | ||
| 70 | NpadAbstractLedHandler* GetAbstractLedHandler(); | ||
| 71 | NpadAbstractIrSensorHandler* GetAbstractIrSensorHandler(); | ||
| 72 | NpadAbstractMcuHandler* GetAbstractMcuHandler(); | ||
| 73 | NpadAbstractNfcHandler* GetAbstractNfcHandler(); | ||
| 74 | NpadAbstractVibrationHandler* GetAbstractVibrationHandler(); | ||
| 75 | NpadAbstractSixAxisHandler* GetAbstractSixAxisHandler(); | ||
| 76 | NpadAbstractButtonHandler* GetAbstractButtonHandler(); | ||
| 77 | NpadAbstractBatteryHandler* GetAbstractBatteryHandler(); | ||
| 78 | |||
| 79 | NpadN64VibrationDevice* GetN64VibrationDevice(); | ||
| 80 | NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index); | ||
| 81 | void GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list); | ||
| 82 | NpadGcVibrationDevice* GetGCVibrationDevice(); | ||
| 83 | |||
| 84 | Core::HID::NpadIdType GetLastActiveNpad(); | ||
| 85 | void UpdateInterfaceType(); | ||
| 86 | void Update(); | ||
| 87 | |||
| 88 | void UpdatePadState(); | ||
| 89 | void EnableAppletToGetInput(u64 aruid); | ||
| 90 | |||
| 91 | private: | ||
| 92 | AppletResourceHolder* applet_resource_holder{nullptr}; | ||
| 93 | NpadAbstractedPadHolder abstract_pad_holder{}; | ||
| 94 | NpadAbstractPropertiesHandler properties_handler{}; | ||
| 95 | NpadAbstractLedHandler led_handler{}; | ||
| 96 | NpadAbstractIrSensorHandler ir_sensor_handler{}; | ||
| 97 | NpadAbstractNfcHandler nfc_handler{}; | ||
| 98 | NpadAbstractMcuHandler mcu_handler{}; | ||
| 99 | NpadAbstractVibrationHandler vibration_handler{}; | ||
| 100 | NpadAbstractSixAxisHandler sixaxis_handler{}; | ||
| 101 | NpadAbstractButtonHandler button_handler{}; | ||
| 102 | NpadAbstractBatteryHandler battery_handler{}; | ||
| 103 | NpadAbstractPalmaHandler palma_handler{}; | ||
| 104 | |||
| 105 | NpadN64VibrationDevice vibration_n64{}; | ||
| 106 | NpadVibrationDevice vibration_left{}; | ||
| 107 | NpadVibrationDevice vibration_right{}; | ||
| 108 | NpadGcVibrationDevice vibration_gc{}; | ||
| 109 | |||
| 110 | // SixAxisConfigHolder fullkey_config; | ||
| 111 | // SixAxisConfigHolder handheld_config; | ||
| 112 | // SixAxisConfigHolder dual_left_config; | ||
| 113 | // SixAxisConfigHolder dual_right_config; | ||
| 114 | // SixAxisConfigHolder left_config; | ||
| 115 | // SixAxisConfigHolder right_config; | ||
| 116 | |||
| 117 | s32 ref_counter{}; | ||
| 118 | Core::HID::NpadInterfaceType interface_type{Core::HID::NpadInterfaceType::None}; | ||
| 119 | }; | ||
| 120 | |||
| 121 | using FullAbstractPad = std::array<AbstractPad, MaxSupportedNpadIdTypes>; | ||
| 122 | |||
| 123 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp new file mode 100644 index 000000000..8334dc34f --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 6 | #include "hid_core/resources/npad/npad_types.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | Result NpadAbstractedPadHolder::RegisterAbstractPad(IAbstractedPad* abstracted_pad) { | ||
| 11 | if (list_size >= assignment_list.size()) { | ||
| 12 | return ResultNpadIsNotProController; | ||
| 13 | } | ||
| 14 | |||
| 15 | for (std::size_t i = 0; i < list_size; i++) { | ||
| 16 | if (assignment_list[i].device_type == abstracted_pad->device_type) { | ||
| 17 | return ResultNpadIsNotProController; | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | assignment_list[list_size] = { | ||
| 22 | .abstracted_pad = abstracted_pad, | ||
| 23 | .device_type = abstracted_pad->device_type, | ||
| 24 | .interface_type = abstracted_pad->interface_type, | ||
| 25 | .controller_id = abstracted_pad->controller_id, | ||
| 26 | }; | ||
| 27 | |||
| 28 | list_size++; | ||
| 29 | return ResultSuccess; | ||
| 30 | } | ||
| 31 | |||
| 32 | void NpadAbstractedPadHolder::RemoveAbstractPadByControllerId(u64 controller_id) { | ||
| 33 | if (list_size == 0) { | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | if (controller_id == 0) { | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | for (std::size_t i = 0; i < list_size; i++) { | ||
| 40 | if (assignment_list[i].controller_id != controller_id) { | ||
| 41 | continue; | ||
| 42 | } | ||
| 43 | for (std::size_t e = i + 1; e < list_size; e++) { | ||
| 44 | assignment_list[e - 1] = assignment_list[e]; | ||
| 45 | } | ||
| 46 | list_size--; | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | void NpadAbstractedPadHolder::DetachAbstractedPad() { | ||
| 52 | while (list_size > 0) { | ||
| 53 | for (std::size_t i = 1; i < list_size; i++) { | ||
| 54 | assignment_list[i - 1] = assignment_list[i]; | ||
| 55 | } | ||
| 56 | list_size--; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | u64 NpadAbstractedPadHolder::RemoveAbstractPadByAssignmentStyle( | ||
| 61 | Service::HID::AssignmentStyle assignment_style) { | ||
| 62 | for (std::size_t i = 0; i < list_size; i++) { | ||
| 63 | if ((assignment_style.raw & assignment_list[i].abstracted_pad->assignment_style.raw) == 0) { | ||
| 64 | continue; | ||
| 65 | } | ||
| 66 | for (std::size_t e = i + 1; e < list_size; e++) { | ||
| 67 | assignment_list[e - 1] = assignment_list[e]; | ||
| 68 | } | ||
| 69 | list_size--; | ||
| 70 | return list_size; | ||
| 71 | } | ||
| 72 | return list_size; | ||
| 73 | } | ||
| 74 | |||
| 75 | u32 NpadAbstractedPadHolder::GetAbstractedPads(std::span<IAbstractedPad*> list) const { | ||
| 76 | u32 num_elements = std::min(static_cast<u32>(list.size()), list_size); | ||
| 77 | for (std::size_t i = 0; i < num_elements; i++) { | ||
| 78 | list[i] = assignment_list[i].abstracted_pad; | ||
| 79 | } | ||
| 80 | return num_elements; | ||
| 81 | } | ||
| 82 | |||
| 83 | void NpadAbstractedPadHolder::SetAssignmentMode(const NpadJoyAssignmentMode& mode) { | ||
| 84 | assignment_mode = mode; | ||
| 85 | } | ||
| 86 | |||
| 87 | NpadJoyAssignmentMode NpadAbstractedPadHolder::GetAssignmentMode() const { | ||
| 88 | return assignment_mode; | ||
| 89 | } | ||
| 90 | |||
| 91 | std::size_t NpadAbstractedPadHolder::GetStyleIndexList( | ||
| 92 | std::span<Core::HID::NpadStyleIndex> list) const { | ||
| 93 | for (std::size_t i = 0; i < list_size; i++) { | ||
| 94 | list[i] = assignment_list[i].device_type; | ||
| 95 | } | ||
| 96 | return list_size; | ||
| 97 | } | ||
| 98 | |||
| 99 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad_holder.h b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.h new file mode 100644 index 000000000..fb7f472e8 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <mutex> | ||
| 8 | #include <span> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | #include "hid_core/hid_types.h" | ||
| 13 | #include "hid_core/resources/npad/npad_types.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | struct IAbstractedPad; | ||
| 17 | |||
| 18 | struct AbstractAssignmentHolder { | ||
| 19 | IAbstractedPad* abstracted_pad; | ||
| 20 | Core::HID::NpadStyleIndex device_type; | ||
| 21 | Core::HID::NpadInterfaceType interface_type; | ||
| 22 | INSERT_PADDING_BYTES(0x6); | ||
| 23 | u64 controller_id; | ||
| 24 | }; | ||
| 25 | static_assert(sizeof(AbstractAssignmentHolder) == 0x18, | ||
| 26 | "AbstractAssignmentHolder is an invalid size"); | ||
| 27 | |||
| 28 | /// This is nn::hid::server::NpadAbstractedPadHolder | ||
| 29 | class NpadAbstractedPadHolder final { | ||
| 30 | public: | ||
| 31 | Result RegisterAbstractPad(IAbstractedPad* abstracted_pad); | ||
| 32 | void RemoveAbstractPadByControllerId(u64 controller_id); | ||
| 33 | void DetachAbstractedPad(); | ||
| 34 | u64 RemoveAbstractPadByAssignmentStyle(Service::HID::AssignmentStyle assignment_style); | ||
| 35 | u32 GetAbstractedPads(std::span<IAbstractedPad*> list) const; | ||
| 36 | |||
| 37 | void SetAssignmentMode(const NpadJoyAssignmentMode& mode); | ||
| 38 | NpadJoyAssignmentMode GetAssignmentMode() const; | ||
| 39 | |||
| 40 | std::size_t GetStyleIndexList(std::span<Core::HID::NpadStyleIndex> list) const; | ||
| 41 | |||
| 42 | private: | ||
| 43 | std::array<AbstractAssignmentHolder, 5> assignment_list{}; | ||
| 44 | u32 list_size{}; | ||
| 45 | NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual}; | ||
| 46 | }; | ||
| 47 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp new file mode 100644 index 000000000..04d276d61 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/abstracted_pad/abstract_palma_handler.h" | ||
| 6 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | NpadAbstractPalmaHandler::NpadAbstractPalmaHandler() {} | ||
| 11 | |||
| 12 | NpadAbstractPalmaHandler::~NpadAbstractPalmaHandler() = default; | ||
| 13 | |||
| 14 | void NpadAbstractPalmaHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 15 | abstract_pad_holder = holder; | ||
| 16 | } | ||
| 17 | |||
| 18 | void NpadAbstractPalmaHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 19 | properties_handler = handler; | ||
| 20 | return; | ||
| 21 | } | ||
| 22 | |||
| 23 | void NpadAbstractPalmaHandler::SetPalmaResource(PalmaResource* resource) { | ||
| 24 | palma_resource = resource; | ||
| 25 | } | ||
| 26 | |||
| 27 | Result NpadAbstractPalmaHandler::IncrementRefCounter() { | ||
| 28 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 29 | return ResultNpadHandlerOverflow; | ||
| 30 | } | ||
| 31 | ref_counter++; | ||
| 32 | return ResultSuccess; | ||
| 33 | } | ||
| 34 | |||
| 35 | Result NpadAbstractPalmaHandler::DecrementRefCounter() { | ||
| 36 | if (ref_counter == 0) { | ||
| 37 | return ResultNpadHandlerNotInitialized; | ||
| 38 | } | ||
| 39 | ref_counter--; | ||
| 40 | return ResultSuccess; | ||
| 41 | } | ||
| 42 | |||
| 43 | void NpadAbstractPalmaHandler::UpdatePalmaState() { | ||
| 44 | // TODO | ||
| 45 | } | ||
| 46 | |||
| 47 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h new file mode 100644 index 000000000..fbd2e67e5 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | class NpadAbstractedPadHolder; | ||
| 12 | class NpadAbstractPropertiesHandler; | ||
| 13 | class PalmaResource; | ||
| 14 | |||
| 15 | class NpadAbstractPalmaHandler final { | ||
| 16 | public: | ||
| 17 | explicit NpadAbstractPalmaHandler(); | ||
| 18 | ~NpadAbstractPalmaHandler(); | ||
| 19 | |||
| 20 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 21 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 22 | void SetPalmaResource(PalmaResource* resource); | ||
| 23 | |||
| 24 | Result IncrementRefCounter(); | ||
| 25 | Result DecrementRefCounter(); | ||
| 26 | |||
| 27 | void UpdatePalmaState(); | ||
| 28 | |||
| 29 | private: | ||
| 30 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 31 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 32 | PalmaResource* palma_resource{nullptr}; | ||
| 33 | |||
| 34 | s32 ref_counter{}; | ||
| 35 | }; | ||
| 36 | |||
| 37 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp new file mode 100644 index 000000000..4897a2784 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp | |||
| @@ -0,0 +1,322 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_util.h" | ||
| 5 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 6 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 7 | #include "hid_core/resources/applet_resource.h" | ||
| 8 | #include "hid_core/resources/npad/npad_resource.h" | ||
| 9 | #include "hid_core/resources/npad/npad_types.h" | ||
| 10 | #include "hid_core/resources/shared_memory_format.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | NpadAbstractPropertiesHandler::NpadAbstractPropertiesHandler() {} | ||
| 15 | |||
| 16 | NpadAbstractPropertiesHandler::~NpadAbstractPropertiesHandler() = default; | ||
| 17 | |||
| 18 | void NpadAbstractPropertiesHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 19 | abstract_pad_holder = holder; | ||
| 20 | return; | ||
| 21 | } | ||
| 22 | |||
| 23 | void NpadAbstractPropertiesHandler::SetAppletResource(AppletResourceHolder* applet_resource) { | ||
| 24 | applet_resource_holder = applet_resource; | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | |||
| 28 | void NpadAbstractPropertiesHandler::SetNpadId(Core::HID::NpadIdType npad_id) { | ||
| 29 | if (!IsNpadIdValid(npad_id)) { | ||
| 30 | ASSERT_MSG(false, "Invalid npad id"); | ||
| 31 | } | ||
| 32 | |||
| 33 | npad_id_type = npad_id; | ||
| 34 | } | ||
| 35 | |||
| 36 | Core::HID::NpadIdType NpadAbstractPropertiesHandler::GetNpadId() const { | ||
| 37 | return npad_id_type; | ||
| 38 | } | ||
| 39 | |||
| 40 | Result NpadAbstractPropertiesHandler::IncrementRefCounter() { | ||
| 41 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 42 | return ResultNpadHandlerOverflow; | ||
| 43 | } | ||
| 44 | |||
| 45 | if (ref_counter != 0) { | ||
| 46 | ref_counter++; | ||
| 47 | return ResultSuccess; | ||
| 48 | } | ||
| 49 | |||
| 50 | const auto npad_index = NpadIdTypeToIndex(npad_id_type); | ||
| 51 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 52 | auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index); | ||
| 53 | auto& internal_state = | ||
| 54 | data->shared_memory_format->npad.npad_entry[npad_index].internal_state; | ||
| 55 | if (!data->flag.is_assigned) { | ||
| 56 | continue; | ||
| 57 | } | ||
| 58 | internal_state.fullkey_lifo.buffer_count = 0; | ||
| 59 | internal_state.handheld_lifo.buffer_count = 0; | ||
| 60 | internal_state.joy_dual_lifo.buffer_count = 0; | ||
| 61 | internal_state.joy_left_lifo.buffer_count = 0; | ||
| 62 | internal_state.joy_right_lifo.buffer_count = 0; | ||
| 63 | internal_state.palma_lifo.buffer_count = 0; | ||
| 64 | internal_state.system_ext_lifo.buffer_count = 0; | ||
| 65 | internal_state.gc_trigger_lifo.buffer_count = 0; | ||
| 66 | internal_state.sixaxis_fullkey_lifo.lifo.buffer_count = 0; | ||
| 67 | internal_state.sixaxis_handheld_lifo.lifo.buffer_count = 0; | ||
| 68 | internal_state.sixaxis_dual_left_lifo.lifo.buffer_count = 0; | ||
| 69 | internal_state.sixaxis_dual_right_lifo.lifo.buffer_count = 0; | ||
| 70 | internal_state.sixaxis_left_lifo.lifo.buffer_count = 0; | ||
| 71 | internal_state.sixaxis_right_lifo.lifo.buffer_count = 0; | ||
| 72 | |||
| 73 | internal_state.style_tag = {Core::HID::NpadStyleSet::None}; | ||
| 74 | internal_state.assignment_mode = NpadJoyAssignmentMode::Dual; | ||
| 75 | internal_state.joycon_color = {}; | ||
| 76 | internal_state.fullkey_color = {}; | ||
| 77 | |||
| 78 | internal_state.system_properties.raw = 0; | ||
| 79 | internal_state.button_properties.raw = 0; | ||
| 80 | internal_state.device_type.raw = 0; | ||
| 81 | |||
| 82 | internal_state.battery_level_dual = Core::HID::NpadBatteryLevel::Empty; | ||
| 83 | internal_state.battery_level_left = Core::HID::NpadBatteryLevel::Empty; | ||
| 84 | internal_state.battery_level_right = Core::HID::NpadBatteryLevel::Empty; | ||
| 85 | |||
| 86 | internal_state.applet_footer_type = AppletFooterUiType::None; | ||
| 87 | internal_state.applet_footer_attributes = {}; | ||
| 88 | internal_state.lark_type_l_and_main = {}; | ||
| 89 | internal_state.lark_type_r = {}; | ||
| 90 | |||
| 91 | internal_state.sixaxis_fullkey_properties.is_newly_assigned.Assign(true); | ||
| 92 | internal_state.sixaxis_handheld_properties.is_newly_assigned.Assign(true); | ||
| 93 | internal_state.sixaxis_dual_left_properties.is_newly_assigned.Assign(true); | ||
| 94 | internal_state.sixaxis_dual_right_properties.is_newly_assigned.Assign(true); | ||
| 95 | internal_state.sixaxis_left_properties.is_newly_assigned.Assign(true); | ||
| 96 | internal_state.sixaxis_right_properties.is_newly_assigned.Assign(true); | ||
| 97 | } | ||
| 98 | |||
| 99 | ref_counter++; | ||
| 100 | return ResultSuccess; | ||
| 101 | } | ||
| 102 | |||
| 103 | Result NpadAbstractPropertiesHandler::DecrementRefCounter() { | ||
| 104 | if (ref_counter == 0) { | ||
| 105 | return ResultNpadHandlerNotInitialized; | ||
| 106 | } | ||
| 107 | ref_counter--; | ||
| 108 | return ResultSuccess; | ||
| 109 | } | ||
| 110 | |||
| 111 | Result NpadAbstractPropertiesHandler::ActivateNpadUnknown0x88(u64 aruid) { | ||
| 112 | const auto npad_index = NpadIdTypeToIndex(npad_id_type); | ||
| 113 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 114 | auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index); | ||
| 115 | if (!data->flag.is_assigned || data->aruid != aruid) { | ||
| 116 | continue; | ||
| 117 | } | ||
| 118 | UpdateDeviceProperties(aruid, data->shared_memory_format->npad.npad_entry[npad_index]); | ||
| 119 | return ResultSuccess; | ||
| 120 | } | ||
| 121 | return ResultSuccess; | ||
| 122 | } | ||
| 123 | |||
| 124 | void NpadAbstractPropertiesHandler::UpdateDeviceType() { | ||
| 125 | // TODO | ||
| 126 | } | ||
| 127 | |||
| 128 | void NpadAbstractPropertiesHandler::UpdateDeviceColor() { | ||
| 129 | // TODO | ||
| 130 | } | ||
| 131 | |||
| 132 | void NpadAbstractPropertiesHandler::UpdateFooterAttributes() { | ||
| 133 | // TODO | ||
| 134 | } | ||
| 135 | |||
| 136 | void NpadAbstractPropertiesHandler::UpdateAllDeviceProperties() { | ||
| 137 | const auto npad_index = NpadIdTypeToIndex(npad_id_type); | ||
| 138 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 139 | auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index); | ||
| 140 | if (!data->flag.is_assigned) { | ||
| 141 | continue; | ||
| 142 | } | ||
| 143 | auto& npad_entry = data->shared_memory_format->npad.npad_entry[npad_index]; | ||
| 144 | UpdateDeviceProperties(data->aruid, npad_entry); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetFullkeyInterfaceType() { | ||
| 149 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 150 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 151 | |||
| 152 | for (std::size_t i = 0; i < count; i++) { | ||
| 153 | auto* abstract_pad = abstract_pads[i]; | ||
| 154 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 155 | continue; | ||
| 156 | } | ||
| 157 | if (abstract_pad->device_type != Core::HID::NpadStyleIndex::Fullkey) { | ||
| 158 | continue; | ||
| 159 | } | ||
| 160 | if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) { | ||
| 161 | // Abort | ||
| 162 | continue; | ||
| 163 | } | ||
| 164 | return abstract_pad->interface_type; | ||
| 165 | } | ||
| 166 | |||
| 167 | return Core::HID::NpadInterfaceType::None; | ||
| 168 | } | ||
| 169 | |||
| 170 | Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetInterfaceType() { | ||
| 171 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 172 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 173 | |||
| 174 | for (std::size_t i = 0; i < count; i++) { | ||
| 175 | auto* abstract_pad = abstract_pads[i]; | ||
| 176 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 177 | continue; | ||
| 178 | } | ||
| 179 | if (!abstract_pad->disabled_feature_set.has_identification_code) { | ||
| 180 | continue; | ||
| 181 | } | ||
| 182 | if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) { | ||
| 183 | // Abort | ||
| 184 | continue; | ||
| 185 | } | ||
| 186 | return abstract_pad->interface_type; | ||
| 187 | } | ||
| 188 | return Core::HID::NpadInterfaceType::None; | ||
| 189 | } | ||
| 190 | |||
| 191 | Core::HID::NpadStyleSet NpadAbstractPropertiesHandler::GetStyleSet(u64 aruid) { | ||
| 192 | // TODO | ||
| 193 | return Core::HID::NpadStyleSet::None; | ||
| 194 | } | ||
| 195 | |||
| 196 | std::size_t NpadAbstractPropertiesHandler::GetAbstractedPadsWithStyleTag( | ||
| 197 | std::span<IAbstractedPad*> list, Core::HID::NpadStyleTag style) { | ||
| 198 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 199 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 200 | |||
| 201 | if (count == 0) { | ||
| 202 | return count; | ||
| 203 | } | ||
| 204 | |||
| 205 | bool is_supported_style_set{}; | ||
| 206 | const auto result = applet_resource_holder->shared_npad_resource->IsSupportedNpadStyleSet( | ||
| 207 | is_supported_style_set, applet_resource_holder->applet_resource->GetActiveAruid()); | ||
| 208 | |||
| 209 | if (!is_supported_style_set || result.IsError()) { | ||
| 210 | for (std::size_t i = 0; i < count; i++) { | ||
| 211 | // TODO | ||
| 212 | } | ||
| 213 | return count; | ||
| 214 | } | ||
| 215 | |||
| 216 | std::size_t filtered_count{}; | ||
| 217 | for (std::size_t i = 0; i < count; i++) { | ||
| 218 | auto* abstract_pad = abstract_pads[i]; | ||
| 219 | const bool is_enabled = true; | ||
| 220 | if (is_enabled) { | ||
| 221 | list[filtered_count] = abstract_pad; | ||
| 222 | filtered_count++; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | return filtered_count; | ||
| 227 | } | ||
| 228 | |||
| 229 | std::size_t NpadAbstractPropertiesHandler::GetAbstractedPads(std::span<IAbstractedPad*> list) { | ||
| 230 | Core::HID::NpadStyleTag style{ | ||
| 231 | GetStyleSet(applet_resource_holder->applet_resource->GetActiveAruid())}; | ||
| 232 | return GetAbstractedPadsWithStyleTag(list, style); | ||
| 233 | } | ||
| 234 | |||
| 235 | AppletFooterUiType NpadAbstractPropertiesHandler::GetAppletFooterUiType() { | ||
| 236 | return applet_ui_type.footer; | ||
| 237 | } | ||
| 238 | |||
| 239 | AppletDetailedUiType NpadAbstractPropertiesHandler::GetAppletDetailedUiType() { | ||
| 240 | return applet_ui_type; | ||
| 241 | } | ||
| 242 | |||
| 243 | void NpadAbstractPropertiesHandler::UpdateDeviceProperties(u64 aruid, | ||
| 244 | NpadSharedMemoryEntry& internal_state) { | ||
| 245 | // TODO | ||
| 246 | } | ||
| 247 | |||
| 248 | Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetNpadInterfaceType() { | ||
| 249 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 250 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 251 | |||
| 252 | for (std::size_t i = 0; i < count; i++) { | ||
| 253 | auto* abstract_pad = abstract_pads[i]; | ||
| 254 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 255 | continue; | ||
| 256 | } | ||
| 257 | if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) { | ||
| 258 | // Abort | ||
| 259 | continue; | ||
| 260 | } | ||
| 261 | return abstract_pad->interface_type; | ||
| 262 | } | ||
| 263 | |||
| 264 | return Core::HID::NpadInterfaceType::None; | ||
| 265 | } | ||
| 266 | |||
| 267 | Result NpadAbstractPropertiesHandler::GetNpadFullKeyGripColor( | ||
| 268 | Core::HID::NpadColor& main_color, Core::HID::NpadColor& sub_color) const { | ||
| 269 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 270 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 271 | |||
| 272 | if (applet_ui_type.footer != AppletFooterUiType::SwitchProController) { | ||
| 273 | return ResultNpadIsNotProController; | ||
| 274 | } | ||
| 275 | |||
| 276 | for (std::size_t i = 0; i < count; i++) { | ||
| 277 | auto* abstract_pad = abstract_pads[i]; | ||
| 278 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 279 | continue; | ||
| 280 | } | ||
| 281 | return ResultSuccess; | ||
| 282 | } | ||
| 283 | |||
| 284 | return ResultNpadIsNotProController; | ||
| 285 | } | ||
| 286 | |||
| 287 | void NpadAbstractPropertiesHandler::GetNpadLeftRightInterfaceType( | ||
| 288 | Core::HID::NpadInterfaceType& out_left_interface, | ||
| 289 | Core::HID::NpadInterfaceType& out_right_interface) const { | ||
| 290 | out_left_interface = Core::HID::NpadInterfaceType::None; | ||
| 291 | out_right_interface = Core::HID::NpadInterfaceType::None; | ||
| 292 | |||
| 293 | std::array<IAbstractedPad*, 5> abstract_pads{}; | ||
| 294 | const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads); | ||
| 295 | |||
| 296 | for (std::size_t i = 0; i < count; i++) { | ||
| 297 | auto* abstract_pad = abstract_pads[i]; | ||
| 298 | if (!abstract_pad->internal_flags.is_connected) { | ||
| 299 | continue; | ||
| 300 | } | ||
| 301 | if (abstract_pad->assignment_style.is_external_left_assigned && | ||
| 302 | abstract_pad->assignment_style.is_handheld_left_assigned) { | ||
| 303 | if (abstract_pad->interface_type > Core::HID::NpadInterfaceType::Embedded) { | ||
| 304 | // Abort | ||
| 305 | continue; | ||
| 306 | } | ||
| 307 | out_left_interface = abstract_pad->interface_type; | ||
| 308 | continue; | ||
| 309 | } | ||
| 310 | if (abstract_pad->assignment_style.is_external_right_assigned && | ||
| 311 | abstract_pad->assignment_style.is_handheld_right_assigned) { | ||
| 312 | if (abstract_pad->interface_type > Core::HID::NpadInterfaceType::Embedded) { | ||
| 313 | // Abort | ||
| 314 | continue; | ||
| 315 | } | ||
| 316 | out_right_interface = abstract_pad->interface_type; | ||
| 317 | continue; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h new file mode 100644 index 000000000..fa6827899 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <span> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/result.h" | ||
| 10 | #include "hid_core/hid_types.h" | ||
| 11 | #include "hid_core/resources/npad/npad_types.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | struct NpadSharedMemoryEntry; | ||
| 15 | |||
| 16 | struct AppletResourceHolder; | ||
| 17 | class NpadAbstractedPadHolder; | ||
| 18 | |||
| 19 | struct ColorProperties { | ||
| 20 | ColorAttribute attribute; | ||
| 21 | Core::HID::NpadControllerColor color; | ||
| 22 | INSERT_PADDING_BYTES(0x4); | ||
| 23 | }; | ||
| 24 | |||
| 25 | /// Handles Npad request from HID interfaces | ||
| 26 | class NpadAbstractPropertiesHandler final { | ||
| 27 | public: | ||
| 28 | explicit NpadAbstractPropertiesHandler(); | ||
| 29 | ~NpadAbstractPropertiesHandler(); | ||
| 30 | |||
| 31 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 32 | void SetAppletResource(AppletResourceHolder* applet_resource); | ||
| 33 | void SetNpadId(Core::HID::NpadIdType npad_id); | ||
| 34 | |||
| 35 | Core::HID::NpadIdType GetNpadId() const; | ||
| 36 | |||
| 37 | Result IncrementRefCounter(); | ||
| 38 | Result DecrementRefCounter(); | ||
| 39 | |||
| 40 | Result ActivateNpadUnknown0x88(u64 aruid); | ||
| 41 | |||
| 42 | void UpdateDeviceType(); | ||
| 43 | void UpdateDeviceColor(); | ||
| 44 | void UpdateFooterAttributes(); | ||
| 45 | void UpdateAllDeviceProperties(); | ||
| 46 | |||
| 47 | Core::HID::NpadInterfaceType GetFullkeyInterfaceType(); | ||
| 48 | Core::HID::NpadInterfaceType GetInterfaceType(); | ||
| 49 | |||
| 50 | Core::HID::NpadStyleSet GetStyleSet(u64 aruid); | ||
| 51 | std::size_t GetAbstractedPadsWithStyleTag(std::span<IAbstractedPad*> list, | ||
| 52 | Core::HID::NpadStyleTag style); | ||
| 53 | std::size_t GetAbstractedPads(std::span<IAbstractedPad*> list); | ||
| 54 | |||
| 55 | AppletFooterUiType GetAppletFooterUiType(); | ||
| 56 | |||
| 57 | AppletDetailedUiType GetAppletDetailedUiType(); | ||
| 58 | |||
| 59 | void UpdateDeviceProperties(u64 aruid, NpadSharedMemoryEntry& internal_state); | ||
| 60 | |||
| 61 | Core::HID::NpadInterfaceType GetNpadInterfaceType(); | ||
| 62 | |||
| 63 | Result GetNpadFullKeyGripColor(Core::HID::NpadColor& main_color, | ||
| 64 | Core::HID::NpadColor& sub_color) const; | ||
| 65 | |||
| 66 | void GetNpadLeftRightInterfaceType(Core::HID::NpadInterfaceType& param_2, | ||
| 67 | Core::HID::NpadInterfaceType& param_3) const; | ||
| 68 | |||
| 69 | private: | ||
| 70 | AppletResourceHolder* applet_resource_holder{nullptr}; | ||
| 71 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 72 | Core::HID::NpadIdType npad_id_type{Core::HID::NpadIdType::Invalid}; | ||
| 73 | s32 ref_counter{}; | ||
| 74 | Core::HID::DeviceIndex device_type{}; | ||
| 75 | AppletDetailedUiType applet_ui_type{}; | ||
| 76 | AppletFooterUiAttributes applet_ui_attributes{}; | ||
| 77 | bool is_vertical{}; | ||
| 78 | bool is_horizontal{}; | ||
| 79 | bool use_plus{}; | ||
| 80 | bool use_minus{}; | ||
| 81 | bool has_directional_buttons{}; | ||
| 82 | ColorProperties fullkey_color{}; | ||
| 83 | ColorProperties left_color{}; | ||
| 84 | ColorProperties right_color{}; | ||
| 85 | }; | ||
| 86 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp new file mode 100644 index 000000000..6d759298e --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp | |||
| @@ -0,0 +1,154 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/hid_util.h" | ||
| 6 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 7 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 8 | #include "hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h" | ||
| 9 | #include "hid_core/resources/applet_resource.h" | ||
| 10 | #include "hid_core/resources/npad/npad_types.h" | ||
| 11 | #include "hid_core/resources/shared_memory_format.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | NpadAbstractSixAxisHandler::NpadAbstractSixAxisHandler() {} | ||
| 16 | |||
| 17 | NpadAbstractSixAxisHandler::~NpadAbstractSixAxisHandler() = default; | ||
| 18 | |||
| 19 | void NpadAbstractSixAxisHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 20 | abstract_pad_holder = holder; | ||
| 21 | } | ||
| 22 | |||
| 23 | void NpadAbstractSixAxisHandler::SetAppletResource(AppletResourceHolder* applet_resource) { | ||
| 24 | applet_resource_holder = applet_resource; | ||
| 25 | } | ||
| 26 | |||
| 27 | void NpadAbstractSixAxisHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 28 | properties_handler = handler; | ||
| 29 | } | ||
| 30 | |||
| 31 | void NpadAbstractSixAxisHandler::SetSixaxisResource(SixAxisResource* resource) { | ||
| 32 | six_axis_resource = resource; | ||
| 33 | } | ||
| 34 | |||
| 35 | Result NpadAbstractSixAxisHandler::IncrementRefCounter() { | ||
| 36 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 37 | return ResultNpadHandlerOverflow; | ||
| 38 | } | ||
| 39 | ref_counter++; | ||
| 40 | return ResultSuccess; | ||
| 41 | } | ||
| 42 | |||
| 43 | Result NpadAbstractSixAxisHandler::DecrementRefCounter() { | ||
| 44 | if (ref_counter == 0) { | ||
| 45 | return ResultNpadHandlerNotInitialized; | ||
| 46 | } | ||
| 47 | ref_counter--; | ||
| 48 | return ResultSuccess; | ||
| 49 | } | ||
| 50 | |||
| 51 | u64 NpadAbstractSixAxisHandler::IsFirmwareUpdateAvailable() { | ||
| 52 | // TODO | ||
| 53 | return false; | ||
| 54 | } | ||
| 55 | |||
| 56 | Result NpadAbstractSixAxisHandler::UpdateSixAxisState() { | ||
| 57 | Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); | ||
| 58 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 59 | auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i); | ||
| 60 | if (data->flag.is_assigned) { | ||
| 61 | continue; | ||
| 62 | } | ||
| 63 | auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; | ||
| 64 | UpdateSixaxisInternalState(npad_entry, data->aruid, | ||
| 65 | data->flag.enable_six_axis_sensor.As<bool>()); | ||
| 66 | } | ||
| 67 | return ResultSuccess; | ||
| 68 | } | ||
| 69 | |||
| 70 | Result NpadAbstractSixAxisHandler::UpdateSixAxisState(u64 aruid) { | ||
| 71 | Core::HID::NpadIdType npad_id = properties_handler->GetNpadId(); | ||
| 72 | auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid); | ||
| 73 | if (data == nullptr) { | ||
| 74 | return ResultSuccess; | ||
| 75 | } | ||
| 76 | auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)]; | ||
| 77 | UpdateSixaxisInternalState(npad_entry, data->aruid, | ||
| 78 | data->flag.enable_six_axis_sensor.As<bool>()); | ||
| 79 | return ResultSuccess; | ||
| 80 | } | ||
| 81 | |||
| 82 | Result NpadAbstractSixAxisHandler::UpdateSixAxisState2(u64 aruid) { | ||
| 83 | const auto npad_index = NpadIdTypeToIndex(properties_handler->GetNpadId()); | ||
| 84 | AruidData* aruid_data = applet_resource_holder->applet_resource->GetAruidData(aruid); | ||
| 85 | if (aruid_data == nullptr) { | ||
| 86 | return ResultSuccess; | ||
| 87 | } | ||
| 88 | auto& npad_internal_state = aruid_data->shared_memory_format->npad.npad_entry[npad_index]; | ||
| 89 | UpdateSixaxisInternalState(npad_internal_state, aruid, | ||
| 90 | aruid_data->flag.enable_six_axis_sensor.As<bool>()); | ||
| 91 | return ResultSuccess; | ||
| 92 | } | ||
| 93 | |||
| 94 | void NpadAbstractSixAxisHandler::UpdateSixaxisInternalState(NpadSharedMemoryEntry& npad_entry, | ||
| 95 | u64 aruid, bool is_sensor_enabled) { | ||
| 96 | const Core::HID::NpadStyleTag style_tag{properties_handler->GetStyleSet(aruid)}; | ||
| 97 | |||
| 98 | if (!style_tag.palma) { | ||
| 99 | UpdateSixaxisFullkeyLifo(style_tag, npad_entry.internal_state.sixaxis_fullkey_lifo, | ||
| 100 | is_sensor_enabled); | ||
| 101 | } else { | ||
| 102 | UpdateSixAxisPalmaLifo(style_tag, npad_entry.internal_state.sixaxis_fullkey_lifo, | ||
| 103 | is_sensor_enabled); | ||
| 104 | } | ||
| 105 | UpdateSixaxisHandheldLifo(style_tag, npad_entry.internal_state.sixaxis_handheld_lifo, | ||
| 106 | is_sensor_enabled); | ||
| 107 | UpdateSixaxisDualLifo(style_tag, npad_entry.internal_state.sixaxis_dual_left_lifo, | ||
| 108 | is_sensor_enabled); | ||
| 109 | UpdateSixaxisDualLifo(style_tag, npad_entry.internal_state.sixaxis_dual_right_lifo, | ||
| 110 | is_sensor_enabled); | ||
| 111 | UpdateSixaxisLeftLifo(style_tag, npad_entry.internal_state.sixaxis_left_lifo, | ||
| 112 | is_sensor_enabled); | ||
| 113 | UpdateSixaxisRightLifo(style_tag, npad_entry.internal_state.sixaxis_right_lifo, | ||
| 114 | is_sensor_enabled); | ||
| 115 | // TODO: Set sixaxis properties | ||
| 116 | } | ||
| 117 | |||
| 118 | void NpadAbstractSixAxisHandler::UpdateSixaxisFullkeyLifo(Core::HID::NpadStyleTag style_tag, | ||
| 119 | NpadSixAxisSensorLifo& sensor_lifo, | ||
| 120 | bool is_sensor_enabled) { | ||
| 121 | // TODO | ||
| 122 | } | ||
| 123 | |||
| 124 | void NpadAbstractSixAxisHandler::UpdateSixAxisPalmaLifo(Core::HID::NpadStyleTag style_tag, | ||
| 125 | NpadSixAxisSensorLifo& sensor_lifo, | ||
| 126 | bool is_sensor_enabled) { | ||
| 127 | // TODO | ||
| 128 | } | ||
| 129 | |||
| 130 | void NpadAbstractSixAxisHandler::UpdateSixaxisHandheldLifo(Core::HID::NpadStyleTag style_tag, | ||
| 131 | NpadSixAxisSensorLifo& sensor_lifo, | ||
| 132 | bool is_sensor_enabled) { | ||
| 133 | // TODO | ||
| 134 | } | ||
| 135 | |||
| 136 | void NpadAbstractSixAxisHandler::UpdateSixaxisDualLifo(Core::HID::NpadStyleTag style_tag, | ||
| 137 | NpadSixAxisSensorLifo& sensor_lifo, | ||
| 138 | bool is_sensor_enabled) { | ||
| 139 | // TODO | ||
| 140 | } | ||
| 141 | |||
| 142 | void NpadAbstractSixAxisHandler::UpdateSixaxisLeftLifo(Core::HID::NpadStyleTag style_tag, | ||
| 143 | NpadSixAxisSensorLifo& sensor_lifo, | ||
| 144 | bool is_sensor_enabled) { | ||
| 145 | // TODO | ||
| 146 | } | ||
| 147 | |||
| 148 | void NpadAbstractSixAxisHandler::UpdateSixaxisRightLifo(Core::HID::NpadStyleTag style_tag, | ||
| 149 | NpadSixAxisSensorLifo& sensor_lifo, | ||
| 150 | bool is_sensor_enabled) { | ||
| 151 | // TODO | ||
| 152 | } | ||
| 153 | |||
| 154 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h new file mode 100644 index 000000000..9c20459e9 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | class SixAxisResource; | ||
| 12 | struct AppletResourceHolder; | ||
| 13 | class NpadAbstractedPadHolder; | ||
| 14 | class NpadAbstractPropertiesHandler; | ||
| 15 | struct NpadSixAxisSensorLifo; | ||
| 16 | |||
| 17 | /// Handles Npad request from HID interfaces | ||
| 18 | class NpadAbstractSixAxisHandler final { | ||
| 19 | public: | ||
| 20 | explicit NpadAbstractSixAxisHandler(); | ||
| 21 | ~NpadAbstractSixAxisHandler(); | ||
| 22 | |||
| 23 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 24 | void SetAppletResource(AppletResourceHolder* applet_resource); | ||
| 25 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 26 | void SetSixaxisResource(SixAxisResource* resource); | ||
| 27 | |||
| 28 | Result IncrementRefCounter(); | ||
| 29 | Result DecrementRefCounter(); | ||
| 30 | |||
| 31 | u64 IsFirmwareUpdateAvailable(); | ||
| 32 | |||
| 33 | Result UpdateSixAxisState(); | ||
| 34 | Result UpdateSixAxisState(u64 aruid); | ||
| 35 | Result UpdateSixAxisState2(u64 aruid); | ||
| 36 | |||
| 37 | private: | ||
| 38 | void UpdateSixaxisInternalState(NpadSharedMemoryEntry& npad_entry, u64 aruid, | ||
| 39 | bool is_sensor_enabled); | ||
| 40 | void UpdateSixaxisFullkeyLifo(Core::HID::NpadStyleTag style_tag, | ||
| 41 | NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled); | ||
| 42 | void UpdateSixAxisPalmaLifo(Core::HID::NpadStyleTag style_tag, | ||
| 43 | NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled); | ||
| 44 | void UpdateSixaxisHandheldLifo(Core::HID::NpadStyleTag style_tag, | ||
| 45 | NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled); | ||
| 46 | void UpdateSixaxisDualLifo(Core::HID::NpadStyleTag style_tag, | ||
| 47 | NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled); | ||
| 48 | void UpdateSixaxisLeftLifo(Core::HID::NpadStyleTag style_tag, | ||
| 49 | NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled); | ||
| 50 | void UpdateSixaxisRightLifo(Core::HID::NpadStyleTag style_tag, | ||
| 51 | NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled); | ||
| 52 | |||
| 53 | AppletResourceHolder* applet_resource_holder{nullptr}; | ||
| 54 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 55 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 56 | SixAxisResource* six_axis_resource{nullptr}; | ||
| 57 | |||
| 58 | s32 ref_counter{}; | ||
| 59 | }; | ||
| 60 | |||
| 61 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp new file mode 100644 index 000000000..a00d6c9de --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/hid_util.h" | ||
| 6 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | ||
| 7 | #include "hid_core/resources/abstracted_pad/abstract_properties_handler.h" | ||
| 8 | #include "hid_core/resources/abstracted_pad/abstract_vibration_handler.h" | ||
| 9 | #include "hid_core/resources/applet_resource.h" | ||
| 10 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 11 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 12 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 13 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | |||
| 17 | NpadAbstractVibrationHandler::NpadAbstractVibrationHandler() {} | ||
| 18 | |||
| 19 | NpadAbstractVibrationHandler::~NpadAbstractVibrationHandler() = default; | ||
| 20 | |||
| 21 | void NpadAbstractVibrationHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) { | ||
| 22 | abstract_pad_holder = holder; | ||
| 23 | } | ||
| 24 | |||
| 25 | void NpadAbstractVibrationHandler::SetAppletResource(AppletResourceHolder* applet_resource) { | ||
| 26 | applet_resource_holder = applet_resource; | ||
| 27 | } | ||
| 28 | |||
| 29 | void NpadAbstractVibrationHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) { | ||
| 30 | properties_handler = handler; | ||
| 31 | } | ||
| 32 | |||
| 33 | void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) { | ||
| 34 | n64_vibration_device = n64_device; | ||
| 35 | } | ||
| 36 | |||
| 37 | void NpadAbstractVibrationHandler::SetVibration(std::span<NpadVibrationDevice*> device) { | ||
| 38 | for (std::size_t i = 0; i < device.size() && i < vibration_device.size(); i++) { | ||
| 39 | vibration_device[i] = device[i]; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) { | ||
| 44 | gc_vibration_device = gc_device; | ||
| 45 | } | ||
| 46 | |||
| 47 | Result NpadAbstractVibrationHandler::IncrementRefCounter() { | ||
| 48 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 49 | return ResultNpadHandlerOverflow; | ||
| 50 | } | ||
| 51 | ref_counter++; | ||
| 52 | return ResultSuccess; | ||
| 53 | } | ||
| 54 | |||
| 55 | Result NpadAbstractVibrationHandler::DecrementRefCounter() { | ||
| 56 | if (ref_counter == 0) { | ||
| 57 | return ResultNpadHandlerNotInitialized; | ||
| 58 | } | ||
| 59 | ref_counter--; | ||
| 60 | return ResultSuccess; | ||
| 61 | } | ||
| 62 | |||
| 63 | void NpadAbstractVibrationHandler::UpdateVibrationState() { | ||
| 64 | const bool is_handheld_hid_enabled = | ||
| 65 | applet_resource_holder->handheld_config->is_handheld_hid_enabled; | ||
| 66 | const bool is_force_handheld_style_vibration = | ||
| 67 | applet_resource_holder->handheld_config->is_force_handheld_style_vibration; | ||
| 68 | |||
| 69 | if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) { | ||
| 70 | // TODO | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h new file mode 100644 index 000000000..aeb07ce86 --- /dev/null +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <span> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/result.h" | ||
| 10 | #include "hid_core/hid_types.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | struct AppletResourceHolder; | ||
| 14 | class NpadAbstractedPadHolder; | ||
| 15 | class NpadAbstractPropertiesHandler; | ||
| 16 | class NpadGcVibrationDevice; | ||
| 17 | class NpadVibrationDevice; | ||
| 18 | class NpadN64VibrationDevice; | ||
| 19 | class NpadVibration; | ||
| 20 | |||
| 21 | /// Keeps track of battery levels and updates npad battery shared memory values | ||
| 22 | class NpadAbstractVibrationHandler final { | ||
| 23 | public: | ||
| 24 | explicit NpadAbstractVibrationHandler(); | ||
| 25 | ~NpadAbstractVibrationHandler(); | ||
| 26 | |||
| 27 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | ||
| 28 | void SetAppletResource(AppletResourceHolder* applet_resource); | ||
| 29 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | ||
| 30 | |||
| 31 | void SetN64Vibration(NpadN64VibrationDevice* n64_device); | ||
| 32 | void SetVibration(std::span<NpadVibrationDevice*> device); | ||
| 33 | void SetGcVibration(NpadGcVibrationDevice* gc_device); | ||
| 34 | |||
| 35 | Result IncrementRefCounter(); | ||
| 36 | Result DecrementRefCounter(); | ||
| 37 | |||
| 38 | void UpdateVibrationState(); | ||
| 39 | |||
| 40 | private: | ||
| 41 | AppletResourceHolder* applet_resource_holder{nullptr}; | ||
| 42 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | ||
| 43 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | ||
| 44 | |||
| 45 | NpadN64VibrationDevice* n64_vibration_device{nullptr}; | ||
| 46 | std::array<NpadVibrationDevice*, 2> vibration_device{}; | ||
| 47 | NpadGcVibrationDevice* gc_vibration_device{nullptr}; | ||
| 48 | NpadVibration* vibration_handler{nullptr}; | ||
| 49 | s32 ref_counter{}; | ||
| 50 | }; | ||
| 51 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 1f8a0f8ab..97537a2e2 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp | |||
| @@ -193,7 +193,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { | |||
| 193 | case Core::HID::NpadStyleIndex::None: | 193 | case Core::HID::NpadStyleIndex::None: |
| 194 | ASSERT(false); | 194 | ASSERT(false); |
| 195 | break; | 195 | break; |
| 196 | case Core::HID::NpadStyleIndex::ProController: | 196 | case Core::HID::NpadStyleIndex::Fullkey: |
| 197 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | 197 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; |
| 198 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; | 198 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; |
| 199 | shared_memory->battery_level_dual = battery_level.dual.battery_level; | 199 | shared_memory->battery_level_dual = battery_level.dual.battery_level; |
| @@ -491,7 +491,7 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | |||
| 491 | case Core::HID::NpadStyleIndex::None: | 491 | case Core::HID::NpadStyleIndex::None: |
| 492 | ASSERT(false); | 492 | ASSERT(false); |
| 493 | break; | 493 | break; |
| 494 | case Core::HID::NpadStyleIndex::ProController: | 494 | case Core::HID::NpadStyleIndex::Fullkey: |
| 495 | case Core::HID::NpadStyleIndex::NES: | 495 | case Core::HID::NpadStyleIndex::NES: |
| 496 | case Core::HID::NpadStyleIndex::SNES: | 496 | case Core::HID::NpadStyleIndex::SNES: |
| 497 | case Core::HID::NpadStyleIndex::N64: | 497 | case Core::HID::NpadStyleIndex::N64: |
| @@ -1292,7 +1292,7 @@ Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( | |||
| 1292 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | 1292 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { |
| 1293 | auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); | 1293 | auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); |
| 1294 | switch (sixaxis_handle.npad_type) { | 1294 | switch (sixaxis_handle.npad_type) { |
| 1295 | case Core::HID::NpadStyleIndex::ProController: | 1295 | case Core::HID::NpadStyleIndex::Fullkey: |
| 1296 | case Core::HID::NpadStyleIndex::Pokeball: | 1296 | case Core::HID::NpadStyleIndex::Pokeball: |
| 1297 | return controller.shared_memory->sixaxis_fullkey_properties; | 1297 | return controller.shared_memory->sixaxis_fullkey_properties; |
| 1298 | case Core::HID::NpadStyleIndex::Handheld: | 1298 | case Core::HID::NpadStyleIndex::Handheld: |
| @@ -1315,7 +1315,7 @@ const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( | |||
| 1315 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { | 1315 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { |
| 1316 | const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); | 1316 | const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); |
| 1317 | switch (sixaxis_handle.npad_type) { | 1317 | switch (sixaxis_handle.npad_type) { |
| 1318 | case Core::HID::NpadStyleIndex::ProController: | 1318 | case Core::HID::NpadStyleIndex::Fullkey: |
| 1319 | case Core::HID::NpadStyleIndex::Pokeball: | 1319 | case Core::HID::NpadStyleIndex::Pokeball: |
| 1320 | return controller.shared_memory->sixaxis_fullkey_properties; | 1320 | return controller.shared_memory->sixaxis_fullkey_properties; |
| 1321 | case Core::HID::NpadStyleIndex::Handheld: | 1321 | case Core::HID::NpadStyleIndex::Handheld: |
diff --git a/src/hid_core/resources/npad/npad_data.cpp b/src/hid_core/resources/npad/npad_data.cpp index c7e9760cb..29ad5cb08 100644 --- a/src/hid_core/resources/npad/npad_data.cpp +++ b/src/hid_core/resources/npad/npad_data.cpp | |||
| @@ -151,7 +151,7 @@ Core::HID::NpadStyleSet NPadData::GetSupportedNpadStyleSet() const { | |||
| 151 | bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const { | 151 | bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const { |
| 152 | Core::HID::NpadStyleTag style = {supported_npad_style_set}; | 152 | Core::HID::NpadStyleTag style = {supported_npad_style_set}; |
| 153 | switch (style_index) { | 153 | switch (style_index) { |
| 154 | case Core::HID::NpadStyleIndex::ProController: | 154 | case Core::HID::NpadStyleIndex::Fullkey: |
| 155 | return style.fullkey.As<bool>(); | 155 | return style.fullkey.As<bool>(); |
| 156 | case Core::HID::NpadStyleIndex::Handheld: | 156 | case Core::HID::NpadStyleIndex::Handheld: |
| 157 | return style.handheld.As<bool>(); | 157 | return style.handheld.As<bool>(); |
diff --git a/src/hid_core/resources/npad/npad_types.h b/src/hid_core/resources/npad/npad_types.h index a02f9cf16..074dd40cf 100644 --- a/src/hid_core/resources/npad/npad_types.h +++ b/src/hid_core/resources/npad/npad_types.h | |||
| @@ -252,4 +252,103 @@ enum class NpadLagerType : u32 { | |||
| 252 | U, | 252 | U, |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| 255 | // nn::hidtypes::FeatureType | ||
| 256 | struct FeatureType { | ||
| 257 | union { | ||
| 258 | u64 raw{}; | ||
| 259 | BitField<0, 1, u64> has_left_analog_stick; | ||
| 260 | BitField<1, 1, u64> has_right_analog_stick; | ||
| 261 | BitField<2, 1, u64> has_left_joy_six_axis_sensor; | ||
| 262 | BitField<3, 1, u64> has_right_joy_six_axis_sensor; | ||
| 263 | BitField<4, 1, u64> has_fullkey_joy_six_axis_sensor; | ||
| 264 | BitField<5, 1, u64> has_left_lra_vibration_device; | ||
| 265 | BitField<6, 1, u64> has_right_lra_vibration_device; | ||
| 266 | BitField<7, 1, u64> has_gc_vibration_device; | ||
| 267 | BitField<8, 1, u64> has_erm_vibration_device; | ||
| 268 | BitField<9, 1, u64> has_left_joy_rail_bus; | ||
| 269 | BitField<10, 1, u64> has_right_joy_rail_bus; | ||
| 270 | BitField<11, 1, u64> has_internal_bus; | ||
| 271 | BitField<12, 1, u64> is_palma; | ||
| 272 | BitField<13, 1, u64> has_nfc; | ||
| 273 | BitField<14, 1, u64> has_ir_sensor; | ||
| 274 | BitField<15, 1, u64> is_analog_stick_calibration_supported; | ||
| 275 | BitField<16, 1, u64> is_six_axis_Sensor_user_calibration_supported; | ||
| 276 | BitField<17, 1, u64> has_left_right_joy_battery; | ||
| 277 | BitField<18, 1, u64> has_fullkey_battery; | ||
| 278 | BitField<19, 1, u64> is_disconnect_controller_if_battery_none; | ||
| 279 | BitField<20, 1, u64> has_controller_color; | ||
| 280 | BitField<21, 1, u64> has_grip_color; | ||
| 281 | BitField<22, 1, u64> has_identification_code; | ||
| 282 | BitField<23, 1, u64> has_bluetooth_address; | ||
| 283 | BitField<24, 1, u64> has_mcu; | ||
| 284 | BitField<25, 1, u64> has_notification_led; | ||
| 285 | BitField<26, 1, u64> has_directional_buttons; | ||
| 286 | BitField<27, 1, u64> has_indicator_led; | ||
| 287 | BitField<28, 1, u64> is_button_config_embedded_supported; | ||
| 288 | BitField<29, 1, u64> is_button_config_full_supported; | ||
| 289 | BitField<30, 1, u64> is_button_config_left_supported; | ||
| 290 | BitField<31, 1, u64> is_button_config_right_supported; | ||
| 291 | BitField<32, 1, u64> is_usb_hid_device; | ||
| 292 | BitField<33, 1, u64> is_kuina_device; | ||
| 293 | BitField<34, 1, u64> is_direct_usb_to_bt_switching_device; | ||
| 294 | BitField<35, 1, u64> is_normalize_analog_stick_with_inner_cross; | ||
| 295 | }; | ||
| 296 | }; | ||
| 297 | static_assert(sizeof(FeatureType) == 8, "FeatureType is an invalid size"); | ||
| 298 | |||
| 299 | // This is nn::hid::AssignmentStyle | ||
| 300 | struct AssignmentStyle { | ||
| 301 | union { | ||
| 302 | u32 raw{}; | ||
| 303 | BitField<0, 1, u32> is_external_assigned; | ||
| 304 | BitField<1, 1, u32> is_external_left_assigned; | ||
| 305 | BitField<2, 1, u32> is_external_right_assigned; | ||
| 306 | BitField<3, 1, u32> is_handheld_assigned; | ||
| 307 | BitField<4, 1, u32> is_handheld_left_assigned; | ||
| 308 | BitField<5, 1, u32> is_handheld_right_assigned; | ||
| 309 | }; | ||
| 310 | }; | ||
| 311 | static_assert(sizeof(AssignmentStyle) == 4, "AssignmentStyle is an invalid size"); | ||
| 312 | |||
| 313 | // This is nn::hid::server::IAbstractedPad::InternalFlags | ||
| 314 | struct InternalFlags { | ||
| 315 | union { | ||
| 316 | u32 raw{}; | ||
| 317 | BitField<0, 1, u32> is_bound; | ||
| 318 | BitField<1, 1, u32> is_connected; | ||
| 319 | BitField<2, 1, u32> is_battery_low_ovln_required; | ||
| 320 | BitField<3, 1, u32> is_battery_low_ovln_delay_required; | ||
| 321 | BitField<4, 1, u32> is_sample_recieved; | ||
| 322 | BitField<5, 1, u32> is_virtual_input; | ||
| 323 | BitField<6, 1, u32> is_wired; | ||
| 324 | BitField<8, 1, u32> use_center_clamp; | ||
| 325 | BitField<9, 1, u32> has_virtual_six_axis_sensor_acceleration; | ||
| 326 | BitField<10, 1, u32> has_virtual_six_axis_sensor_angle; | ||
| 327 | BitField<11, 1, u32> is_debug_pad; | ||
| 328 | }; | ||
| 329 | }; | ||
| 330 | static_assert(sizeof(InternalFlags) == 4, "InternalFlags is an invalid size"); | ||
| 331 | |||
| 332 | /// This is nn::hid::server::IAbstractedPad | ||
| 333 | struct IAbstractedPad { | ||
| 334 | InternalFlags internal_flags; | ||
| 335 | u64 controller_id; | ||
| 336 | u32 controller_number; | ||
| 337 | u64 low_battery_display_delay_time; | ||
| 338 | u64 low_battery_display_delay_interval; | ||
| 339 | FeatureType feature_set; | ||
| 340 | FeatureType disabled_feature_set; | ||
| 341 | AssignmentStyle assignment_style; | ||
| 342 | Core::HID::NpadStyleIndex device_type; | ||
| 343 | Core::HID::NpadInterfaceType interface_type; | ||
| 344 | Core::HID::NpadPowerInfo power_info; | ||
| 345 | u32 pad_state; | ||
| 346 | u32 button_mask; | ||
| 347 | u32 system_button_mask; | ||
| 348 | u8 indicator; | ||
| 349 | std::vector<f32> virtual_six_axis_sensor_acceleration; | ||
| 350 | std::vector<f32> virtual_six_axis_sensor_angle; | ||
| 351 | u64 xcd_handle; | ||
| 352 | u64 color; | ||
| 353 | }; | ||
| 255 | } // namespace Service::HID | 354 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/npad/npad_vibration.cpp b/src/hid_core/resources/npad/npad_vibration.cpp new file mode 100644 index 000000000..3bdd55dec --- /dev/null +++ b/src/hid_core/resources/npad/npad_vibration.cpp | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 6 | |||
| 7 | namespace Service::HID { | ||
| 8 | |||
| 9 | NpadVibration::NpadVibration() {} | ||
| 10 | |||
| 11 | NpadVibration::~NpadVibration() = default; | ||
| 12 | |||
| 13 | Result NpadVibration::Activate() { | ||
| 14 | std::scoped_lock lock{mutex}; | ||
| 15 | |||
| 16 | const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume(); | ||
| 17 | // if (master_volume < 0.0f || master_volume > 1.0f) { | ||
| 18 | // return ResultVibrationStrenghtOutOfRange; | ||
| 19 | // } | ||
| 20 | |||
| 21 | volume = master_volume; | ||
| 22 | return ResultSuccess; | ||
| 23 | } | ||
| 24 | |||
| 25 | Result NpadVibration::Deactivate() { | ||
| 26 | return ResultSuccess; | ||
| 27 | } | ||
| 28 | |||
| 29 | Result NpadVibration::SetVibrationMasterVolume(f32 master_volume) { | ||
| 30 | std::scoped_lock lock{mutex}; | ||
| 31 | |||
| 32 | if (master_volume < 0.0f && master_volume > 1.0f) { | ||
| 33 | return ResultVibrationStrenghtOutOfRange; | ||
| 34 | } | ||
| 35 | |||
| 36 | volume = master_volume; | ||
| 37 | // nn::settings::system::SetVibrationMasterVolume(master_volume); | ||
| 38 | |||
| 39 | return ResultSuccess; | ||
| 40 | } | ||
| 41 | |||
| 42 | Result NpadVibration::GetVibrationVolume(f32& out_volume) const { | ||
| 43 | std::scoped_lock lock{mutex}; | ||
| 44 | out_volume = volume; | ||
| 45 | return ResultSuccess; | ||
| 46 | } | ||
| 47 | |||
| 48 | Result NpadVibration::GetVibrationMasterVolume(f32& out_volume) const { | ||
| 49 | std::scoped_lock lock{mutex}; | ||
| 50 | |||
| 51 | const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume(); | ||
| 52 | // if (master_volume < 0.0f || master_volume > 1.0f) { | ||
| 53 | // return ResultVibrationStrenghtOutOfRange; | ||
| 54 | // } | ||
| 55 | |||
| 56 | out_volume = master_volume; | ||
| 57 | return ResultSuccess; | ||
| 58 | } | ||
| 59 | |||
| 60 | Result NpadVibration::BeginPermitVibrationSession(u64 aruid) { | ||
| 61 | std::scoped_lock lock{mutex}; | ||
| 62 | session_aruid = aruid; | ||
| 63 | volume = 1.0; | ||
| 64 | return ResultSuccess; | ||
| 65 | } | ||
| 66 | |||
| 67 | Result NpadVibration::EndPermitVibrationSession() { | ||
| 68 | std::scoped_lock lock{mutex}; | ||
| 69 | |||
| 70 | const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume(); | ||
| 71 | // if (master_volume < 0.0f || master_volume > 1.0f) { | ||
| 72 | // return ResultVibrationStrenghtOutOfRange; | ||
| 73 | // } | ||
| 74 | |||
| 75 | volume = master_volume; | ||
| 76 | session_aruid = 0; | ||
| 77 | return ResultSuccess; | ||
| 78 | } | ||
| 79 | |||
| 80 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/npad/npad_vibration.h b/src/hid_core/resources/npad/npad_vibration.h new file mode 100644 index 000000000..0748aeffc --- /dev/null +++ b/src/hid_core/resources/npad/npad_vibration.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <mutex> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/result.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | |||
| 13 | class NpadVibration final { | ||
| 14 | public: | ||
| 15 | explicit NpadVibration(); | ||
| 16 | ~NpadVibration(); | ||
| 17 | |||
| 18 | Result Activate(); | ||
| 19 | Result Deactivate(); | ||
| 20 | |||
| 21 | Result SetVibrationMasterVolume(f32 master_volume); | ||
| 22 | Result GetVibrationVolume(f32& out_volume) const; | ||
| 23 | Result GetVibrationMasterVolume(f32& out_volume) const; | ||
| 24 | |||
| 25 | Result BeginPermitVibrationSession(u64 aruid); | ||
| 26 | Result EndPermitVibrationSession(); | ||
| 27 | |||
| 28 | private: | ||
| 29 | f32 volume{}; | ||
| 30 | u64 session_aruid{}; | ||
| 31 | mutable std::mutex mutex; | ||
| 32 | }; | ||
| 33 | |||
| 34 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/six_axis/six_axis.cpp b/src/hid_core/resources/six_axis/six_axis.cpp index 8a9677c50..da12d2d5a 100644 --- a/src/hid_core/resources/six_axis/six_axis.cpp +++ b/src/hid_core/resources/six_axis/six_axis.cpp | |||
| @@ -114,7 +114,7 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | |||
| 114 | case Core::HID::NpadStyleIndex::None: | 114 | case Core::HID::NpadStyleIndex::None: |
| 115 | ASSERT(false); | 115 | ASSERT(false); |
| 116 | break; | 116 | break; |
| 117 | case Core::HID::NpadStyleIndex::ProController: | 117 | case Core::HID::NpadStyleIndex::Fullkey: |
| 118 | set_motion_state(sixaxis_fullkey_state, motion_state[0]); | 118 | set_motion_state(sixaxis_fullkey_state, motion_state[0]); |
| 119 | break; | 119 | break; |
| 120 | case Core::HID::NpadStyleIndex::Handheld: | 120 | case Core::HID::NpadStyleIndex::Handheld: |
| @@ -345,7 +345,7 @@ SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( | |||
| 345 | const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | 345 | const Core::HID::SixAxisSensorHandle& sixaxis_handle) { |
| 346 | auto& controller = GetControllerFromHandle(sixaxis_handle); | 346 | auto& controller = GetControllerFromHandle(sixaxis_handle); |
| 347 | switch (sixaxis_handle.npad_type) { | 347 | switch (sixaxis_handle.npad_type) { |
| 348 | case Core::HID::NpadStyleIndex::ProController: | 348 | case Core::HID::NpadStyleIndex::Fullkey: |
| 349 | case Core::HID::NpadStyleIndex::Pokeball: | 349 | case Core::HID::NpadStyleIndex::Pokeball: |
| 350 | return controller.sixaxis_fullkey; | 350 | return controller.sixaxis_fullkey; |
| 351 | case Core::HID::NpadStyleIndex::Handheld: | 351 | case Core::HID::NpadStyleIndex::Handheld: |
| @@ -368,7 +368,7 @@ const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( | |||
| 368 | const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { | 368 | const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { |
| 369 | const auto& controller = GetControllerFromHandle(sixaxis_handle); | 369 | const auto& controller = GetControllerFromHandle(sixaxis_handle); |
| 370 | switch (sixaxis_handle.npad_type) { | 370 | switch (sixaxis_handle.npad_type) { |
| 371 | case Core::HID::NpadStyleIndex::ProController: | 371 | case Core::HID::NpadStyleIndex::Fullkey: |
| 372 | case Core::HID::NpadStyleIndex::Pokeball: | 372 | case Core::HID::NpadStyleIndex::Pokeball: |
| 373 | return controller.sixaxis_fullkey; | 373 | return controller.sixaxis_fullkey; |
| 374 | case Core::HID::NpadStyleIndex::Handheld: | 374 | case Core::HID::NpadStyleIndex::Handheld: |
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.cpp b/src/hid_core/resources/vibration/gc_vibration_device.cpp new file mode 100644 index 000000000..f01f81b9a --- /dev/null +++ b/src/hid_core/resources/vibration/gc_vibration_device.cpp | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/npad/npad_types.h" | ||
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 7 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | NpadGcVibrationDevice::NpadGcVibrationDevice() {} | ||
| 12 | |||
| 13 | Result NpadGcVibrationDevice::IncrementRefCounter() { | ||
| 14 | if (ref_counter == 0 && is_mounted) { | ||
| 15 | f32 volume = 1.0f; | ||
| 16 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 17 | if (result.IsSuccess()) { | ||
| 18 | // TODO: SendVibrationGcErmCommand | ||
| 19 | } | ||
| 20 | } | ||
| 21 | ref_counter++; | ||
| 22 | return ResultSuccess; | ||
| 23 | } | ||
| 24 | |||
| 25 | Result NpadGcVibrationDevice::DecrementRefCounter() { | ||
| 26 | if (ref_counter == 1 && !is_mounted) { | ||
| 27 | f32 volume = 1.0f; | ||
| 28 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 29 | if (result.IsSuccess()) { | ||
| 30 | // TODO: SendVibrationGcErmCommand | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | if (ref_counter > 0) { | ||
| 35 | ref_counter--; | ||
| 36 | } | ||
| 37 | |||
| 38 | return ResultSuccess; | ||
| 39 | } | ||
| 40 | |||
| 41 | Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { | ||
| 42 | if (!is_mounted) { | ||
| 43 | return ResultSuccess; | ||
| 44 | } | ||
| 45 | f32 volume = 1.0f; | ||
| 46 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 47 | if (result.IsError()) { | ||
| 48 | return result; | ||
| 49 | } | ||
| 50 | if (volume == 0.0) { | ||
| 51 | command = Core::HID::VibrationGcErmCommand::Stop; | ||
| 52 | } else { | ||
| 53 | if (command > Core::HID::VibrationGcErmCommand::StopHard) { | ||
| 54 | // Abort | ||
| 55 | return ResultSuccess; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | // TODO: SendVibrationGcErmCommand | ||
| 59 | return ResultSuccess; | ||
| 60 | } | ||
| 61 | |||
| 62 | Result NpadGcVibrationDevice::GetActualVibrationGcErmCommand( | ||
| 63 | Core::HID::VibrationGcErmCommand& out_command) { | ||
| 64 | if (!is_mounted) { | ||
| 65 | out_command = Core::HID::VibrationGcErmCommand::Stop; | ||
| 66 | return ResultSuccess; | ||
| 67 | } | ||
| 68 | |||
| 69 | f32 volume = 1.0f; | ||
| 70 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 71 | if (result.IsError()) { | ||
| 72 | return result; | ||
| 73 | } | ||
| 74 | if (volume == 0.0f) { | ||
| 75 | out_command = Core::HID::VibrationGcErmCommand::Stop; | ||
| 76 | return ResultSuccess; | ||
| 77 | } | ||
| 78 | |||
| 79 | // TODO: GetActualVibrationGcErmCommand | ||
| 80 | return ResultSuccess; | ||
| 81 | } | ||
| 82 | |||
| 83 | Result NpadGcVibrationDevice::SendVibrationNotificationPattern( | ||
| 84 | Core::HID::VibrationGcErmCommand command) { | ||
| 85 | if (!is_mounted) { | ||
| 86 | return ResultSuccess; | ||
| 87 | } | ||
| 88 | |||
| 89 | f32 volume = 1.0f; | ||
| 90 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 91 | if (result.IsError()) { | ||
| 92 | return result; | ||
| 93 | } | ||
| 94 | if (volume <= 0.0f) { | ||
| 95 | command = Core::HID::VibrationGcErmCommand::Stop; | ||
| 96 | } | ||
| 97 | if (command > Core::HID::VibrationGcErmCommand::StopHard) { | ||
| 98 | // Abort | ||
| 99 | return ResultSuccess; | ||
| 100 | } | ||
| 101 | |||
| 102 | // TODO: SendVibrationNotificationPattern | ||
| 103 | return ResultSuccess; | ||
| 104 | } | ||
| 105 | |||
| 106 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.h b/src/hid_core/resources/vibration/gc_vibration_device.h new file mode 100644 index 000000000..87abca57d --- /dev/null +++ b/src/hid_core/resources/vibration/gc_vibration_device.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "hid_core/hid_types.h" | ||
| 12 | #include "hid_core/resources/npad/npad_types.h" | ||
| 13 | #include "hid_core/resources/vibration/vibration_base.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | class NpadVibration; | ||
| 17 | |||
| 18 | /// Handles Npad request from HID interfaces | ||
| 19 | class NpadGcVibrationDevice final : public NpadVibrationBase { | ||
| 20 | public: | ||
| 21 | explicit NpadGcVibrationDevice(); | ||
| 22 | |||
| 23 | Result IncrementRefCounter() override; | ||
| 24 | Result DecrementRefCounter() override; | ||
| 25 | |||
| 26 | Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); | ||
| 27 | |||
| 28 | Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command); | ||
| 29 | Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command); | ||
| 30 | }; | ||
| 31 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.cpp b/src/hid_core/resources/vibration/n64_vibration_device.cpp new file mode 100644 index 000000000..639f87abf --- /dev/null +++ b/src/hid_core/resources/vibration/n64_vibration_device.cpp | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/npad/npad_types.h" | ||
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 7 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | NpadN64VibrationDevice::NpadN64VibrationDevice() {} | ||
| 12 | |||
| 13 | Result NpadN64VibrationDevice::IncrementRefCounter() { | ||
| 14 | if (ref_counter == 0 && is_mounted) { | ||
| 15 | f32 volume = 1.0f; | ||
| 16 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 17 | if (result.IsSuccess()) { | ||
| 18 | // TODO: SendVibrationInBool | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | ref_counter++; | ||
| 23 | return ResultSuccess; | ||
| 24 | } | ||
| 25 | |||
| 26 | Result NpadN64VibrationDevice::DecrementRefCounter() { | ||
| 27 | if (ref_counter == 1) { | ||
| 28 | if (!is_mounted) { | ||
| 29 | ref_counter = 0; | ||
| 30 | if (is_mounted != false) { | ||
| 31 | // TODO: SendVibrationInBool | ||
| 32 | } | ||
| 33 | return ResultSuccess; | ||
| 34 | } | ||
| 35 | f32 volume = 1.0f; | ||
| 36 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 37 | if (result.IsSuccess()) { | ||
| 38 | // TODO | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | if (ref_counter > 0) { | ||
| 43 | ref_counter--; | ||
| 44 | } | ||
| 45 | |||
| 46 | return ResultSuccess; | ||
| 47 | } | ||
| 48 | |||
| 49 | Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { | ||
| 50 | if (ref_counter < 1) { | ||
| 51 | return ResultVibrationNotInitialized; | ||
| 52 | } | ||
| 53 | if (is_mounted) { | ||
| 54 | f32 volume = 1.0f; | ||
| 55 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 56 | if (result.IsError()) { | ||
| 57 | return result; | ||
| 58 | } | ||
| 59 | // TODO: SendVibrationInBool | ||
| 60 | } | ||
| 61 | return ResultSuccess; | ||
| 62 | } | ||
| 63 | |||
| 64 | Result NpadN64VibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u32 pattern) { | ||
| 65 | if (!is_mounted) { | ||
| 66 | return ResultSuccess; | ||
| 67 | } | ||
| 68 | f32 volume = 1.0f; | ||
| 69 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 70 | if (result.IsError()) { | ||
| 71 | return result; | ||
| 72 | } | ||
| 73 | if (volume <= 0.0) { | ||
| 74 | pattern = 0; | ||
| 75 | } | ||
| 76 | // TODO: SendVibrationNotificationPattern | ||
| 77 | return ResultSuccess; | ||
| 78 | } | ||
| 79 | |||
| 80 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.h b/src/hid_core/resources/vibration/n64_vibration_device.h new file mode 100644 index 000000000..54e6efc1a --- /dev/null +++ b/src/hid_core/resources/vibration/n64_vibration_device.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "hid_core/hid_types.h" | ||
| 12 | #include "hid_core/resources/npad/npad_types.h" | ||
| 13 | #include "hid_core/resources/vibration/vibration_base.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | class NpadVibration; | ||
| 17 | |||
| 18 | /// Handles Npad request from HID interfaces | ||
| 19 | class NpadN64VibrationDevice final : public NpadVibrationBase { | ||
| 20 | public: | ||
| 21 | explicit NpadN64VibrationDevice(); | ||
| 22 | |||
| 23 | Result IncrementRefCounter() override; | ||
| 24 | Result DecrementRefCounter() override; | ||
| 25 | |||
| 26 | Result SendValueInBool(bool is_vibrating); | ||
| 27 | Result SendVibrationNotificationPattern(u32 pattern); | ||
| 28 | }; | ||
| 29 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/vibration/vibration_base.cpp b/src/hid_core/resources/vibration/vibration_base.cpp new file mode 100644 index 000000000..350f349c2 --- /dev/null +++ b/src/hid_core/resources/vibration/vibration_base.cpp | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/npad/npad_types.h" | ||
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 7 | #include "hid_core/resources/vibration/vibration_base.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | NpadVibrationBase::NpadVibrationBase() {} | ||
| 12 | |||
| 13 | Result NpadVibrationBase::IncrementRefCounter() { | ||
| 14 | ref_counter++; | ||
| 15 | return ResultSuccess; | ||
| 16 | } | ||
| 17 | |||
| 18 | Result NpadVibrationBase::DecrementRefCounter() { | ||
| 19 | if (ref_counter > 0) { | ||
| 20 | ref_counter--; | ||
| 21 | } | ||
| 22 | |||
| 23 | return ResultSuccess; | ||
| 24 | } | ||
| 25 | |||
| 26 | bool NpadVibrationBase::IsVibrationMounted() const { | ||
| 27 | return is_mounted; | ||
| 28 | } | ||
| 29 | |||
| 30 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/vibration/vibration_base.h b/src/hid_core/resources/vibration/vibration_base.h new file mode 100644 index 000000000..c6c5fc4d9 --- /dev/null +++ b/src/hid_core/resources/vibration/vibration_base.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/result.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | class NpadVibration; | ||
| 11 | |||
| 12 | /// Handles Npad request from HID interfaces | ||
| 13 | class NpadVibrationBase { | ||
| 14 | public: | ||
| 15 | explicit NpadVibrationBase(); | ||
| 16 | |||
| 17 | virtual Result IncrementRefCounter(); | ||
| 18 | virtual Result DecrementRefCounter(); | ||
| 19 | |||
| 20 | bool IsVibrationMounted() const; | ||
| 21 | |||
| 22 | protected: | ||
| 23 | u64 xcd_handle{}; | ||
| 24 | s32 ref_counter{}; | ||
| 25 | bool is_mounted{}; | ||
| 26 | NpadVibration* vibration_handler{nullptr}; | ||
| 27 | }; | ||
| 28 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/vibration/vibration_device.cpp b/src/hid_core/resources/vibration/vibration_device.cpp new file mode 100644 index 000000000..888c3a7ed --- /dev/null +++ b/src/hid_core/resources/vibration/vibration_device.cpp | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "hid_core/hid_result.h" | ||
| 5 | #include "hid_core/resources/npad/npad_types.h" | ||
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 7 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | NpadVibrationDevice::NpadVibrationDevice() {} | ||
| 12 | |||
| 13 | Result NpadVibrationDevice::IncrementRefCounter() { | ||
| 14 | ref_counter++; | ||
| 15 | return ResultSuccess; | ||
| 16 | } | ||
| 17 | |||
| 18 | Result NpadVibrationDevice::DecrementRefCounter() { | ||
| 19 | if (ref_counter > 0) { | ||
| 20 | ref_counter--; | ||
| 21 | } | ||
| 22 | |||
| 23 | return ResultSuccess; | ||
| 24 | } | ||
| 25 | |||
| 26 | Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) { | ||
| 27 | if (ref_counter == 0) { | ||
| 28 | return ResultVibrationNotInitialized; | ||
| 29 | } | ||
| 30 | if (!is_mounted) { | ||
| 31 | return ResultSuccess; | ||
| 32 | } | ||
| 33 | |||
| 34 | f32 volume = 1.0f; | ||
| 35 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 36 | if (result.IsError()) { | ||
| 37 | return result; | ||
| 38 | } | ||
| 39 | if (volume <= 0.0f) { | ||
| 40 | // TODO: SendVibrationValue | ||
| 41 | return ResultSuccess; | ||
| 42 | } | ||
| 43 | |||
| 44 | Core::HID::VibrationValue vibration_value = value; | ||
| 45 | vibration_value.high_amplitude *= volume; | ||
| 46 | vibration_value.low_amplitude *= volume; | ||
| 47 | |||
| 48 | // TODO: SendVibrationValue | ||
| 49 | return ResultSuccess; | ||
| 50 | } | ||
| 51 | |||
| 52 | Result NpadVibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u32 pattern) { | ||
| 53 | if (!is_mounted) { | ||
| 54 | return ResultSuccess; | ||
| 55 | } | ||
| 56 | |||
| 57 | f32 volume = 1.0f; | ||
| 58 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 59 | if (result.IsError()) { | ||
| 60 | return result; | ||
| 61 | } | ||
| 62 | if (volume <= 0.0) { | ||
| 63 | pattern = 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | // return xcd_handle->SendVibrationNotificationPattern(pattern); | ||
| 67 | return ResultSuccess; | ||
| 68 | } | ||
| 69 | |||
| 70 | Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) { | ||
| 71 | if (ref_counter < 1) { | ||
| 72 | return ResultVibrationNotInitialized; | ||
| 73 | } | ||
| 74 | |||
| 75 | out_value = Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 76 | if (!is_mounted) { | ||
| 77 | return ResultSuccess; | ||
| 78 | } | ||
| 79 | |||
| 80 | // TODO: SendVibrationValue | ||
| 81 | return ResultSuccess; | ||
| 82 | } | ||
| 83 | |||
| 84 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/vibration/vibration_device.h b/src/hid_core/resources/vibration/vibration_device.h new file mode 100644 index 000000000..3574ad60b --- /dev/null +++ b/src/hid_core/resources/vibration/vibration_device.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "hid_core/hid_types.h" | ||
| 12 | #include "hid_core/resources/npad/npad_types.h" | ||
| 13 | #include "hid_core/resources/vibration/vibration_base.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | class NpadVibration; | ||
| 17 | |||
| 18 | /// Handles Npad request from HID interfaces | ||
| 19 | class NpadVibrationDevice final : public NpadVibrationBase { | ||
| 20 | public: | ||
| 21 | explicit NpadVibrationDevice(); | ||
| 22 | |||
| 23 | Result IncrementRefCounter(); | ||
| 24 | Result DecrementRefCounter(); | ||
| 25 | |||
| 26 | Result SendVibrationValue(const Core::HID::VibrationValue& value); | ||
| 27 | Result SendVibrationNotificationPattern(u32 pattern); | ||
| 28 | |||
| 29 | Result GetActualVibrationValue(Core::HID::VibrationValue& out_value); | ||
| 30 | |||
| 31 | private: | ||
| 32 | u32 device_index{}; | ||
| 33 | }; | ||
| 34 | |||
| 35 | } // namespace Service::HID | ||
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 8b340ee6c..48ce860ad 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp | |||
| @@ -41,7 +41,7 @@ void UpdateController(Core::HID::EmulatedController* controller, | |||
| 41 | bool IsControllerCompatible(Core::HID::NpadStyleIndex controller_type, | 41 | bool IsControllerCompatible(Core::HID::NpadStyleIndex controller_type, |
| 42 | Core::Frontend::ControllerParameters parameters) { | 42 | Core::Frontend::ControllerParameters parameters) { |
| 43 | switch (controller_type) { | 43 | switch (controller_type) { |
| 44 | case Core::HID::NpadStyleIndex::ProController: | 44 | case Core::HID::NpadStyleIndex::Fullkey: |
| 45 | return parameters.allow_pro_controller; | 45 | return parameters.allow_pro_controller; |
| 46 | case Core::HID::NpadStyleIndex::JoyconDual: | 46 | case Core::HID::NpadStyleIndex::JoyconDual: |
| 47 | return parameters.allow_dual_joycons; | 47 | return parameters.allow_dual_joycons; |
| @@ -462,7 +462,7 @@ void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index | |||
| 462 | }; | 462 | }; |
| 463 | 463 | ||
| 464 | if (npad_style_set.fullkey == 1) { | 464 | if (npad_style_set.fullkey == 1) { |
| 465 | add_item(Core::HID::NpadStyleIndex::ProController, tr("Pro Controller")); | 465 | add_item(Core::HID::NpadStyleIndex::Fullkey, tr("Pro Controller")); |
| 466 | } | 466 | } |
| 467 | 467 | ||
| 468 | if (npad_style_set.joycon_dual == 1) { | 468 | if (npad_style_set.joycon_dual == 1) { |
| @@ -519,7 +519,7 @@ Core::HID::NpadStyleIndex QtControllerSelectorDialog::GetControllerTypeFromIndex | |||
| 519 | [index](const auto& pair) { return pair.first == index; }); | 519 | [index](const auto& pair) { return pair.first == index; }); |
| 520 | 520 | ||
| 521 | if (it == pairs.end()) { | 521 | if (it == pairs.end()) { |
| 522 | return Core::HID::NpadStyleIndex::ProController; | 522 | return Core::HID::NpadStyleIndex::Fullkey; |
| 523 | } | 523 | } |
| 524 | 524 | ||
| 525 | return it->second; | 525 | return it->second; |
| @@ -549,7 +549,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) | |||
| 549 | const QString stylesheet = [this, player_index] { | 549 | const QString stylesheet = [this, player_index] { |
| 550 | switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), | 550 | switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), |
| 551 | player_index)) { | 551 | player_index)) { |
| 552 | case Core::HID::NpadStyleIndex::ProController: | 552 | case Core::HID::NpadStyleIndex::Fullkey: |
| 553 | case Core::HID::NpadStyleIndex::GameCube: | 553 | case Core::HID::NpadStyleIndex::GameCube: |
| 554 | return QStringLiteral("image: url(:/controller/applet_pro_controller%0); "); | 554 | return QStringLiteral("image: url(:/controller/applet_pro_controller%0); "); |
| 555 | case Core::HID::NpadStyleIndex::JoyconDual: | 555 | case Core::HID::NpadStyleIndex::JoyconDual: |
diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp index bbe17c35e..ac81ace9e 100644 --- a/src/yuzu/applets/qt_software_keyboard.cpp +++ b/src/yuzu/applets/qt_software_keyboard.cpp | |||
| @@ -832,7 +832,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { | |||
| 832 | }(); | 832 | }(); |
| 833 | 833 | ||
| 834 | switch (controller_type) { | 834 | switch (controller_type) { |
| 835 | case Core::HID::NpadStyleIndex::ProController: | 835 | case Core::HID::NpadStyleIndex::Fullkey: |
| 836 | case Core::HID::NpadStyleIndex::GameCube: | 836 | case Core::HID::NpadStyleIndex::GameCube: |
| 837 | ui->icon_controller->setStyleSheet( | 837 | ui->icon_controller->setStyleSheet( |
| 838 | QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); | 838 | QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); |
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index f3552191a..5dac9f1e7 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -1094,7 +1094,7 @@ void ConfigureInputPlayer::SetConnectableControllers() { | |||
| 1094 | }; | 1094 | }; |
| 1095 | 1095 | ||
| 1096 | if (npad_style_set.fullkey == 1) { | 1096 | if (npad_style_set.fullkey == 1) { |
| 1097 | add_item(Core::HID::NpadStyleIndex::ProController, tr("Pro Controller")); | 1097 | add_item(Core::HID::NpadStyleIndex::Fullkey, tr("Pro Controller")); |
| 1098 | } | 1098 | } |
| 1099 | 1099 | ||
| 1100 | if (npad_style_set.joycon_dual == 1) { | 1100 | if (npad_style_set.joycon_dual == 1) { |
| @@ -1149,7 +1149,7 @@ Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int i | |||
| 1149 | [index](const auto& pair) { return pair.first == index; }); | 1149 | [index](const auto& pair) { return pair.first == index; }); |
| 1150 | 1150 | ||
| 1151 | if (it == index_controller_type_pairs.end()) { | 1151 | if (it == index_controller_type_pairs.end()) { |
| 1152 | return Core::HID::NpadStyleIndex::ProController; | 1152 | return Core::HID::NpadStyleIndex::Fullkey; |
| 1153 | } | 1153 | } |
| 1154 | 1154 | ||
| 1155 | return it->second; | 1155 | return it->second; |
| @@ -1178,7 +1178,7 @@ void ConfigureInputPlayer::UpdateInputDevices() { | |||
| 1178 | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | 1178 | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { |
| 1179 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | 1179 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); |
| 1180 | if (debug) { | 1180 | if (debug) { |
| 1181 | layout = Core::HID::NpadStyleIndex::ProController; | 1181 | layout = Core::HID::NpadStyleIndex::Fullkey; |
| 1182 | } | 1182 | } |
| 1183 | 1183 | ||
| 1184 | // List of all the widgets that will be hidden by any of the following layouts that need | 1184 | // List of all the widgets that will be hidden by any of the following layouts that need |
| @@ -1206,7 +1206,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | |||
| 1206 | 1206 | ||
| 1207 | std::vector<QWidget*> layout_hidden; | 1207 | std::vector<QWidget*> layout_hidden; |
| 1208 | switch (layout) { | 1208 | switch (layout) { |
| 1209 | case Core::HID::NpadStyleIndex::ProController: | 1209 | case Core::HID::NpadStyleIndex::Fullkey: |
| 1210 | case Core::HID::NpadStyleIndex::Handheld: | 1210 | case Core::HID::NpadStyleIndex::Handheld: |
| 1211 | layout_hidden = { | 1211 | layout_hidden = { |
| 1212 | ui->buttonShoulderButtonsSLSRLeft, | 1212 | ui->buttonShoulderButtonsSLSRLeft, |
| @@ -1254,7 +1254,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | |||
| 1254 | void ConfigureInputPlayer::UpdateControllerEnabledButtons() { | 1254 | void ConfigureInputPlayer::UpdateControllerEnabledButtons() { |
| 1255 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | 1255 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); |
| 1256 | if (debug) { | 1256 | if (debug) { |
| 1257 | layout = Core::HID::NpadStyleIndex::ProController; | 1257 | layout = Core::HID::NpadStyleIndex::Fullkey; |
| 1258 | } | 1258 | } |
| 1259 | 1259 | ||
| 1260 | // List of all the widgets that will be disabled by any of the following layouts that need | 1260 | // List of all the widgets that will be disabled by any of the following layouts that need |
| @@ -1271,7 +1271,7 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() { | |||
| 1271 | 1271 | ||
| 1272 | std::vector<QWidget*> layout_disable; | 1272 | std::vector<QWidget*> layout_disable; |
| 1273 | switch (layout) { | 1273 | switch (layout) { |
| 1274 | case Core::HID::NpadStyleIndex::ProController: | 1274 | case Core::HID::NpadStyleIndex::Fullkey: |
| 1275 | case Core::HID::NpadStyleIndex::JoyconDual: | 1275 | case Core::HID::NpadStyleIndex::JoyconDual: |
| 1276 | case Core::HID::NpadStyleIndex::Handheld: | 1276 | case Core::HID::NpadStyleIndex::Handheld: |
| 1277 | case Core::HID::NpadStyleIndex::JoyconLeft: | 1277 | case Core::HID::NpadStyleIndex::JoyconLeft: |
| @@ -1304,7 +1304,7 @@ void ConfigureInputPlayer::UpdateMotionButtons() { | |||
| 1304 | 1304 | ||
| 1305 | // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. | 1305 | // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. |
| 1306 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | 1306 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { |
| 1307 | case Core::HID::NpadStyleIndex::ProController: | 1307 | case Core::HID::NpadStyleIndex::Fullkey: |
| 1308 | case Core::HID::NpadStyleIndex::JoyconLeft: | 1308 | case Core::HID::NpadStyleIndex::JoyconLeft: |
| 1309 | case Core::HID::NpadStyleIndex::Handheld: | 1309 | case Core::HID::NpadStyleIndex::Handheld: |
| 1310 | // Show "Motion 1" and hide "Motion 2". | 1310 | // Show "Motion 1" and hide "Motion 2". |
| @@ -1333,11 +1333,11 @@ void ConfigureInputPlayer::UpdateMotionButtons() { | |||
| 1333 | void ConfigureInputPlayer::UpdateControllerButtonNames() { | 1333 | void ConfigureInputPlayer::UpdateControllerButtonNames() { |
| 1334 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | 1334 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); |
| 1335 | if (debug) { | 1335 | if (debug) { |
| 1336 | layout = Core::HID::NpadStyleIndex::ProController; | 1336 | layout = Core::HID::NpadStyleIndex::Fullkey; |
| 1337 | } | 1337 | } |
| 1338 | 1338 | ||
| 1339 | switch (layout) { | 1339 | switch (layout) { |
| 1340 | case Core::HID::NpadStyleIndex::ProController: | 1340 | case Core::HID::NpadStyleIndex::Fullkey: |
| 1341 | case Core::HID::NpadStyleIndex::JoyconDual: | 1341 | case Core::HID::NpadStyleIndex::JoyconDual: |
| 1342 | case Core::HID::NpadStyleIndex::Handheld: | 1342 | case Core::HID::NpadStyleIndex::Handheld: |
| 1343 | case Core::HID::NpadStyleIndex::JoyconLeft: | 1343 | case Core::HID::NpadStyleIndex::JoyconLeft: |
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 19fdca7d3..8f91f5e92 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp | |||
| @@ -244,7 +244,7 @@ void PlayerControlPreview::paintEvent(QPaintEvent* event) { | |||
| 244 | case Core::HID::NpadStyleIndex::GameCube: | 244 | case Core::HID::NpadStyleIndex::GameCube: |
| 245 | DrawGCController(p, center); | 245 | DrawGCController(p, center); |
| 246 | break; | 246 | break; |
| 247 | case Core::HID::NpadStyleIndex::ProController: | 247 | case Core::HID::NpadStyleIndex::Fullkey: |
| 248 | default: | 248 | default: |
| 249 | DrawProController(p, center); | 249 | DrawProController(p, center); |
| 250 | break; | 250 | break; |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 4f4c75f5c..fd5342537 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -3988,7 +3988,7 @@ void GMainWindow::OnToggleDockedMode() { | |||
| 3988 | tr("Handheld controller can't be used on docked mode. Pro " | 3988 | tr("Handheld controller can't be used on docked mode. Pro " |
| 3989 | "controller will be selected.")); | 3989 | "controller will be selected.")); |
| 3990 | handheld->Disconnect(); | 3990 | handheld->Disconnect(); |
| 3991 | player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); | 3991 | player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey); |
| 3992 | player_1->Connect(); | 3992 | player_1->Connect(); |
| 3993 | controller_dialog->refreshConfiguration(); | 3993 | controller_dialog->refreshConfiguration(); |
| 3994 | } | 3994 | } |
diff --git a/src/yuzu/util/controller_navigation.cpp b/src/yuzu/util/controller_navigation.cpp index 2690b075d..0dbfca243 100644 --- a/src/yuzu/util/controller_navigation.cpp +++ b/src/yuzu/util/controller_navigation.cpp | |||
| @@ -66,7 +66,7 @@ void ControllerNavigation::ControllerUpdateButton() { | |||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | switch (controller_type) { | 68 | switch (controller_type) { |
| 69 | case Core::HID::NpadStyleIndex::ProController: | 69 | case Core::HID::NpadStyleIndex::Fullkey: |
| 70 | case Core::HID::NpadStyleIndex::JoyconDual: | 70 | case Core::HID::NpadStyleIndex::JoyconDual: |
| 71 | case Core::HID::NpadStyleIndex::Handheld: | 71 | case Core::HID::NpadStyleIndex::Handheld: |
| 72 | case Core::HID::NpadStyleIndex::GameCube: | 72 | case Core::HID::NpadStyleIndex::GameCube: |
| @@ -116,7 +116,7 @@ void ControllerNavigation::ControllerUpdateStick() { | |||
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | switch (controller_type) { | 118 | switch (controller_type) { |
| 119 | case Core::HID::NpadStyleIndex::ProController: | 119 | case Core::HID::NpadStyleIndex::Fullkey: |
| 120 | case Core::HID::NpadStyleIndex::JoyconDual: | 120 | case Core::HID::NpadStyleIndex::JoyconDual: |
| 121 | case Core::HID::NpadStyleIndex::Handheld: | 121 | case Core::HID::NpadStyleIndex::Handheld: |
| 122 | case Core::HID::NpadStyleIndex::GameCube: | 122 | case Core::HID::NpadStyleIndex::GameCube: |