Compare commits
1 Commits
android-13
...
android-13
Author | SHA1 | Date | |
---|---|---|---|
f5dc5be691 |
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -4,6 +4,9 @@
|
|||||||
[submodule "enet"]
|
[submodule "enet"]
|
||||||
path = externals/enet
|
path = externals/enet
|
||||||
url = https://github.com/lsalzman/enet.git
|
url = https://github.com/lsalzman/enet.git
|
||||||
|
[submodule "inih"]
|
||||||
|
path = externals/inih/inih
|
||||||
|
url = https://github.com/benhoyt/inih.git
|
||||||
[submodule "cubeb"]
|
[submodule "cubeb"]
|
||||||
path = externals/cubeb
|
path = externals/cubeb
|
||||||
url = https://github.com/mozilla/cubeb.git
|
url = https://github.com/mozilla/cubeb.git
|
||||||
@ -58,6 +61,3 @@
|
|||||||
[submodule "breakpad"]
|
[submodule "breakpad"]
|
||||||
path = externals/breakpad
|
path = externals/breakpad
|
||||||
url = https://github.com/yuzu-emu/breakpad.git
|
url = https://github.com/yuzu-emu/breakpad.git
|
||||||
[submodule "simpleini"]
|
|
||||||
path = externals/simpleini
|
|
||||||
url = https://github.com/brofield/simpleini.git
|
|
||||||
|
@ -285,6 +285,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
|||||||
find_package(Boost 1.79.0 REQUIRED context)
|
find_package(Boost 1.79.0 REQUIRED context)
|
||||||
find_package(enet 1.3 MODULE)
|
find_package(enet 1.3 MODULE)
|
||||||
find_package(fmt 9 REQUIRED)
|
find_package(fmt 9 REQUIRED)
|
||||||
|
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||||
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
|
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
|
||||||
find_package(lz4 REQUIRED)
|
find_package(lz4 REQUIRED)
|
||||||
find_package(nlohmann_json 3.8 REQUIRED)
|
find_package(nlohmann_json 3.8 REQUIRED)
|
||||||
|
27
CMakeModules/Findinih.cmake
Normal file
27
CMakeModules/Findinih.cmake
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
find_package(PkgConfig QUIET)
|
||||||
|
pkg_search_module(INIH QUIET IMPORTED_TARGET inih)
|
||||||
|
if (INIReader IN_LIST inih_FIND_COMPONENTS)
|
||||||
|
pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader)
|
||||||
|
if (INIREADER_FOUND)
|
||||||
|
set(inih_INIReader_FOUND TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(inih
|
||||||
|
REQUIRED_VARS INIH_LINK_LIBRARIES
|
||||||
|
VERSION_VAR INIH_VERSION
|
||||||
|
HANDLE_COMPONENTS
|
||||||
|
)
|
||||||
|
|
||||||
|
if (inih_FOUND AND NOT TARGET inih::inih)
|
||||||
|
add_library(inih::inih ALIAS PkgConfig::INIH)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (inih_FOUND AND inih_INIReader_FOUND AND NOT TARGET inih::INIReader)
|
||||||
|
add_library(inih::INIReader ALIAS PkgConfig::INIREADER)
|
||||||
|
endif()
|
@ -1,8 +1,5 @@
|
|||||||
| Pull Request | Commit | Title | Author | Merged? |
|
| Pull Request | Commit | Title | Author | Merged? |
|
||||||
|----|----|----|----|----|
|
|----|----|----|----|----|
|
||||||
| [11535](https://github.com/yuzu-emu/yuzu//pull/11535) | [`50bcfa5fb`](https://github.com/yuzu-emu/yuzu//pull/11535/files) | renderer_vulkan: Introduce separate cmd buffer for uploads | [GPUCode](https://github.com/GPUCode/) | Yes |
|
|
||||||
| [11889](https://github.com/yuzu-emu/yuzu//pull/11889) | [`44fa74715`](https://github.com/yuzu-emu/yuzu//pull/11889/files) | configuration: Unify config handling across frontends | [t895](https://github.com/t895/) | Yes |
|
|
||||||
| [12036](https://github.com/yuzu-emu/yuzu//pull/12036) | [`c9437e524`](https://github.com/yuzu-emu/yuzu//pull/12036/files) | Query Cache: Disable write syncing on Android | [FernandoS27](https://github.com/FernandoS27/) | Yes |
|
|
||||||
|
|
||||||
|
|
||||||
End of merge log. You can find the original README.md below the break.
|
End of merge log. You can find the original README.md below the break.
|
||||||
|
8
externals/CMakeLists.txt
vendored
8
externals/CMakeLists.txt
vendored
@ -34,6 +34,11 @@ endif()
|
|||||||
# Glad
|
# Glad
|
||||||
add_subdirectory(glad)
|
add_subdirectory(glad)
|
||||||
|
|
||||||
|
# inih
|
||||||
|
if (NOT TARGET inih::INIReader)
|
||||||
|
add_subdirectory(inih)
|
||||||
|
endif()
|
||||||
|
|
||||||
# mbedtls
|
# mbedtls
|
||||||
add_subdirectory(mbedtls)
|
add_subdirectory(mbedtls)
|
||||||
target_include_directories(mbedtls PUBLIC ./mbedtls/include)
|
target_include_directories(mbedtls PUBLIC ./mbedtls/include)
|
||||||
@ -290,6 +295,3 @@ if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client)
|
|||||||
target_link_libraries(dump_syms PRIVATE libbreakpad_client ZLIB::ZLIB)
|
target_link_libraries(dump_syms PRIVATE libbreakpad_client ZLIB::ZLIB)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# SimpleIni
|
|
||||||
add_subdirectory(simpleini)
|
|
||||||
|
13
externals/inih/CMakeLists.txt
vendored
Normal file
13
externals/inih/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 Gui Andrade <admin@archshift.com>
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
add_library(inih
|
||||||
|
inih/ini.c
|
||||||
|
inih/ini.h
|
||||||
|
inih/cpp/INIReader.cpp
|
||||||
|
inih/cpp/INIReader.h
|
||||||
|
)
|
||||||
|
|
||||||
|
create_target_directory_groups(inih)
|
||||||
|
target_include_directories(inih INTERFACE inih/cpp)
|
||||||
|
add_library(inih::INIReader ALIAS inih)
|
1
externals/inih/inih
vendored
Submodule
1
externals/inih/inih
vendored
Submodule
Submodule externals/inih/inih added at 9cecf0643d
1
externals/simpleini
vendored
1
externals/simpleini
vendored
Submodule externals/simpleini deleted from 382ddbb4b9
@ -187,7 +187,6 @@ add_subdirectory(audio_core)
|
|||||||
add_subdirectory(video_core)
|
add_subdirectory(video_core)
|
||||||
add_subdirectory(network)
|
add_subdirectory(network)
|
||||||
add_subdirectory(input_common)
|
add_subdirectory(input_common)
|
||||||
add_subdirectory(frontend_common)
|
|
||||||
add_subdirectory(shader_recompiler)
|
add_subdirectory(shader_recompiler)
|
||||||
|
|
||||||
if (YUZU_ROOM)
|
if (YUZU_ROOM)
|
||||||
|
@ -219,6 +219,7 @@ dependencies {
|
|||||||
implementation("io.coil-kt:coil:2.2.2")
|
implementation("io.coil-kt:coil:2.2.2")
|
||||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||||
implementation("androidx.window:window:1.2.0-beta03")
|
implementation("androidx.window:window:1.2.0-beta03")
|
||||||
|
implementation("org.ini4j:ini4j:0.5.4")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
|
||||||
|
@ -230,6 +230,8 @@ object NativeLibrary {
|
|||||||
*/
|
*/
|
||||||
external fun onTouchReleased(finger_id: Int)
|
external fun onTouchReleased(finger_id: Int)
|
||||||
|
|
||||||
|
external fun reloadSettings()
|
||||||
|
|
||||||
external fun initGameIni(gameID: String?)
|
external fun initGameIni(gameID: String?)
|
||||||
|
|
||||||
external fun setAppDirectory(directory: String)
|
external fun setAppDirectory(directory: String)
|
||||||
|
@ -373,10 +373,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
val isEmulationActive = emulationViewModel.emulationStarted.value &&
|
|
||||||
!emulationViewModel.isEmulationStopping.value
|
|
||||||
pictureInPictureParamsBuilder.setAutoEnterEnabled(
|
pictureInPictureParamsBuilder.setAutoEnterEnabled(
|
||||||
BooleanSetting.PICTURE_IN_PICTURE.boolean && isEmulationActive
|
BooleanSetting.PICTURE_IN_PICTURE.boolean
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
||||||
|
@ -22,16 +22,12 @@ import androidx.core.graphics.drawable.toBitmap
|
|||||||
import androidx.core.graphics.drawable.toDrawable
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
@ -96,34 +92,28 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
|||||||
data = Uri.parse(holder.game.path)
|
data = Uri.parse(holder.game.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
activity.lifecycleScope.launch {
|
val layerDrawable = ResourcesCompat.getDrawable(
|
||||||
withContext(Dispatchers.IO) {
|
YuzuApplication.appContext.resources,
|
||||||
val layerDrawable = ResourcesCompat.getDrawable(
|
R.drawable.shortcut,
|
||||||
YuzuApplication.appContext.resources,
|
null
|
||||||
R.drawable.shortcut,
|
) as LayerDrawable
|
||||||
null
|
layerDrawable.setDrawableByLayerId(
|
||||||
) as LayerDrawable
|
R.id.shortcut_foreground,
|
||||||
layerDrawable.setDrawableByLayerId(
|
GameIconUtils.getGameIcon(holder.game).toDrawable(YuzuApplication.appContext.resources)
|
||||||
R.id.shortcut_foreground,
|
)
|
||||||
GameIconUtils.getGameIcon(activity, holder.game)
|
val inset = YuzuApplication.appContext.resources
|
||||||
.toDrawable(YuzuApplication.appContext.resources)
|
.getDimensionPixelSize(R.dimen.icon_inset)
|
||||||
|
layerDrawable.setLayerInset(1, inset, inset, inset, inset)
|
||||||
|
val shortcut = ShortcutInfoCompat.Builder(YuzuApplication.appContext, holder.game.path)
|
||||||
|
.setShortLabel(holder.game.title)
|
||||||
|
.setIcon(
|
||||||
|
IconCompat.createWithAdaptiveBitmap(
|
||||||
|
layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
|
||||||
)
|
)
|
||||||
val inset = YuzuApplication.appContext.resources
|
)
|
||||||
.getDimensionPixelSize(R.dimen.icon_inset)
|
.setIntent(openIntent)
|
||||||
layerDrawable.setLayerInset(1, inset, inset, inset, inset)
|
.build()
|
||||||
val shortcut =
|
ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
|
||||||
ShortcutInfoCompat.Builder(YuzuApplication.appContext, holder.game.path)
|
|
||||||
.setShortLabel(holder.game.title)
|
|
||||||
.setIcon(
|
|
||||||
IconCompat.createWithAdaptiveBitmap(
|
|
||||||
layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.setIntent(openIntent)
|
|
||||||
.build()
|
|
||||||
ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game)
|
val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game)
|
||||||
view.findNavController().navigate(action)
|
view.findNavController().navigate(action)
|
||||||
|
@ -7,7 +7,7 @@ import android.text.TextUtils
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||||
|
|
||||||
object Settings {
|
object Settings {
|
||||||
private val context get() = YuzuApplication.appContext
|
private val context get() = YuzuApplication.appContext
|
||||||
@ -19,7 +19,7 @@ object Settings {
|
|||||||
context.getString(R.string.ini_saved),
|
context.getString(R.string.ini_saved),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
NativeConfig.saveSettings()
|
SettingsFile.saveFile(SettingsFile.FILE_NAME_CONFIG)
|
||||||
} else {
|
} else {
|
||||||
// TODO: Save custom game settings
|
// TODO: Save custom game settings
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
@ -82,6 +82,7 @@ object Settings {
|
|||||||
|
|
||||||
enum class MenuTag(val titleId: Int) {
|
enum class MenuTag(val titleId: Int) {
|
||||||
SECTION_ROOT(R.string.advanced_settings),
|
SECTION_ROOT(R.string.advanced_settings),
|
||||||
|
SECTION_GENERAL(R.string.preferences_general),
|
||||||
SECTION_SYSTEM(R.string.preferences_system),
|
SECTION_SYSTEM(R.string.preferences_system),
|
||||||
SECTION_RENDERER(R.string.preferences_graphics),
|
SECTION_RENDERER(R.string.preferences_graphics),
|
||||||
SECTION_AUDIO(R.string.preferences_audio),
|
SECTION_AUDIO(R.string.preferences_audio),
|
||||||
|
@ -3,13 +3,10 @@
|
|||||||
|
|
||||||
package org.yuzu.yuzu_emu.features.settings.model.view
|
package org.yuzu.yuzu_emu.features.settings.model.view
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
|
||||||
|
|
||||||
class RunnableSetting(
|
class RunnableSetting(
|
||||||
titleId: Int,
|
titleId: Int,
|
||||||
descriptionId: Int,
|
descriptionId: Int,
|
||||||
val isRuntimeRunnable: Boolean,
|
val isRuntimeRunnable: Boolean,
|
||||||
@DrawableRes val iconId: Int = 0,
|
|
||||||
val runnable: () -> Unit
|
val runnable: () -> Unit
|
||||||
) : SettingsItem(emptySetting, titleId, descriptionId) {
|
) : SettingsItem(emptySetting, titleId, descriptionId) {
|
||||||
override val type = TYPE_RUNNABLE
|
override val type = TYPE_RUNNABLE
|
||||||
|
@ -3,14 +3,11 @@
|
|||||||
|
|
||||||
package org.yuzu.yuzu_emu.features.settings.model.view
|
package org.yuzu.yuzu_emu.features.settings.model.view
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
|
||||||
import androidx.annotation.StringRes
|
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
|
|
||||||
class SubmenuSetting(
|
class SubmenuSetting(
|
||||||
@StringRes titleId: Int,
|
titleId: Int,
|
||||||
@StringRes descriptionId: Int,
|
descriptionId: Int,
|
||||||
@DrawableRes val iconId: Int,
|
|
||||||
val menuKey: Settings.MenuTag
|
val menuKey: Settings.MenuTag
|
||||||
) : SettingsItem(emptySetting, titleId, descriptionId) {
|
) : SettingsItem(emptySetting, titleId, descriptionId) {
|
||||||
override val type = TYPE_SUBMENU
|
override val type = TYPE_SUBMENU
|
||||||
|
@ -21,6 +21,7 @@ import androidx.navigation.navArgs
|
|||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
|
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
|
||||||
@ -164,12 +165,11 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
settingsViewModel.shouldSave = false
|
settingsViewModel.shouldSave = false
|
||||||
|
|
||||||
// Delete settings file because the user may have changed values that do not exist in the UI
|
// Delete settings file because the user may have changed values that do not exist in the UI
|
||||||
NativeConfig.unloadConfig()
|
|
||||||
val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG)
|
val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG)
|
||||||
if (!settingsFile.delete()) {
|
if (!settingsFile.delete()) {
|
||||||
throw IOException("Failed to delete $settingsFile")
|
throw IOException("Failed to delete $settingsFile")
|
||||||
}
|
}
|
||||||
NativeConfig.initializeConfig()
|
NativeLibrary.reloadSettings()
|
||||||
|
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
|
@ -20,6 +20,7 @@ import androidx.lifecycle.repeatOnLifecycle
|
|||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.google.android.material.divider.MaterialDividerItemDecoration
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -67,9 +68,15 @@ class SettingsFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
binding.toolbarSettingsLayout.title = getString(args.menuTag.titleId)
|
binding.toolbarSettingsLayout.title = getString(args.menuTag.titleId)
|
||||||
|
val dividerDecoration = MaterialDividerItemDecoration(
|
||||||
|
requireContext(),
|
||||||
|
LinearLayoutManager.VERTICAL
|
||||||
|
)
|
||||||
|
dividerDecoration.isLastItemDecorated = false
|
||||||
binding.listSettings.apply {
|
binding.listSettings.apply {
|
||||||
adapter = settingsAdapter
|
adapter = settingsAdapter
|
||||||
layoutManager = LinearLayoutManager(requireContext())
|
layoutManager = LinearLayoutManager(requireContext())
|
||||||
|
addItemDecoration(dividerDecoration)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.toolbarSettings.setNavigationOnClickListener {
|
binding.toolbarSettings.setNavigationOnClickListener {
|
||||||
@ -87,6 +94,17 @@ class SettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
launch {
|
||||||
|
settingsViewModel.isUsingSearch.collectLatest {
|
||||||
|
if (it) {
|
||||||
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||||
|
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||||
|
} else {
|
||||||
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
|
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.menuTag == Settings.MenuTag.SECTION_ROOT) {
|
if (args.menuTag == Settings.MenuTag.SECTION_ROOT) {
|
||||||
@ -94,6 +112,8 @@ class SettingsFragment : Fragment() {
|
|||||||
binding.toolbarSettings.setOnMenuItemClickListener {
|
binding.toolbarSettings.setOnMenuItemClickListener {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
R.id.action_search -> {
|
R.id.action_search -> {
|
||||||
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||||
|
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||||
view.findNavController()
|
view.findNavController()
|
||||||
.navigate(R.id.action_settingsFragment_to_settingsSearchFragment)
|
.navigate(R.id.action_settingsFragment_to_settingsSearchFragment)
|
||||||
true
|
true
|
||||||
@ -109,6 +129,11 @@ class SettingsFragment : Fragment() {
|
|||||||
setInsets()
|
setInsets()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
settingsViewModel.setIsUsingSearch(false)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setInsets() {
|
private fun setInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
binding.root
|
binding.root
|
||||||
@ -119,9 +144,10 @@ class SettingsFragment : Fragment() {
|
|||||||
val leftInsets = barInsets.left + cutoutInsets.left
|
val leftInsets = barInsets.left + cutoutInsets.left
|
||||||
val rightInsets = barInsets.right + cutoutInsets.right
|
val rightInsets = barInsets.right + cutoutInsets.right
|
||||||
|
|
||||||
|
val sideMargin = resources.getDimensionPixelSize(R.dimen.spacing_medlarge)
|
||||||
val mlpSettingsList = binding.listSettings.layoutParams as MarginLayoutParams
|
val mlpSettingsList = binding.listSettings.layoutParams as MarginLayoutParams
|
||||||
mlpSettingsList.leftMargin = leftInsets
|
mlpSettingsList.leftMargin = sideMargin + leftInsets
|
||||||
mlpSettingsList.rightMargin = rightInsets
|
mlpSettingsList.rightMargin = sideMargin + rightInsets
|
||||||
binding.listSettings.layoutParams = mlpSettingsList
|
binding.listSettings.layoutParams = mlpSettingsList
|
||||||
binding.listSettings.updatePadding(
|
binding.listSettings.updatePadding(
|
||||||
bottom = barInsets.bottom
|
bottom = barInsets.bottom
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
package org.yuzu.yuzu_emu.features.settings.ui
|
package org.yuzu.yuzu_emu.features.settings.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@ -31,6 +32,8 @@ class SettingsFragmentPresenter(
|
|||||||
private val preferences: SharedPreferences
|
private val preferences: SharedPreferences
|
||||||
get() = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
get() = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||||
|
|
||||||
|
private val context: Context get() = YuzuApplication.appContext
|
||||||
|
|
||||||
// Extension for populating settings list based on paired settings
|
// Extension for populating settings list based on paired settings
|
||||||
fun ArrayList<SettingsItem>.add(key: String) {
|
fun ArrayList<SettingsItem>.add(key: String) {
|
||||||
val item = SettingsItem.settingsItems[key]!!
|
val item = SettingsItem.settingsItems[key]!!
|
||||||
@ -50,6 +53,7 @@ class SettingsFragmentPresenter(
|
|||||||
val sl = ArrayList<SettingsItem>()
|
val sl = ArrayList<SettingsItem>()
|
||||||
when (menuTag) {
|
when (menuTag) {
|
||||||
Settings.MenuTag.SECTION_ROOT -> addConfigSettings(sl)
|
Settings.MenuTag.SECTION_ROOT -> addConfigSettings(sl)
|
||||||
|
Settings.MenuTag.SECTION_GENERAL -> addGeneralSettings(sl)
|
||||||
Settings.MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
|
Settings.MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
|
||||||
Settings.MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
Settings.MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
||||||
Settings.MenuTag.SECTION_AUDIO -> addAudioSettings(sl)
|
Settings.MenuTag.SECTION_AUDIO -> addAudioSettings(sl)
|
||||||
@ -71,53 +75,30 @@ class SettingsFragmentPresenter(
|
|||||||
|
|
||||||
private fun addConfigSettings(sl: ArrayList<SettingsItem>) {
|
private fun addConfigSettings(sl: ArrayList<SettingsItem>) {
|
||||||
sl.apply {
|
sl.apply {
|
||||||
|
add(SubmenuSetting(R.string.preferences_general, 0, Settings.MenuTag.SECTION_GENERAL))
|
||||||
|
add(SubmenuSetting(R.string.preferences_system, 0, Settings.MenuTag.SECTION_SYSTEM))
|
||||||
|
add(SubmenuSetting(R.string.preferences_graphics, 0, Settings.MenuTag.SECTION_RENDERER))
|
||||||
|
add(SubmenuSetting(R.string.preferences_audio, 0, Settings.MenuTag.SECTION_AUDIO))
|
||||||
|
add(SubmenuSetting(R.string.preferences_debug, 0, Settings.MenuTag.SECTION_DEBUG))
|
||||||
add(
|
add(
|
||||||
SubmenuSetting(
|
RunnableSetting(R.string.reset_to_default, 0, false) {
|
||||||
R.string.preferences_system,
|
settingsViewModel.setShouldShowResetSettingsDialog(true)
|
||||||
R.string.preferences_system_description,
|
}
|
||||||
R.drawable.ic_system_settings,
|
|
||||||
Settings.MenuTag.SECTION_SYSTEM
|
|
||||||
)
|
|
||||||
)
|
|
||||||
add(
|
|
||||||
SubmenuSetting(
|
|
||||||
R.string.preferences_graphics,
|
|
||||||
R.string.preferences_graphics_description,
|
|
||||||
R.drawable.ic_graphics,
|
|
||||||
Settings.MenuTag.SECTION_RENDERER
|
|
||||||
)
|
|
||||||
)
|
|
||||||
add(
|
|
||||||
SubmenuSetting(
|
|
||||||
R.string.preferences_audio,
|
|
||||||
R.string.preferences_audio_description,
|
|
||||||
R.drawable.ic_audio,
|
|
||||||
Settings.MenuTag.SECTION_AUDIO
|
|
||||||
)
|
|
||||||
)
|
|
||||||
add(
|
|
||||||
SubmenuSetting(
|
|
||||||
R.string.preferences_debug,
|
|
||||||
R.string.preferences_debug_description,
|
|
||||||
R.drawable.ic_code,
|
|
||||||
Settings.MenuTag.SECTION_DEBUG
|
|
||||||
)
|
|
||||||
)
|
|
||||||
add(
|
|
||||||
RunnableSetting(
|
|
||||||
R.string.reset_to_default,
|
|
||||||
R.string.reset_to_default_description,
|
|
||||||
false,
|
|
||||||
R.drawable.ic_restore
|
|
||||||
) { settingsViewModel.setShouldShowResetSettingsDialog(true) }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addGeneralSettings(sl: ArrayList<SettingsItem>) {
|
||||||
|
sl.apply {
|
||||||
|
add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key)
|
||||||
|
add(ShortSetting.RENDERER_SPEED_LIMIT.key)
|
||||||
|
add(IntSetting.CPU_ACCURACY.key)
|
||||||
|
add(BooleanSetting.PICTURE_IN_PICTURE.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun addSystemSettings(sl: ArrayList<SettingsItem>) {
|
private fun addSystemSettings(sl: ArrayList<SettingsItem>) {
|
||||||
sl.apply {
|
sl.apply {
|
||||||
add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key)
|
|
||||||
add(ShortSetting.RENDERER_SPEED_LIMIT.key)
|
|
||||||
add(BooleanSetting.USE_DOCKED_MODE.key)
|
add(BooleanSetting.USE_DOCKED_MODE.key)
|
||||||
add(IntSetting.REGION_INDEX.key)
|
add(IntSetting.REGION_INDEX.key)
|
||||||
add(IntSetting.LANGUAGE_INDEX.key)
|
add(IntSetting.LANGUAGE_INDEX.key)
|
||||||
@ -135,7 +116,6 @@ class SettingsFragmentPresenter(
|
|||||||
add(IntSetting.RENDERER_ANTI_ALIASING.key)
|
add(IntSetting.RENDERER_ANTI_ALIASING.key)
|
||||||
add(IntSetting.RENDERER_SCREEN_LAYOUT.key)
|
add(IntSetting.RENDERER_SCREEN_LAYOUT.key)
|
||||||
add(IntSetting.RENDERER_ASPECT_RATIO.key)
|
add(IntSetting.RENDERER_ASPECT_RATIO.key)
|
||||||
add(BooleanSetting.PICTURE_IN_PICTURE.key)
|
|
||||||
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
|
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
|
||||||
add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key)
|
add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key)
|
||||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
||||||
@ -269,7 +249,6 @@ class SettingsFragmentPresenter(
|
|||||||
add(BooleanSetting.RENDERER_DEBUG.key)
|
add(BooleanSetting.RENDERER_DEBUG.key)
|
||||||
|
|
||||||
add(HeaderSetting(R.string.cpu))
|
add(HeaderSetting(R.string.cpu))
|
||||||
add(IntSetting.CPU_ACCURACY.key)
|
|
||||||
add(BooleanSetting.CPU_DEBUG_MODE.key)
|
add(BooleanSetting.CPU_DEBUG_MODE.key)
|
||||||
add(SettingsItem.FASTMEM_COMBINED)
|
add(SettingsItem.FASTMEM_COMBINED)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import org.yuzu.yuzu_emu.NativeLibrary
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.RunnableSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.RunnableSetting
|
||||||
@ -17,19 +16,6 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
|||||||
|
|
||||||
override fun bind(item: SettingsItem) {
|
override fun bind(item: SettingsItem) {
|
||||||
setting = item as RunnableSetting
|
setting = item as RunnableSetting
|
||||||
if (item.iconId != 0) {
|
|
||||||
binding.icon.visibility = View.VISIBLE
|
|
||||||
binding.icon.setImageDrawable(
|
|
||||||
ResourcesCompat.getDrawable(
|
|
||||||
binding.icon.resources,
|
|
||||||
item.iconId,
|
|
||||||
binding.icon.context.theme
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
binding.icon.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.textSettingName.setText(item.nameId)
|
binding.textSettingName.setText(item.nameId)
|
||||||
if (item.descriptionId != 0) {
|
if (item.descriptionId != 0) {
|
||||||
binding.textSettingDescription.setText(item.descriptionId)
|
binding.textSettingDescription.setText(item.descriptionId)
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SubmenuSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.SubmenuSetting
|
||||||
@ -16,19 +15,6 @@ class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAd
|
|||||||
|
|
||||||
override fun bind(item: SettingsItem) {
|
override fun bind(item: SettingsItem) {
|
||||||
this.item = item as SubmenuSetting
|
this.item = item as SubmenuSetting
|
||||||
if (item.iconId != 0) {
|
|
||||||
binding.icon.visibility = View.VISIBLE
|
|
||||||
binding.icon.setImageDrawable(
|
|
||||||
ResourcesCompat.getDrawable(
|
|
||||||
binding.icon.resources,
|
|
||||||
item.iconId,
|
|
||||||
binding.icon.context.theme
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
binding.icon.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.textSettingName.setText(item.nameId)
|
binding.textSettingName.setText(item.nameId)
|
||||||
if (item.descriptionId != 0) {
|
if (item.descriptionId != 0) {
|
||||||
binding.textSettingDescription.setText(item.descriptionId)
|
binding.textSettingDescription.setText(item.descriptionId)
|
||||||
|
@ -3,8 +3,15 @@
|
|||||||
|
|
||||||
package org.yuzu.yuzu_emu.features.settings.utils
|
package org.yuzu.yuzu_emu.features.settings.utils
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
import java.io.*
|
import java.io.*
|
||||||
|
import org.ini4j.Wini
|
||||||
|
import org.yuzu.yuzu_emu.R
|
||||||
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.*
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
|
import org.yuzu.yuzu_emu.utils.Log
|
||||||
|
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains static methods for interacting with .ini files in which settings are stored.
|
* Contains static methods for interacting with .ini files in which settings are stored.
|
||||||
@ -12,6 +19,41 @@ import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
|||||||
object SettingsFile {
|
object SettingsFile {
|
||||||
const val FILE_NAME_CONFIG = "config"
|
const val FILE_NAME_CONFIG = "config"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a Settings HashMap to a given .ini file on disk. If unsuccessful, outputs an error
|
||||||
|
* telling why it failed.
|
||||||
|
*
|
||||||
|
* @param fileName The target filename without a path or extension.
|
||||||
|
*/
|
||||||
|
fun saveFile(fileName: String) {
|
||||||
|
val ini = getSettingsFile(fileName)
|
||||||
|
try {
|
||||||
|
val wini = Wini(ini)
|
||||||
|
for (specificCategory in Settings.Category.values()) {
|
||||||
|
val categoryHeader = NativeConfig.getConfigHeader(specificCategory.ordinal)
|
||||||
|
for (setting in Settings.settingsList) {
|
||||||
|
if (setting.key!!.isEmpty()) continue
|
||||||
|
|
||||||
|
val settingCategoryHeader =
|
||||||
|
NativeConfig.getConfigHeader(setting.category.ordinal)
|
||||||
|
val iniSetting: String? = wini.get(categoryHeader, setting.key)
|
||||||
|
if (iniSetting != null || settingCategoryHeader == categoryHeader) {
|
||||||
|
wini.put(settingCategoryHeader, setting.key, setting.valueAsString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wini.store()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.message)
|
||||||
|
val context = YuzuApplication.appContext
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.getString(R.string.error_saving, fileName, e.message),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getSettingsFile(fileName: String): File =
|
fun getSettingsFile(fileName: String): File =
|
||||||
File(DirectoryInitialization.userDirectory + "/config/" + fileName + ".ini")
|
File(DirectoryInitialization.userDirectory + "/config/" + fileName + ".ini")
|
||||||
}
|
}
|
||||||
|
@ -114,10 +114,10 @@ class AboutFragment : Fragment() {
|
|||||||
val leftInsets = barInsets.left + cutoutInsets.left
|
val leftInsets = barInsets.left + cutoutInsets.left
|
||||||
val rightInsets = barInsets.right + cutoutInsets.right
|
val rightInsets = barInsets.right + cutoutInsets.right
|
||||||
|
|
||||||
val mlpToolbar = binding.toolbarAbout.layoutParams as MarginLayoutParams
|
val mlpAppBar = binding.appbarAbout.layoutParams as MarginLayoutParams
|
||||||
mlpToolbar.leftMargin = leftInsets
|
mlpAppBar.leftMargin = leftInsets
|
||||||
mlpToolbar.rightMargin = rightInsets
|
mlpAppBar.rightMargin = rightInsets
|
||||||
binding.toolbarAbout.layoutParams = mlpToolbar
|
binding.appbarAbout.layoutParams = mlpAppBar
|
||||||
|
|
||||||
val mlpScrollAbout = binding.scrollAbout.layoutParams as MarginLayoutParams
|
val mlpScrollAbout = binding.scrollAbout.layoutParams as MarginLayoutParams
|
||||||
mlpScrollAbout.leftMargin = leftInsets
|
mlpScrollAbout.leftMargin = leftInsets
|
||||||
|
@ -40,10 +40,8 @@ class SettingsSearchFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@ -57,6 +55,7 @@ class SettingsSearchFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
settingsViewModel.setIsUsingSearch(true)
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
binding.searchText.setText(savedInstanceState.getString(SEARCH_TEXT))
|
binding.searchText.setText(savedInstanceState.getString(SEARCH_TEXT))
|
||||||
|
@ -29,6 +29,9 @@ class SettingsViewModel : ViewModel() {
|
|||||||
val shouldReloadSettingsList: StateFlow<Boolean> get() = _shouldReloadSettingsList
|
val shouldReloadSettingsList: StateFlow<Boolean> get() = _shouldReloadSettingsList
|
||||||
private val _shouldReloadSettingsList = MutableStateFlow(false)
|
private val _shouldReloadSettingsList = MutableStateFlow(false)
|
||||||
|
|
||||||
|
val isUsingSearch: StateFlow<Boolean> get() = _isUsingSearch
|
||||||
|
private val _isUsingSearch = MutableStateFlow(false)
|
||||||
|
|
||||||
val sliderProgress: StateFlow<Int> get() = _sliderProgress
|
val sliderProgress: StateFlow<Int> get() = _sliderProgress
|
||||||
private val _sliderProgress = MutableStateFlow(-1)
|
private val _sliderProgress = MutableStateFlow(-1)
|
||||||
|
|
||||||
@ -54,6 +57,10 @@ class SettingsViewModel : ViewModel() {
|
|||||||
_shouldReloadSettingsList.value = value
|
_shouldReloadSettingsList.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setIsUsingSearch(value: Boolean) {
|
||||||
|
_isUsingSearch.value = value
|
||||||
|
}
|
||||||
|
|
||||||
fun setSliderTextValue(value: Float, units: String) {
|
fun setSliderTextValue(value: Float, units: String) {
|
||||||
_sliderProgress.value = value.toInt()
|
_sliderProgress.value = value.toInt()
|
||||||
_sliderTextValue.value = String.format(
|
_sliderTextValue.value = String.format(
|
||||||
|
@ -632,7 +632,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear existing user data
|
// Clear existing user data
|
||||||
NativeConfig.unloadConfig()
|
|
||||||
File(DirectoryInitialization.userDirectory!!).deleteRecursively()
|
File(DirectoryInitialization.userDirectory!!).deleteRecursively()
|
||||||
|
|
||||||
// Copy archive to internal storage
|
// Copy archive to internal storage
|
||||||
@ -651,7 +650,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||||||
|
|
||||||
// Reinitialize relevant data
|
// Reinitialize relevant data
|
||||||
NativeLibrary.initializeSystem(true)
|
NativeLibrary.initializeSystem(true)
|
||||||
NativeConfig.initializeConfig()
|
|
||||||
gamesViewModel.reloadGames(false)
|
gamesViewModel.reloadGames(false)
|
||||||
|
|
||||||
return@newInstance getString(R.string.user_data_import_success)
|
return@newInstance getString(R.string.user_data_import_success)
|
||||||
|
@ -16,7 +16,6 @@ object DirectoryInitialization {
|
|||||||
if (!areDirectoriesReady) {
|
if (!areDirectoriesReady) {
|
||||||
initializeInternalStorage()
|
initializeInternalStorage()
|
||||||
NativeLibrary.initializeSystem(false)
|
NativeLibrary.initializeSystem(false)
|
||||||
NativeConfig.initializeConfig()
|
|
||||||
areDirectoriesReady = true
|
areDirectoriesReady = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ import android.graphics.BitmapFactory
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.core.graphics.drawable.toDrawable
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
import androidx.lifecycle.LifecycleOwner
|
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.decode.DataSource
|
import coil.decode.DataSource
|
||||||
|
import coil.executeBlocking
|
||||||
import coil.fetch.DrawableResult
|
import coil.fetch.DrawableResult
|
||||||
import coil.fetch.FetchResult
|
import coil.fetch.FetchResult
|
||||||
import coil.fetch.Fetcher
|
import coil.fetch.Fetcher
|
||||||
@ -76,13 +76,12 @@ object GameIconUtils {
|
|||||||
imageLoader.enqueue(request)
|
imageLoader.enqueue(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGameIcon(lifecycleOwner: LifecycleOwner, game: Game): Bitmap {
|
fun getGameIcon(game: Game): Bitmap {
|
||||||
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
||||||
.data(game)
|
.data(game)
|
||||||
.lifecycle(lifecycleOwner)
|
|
||||||
.error(R.drawable.default_icon)
|
.error(R.drawable.default_icon)
|
||||||
.build()
|
.build()
|
||||||
return imageLoader.execute(request)
|
return imageLoader.executeBlocking(request)
|
||||||
.drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888)
|
.drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,30 +4,6 @@
|
|||||||
package org.yuzu.yuzu_emu.utils
|
package org.yuzu.yuzu_emu.utils
|
||||||
|
|
||||||
object NativeConfig {
|
object NativeConfig {
|
||||||
/**
|
|
||||||
* Creates a Config object and opens the emulation config.
|
|
||||||
*/
|
|
||||||
@Synchronized
|
|
||||||
external fun initializeConfig()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the stored config object. This automatically saves the existing config.
|
|
||||||
*/
|
|
||||||
@Synchronized
|
|
||||||
external fun unloadConfig()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads values saved to the config file and saves them.
|
|
||||||
*/
|
|
||||||
@Synchronized
|
|
||||||
external fun reloadSettings()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves settings values in memory to disk.
|
|
||||||
*/
|
|
||||||
@Synchronized
|
|
||||||
external fun saveSettings()
|
|
||||||
|
|
||||||
external fun getBoolean(key: String, getDefault: Boolean): Boolean
|
external fun getBoolean(key: String, getDefault: Boolean): Boolean
|
||||||
external fun setBoolean(key: String, value: Boolean)
|
external fun setBoolean(key: String, value: Boolean)
|
||||||
|
|
||||||
|
@ -6,6 +6,9 @@ add_library(yuzu-android SHARED
|
|||||||
android_common/android_common.h
|
android_common/android_common.h
|
||||||
applets/software_keyboard.cpp
|
applets/software_keyboard.cpp
|
||||||
applets/software_keyboard.h
|
applets/software_keyboard.h
|
||||||
|
config.cpp
|
||||||
|
config.h
|
||||||
|
default_ini.h
|
||||||
emu_window/emu_window.cpp
|
emu_window/emu_window.cpp
|
||||||
emu_window/emu_window.h
|
emu_window/emu_window.h
|
||||||
id_cache.cpp
|
id_cache.cpp
|
||||||
@ -13,17 +16,15 @@ add_library(yuzu-android SHARED
|
|||||||
native.cpp
|
native.cpp
|
||||||
native.h
|
native.h
|
||||||
native_config.cpp
|
native_config.cpp
|
||||||
android_settings.cpp
|
uisettings.cpp
|
||||||
game_metadata.cpp
|
game_metadata.cpp
|
||||||
native_log.cpp
|
native_log.cpp
|
||||||
android_config.cpp
|
|
||||||
android_config.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
|
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
|
||||||
|
|
||||||
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common)
|
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common)
|
||||||
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
|
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log)
|
||||||
if (ARCHITECTURE_arm64)
|
if (ARCHITECTURE_arm64)
|
||||||
target_link_libraries(yuzu-android PRIVATE adrenotools)
|
target_link_libraries(yuzu-android PRIVATE adrenotools)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "android_config.h"
|
|
||||||
#include "android_settings.h"
|
|
||||||
#include "common/settings_setting.h"
|
|
||||||
|
|
||||||
AndroidConfig::AndroidConfig(const std::string& config_name, ConfigType config_type)
|
|
||||||
: Config(config_type) {
|
|
||||||
Initialize(config_name);
|
|
||||||
if (config_type != ConfigType::InputProfile) {
|
|
||||||
ReadAndroidValues();
|
|
||||||
SaveAndroidValues();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidConfig::~AndroidConfig() {
|
|
||||||
if (global) {
|
|
||||||
AndroidConfig::SaveAllValues();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidConfig::ReloadAllValues() {
|
|
||||||
Reload();
|
|
||||||
ReadAndroidValues();
|
|
||||||
SaveAndroidValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidConfig::SaveAllValues() {
|
|
||||||
Save();
|
|
||||||
SaveAndroidValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidConfig::ReadAndroidValues() {
|
|
||||||
if (global) {
|
|
||||||
ReadAndroidUIValues();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidConfig::ReadAndroidUIValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Android));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Android);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidConfig::SaveAndroidValues() {
|
|
||||||
if (global) {
|
|
||||||
SaveAndroidUIValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteToIni();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidConfig::SaveAndroidUIValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Android));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Android);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Settings::BasicSetting*>& AndroidConfig::FindRelevantList(Settings::Category category) {
|
|
||||||
auto& map = Settings::values.linkage.by_category;
|
|
||||||
if (map.contains(category)) {
|
|
||||||
return Settings::values.linkage.by_category[category];
|
|
||||||
}
|
|
||||||
return AndroidSettings::values.linkage.by_category[category];
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "frontend_common/config.h"
|
|
||||||
|
|
||||||
class AndroidConfig final : public Config {
|
|
||||||
public:
|
|
||||||
explicit AndroidConfig(const std::string& config_name = "config",
|
|
||||||
ConfigType config_type = ConfigType::GlobalConfig);
|
|
||||||
~AndroidConfig() override;
|
|
||||||
|
|
||||||
void ReloadAllValues() override;
|
|
||||||
void SaveAllValues() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void ReadAndroidValues();
|
|
||||||
void ReadAndroidUIValues();
|
|
||||||
void ReadHidbusValues() override {}
|
|
||||||
void ReadDebugControlValues() override {}
|
|
||||||
void ReadPathValues() override {}
|
|
||||||
void ReadShortcutValues() override {}
|
|
||||||
void ReadUIValues() override {}
|
|
||||||
void ReadUIGamelistValues() override {}
|
|
||||||
void ReadUILayoutValues() override {}
|
|
||||||
void ReadMultiplayerValues() override {}
|
|
||||||
|
|
||||||
void SaveAndroidValues();
|
|
||||||
void SaveAndroidUIValues();
|
|
||||||
void SaveHidbusValues() override {}
|
|
||||||
void SaveDebugControlValues() override {}
|
|
||||||
void SavePathValues() override {}
|
|
||||||
void SaveShortcutValues() override {}
|
|
||||||
void SaveUIValues() override {}
|
|
||||||
void SaveUIGamelistValues() override {}
|
|
||||||
void SaveUILayoutValues() override {}
|
|
||||||
void SaveMultiplayerValues() override {}
|
|
||||||
|
|
||||||
std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override;
|
|
||||||
};
|
|
330
src/android/app/src/main/jni/config.cpp
Normal file
330
src/android/app/src/main/jni/config.cpp
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <INIReader.h>
|
||||||
|
#include "common/fs/file.h"
|
||||||
|
#include "common/fs/fs.h"
|
||||||
|
#include "common/fs/path_util.h"
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "common/settings_enums.h"
|
||||||
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
|
#include "input_common/main.h"
|
||||||
|
#include "jni/config.h"
|
||||||
|
#include "jni/default_ini.h"
|
||||||
|
#include "uisettings.h"
|
||||||
|
|
||||||
|
namespace FS = Common::FS;
|
||||||
|
|
||||||
|
Config::Config(const std::string& config_name, ConfigType config_type)
|
||||||
|
: type(config_type), global{config_type == ConfigType::GlobalConfig} {
|
||||||
|
Initialize(config_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::~Config() = default;
|
||||||
|
|
||||||
|
bool Config::LoadINI(const std::string& default_contents, bool retry) {
|
||||||
|
void(FS::CreateParentDir(config_loc));
|
||||||
|
config = std::make_unique<INIReader>(FS::PathToUTF8String(config_loc));
|
||||||
|
const auto config_loc_str = FS::PathToUTF8String(config_loc);
|
||||||
|
if (config->ParseError() < 0) {
|
||||||
|
if (retry) {
|
||||||
|
LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...",
|
||||||
|
config_loc_str);
|
||||||
|
|
||||||
|
void(FS::CreateParentDir(config_loc));
|
||||||
|
void(FS::WriteStringToFile(config_loc, FS::FileType::TextFile, default_contents));
|
||||||
|
|
||||||
|
config = std::make_unique<INIReader>(config_loc_str);
|
||||||
|
|
||||||
|
return LoadINI(default_contents, false);
|
||||||
|
}
|
||||||
|
LOG_ERROR(Config, "Failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOG_INFO(Config, "Successfully loaded {}", config_loc_str);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) {
|
||||||
|
std::string setting_value = config->Get(group, setting.GetLabel(), setting.GetDefault());
|
||||||
|
if (setting_value.empty()) {
|
||||||
|
setting_value = setting.GetDefault();
|
||||||
|
}
|
||||||
|
setting = std::move(setting_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) {
|
||||||
|
setting = config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type, bool ranged>
|
||||||
|
void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
|
||||||
|
setting = static_cast<Type>(
|
||||||
|
config->GetInteger(group, setting.GetLabel(), static_cast<long>(setting.GetDefault())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::ReadValues() {
|
||||||
|
ReadSetting("ControlsGeneral", Settings::values.mouse_enabled);
|
||||||
|
ReadSetting("ControlsGeneral", Settings::values.touch_device);
|
||||||
|
ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled);
|
||||||
|
ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled);
|
||||||
|
ReadSetting("ControlsGeneral", Settings::values.vibration_enabled);
|
||||||
|
ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations);
|
||||||
|
ReadSetting("ControlsGeneral", Settings::values.motion_enabled);
|
||||||
|
Settings::values.touchscreen.enabled =
|
||||||
|
config->GetBoolean("ControlsGeneral", "touch_enabled", true);
|
||||||
|
Settings::values.touchscreen.rotation_angle =
|
||||||
|
config->GetInteger("ControlsGeneral", "touch_angle", 0);
|
||||||
|
Settings::values.touchscreen.diameter_x =
|
||||||
|
config->GetInteger("ControlsGeneral", "touch_diameter_x", 15);
|
||||||
|
Settings::values.touchscreen.diameter_y =
|
||||||
|
config->GetInteger("ControlsGeneral", "touch_diameter_y", 15);
|
||||||
|
|
||||||
|
int num_touch_from_button_maps =
|
||||||
|
config->GetInteger("ControlsGeneral", "touch_from_button_map", 0);
|
||||||
|
if (num_touch_from_button_maps > 0) {
|
||||||
|
for (int i = 0; i < num_touch_from_button_maps; ++i) {
|
||||||
|
Settings::TouchFromButtonMap map;
|
||||||
|
map.name = config->Get("ControlsGeneral",
|
||||||
|
std::string("touch_from_button_maps_") + std::to_string(i) +
|
||||||
|
std::string("_name"),
|
||||||
|
"default");
|
||||||
|
const int num_touch_maps = config->GetInteger(
|
||||||
|
"ControlsGeneral",
|
||||||
|
std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"),
|
||||||
|
0);
|
||||||
|
map.buttons.reserve(num_touch_maps);
|
||||||
|
|
||||||
|
for (int j = 0; j < num_touch_maps; ++j) {
|
||||||
|
std::string touch_mapping =
|
||||||
|
config->Get("ControlsGeneral",
|
||||||
|
std::string("touch_from_button_maps_") + std::to_string(i) +
|
||||||
|
std::string("_bind_") + std::to_string(j),
|
||||||
|
"");
|
||||||
|
map.buttons.emplace_back(std::move(touch_mapping));
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::values.touch_from_button_maps.emplace_back(std::move(map));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Settings::values.touch_from_button_maps.emplace_back(
|
||||||
|
Settings::TouchFromButtonMap{"default", {}});
|
||||||
|
num_touch_from_button_maps = 1;
|
||||||
|
}
|
||||||
|
Settings::values.touch_from_button_map_index = std::clamp(
|
||||||
|
Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
|
||||||
|
|
||||||
|
ReadSetting("ControlsGeneral", Settings::values.udp_input_servers);
|
||||||
|
|
||||||
|
// Data Storage
|
||||||
|
ReadSetting("Data Storage", Settings::values.use_virtual_sd);
|
||||||
|
FS::SetYuzuPath(FS::YuzuPath::NANDDir,
|
||||||
|
config->Get("Data Storage", "nand_directory",
|
||||||
|
FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
|
||||||
|
FS::SetYuzuPath(FS::YuzuPath::SDMCDir,
|
||||||
|
config->Get("Data Storage", "sdmc_directory",
|
||||||
|
FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
|
||||||
|
FS::SetYuzuPath(FS::YuzuPath::LoadDir,
|
||||||
|
config->Get("Data Storage", "load_directory",
|
||||||
|
FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
|
||||||
|
FS::SetYuzuPath(FS::YuzuPath::DumpDir,
|
||||||
|
config->Get("Data Storage", "dump_directory",
|
||||||
|
FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
|
||||||
|
ReadSetting("Data Storage", Settings::values.gamecard_inserted);
|
||||||
|
ReadSetting("Data Storage", Settings::values.gamecard_current_game);
|
||||||
|
ReadSetting("Data Storage", Settings::values.gamecard_path);
|
||||||
|
|
||||||
|
// System
|
||||||
|
ReadSetting("System", Settings::values.current_user);
|
||||||
|
Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0,
|
||||||
|
Service::Account::MAX_USERS - 1);
|
||||||
|
|
||||||
|
// Disable docked mode by default on Android
|
||||||
|
Settings::values.use_docked_mode.SetValue(config->GetBoolean("System", "use_docked_mode", false)
|
||||||
|
? Settings::ConsoleMode::Docked
|
||||||
|
: Settings::ConsoleMode::Handheld);
|
||||||
|
|
||||||
|
const auto rng_seed_enabled = config->GetBoolean("System", "rng_seed_enabled", false);
|
||||||
|
if (rng_seed_enabled) {
|
||||||
|
Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0));
|
||||||
|
} else {
|
||||||
|
Settings::values.rng_seed.SetValue(0);
|
||||||
|
}
|
||||||
|
Settings::values.rng_seed_enabled.SetValue(rng_seed_enabled);
|
||||||
|
|
||||||
|
const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false);
|
||||||
|
if (custom_rtc_enabled) {
|
||||||
|
Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0);
|
||||||
|
} else {
|
||||||
|
Settings::values.custom_rtc = 0;
|
||||||
|
}
|
||||||
|
Settings::values.custom_rtc_enabled = custom_rtc_enabled;
|
||||||
|
|
||||||
|
ReadSetting("System", Settings::values.language_index);
|
||||||
|
ReadSetting("System", Settings::values.region_index);
|
||||||
|
ReadSetting("System", Settings::values.time_zone_index);
|
||||||
|
ReadSetting("System", Settings::values.sound_index);
|
||||||
|
|
||||||
|
// Core
|
||||||
|
ReadSetting("Core", Settings::values.use_multi_core);
|
||||||
|
ReadSetting("Core", Settings::values.memory_layout_mode);
|
||||||
|
|
||||||
|
// Cpu
|
||||||
|
ReadSetting("Cpu", Settings::values.cpu_accuracy);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpu_debug_mode);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_page_tables);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_block_linking);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_context_elimination);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_const_prop);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_misc_ir);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_fastmem);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check);
|
||||||
|
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_global_monitor);
|
||||||
|
|
||||||
|
// Renderer
|
||||||
|
ReadSetting("Renderer", Settings::values.renderer_backend);
|
||||||
|
ReadSetting("Renderer", Settings::values.renderer_debug);
|
||||||
|
ReadSetting("Renderer", Settings::values.renderer_shader_feedback);
|
||||||
|
ReadSetting("Renderer", Settings::values.enable_nsight_aftermath);
|
||||||
|
ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks);
|
||||||
|
ReadSetting("Renderer", Settings::values.vulkan_device);
|
||||||
|
|
||||||
|
ReadSetting("Renderer", Settings::values.resolution_setup);
|
||||||
|
ReadSetting("Renderer", Settings::values.scaling_filter);
|
||||||
|
ReadSetting("Renderer", Settings::values.fsr_sharpening_slider);
|
||||||
|
ReadSetting("Renderer", Settings::values.anti_aliasing);
|
||||||
|
ReadSetting("Renderer", Settings::values.fullscreen_mode);
|
||||||
|
ReadSetting("Renderer", Settings::values.aspect_ratio);
|
||||||
|
ReadSetting("Renderer", Settings::values.max_anisotropy);
|
||||||
|
ReadSetting("Renderer", Settings::values.use_speed_limit);
|
||||||
|
ReadSetting("Renderer", Settings::values.speed_limit);
|
||||||
|
ReadSetting("Renderer", Settings::values.use_disk_shader_cache);
|
||||||
|
ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation);
|
||||||
|
ReadSetting("Renderer", Settings::values.vsync_mode);
|
||||||
|
ReadSetting("Renderer", Settings::values.shader_backend);
|
||||||
|
ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
|
||||||
|
ReadSetting("Renderer", Settings::values.nvdec_emulation);
|
||||||
|
ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
|
||||||
|
ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
|
||||||
|
|
||||||
|
ReadSetting("Renderer", Settings::values.bg_red);
|
||||||
|
ReadSetting("Renderer", Settings::values.bg_green);
|
||||||
|
ReadSetting("Renderer", Settings::values.bg_blue);
|
||||||
|
|
||||||
|
// Use GPU accuracy normal by default on Android
|
||||||
|
Settings::values.gpu_accuracy = static_cast<Settings::GpuAccuracy>(config->GetInteger(
|
||||||
|
"Renderer", "gpu_accuracy", static_cast<u32>(Settings::GpuAccuracy::Normal)));
|
||||||
|
|
||||||
|
// Use GPU default anisotropic filtering on Android
|
||||||
|
Settings::values.max_anisotropy =
|
||||||
|
static_cast<Settings::AnisotropyMode>(config->GetInteger("Renderer", "max_anisotropy", 1));
|
||||||
|
|
||||||
|
// Disable ASTC compute by default on Android
|
||||||
|
Settings::values.accelerate_astc.SetValue(
|
||||||
|
config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu
|
||||||
|
: Settings::AstcDecodeMode::Cpu);
|
||||||
|
|
||||||
|
// Enable asynchronous presentation by default on Android
|
||||||
|
Settings::values.async_presentation =
|
||||||
|
config->GetBoolean("Renderer", "async_presentation", true);
|
||||||
|
|
||||||
|
// Disable force_max_clock by default on Android
|
||||||
|
Settings::values.renderer_force_max_clock =
|
||||||
|
config->GetBoolean("Renderer", "force_max_clock", false);
|
||||||
|
|
||||||
|
// Disable use_reactive_flushing by default on Android
|
||||||
|
Settings::values.use_reactive_flushing =
|
||||||
|
config->GetBoolean("Renderer", "use_reactive_flushing", false);
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
ReadSetting("Audio", Settings::values.sink_id);
|
||||||
|
ReadSetting("Audio", Settings::values.audio_output_device_id);
|
||||||
|
ReadSetting("Audio", Settings::values.volume);
|
||||||
|
|
||||||
|
// Miscellaneous
|
||||||
|
// log_filter has a different default here than from common
|
||||||
|
Settings::values.log_filter = "*:Info";
|
||||||
|
ReadSetting("Miscellaneous", Settings::values.use_dev_keys);
|
||||||
|
|
||||||
|
// Debugging
|
||||||
|
Settings::values.record_frame_times =
|
||||||
|
config->GetBoolean("Debugging", "record_frame_times", false);
|
||||||
|
ReadSetting("Debugging", Settings::values.dump_exefs);
|
||||||
|
ReadSetting("Debugging", Settings::values.dump_nso);
|
||||||
|
ReadSetting("Debugging", Settings::values.enable_fs_access_log);
|
||||||
|
ReadSetting("Debugging", Settings::values.reporting_services);
|
||||||
|
ReadSetting("Debugging", Settings::values.quest_flag);
|
||||||
|
ReadSetting("Debugging", Settings::values.use_debug_asserts);
|
||||||
|
ReadSetting("Debugging", Settings::values.use_auto_stub);
|
||||||
|
ReadSetting("Debugging", Settings::values.disable_macro_jit);
|
||||||
|
ReadSetting("Debugging", Settings::values.disable_macro_hle);
|
||||||
|
ReadSetting("Debugging", Settings::values.use_gdbstub);
|
||||||
|
ReadSetting("Debugging", Settings::values.gdbstub_port);
|
||||||
|
|
||||||
|
const auto title_list = config->Get("AddOns", "title_ids", "");
|
||||||
|
std::stringstream ss(title_list);
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(ss, line, '|')) {
|
||||||
|
const auto title_id = std::strtoul(line.c_str(), nullptr, 16);
|
||||||
|
const auto disabled_list = config->Get("AddOns", "disabled_" + line, "");
|
||||||
|
|
||||||
|
std::stringstream inner_ss(disabled_list);
|
||||||
|
std::string inner_line;
|
||||||
|
std::vector<std::string> out;
|
||||||
|
while (std::getline(inner_ss, inner_line, '|')) {
|
||||||
|
out.push_back(inner_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::values.disabled_addons.insert_or_assign(title_id, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Web Service
|
||||||
|
ReadSetting("WebService", Settings::values.enable_telemetry);
|
||||||
|
ReadSetting("WebService", Settings::values.web_api_url);
|
||||||
|
ReadSetting("WebService", Settings::values.yuzu_username);
|
||||||
|
ReadSetting("WebService", Settings::values.yuzu_token);
|
||||||
|
|
||||||
|
// Network
|
||||||
|
ReadSetting("Network", Settings::values.network_interface);
|
||||||
|
|
||||||
|
// Android
|
||||||
|
ReadSetting("Android", AndroidSettings::values.picture_in_picture);
|
||||||
|
ReadSetting("Android", AndroidSettings::values.screen_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::Initialize(const std::string& config_name) {
|
||||||
|
const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
|
||||||
|
const auto config_file = fmt::format("{}.ini", config_name);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case ConfigType::GlobalConfig:
|
||||||
|
config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
|
||||||
|
break;
|
||||||
|
case ConfigType::PerGameConfig:
|
||||||
|
config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
|
||||||
|
break;
|
||||||
|
case ConfigType::InputProfile:
|
||||||
|
config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
|
||||||
|
LoadINI(DefaultINI::android_config_file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LoadINI(DefaultINI::android_config_file);
|
||||||
|
ReadValues();
|
||||||
|
}
|
47
src/android/app/src/main/jni/config.h
Normal file
47
src/android/app/src/main/jni/config.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "common/settings.h"
|
||||||
|
|
||||||
|
class INIReader;
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
bool LoadINI(const std::string& default_contents = "", bool retry = true);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class ConfigType {
|
||||||
|
GlobalConfig,
|
||||||
|
PerGameConfig,
|
||||||
|
InputProfile,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Config(const std::string& config_name = "config",
|
||||||
|
ConfigType config_type = ConfigType::GlobalConfig);
|
||||||
|
~Config();
|
||||||
|
|
||||||
|
void Initialize(const std::string& config_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Applies a value read from the config to a Setting.
|
||||||
|
*
|
||||||
|
* @param group The name of the INI group
|
||||||
|
* @param setting The yuzu setting to modify
|
||||||
|
*/
|
||||||
|
template <typename Type, bool ranged>
|
||||||
|
void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
|
||||||
|
|
||||||
|
void ReadValues();
|
||||||
|
|
||||||
|
const ConfigType type;
|
||||||
|
std::unique_ptr<INIReader> config;
|
||||||
|
std::string config_loc;
|
||||||
|
const bool global;
|
||||||
|
};
|
511
src/android/app/src/main/jni/default_ini.h
Normal file
511
src/android/app/src/main/jni/default_ini.h
Normal file
@ -0,0 +1,511 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace DefaultINI {
|
||||||
|
|
||||||
|
const char* android_config_file = R"(
|
||||||
|
|
||||||
|
[ControlsP0]
|
||||||
|
# The input devices and parameters for each Switch native input
|
||||||
|
# The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ...
|
||||||
|
# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
|
||||||
|
# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
|
||||||
|
|
||||||
|
# Indicates if this player should be connected at boot
|
||||||
|
connected=
|
||||||
|
|
||||||
|
# for button input, the following devices are available:
|
||||||
|
# - "keyboard" (default) for keyboard input. Required parameters:
|
||||||
|
# - "code": the code of the key to bind
|
||||||
|
# - "sdl" for joystick input using SDL. Required parameters:
|
||||||
|
# - "guid": SDL identification GUID of the joystick
|
||||||
|
# - "port": the index of the joystick to bind
|
||||||
|
# - "button"(optional): the index of the button to bind
|
||||||
|
# - "hat"(optional): the index of the hat to bind as direction buttons
|
||||||
|
# - "axis"(optional): the index of the axis to bind
|
||||||
|
# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right"
|
||||||
|
# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
|
||||||
|
# triggered if the axis value crosses
|
||||||
|
# - "direction"(only used for axis): "+" means the button is triggered when the axis value
|
||||||
|
# is greater than the threshold; "-" means the button is triggered when the axis value
|
||||||
|
# is smaller than the threshold
|
||||||
|
button_a=
|
||||||
|
button_b=
|
||||||
|
button_x=
|
||||||
|
button_y=
|
||||||
|
button_lstick=
|
||||||
|
button_rstick=
|
||||||
|
button_l=
|
||||||
|
button_r=
|
||||||
|
button_zl=
|
||||||
|
button_zr=
|
||||||
|
button_plus=
|
||||||
|
button_minus=
|
||||||
|
button_dleft=
|
||||||
|
button_dup=
|
||||||
|
button_dright=
|
||||||
|
button_ddown=
|
||||||
|
button_lstick_left=
|
||||||
|
button_lstick_up=
|
||||||
|
button_lstick_right=
|
||||||
|
button_lstick_down=
|
||||||
|
button_sl=
|
||||||
|
button_sr=
|
||||||
|
button_home=
|
||||||
|
button_screenshot=
|
||||||
|
|
||||||
|
# for analog input, the following devices are available:
|
||||||
|
# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters:
|
||||||
|
# - "up", "down", "left", "right": sub-devices for each direction.
|
||||||
|
# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00"
|
||||||
|
# - "modifier": sub-devices as a modifier.
|
||||||
|
# - "modifier_scale": a float number representing the applied modifier scale to the analog input.
|
||||||
|
# Must be in range of 0.0-1.0. Defaults to 0.5
|
||||||
|
# - "sdl" for joystick input using SDL. Required parameters:
|
||||||
|
# - "guid": SDL identification GUID of the joystick
|
||||||
|
# - "port": the index of the joystick to bind
|
||||||
|
# - "axis_x": the index of the axis to bind as x-axis (default to 0)
|
||||||
|
# - "axis_y": the index of the axis to bind as y-axis (default to 1)
|
||||||
|
lstick=
|
||||||
|
rstick=
|
||||||
|
|
||||||
|
# for motion input, the following devices are available:
|
||||||
|
# - "keyboard" (default) for emulating random motion input from buttons. Required parameters:
|
||||||
|
# - "code": the code of the key to bind
|
||||||
|
# - "sdl" for motion input using SDL. Required parameters:
|
||||||
|
# - "guid": SDL identification GUID of the joystick
|
||||||
|
# - "port": the index of the joystick to bind
|
||||||
|
# - "motion": the index of the motion sensor to bind
|
||||||
|
# - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters:
|
||||||
|
# - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001"
|
||||||
|
# - "port": the port of the cemu hook server
|
||||||
|
# - "pad": the index of the joystick
|
||||||
|
# - "motion": the index of the motion sensor of the joystick to bind
|
||||||
|
motionleft=
|
||||||
|
motionright=
|
||||||
|
|
||||||
|
[ControlsGeneral]
|
||||||
|
# To use the debug_pad, prepend `debug_pad_` before each button setting above.
|
||||||
|
# i.e. debug_pad_button_a=
|
||||||
|
|
||||||
|
# Enable debug pad inputs to the guest
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
debug_pad_enabled =
|
||||||
|
|
||||||
|
# Whether to enable or disable vibration
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
vibration_enabled=
|
||||||
|
|
||||||
|
# Whether to enable or disable accurate vibrations
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
enable_accurate_vibrations=
|
||||||
|
|
||||||
|
# Enables controller motion inputs
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
motion_enabled =
|
||||||
|
|
||||||
|
# Defines the udp device's touch screen coordinate system for cemuhookudp devices
|
||||||
|
# - "min_x", "min_y", "max_x", "max_y"
|
||||||
|
touch_device=
|
||||||
|
|
||||||
|
# for mapping buttons to touch inputs.
|
||||||
|
#touch_from_button_map=1
|
||||||
|
#touch_from_button_maps_0_name=default
|
||||||
|
#touch_from_button_maps_0_count=2
|
||||||
|
#touch_from_button_maps_0_bind_0=foo
|
||||||
|
#touch_from_button_maps_0_bind_1=bar
|
||||||
|
# etc.
|
||||||
|
|
||||||
|
# List of Cemuhook UDP servers, delimited by ','.
|
||||||
|
# Default: 127.0.0.1:26760
|
||||||
|
# Example: 127.0.0.1:26760,123.4.5.67:26761
|
||||||
|
udp_input_servers =
|
||||||
|
|
||||||
|
# Enable controlling an axis via a mouse input.
|
||||||
|
# 0 (default): Off, 1: On
|
||||||
|
mouse_panning =
|
||||||
|
|
||||||
|
# Set mouse sensitivity.
|
||||||
|
# Default: 1.0
|
||||||
|
mouse_panning_sensitivity =
|
||||||
|
|
||||||
|
# Emulate an analog control stick from keyboard inputs.
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
emulate_analog_keyboard =
|
||||||
|
|
||||||
|
# Enable mouse inputs to the guest
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
mouse_enabled =
|
||||||
|
|
||||||
|
# Enable keyboard inputs to the guest
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
keyboard_enabled =
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
# Whether to use multi-core for CPU emulation
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
use_multi_core =
|
||||||
|
|
||||||
|
# Enable unsafe extended guest system memory layout (8GB DRAM)
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
use_unsafe_extended_memory_layout =
|
||||||
|
|
||||||
|
[Cpu]
|
||||||
|
# Adjusts various optimizations.
|
||||||
|
# Auto-select mode enables choice unsafe optimizations.
|
||||||
|
# Accurate enables only safe optimizations.
|
||||||
|
# Unsafe allows any unsafe optimizations.
|
||||||
|
# 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations
|
||||||
|
cpu_accuracy =
|
||||||
|
|
||||||
|
# Allow disabling safe optimizations.
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
cpu_debug_mode =
|
||||||
|
|
||||||
|
# Enable inline page tables optimization (faster guest memory access)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_page_tables =
|
||||||
|
|
||||||
|
# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_block_linking =
|
||||||
|
|
||||||
|
# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_return_stack_buffer =
|
||||||
|
|
||||||
|
# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_fast_dispatcher =
|
||||||
|
|
||||||
|
# Enable context elimination CPU Optimization (reduce host memory use for guest context)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_context_elimination =
|
||||||
|
|
||||||
|
# Enable constant propagation CPU optimization (basic IR optimization)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_const_prop =
|
||||||
|
|
||||||
|
# Enable miscellaneous CPU optimizations (basic IR optimization)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_misc_ir =
|
||||||
|
|
||||||
|
# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_reduce_misalign_checks =
|
||||||
|
|
||||||
|
# Enable Host MMU Emulation (faster guest memory access)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_fastmem =
|
||||||
|
|
||||||
|
# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_fastmem_exclusives =
|
||||||
|
|
||||||
|
# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_recompile_exclusives =
|
||||||
|
|
||||||
|
# Enable optimization to ignore invalid memory accesses (faster guest memory access)
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_ignore_memory_aborts =
|
||||||
|
|
||||||
|
# Enable unfuse FMA (improve performance on CPUs without FMA)
|
||||||
|
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_unsafe_unfuse_fma =
|
||||||
|
|
||||||
|
# Enable faster FRSQRTE and FRECPE
|
||||||
|
# Only enabled if cpu_accuracy is set to Unsafe.
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_unsafe_reduce_fp_error =
|
||||||
|
|
||||||
|
# Enable faster ASIMD instructions (32 bits only)
|
||||||
|
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_unsafe_ignore_standard_fpcr =
|
||||||
|
|
||||||
|
# Enable inaccurate NaN handling
|
||||||
|
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_unsafe_inaccurate_nan =
|
||||||
|
|
||||||
|
# Disable address space checks (64 bits only)
|
||||||
|
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_unsafe_fastmem_check =
|
||||||
|
|
||||||
|
# Enable faster exclusive instructions
|
||||||
|
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||||
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
cpuopt_unsafe_ignore_global_monitor =
|
||||||
|
|
||||||
|
[Renderer]
|
||||||
|
# Which backend API to use.
|
||||||
|
# 0: OpenGL (unsupported), 1 (default): Vulkan, 2: Null
|
||||||
|
backend =
|
||||||
|
|
||||||
|
# Whether to enable asynchronous presentation (Vulkan only)
|
||||||
|
# 0: Off, 1 (default): On
|
||||||
|
async_presentation =
|
||||||
|
|
||||||
|
# Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied).
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
force_max_clock =
|
||||||
|
|
||||||
|
# Enable graphics API debugging mode.
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
debug =
|
||||||
|
|
||||||
|
# Enable shader feedback.
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
renderer_shader_feedback =
|
||||||
|
|
||||||
|
# Enable Nsight Aftermath crash dumps
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
nsight_aftermath =
|
||||||
|
|
||||||
|
# Disable shader loop safety checks, executing the shader without loop logic changes
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
disable_shader_loop_safety_checks =
|
||||||
|
|
||||||
|
# Which Vulkan physical device to use (defaults to 0)
|
||||||
|
vulkan_device =
|
||||||
|
|
||||||
|
# 0: 0.5x (360p/540p) [EXPERIMENTAL]
|
||||||
|
# 1: 0.75x (540p/810p) [EXPERIMENTAL]
|
||||||
|
# 2 (default): 1x (720p/1080p)
|
||||||
|
# 3: 2x (1440p/2160p)
|
||||||
|
# 4: 3x (2160p/3240p)
|
||||||
|
# 5: 4x (2880p/4320p)
|
||||||
|
# 6: 5x (3600p/5400p)
|
||||||
|
# 7: 6x (4320p/6480p)
|
||||||
|
resolution_setup =
|
||||||
|
|
||||||
|
# Pixel filter to use when up- or down-sampling rendered frames.
|
||||||
|
# 0: Nearest Neighbor
|
||||||
|
# 1 (default): Bilinear
|
||||||
|
# 2: Bicubic
|
||||||
|
# 3: Gaussian
|
||||||
|
# 4: ScaleForce
|
||||||
|
# 5: AMD FidelityFX™️ Super Resolution [Vulkan Only]
|
||||||
|
scaling_filter =
|
||||||
|
|
||||||
|
# Anti-Aliasing (AA)
|
||||||
|
# 0 (default): None, 1: FXAA
|
||||||
|
anti_aliasing =
|
||||||
|
|
||||||
|
# Whether to use fullscreen or borderless window mode
|
||||||
|
# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen
|
||||||
|
fullscreen_mode =
|
||||||
|
|
||||||
|
# Aspect ratio
|
||||||
|
# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window
|
||||||
|
aspect_ratio =
|
||||||
|
|
||||||
|
# Anisotropic filtering
|
||||||
|
# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x
|
||||||
|
max_anisotropy =
|
||||||
|
|
||||||
|
# Whether to enable VSync or not.
|
||||||
|
# OpenGL: Values other than 0 enable VSync
|
||||||
|
# Vulkan: FIFO is selected if the requested mode is not supported by the driver.
|
||||||
|
# FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate.
|
||||||
|
# FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down.
|
||||||
|
# Mailbox can have lower latency than FIFO and does not tear but may drop frames.
|
||||||
|
# Immediate (no synchronization) just presents whatever is available and can exhibit tearing.
|
||||||
|
# 0: Immediate (Off), 1 (Default): Mailbox (On), 2: FIFO, 3: FIFO Relaxed
|
||||||
|
use_vsync =
|
||||||
|
|
||||||
|
# Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is
|
||||||
|
# not available and GLASM is selected, GLSL will be used.
|
||||||
|
# 0: GLSL, 1 (default): GLASM, 2: SPIR-V
|
||||||
|
shader_backend =
|
||||||
|
|
||||||
|
# Whether to allow asynchronous shader building.
|
||||||
|
# 0 (default): Off, 1: On
|
||||||
|
use_asynchronous_shaders =
|
||||||
|
|
||||||
|
# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.
|
||||||
|
# 0 (default): Off, 1: On
|
||||||
|
use_reactive_flushing =
|
||||||
|
|
||||||
|
# NVDEC emulation.
|
||||||
|
# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding
|
||||||
|
nvdec_emulation =
|
||||||
|
|
||||||
|
# Accelerate ASTC texture decoding.
|
||||||
|
# 0 (default): Off, 1: On
|
||||||
|
accelerate_astc =
|
||||||
|
|
||||||
|
# Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value
|
||||||
|
# 0: Off, 1: On (default)
|
||||||
|
use_speed_limit =
|
||||||
|
|
||||||
|
# Limits the speed of the game to run no faster than this value as a percentage of target speed
|
||||||
|
# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
|
||||||
|
speed_limit =
|
||||||
|
|
||||||
|
# Whether to use disk based shader cache
|
||||||
|
# 0: Off, 1 (default): On
|
||||||
|
use_disk_shader_cache =
|
||||||
|
|
||||||
|
# Which gpu accuracy level to use
|
||||||
|
# 0 (default): Normal, 1: High, 2: Extreme (Very slow)
|
||||||
|
gpu_accuracy =
|
||||||
|
|
||||||
|
# Whether to use asynchronous GPU emulation
|
||||||
|
# 0 : Off (slow), 1 (default): On (fast)
|
||||||
|
use_asynchronous_gpu_emulation =
|
||||||
|
|
||||||
|
# Inform the guest that GPU operations completed more quickly than they did.
|
||||||
|
# 0: Off, 1 (default): On
|
||||||
|
use_fast_gpu_time =
|
||||||
|
|
||||||
|
# Force unmodified buffers to be flushed, which can cost performance.
|
||||||
|
# 0: Off (default), 1: On
|
||||||
|
use_pessimistic_flushes =
|
||||||
|
|
||||||
|
# Whether to use garbage collection or not for GPU caches.
|
||||||
|
# 0 (default): Off, 1: On
|
||||||
|
use_caches_gc =
|
||||||
|
|
||||||
|
# The clear color for the renderer. What shows up on the sides of the bottom screen.
|
||||||
|
# Must be in range of 0-255. Defaults to 0 for all.
|
||||||
|
bg_red =
|
||||||
|
bg_blue =
|
||||||
|
bg_green =
|
||||||
|
|
||||||
|
[Audio]
|
||||||
|
# Which audio output engine to use.
|
||||||
|
# auto (default): Auto-select
|
||||||
|
# cubeb: Cubeb audio engine (if available)
|
||||||
|
# sdl2: SDL2 audio engine (if available)
|
||||||
|
# null: No audio output
|
||||||
|
output_engine =
|
||||||
|
|
||||||
|
# Which audio device to use.
|
||||||
|
# auto (default): Auto-select
|
||||||
|
output_device =
|
||||||
|
|
||||||
|
# Output volume.
|
||||||
|
# 100 (default): 100%, 0; mute
|
||||||
|
volume =
|
||||||
|
|
||||||
|
[Data Storage]
|
||||||
|
# Whether to create a virtual SD card.
|
||||||
|
# 1: Yes, 0 (default): No
|
||||||
|
use_virtual_sd =
|
||||||
|
|
||||||
|
# Whether or not to enable gamecard emulation
|
||||||
|
# 1: Yes, 0 (default): No
|
||||||
|
gamecard_inserted =
|
||||||
|
|
||||||
|
# Whether or not the gamecard should be emulated as the current game
|
||||||
|
# If 'gamecard_inserted' is 0 this setting is irrelevant
|
||||||
|
# 1: Yes, 0 (default): No
|
||||||
|
gamecard_current_game =
|
||||||
|
|
||||||
|
# Path to an XCI file to use as the gamecard
|
||||||
|
# If 'gamecard_inserted' is 0 this setting is irrelevant
|
||||||
|
# If 'gamecard_current_game' is 1 this setting is irrelevant
|
||||||
|
gamecard_path =
|
||||||
|
|
||||||
|
[System]
|
||||||
|
# Whether the system is docked
|
||||||
|
# 1 (default): Yes, 0: No
|
||||||
|
use_docked_mode =
|
||||||
|
|
||||||
|
# Sets the seed for the RNG generator built into the switch
|
||||||
|
# rng_seed will be ignored and randomly generated if rng_seed_enabled is false
|
||||||
|
rng_seed_enabled =
|
||||||
|
rng_seed =
|
||||||
|
|
||||||
|
# Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service
|
||||||
|
# This will auto-increment, with the time set being the time the game is started
|
||||||
|
# This override will only occur if custom_rtc_enabled is true, otherwise the current time is used
|
||||||
|
custom_rtc_enabled =
|
||||||
|
custom_rtc =
|
||||||
|
|
||||||
|
# Sets the systems language index
|
||||||
|
# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese,
|
||||||
|
# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French,
|
||||||
|
# 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese
|
||||||
|
language_index =
|
||||||
|
|
||||||
|
# The system region that yuzu will use during emulation
|
||||||
|
# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
|
||||||
|
region_index =
|
||||||
|
|
||||||
|
# The system time zone that yuzu will use during emulation
|
||||||
|
# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone
|
||||||
|
time_zone_index =
|
||||||
|
|
||||||
|
# Sets the sound output mode.
|
||||||
|
# 0: Mono, 1 (default): Stereo, 2: Surround
|
||||||
|
sound_index =
|
||||||
|
|
||||||
|
[Miscellaneous]
|
||||||
|
# A filter which removes logs below a certain logging level.
|
||||||
|
# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
|
||||||
|
log_filter = *:Trace
|
||||||
|
|
||||||
|
# Use developer keys
|
||||||
|
# 0 (default): Disabled, 1: Enabled
|
||||||
|
use_dev_keys =
|
||||||
|
|
||||||
|
[Debugging]
|
||||||
|
# Record frame time data, can be found in the log directory. Boolean value
|
||||||
|
record_frame_times =
|
||||||
|
# Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them
|
||||||
|
dump_exefs=false
|
||||||
|
# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
|
||||||
|
dump_nso=false
|
||||||
|
# Determines whether or not yuzu will save the filesystem access log.
|
||||||
|
enable_fs_access_log=false
|
||||||
|
# Enables verbose reporting services
|
||||||
|
reporting_services =
|
||||||
|
# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode
|
||||||
|
# false: Retail/Normal Mode (default), true: Kiosk Mode
|
||||||
|
quest_flag =
|
||||||
|
# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
|
||||||
|
# false: Disabled (default), true: Enabled
|
||||||
|
use_debug_asserts =
|
||||||
|
# Determines whether unimplemented HLE service calls should be automatically stubbed.
|
||||||
|
# false: Disabled (default), true: Enabled
|
||||||
|
use_auto_stub =
|
||||||
|
# Enables/Disables the macro JIT compiler
|
||||||
|
disable_macro_jit=false
|
||||||
|
# Determines whether to enable the GDB stub and wait for the debugger to attach before running.
|
||||||
|
# false: Disabled (default), true: Enabled
|
||||||
|
use_gdbstub=false
|
||||||
|
# The port to use for the GDB server, if it is enabled.
|
||||||
|
gdbstub_port=6543
|
||||||
|
|
||||||
|
[WebService]
|
||||||
|
# Whether or not to enable telemetry
|
||||||
|
# 0: No, 1 (default): Yes
|
||||||
|
enable_telemetry =
|
||||||
|
# URL for Web API
|
||||||
|
web_api_url = https://api.yuzu-emu.org
|
||||||
|
# Username and token for yuzu Web Service
|
||||||
|
# See https://profile.yuzu-emu.org/ for more info
|
||||||
|
yuzu_username =
|
||||||
|
yuzu_token =
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
# Name of the network interface device to use with yuzu LAN play.
|
||||||
|
# e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo'
|
||||||
|
# e.g. On Windows: 'Ethernet', 'Wi-Fi'
|
||||||
|
network_interface =
|
||||||
|
|
||||||
|
[AddOns]
|
||||||
|
# Used to disable add-ons
|
||||||
|
# List of title IDs of games that will have add-ons disabled (separated by '|'):
|
||||||
|
title_ids =
|
||||||
|
# For each title ID, have a key/value pair called `disabled_<title_id>` equal to the names of the add-ons to disable (sep. by '|')
|
||||||
|
# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey
|
||||||
|
)";
|
||||||
|
} // namespace DefaultINI
|
@ -9,7 +9,6 @@
|
|||||||
#include "input_common/drivers/virtual_gamepad.h"
|
#include "input_common/drivers/virtual_gamepad.h"
|
||||||
#include "input_common/main.h"
|
#include "input_common/main.h"
|
||||||
#include "jni/emu_window/emu_window.h"
|
#include "jni/emu_window/emu_window.h"
|
||||||
#include "jni/native.h"
|
|
||||||
|
|
||||||
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||||
m_window_width = ANativeWindow_getWidth(surface);
|
m_window_width = ANativeWindow_getWidth(surface);
|
||||||
@ -58,13 +57,6 @@ void EmuWindow_Android::OnRemoveNfcTag() {
|
|||||||
m_input_subsystem->GetVirtualAmiibo()->CloseAmiibo();
|
m_input_subsystem->GetVirtualAmiibo()->CloseAmiibo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnFrameDisplayed() {
|
|
||||||
if (!m_first_frame) {
|
|
||||||
EmulationSession::GetInstance().OnEmulationStarted();
|
|
||||||
m_first_frame = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem,
|
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem,
|
||||||
ANativeWindow* surface,
|
ANativeWindow* surface,
|
||||||
std::shared_ptr<Common::DynamicLibrary> driver_library)
|
std::shared_ptr<Common::DynamicLibrary> driver_library)
|
||||||
|
@ -45,7 +45,7 @@ public:
|
|||||||
float gyro_z, float accel_x, float accel_y, float accel_z);
|
float gyro_z, float accel_x, float accel_y, float accel_z);
|
||||||
void OnReadNfcTag(std::span<u8> data);
|
void OnReadNfcTag(std::span<u8> data);
|
||||||
void OnRemoveNfcTag();
|
void OnRemoveNfcTag();
|
||||||
void OnFrameDisplayed() override;
|
void OnFrameDisplayed() override {}
|
||||||
|
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
|
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
|
||||||
return {std::make_unique<GraphicsContext_Android>(m_driver_library)};
|
return {std::make_unique<GraphicsContext_Android>(m_driver_library)};
|
||||||
@ -61,6 +61,4 @@ private:
|
|||||||
float m_window_height{};
|
float m_window_height{};
|
||||||
|
|
||||||
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
|
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
|
||||||
|
|
||||||
bool m_first_frame = false;
|
|
||||||
};
|
};
|
||||||
|
@ -52,8 +52,8 @@
|
|||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/applets/applets.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "frontend_common/config.h"
|
|
||||||
#include "jni/android_common/android_common.h"
|
#include "jni/android_common/android_common.h"
|
||||||
|
#include "jni/config.h"
|
||||||
#include "jni/id_cache.h"
|
#include "jni/id_cache.h"
|
||||||
#include "jni/native.h"
|
#include "jni/native.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
@ -372,6 +372,8 @@ void EmulationSession::RunEmulation() {
|
|||||||
m_system.InitializeDebugger();
|
m_system.InitializeDebugger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnEmulationStarted();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
{
|
{
|
||||||
[[maybe_unused]] std::unique_lock lock(m_mutex);
|
[[maybe_unused]] std::unique_lock lock(m_mutex);
|
||||||
@ -664,6 +666,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased(JNIEnv* env, jclass c
|
|||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz,
|
||||||
jboolean reload) {
|
jboolean reload) {
|
||||||
|
// Create the default config.ini.
|
||||||
|
Config{};
|
||||||
// Initialize the emulated system.
|
// Initialize the emulated system.
|
||||||
if (!reload) {
|
if (!reload) {
|
||||||
EmulationSession::GetInstance().System().Initialize();
|
EmulationSession::GetInstance().System().Initialize();
|
||||||
@ -678,6 +682,17 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass cl
|
|||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z(
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z(
|
||||||
JNIEnv* env, jclass clazz, jstring j_file, jstring j_savestate, jboolean j_delete_savestate) {}
|
JNIEnv* env, jclass clazz, jstring j_file, jstring j_savestate, jboolean j_delete_savestate) {}
|
||||||
|
|
||||||
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadSettings(JNIEnv* env, jclass clazz) {
|
||||||
|
Config{};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initGameIni(JNIEnv* env, jclass clazz,
|
||||||
|
jstring j_game_id) {
|
||||||
|
std::string_view game_id = env->GetStringUTFChars(j_game_id, 0);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(j_game_id, game_id.data());
|
||||||
|
}
|
||||||
|
|
||||||
jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) {
|
jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) {
|
||||||
jdoubleArray j_stats = env->NewDoubleArray(4);
|
jdoubleArray j_stats = env->NewDoubleArray(4);
|
||||||
|
|
||||||
|
@ -52,10 +52,9 @@ public:
|
|||||||
void OnGamepadDisconnectEvent([[maybe_unused]] int index);
|
void OnGamepadDisconnectEvent([[maybe_unused]] int index);
|
||||||
SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard();
|
SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard();
|
||||||
|
|
||||||
static void OnEmulationStarted();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
||||||
|
static void OnEmulationStarted();
|
||||||
static void OnEmulationStopped(Core::SystemResultStatus result);
|
static void OnEmulationStopped(Core::SystemResultStatus result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -5,14 +5,11 @@
|
|||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
#include "android_config.h"
|
|
||||||
#include "android_settings.h"
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "frontend_common/config.h"
|
|
||||||
#include "jni/android_common/android_common.h"
|
#include "jni/android_common/android_common.h"
|
||||||
|
#include "jni/config.h"
|
||||||
std::unique_ptr<AndroidConfig> config;
|
#include "uisettings.h"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
|
Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
|
||||||
@ -31,22 +28,6 @@ Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializeConfig(JNIEnv* env, jobject obj) {
|
|
||||||
config = std::make_unique<AndroidConfig>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_unloadConfig(JNIEnv* env, jobject obj) {
|
|
||||||
config.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_reloadSettings(JNIEnv* env, jobject obj) {
|
|
||||||
config->AndroidConfig::ReloadAllValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_saveSettings(JNIEnv* env, jobject obj) {
|
|
||||||
config->AndroidConfig::SaveAllValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getBoolean(JNIEnv* env, jobject obj,
|
jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getBoolean(JNIEnv* env, jobject obj,
|
||||||
jstring jkey, jboolean getDefault) {
|
jstring jkey, jboolean getDefault) {
|
||||||
auto setting = getSetting<bool>(env, jkey);
|
auto setting = getSetting<bool>(env, jkey);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "android_settings.h"
|
#include "uisettings.h"
|
||||||
|
|
||||||
namespace AndroidSettings {
|
namespace AndroidSettings {
|
||||||
|
|
@ -13,7 +13,7 @@ struct Values {
|
|||||||
Settings::Linkage linkage;
|
Settings::Linkage linkage;
|
||||||
|
|
||||||
// Android
|
// Android
|
||||||
Settings::Setting<bool> picture_in_picture{linkage, false, "picture_in_picture",
|
Settings::Setting<bool> picture_in_picture{linkage, true, "picture_in_picture",
|
||||||
Settings::Category::Android};
|
Settings::Category::Android};
|
||||||
Settings::Setting<s32> screen_layout{linkage,
|
Settings::Setting<s32> screen_layout{linkage,
|
||||||
5,
|
5,
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportHeight="24"
|
|
||||||
android:viewportWidth="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="?attr/colorControlNormal"
|
|
||||||
android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z" />
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="960"
|
|
||||||
android:viewportHeight="960">
|
|
||||||
<path
|
|
||||||
android:fillColor="?attr/colorControlNormal"
|
|
||||||
android:pathData="M320,720 L80,480l240,-240 57,57 -184,184 183,183 -56,56ZM640,720 L583,663 767,479 584,296 640,240 880,480 640,720Z"/>
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="960"
|
|
||||||
android:viewportHeight="960">
|
|
||||||
<path
|
|
||||||
android:fillColor="?attr/colorControlNormal"
|
|
||||||
android:pathData="M160,840q-33,0 -56.5,-23.5T80,760v-560q0,-33 23.5,-56.5T160,120h560q33,0 56.5,23.5T800,200v80h80v80h-80v80h80v80h-80v80h80v80h-80v80q0,33 -23.5,56.5T720,840L160,840ZM160,760h560v-560L160,200v560ZM240,680h200v-160L240,520v160ZM480,400h160v-120L480,280v120ZM240,480h200v-200L240,280v200ZM480,680h160v-240L480,440v240ZM160,200v560,-560Z"/>
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="960"
|
|
||||||
android:viewportHeight="960">
|
|
||||||
<path
|
|
||||||
android:fillColor="?attr/colorControlNormal"
|
|
||||||
android:pathData="M320,960q-17,0 -28.5,-11.5T280,920q0,-17 11.5,-28.5T320,880q17,0 28.5,11.5T360,920q0,17 -11.5,28.5T320,960ZM480,960q-17,0 -28.5,-11.5T440,920q0,-17 11.5,-28.5T480,880q17,0 28.5,11.5T520,920q0,17 -11.5,28.5T480,960ZM640,960q-17,0 -28.5,-11.5T600,920q0,-17 11.5,-28.5T640,880q17,0 28.5,11.5T680,920q0,17 -11.5,28.5T640,960ZM320,800q-33,0 -56.5,-23.5T240,720v-640q0,-33 23.5,-56.5T320,0h320q33,0 56.5,23.5T720,80v640q0,33 -23.5,56.5T640,800L320,800ZM320,720h320v-40L320,680v40ZM320,600h320v-400L320,200v400ZM320,120h320v-40L320,80v40ZM320,120v-40,40ZM320,720v-40,40Z"/>
|
|
||||||
</vector>
|
|
@ -1,233 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/coordinator_about"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="?attr/colorSurface">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
|
||||||
android:id="@+id/appbar_about"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fitsSystemWindows="true">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
|
||||||
android:id="@+id/toolbar_about"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
app:navigationIcon="@drawable/ic_back"
|
|
||||||
app:title="@string/about" />
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
|
||||||
android:id="@+id/scroll_about"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:fadeScrollbars="false"
|
|
||||||
android:scrollbars="vertical"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/content_about"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/image_logo"
|
|
||||||
android:layout_width="200dp"
|
|
||||||
android:layout_height="200dp"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:padding="20dp"
|
|
||||||
android:src="@drawable/ic_yuzu_title" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:paddingVertical="16dp">
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
style="@style/TextAppearance.Material3.TitleMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:text="@string/about"
|
|
||||||
android:textAlignment="viewStart" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
style="@style/TextAppearance.Material3.BodyMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:text="@string/about_app_description"
|
|
||||||
android:textAlignment="viewStart" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="20dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/button_contributors"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:paddingVertical="16dp">
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
style="@style/TextAppearance.Material3.TitleMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:text="@string/contributors"
|
|
||||||
android:textAlignment="viewStart" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
style="@style/TextAppearance.Material3.BodyMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:text="@string/contributors_description"
|
|
||||||
android:textAlignment="viewStart" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="20dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/button_licenses"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:paddingVertical="16dp">
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
style="@style/TextAppearance.Material3.TitleMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:text="@string/licenses"
|
|
||||||
android:textAlignment="viewStart" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
style="@style/TextAppearance.Material3.BodyMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:text="@string/licenses_description"
|
|
||||||
android:textAlignment="viewStart" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="20dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/button_build_hash"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:paddingVertical="16dp">
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
style="@style/TextAppearance.Material3.TitleMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:text="@string/build"
|
|
||||||
android:textAlignment="viewStart" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/text_build_hash"
|
|
||||||
style="@style/TextAppearance.Material3.BodyMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:textAlignment="viewStart"
|
|
||||||
tools:text="abc123" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="20dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="40dp"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button_discord"
|
|
||||||
style="?attr/materialIconButtonStyle"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
app:icon="@drawable/ic_discord"
|
|
||||||
app:iconGravity="textEnd"
|
|
||||||
app:iconSize="24dp"
|
|
||||||
app:iconTint="?attr/colorOnSurface" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button_website"
|
|
||||||
style="?attr/materialIconButtonStyle"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
app:icon="@drawable/ic_website"
|
|
||||||
app:iconGravity="textEnd"
|
|
||||||
app:iconSize="24dp"
|
|
||||||
app:iconTint="?attr/colorOnSurface" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button_github"
|
|
||||||
style="?attr/materialIconButtonStyle"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
app:icon="@drawable/ic_github"
|
|
||||||
app:iconGravity="textEnd"
|
|
||||||
app:iconSize="24dp"
|
|
||||||
app:iconTint="?attr/colorOnSurface" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -6,8 +6,8 @@
|
|||||||
android:id="@+id/option_card"
|
android:id="@+id/option_card"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="24dp"
|
android:layout_marginVertical="12dp"
|
||||||
android:layout_marginHorizontal="12dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:backgroundTint="?attr/colorSurfaceVariant"
|
android:backgroundTint="?attr/colorSurfaceVariant"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
|
@ -38,17 +38,17 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/image_logo"
|
android:id="@+id/image_logo"
|
||||||
android:layout_width="150dp"
|
android:layout_width="250dp"
|
||||||
android:layout_height="150dp"
|
android:layout_height="250dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="20dp"
|
||||||
android:layout_marginBottom="28dp"
|
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:src="@drawable/ic_yuzu_title" />
|
android:src="@drawable/ic_yuzu_title" />
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
<com.google.android.material.divider.MaterialDivider
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="20dp" />
|
android:layout_marginHorizontal="20dp"
|
||||||
|
android:layout_marginTop="28dp" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -139,7 +139,7 @@
|
|||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/show_fps_text"
|
android:id="@+id/show_fps_text"
|
||||||
style="@style/TextAppearance.Material3.BodySmall"
|
style="@style/TextAppearance.Material3.BodyMedium"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="left"
|
android:layout_gravity="left"
|
||||||
@ -147,8 +147,7 @@
|
|||||||
android:focusable="false"
|
android:focusable="false"
|
||||||
android:paddingHorizontal="20dp"
|
android:paddingHorizontal="20dp"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:shadowColor="@android:color/black"
|
android:textSize="12sp"
|
||||||
android:shadowRadius="3"
|
|
||||||
tools:ignore="RtlHardcoded" />
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
@ -14,14 +14,13 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:background="?attr/colorSurface"
|
android:background="?attr/colorSurface">
|
||||||
android:paddingHorizontal="8dp">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/logo_image"
|
android:id="@+id/logo_image"
|
||||||
android:layout_width="96dp"
|
android:layout_width="128dp"
|
||||||
android:layout_height="96dp"
|
android:layout_height="128dp"
|
||||||
android:layout_marginVertical="32dp"
|
android:layout_margin="64dp"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:src="@drawable/ic_yuzu_full" />
|
android:src="@drawable/ic_yuzu_full" />
|
||||||
|
|
||||||
|
@ -10,59 +10,41 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:minHeight="72dp"
|
android:minHeight="72dp"
|
||||||
android:padding="16dp">
|
android:padding="@dimen/spacing_large">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/text_setting_name"
|
||||||
android:layout_width="24dp"
|
style="@style/TextAppearance.Material3.HeadlineMedium"
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="24dp"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:tint="?attr/colorOnSurface" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:textAlignment="viewStart"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:lineHeight="22dp"
|
||||||
|
tools:text="Setting Name" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/text_setting_name"
|
android:id="@+id/text_setting_description"
|
||||||
style="@style/TextAppearance.Material3.HeadlineMedium"
|
style="@style/TextAppearance.Material3.BodySmall"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="viewStart"
|
android:layout_marginTop="@dimen/spacing_small"
|
||||||
android:textSize="17sp"
|
android:textAlignment="viewStart"
|
||||||
app:lineHeight="22dp"
|
tools:text="@string/app_disclaimer" />
|
||||||
tools:text="Setting Name" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/text_setting_description"
|
android:id="@+id/text_setting_value"
|
||||||
style="@style/TextAppearance.Material3.BodySmall"
|
style="@style/TextAppearance.Material3.LabelMedium"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/spacing_small"
|
android:layout_marginTop="@dimen/spacing_small"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
tools:text="@string/app_disclaimer" />
|
android:textStyle="bold"
|
||||||
|
tools:text="1x" />
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/text_setting_value"
|
|
||||||
style="@style/TextAppearance.Material3.LabelMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/spacing_small"
|
|
||||||
android:textAlignment="viewStart"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="13sp"
|
|
||||||
tools:text="1x" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:minHeight="72dp"
|
android:minHeight="72dp"
|
||||||
android:padding="16dp">
|
android:paddingVertical="@dimen/spacing_large"
|
||||||
|
android:paddingStart="@dimen/spacing_large"
|
||||||
|
android:paddingEnd="24dp">
|
||||||
|
|
||||||
<com.google.android.material.materialswitch.MaterialSwitch
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
android:id="@+id/switch_widget"
|
android:id="@+id/switch_widget"
|
||||||
@ -22,7 +24,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginEnd="24dp"
|
android:layout_marginEnd="@dimen/spacing_large"
|
||||||
android:layout_toStartOf="@+id/switch_widget"
|
android:layout_toStartOf="@+id/switch_widget"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@ -33,7 +35,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textSize="17sp"
|
android:textSize="16sp"
|
||||||
app:lineHeight="28dp"
|
app:lineHeight="28dp"
|
||||||
tools:text="@string/frame_limit_enable" />
|
tools:text="@string/frame_limit_enable" />
|
||||||
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="start|center_vertical"
|
android:layout_gravity="start|center_vertical"
|
||||||
android:paddingHorizontal="@dimen/spacing_large"
|
android:paddingHorizontal="@dimen/spacing_large"
|
||||||
android:paddingTop="16dp"
|
android:paddingVertical="16dp"
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textColor="?attr/colorPrimary"
|
android:textColor="?attr/colorPrimary"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<string-array name="regionNames">
|
<string-array name="regionNames">
|
||||||
|
<item>@string/auto</item>
|
||||||
<item>@string/region_australia</item>
|
<item>@string/region_australia</item>
|
||||||
<item>@string/region_china</item>
|
<item>@string/region_china</item>
|
||||||
<item>@string/region_europe</item>
|
<item>@string/region_europe</item>
|
||||||
@ -12,6 +13,7 @@
|
|||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<integer-array name="regionValues">
|
<integer-array name="regionValues">
|
||||||
|
<item>-1</item>
|
||||||
<item>3</item>
|
<item>3</item>
|
||||||
<item>4</item>
|
<item>4</item>
|
||||||
<item>2</item>
|
<item>2</item>
|
||||||
|
@ -240,7 +240,6 @@
|
|||||||
<string name="shutting_down">Shutting down…</string>
|
<string name="shutting_down">Shutting down…</string>
|
||||||
<string name="reset_setting_confirmation">Do you want to reset this setting back to its default value?</string>
|
<string name="reset_setting_confirmation">Do you want to reset this setting back to its default value?</string>
|
||||||
<string name="reset_to_default">Reset to default</string>
|
<string name="reset_to_default">Reset to default</string>
|
||||||
<string name="reset_to_default_description">Resets all advanced settings</string>
|
|
||||||
<string name="reset_all_settings">Reset all settings?</string>
|
<string name="reset_all_settings">Reset all settings?</string>
|
||||||
<string name="reset_all_settings_description">All advanced settings will be reset to their default configuration. This can not be undone.</string>
|
<string name="reset_all_settings_description">All advanced settings will be reset to their default configuration. This can not be undone.</string>
|
||||||
<string name="settings_reset">Settings reset</string>
|
<string name="settings_reset">Settings reset</string>
|
||||||
@ -272,14 +271,10 @@
|
|||||||
<string name="preferences_settings">Settings</string>
|
<string name="preferences_settings">Settings</string>
|
||||||
<string name="preferences_general">General</string>
|
<string name="preferences_general">General</string>
|
||||||
<string name="preferences_system">System</string>
|
<string name="preferences_system">System</string>
|
||||||
<string name="preferences_system_description">Docked mode, region, language</string>
|
|
||||||
<string name="preferences_graphics">Graphics</string>
|
<string name="preferences_graphics">Graphics</string>
|
||||||
<string name="preferences_graphics_description">Accuracy level, resolution, shader cache</string>
|
|
||||||
<string name="preferences_audio">Audio</string>
|
<string name="preferences_audio">Audio</string>
|
||||||
<string name="preferences_audio_description">Output engine, volume</string>
|
|
||||||
<string name="preferences_theme">Theme and color</string>
|
<string name="preferences_theme">Theme and color</string>
|
||||||
<string name="preferences_debug">Debug</string>
|
<string name="preferences_debug">Debug</string>
|
||||||
<string name="preferences_debug_description">CPU/GPU debugging, graphics API, fastmem</string>
|
|
||||||
|
|
||||||
<!-- ROM loading errors -->
|
<!-- ROM loading errors -->
|
||||||
<string name="loader_error_encrypted">Your ROM is encrypted</string>
|
<string name="loader_error_encrypted">Your ROM is encrypted</string>
|
||||||
|
@ -146,7 +146,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalPause();
|
paused = true;
|
||||||
if (cubeb_stream_stop(stream_backend) != CUBEB_OK) {
|
if (cubeb_stream_stop(stream_backend) != CUBEB_OK) {
|
||||||
LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream");
|
LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream");
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ public:
|
|||||||
if (device == 0 || paused) {
|
if (device == 0 || paused) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SignalPause();
|
paused = true;
|
||||||
SDL_PauseAudioDevice(device, 1);
|
SDL_PauseAudioDevice(device, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,19 +282,11 @@ u64 SinkStream::GetExpectedPlayedSampleCount() {
|
|||||||
void SinkStream::WaitFreeSpace(std::stop_token stop_token) {
|
void SinkStream::WaitFreeSpace(std::stop_token stop_token) {
|
||||||
std::unique_lock lk{release_mutex};
|
std::unique_lock lk{release_mutex};
|
||||||
release_cv.wait_for(lk, std::chrono::milliseconds(5),
|
release_cv.wait_for(lk, std::chrono::milliseconds(5),
|
||||||
[this]() { return paused || queued_buffers < max_queue_size; });
|
[this]() { return queued_buffers < max_queue_size; });
|
||||||
if (queued_buffers > max_queue_size + 3) {
|
if (queued_buffers > max_queue_size + 3) {
|
||||||
Common::CondvarWait(release_cv, lk, stop_token,
|
Common::CondvarWait(release_cv, lk, stop_token,
|
||||||
[this] { return paused || queued_buffers < max_queue_size; });
|
[this] { return queued_buffers < max_queue_size; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SinkStream::SignalPause() {
|
|
||||||
{
|
|
||||||
std::scoped_lock lk{release_mutex};
|
|
||||||
paused = true;
|
|
||||||
}
|
|
||||||
release_cv.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace AudioCore::Sink
|
} // namespace AudioCore::Sink
|
||||||
|
@ -213,12 +213,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void WaitFreeSpace(std::stop_token stop_token);
|
void WaitFreeSpace(std::stop_token stop_token);
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Unblocks the ADSP if the stream is paused.
|
|
||||||
*/
|
|
||||||
void SignalPause();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Core system
|
/// Core system
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
@ -203,12 +203,10 @@ const char* TranslateCategory(Category category) {
|
|||||||
case Category::Ui:
|
case Category::Ui:
|
||||||
case Category::UiGeneral:
|
case Category::UiGeneral:
|
||||||
return "UI";
|
return "UI";
|
||||||
case Category::UiAudio:
|
|
||||||
return "UiAudio";
|
|
||||||
case Category::UiLayout:
|
case Category::UiLayout:
|
||||||
return "UILayout";
|
return "UiLayout";
|
||||||
case Category::UiGameList:
|
case Category::UiGameList:
|
||||||
return "UIGameList";
|
return "UiGameList";
|
||||||
case Category::Screenshots:
|
case Category::Screenshots:
|
||||||
return "Screenshots";
|
return "Screenshots";
|
||||||
case Category::Shortcuts:
|
case Category::Shortcuts:
|
||||||
|
@ -153,7 +153,7 @@ struct Values {
|
|||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
Setting<bool, false> audio_muted{
|
Setting<bool, false> audio_muted{
|
||||||
linkage, false, "audio_muted", Category::Audio, Specialization::Default, true, true};
|
linkage, false, "audio_muted", Category::Audio, Specialization::Default, false, true};
|
||||||
Setting<bool, false> dump_audio_commands{
|
Setting<bool, false> dump_audio_commands{
|
||||||
linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false};
|
linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false};
|
||||||
|
|
||||||
@ -232,11 +232,7 @@ struct Values {
|
|||||||
SwitchableSetting<bool> use_asynchronous_gpu_emulation{
|
SwitchableSetting<bool> use_asynchronous_gpu_emulation{
|
||||||
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
|
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
|
||||||
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
||||||
#ifdef ANDROID
|
|
||||||
AstcDecodeMode::Cpu,
|
|
||||||
#else
|
|
||||||
AstcDecodeMode::Gpu,
|
AstcDecodeMode::Gpu,
|
||||||
#endif
|
|
||||||
AstcDecodeMode::Cpu,
|
AstcDecodeMode::Cpu,
|
||||||
AstcDecodeMode::CpuAsynchronous,
|
AstcDecodeMode::CpuAsynchronous,
|
||||||
"accelerate_astc",
|
"accelerate_astc",
|
||||||
@ -308,11 +304,7 @@ struct Values {
|
|||||||
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
||||||
|
|
||||||
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
||||||
#ifdef ANDROID
|
|
||||||
GpuAccuracy::Normal,
|
|
||||||
#else
|
|
||||||
GpuAccuracy::High,
|
GpuAccuracy::High,
|
||||||
#endif
|
|
||||||
GpuAccuracy::Normal,
|
GpuAccuracy::Normal,
|
||||||
GpuAccuracy::Extreme,
|
GpuAccuracy::Extreme,
|
||||||
"gpu_accuracy",
|
"gpu_accuracy",
|
||||||
@ -321,38 +313,20 @@ struct Values {
|
|||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
GpuAccuracy current_gpu_accuracy{GpuAccuracy::High};
|
GpuAccuracy current_gpu_accuracy{GpuAccuracy::High};
|
||||||
SwitchableSetting<AnisotropyMode, true> max_anisotropy{linkage,
|
SwitchableSetting<AnisotropyMode, true> max_anisotropy{
|
||||||
#ifdef ANDROID
|
linkage, AnisotropyMode::Automatic, AnisotropyMode::Automatic, AnisotropyMode::X16,
|
||||||
AnisotropyMode::Default,
|
"max_anisotropy", Category::RendererAdvanced};
|
||||||
#else
|
|
||||||
AnisotropyMode::Automatic,
|
|
||||||
#endif
|
|
||||||
AnisotropyMode::Automatic,
|
|
||||||
AnisotropyMode::X16,
|
|
||||||
"max_anisotropy",
|
|
||||||
Category::RendererAdvanced};
|
|
||||||
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
|
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
|
||||||
AstcRecompression::Uncompressed,
|
AstcRecompression::Uncompressed,
|
||||||
AstcRecompression::Uncompressed,
|
AstcRecompression::Uncompressed,
|
||||||
AstcRecompression::Bc3,
|
AstcRecompression::Bc3,
|
||||||
"astc_recompression",
|
"astc_recompression",
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
SwitchableSetting<bool> async_presentation{linkage,
|
SwitchableSetting<bool> async_presentation{linkage, false, "async_presentation",
|
||||||
#ifdef ANDROID
|
Category::RendererAdvanced};
|
||||||
true,
|
|
||||||
#else
|
|
||||||
false,
|
|
||||||
#endif
|
|
||||||
"async_presentation", Category::RendererAdvanced};
|
|
||||||
SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock",
|
SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock",
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
SwitchableSetting<bool> use_reactive_flushing{linkage,
|
SwitchableSetting<bool> use_reactive_flushing{linkage, true, "use_reactive_flushing",
|
||||||
#ifdef ANDROID
|
|
||||||
false,
|
|
||||||
#else
|
|
||||||
true,
|
|
||||||
#endif
|
|
||||||
"use_reactive_flushing",
|
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
|
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
@ -384,8 +358,6 @@ struct Values {
|
|||||||
Category::RendererDebug};
|
Category::RendererDebug};
|
||||||
// TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control
|
// TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control
|
||||||
bool renderer_amdvlk_depth_bias_workaround{};
|
bool renderer_amdvlk_depth_bias_workaround{};
|
||||||
Setting<bool> disable_buffer_reorder{linkage, false, "disable_buffer_reorder",
|
|
||||||
Category::RendererDebug};
|
|
||||||
|
|
||||||
// System
|
// System
|
||||||
SwitchableSetting<Language, true> language_index{linkage,
|
SwitchableSetting<Language, true> language_index{linkage,
|
||||||
@ -418,11 +390,7 @@ struct Values {
|
|||||||
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
||||||
|
|
||||||
SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
|
SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
|
||||||
#ifdef ANDROID
|
|
||||||
ConsoleMode::Handheld,
|
|
||||||
#else
|
|
||||||
ConsoleMode::Docked,
|
ConsoleMode::Docked,
|
||||||
#endif
|
|
||||||
"use_docked_mode",
|
"use_docked_mode",
|
||||||
Category::System,
|
Category::System,
|
||||||
Specialization::Radio,
|
Specialization::Radio,
|
||||||
|
@ -32,7 +32,6 @@ enum class Category : u32 {
|
|||||||
AddOns,
|
AddOns,
|
||||||
Controls,
|
Controls,
|
||||||
Ui,
|
Ui,
|
||||||
UiAudio,
|
|
||||||
UiGeneral,
|
UiGeneral,
|
||||||
UiLayout,
|
UiLayout,
|
||||||
UiGameList,
|
UiGameList,
|
||||||
|
@ -6,11 +6,10 @@
|
|||||||
namespace Settings {
|
namespace Settings {
|
||||||
namespace NativeButton {
|
namespace NativeButton {
|
||||||
const std::array<const char*, NumButtons> mapping = {{
|
const std::array<const char*, NumButtons> mapping = {{
|
||||||
"button_a", "button_b", "button_x", "button_y", "button_lstick",
|
"button_a", "button_b", "button_x", "button_y", "button_lstick",
|
||||||
"button_rstick", "button_l", "button_r", "button_zl", "button_zr",
|
"button_rstick", "button_l", "button_r", "button_zl", "button_zr",
|
||||||
"button_plus", "button_minus", "button_dleft", "button_dup", "button_dright",
|
"button_plus", "button_minus", "button_dleft", "button_dup", "button_dright",
|
||||||
"button_ddown", "button_slleft", "button_srleft", "button_home", "button_screenshot",
|
"button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot",
|
||||||
"button_slright", "button_srright",
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,15 +29,12 @@ enum Values : int {
|
|||||||
DRight,
|
DRight,
|
||||||
DDown,
|
DDown,
|
||||||
|
|
||||||
SLLeft,
|
SL,
|
||||||
SRLeft,
|
SR,
|
||||||
|
|
||||||
Home,
|
Home,
|
||||||
Screenshot,
|
Screenshot,
|
||||||
|
|
||||||
SLRight,
|
|
||||||
SRRight,
|
|
||||||
|
|
||||||
NumButtons,
|
NumButtons,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -521,19 +521,11 @@ add_library(core STATIC
|
|||||||
hle/service/grc/grc.h
|
hle/service/grc/grc.h
|
||||||
hle/service/hid/hid.cpp
|
hle/service/hid/hid.cpp
|
||||||
hle/service/hid/hid.h
|
hle/service/hid/hid.h
|
||||||
hle/service/hid/hid_debug_server.cpp
|
|
||||||
hle/service/hid/hid_debug_server.h
|
|
||||||
hle/service/hid/hid_server.cpp
|
|
||||||
hle/service/hid/hid_server.h
|
|
||||||
hle/service/hid/hid_system_server.cpp
|
|
||||||
hle/service/hid/hid_system_server.h
|
|
||||||
hle/service/hid/hidbus.cpp
|
hle/service/hid/hidbus.cpp
|
||||||
hle/service/hid/hidbus.h
|
hle/service/hid/hidbus.h
|
||||||
hle/service/hid/irs.cpp
|
hle/service/hid/irs.cpp
|
||||||
hle/service/hid/irs.h
|
hle/service/hid/irs.h
|
||||||
hle/service/hid/irs_ring_lifo.h
|
hle/service/hid/irs_ring_lifo.h
|
||||||
hle/service/hid/resource_manager.cpp
|
|
||||||
hle/service/hid/resource_manager.h
|
|
||||||
hle/service/hid/ring_lifo.h
|
hle/service/hid/ring_lifo.h
|
||||||
hle/service/hid/xcd.cpp
|
hle/service/hid/xcd.cpp
|
||||||
hle/service/hid/xcd.h
|
hle/service/hid/xcd.h
|
||||||
|
@ -153,14 +153,6 @@ void ARM_Interface::Run() {
|
|||||||
Kernel::KThread* current_thread{Kernel::GetCurrentThreadPointer(system.Kernel())};
|
Kernel::KThread* current_thread{Kernel::GetCurrentThreadPointer(system.Kernel())};
|
||||||
HaltReason hr{};
|
HaltReason hr{};
|
||||||
|
|
||||||
// If the thread is scheduled for termination, exit the thread.
|
|
||||||
if (current_thread->HasDpc()) {
|
|
||||||
if (current_thread->IsTerminationRequested()) {
|
|
||||||
current_thread->Exit();
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify the debugger and go to sleep if a step was performed
|
// Notify the debugger and go to sleep if a step was performed
|
||||||
// and this thread has been scheduled again.
|
// and this thread has been scheduled again.
|
||||||
if (current_thread->GetStepState() == StepState::StepPerformed) {
|
if (current_thread->GetStepState() == StepState::StepPerformed) {
|
||||||
@ -182,6 +174,14 @@ void ARM_Interface::Run() {
|
|||||||
}
|
}
|
||||||
system.ExitCPUProfile();
|
system.ExitCPUProfile();
|
||||||
|
|
||||||
|
// If the thread is scheduled for termination, exit the thread.
|
||||||
|
if (current_thread->HasDpc()) {
|
||||||
|
if (current_thread->IsTerminationRequested()) {
|
||||||
|
current_thread->Exit();
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Notify the debugger and go to sleep if a breakpoint was hit,
|
// Notify the debugger and go to sleep if a breakpoint was hit,
|
||||||
// or if the thread is unable to continue for any reason.
|
// or if the thread is unable to continue for any reason.
|
||||||
if (True(hr & HaltReason::InstructionBreakpoint) || True(hr & HaltReason::PrefetchAbort)) {
|
if (True(hr & HaltReason::InstructionBreakpoint) || True(hr & HaltReason::PrefetchAbort)) {
|
||||||
|
@ -76,7 +76,6 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CoreTiming::ClearPendingEvents() {
|
void CoreTiming::ClearPendingEvents() {
|
||||||
std::scoped_lock lock{basic_lock};
|
|
||||||
event_queue.clear();
|
event_queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +113,6 @@ bool CoreTiming::IsRunning() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CoreTiming::HasPendingEvents() const {
|
bool CoreTiming::HasPendingEvents() const {
|
||||||
std::scoped_lock lock{basic_lock};
|
|
||||||
return !(wait_set && event_queue.empty());
|
return !(wait_set && event_queue.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ private:
|
|||||||
std::shared_ptr<EventType> ev_lost;
|
std::shared_ptr<EventType> ev_lost;
|
||||||
Common::Event event{};
|
Common::Event event{};
|
||||||
Common::Event pause_event{};
|
Common::Event pause_event{};
|
||||||
mutable std::mutex basic_lock;
|
std::mutex basic_lock;
|
||||||
std::mutex advance_lock;
|
std::mutex advance_lock;
|
||||||
std::unique_ptr<std::jthread> timer_thread;
|
std::unique_ptr<std::jthread> timer_thread;
|
||||||
std::atomic<bool> paused{};
|
std::atomic<bool> paused{};
|
||||||
|
@ -562,120 +562,6 @@ static std::string PaginateBuffer(std::string_view buffer, std::string_view requ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VAddr GetModuleEnd(Kernel::KProcessPageTable& page_table, VAddr base) {
|
|
||||||
Kernel::KMemoryInfo mem_info;
|
|
||||||
Kernel::Svc::MemoryInfo svc_mem_info;
|
|
||||||
Kernel::Svc::PageInfo page_info;
|
|
||||||
VAddr cur_addr{base};
|
|
||||||
|
|
||||||
// Expect: r-x Code (.text)
|
|
||||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
|
||||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
|
||||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
|
||||||
if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
|
|
||||||
svc_mem_info.permission != Kernel::Svc::MemoryPermission::ReadExecute) {
|
|
||||||
return cur_addr - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expect: r-- Code (.rodata)
|
|
||||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
|
||||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
|
||||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
|
||||||
if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
|
|
||||||
svc_mem_info.permission != Kernel::Svc::MemoryPermission::Read) {
|
|
||||||
return cur_addr - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expect: rw- CodeData (.data)
|
|
||||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
|
||||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
|
||||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
|
||||||
return cur_addr - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Loader::AppLoader::Modules FindModules(Core::System& system) {
|
|
||||||
Loader::AppLoader::Modules modules;
|
|
||||||
|
|
||||||
auto& page_table = system.ApplicationProcess()->GetPageTable();
|
|
||||||
auto& memory = system.ApplicationMemory();
|
|
||||||
VAddr cur_addr = 0;
|
|
||||||
|
|
||||||
// Look for executable sections in Code or AliasCode regions.
|
|
||||||
while (true) {
|
|
||||||
Kernel::KMemoryInfo mem_info{};
|
|
||||||
Kernel::Svc::PageInfo page_info{};
|
|
||||||
R_ASSERT(
|
|
||||||
page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
|
||||||
auto svc_mem_info = mem_info.GetSvcMemoryInfo();
|
|
||||||
|
|
||||||
if (svc_mem_info.permission == Kernel::Svc::MemoryPermission::ReadExecute &&
|
|
||||||
(svc_mem_info.state == Kernel::Svc::MemoryState::Code ||
|
|
||||||
svc_mem_info.state == Kernel::Svc::MemoryState::AliasCode)) {
|
|
||||||
// Try to read the module name from its path.
|
|
||||||
constexpr s32 PathLengthMax = 0x200;
|
|
||||||
struct {
|
|
||||||
u32 zero;
|
|
||||||
s32 path_length;
|
|
||||||
std::array<char, PathLengthMax> path;
|
|
||||||
} module_path;
|
|
||||||
|
|
||||||
if (memory.ReadBlock(svc_mem_info.base_address + svc_mem_info.size, &module_path,
|
|
||||||
sizeof(module_path))) {
|
|
||||||
if (module_path.zero == 0 && module_path.path_length > 0) {
|
|
||||||
// Truncate module name.
|
|
||||||
module_path.path[PathLengthMax - 1] = '\0';
|
|
||||||
|
|
||||||
// Ignore leading directories.
|
|
||||||
char* path_pointer = module_path.path.data();
|
|
||||||
|
|
||||||
for (s32 i = 0; i < std::min(PathLengthMax, module_path.path_length) &&
|
|
||||||
module_path.path[i] != '\0';
|
|
||||||
i++) {
|
|
||||||
if (module_path.path[i] == '/' || module_path.path[i] == '\\') {
|
|
||||||
path_pointer = module_path.path.data() + i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert output.
|
|
||||||
modules.emplace(svc_mem_info.base_address, path_pointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we're done.
|
|
||||||
const uintptr_t next_address = svc_mem_info.base_address + svc_mem_info.size;
|
|
||||||
if (next_address <= cur_addr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_addr = next_address;
|
|
||||||
}
|
|
||||||
|
|
||||||
return modules;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VAddr FindMainModuleEntrypoint(Core::System& system) {
|
|
||||||
Loader::AppLoader::Modules modules;
|
|
||||||
system.GetAppLoader().ReadNSOModules(modules);
|
|
||||||
|
|
||||||
// Do we have a module named main?
|
|
||||||
const auto main = std::find_if(modules.begin(), modules.end(),
|
|
||||||
[](const auto& key) { return key.second == "main"; });
|
|
||||||
|
|
||||||
if (main != modules.end()) {
|
|
||||||
return main->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we have any loaded executable sections?
|
|
||||||
modules = FindModules(system);
|
|
||||||
if (!modules.empty()) {
|
|
||||||
return modules.begin()->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// As a last resort, use the start of the code region.
|
|
||||||
return GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GDBStub::HandleQuery(std::string_view command) {
|
void GDBStub::HandleQuery(std::string_view command) {
|
||||||
if (command.starts_with("TStatus")) {
|
if (command.starts_with("TStatus")) {
|
||||||
// no tracepoint support
|
// no tracepoint support
|
||||||
@ -687,10 +573,21 @@ void GDBStub::HandleQuery(std::string_view command) {
|
|||||||
const auto target_xml{arch->GetTargetXML()};
|
const auto target_xml{arch->GetTargetXML()};
|
||||||
SendReply(PaginateBuffer(target_xml, command.substr(30)));
|
SendReply(PaginateBuffer(target_xml, command.substr(30)));
|
||||||
} else if (command.starts_with("Offsets")) {
|
} else if (command.starts_with("Offsets")) {
|
||||||
const auto main_offset = FindMainModuleEntrypoint(system);
|
Loader::AppLoader::Modules modules;
|
||||||
SendReply(fmt::format("TextSeg={:x}", main_offset));
|
system.GetAppLoader().ReadNSOModules(modules);
|
||||||
|
|
||||||
|
const auto main = std::find_if(modules.begin(), modules.end(),
|
||||||
|
[](const auto& key) { return key.second == "main"; });
|
||||||
|
if (main != modules.end()) {
|
||||||
|
SendReply(fmt::format("TextSeg={:x}", main->first));
|
||||||
|
} else {
|
||||||
|
SendReply(fmt::format(
|
||||||
|
"TextSeg={:x}",
|
||||||
|
GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart())));
|
||||||
|
}
|
||||||
} else if (command.starts_with("Xfer:libraries:read::")) {
|
} else if (command.starts_with("Xfer:libraries:read::")) {
|
||||||
auto modules = FindModules(system);
|
Loader::AppLoader::Modules modules;
|
||||||
|
system.GetAppLoader().ReadNSOModules(modules);
|
||||||
|
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
buffer += R"(<?xml version="1.0"?>)";
|
buffer += R"(<?xml version="1.0"?>)";
|
||||||
@ -830,6 +727,37 @@ static constexpr const char* GetMemoryPermissionString(const Kernel::Svc::Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VAddr GetModuleEnd(Kernel::KProcessPageTable& page_table, VAddr base) {
|
||||||
|
Kernel::KMemoryInfo mem_info;
|
||||||
|
Kernel::Svc::MemoryInfo svc_mem_info;
|
||||||
|
Kernel::Svc::PageInfo page_info;
|
||||||
|
VAddr cur_addr{base};
|
||||||
|
|
||||||
|
// Expect: r-x Code (.text)
|
||||||
|
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||||
|
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||||
|
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||||
|
if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
|
||||||
|
svc_mem_info.permission != Kernel::Svc::MemoryPermission::ReadExecute) {
|
||||||
|
return cur_addr - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect: r-- Code (.rodata)
|
||||||
|
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||||
|
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||||
|
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||||
|
if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
|
||||||
|
svc_mem_info.permission != Kernel::Svc::MemoryPermission::Read) {
|
||||||
|
return cur_addr - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect: rw- CodeData (.data)
|
||||||
|
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||||
|
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||||
|
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||||
|
return cur_addr - 1;
|
||||||
|
}
|
||||||
|
|
||||||
void GDBStub::HandleRcmd(const std::vector<u8>& command) {
|
void GDBStub::HandleRcmd(const std::vector<u8>& command) {
|
||||||
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
|
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
|
||||||
std::string reply;
|
std::string reply;
|
||||||
@ -856,7 +784,8 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
|
|||||||
reply = "Fastmem is not enabled.\n";
|
reply = "Fastmem is not enabled.\n";
|
||||||
}
|
}
|
||||||
} else if (command_str == "get info") {
|
} else if (command_str == "get info") {
|
||||||
auto modules = FindModules(system);
|
Loader::AppLoader::Modules modules;
|
||||||
|
system.GetAppLoader().ReadNSOModules(modules);
|
||||||
|
|
||||||
reply = fmt::format("Process: {:#x} ({})\n"
|
reply = fmt::format("Process: {:#x} ({})\n"
|
||||||
"Program Id: {:#018x}\n",
|
"Program Id: {:#018x}\n",
|
||||||
|
@ -38,6 +38,14 @@ using TouchParams = std::array<Common::ParamPackage, MaxTouchDevices>;
|
|||||||
using ConsoleMotionValues = ConsoleMotionInfo;
|
using ConsoleMotionValues = ConsoleMotionInfo;
|
||||||
using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>;
|
using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>;
|
||||||
|
|
||||||
|
struct TouchFinger {
|
||||||
|
u64 last_touch{};
|
||||||
|
Common::Point<float> position{};
|
||||||
|
u32 id{};
|
||||||
|
TouchAttribute attribute{};
|
||||||
|
bool pressed{};
|
||||||
|
};
|
||||||
|
|
||||||
// Contains all motion related data that is used on the services
|
// Contains all motion related data that is used on the services
|
||||||
struct ConsoleMotion {
|
struct ConsoleMotion {
|
||||||
Common::Vec3f accel{};
|
Common::Vec3f accel{};
|
||||||
|
@ -243,12 +243,10 @@ void EmulatedController::LoadTASParams() {
|
|||||||
tas_button_params[Settings::NativeButton::DUp].Set("button", 13);
|
tas_button_params[Settings::NativeButton::DUp].Set("button", 13);
|
||||||
tas_button_params[Settings::NativeButton::DRight].Set("button", 14);
|
tas_button_params[Settings::NativeButton::DRight].Set("button", 14);
|
||||||
tas_button_params[Settings::NativeButton::DDown].Set("button", 15);
|
tas_button_params[Settings::NativeButton::DDown].Set("button", 15);
|
||||||
tas_button_params[Settings::NativeButton::SLLeft].Set("button", 16);
|
tas_button_params[Settings::NativeButton::SL].Set("button", 16);
|
||||||
tas_button_params[Settings::NativeButton::SRLeft].Set("button", 17);
|
tas_button_params[Settings::NativeButton::SR].Set("button", 17);
|
||||||
tas_button_params[Settings::NativeButton::Home].Set("button", 18);
|
tas_button_params[Settings::NativeButton::Home].Set("button", 18);
|
||||||
tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
|
tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
|
||||||
tas_button_params[Settings::NativeButton::SLRight].Set("button", 20);
|
|
||||||
tas_button_params[Settings::NativeButton::SRRight].Set("button", 21);
|
|
||||||
|
|
||||||
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
|
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
|
||||||
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
|
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
|
||||||
@ -298,12 +296,10 @@ void EmulatedController::LoadVirtualGamepadParams() {
|
|||||||
virtual_button_params[Settings::NativeButton::DUp].Set("button", 13);
|
virtual_button_params[Settings::NativeButton::DUp].Set("button", 13);
|
||||||
virtual_button_params[Settings::NativeButton::DRight].Set("button", 14);
|
virtual_button_params[Settings::NativeButton::DRight].Set("button", 14);
|
||||||
virtual_button_params[Settings::NativeButton::DDown].Set("button", 15);
|
virtual_button_params[Settings::NativeButton::DDown].Set("button", 15);
|
||||||
virtual_button_params[Settings::NativeButton::SLLeft].Set("button", 16);
|
virtual_button_params[Settings::NativeButton::SL].Set("button", 16);
|
||||||
virtual_button_params[Settings::NativeButton::SRLeft].Set("button", 17);
|
virtual_button_params[Settings::NativeButton::SR].Set("button", 17);
|
||||||
virtual_button_params[Settings::NativeButton::Home].Set("button", 18);
|
virtual_button_params[Settings::NativeButton::Home].Set("button", 18);
|
||||||
virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
|
virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
|
||||||
virtual_button_params[Settings::NativeButton::SLRight].Set("button", 20);
|
|
||||||
virtual_button_params[Settings::NativeButton::SRRight].Set("button", 21);
|
|
||||||
|
|
||||||
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
|
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
|
||||||
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
|
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
|
||||||
@ -871,16 +867,12 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
|
|||||||
controller.npad_button_state.down.Assign(current_status.value);
|
controller.npad_button_state.down.Assign(current_status.value);
|
||||||
controller.debug_pad_button_state.d_down.Assign(current_status.value);
|
controller.debug_pad_button_state.d_down.Assign(current_status.value);
|
||||||
break;
|
break;
|
||||||
case Settings::NativeButton::SLLeft:
|
case Settings::NativeButton::SL:
|
||||||
controller.npad_button_state.left_sl.Assign(current_status.value);
|
controller.npad_button_state.left_sl.Assign(current_status.value);
|
||||||
break;
|
|
||||||
case Settings::NativeButton::SLRight:
|
|
||||||
controller.npad_button_state.right_sl.Assign(current_status.value);
|
controller.npad_button_state.right_sl.Assign(current_status.value);
|
||||||
break;
|
break;
|
||||||
case Settings::NativeButton::SRLeft:
|
case Settings::NativeButton::SR:
|
||||||
controller.npad_button_state.left_sr.Assign(current_status.value);
|
controller.npad_button_state.left_sr.Assign(current_status.value);
|
||||||
break;
|
|
||||||
case Settings::NativeButton::SRRight:
|
|
||||||
controller.npad_button_state.right_sr.Assign(current_status.value);
|
controller.npad_button_state.right_sr.Assign(current_status.value);
|
||||||
break;
|
break;
|
||||||
case Settings::NativeButton::Home:
|
case Settings::NativeButton::Home:
|
||||||
@ -1898,16 +1890,12 @@ NpadButton EmulatedController::GetTurboButtonMask() const {
|
|||||||
case Settings::NativeButton::DDown:
|
case Settings::NativeButton::DDown:
|
||||||
button_mask.down.Assign(1);
|
button_mask.down.Assign(1);
|
||||||
break;
|
break;
|
||||||
case Settings::NativeButton::SLLeft:
|
case Settings::NativeButton::SL:
|
||||||
button_mask.left_sl.Assign(1);
|
button_mask.left_sl.Assign(1);
|
||||||
break;
|
|
||||||
case Settings::NativeButton::SLRight:
|
|
||||||
button_mask.right_sl.Assign(1);
|
button_mask.right_sl.Assign(1);
|
||||||
break;
|
break;
|
||||||
case Settings::NativeButton::SRLeft:
|
case Settings::NativeButton::SR:
|
||||||
button_mask.left_sr.Assign(1);
|
button_mask.left_sr.Assign(1);
|
||||||
break;
|
|
||||||
case Settings::NativeButton::SRRight:
|
|
||||||
button_mask.right_sr.Assign(1);
|
button_mask.right_sr.Assign(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -356,14 +356,6 @@ struct TouchState {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
|
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
|
||||||
|
|
||||||
struct TouchFinger {
|
|
||||||
u64 last_touch{};
|
|
||||||
Common::Point<float> position{};
|
|
||||||
u32 id{};
|
|
||||||
TouchAttribute attribute{};
|
|
||||||
bool pressed{};
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::TouchScreenConfigurationForNx
|
// This is nn::hid::TouchScreenConfigurationForNx
|
||||||
struct TouchScreenConfigurationForNx {
|
struct TouchScreenConfigurationForNx {
|
||||||
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
|
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
|
||||||
|
@ -5,14 +5,13 @@
|
|||||||
#include "core/hid/hid_types.h"
|
#include "core/hid/hid_types.h"
|
||||||
#include "core/hid/input_interpreter.h"
|
#include "core/hid/input_interpreter.h"
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
#include "core/hle/service/hid/controllers/npad.h"
|
||||||
#include "core/hle/service/hid/hid_server.h"
|
#include "core/hle/service/hid/hid.h"
|
||||||
#include "core/hle/service/hid/resource_manager.h"
|
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
InputInterpreter::InputInterpreter(Core::System& system)
|
InputInterpreter::InputInterpreter(Core::System& system)
|
||||||
: npad{system.ServiceManager()
|
: npad{system.ServiceManager()
|
||||||
.GetService<Service::HID::IHidServer>("hid")
|
.GetService<Service::HID::Hid>("hid")
|
||||||
->GetResourceManager()
|
->GetAppletResource()
|
||||||
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {
|
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {
|
||||||
ResetButtonStates();
|
ResetButtonStates();
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include "core/hle/kernel/k_capabilities.h"
|
#include "core/hle/kernel/k_capabilities.h"
|
||||||
#include "core/hle/kernel/k_memory_layout.h"
|
#include "core/hle/kernel/k_memory_layout.h"
|
||||||
#include "core/hle/kernel/k_process_page_table.h"
|
#include "core/hle/kernel/k_process_page_table.h"
|
||||||
#include "core/hle/kernel/k_trace.h"
|
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/kernel/svc_version.h"
|
#include "core/hle/kernel/svc_version.h"
|
||||||
@ -330,8 +329,6 @@ Result KCapabilities::SetCapabilities(std::span<const u32> caps, KProcessPageTab
|
|||||||
|
|
||||||
// Map the range.
|
// Map the range.
|
||||||
R_TRY(this->MapRange_(cap, size_cap, page_table));
|
R_TRY(this->MapRange_(cap, size_cap, page_table));
|
||||||
} else if (GetCapabilityType(cap) == CapabilityType::MapRegion && !IsKTraceEnabled) {
|
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table));
|
R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table));
|
||||||
}
|
}
|
||||||
|
@ -1617,9 +1617,9 @@ void KPageTableBase::RemapPageGroup(PageLinkedList* page_list, KProcessAddress a
|
|||||||
const KMemoryInfo info = it->GetMemoryInfo();
|
const KMemoryInfo info = it->GetMemoryInfo();
|
||||||
|
|
||||||
// Determine the range to map.
|
// Determine the range to map.
|
||||||
KProcessAddress map_address = std::max<u64>(info.GetAddress(), GetInteger(start_address));
|
KProcessAddress map_address = std::max(info.GetAddress(), GetInteger(start_address));
|
||||||
const KProcessAddress map_end_address =
|
const KProcessAddress map_end_address =
|
||||||
std::min<u64>(info.GetEndAddress(), GetInteger(end_address));
|
std::min(info.GetEndAddress(), GetInteger(end_address));
|
||||||
ASSERT(map_end_address != map_address);
|
ASSERT(map_end_address != map_address);
|
||||||
|
|
||||||
// Determine if we should disable head merge.
|
// Determine if we should disable head merge.
|
||||||
|
@ -457,14 +457,12 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
|
|||||||
pad_entry.l_stick = stick_state.left;
|
pad_entry.l_stick = stick_state.left;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft ||
|
if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) {
|
||||||
controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
|
|
||||||
pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
|
pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
|
||||||
pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
|
pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller_type == Core::HID::NpadStyleIndex::JoyconRight ||
|
if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) {
|
||||||
controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
|
|
||||||
pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
|
pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
|
||||||
pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
|
pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,12 +3,220 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace Core {
|
#include <chrono>
|
||||||
class System;
|
|
||||||
|
#include "core/hle/service/hid/controllers/controller_base.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Core::Timing {
|
||||||
|
struct EventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::SM {
|
||||||
|
class ServiceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
|
enum class HidController : std::size_t {
|
||||||
|
DebugPad,
|
||||||
|
Touchscreen,
|
||||||
|
Mouse,
|
||||||
|
Keyboard,
|
||||||
|
XPad,
|
||||||
|
HomeButton,
|
||||||
|
SleepButton,
|
||||||
|
CaptureButton,
|
||||||
|
InputDetector,
|
||||||
|
UniquePad,
|
||||||
|
NPad,
|
||||||
|
Gesture,
|
||||||
|
ConsoleSixAxisSensor,
|
||||||
|
DebugMouse,
|
||||||
|
Palma,
|
||||||
|
|
||||||
|
MaxControllers,
|
||||||
|
};
|
||||||
|
|
||||||
|
class IAppletResource final : public ServiceFramework<IAppletResource> {
|
||||||
|
public:
|
||||||
|
explicit IAppletResource(Core::System& system_,
|
||||||
|
KernelHelpers::ServiceContext& service_context_);
|
||||||
|
~IAppletResource() override;
|
||||||
|
|
||||||
|
void ActivateController(HidController controller);
|
||||||
|
void DeactivateController(HidController controller);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T& GetController(HidController controller) {
|
||||||
|
return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const T& GetController(HidController controller) const {
|
||||||
|
return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T>
|
||||||
|
void MakeController(HidController controller, u8* shared_memory) {
|
||||||
|
if constexpr (std::is_constructible_v<T, Core::System&, u8*>) {
|
||||||
|
controllers[static_cast<std::size_t>(controller)] =
|
||||||
|
std::make_unique<T>(system, shared_memory);
|
||||||
|
} else {
|
||||||
|
controllers[static_cast<std::size_t>(controller)] =
|
||||||
|
std::make_unique<T>(system.HIDCore(), shared_memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
|
||||||
|
controllers[static_cast<std::size_t>(controller)] =
|
||||||
|
std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetSharedMemoryHandle(HLERequestContext& ctx);
|
||||||
|
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||||
|
void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||||
|
void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||||
|
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||||
|
|
||||||
|
KernelHelpers::ServiceContext& service_context;
|
||||||
|
|
||||||
|
std::shared_ptr<Core::Timing::EventType> npad_update_event;
|
||||||
|
std::shared_ptr<Core::Timing::EventType> default_update_event;
|
||||||
|
std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
|
||||||
|
std::shared_ptr<Core::Timing::EventType> motion_update_event;
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
|
||||||
|
controllers{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Hid final : public ServiceFramework<Hid> {
|
||||||
|
public:
|
||||||
|
explicit Hid(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_);
|
||||||
|
~Hid() override;
|
||||||
|
|
||||||
|
std::shared_ptr<IAppletResource> GetAppletResource();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateAppletResource(HLERequestContext& ctx);
|
||||||
|
void ActivateDebugPad(HLERequestContext& ctx);
|
||||||
|
void ActivateTouchScreen(HLERequestContext& ctx);
|
||||||
|
void ActivateMouse(HLERequestContext& ctx);
|
||||||
|
void ActivateKeyboard(HLERequestContext& ctx);
|
||||||
|
void SendKeyboardLockKeyEvent(HLERequestContext& ctx);
|
||||||
|
void ActivateXpad(HLERequestContext& ctx);
|
||||||
|
void GetXpadIDs(HLERequestContext& ctx);
|
||||||
|
void ActivateSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void DeactivateSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void StartSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void StopSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx);
|
||||||
|
void EnableSixAxisSensorFusion(HLERequestContext& ctx);
|
||||||
|
void SetSixAxisSensorFusionParameters(HLERequestContext& ctx);
|
||||||
|
void GetSixAxisSensorFusionParameters(HLERequestContext& ctx);
|
||||||
|
void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx);
|
||||||
|
void SetGyroscopeZeroDriftMode(HLERequestContext& ctx);
|
||||||
|
void GetGyroscopeZeroDriftMode(HLERequestContext& ctx);
|
||||||
|
void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx);
|
||||||
|
void IsSixAxisSensorAtRest(HLERequestContext& ctx);
|
||||||
|
void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx);
|
||||||
|
void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx);
|
||||||
|
void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx);
|
||||||
|
void GetSixAxisSensorIcInformation(HLERequestContext& ctx);
|
||||||
|
void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx);
|
||||||
|
void ActivateGesture(HLERequestContext& ctx);
|
||||||
|
void SetSupportedNpadStyleSet(HLERequestContext& ctx);
|
||||||
|
void GetSupportedNpadStyleSet(HLERequestContext& ctx);
|
||||||
|
void SetSupportedNpadIdType(HLERequestContext& ctx);
|
||||||
|
void ActivateNpad(HLERequestContext& ctx);
|
||||||
|
void DeactivateNpad(HLERequestContext& ctx);
|
||||||
|
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
|
||||||
|
void DisconnectNpad(HLERequestContext& ctx);
|
||||||
|
void GetPlayerLedPattern(HLERequestContext& ctx);
|
||||||
|
void ActivateNpadWithRevision(HLERequestContext& ctx);
|
||||||
|
void SetNpadJoyHoldType(HLERequestContext& ctx);
|
||||||
|
void GetNpadJoyHoldType(HLERequestContext& ctx);
|
||||||
|
void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx);
|
||||||
|
void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx);
|
||||||
|
void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx);
|
||||||
|
void MergeSingleJoyAsDualJoy(HLERequestContext& ctx);
|
||||||
|
void StartLrAssignmentMode(HLERequestContext& ctx);
|
||||||
|
void StopLrAssignmentMode(HLERequestContext& ctx);
|
||||||
|
void SetNpadHandheldActivationMode(HLERequestContext& ctx);
|
||||||
|
void GetNpadHandheldActivationMode(HLERequestContext& ctx);
|
||||||
|
void SwapNpadAssignment(HLERequestContext& ctx);
|
||||||
|
void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
|
||||||
|
void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
|
||||||
|
void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
|
||||||
|
void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
|
||||||
|
void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
|
||||||
|
void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
|
||||||
|
void GetVibrationDeviceInfo(HLERequestContext& ctx);
|
||||||
|
void SendVibrationValue(HLERequestContext& ctx);
|
||||||
|
void GetActualVibrationValue(HLERequestContext& ctx);
|
||||||
|
void CreateActiveVibrationDeviceList(HLERequestContext& ctx);
|
||||||
|
void PermitVibration(HLERequestContext& ctx);
|
||||||
|
void IsVibrationPermitted(HLERequestContext& ctx);
|
||||||
|
void SendVibrationValues(HLERequestContext& ctx);
|
||||||
|
void SendVibrationGcErmCommand(HLERequestContext& ctx);
|
||||||
|
void GetActualVibrationGcErmCommand(HLERequestContext& ctx);
|
||||||
|
void BeginPermitVibrationSession(HLERequestContext& ctx);
|
||||||
|
void EndPermitVibrationSession(HLERequestContext& ctx);
|
||||||
|
void IsVibrationDeviceMounted(HLERequestContext& ctx);
|
||||||
|
void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void StartConsoleSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void StopConsoleSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void ActivateSevenSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void StartSevenSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void StopSevenSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void InitializeSevenSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void FinalizeSevenSixAxisSensor(HLERequestContext& ctx);
|
||||||
|
void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx);
|
||||||
|
void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
|
||||||
|
void GetPalmaConnectionHandle(HLERequestContext& ctx);
|
||||||
|
void InitializePalma(HLERequestContext& ctx);
|
||||||
|
void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx);
|
||||||
|
void GetPalmaOperationInfo(HLERequestContext& ctx);
|
||||||
|
void PlayPalmaActivity(HLERequestContext& ctx);
|
||||||
|
void SetPalmaFrModeType(HLERequestContext& ctx);
|
||||||
|
void ReadPalmaStep(HLERequestContext& ctx);
|
||||||
|
void EnablePalmaStep(HLERequestContext& ctx);
|
||||||
|
void ResetPalmaStep(HLERequestContext& ctx);
|
||||||
|
void ReadPalmaApplicationSection(HLERequestContext& ctx);
|
||||||
|
void WritePalmaApplicationSection(HLERequestContext& ctx);
|
||||||
|
void ReadPalmaUniqueCode(HLERequestContext& ctx);
|
||||||
|
void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx);
|
||||||
|
void WritePalmaActivityEntry(HLERequestContext& ctx);
|
||||||
|
void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx);
|
||||||
|
void WritePalmaWaveEntry(HLERequestContext& ctx);
|
||||||
|
void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
|
||||||
|
void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
|
||||||
|
void SuspendPalmaFeature(HLERequestContext& ctx);
|
||||||
|
void GetPalmaOperationResult(HLERequestContext& ctx);
|
||||||
|
void ReadPalmaPlayLog(HLERequestContext& ctx);
|
||||||
|
void ResetPalmaPlayLog(HLERequestContext& ctx);
|
||||||
|
void SetIsPalmaAllConnectable(HLERequestContext& ctx);
|
||||||
|
void SetIsPalmaPairedConnectable(HLERequestContext& ctx);
|
||||||
|
void PairPalma(HLERequestContext& ctx);
|
||||||
|
void SetPalmaBoostMode(HLERequestContext& ctx);
|
||||||
|
void CancelWritePalmaWaveEntry(HLERequestContext& ctx);
|
||||||
|
void EnablePalmaBoostMode(HLERequestContext& ctx);
|
||||||
|
void GetPalmaBluetoothAddress(HLERequestContext& ctx);
|
||||||
|
void SetDisallowedPalmaConnection(HLERequestContext& ctx);
|
||||||
|
void SetNpadCommunicationMode(HLERequestContext& ctx);
|
||||||
|
void GetNpadCommunicationMode(HLERequestContext& ctx);
|
||||||
|
void SetTouchScreenConfiguration(HLERequestContext& ctx);
|
||||||
|
void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
std::shared_ptr<IAppletResource> applet_resource;
|
||||||
|
|
||||||
|
KernelHelpers::ServiceContext service_context;
|
||||||
|
};
|
||||||
|
|
||||||
void LoopProcess(Core::System& system);
|
void LoopProcess(Core::System& system);
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
@ -1,159 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/hid/hid_debug_server.h"
|
|
||||||
#include "core/hle/service/hid/resource_manager.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
|
|
||||||
namespace Service::HID {
|
|
||||||
|
|
||||||
IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource)
|
|
||||||
: ServiceFramework{system_, "hid:dbg"}, resource_manager{resource} {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, nullptr, "DeactivateDebugPad"},
|
|
||||||
{1, nullptr, "SetDebugPadAutoPilotState"},
|
|
||||||
{2, nullptr, "UnsetDebugPadAutoPilotState"},
|
|
||||||
{10, nullptr, "DeactivateTouchScreen"},
|
|
||||||
{11, nullptr, "SetTouchScreenAutoPilotState"},
|
|
||||||
{12, nullptr, "UnsetTouchScreenAutoPilotState"},
|
|
||||||
{13, nullptr, "GetTouchScreenConfiguration"},
|
|
||||||
{14, nullptr, "ProcessTouchScreenAutoTune"},
|
|
||||||
{15, nullptr, "ForceStopTouchScreenManagement"},
|
|
||||||
{16, nullptr, "ForceRestartTouchScreenManagement"},
|
|
||||||
{17, nullptr, "IsTouchScreenManaged"},
|
|
||||||
{20, nullptr, "DeactivateMouse"},
|
|
||||||
{21, nullptr, "SetMouseAutoPilotState"},
|
|
||||||
{22, nullptr, "UnsetMouseAutoPilotState"},
|
|
||||||
{25, nullptr, "SetDebugMouseAutoPilotState"},
|
|
||||||
{26, nullptr, "UnsetDebugMouseAutoPilotState"},
|
|
||||||
{30, nullptr, "DeactivateKeyboard"},
|
|
||||||
{31, nullptr, "SetKeyboardAutoPilotState"},
|
|
||||||
{32, nullptr, "UnsetKeyboardAutoPilotState"},
|
|
||||||
{50, nullptr, "DeactivateXpad"},
|
|
||||||
{51, nullptr, "SetXpadAutoPilotState"},
|
|
||||||
{52, nullptr, "UnsetXpadAutoPilotState"},
|
|
||||||
{53, nullptr, "DeactivateJoyXpad"},
|
|
||||||
{60, nullptr, "ClearNpadSystemCommonPolicy"},
|
|
||||||
{61, nullptr, "DeactivateNpad"},
|
|
||||||
{62, nullptr, "ForceDisconnectNpad"},
|
|
||||||
{91, nullptr, "DeactivateGesture"},
|
|
||||||
{110, nullptr, "DeactivateHomeButton"},
|
|
||||||
{111, nullptr, "SetHomeButtonAutoPilotState"},
|
|
||||||
{112, nullptr, "UnsetHomeButtonAutoPilotState"},
|
|
||||||
{120, nullptr, "DeactivateSleepButton"},
|
|
||||||
{121, nullptr, "SetSleepButtonAutoPilotState"},
|
|
||||||
{122, nullptr, "UnsetSleepButtonAutoPilotState"},
|
|
||||||
{123, nullptr, "DeactivateInputDetector"},
|
|
||||||
{130, nullptr, "DeactivateCaptureButton"},
|
|
||||||
{131, nullptr, "SetCaptureButtonAutoPilotState"},
|
|
||||||
{132, nullptr, "UnsetCaptureButtonAutoPilotState"},
|
|
||||||
{133, nullptr, "SetShiftAccelerometerCalibrationValue"},
|
|
||||||
{134, nullptr, "GetShiftAccelerometerCalibrationValue"},
|
|
||||||
{135, nullptr, "SetShiftGyroscopeCalibrationValue"},
|
|
||||||
{136, nullptr, "GetShiftGyroscopeCalibrationValue"},
|
|
||||||
{140, nullptr, "DeactivateConsoleSixAxisSensor"},
|
|
||||||
{141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
|
|
||||||
{142, nullptr, "DeactivateSevenSixAxisSensor"},
|
|
||||||
{143, nullptr, "GetConsoleSixAxisSensorCountStates"},
|
|
||||||
{144, nullptr, "GetAccelerometerFsr"},
|
|
||||||
{145, nullptr, "SetAccelerometerFsr"},
|
|
||||||
{146, nullptr, "GetAccelerometerOdr"},
|
|
||||||
{147, nullptr, "SetAccelerometerOdr"},
|
|
||||||
{148, nullptr, "GetGyroscopeFsr"},
|
|
||||||
{149, nullptr, "SetGyroscopeFsr"},
|
|
||||||
{150, nullptr, "GetGyroscopeOdr"},
|
|
||||||
{151, nullptr, "SetGyroscopeOdr"},
|
|
||||||
{152, nullptr, "GetWhoAmI"},
|
|
||||||
{201, nullptr, "ActivateFirmwareUpdate"},
|
|
||||||
{202, nullptr, "DeactivateFirmwareUpdate"},
|
|
||||||
{203, nullptr, "StartFirmwareUpdate"},
|
|
||||||
{204, nullptr, "GetFirmwareUpdateStage"},
|
|
||||||
{205, nullptr, "GetFirmwareVersion"},
|
|
||||||
{206, nullptr, "GetDestinationFirmwareVersion"},
|
|
||||||
{207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
|
|
||||||
{208, nullptr, "StartFirmwareUpdateForRevert"},
|
|
||||||
{209, nullptr, "GetAvailableFirmwareVersionForRevert"},
|
|
||||||
{210, nullptr, "IsFirmwareUpdatingDevice"},
|
|
||||||
{211, nullptr, "StartFirmwareUpdateIndividual"},
|
|
||||||
{215, nullptr, "SetUsbFirmwareForceUpdateEnabled"},
|
|
||||||
{216, nullptr, "SetAllKuinaDevicesToFirmwareUpdateMode"},
|
|
||||||
{221, nullptr, "UpdateControllerColor"},
|
|
||||||
{222, nullptr, "ConnectUsbPadsAsync"},
|
|
||||||
{223, nullptr, "DisconnectUsbPadsAsync"},
|
|
||||||
{224, nullptr, "UpdateDesignInfo"},
|
|
||||||
{225, nullptr, "GetUniquePadDriverState"},
|
|
||||||
{226, nullptr, "GetSixAxisSensorDriverStates"},
|
|
||||||
{227, nullptr, "GetRxPacketHistory"},
|
|
||||||
{228, nullptr, "AcquireOperationEventHandle"},
|
|
||||||
{229, nullptr, "ReadSerialFlash"},
|
|
||||||
{230, nullptr, "WriteSerialFlash"},
|
|
||||||
{231, nullptr, "GetOperationResult"},
|
|
||||||
{232, nullptr, "EnableShipmentMode"},
|
|
||||||
{233, nullptr, "ClearPairingInfo"},
|
|
||||||
{234, nullptr, "GetUniquePadDeviceTypeSetInternal"},
|
|
||||||
{235, nullptr, "EnableAnalogStickPower"},
|
|
||||||
{236, nullptr, "RequestKuinaUartClockCal"},
|
|
||||||
{237, nullptr, "GetKuinaUartClockCal"},
|
|
||||||
{238, nullptr, "SetKuinaUartClockTrim"},
|
|
||||||
{239, nullptr, "KuinaLoopbackTest"},
|
|
||||||
{240, nullptr, "RequestBatteryVoltage"},
|
|
||||||
{241, nullptr, "GetBatteryVoltage"},
|
|
||||||
{242, nullptr, "GetUniquePadPowerInfo"},
|
|
||||||
{243, nullptr, "RebootUniquePad"},
|
|
||||||
{244, nullptr, "RequestKuinaFirmwareVersion"},
|
|
||||||
{245, nullptr, "GetKuinaFirmwareVersion"},
|
|
||||||
{246, nullptr, "GetVidPid"},
|
|
||||||
{247, nullptr, "GetAnalogStickCalibrationValue"},
|
|
||||||
{248, nullptr, "GetUniquePadIdsFull"},
|
|
||||||
{249, nullptr, "ConnectUniquePad"},
|
|
||||||
{250, nullptr, "IsVirtual"},
|
|
||||||
{251, nullptr, "GetAnalogStickModuleParam"},
|
|
||||||
{301, nullptr, "GetAbstractedPadHandles"},
|
|
||||||
{302, nullptr, "GetAbstractedPadState"},
|
|
||||||
{303, nullptr, "GetAbstractedPadsState"},
|
|
||||||
{321, nullptr, "SetAutoPilotVirtualPadState"},
|
|
||||||
{322, nullptr, "UnsetAutoPilotVirtualPadState"},
|
|
||||||
{323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
|
|
||||||
{324, nullptr, "AttachHdlsWorkBuffer"},
|
|
||||||
{325, nullptr, "ReleaseHdlsWorkBuffer"},
|
|
||||||
{326, nullptr, "DumpHdlsNpadAssignmentState"},
|
|
||||||
{327, nullptr, "DumpHdlsStates"},
|
|
||||||
{328, nullptr, "ApplyHdlsNpadAssignmentState"},
|
|
||||||
{329, nullptr, "ApplyHdlsStateList"},
|
|
||||||
{330, nullptr, "AttachHdlsVirtualDevice"},
|
|
||||||
{331, nullptr, "DetachHdlsVirtualDevice"},
|
|
||||||
{332, nullptr, "SetHdlsState"},
|
|
||||||
{350, nullptr, "AddRegisteredDevice"},
|
|
||||||
{400, nullptr, "DisableExternalMcuOnNxDevice"},
|
|
||||||
{401, nullptr, "DisableRailDeviceFiltering"},
|
|
||||||
{402, nullptr, "EnableWiredPairing"},
|
|
||||||
{403, nullptr, "EnableShipmentModeAutoClear"},
|
|
||||||
{404, nullptr, "SetRailEnabled"},
|
|
||||||
{500, nullptr, "SetFactoryInt"},
|
|
||||||
{501, nullptr, "IsFactoryBootEnabled"},
|
|
||||||
{550, nullptr, "SetAnalogStickModelDataTemporarily"},
|
|
||||||
{551, nullptr, "GetAnalogStickModelData"},
|
|
||||||
{552, nullptr, "ResetAnalogStickModelData"},
|
|
||||||
{600, nullptr, "ConvertPadState"},
|
|
||||||
{650, nullptr, "AddButtonPlayData"},
|
|
||||||
{651, nullptr, "StartButtonPlayData"},
|
|
||||||
{652, nullptr, "StopButtonPlayData"},
|
|
||||||
{2000, nullptr, "DeactivateDigitizer"},
|
|
||||||
{2001, nullptr, "SetDigitizerAutoPilotState"},
|
|
||||||
{2002, nullptr, "UnsetDigitizerAutoPilotState"},
|
|
||||||
{2002, nullptr, "ReloadFirmwareDebugSettings"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
IHidDebugServer::~IHidDebugServer() = default;
|
|
||||||
|
|
||||||
std::shared_ptr<ResourceManager> IHidDebugServer::GetResourceManager() {
|
|
||||||
resource_manager->Initialize();
|
|
||||||
return resource_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::HID
|
|
@ -1,26 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::HID {
|
|
||||||
class ResourceManager;
|
|
||||||
|
|
||||||
class IHidDebugServer final : public ServiceFramework<IHidDebugServer> {
|
|
||||||
public:
|
|
||||||
explicit IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
|
|
||||||
~IHidDebugServer() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<ResourceManager> GetResourceManager();
|
|
||||||
|
|
||||||
std::shared_ptr<ResourceManager> resource_manager;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::HID
|
|
File diff suppressed because it is too large
Load Diff
@ -1,146 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::HID {
|
|
||||||
class ResourceManager;
|
|
||||||
|
|
||||||
class IHidServer final : public ServiceFramework<IHidServer> {
|
|
||||||
public:
|
|
||||||
explicit IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
|
|
||||||
~IHidServer() override;
|
|
||||||
|
|
||||||
std::shared_ptr<ResourceManager> GetResourceManager();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void CreateAppletResource(HLERequestContext& ctx);
|
|
||||||
void ActivateDebugPad(HLERequestContext& ctx);
|
|
||||||
void ActivateTouchScreen(HLERequestContext& ctx);
|
|
||||||
void ActivateMouse(HLERequestContext& ctx);
|
|
||||||
void ActivateKeyboard(HLERequestContext& ctx);
|
|
||||||
void SendKeyboardLockKeyEvent(HLERequestContext& ctx);
|
|
||||||
void AcquireXpadIdEventHandle(HLERequestContext& ctx);
|
|
||||||
void ReleaseXpadIdEventHandle(HLERequestContext& ctx);
|
|
||||||
void ActivateXpad(HLERequestContext& ctx);
|
|
||||||
void GetXpadIds(HLERequestContext& ctx);
|
|
||||||
void ActivateJoyXpad(HLERequestContext& ctx);
|
|
||||||
void GetJoyXpadLifoHandle(HLERequestContext& ctx);
|
|
||||||
void GetJoyXpadIds(HLERequestContext& ctx);
|
|
||||||
void ActivateSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void DeactivateSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void GetSixAxisSensorLifoHandle(HLERequestContext& ctx);
|
|
||||||
void ActivateJoySixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void DeactivateJoySixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void GetJoySixAxisSensorLifoHandle(HLERequestContext& ctx);
|
|
||||||
void StartSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void StopSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx);
|
|
||||||
void EnableSixAxisSensorFusion(HLERequestContext& ctx);
|
|
||||||
void SetSixAxisSensorFusionParameters(HLERequestContext& ctx);
|
|
||||||
void GetSixAxisSensorFusionParameters(HLERequestContext& ctx);
|
|
||||||
void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx);
|
|
||||||
void SetGyroscopeZeroDriftMode(HLERequestContext& ctx);
|
|
||||||
void GetGyroscopeZeroDriftMode(HLERequestContext& ctx);
|
|
||||||
void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx);
|
|
||||||
void IsSixAxisSensorAtRest(HLERequestContext& ctx);
|
|
||||||
void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx);
|
|
||||||
void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx);
|
|
||||||
void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx);
|
|
||||||
void GetSixAxisSensorIcInformation(HLERequestContext& ctx);
|
|
||||||
void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx);
|
|
||||||
void ActivateGesture(HLERequestContext& ctx);
|
|
||||||
void SetSupportedNpadStyleSet(HLERequestContext& ctx);
|
|
||||||
void GetSupportedNpadStyleSet(HLERequestContext& ctx);
|
|
||||||
void SetSupportedNpadIdType(HLERequestContext& ctx);
|
|
||||||
void ActivateNpad(HLERequestContext& ctx);
|
|
||||||
void DeactivateNpad(HLERequestContext& ctx);
|
|
||||||
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
|
|
||||||
void DisconnectNpad(HLERequestContext& ctx);
|
|
||||||
void GetPlayerLedPattern(HLERequestContext& ctx);
|
|
||||||
void ActivateNpadWithRevision(HLERequestContext& ctx);
|
|
||||||
void SetNpadJoyHoldType(HLERequestContext& ctx);
|
|
||||||
void GetNpadJoyHoldType(HLERequestContext& ctx);
|
|
||||||
void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx);
|
|
||||||
void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx);
|
|
||||||
void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx);
|
|
||||||
void MergeSingleJoyAsDualJoy(HLERequestContext& ctx);
|
|
||||||
void StartLrAssignmentMode(HLERequestContext& ctx);
|
|
||||||
void StopLrAssignmentMode(HLERequestContext& ctx);
|
|
||||||
void SetNpadHandheldActivationMode(HLERequestContext& ctx);
|
|
||||||
void GetNpadHandheldActivationMode(HLERequestContext& ctx);
|
|
||||||
void SwapNpadAssignment(HLERequestContext& ctx);
|
|
||||||
void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
|
|
||||||
void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
|
|
||||||
void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
|
|
||||||
void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
|
|
||||||
void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
|
|
||||||
void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
|
|
||||||
void GetVibrationDeviceInfo(HLERequestContext& ctx);
|
|
||||||
void SendVibrationValue(HLERequestContext& ctx);
|
|
||||||
void GetActualVibrationValue(HLERequestContext& ctx);
|
|
||||||
void CreateActiveVibrationDeviceList(HLERequestContext& ctx);
|
|
||||||
void PermitVibration(HLERequestContext& ctx);
|
|
||||||
void IsVibrationPermitted(HLERequestContext& ctx);
|
|
||||||
void SendVibrationValues(HLERequestContext& ctx);
|
|
||||||
void SendVibrationGcErmCommand(HLERequestContext& ctx);
|
|
||||||
void GetActualVibrationGcErmCommand(HLERequestContext& ctx);
|
|
||||||
void BeginPermitVibrationSession(HLERequestContext& ctx);
|
|
||||||
void EndPermitVibrationSession(HLERequestContext& ctx);
|
|
||||||
void IsVibrationDeviceMounted(HLERequestContext& ctx);
|
|
||||||
void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void StartConsoleSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void StopConsoleSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void ActivateSevenSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void StartSevenSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void StopSevenSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void InitializeSevenSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void FinalizeSevenSixAxisSensor(HLERequestContext& ctx);
|
|
||||||
void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx);
|
|
||||||
void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
|
|
||||||
void GetPalmaConnectionHandle(HLERequestContext& ctx);
|
|
||||||
void InitializePalma(HLERequestContext& ctx);
|
|
||||||
void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx);
|
|
||||||
void GetPalmaOperationInfo(HLERequestContext& ctx);
|
|
||||||
void PlayPalmaActivity(HLERequestContext& ctx);
|
|
||||||
void SetPalmaFrModeType(HLERequestContext& ctx);
|
|
||||||
void ReadPalmaStep(HLERequestContext& ctx);
|
|
||||||
void EnablePalmaStep(HLERequestContext& ctx);
|
|
||||||
void ResetPalmaStep(HLERequestContext& ctx);
|
|
||||||
void ReadPalmaApplicationSection(HLERequestContext& ctx);
|
|
||||||
void WritePalmaApplicationSection(HLERequestContext& ctx);
|
|
||||||
void ReadPalmaUniqueCode(HLERequestContext& ctx);
|
|
||||||
void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx);
|
|
||||||
void WritePalmaActivityEntry(HLERequestContext& ctx);
|
|
||||||
void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx);
|
|
||||||
void WritePalmaWaveEntry(HLERequestContext& ctx);
|
|
||||||
void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
|
|
||||||
void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
|
|
||||||
void SuspendPalmaFeature(HLERequestContext& ctx);
|
|
||||||
void GetPalmaOperationResult(HLERequestContext& ctx);
|
|
||||||
void ReadPalmaPlayLog(HLERequestContext& ctx);
|
|
||||||
void ResetPalmaPlayLog(HLERequestContext& ctx);
|
|
||||||
void SetIsPalmaAllConnectable(HLERequestContext& ctx);
|
|
||||||
void SetIsPalmaPairedConnectable(HLERequestContext& ctx);
|
|
||||||
void PairPalma(HLERequestContext& ctx);
|
|
||||||
void SetPalmaBoostMode(HLERequestContext& ctx);
|
|
||||||
void CancelWritePalmaWaveEntry(HLERequestContext& ctx);
|
|
||||||
void EnablePalmaBoostMode(HLERequestContext& ctx);
|
|
||||||
void GetPalmaBluetoothAddress(HLERequestContext& ctx);
|
|
||||||
void SetDisallowedPalmaConnection(HLERequestContext& ctx);
|
|
||||||
void SetNpadCommunicationMode(HLERequestContext& ctx);
|
|
||||||
void GetNpadCommunicationMode(HLERequestContext& ctx);
|
|
||||||
void SetTouchScreenConfiguration(HLERequestContext& ctx);
|
|
||||||
void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
std::shared_ptr<ResourceManager> resource_manager;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::HID
|
|
@ -1,304 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "core/hid/hid_core.h"
|
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
|
||||||
#include "core/hle/service/hid/controllers/touchscreen.h"
|
|
||||||
#include "core/hle/service/hid/errors.h"
|
|
||||||
#include "core/hle/service/hid/hid_system_server.h"
|
|
||||||
#include "core/hle/service/hid/resource_manager.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
|
|
||||||
namespace Service::HID {
|
|
||||||
|
|
||||||
IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<ResourceManager> resource)
|
|
||||||
: ServiceFramework{system_, "hid:sys"}, service_context{system_, service_name},
|
|
||||||
resource_manager{resource} {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{31, nullptr, "SendKeyboardLockKeyEvent"},
|
|
||||||
{101, nullptr, "AcquireHomeButtonEventHandle"},
|
|
||||||
{111, nullptr, "ActivateHomeButton"},
|
|
||||||
{121, nullptr, "AcquireSleepButtonEventHandle"},
|
|
||||||
{131, nullptr, "ActivateSleepButton"},
|
|
||||||
{141, nullptr, "AcquireCaptureButtonEventHandle"},
|
|
||||||
{151, nullptr, "ActivateCaptureButton"},
|
|
||||||
{161, nullptr, "GetPlatformConfig"},
|
|
||||||
{210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
|
|
||||||
{211, nullptr, "GetNpadsWithNfc"},
|
|
||||||
{212, nullptr, "AcquireNfcActivateEventHandle"},
|
|
||||||
{213, nullptr, "ActivateNfc"},
|
|
||||||
{214, nullptr, "GetXcdHandleForNpadWithNfc"},
|
|
||||||
{215, nullptr, "IsNfcActivated"},
|
|
||||||
{230, nullptr, "AcquireIrSensorEventHandle"},
|
|
||||||
{231, nullptr, "ActivateIrSensor"},
|
|
||||||
{232, nullptr, "GetIrSensorState"},
|
|
||||||
{233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
|
|
||||||
{301, nullptr, "ActivateNpadSystem"},
|
|
||||||
{303, &IHidSystemServer::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
|
|
||||||
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
|
|
||||||
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
|
|
||||||
{306, &IHidSystemServer::GetLastActiveNpad, "GetLastActiveNpad"},
|
|
||||||
{307, nullptr, "GetNpadSystemExtStyle"},
|
|
||||||
{308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
|
|
||||||
{309, nullptr, "GetNpadFullKeyGripColor"},
|
|
||||||
{310, nullptr, "GetMaskedSupportedNpadStyleSet"},
|
|
||||||
{311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
|
|
||||||
{312, nullptr, "SetSupportedNpadStyleSetAll"},
|
|
||||||
{313, nullptr, "GetNpadCaptureButtonAssignment"},
|
|
||||||
{314, nullptr, "GetAppletFooterUiType"},
|
|
||||||
{315, nullptr, "GetAppletDetailedUiType"},
|
|
||||||
{316, nullptr, "GetNpadInterfaceType"},
|
|
||||||
{317, nullptr, "GetNpadLeftRightInterfaceType"},
|
|
||||||
{318, nullptr, "HasBattery"},
|
|
||||||
{319, nullptr, "HasLeftRightBattery"},
|
|
||||||
{321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
|
|
||||||
{322, nullptr, "GetIrSensorState"},
|
|
||||||
{323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
|
|
||||||
{324, nullptr, "GetUniquePadButtonSet"},
|
|
||||||
{325, nullptr, "GetUniquePadColor"},
|
|
||||||
{326, nullptr, "GetUniquePadAppletDetailedUiType"},
|
|
||||||
{327, nullptr, "GetAbstractedPadIdDataFromNpad"},
|
|
||||||
{328, nullptr, "AttachAbstractedPadToNpad"},
|
|
||||||
{329, nullptr, "DetachAbstractedPadAll"},
|
|
||||||
{330, nullptr, "CheckAbstractedPadConnection"},
|
|
||||||
{500, nullptr, "SetAppletResourceUserId"},
|
|
||||||
{501, nullptr, "RegisterAppletResourceUserId"},
|
|
||||||
{502, nullptr, "UnregisterAppletResourceUserId"},
|
|
||||||
{503, nullptr, "EnableAppletToGetInput"},
|
|
||||||
{504, nullptr, "SetAruidValidForVibration"},
|
|
||||||
{505, nullptr, "EnableAppletToGetSixAxisSensor"},
|
|
||||||
{506, nullptr, "EnableAppletToGetPadInput"},
|
|
||||||
{507, nullptr, "EnableAppletToGetTouchScreen"},
|
|
||||||
{510, nullptr, "SetVibrationMasterVolume"},
|
|
||||||
{511, nullptr, "GetVibrationMasterVolume"},
|
|
||||||
{512, nullptr, "BeginPermitVibrationSession"},
|
|
||||||
{513, nullptr, "EndPermitVibrationSession"},
|
|
||||||
{514, nullptr, "Unknown514"},
|
|
||||||
{520, nullptr, "EnableHandheldHids"},
|
|
||||||
{521, nullptr, "DisableHandheldHids"},
|
|
||||||
{522, nullptr, "SetJoyConRailEnabled"},
|
|
||||||
{523, nullptr, "IsJoyConRailEnabled"},
|
|
||||||
{524, nullptr, "IsHandheldHidsEnabled"},
|
|
||||||
{525, nullptr, "IsJoyConAttachedOnAllRail"},
|
|
||||||
{540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
|
|
||||||
{541, nullptr, "GetPlayReportControllerUsages"},
|
|
||||||
{542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
|
|
||||||
{543, nullptr, "GetRegisteredDevicesOld"},
|
|
||||||
{544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
|
|
||||||
{545, nullptr, "SendConnectionTrigger"},
|
|
||||||
{546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
|
|
||||||
{547, nullptr, "GetAllowedBluetoothLinksCount"},
|
|
||||||
{548, nullptr, "GetRegisteredDevices"},
|
|
||||||
{549, nullptr, "GetConnectableRegisteredDevices"},
|
|
||||||
{700, nullptr, "ActivateUniquePad"},
|
|
||||||
{702, nullptr, "AcquireUniquePadConnectionEventHandle"},
|
|
||||||
{703, nullptr, "GetUniquePadIds"},
|
|
||||||
{751, &IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
|
||||||
{800, nullptr, "ListSixAxisSensorHandles"},
|
|
||||||
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
|
|
||||||
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
|
|
||||||
{803, nullptr, "StartSixAxisSensorUserCalibration"},
|
|
||||||
{804, nullptr, "CancelSixAxisSensorUserCalibration"},
|
|
||||||
{805, nullptr, "GetUniquePadBluetoothAddress"},
|
|
||||||
{806, nullptr, "DisconnectUniquePad"},
|
|
||||||
{807, nullptr, "GetUniquePadType"},
|
|
||||||
{808, nullptr, "GetUniquePadInterface"},
|
|
||||||
{809, nullptr, "GetUniquePadSerialNumber"},
|
|
||||||
{810, nullptr, "GetUniquePadControllerNumber"},
|
|
||||||
{811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
|
|
||||||
{812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
|
|
||||||
{821, nullptr, "StartAnalogStickManualCalibration"},
|
|
||||||
{822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
|
|
||||||
{823, nullptr, "CancelAnalogStickManualCalibration"},
|
|
||||||
{824, nullptr, "ResetAnalogStickManualCalibration"},
|
|
||||||
{825, nullptr, "GetAnalogStickState"},
|
|
||||||
{826, nullptr, "GetAnalogStickManualCalibrationStage"},
|
|
||||||
{827, nullptr, "IsAnalogStickButtonPressed"},
|
|
||||||
{828, nullptr, "IsAnalogStickInReleasePosition"},
|
|
||||||
{829, nullptr, "IsAnalogStickInCircumference"},
|
|
||||||
{830, nullptr, "SetNotificationLedPattern"},
|
|
||||||
{831, nullptr, "SetNotificationLedPatternWithTimeout"},
|
|
||||||
{832, nullptr, "PrepareHidsForNotificationWake"},
|
|
||||||
{850, &IHidSystemServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
|
|
||||||
{851, nullptr, "EnableUsbFullKeyController"},
|
|
||||||
{852, nullptr, "IsUsbConnected"},
|
|
||||||
{870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
|
|
||||||
{900, nullptr, "ActivateInputDetector"},
|
|
||||||
{901, nullptr, "NotifyInputDetector"},
|
|
||||||
{1000, nullptr, "InitializeFirmwareUpdate"},
|
|
||||||
{1001, nullptr, "GetFirmwareVersion"},
|
|
||||||
{1002, nullptr, "GetAvailableFirmwareVersion"},
|
|
||||||
{1003, nullptr, "IsFirmwareUpdateAvailable"},
|
|
||||||
{1004, nullptr, "CheckFirmwareUpdateRequired"},
|
|
||||||
{1005, nullptr, "StartFirmwareUpdate"},
|
|
||||||
{1006, nullptr, "AbortFirmwareUpdate"},
|
|
||||||
{1007, nullptr, "GetFirmwareUpdateState"},
|
|
||||||
{1008, nullptr, "ActivateAudioControl"},
|
|
||||||
{1009, nullptr, "AcquireAudioControlEventHandle"},
|
|
||||||
{1010, nullptr, "GetAudioControlStates"},
|
|
||||||
{1011, nullptr, "DeactivateAudioControl"},
|
|
||||||
{1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
|
|
||||||
{1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
|
|
||||||
{1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
|
|
||||||
{1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
|
|
||||||
{1100, nullptr, "GetHidbusSystemServiceObject"},
|
|
||||||
{1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
|
|
||||||
{1130, nullptr, "InitializeUsbFirmwareUpdate"},
|
|
||||||
{1131, nullptr, "FinalizeUsbFirmwareUpdate"},
|
|
||||||
{1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
|
|
||||||
{1133, nullptr, "StartUsbFirmwareUpdate"},
|
|
||||||
{1134, nullptr, "GetUsbFirmwareUpdateState"},
|
|
||||||
{1150, nullptr, "SetTouchScreenMagnification"},
|
|
||||||
{1151, nullptr, "GetTouchScreenFirmwareVersion"},
|
|
||||||
{1152, nullptr, "SetTouchScreenDefaultConfiguration"},
|
|
||||||
{1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
|
|
||||||
{1154, nullptr, "IsFirmwareAvailableForNotification"},
|
|
||||||
{1155, nullptr, "SetForceHandheldStyleVibration"},
|
|
||||||
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
|
|
||||||
{1157, nullptr, "CancelConnectionTrigger"},
|
|
||||||
{1200, nullptr, "IsButtonConfigSupported"},
|
|
||||||
{1201, nullptr, "IsButtonConfigEmbeddedSupported"},
|
|
||||||
{1202, nullptr, "DeleteButtonConfig"},
|
|
||||||
{1203, nullptr, "DeleteButtonConfigEmbedded"},
|
|
||||||
{1204, nullptr, "SetButtonConfigEnabled"},
|
|
||||||
{1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
|
|
||||||
{1206, nullptr, "IsButtonConfigEnabled"},
|
|
||||||
{1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
|
|
||||||
{1208, nullptr, "SetButtonConfigEmbedded"},
|
|
||||||
{1209, nullptr, "SetButtonConfigFull"},
|
|
||||||
{1210, nullptr, "SetButtonConfigLeft"},
|
|
||||||
{1211, nullptr, "SetButtonConfigRight"},
|
|
||||||
{1212, nullptr, "GetButtonConfigEmbedded"},
|
|
||||||
{1213, nullptr, "GetButtonConfigFull"},
|
|
||||||
{1214, nullptr, "GetButtonConfigLeft"},
|
|
||||||
{1215, nullptr, "GetButtonConfigRight"},
|
|
||||||
{1250, nullptr, "IsCustomButtonConfigSupported"},
|
|
||||||
{1251, nullptr, "IsDefaultButtonConfigEmbedded"},
|
|
||||||
{1252, nullptr, "IsDefaultButtonConfigFull"},
|
|
||||||
{1253, nullptr, "IsDefaultButtonConfigLeft"},
|
|
||||||
{1254, nullptr, "IsDefaultButtonConfigRight"},
|
|
||||||
{1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
|
|
||||||
{1256, nullptr, "IsButtonConfigStorageFullEmpty"},
|
|
||||||
{1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
|
|
||||||
{1258, nullptr, "IsButtonConfigStorageRightEmpty"},
|
|
||||||
{1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
|
|
||||||
{1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
|
|
||||||
{1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
|
|
||||||
{1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
|
|
||||||
{1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
|
|
||||||
{1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
|
|
||||||
{1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
|
|
||||||
{1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
|
|
||||||
{1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
|
|
||||||
{1268, nullptr, "DeleteButtonConfigStorageFull"},
|
|
||||||
{1269, nullptr, "DeleteButtonConfigStorageLeft"},
|
|
||||||
{1270, nullptr, "DeleteButtonConfigStorageRight"},
|
|
||||||
{1271, nullptr, "IsUsingCustomButtonConfig"},
|
|
||||||
{1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
|
|
||||||
{1273, nullptr, "SetAllCustomButtonConfigEnabled"},
|
|
||||||
{1274, nullptr, "SetDefaultButtonConfig"},
|
|
||||||
{1275, nullptr, "SetAllDefaultButtonConfig"},
|
|
||||||
{1276, nullptr, "SetHidButtonConfigEmbedded"},
|
|
||||||
{1277, nullptr, "SetHidButtonConfigFull"},
|
|
||||||
{1278, nullptr, "SetHidButtonConfigLeft"},
|
|
||||||
{1279, nullptr, "SetHidButtonConfigRight"},
|
|
||||||
{1280, nullptr, "GetHidButtonConfigEmbedded"},
|
|
||||||
{1281, nullptr, "GetHidButtonConfigFull"},
|
|
||||||
{1282, nullptr, "GetHidButtonConfigLeft"},
|
|
||||||
{1283, nullptr, "GetHidButtonConfigRight"},
|
|
||||||
{1284, nullptr, "GetButtonConfigStorageEmbedded"},
|
|
||||||
{1285, nullptr, "GetButtonConfigStorageFull"},
|
|
||||||
{1286, nullptr, "GetButtonConfigStorageLeft"},
|
|
||||||
{1287, nullptr, "GetButtonConfigStorageRight"},
|
|
||||||
{1288, nullptr, "SetButtonConfigStorageEmbedded"},
|
|
||||||
{1289, nullptr, "SetButtonConfigStorageFull"},
|
|
||||||
{1290, nullptr, "DeleteButtonConfigStorageRight"},
|
|
||||||
{1291, nullptr, "DeleteButtonConfigStorageRight"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
|
|
||||||
joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
|
|
||||||
}
|
|
||||||
|
|
||||||
IHidSystemServer::~IHidSystemServer() {
|
|
||||||
service_context.CloseEvent(joy_detach_event);
|
|
||||||
};
|
|
||||||
|
|
||||||
void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_HID, "called");
|
|
||||||
|
|
||||||
GetResourceManager()
|
|
||||||
->GetController<Controller_NPad>(HidController::NPad)
|
|
||||||
.ApplyNpadSystemCommonPolicy();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_HID, "(STUBBED) called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushEnum(system.HIDCore().GetLastActiveController());
|
|
||||||
}
|
|
||||||
|
|
||||||
void IHidSystemServer::GetUniquePadsFromNpad(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
|
|
||||||
|
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type);
|
|
||||||
|
|
||||||
const std::vector<Core::HID::UniquePadId> unique_pads{};
|
|
||||||
|
|
||||||
ctx.WriteBuffer(unique_pads);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(static_cast<u32>(unique_pads.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void IHidSystemServer::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
|
|
||||||
const bool is_enabled = false;
|
|
||||||
|
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(is_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called");
|
|
||||||
|
|
||||||
Core::HID::TouchScreenConfigurationForNx touchscreen_config{
|
|
||||||
.mode = Core::HID::TouchScreenModeForNx::Finger,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 &&
|
|
||||||
touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) {
|
|
||||||
touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(touchscreen_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<ResourceManager> IHidSystemServer::GetResourceManager() {
|
|
||||||
resource_manager->Initialize();
|
|
||||||
return resource_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::HID
|
|
@ -1,40 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
class KEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::HID {
|
|
||||||
class ResourceManager;
|
|
||||||
|
|
||||||
class IHidSystemServer final : public ServiceFramework<IHidSystemServer> {
|
|
||||||
public:
|
|
||||||
explicit IHidSystemServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
|
|
||||||
~IHidSystemServer() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx);
|
|
||||||
void GetLastActiveNpad(HLERequestContext& ctx);
|
|
||||||
void GetUniquePadsFromNpad(HLERequestContext& ctx);
|
|
||||||
void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx);
|
|
||||||
void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
|
|
||||||
void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
std::shared_ptr<ResourceManager> GetResourceManager();
|
|
||||||
|
|
||||||
Kernel::KEvent* joy_detach_event;
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
std::shared_ptr<ResourceManager> resource_manager;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::HID
|
|
@ -138,7 +138,7 @@ void IRS::RunMomentProcessor(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
if (result.IsSuccess()) {
|
if (result.IsSuccess()) {
|
||||||
auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
|
auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
|
||||||
MakeProcessorWithCoreContext<MomentProcessor>(parameters.camera_handle, device);
|
MakeProcessor<MomentProcessor>(parameters.camera_handle, device);
|
||||||
auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle);
|
auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle);
|
||||||
image_transfer_processor.SetConfig(parameters.processor_config);
|
image_transfer_processor.SetConfig(parameters.processor_config);
|
||||||
npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
|
npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
|
||||||
|
@ -3,12 +3,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/hid/hid_types.h"
|
#include "core/hid/hid_types.h"
|
||||||
#include "core/hid/irs_types.h"
|
#include "core/hid/irs_types.h"
|
||||||
#include "core/hle/service/hid/irsensor/processor_base.h"
|
#include "core/hle/service/hid/irsensor/processor_base.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
class EmulatedController;
|
class EmulatedController;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
|
@ -3,18 +3,16 @@
|
|||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/core_timing.h"
|
|
||||||
#include "core/hid/emulated_controller.h"
|
#include "core/hid/emulated_controller.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hle/service/hid/irsensor/clustering_processor.h"
|
#include "core/hle/service/hid/irsensor/clustering_processor.h"
|
||||||
|
|
||||||
namespace Service::IRS {
|
namespace Service::IRS {
|
||||||
ClusteringProcessor::ClusteringProcessor(Core::System& system_,
|
ClusteringProcessor::ClusteringProcessor(Core::HID::HIDCore& hid_core_,
|
||||||
Core::IrSensor::DeviceFormat& device_format,
|
Core::IrSensor::DeviceFormat& device_format,
|
||||||
std::size_t npad_index)
|
std::size_t npad_index)
|
||||||
: device{device_format}, system{system_} {
|
: device{device_format} {
|
||||||
npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
|
npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index);
|
||||||
|
|
||||||
device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor;
|
device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor;
|
||||||
device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
|
device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
|
||||||
@ -50,7 +48,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
next_state = {};
|
next_state = {};
|
||||||
const auto& camera_data = npad_device->GetCamera();
|
const auto camera_data = npad_device->GetCamera();
|
||||||
auto filtered_image = camera_data.data;
|
auto filtered_image = camera_data.data;
|
||||||
|
|
||||||
RemoveLowIntensityData(filtered_image);
|
RemoveLowIntensityData(filtered_image);
|
||||||
@ -85,7 +83,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
next_state.sampling_number = camera_data.sample;
|
next_state.sampling_number = camera_data.sample;
|
||||||
next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count();
|
next_state.timestamp = next_state.timestamp + 131;
|
||||||
next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
|
next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
|
||||||
shared_memory->clustering_lifo.WriteNextEntry(next_state);
|
shared_memory->clustering_lifo.WriteNextEntry(next_state);
|
||||||
|
|
||||||
@ -204,14 +202,14 @@ ClusteringProcessor::ClusteringData ClusteringProcessor::MergeCluster(
|
|||||||
}
|
}
|
||||||
|
|
||||||
u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
|
u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
|
||||||
if ((y * width) + x >= data.size()) {
|
if ((y * width) + x > data.size()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return data[(y * width) + x];
|
return data[(y * width) + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) {
|
void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) {
|
||||||
if ((y * width) + x >= data.size()) {
|
if ((y * width) + x > data.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
data[(y * width) + x] = value;
|
data[(y * width) + x] = value;
|
||||||
|
@ -8,10 +8,6 @@
|
|||||||
#include "core/hle/service/hid/irs_ring_lifo.h"
|
#include "core/hle/service/hid/irs_ring_lifo.h"
|
||||||
#include "core/hle/service/hid/irsensor/processor_base.h"
|
#include "core/hle/service/hid/irsensor/processor_base.h"
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
class EmulatedController;
|
class EmulatedController;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
@ -19,7 +15,8 @@ class EmulatedController;
|
|||||||
namespace Service::IRS {
|
namespace Service::IRS {
|
||||||
class ClusteringProcessor final : public ProcessorBase {
|
class ClusteringProcessor final : public ProcessorBase {
|
||||||
public:
|
public:
|
||||||
explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
|
explicit ClusteringProcessor(Core::HID::HIDCore& hid_core_,
|
||||||
|
Core::IrSensor::DeviceFormat& device_format,
|
||||||
std::size_t npad_index);
|
std::size_t npad_index);
|
||||||
~ClusteringProcessor() override;
|
~ClusteringProcessor() override;
|
||||||
|
|
||||||
@ -109,7 +106,5 @@ private:
|
|||||||
Core::IrSensor::DeviceFormat& device;
|
Core::IrSensor::DeviceFormat& device;
|
||||||
Core::HID::EmulatedController* npad_device;
|
Core::HID::EmulatedController* npad_device;
|
||||||
int callback_key{};
|
int callback_key{};
|
||||||
|
|
||||||
Core::System& system;
|
|
||||||
};
|
};
|
||||||
} // namespace Service::IRS
|
} // namespace Service::IRS
|
||||||
|
@ -49,7 +49,7 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& camera_data = npad_device->GetCamera();
|
const auto camera_data = npad_device->GetCamera();
|
||||||
|
|
||||||
// This indicates how much ambient light is present
|
// This indicates how much ambient light is present
|
||||||
processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
|
processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
|
||||||
|
@ -1,137 +1,24 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/core_timing.h"
|
|
||||||
#include "core/hid/emulated_controller.h"
|
|
||||||
#include "core/hid/hid_core.h"
|
|
||||||
#include "core/hle/service/hid/irsensor/moment_processor.h"
|
#include "core/hle/service/hid/irsensor/moment_processor.h"
|
||||||
|
|
||||||
namespace Service::IRS {
|
namespace Service::IRS {
|
||||||
static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size40x30;
|
MomentProcessor::MomentProcessor(Core::IrSensor::DeviceFormat& device_format)
|
||||||
static constexpr std::size_t ImageWidth = 40;
|
: device(device_format) {
|
||||||
static constexpr std::size_t ImageHeight = 30;
|
|
||||||
|
|
||||||
MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
|
|
||||||
std::size_t npad_index)
|
|
||||||
: device(device_format), system{system_} {
|
|
||||||
npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
|
|
||||||
|
|
||||||
device.mode = Core::IrSensor::IrSensorMode::MomentProcessor;
|
device.mode = Core::IrSensor::IrSensorMode::MomentProcessor;
|
||||||
device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
|
device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
|
||||||
device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped;
|
device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped;
|
||||||
|
|
||||||
shared_memory = std::construct_at(
|
|
||||||
reinterpret_cast<MomentSharedMemory*>(&device_format.state.processor_raw_data));
|
|
||||||
|
|
||||||
Core::HID::ControllerUpdateCallback engine_callback{
|
|
||||||
.on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); },
|
|
||||||
.is_npad_service = true,
|
|
||||||
};
|
|
||||||
callback_key = npad_device->SetCallback(engine_callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MomentProcessor::~MomentProcessor() {
|
MomentProcessor::~MomentProcessor() = default;
|
||||||
npad_device->DeleteCallback(callback_key);
|
|
||||||
};
|
|
||||||
|
|
||||||
void MomentProcessor::StartProcessor() {
|
void MomentProcessor::StartProcessor() {}
|
||||||
device.camera_status = Core::IrSensor::IrCameraStatus::Available;
|
|
||||||
device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MomentProcessor::SuspendProcessor() {}
|
void MomentProcessor::SuspendProcessor() {}
|
||||||
|
|
||||||
void MomentProcessor::StopProcessor() {}
|
void MomentProcessor::StopProcessor() {}
|
||||||
|
|
||||||
void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) {
|
|
||||||
if (type != Core::HID::ControllerTriggerType::IrSensor) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_state = {};
|
|
||||||
const auto& camera_data = npad_device->GetCamera();
|
|
||||||
|
|
||||||
const auto window_width = static_cast<std::size_t>(current_config.window_of_interest.width);
|
|
||||||
const auto window_height = static_cast<std::size_t>(current_config.window_of_interest.height);
|
|
||||||
const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x);
|
|
||||||
const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y);
|
|
||||||
|
|
||||||
const std::size_t block_width = window_width / Columns;
|
|
||||||
const std::size_t block_height = window_height / Rows;
|
|
||||||
|
|
||||||
for (std::size_t row = 0; row < Rows; row++) {
|
|
||||||
for (std::size_t column = 0; column < Columns; column++) {
|
|
||||||
const size_t x_pos = (column * block_width) + window_start_x;
|
|
||||||
const size_t y_pos = (row * block_height) + window_start_y;
|
|
||||||
auto& statistic = next_state.statistic[column + (row * Columns)];
|
|
||||||
statistic = GetStatistic(camera_data.data, x_pos, y_pos, block_width, block_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
next_state.sampling_number = camera_data.sample;
|
|
||||||
next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count();
|
|
||||||
next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
|
|
||||||
shared_memory->moment_lifo.WriteNextEntry(next_state);
|
|
||||||
|
|
||||||
if (!IsProcessorActive()) {
|
|
||||||
StartProcessor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 MomentProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
|
|
||||||
if ((y * ImageWidth) + x >= data.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return data[(y * ImageWidth) + x];
|
|
||||||
}
|
|
||||||
|
|
||||||
MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector<u8>& data,
|
|
||||||
std::size_t start_x,
|
|
||||||
std::size_t start_y,
|
|
||||||
std::size_t width,
|
|
||||||
std::size_t height) const {
|
|
||||||
// The actual implementation is always 320x240
|
|
||||||
static constexpr std::size_t RealWidth = 320;
|
|
||||||
static constexpr std::size_t RealHeight = 240;
|
|
||||||
static constexpr std::size_t Threshold = 30;
|
|
||||||
MomentStatistic statistic{};
|
|
||||||
std::size_t active_points{};
|
|
||||||
|
|
||||||
// Sum all data points on the block that meet with the threshold
|
|
||||||
for (std::size_t y = 0; y < width; y++) {
|
|
||||||
for (std::size_t x = 0; x < height; x++) {
|
|
||||||
const size_t x_pos = x + start_x;
|
|
||||||
const size_t y_pos = y + start_y;
|
|
||||||
const auto pixel =
|
|
||||||
GetPixel(data, x_pos * ImageWidth / RealWidth, y_pos * ImageHeight / RealHeight);
|
|
||||||
|
|
||||||
if (pixel < Threshold) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
statistic.average_intensity += pixel;
|
|
||||||
|
|
||||||
statistic.centroid.x += static_cast<float>(x_pos);
|
|
||||||
statistic.centroid.y += static_cast<float>(y_pos);
|
|
||||||
|
|
||||||
active_points++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return an empty field if no points were available
|
|
||||||
if (active_points == 0) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally calculate the actual centroid and average intensity
|
|
||||||
statistic.centroid.x /= static_cast<float>(active_points);
|
|
||||||
statistic.centroid.y /= static_cast<float>(active_points);
|
|
||||||
statistic.average_intensity /= static_cast<f32>(width * height);
|
|
||||||
|
|
||||||
return statistic;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) {
|
void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) {
|
||||||
current_config.camera_config.exposure_time = config.camera_config.exposure_time;
|
current_config.camera_config.exposure_time = config.camera_config.exposure_time;
|
||||||
current_config.camera_config.gain = config.camera_config.gain;
|
current_config.camera_config.gain = config.camera_config.gain;
|
||||||
@ -142,8 +29,6 @@ void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig conf
|
|||||||
current_config.preprocess =
|
current_config.preprocess =
|
||||||
static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess);
|
static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess);
|
||||||
current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold;
|
current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold;
|
||||||
|
|
||||||
npad_device->SetCameraFormat(format);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::IRS
|
} // namespace Service::IRS
|
||||||
|
@ -6,22 +6,12 @@
|
|||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hid/irs_types.h"
|
#include "core/hid/irs_types.h"
|
||||||
#include "core/hle/service/hid/irs_ring_lifo.h"
|
|
||||||
#include "core/hle/service/hid/irsensor/processor_base.h"
|
#include "core/hle/service/hid/irsensor/processor_base.h"
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Core::HID {
|
|
||||||
class EmulatedController;
|
|
||||||
} // namespace Core::HID
|
|
||||||
|
|
||||||
namespace Service::IRS {
|
namespace Service::IRS {
|
||||||
class MomentProcessor final : public ProcessorBase {
|
class MomentProcessor final : public ProcessorBase {
|
||||||
public:
|
public:
|
||||||
explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
|
explicit MomentProcessor(Core::IrSensor::DeviceFormat& device_format);
|
||||||
std::size_t npad_index);
|
|
||||||
~MomentProcessor() override;
|
~MomentProcessor() override;
|
||||||
|
|
||||||
// Called when the processor is initialized
|
// Called when the processor is initialized
|
||||||
@ -37,9 +27,6 @@ public:
|
|||||||
void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config);
|
void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr std::size_t Columns = 8;
|
|
||||||
static constexpr std::size_t Rows = 6;
|
|
||||||
|
|
||||||
// This is nn::irsensor::MomentProcessorConfig
|
// This is nn::irsensor::MomentProcessorConfig
|
||||||
struct MomentProcessorConfig {
|
struct MomentProcessorConfig {
|
||||||
Core::IrSensor::CameraConfig camera_config;
|
Core::IrSensor::CameraConfig camera_config;
|
||||||
@ -63,29 +50,12 @@ private:
|
|||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level;
|
Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level;
|
||||||
INSERT_PADDING_BYTES(4);
|
INSERT_PADDING_BYTES(4);
|
||||||
std::array<MomentStatistic, Columns * Rows> statistic;
|
std::array<MomentStatistic, 0x30> stadistic;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size");
|
static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size");
|
||||||
|
|
||||||
struct MomentSharedMemory {
|
|
||||||
Service::IRS::Lifo<MomentProcessorState, 6> moment_lifo;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(MomentSharedMemory) == 0xE20, "MomentSharedMemory is an invalid size");
|
|
||||||
|
|
||||||
void OnControllerUpdate(Core::HID::ControllerTriggerType type);
|
|
||||||
u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const;
|
|
||||||
MomentStatistic GetStatistic(const std::vector<u8>& data, std::size_t start_x,
|
|
||||||
std::size_t start_y, std::size_t width, std::size_t height) const;
|
|
||||||
|
|
||||||
MomentSharedMemory* shared_memory = nullptr;
|
|
||||||
MomentProcessorState next_state{};
|
|
||||||
|
|
||||||
MomentProcessorConfig current_config{};
|
MomentProcessorConfig current_config{};
|
||||||
Core::IrSensor::DeviceFormat& device;
|
Core::IrSensor::DeviceFormat& device;
|
||||||
Core::HID::EmulatedController* npad_device;
|
|
||||||
int callback_key{};
|
|
||||||
|
|
||||||
Core::System& system;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::IRS
|
} // namespace Service::IRS
|
||||||
|
@ -1,192 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/core_timing.h"
|
|
||||||
#include "core/hid/hid_core.h"
|
|
||||||
#include "core/hle/kernel/k_shared_memory.h"
|
|
||||||
#include "core/hle/service/hid/resource_manager.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
|
|
||||||
#include "core/hle/service/hid/controllers/console_sixaxis.h"
|
|
||||||
#include "core/hle/service/hid/controllers/controller_base.h"
|
|
||||||
#include "core/hle/service/hid/controllers/debug_pad.h"
|
|
||||||
#include "core/hle/service/hid/controllers/gesture.h"
|
|
||||||
#include "core/hle/service/hid/controllers/keyboard.h"
|
|
||||||
#include "core/hle/service/hid/controllers/mouse.h"
|
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
|
||||||
#include "core/hle/service/hid/controllers/palma.h"
|
|
||||||
#include "core/hle/service/hid/controllers/stubbed.h"
|
|
||||||
#include "core/hle/service/hid/controllers/touchscreen.h"
|
|
||||||
#include "core/hle/service/hid/controllers/xpad.h"
|
|
||||||
|
|
||||||
namespace Service::HID {
|
|
||||||
|
|
||||||
// Updating period for each HID device.
|
|
||||||
// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
|
|
||||||
// Correct npad_update_ns is 4ms this is overclocked to lower input lag
|
|
||||||
constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
|
|
||||||
constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz)
|
|
||||||
constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
|
|
||||||
constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
|
|
||||||
|
|
||||||
ResourceManager::ResourceManager(Core::System& system_)
|
|
||||||
: system{system_}, service_context{system_, "hid"} {}
|
|
||||||
|
|
||||||
ResourceManager::~ResourceManager() = default;
|
|
||||||
|
|
||||||
void ResourceManager::Initialize() {
|
|
||||||
if (is_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
|
|
||||||
MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory);
|
|
||||||
MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory);
|
|
||||||
MakeController<Controller_Mouse>(HidController::Mouse, shared_memory);
|
|
||||||
MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory);
|
|
||||||
MakeController<Controller_XPad>(HidController::XPad, shared_memory);
|
|
||||||
MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory);
|
|
||||||
MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory);
|
|
||||||
MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory);
|
|
||||||
MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory);
|
|
||||||
MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory);
|
|
||||||
MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory);
|
|
||||||
MakeController<Controller_Gesture>(HidController::Gesture, shared_memory);
|
|
||||||
MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory);
|
|
||||||
MakeController<Controller_Stubbed>(HidController::DebugMouse, shared_memory);
|
|
||||||
MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory);
|
|
||||||
|
|
||||||
// Homebrew doesn't try to activate some controllers, so we activate them by default
|
|
||||||
GetController<Controller_NPad>(HidController::NPad).ActivateController();
|
|
||||||
GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController();
|
|
||||||
|
|
||||||
GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
|
|
||||||
GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
|
|
||||||
GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
|
|
||||||
GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
|
|
||||||
GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
|
|
||||||
GetController<Controller_Stubbed>(HidController::DebugMouse).SetCommonHeaderOffset(0x3DC00);
|
|
||||||
|
|
||||||
system.HIDCore().ReloadInputDevices();
|
|
||||||
is_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::ActivateController(HidController controller) {
|
|
||||||
controllers[static_cast<size_t>(controller)]->ActivateController();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::DeactivateController(HidController controller) {
|
|
||||||
controllers[static_cast<size_t>(controller)]->DeactivateController();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::UpdateControllers(std::uintptr_t user_data,
|
|
||||||
std::chrono::nanoseconds ns_late) {
|
|
||||||
auto& core_timing = system.CoreTiming();
|
|
||||||
|
|
||||||
for (const auto& controller : controllers) {
|
|
||||||
// Keyboard has it's own update event
|
|
||||||
if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Mouse has it's own update event
|
|
||||||
if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Npad has it's own update event
|
|
||||||
if (controller == controllers[static_cast<size_t>(HidController::NPad)]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
controller->OnUpdate(core_timing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
|
||||||
auto& core_timing = system.CoreTiming();
|
|
||||||
|
|
||||||
controllers[static_cast<size_t>(HidController::NPad)]->OnUpdate(core_timing);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data,
|
|
||||||
std::chrono::nanoseconds ns_late) {
|
|
||||||
auto& core_timing = system.CoreTiming();
|
|
||||||
|
|
||||||
controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing);
|
|
||||||
controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
|
||||||
auto& core_timing = system.CoreTiming();
|
|
||||||
|
|
||||||
controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing);
|
|
||||||
}
|
|
||||||
|
|
||||||
IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource)
|
|
||||||
: ServiceFramework{system_, "IAppletResource"} {
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
|
|
||||||
};
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
|
|
||||||
resource->Initialize();
|
|
||||||
|
|
||||||
// Register update callbacks
|
|
||||||
npad_update_event = Core::Timing::CreateEvent(
|
|
||||||
"HID::UpdatePadCallback",
|
|
||||||
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
|
|
||||||
-> std::optional<std::chrono::nanoseconds> {
|
|
||||||
const auto guard = LockService();
|
|
||||||
resource->UpdateNpad(user_data, ns_late);
|
|
||||||
return std::nullopt;
|
|
||||||
});
|
|
||||||
default_update_event = Core::Timing::CreateEvent(
|
|
||||||
"HID::UpdateDefaultCallback",
|
|
||||||
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
|
|
||||||
-> std::optional<std::chrono::nanoseconds> {
|
|
||||||
const auto guard = LockService();
|
|
||||||
resource->UpdateControllers(user_data, ns_late);
|
|
||||||
return std::nullopt;
|
|
||||||
});
|
|
||||||
mouse_keyboard_update_event = Core::Timing::CreateEvent(
|
|
||||||
"HID::UpdateMouseKeyboardCallback",
|
|
||||||
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
|
|
||||||
-> std::optional<std::chrono::nanoseconds> {
|
|
||||||
const auto guard = LockService();
|
|
||||||
resource->UpdateMouseKeyboard(user_data, ns_late);
|
|
||||||
return std::nullopt;
|
|
||||||
});
|
|
||||||
motion_update_event = Core::Timing::CreateEvent(
|
|
||||||
"HID::UpdateMotionCallback",
|
|
||||||
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
|
|
||||||
-> std::optional<std::chrono::nanoseconds> {
|
|
||||||
const auto guard = LockService();
|
|
||||||
resource->UpdateMotion(user_data, ns_late);
|
|
||||||
return std::nullopt;
|
|
||||||
});
|
|
||||||
|
|
||||||
system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
|
|
||||||
system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
|
|
||||||
default_update_event);
|
|
||||||
system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
|
|
||||||
mouse_keyboard_update_event);
|
|
||||||
system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
|
|
||||||
motion_update_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
IAppletResource::~IAppletResource() {
|
|
||||||
system.CoreTiming().UnscheduleEvent(npad_update_event, 0);
|
|
||||||
system.CoreTiming().UnscheduleEvent(default_update_event, 0);
|
|
||||||
system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
|
|
||||||
system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_HID, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(&system.Kernel().GetHidSharedMem());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::HID
|
|
@ -1,106 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/hle/service/hid/controllers/controller_base.h"
|
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Core::Timing {
|
|
||||||
struct EventType;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Core::HID {
|
|
||||||
class HIDCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::HID {
|
|
||||||
|
|
||||||
enum class HidController : std::size_t {
|
|
||||||
DebugPad,
|
|
||||||
Touchscreen,
|
|
||||||
Mouse,
|
|
||||||
Keyboard,
|
|
||||||
XPad,
|
|
||||||
HomeButton,
|
|
||||||
SleepButton,
|
|
||||||
CaptureButton,
|
|
||||||
InputDetector,
|
|
||||||
UniquePad,
|
|
||||||
NPad,
|
|
||||||
Gesture,
|
|
||||||
ConsoleSixAxisSensor,
|
|
||||||
DebugMouse,
|
|
||||||
Palma,
|
|
||||||
|
|
||||||
MaxControllers,
|
|
||||||
};
|
|
||||||
class ResourceManager {
|
|
||||||
public:
|
|
||||||
explicit ResourceManager(Core::System& system_);
|
|
||||||
~ResourceManager();
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T& GetController(HidController controller) {
|
|
||||||
return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
const T& GetController(HidController controller) const {
|
|
||||||
return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Initialize();
|
|
||||||
void ActivateController(HidController controller);
|
|
||||||
void DeactivateController(HidController controller);
|
|
||||||
|
|
||||||
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
|
||||||
void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
|
||||||
void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
|
||||||
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename T>
|
|
||||||
void MakeController(HidController controller, u8* shared_memory) {
|
|
||||||
if constexpr (std::is_constructible_v<T, Core::System&, u8*>) {
|
|
||||||
controllers[static_cast<std::size_t>(controller)] =
|
|
||||||
std::make_unique<T>(system, shared_memory);
|
|
||||||
} else {
|
|
||||||
controllers[static_cast<std::size_t>(controller)] =
|
|
||||||
std::make_unique<T>(system.HIDCore(), shared_memory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
|
|
||||||
controllers[static_cast<std::size_t>(controller)] =
|
|
||||||
std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_initialized{false};
|
|
||||||
std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
|
|
||||||
controllers{};
|
|
||||||
|
|
||||||
Core::System& system;
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IAppletResource final : public ServiceFramework<IAppletResource> {
|
|
||||||
public:
|
|
||||||
explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource);
|
|
||||||
~IAppletResource() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetSharedMemoryHandle(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
std::shared_ptr<Core::Timing::EventType> npad_update_event;
|
|
||||||
std::shared_ptr<Core::Timing::EventType> default_update_event;
|
|
||||||
std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
|
|
||||||
std::shared_ptr<Core::Timing::EventType> motion_update_event;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::HID
|
|
@ -1,10 +1,8 @@
|
|||||||
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
||||||
// SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <mutex>
|
|
||||||
#include <span>
|
#include <span>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
@ -12,7 +10,6 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/page_table.h"
|
#include "common/page_table.h"
|
||||||
#include "common/scope_exit.h"
|
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
@ -321,7 +318,7 @@ struct Memory::Impl {
|
|||||||
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
||||||
u8* const host_ptr) {
|
u8* const host_ptr) {
|
||||||
if constexpr (!UNSAFE) {
|
if constexpr (!UNSAFE) {
|
||||||
HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount);
|
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount);
|
||||||
}
|
}
|
||||||
std::memcpy(host_ptr, src_buffer, copy_amount);
|
std::memcpy(host_ptr, src_buffer, copy_amount);
|
||||||
},
|
},
|
||||||
@ -354,7 +351,7 @@ struct Memory::Impl {
|
|||||||
},
|
},
|
||||||
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
||||||
u8* const host_ptr) {
|
u8* const host_ptr) {
|
||||||
HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount);
|
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount);
|
||||||
std::memset(host_ptr, 0, copy_amount);
|
std::memset(host_ptr, 0, copy_amount);
|
||||||
},
|
},
|
||||||
[](const std::size_t copy_amount) {});
|
[](const std::size_t copy_amount) {});
|
||||||
@ -423,7 +420,7 @@ struct Memory::Impl {
|
|||||||
const std::size_t block_size) {
|
const std::size_t block_size) {
|
||||||
// dc cvac: Store to point of coherency
|
// dc cvac: Store to point of coherency
|
||||||
// CPU flush -> GPU invalidate
|
// CPU flush -> GPU invalidate
|
||||||
HandleRasterizerWrite(GetInteger(current_vaddr), block_size);
|
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
|
||||||
};
|
};
|
||||||
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
||||||
}
|
}
|
||||||
@ -433,7 +430,7 @@ struct Memory::Impl {
|
|||||||
const std::size_t block_size) {
|
const std::size_t block_size) {
|
||||||
// dc civac: Store to point of coherency, and invalidate from cache
|
// dc civac: Store to point of coherency, and invalidate from cache
|
||||||
// CPU flush -> GPU invalidate
|
// CPU flush -> GPU invalidate
|
||||||
HandleRasterizerWrite(GetInteger(current_vaddr), block_size);
|
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
|
||||||
};
|
};
|
||||||
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
||||||
}
|
}
|
||||||
@ -770,18 +767,7 @@ struct Memory::Impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HandleRasterizerWrite(VAddr address, size_t size) {
|
void HandleRasterizerWrite(VAddr address, size_t size) {
|
||||||
constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1;
|
const size_t core = system.GetCurrentHostThreadID();
|
||||||
const size_t core = std::min(system.GetCurrentHostThreadID(),
|
|
||||||
sys_core); // any other calls threads go to syscore.
|
|
||||||
// Guard on sys_core;
|
|
||||||
if (core == sys_core) [[unlikely]] {
|
|
||||||
sys_core_guard.lock();
|
|
||||||
}
|
|
||||||
SCOPE_EXIT({
|
|
||||||
if (core == sys_core) [[unlikely]] {
|
|
||||||
sys_core_guard.unlock();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
auto& current_area = rasterizer_write_areas[core];
|
auto& current_area = rasterizer_write_areas[core];
|
||||||
VAddr subaddress = address >> YUZU_PAGEBITS;
|
VAddr subaddress = address >> YUZU_PAGEBITS;
|
||||||
bool do_collection = current_area.last_address == subaddress;
|
bool do_collection = current_area.last_address == subaddress;
|
||||||
@ -813,7 +799,6 @@ struct Memory::Impl {
|
|||||||
rasterizer_read_areas{};
|
rasterizer_read_areas{};
|
||||||
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
|
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
|
||||||
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
|
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
|
||||||
std::mutex sys_core_guard;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory::Memory(Core::System& system_) : system{system_} {
|
Memory::Memory(Core::System& system_) : system{system_} {
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
#include "core/hle/kernel/k_page_table.h"
|
#include "core/hle/kernel/k_page_table.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
#include "core/hle/service/hid/controllers/npad.h"
|
||||||
#include "core/hle/service/hid/hid_server.h"
|
#include "core/hle/service/hid/hid.h"
|
||||||
#include "core/hle/service/hid/resource_manager.h"
|
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "core/memory/cheat_engine.h"
|
#include "core/memory/cheat_engine.h"
|
||||||
@ -55,13 +54,13 @@ void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u64 StandardVmCallbacks::HidKeysDown() {
|
u64 StandardVmCallbacks::HidKeysDown() {
|
||||||
const auto hid = system.ServiceManager().GetService<Service::HID::IHidServer>("hid");
|
const auto hid = system.ServiceManager().GetService<Service::HID::Hid>("hid");
|
||||||
if (hid == nullptr) {
|
if (hid == nullptr) {
|
||||||
LOG_WARNING(CheatEngine, "Attempted to read input state, but hid is not initialized!");
|
LOG_WARNING(CheatEngine, "Attempted to read input state, but hid is not initialized!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto applet_resource = hid->GetResourceManager();
|
const auto applet_resource = hid->GetAppletResource();
|
||||||
if (applet_resource == nullptr) {
|
if (applet_resource == nullptr) {
|
||||||
LOG_WARNING(CheatEngine,
|
LOG_WARNING(CheatEngine,
|
||||||
"Attempted to read input state, but applet resource is not initialized!");
|
"Attempted to read input state, but applet resource is not initialized!");
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
add_library(frontend_common STATIC
|
|
||||||
config.cpp
|
|
||||||
config.h
|
|
||||||
)
|
|
||||||
|
|
||||||
create_target_directory_groups(frontend_common)
|
|
||||||
target_link_libraries(frontend_common PUBLIC core SimpleIni PRIVATE common Boost::headers)
|
|
@ -1,931 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
|
||||||
#include "common/fs/fs.h"
|
|
||||||
#include "common/fs/path_util.h"
|
|
||||||
#include "common/settings.h"
|
|
||||||
#include "common/settings_common.h"
|
|
||||||
#include "common/settings_enums.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
|
||||||
#include "network/network.h"
|
|
||||||
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
|
||||||
|
|
||||||
namespace FS = Common::FS;
|
|
||||||
|
|
||||||
Config::Config(const ConfigType config_type)
|
|
||||||
: type(config_type), global{config_type == ConfigType::GlobalConfig} {}
|
|
||||||
|
|
||||||
void Config::Initialize(const std::string& config_name) {
|
|
||||||
const std::filesystem::path fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
|
|
||||||
const auto config_file = fmt::format("{}.ini", config_name);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case ConfigType::GlobalConfig:
|
|
||||||
config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
|
|
||||||
void(FS::CreateParentDir(config_loc));
|
|
||||||
SetUpIni();
|
|
||||||
Reload();
|
|
||||||
break;
|
|
||||||
case ConfigType::PerGameConfig:
|
|
||||||
config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
|
|
||||||
void(FS::CreateParentDir(config_loc));
|
|
||||||
SetUpIni();
|
|
||||||
Reload();
|
|
||||||
break;
|
|
||||||
case ConfigType::InputProfile:
|
|
||||||
config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
|
|
||||||
void(FS::CreateParentDir(config_loc));
|
|
||||||
SetUpIni();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::Initialize(const std::optional<std::string> config_path) {
|
|
||||||
const std::filesystem::path default_sdl_config_path =
|
|
||||||
FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
|
|
||||||
config_loc = config_path.value_or(FS::PathToUTF8String(default_sdl_config_path));
|
|
||||||
void(FS::CreateParentDir(config_loc));
|
|
||||||
SetUpIni();
|
|
||||||
Reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::WriteToIni() const {
|
|
||||||
if (const SI_Error rc = config->SaveFile(config_loc.c_str()); rc < 0) {
|
|
||||||
LOG_ERROR(Frontend, "Config file could not be saved!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SetUpIni() {
|
|
||||||
config = std::make_unique<CSimpleIniA>();
|
|
||||||
config->SetUnicode(true);
|
|
||||||
config->SetSpaces(false);
|
|
||||||
config->LoadFile(config_loc.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Config::IsCustomConfig() const {
|
|
||||||
return type == ConfigType::PerGameConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadPlayerValues(const std::size_t player_index) {
|
|
||||||
std::string player_prefix;
|
|
||||||
if (type != ConfigType::InputProfile) {
|
|
||||||
player_prefix.append("player_").append(ToString(player_index)).append("_");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& player = Settings::values.players.GetValue()[player_index];
|
|
||||||
if (IsCustomConfig()) {
|
|
||||||
const auto profile_name =
|
|
||||||
ReadStringSetting(std::string(player_prefix).append("profile_name"));
|
|
||||||
if (profile_name.empty()) {
|
|
||||||
// Use the global input config
|
|
||||||
player = Settings::values.players.GetValue(true)[player_index];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
player.profile_name = profile_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player_prefix.empty() && Settings::IsConfiguringGlobal()) {
|
|
||||||
const auto controller = static_cast<Settings::ControllerType>(
|
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("type"),
|
|
||||||
static_cast<u8>(Settings::ControllerType::ProController)));
|
|
||||||
|
|
||||||
if (controller == Settings::ControllerType::LeftJoycon ||
|
|
||||||
controller == Settings::ControllerType::RightJoycon) {
|
|
||||||
player.controller_type = controller;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::string connected_key = player_prefix;
|
|
||||||
player.connected = ReadBooleanSetting(connected_key.append("connected"),
|
|
||||||
std::make_optional(player_index == 0));
|
|
||||||
|
|
||||||
player.controller_type = static_cast<Settings::ControllerType>(
|
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("type"),
|
|
||||||
static_cast<u8>(Settings::ControllerType::ProController)));
|
|
||||||
|
|
||||||
player.vibration_enabled = ReadBooleanSetting(
|
|
||||||
std::string(player_prefix).append("vibration_enabled"), std::make_optional(true));
|
|
||||||
|
|
||||||
player.vibration_strength = static_cast<int>(
|
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("vibration_strength"), 100));
|
|
||||||
|
|
||||||
player.body_color_left = static_cast<u32>(ReadIntegerSetting(
|
|
||||||
std::string(player_prefix).append("body_color_left"), Settings::JOYCON_BODY_NEON_BLUE));
|
|
||||||
player.body_color_right = static_cast<u32>(ReadIntegerSetting(
|
|
||||||
std::string(player_prefix).append("body_color_right"), Settings::JOYCON_BODY_NEON_RED));
|
|
||||||
player.button_color_left = static_cast<u32>(
|
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("button_color_left"),
|
|
||||||
Settings::JOYCON_BUTTONS_NEON_BLUE));
|
|
||||||
player.button_color_right = static_cast<u32>(
|
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("button_color_right"),
|
|
||||||
Settings::JOYCON_BUTTONS_NEON_RED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadTouchscreenValues() {
|
|
||||||
Settings::values.touchscreen.enabled =
|
|
||||||
ReadBooleanSetting(std::string("touchscreen_enabled"), std::make_optional(true));
|
|
||||||
Settings::values.touchscreen.rotation_angle =
|
|
||||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_angle"), 0));
|
|
||||||
Settings::values.touchscreen.diameter_x =
|
|
||||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_x"), 15));
|
|
||||||
Settings::values.touchscreen.diameter_y =
|
|
||||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_y"), 15));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadAudioValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Audio));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Audio);
|
|
||||||
ReadCategory(Settings::Category::UiAudio);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadControlValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Controls);
|
|
||||||
|
|
||||||
Settings::values.players.SetGlobal(!IsCustomConfig());
|
|
||||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
|
||||||
ReadPlayerValues(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable docked mode if handheld is selected
|
|
||||||
const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
|
|
||||||
if (controller_type == Settings::ControllerType::Handheld) {
|
|
||||||
Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig());
|
|
||||||
Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsCustomConfig()) {
|
|
||||||
EndGroup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ReadTouchscreenValues();
|
|
||||||
ReadMotionTouchValues();
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadMotionTouchValues() {
|
|
||||||
int num_touch_from_button_maps = BeginArray(std::string("touch_from_button_maps"));
|
|
||||||
|
|
||||||
if (num_touch_from_button_maps > 0) {
|
|
||||||
for (int i = 0; i < num_touch_from_button_maps; ++i) {
|
|
||||||
SetArrayIndex(i);
|
|
||||||
|
|
||||||
Settings::TouchFromButtonMap map;
|
|
||||||
map.name = ReadStringSetting(std::string("name"), std::string("default"));
|
|
||||||
|
|
||||||
const int num_touch_maps = BeginArray(std::string("entries"));
|
|
||||||
map.buttons.reserve(num_touch_maps);
|
|
||||||
for (int j = 0; j < num_touch_maps; j++) {
|
|
||||||
SetArrayIndex(j);
|
|
||||||
std::string touch_mapping = ReadStringSetting(std::string("bind"));
|
|
||||||
map.buttons.emplace_back(std::move(touch_mapping));
|
|
||||||
}
|
|
||||||
EndArray(); // entries
|
|
||||||
Settings::values.touch_from_button_maps.emplace_back(std::move(map));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Settings::values.touch_from_button_maps.emplace_back(
|
|
||||||
Settings::TouchFromButtonMap{"default", {}});
|
|
||||||
num_touch_from_button_maps = 1;
|
|
||||||
}
|
|
||||||
EndArray(); // touch_from_button_maps
|
|
||||||
|
|
||||||
Settings::values.touch_from_button_map_index = std::clamp(
|
|
||||||
Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadCoreValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Core));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Core);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadDataStorageValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
|
||||||
|
|
||||||
FS::SetYuzuPath(FS::YuzuPath::NANDDir, ReadStringSetting(std::string("nand_directory")));
|
|
||||||
FS::SetYuzuPath(FS::YuzuPath::SDMCDir, ReadStringSetting(std::string("sdmc_directory")));
|
|
||||||
FS::SetYuzuPath(FS::YuzuPath::LoadDir, ReadStringSetting(std::string("load_directory")));
|
|
||||||
FS::SetYuzuPath(FS::YuzuPath::DumpDir, ReadStringSetting(std::string("dump_directory")));
|
|
||||||
FS::SetYuzuPath(FS::YuzuPath::TASDir, ReadStringSetting(std::string("tas_directory")));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::DataStorage);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadDebuggingValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
|
||||||
|
|
||||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
|
||||||
Settings::values.record_frame_times =
|
|
||||||
ReadBooleanSetting(std::string("record_frame_times"), std::make_optional(false));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Debugging);
|
|
||||||
ReadCategory(Settings::Category::DebuggingGraphics);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadServiceValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Services);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadDisabledAddOnValues() {
|
|
||||||
// Custom config section
|
|
||||||
BeginGroup(std::string("DisabledAddOns"));
|
|
||||||
|
|
||||||
const int size = BeginArray(std::string(""));
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
SetArrayIndex(i);
|
|
||||||
const auto title_id = ReadIntegerSetting(std::string("title_id"), 0);
|
|
||||||
std::vector<std::string> out;
|
|
||||||
const int d_size = BeginArray("disabled");
|
|
||||||
for (int j = 0; j < d_size; ++j) {
|
|
||||||
SetArrayIndex(j);
|
|
||||||
out.push_back(ReadStringSetting(std::string("d"), std::string("")));
|
|
||||||
}
|
|
||||||
EndArray(); // d
|
|
||||||
Settings::values.disabled_addons.insert_or_assign(title_id, out);
|
|
||||||
}
|
|
||||||
EndArray(); // Base disabled addons array - Has no base key
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadMiscellaneousValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Miscellaneous);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadCpuValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Cpu));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Cpu);
|
|
||||||
ReadCategory(Settings::Category::CpuDebug);
|
|
||||||
ReadCategory(Settings::Category::CpuUnsafe);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadRendererValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Renderer));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Renderer);
|
|
||||||
ReadCategory(Settings::Category::RendererAdvanced);
|
|
||||||
ReadCategory(Settings::Category::RendererDebug);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadScreenshotValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Screenshots);
|
|
||||||
FS::SetYuzuPath(FS::YuzuPath::ScreenshotsDir,
|
|
||||||
ReadStringSetting(std::string("screenshot_path"),
|
|
||||||
FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir)));
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadSystemValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::System));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::System);
|
|
||||||
ReadCategory(Settings::Category::SystemAudio);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadWebServiceValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::WebService));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::WebService);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadNetworkValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Network);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadValues() {
|
|
||||||
if (global) {
|
|
||||||
ReadDataStorageValues();
|
|
||||||
ReadDebuggingValues();
|
|
||||||
ReadDisabledAddOnValues();
|
|
||||||
ReadNetworkValues();
|
|
||||||
ReadServiceValues();
|
|
||||||
ReadWebServiceValues();
|
|
||||||
ReadMiscellaneousValues();
|
|
||||||
}
|
|
||||||
ReadControlValues();
|
|
||||||
ReadCoreValues();
|
|
||||||
ReadCpuValues();
|
|
||||||
ReadRendererValues();
|
|
||||||
ReadAudioValues();
|
|
||||||
ReadSystemValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SavePlayerValues(const std::size_t player_index) {
|
|
||||||
std::string player_prefix;
|
|
||||||
if (type != ConfigType::InputProfile) {
|
|
||||||
player_prefix = std::string("player_").append(ToString(player_index)).append("_");
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
|
||||||
if (IsCustomConfig()) {
|
|
||||||
if (player.profile_name.empty()) {
|
|
||||||
// No custom profile selected
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
WriteSetting(std::string(player_prefix).append("profile_name"), player.profile_name,
|
|
||||||
std::make_optional(std::string("")));
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteSetting(std::string(player_prefix).append("type"), static_cast<u8>(player.controller_type),
|
|
||||||
std::make_optional(static_cast<u8>(Settings::ControllerType::ProController)));
|
|
||||||
|
|
||||||
if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) {
|
|
||||||
WriteSetting(std::string(player_prefix).append("connected"), player.connected,
|
|
||||||
std::make_optional(player_index == 0));
|
|
||||||
WriteSetting(std::string(player_prefix).append("vibration_enabled"),
|
|
||||||
player.vibration_enabled, std::make_optional(true));
|
|
||||||
WriteSetting(std::string(player_prefix).append("vibration_strength"),
|
|
||||||
player.vibration_strength, std::make_optional(100));
|
|
||||||
WriteSetting(std::string(player_prefix).append("body_color_left"), player.body_color_left,
|
|
||||||
std::make_optional(Settings::JOYCON_BODY_NEON_BLUE));
|
|
||||||
WriteSetting(std::string(player_prefix).append("body_color_right"), player.body_color_right,
|
|
||||||
std::make_optional(Settings::JOYCON_BODY_NEON_RED));
|
|
||||||
WriteSetting(std::string(player_prefix).append("button_color_left"),
|
|
||||||
player.button_color_left,
|
|
||||||
std::make_optional(Settings::JOYCON_BUTTONS_NEON_BLUE));
|
|
||||||
WriteSetting(std::string(player_prefix).append("button_color_right"),
|
|
||||||
player.button_color_right,
|
|
||||||
std::make_optional(Settings::JOYCON_BUTTONS_NEON_RED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveTouchscreenValues() {
|
|
||||||
const auto& touchscreen = Settings::values.touchscreen;
|
|
||||||
|
|
||||||
WriteSetting(std::string("touchscreen_enabled"), touchscreen.enabled, std::make_optional(true));
|
|
||||||
|
|
||||||
WriteSetting(std::string("touchscreen_angle"), touchscreen.rotation_angle,
|
|
||||||
std::make_optional(static_cast<u32>(0)));
|
|
||||||
WriteSetting(std::string("touchscreen_diameter_x"), touchscreen.diameter_x,
|
|
||||||
std::make_optional(static_cast<u32>(15)));
|
|
||||||
WriteSetting(std::string("touchscreen_diameter_y"), touchscreen.diameter_y,
|
|
||||||
std::make_optional(static_cast<u32>(15)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveMotionTouchValues() {
|
|
||||||
BeginArray(std::string("touch_from_button_maps"));
|
|
||||||
for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
|
|
||||||
SetArrayIndex(static_cast<int>(p));
|
|
||||||
WriteSetting(std::string("name"), Settings::values.touch_from_button_maps[p].name,
|
|
||||||
std::make_optional(std::string("default")));
|
|
||||||
|
|
||||||
BeginArray(std::string("entries"));
|
|
||||||
for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size();
|
|
||||||
++q) {
|
|
||||||
SetArrayIndex(static_cast<int>(q));
|
|
||||||
WriteSetting(std::string("bind"),
|
|
||||||
Settings::values.touch_from_button_maps[p].buttons[q]);
|
|
||||||
}
|
|
||||||
EndArray(); // entries
|
|
||||||
}
|
|
||||||
EndArray(); // touch_from_button_maps
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveValues() {
|
|
||||||
if (global) {
|
|
||||||
SaveDataStorageValues();
|
|
||||||
SaveDebuggingValues();
|
|
||||||
SaveDisabledAddOnValues();
|
|
||||||
SaveNetworkValues();
|
|
||||||
SaveWebServiceValues();
|
|
||||||
SaveMiscellaneousValues();
|
|
||||||
}
|
|
||||||
SaveControlValues();
|
|
||||||
SaveCoreValues();
|
|
||||||
SaveCpuValues();
|
|
||||||
SaveRendererValues();
|
|
||||||
SaveAudioValues();
|
|
||||||
SaveSystemValues();
|
|
||||||
|
|
||||||
WriteToIni();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveAudioValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Audio));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Audio);
|
|
||||||
WriteCategory(Settings::Category::UiAudio);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveControlValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Controls);
|
|
||||||
|
|
||||||
Settings::values.players.SetGlobal(!IsCustomConfig());
|
|
||||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
|
||||||
SavePlayerValues(p);
|
|
||||||
}
|
|
||||||
if (IsCustomConfig()) {
|
|
||||||
EndGroup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SaveTouchscreenValues();
|
|
||||||
SaveMotionTouchValues();
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveCoreValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Core));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Core);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveDataStorageValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
|
||||||
|
|
||||||
WriteSetting(std::string("nand_directory"), FS::GetYuzuPathString(FS::YuzuPath::NANDDir),
|
|
||||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
|
|
||||||
WriteSetting(std::string("sdmc_directory"), FS::GetYuzuPathString(FS::YuzuPath::SDMCDir),
|
|
||||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
|
|
||||||
WriteSetting(std::string("load_directory"), FS::GetYuzuPathString(FS::YuzuPath::LoadDir),
|
|
||||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
|
|
||||||
WriteSetting(std::string("dump_directory"), FS::GetYuzuPathString(FS::YuzuPath::DumpDir),
|
|
||||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
|
|
||||||
WriteSetting(std::string("tas_directory"), FS::GetYuzuPathString(FS::YuzuPath::TASDir),
|
|
||||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::DataStorage);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveDebuggingValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
|
||||||
|
|
||||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
|
||||||
WriteSetting(std::string("record_frame_times"), Settings::values.record_frame_times);
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Debugging);
|
|
||||||
WriteCategory(Settings::Category::DebuggingGraphics);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveNetworkValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Network);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveDisabledAddOnValues() {
|
|
||||||
// Custom config section
|
|
||||||
BeginGroup(std::string("DisabledAddOns"));
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
BeginArray(std::string(""));
|
|
||||||
for (const auto& elem : Settings::values.disabled_addons) {
|
|
||||||
SetArrayIndex(i);
|
|
||||||
WriteSetting(std::string("title_id"), elem.first, std::make_optional(static_cast<u64>(0)));
|
|
||||||
BeginArray(std::string("disabled"));
|
|
||||||
for (std::size_t j = 0; j < elem.second.size(); ++j) {
|
|
||||||
SetArrayIndex(static_cast<int>(j));
|
|
||||||
WriteSetting(std::string("d"), elem.second[j], std::make_optional(std::string("")));
|
|
||||||
}
|
|
||||||
EndArray(); // disabled
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
EndArray(); // Base disabled addons array - Has no base key
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveMiscellaneousValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Miscellaneous);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveCpuValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Cpu));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Cpu);
|
|
||||||
WriteCategory(Settings::Category::CpuDebug);
|
|
||||||
WriteCategory(Settings::Category::CpuUnsafe);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveRendererValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Renderer));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Renderer);
|
|
||||||
WriteCategory(Settings::Category::RendererAdvanced);
|
|
||||||
WriteCategory(Settings::Category::RendererDebug);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveScreenshotValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots));
|
|
||||||
|
|
||||||
WriteSetting(std::string("screenshot_path"),
|
|
||||||
FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir));
|
|
||||||
WriteCategory(Settings::Category::Screenshots);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveSystemValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::System));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::System);
|
|
||||||
WriteCategory(Settings::Category::SystemAudio);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SaveWebServiceValues() {
|
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::WebService));
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::WebService);
|
|
||||||
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Config::ReadBooleanSetting(const std::string& key, const std::optional<bool> default_value) {
|
|
||||||
std::string full_key = GetFullKey(key, false);
|
|
||||||
if (!default_value.has_value()) {
|
|
||||||
return config->GetBoolValue(GetSection().c_str(), full_key.c_str(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config->GetBoolValue(GetSection().c_str(),
|
|
||||||
std::string(full_key).append("\\default").c_str(), false)) {
|
|
||||||
return static_cast<bool>(default_value.value());
|
|
||||||
} else {
|
|
||||||
return config->GetBoolValue(GetSection().c_str(), full_key.c_str(),
|
|
||||||
static_cast<bool>(default_value.value()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s64 Config::ReadIntegerSetting(const std::string& key, const std::optional<s64> default_value) {
|
|
||||||
std::string full_key = GetFullKey(key, false);
|
|
||||||
if (!default_value.has_value()) {
|
|
||||||
try {
|
|
||||||
return std::stoll(
|
|
||||||
std::string(config->GetValue(GetSection().c_str(), full_key.c_str(), "0")));
|
|
||||||
} catch (...) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s64 result = 0;
|
|
||||||
if (config->GetBoolValue(GetSection().c_str(),
|
|
||||||
std::string(full_key).append("\\default").c_str(), true)) {
|
|
||||||
result = default_value.value();
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
result = std::stoll(std::string(config->GetValue(
|
|
||||||
GetSection().c_str(), full_key.c_str(), ToString(default_value.value()).c_str())));
|
|
||||||
} catch (...) {
|
|
||||||
result = default_value.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Config::ReadDoubleSetting(const std::string& key,
|
|
||||||
const std::optional<double> default_value) {
|
|
||||||
std::string full_key = GetFullKey(key, false);
|
|
||||||
if (!default_value.has_value()) {
|
|
||||||
return config->GetDoubleValue(GetSection().c_str(), full_key.c_str(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
double result;
|
|
||||||
if (config->GetBoolValue(GetSection().c_str(),
|
|
||||||
std::string(full_key).append("\\default").c_str(), true)) {
|
|
||||||
result = default_value.value();
|
|
||||||
} else {
|
|
||||||
result =
|
|
||||||
config->GetDoubleValue(GetSection().c_str(), full_key.c_str(), default_value.value());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Config::ReadStringSetting(const std::string& key,
|
|
||||||
const std::optional<std::string> default_value) {
|
|
||||||
std::string result;
|
|
||||||
std::string full_key = GetFullKey(key, false);
|
|
||||||
if (!default_value.has_value()) {
|
|
||||||
result = config->GetValue(GetSection().c_str(), full_key.c_str(), "");
|
|
||||||
boost::replace_all(result, "\"", "");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config->GetBoolValue(GetSection().c_str(),
|
|
||||||
std::string(full_key).append("\\default").c_str(), true)) {
|
|
||||||
result = default_value.value();
|
|
||||||
} else {
|
|
||||||
result =
|
|
||||||
config->GetValue(GetSection().c_str(), full_key.c_str(), default_value.value().c_str());
|
|
||||||
}
|
|
||||||
boost::replace_all(result, "\"", "");
|
|
||||||
boost::replace_all(result, "//", "/");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Config::Exists(const std::string& section, const std::string& key) const {
|
|
||||||
const std::string value = config->GetValue(section.c_str(), key.c_str(), "");
|
|
||||||
return !value.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
void Config::WriteSetting(const std::string& key, const Type& value,
|
|
||||||
const std::optional<Type>& default_value,
|
|
||||||
const std::optional<bool>& use_global) {
|
|
||||||
std::string full_key = GetFullKey(key, false);
|
|
||||||
|
|
||||||
std::string saved_value;
|
|
||||||
std::string string_default;
|
|
||||||
if constexpr (std::is_same_v<Type, std::string>) {
|
|
||||||
saved_value.append(AdjustOutputString(value));
|
|
||||||
if (default_value.has_value()) {
|
|
||||||
string_default.append(AdjustOutputString(default_value.value()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
saved_value.append(AdjustOutputString(ToString(value)));
|
|
||||||
if (default_value.has_value()) {
|
|
||||||
string_default.append(ToString(default_value.value()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (default_value.has_value() && use_global.has_value()) {
|
|
||||||
if (!global) {
|
|
||||||
WriteSettingInternal(std::string(full_key).append("\\global"),
|
|
||||||
ToString(use_global.value()));
|
|
||||||
}
|
|
||||||
if (global || use_global.value() == false) {
|
|
||||||
WriteSettingInternal(std::string(full_key).append("\\default"),
|
|
||||||
ToString(string_default == saved_value));
|
|
||||||
WriteSettingInternal(full_key, saved_value);
|
|
||||||
}
|
|
||||||
} else if (default_value.has_value() && !use_global.has_value()) {
|
|
||||||
WriteSettingInternal(std::string(full_key).append("\\default"),
|
|
||||||
ToString(string_default == saved_value));
|
|
||||||
WriteSettingInternal(full_key, saved_value);
|
|
||||||
} else {
|
|
||||||
WriteSettingInternal(full_key, saved_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::WriteSettingInternal(const std::string& key, const std::string& value) {
|
|
||||||
config->SetValue(GetSection().c_str(), key.c_str(), value.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::Reload() {
|
|
||||||
ReadValues();
|
|
||||||
// To apply default value changes
|
|
||||||
SaveValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::Save() {
|
|
||||||
SaveValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ClearControlPlayerValues() const {
|
|
||||||
// If key is an empty string, all keys in the current group() are removed.
|
|
||||||
const char* section = Settings::TranslateCategory(Settings::Category::Controls);
|
|
||||||
CSimpleIniA::TNamesDepend keys;
|
|
||||||
config->GetAllKeys(section, keys);
|
|
||||||
for (const auto& key : keys) {
|
|
||||||
if (std::string(config->GetValue(section, key.pItem)).empty()) {
|
|
||||||
config->Delete(section, key.pItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& Config::GetConfigFilePath() const {
|
|
||||||
return config_loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadCategory(const Settings::Category category) {
|
|
||||||
const auto& settings = FindRelevantList(category);
|
|
||||||
std::ranges::for_each(settings, [&](const auto& setting) { ReadSettingGeneric(setting); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::WriteCategory(const Settings::Category category) {
|
|
||||||
const auto& settings = FindRelevantList(category);
|
|
||||||
std::ranges::for_each(settings, [&](const auto& setting) { WriteSettingGeneric(setting); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) {
|
|
||||||
if (!setting->Save() || (!setting->Switchable() && !global)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string key = AdjustKey(setting->GetLabel());
|
|
||||||
const std::string default_value(setting->DefaultToString());
|
|
||||||
|
|
||||||
bool use_global = true;
|
|
||||||
if (setting->Switchable() && !global) {
|
|
||||||
use_global =
|
|
||||||
ReadBooleanSetting(std::string(key).append("\\use_global"), std::make_optional(true));
|
|
||||||
setting->SetGlobal(use_global);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (global || !use_global) {
|
|
||||||
const bool is_default =
|
|
||||||
ReadBooleanSetting(std::string(key).append("\\default"), std::make_optional(true));
|
|
||||||
if (!is_default) {
|
|
||||||
const std::string setting_string = ReadStringSetting(key, default_value);
|
|
||||||
setting->LoadString(setting_string);
|
|
||||||
} else {
|
|
||||||
// Empty string resets the Setting to default
|
|
||||||
setting->LoadString("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::WriteSettingGeneric(const Settings::BasicSetting* const setting) {
|
|
||||||
if (!setting->Save()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string key = AdjustKey(setting->GetLabel());
|
|
||||||
if (setting->Switchable()) {
|
|
||||||
if (!global) {
|
|
||||||
WriteSetting(std::string(key).append("\\use_global"), setting->UsingGlobal());
|
|
||||||
}
|
|
||||||
if (global || !setting->UsingGlobal()) {
|
|
||||||
WriteSetting(std::string(key).append("\\default"),
|
|
||||||
setting->ToString() == setting->DefaultToString());
|
|
||||||
WriteSetting(key, setting->ToString());
|
|
||||||
}
|
|
||||||
} else if (global) {
|
|
||||||
WriteSetting(std::string(key).append("\\default"),
|
|
||||||
setting->ToString() == setting->DefaultToString());
|
|
||||||
WriteSetting(key, setting->ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::BeginGroup(const std::string& group) {
|
|
||||||
// You can't begin a group while reading/writing from a config array
|
|
||||||
ASSERT(array_stack.empty());
|
|
||||||
|
|
||||||
key_stack.push_back(AdjustKey(group));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::EndGroup() {
|
|
||||||
// You can't end a group if you haven't started one yet
|
|
||||||
ASSERT(!key_stack.empty());
|
|
||||||
|
|
||||||
// You can't end a group when reading/writing from a config array
|
|
||||||
ASSERT(array_stack.empty());
|
|
||||||
|
|
||||||
key_stack.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Config::GetSection() {
|
|
||||||
if (key_stack.empty()) {
|
|
||||||
return std::string{""};
|
|
||||||
}
|
|
||||||
|
|
||||||
return key_stack.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Config::GetGroup() const {
|
|
||||||
if (key_stack.size() <= 1) {
|
|
||||||
return std::string{""};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string key;
|
|
||||||
for (size_t i = 1; i < key_stack.size(); ++i) {
|
|
||||||
key.append(key_stack[i]).append("\\");
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Config::AdjustKey(const std::string& key) {
|
|
||||||
std::string adjusted_key(key);
|
|
||||||
boost::replace_all(adjusted_key, "/", "\\");
|
|
||||||
boost::replace_all(adjusted_key, " ", "%20");
|
|
||||||
return adjusted_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Config::AdjustOutputString(const std::string& string) {
|
|
||||||
std::string adjusted_string(string);
|
|
||||||
boost::replace_all(adjusted_string, "\\", "/");
|
|
||||||
boost::replace_all(adjusted_string, "//", "/");
|
|
||||||
|
|
||||||
// Needed for backwards compatibility with QSettings deserialization
|
|
||||||
for (const auto& special_character : special_characters) {
|
|
||||||
if (adjusted_string.find(special_character) != std::string::npos) {
|
|
||||||
adjusted_string.insert(0, "\"");
|
|
||||||
adjusted_string.append("\"");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return adjusted_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Config::GetFullKey(const std::string& key, bool skipArrayIndex) {
|
|
||||||
if (array_stack.empty()) {
|
|
||||||
return std::string(GetGroup()).append(AdjustKey(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string array_key;
|
|
||||||
for (size_t i = 0; i < array_stack.size(); ++i) {
|
|
||||||
if (!array_stack[i].name.empty()) {
|
|
||||||
array_key.append(array_stack[i].name).append("\\");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skipArrayIndex || (array_stack.size() - 1 != i && array_stack.size() > 1)) {
|
|
||||||
array_key.append(ToString(array_stack[i].index)).append("\\");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::string final_key = std::string(GetGroup()).append(array_key).append(AdjustKey(key));
|
|
||||||
return final_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Config::BeginArray(const std::string& array) {
|
|
||||||
array_stack.push_back(ConfigArray{AdjustKey(array), 0, 0});
|
|
||||||
const int size = config->GetLongValue(GetSection().c_str(),
|
|
||||||
GetFullKey(std::string("size"), true).c_str(), 0);
|
|
||||||
array_stack.back().size = size;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::EndArray() {
|
|
||||||
// You can't end a config array before starting one
|
|
||||||
ASSERT(!array_stack.empty());
|
|
||||||
|
|
||||||
// Write out the size to config
|
|
||||||
if (key_stack.size() == 1 && array_stack.back().name.empty()) {
|
|
||||||
// Edge-case where the first array created doesn't have a name
|
|
||||||
config->SetValue(GetSection().c_str(), std::string("size").c_str(),
|
|
||||||
ToString(array_stack.back().size).c_str());
|
|
||||||
} else {
|
|
||||||
const auto key = GetFullKey(std::string("size"), true);
|
|
||||||
config->SetValue(GetSection().c_str(), key.c_str(),
|
|
||||||
ToString(array_stack.back().size).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
array_stack.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::SetArrayIndex(const int index) {
|
|
||||||
// You can't set the array index if you haven't started one yet
|
|
||||||
ASSERT(!array_stack.empty());
|
|
||||||
|
|
||||||
const int array_index = index + 1;
|
|
||||||
|
|
||||||
// You can't exceed the known max size of the array by more than 1
|
|
||||||
ASSERT(array_stack.front().size + 1 >= array_index);
|
|
||||||
|
|
||||||
// Change the config array size to the current index since you may want
|
|
||||||
// to reduce the number of elements that you read back from the config
|
|
||||||
// in the future.
|
|
||||||
array_stack.back().size = array_index;
|
|
||||||
array_stack.back().index = array_index;
|
|
||||||
}
|
|
@ -1,206 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include "common/settings.h"
|
|
||||||
|
|
||||||
#include <SimpleIni.h>
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
|
||||||
|
|
||||||
// Workaround for conflicting definition in libloaderapi.h caused by SimpleIni
|
|
||||||
#undef LoadString
|
|
||||||
#undef CreateFile
|
|
||||||
#undef DeleteFile
|
|
||||||
#undef CopyFile
|
|
||||||
#undef CreateDirectory
|
|
||||||
#undef MoveFile
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Config {
|
|
||||||
public:
|
|
||||||
enum class ConfigType {
|
|
||||||
GlobalConfig,
|
|
||||||
PerGameConfig,
|
|
||||||
InputProfile,
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual ~Config() = default;
|
|
||||||
|
|
||||||
void ClearControlPlayerValues() const;
|
|
||||||
|
|
||||||
[[nodiscard]] const std::string& GetConfigFilePath() const;
|
|
||||||
|
|
||||||
[[nodiscard]] bool Exists(const std::string& section, const std::string& key) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit Config(ConfigType config_type = ConfigType::GlobalConfig);
|
|
||||||
|
|
||||||
void Initialize(const std::string& config_name = "config");
|
|
||||||
void Initialize(std::optional<std::string> config_path);
|
|
||||||
|
|
||||||
void WriteToIni() const;
|
|
||||||
|
|
||||||
void SetUpIni();
|
|
||||||
[[nodiscard]] bool IsCustomConfig() const;
|
|
||||||
|
|
||||||
void Reload();
|
|
||||||
void Save();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Derived config classes must implement this so they can reload all platform-specific
|
|
||||||
* values and global ones.
|
|
||||||
*/
|
|
||||||
virtual void ReloadAllValues() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Derived config classes must implement this so they can save all platform-specific
|
|
||||||
* and global values.
|
|
||||||
*/
|
|
||||||
virtual void SaveAllValues() = 0;
|
|
||||||
|
|
||||||
void ReadValues();
|
|
||||||
void ReadPlayerValues(std::size_t player_index);
|
|
||||||
|
|
||||||
void ReadTouchscreenValues();
|
|
||||||
void ReadMotionTouchValues();
|
|
||||||
|
|
||||||
// Read functions bases off the respective config section names.
|
|
||||||
void ReadAudioValues();
|
|
||||||
void ReadControlValues();
|
|
||||||
void ReadCoreValues();
|
|
||||||
void ReadDataStorageValues();
|
|
||||||
void ReadDebuggingValues();
|
|
||||||
void ReadServiceValues();
|
|
||||||
void ReadDisabledAddOnValues();
|
|
||||||
void ReadMiscellaneousValues();
|
|
||||||
void ReadCpuValues();
|
|
||||||
void ReadRendererValues();
|
|
||||||
void ReadScreenshotValues();
|
|
||||||
void ReadSystemValues();
|
|
||||||
void ReadWebServiceValues();
|
|
||||||
void ReadNetworkValues();
|
|
||||||
|
|
||||||
// Read platform specific sections
|
|
||||||
virtual void ReadHidbusValues() = 0;
|
|
||||||
virtual void ReadDebugControlValues() = 0;
|
|
||||||
virtual void ReadPathValues() = 0;
|
|
||||||
virtual void ReadShortcutValues() = 0;
|
|
||||||
virtual void ReadUIValues() = 0;
|
|
||||||
virtual void ReadUIGamelistValues() = 0;
|
|
||||||
virtual void ReadUILayoutValues() = 0;
|
|
||||||
virtual void ReadMultiplayerValues() = 0;
|
|
||||||
|
|
||||||
void SaveValues();
|
|
||||||
void SavePlayerValues(std::size_t player_index);
|
|
||||||
void SaveTouchscreenValues();
|
|
||||||
void SaveMotionTouchValues();
|
|
||||||
|
|
||||||
// Save functions based off the respective config section names.
|
|
||||||
void SaveAudioValues();
|
|
||||||
void SaveControlValues();
|
|
||||||
void SaveCoreValues();
|
|
||||||
void SaveDataStorageValues();
|
|
||||||
void SaveDebuggingValues();
|
|
||||||
void SaveNetworkValues();
|
|
||||||
void SaveDisabledAddOnValues();
|
|
||||||
void SaveMiscellaneousValues();
|
|
||||||
void SaveCpuValues();
|
|
||||||
void SaveRendererValues();
|
|
||||||
void SaveScreenshotValues();
|
|
||||||
void SaveSystemValues();
|
|
||||||
void SaveWebServiceValues();
|
|
||||||
|
|
||||||
// Save platform specific sections
|
|
||||||
virtual void SaveHidbusValues() = 0;
|
|
||||||
virtual void SaveDebugControlValues() = 0;
|
|
||||||
virtual void SavePathValues() = 0;
|
|
||||||
virtual void SaveShortcutValues() = 0;
|
|
||||||
virtual void SaveUIValues() = 0;
|
|
||||||
virtual void SaveUIGamelistValues() = 0;
|
|
||||||
virtual void SaveUILayoutValues() = 0;
|
|
||||||
virtual void SaveMultiplayerValues() = 0;
|
|
||||||
|
|
||||||
virtual std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a setting from the qt_config.
|
|
||||||
*
|
|
||||||
* @param key The setting's identifier
|
|
||||||
* @param default_value The value to use when the setting is not already present in the config
|
|
||||||
*/
|
|
||||||
bool ReadBooleanSetting(const std::string& key,
|
|
||||||
std::optional<bool> default_value = std::nullopt);
|
|
||||||
s64 ReadIntegerSetting(const std::string& key, std::optional<s64> default_value = std::nullopt);
|
|
||||||
double ReadDoubleSetting(const std::string& key,
|
|
||||||
std::optional<double> default_value = std::nullopt);
|
|
||||||
std::string ReadStringSetting(const std::string& key,
|
|
||||||
std::optional<std::string> default_value = std::nullopt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a setting to the qt_config.
|
|
||||||
*
|
|
||||||
* @param key The setting's idetentifier
|
|
||||||
* @param value Value of the setting
|
|
||||||
* @param default_value Default of the setting if not present in config
|
|
||||||
* @param use_global Specifies if the custom or global config should be in use, for custom
|
|
||||||
* configs
|
|
||||||
*/
|
|
||||||
template <typename Type = int>
|
|
||||||
void WriteSetting(const std::string& key, const Type& value,
|
|
||||||
const std::optional<Type>& default_value = std::nullopt,
|
|
||||||
const std::optional<bool>& use_global = std::nullopt);
|
|
||||||
void WriteSettingInternal(const std::string& key, const std::string& value);
|
|
||||||
|
|
||||||
void ReadCategory(Settings::Category category);
|
|
||||||
void WriteCategory(Settings::Category category);
|
|
||||||
void ReadSettingGeneric(Settings::BasicSetting* setting);
|
|
||||||
void WriteSettingGeneric(const Settings::BasicSetting* setting);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
[[nodiscard]] std::string ToString(const T& value_) {
|
|
||||||
if constexpr (std::is_same_v<T, std::string>) {
|
|
||||||
return value_;
|
|
||||||
} else if constexpr (std::is_same_v<T, std::optional<u32>>) {
|
|
||||||
return value_.has_value() ? std::to_string(*value_) : "none";
|
|
||||||
} else if constexpr (std::is_same_v<T, bool>) {
|
|
||||||
return value_ ? "true" : "false";
|
|
||||||
} else {
|
|
||||||
return std::to_string(static_cast<s64>(value_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BeginGroup(const std::string& group);
|
|
||||||
void EndGroup();
|
|
||||||
std::string GetSection();
|
|
||||||
[[nodiscard]] std::string GetGroup() const;
|
|
||||||
static std::string AdjustKey(const std::string& key);
|
|
||||||
static std::string AdjustOutputString(const std::string& string);
|
|
||||||
std::string GetFullKey(const std::string& key, bool skipArrayIndex);
|
|
||||||
int BeginArray(const std::string& array);
|
|
||||||
void EndArray();
|
|
||||||
void SetArrayIndex(int index);
|
|
||||||
|
|
||||||
const ConfigType type;
|
|
||||||
std::unique_ptr<CSimpleIniA> config;
|
|
||||||
std::string config_loc;
|
|
||||||
const bool global;
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline static std::array<char, 19> special_characters = {'!', '#', '$', '%', '^', '&', '*',
|
|
||||||
'|', ';', '\'', '\"', ',', '<', '.',
|
|
||||||
'>', '?', '`', '~', '='};
|
|
||||||
|
|
||||||
struct ConfigArray {
|
|
||||||
std::string name;
|
|
||||||
int size;
|
|
||||||
int index;
|
|
||||||
};
|
|
||||||
std::vector<ConfigArray> array_stack;
|
|
||||||
std::vector<std::string> key_stack;
|
|
||||||
};
|
|
@ -415,7 +415,7 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
|
|||||||
// This list is missing ZL/ZR since those are not considered buttons.
|
// This list is missing ZL/ZR since those are not considered buttons.
|
||||||
// We will add those afterwards
|
// We will add those afterwards
|
||||||
// This list also excludes any button that can't be really mapped
|
// This list also excludes any button that can't be really mapped
|
||||||
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 14>
|
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 12>
|
||||||
switch_to_gcadapter_button = {
|
switch_to_gcadapter_button = {
|
||||||
std::pair{Settings::NativeButton::A, PadButton::ButtonA},
|
std::pair{Settings::NativeButton::A, PadButton::ButtonA},
|
||||||
{Settings::NativeButton::B, PadButton::ButtonB},
|
{Settings::NativeButton::B, PadButton::ButtonB},
|
||||||
@ -426,10 +426,8 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
|
|||||||
{Settings::NativeButton::DUp, PadButton::ButtonUp},
|
{Settings::NativeButton::DUp, PadButton::ButtonUp},
|
||||||
{Settings::NativeButton::DRight, PadButton::ButtonRight},
|
{Settings::NativeButton::DRight, PadButton::ButtonRight},
|
||||||
{Settings::NativeButton::DDown, PadButton::ButtonDown},
|
{Settings::NativeButton::DDown, PadButton::ButtonDown},
|
||||||
{Settings::NativeButton::SLLeft, PadButton::TriggerL},
|
{Settings::NativeButton::SL, PadButton::TriggerL},
|
||||||
{Settings::NativeButton::SRLeft, PadButton::TriggerR},
|
{Settings::NativeButton::SR, PadButton::TriggerR},
|
||||||
{Settings::NativeButton::SLRight, PadButton::TriggerL},
|
|
||||||
{Settings::NativeButton::SRRight, PadButton::TriggerR},
|
|
||||||
{Settings::NativeButton::R, PadButton::TriggerZ},
|
{Settings::NativeButton::R, PadButton::TriggerZ},
|
||||||
};
|
};
|
||||||
if (!params.Has("port")) {
|
if (!params.Has("port")) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user