Compare commits
1 Commits
android-46
...
android-27
Author | SHA1 | Date | |
---|---|---|---|
27c3d35f2f |
@ -3,4 +3,4 @@
|
||||
|
||||
[codespell]
|
||||
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
|
||||
ignore-words-list = aci,allright,ba,canonicalizations,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,zink
|
||||
ignore-words-list = aci,allright,ba,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,zink
|
||||
|
@ -48,7 +48,7 @@ It is written in C++ with portability in mind, and we actively maintain builds f
|
||||
|
||||
The emulator is capable of running most commercial games at full speed, provided you meet the [necessary hardware requirements](https://yuzu-emu.org/help/quickstart/#hardware-requirements).
|
||||
|
||||
For a full list of games yuzu supports, please visit our [Compatibility page](https://yuzu-emu.org/game/).
|
||||
For a full list of games yuzu support, please visit our [Compatibility page](https://yuzu-emu.org/game/)
|
||||
|
||||
Check out our [website](https://yuzu-emu.org/) for the latest news on exciting features, monthly progress reports, and more!
|
||||
|
||||
|
@ -35,7 +35,6 @@ if (MSVC)
|
||||
# /volatile:iso - Use strict standards-compliant volatile semantics.
|
||||
# /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates
|
||||
# /Zc:inline - Let codegen omit inline functions in object files
|
||||
# /Zc:preprocessor - Enable standards-conforming preprocessor
|
||||
# /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null
|
||||
# /GT - Supports fiber safety for data allocated using static thread-local storage
|
||||
add_compile_options(
|
||||
@ -49,7 +48,6 @@ if (MSVC)
|
||||
/volatile:iso
|
||||
/Zc:externConstexpr
|
||||
/Zc:inline
|
||||
/Zc:preprocessor
|
||||
/Zc:throwingNew
|
||||
/GT
|
||||
|
||||
@ -134,7 +132,7 @@ else()
|
||||
endif()
|
||||
|
||||
# GCC bugs
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# These diagnostics would be great if they worked, but are just completely broken
|
||||
# and produce bogus errors on external libraries like fmt.
|
||||
add_compile_options(
|
||||
|
@ -49,7 +49,6 @@ class LicenseAdapter(private val activity: AppCompatActivity, var licenses: List
|
||||
val context = YuzuApplication.appContext
|
||||
binding.textSettingName.text = context.getString(license.titleId)
|
||||
binding.textSettingDescription.text = context.getString(license.descriptionId)
|
||||
binding.textSettingValue.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,19 +5,13 @@ package org.yuzu.yuzu_emu.adapters
|
||||
|
||||
import android.text.Html
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import org.yuzu.yuzu_emu.databinding.PageSetupBinding
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.model.SetupCallback
|
||||
import org.yuzu.yuzu_emu.model.SetupPage
|
||||
import org.yuzu.yuzu_emu.model.StepState
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
||||
|
||||
class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) :
|
||||
RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() {
|
||||
@ -32,7 +26,7 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
||||
holder.bind(pages[position])
|
||||
|
||||
inner class SetupPageViewHolder(val binding: PageSetupBinding) :
|
||||
RecyclerView.ViewHolder(binding.root), SetupCallback {
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
lateinit var page: SetupPage
|
||||
|
||||
init {
|
||||
@ -41,12 +35,6 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
||||
|
||||
fun bind(page: SetupPage) {
|
||||
this.page = page
|
||||
|
||||
if (page.stepCompleted.invoke() == StepState.COMPLETE) {
|
||||
binding.buttonAction.visibility = View.INVISIBLE
|
||||
binding.textConfirmation.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
binding.icon.setImageDrawable(
|
||||
ResourcesCompat.getDrawable(
|
||||
activity.resources,
|
||||
@ -74,15 +62,9 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
||||
MaterialButton.ICON_GRAVITY_END
|
||||
}
|
||||
setOnClickListener {
|
||||
page.buttonAction.invoke(this@SetupPageViewHolder)
|
||||
page.buttonAction.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStepCompleted() {
|
||||
ViewUtils.hideView(binding.buttonAction, 200)
|
||||
ViewUtils.showView(binding.textConfirmation, 200)
|
||||
ViewModelProvider(activity)[HomeViewModel::class.java].setShouldPageForward(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,11 +207,8 @@ class SettingsAdapter(
|
||||
val sliderBinding = DialogSliderBinding.inflate(inflater)
|
||||
|
||||
textSliderValue = sliderBinding.textValue
|
||||
textSliderValue!!.text = String.format(
|
||||
context.getString(R.string.value_with_units),
|
||||
sliderProgress.toString(),
|
||||
item.units
|
||||
)
|
||||
textSliderValue!!.text = sliderProgress.toString()
|
||||
sliderBinding.textUnits.text = item.units
|
||||
|
||||
sliderBinding.slider.apply {
|
||||
valueFrom = item.min.toFloat()
|
||||
@ -219,11 +216,7 @@ class SettingsAdapter(
|
||||
value = sliderProgress.toFloat()
|
||||
addOnChangeListener { _: Slider, value: Float, _: Boolean ->
|
||||
sliderProgress = value.toInt()
|
||||
textSliderValue!!.text = String.format(
|
||||
context.getString(R.string.value_with_units),
|
||||
sliderProgress.toString(),
|
||||
item.units
|
||||
)
|
||||
textSliderValue!!.text = sliderProgress.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,6 +225,10 @@ class SettingsAdapter(
|
||||
.setView(sliderBinding.root)
|
||||
.setPositiveButton(android.R.string.ok, this)
|
||||
.setNegativeButton(android.R.string.cancel, defaultCancelListener)
|
||||
.setNeutralButton(R.string.slider_default) { dialog: DialogInterface, which: Int ->
|
||||
sliderBinding.slider.value = item.defaultValue!!.toFloat()
|
||||
onClick(dialog, which)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
|
@ -25,17 +25,12 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
||||
binding.textSettingDescription.setText(item.descriptionId)
|
||||
binding.textSettingDescription.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
val epochTime = setting.value.toLong()
|
||||
val instant = Instant.ofEpochMilli(epochTime * 1000)
|
||||
val zonedTime = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"))
|
||||
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
||||
binding.textSettingDescription.text = dateFormatter.format(zonedTime)
|
||||
}
|
||||
|
||||
binding.textSettingValue.visibility = View.VISIBLE
|
||||
val epochTime = setting.value.toLong()
|
||||
val instant = Instant.ofEpochMilli(epochTime * 1000)
|
||||
val zonedTime = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"))
|
||||
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
||||
binding.textSettingValue.text = dateFormatter.format(zonedTime)
|
||||
|
||||
setStyle(setting.isEditable, binding)
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
|
@ -23,9 +23,6 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
||||
} else {
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
}
|
||||
binding.textSettingValue.visibility = View.GONE
|
||||
|
||||
setStyle(setting.isEditable, binding)
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
|
@ -5,8 +5,6 @@ package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||
|
||||
@ -35,18 +33,4 @@ abstract class SettingViewHolder(itemView: View, protected val adapter: Settings
|
||||
abstract override fun onClick(clicked: View)
|
||||
|
||||
abstract override fun onLongClick(clicked: View): Boolean
|
||||
|
||||
fun setStyle(isEditable: Boolean, binding: ListItemSettingBinding) {
|
||||
val opacity = if (isEditable) 1.0f else 0.5f
|
||||
binding.textSettingName.alpha = opacity
|
||||
binding.textSettingDescription.alpha = opacity
|
||||
binding.textSettingValue.alpha = opacity
|
||||
}
|
||||
|
||||
fun setStyle(isEditable: Boolean, binding: ListItemSettingSwitchBinding) {
|
||||
binding.switchWidget.isEnabled = isEditable
|
||||
val opacity = if (isEditable) 1.0f else 0.5f
|
||||
binding.textSettingName.alpha = opacity
|
||||
binding.textSettingDescription.alpha = opacity
|
||||
}
|
||||
}
|
||||
|
@ -17,33 +17,28 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
|
||||
override fun bind(item: SettingsItem) {
|
||||
setting = item
|
||||
binding.textSettingName.setText(item.nameId)
|
||||
binding.textSettingDescription.visibility = View.VISIBLE
|
||||
if (item.descriptionId != 0) {
|
||||
binding.textSettingDescription.setText(item.descriptionId)
|
||||
binding.textSettingDescription.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.textSettingValue.visibility = View.VISIBLE
|
||||
if (item is SingleChoiceSetting) {
|
||||
val resMgr = binding.textSettingValue.context.resources
|
||||
} else if (item is SingleChoiceSetting) {
|
||||
val resMgr = binding.textSettingDescription.context.resources
|
||||
val values = resMgr.getIntArray(item.valuesId)
|
||||
for (i in values.indices) {
|
||||
if (values[i] == item.selectedValue) {
|
||||
binding.textSettingValue.text = resMgr.getStringArray(item.choicesId)[i]
|
||||
break
|
||||
binding.textSettingDescription.text = resMgr.getStringArray(item.choicesId)[i]
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if (item is StringSingleChoiceSetting) {
|
||||
for (i in item.values!!.indices) {
|
||||
if (item.values[i] == item.selectedValue) {
|
||||
binding.textSettingValue.text = item.choices[i]
|
||||
break
|
||||
binding.textSettingDescription.text = item.choices[i]
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
}
|
||||
|
||||
setStyle(setting.isEditable, binding)
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||
|
||||
import android.view.View
|
||||
import org.yuzu.yuzu_emu.R
|
||||
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.SliderSetting
|
||||
@ -23,14 +22,6 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
|
||||
} else {
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
}
|
||||
binding.textSettingValue.visibility = View.VISIBLE
|
||||
binding.textSettingValue.text = String.format(
|
||||
binding.textSettingValue.context.getString(R.string.value_with_units),
|
||||
setting.selectedValue,
|
||||
setting.units
|
||||
)
|
||||
|
||||
setStyle(setting.isEditable, binding)
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
|
@ -22,7 +22,6 @@ class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAd
|
||||
} else {
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
}
|
||||
binding.textSettingValue.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
|
@ -25,12 +25,12 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
|
||||
binding.textSettingDescription.text = ""
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
}
|
||||
binding.switchWidget.isChecked = setting.isChecked
|
||||
binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean ->
|
||||
adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked)
|
||||
}
|
||||
binding.switchWidget.isChecked = setting.isChecked
|
||||
|
||||
setStyle(setting.isEditable, binding)
|
||||
binding.switchWidget.isEnabled = setting.isEditable
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
|
@ -19,7 +19,6 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.findNavController
|
||||
@ -33,13 +32,10 @@ import org.yuzu.yuzu_emu.adapters.SetupAdapter
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentSetupBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.model.SetupCallback
|
||||
import org.yuzu.yuzu_emu.model.SetupPage
|
||||
import org.yuzu.yuzu_emu.model.StepState
|
||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.GameHelper
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
||||
|
||||
class SetupFragment : Fragment() {
|
||||
private var _binding: FragmentSetupBinding? = null
|
||||
@ -116,22 +112,14 @@ class SetupFragment : Fragment() {
|
||||
0,
|
||||
false,
|
||||
R.string.give_permission,
|
||||
{
|
||||
notificationCallback = it
|
||||
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||
},
|
||||
{ permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) },
|
||||
true,
|
||||
R.string.notification_warning,
|
||||
R.string.notification_warning_description,
|
||||
0,
|
||||
{
|
||||
if (NotificationManagerCompat.from(requireContext())
|
||||
NotificationManagerCompat.from(requireContext())
|
||||
.areNotificationsEnabled()
|
||||
) {
|
||||
StepState.COMPLETE
|
||||
} else {
|
||||
StepState.INCOMPLETE
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -145,22 +133,12 @@ class SetupFragment : Fragment() {
|
||||
R.drawable.ic_add,
|
||||
true,
|
||||
R.string.select_keys,
|
||||
{
|
||||
keyCallback = it
|
||||
getProdKey.launch(arrayOf("*/*"))
|
||||
},
|
||||
{ mainActivity.getProdKey.launch(arrayOf("*/*")) },
|
||||
true,
|
||||
R.string.install_prod_keys_warning,
|
||||
R.string.install_prod_keys_warning_description,
|
||||
R.string.install_prod_keys_warning_help,
|
||||
{
|
||||
val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys")
|
||||
if (file.exists()) {
|
||||
StepState.COMPLETE
|
||||
} else {
|
||||
StepState.INCOMPLETE
|
||||
}
|
||||
}
|
||||
{ File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() }
|
||||
)
|
||||
)
|
||||
add(
|
||||
@ -172,8 +150,9 @@ class SetupFragment : Fragment() {
|
||||
true,
|
||||
R.string.add_games,
|
||||
{
|
||||
gamesDirCallback = it
|
||||
getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data)
|
||||
mainActivity.getGamesDirectory.launch(
|
||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
|
||||
)
|
||||
},
|
||||
true,
|
||||
R.string.add_games_warning,
|
||||
@ -184,11 +163,7 @@ class SetupFragment : Fragment() {
|
||||
PreferenceManager.getDefaultSharedPreferences(
|
||||
YuzuApplication.appContext
|
||||
)
|
||||
if (preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()) {
|
||||
StepState.COMPLETE
|
||||
} else {
|
||||
StepState.INCOMPLETE
|
||||
}
|
||||
preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -206,13 +181,6 @@ class SetupFragment : Fragment() {
|
||||
)
|
||||
}
|
||||
|
||||
homeViewModel.shouldPageForward.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
pageForward()
|
||||
homeViewModel.setShouldPageForward(false)
|
||||
}
|
||||
}
|
||||
|
||||
binding.viewPager2.apply {
|
||||
adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages)
|
||||
offscreenPageLimit = 2
|
||||
@ -226,15 +194,15 @@ class SetupFragment : Fragment() {
|
||||
super.onPageSelected(position)
|
||||
|
||||
if (position == 1 && previousPosition == 0) {
|
||||
ViewUtils.showView(binding.buttonNext)
|
||||
ViewUtils.showView(binding.buttonBack)
|
||||
showView(binding.buttonNext)
|
||||
showView(binding.buttonBack)
|
||||
} else if (position == 0 && previousPosition == 1) {
|
||||
ViewUtils.hideView(binding.buttonBack)
|
||||
ViewUtils.hideView(binding.buttonNext)
|
||||
hideView(binding.buttonBack)
|
||||
hideView(binding.buttonNext)
|
||||
} else if (position == pages.size - 1 && previousPosition == pages.size - 2) {
|
||||
ViewUtils.hideView(binding.buttonNext)
|
||||
hideView(binding.buttonNext)
|
||||
} else if (position == pages.size - 2 && previousPosition == pages.size - 1) {
|
||||
ViewUtils.showView(binding.buttonNext)
|
||||
showView(binding.buttonNext)
|
||||
}
|
||||
|
||||
previousPosition = position
|
||||
@ -247,8 +215,7 @@ class SetupFragment : Fragment() {
|
||||
|
||||
// Checks if the user has completed the task on the current page
|
||||
if (currentPage.hasWarning) {
|
||||
val stepState = currentPage.stepCompleted.invoke()
|
||||
if (stepState != StepState.INCOMPLETE) {
|
||||
if (currentPage.taskCompleted.invoke()) {
|
||||
pageForward()
|
||||
return@setOnClickListener
|
||||
}
|
||||
@ -297,15 +264,9 @@ class SetupFragment : Fragment() {
|
||||
_binding = null
|
||||
}
|
||||
|
||||
private lateinit var notificationCallback: SetupCallback
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
private val permissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||
if (it) {
|
||||
notificationCallback.onStepCompleted()
|
||||
}
|
||||
|
||||
if (!it &&
|
||||
!shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)
|
||||
) {
|
||||
@ -316,27 +277,6 @@ class SetupFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var keyCallback: SetupCallback
|
||||
|
||||
val getProdKey =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result != null) {
|
||||
if (mainActivity.processKey(result)) {
|
||||
keyCallback.onStepCompleted()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var gamesDirCallback: SetupCallback
|
||||
|
||||
val getGamesDirectory =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||
if (result != null) {
|
||||
mainActivity.processGamesDir(result)
|
||||
gamesDirCallback.onStepCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
private fun finishSetup() {
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
||||
.putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false)
|
||||
@ -344,6 +284,33 @@ class SetupFragment : Fragment() {
|
||||
mainActivity.finishSetup(binding.root.findNavController())
|
||||
}
|
||||
|
||||
private fun showView(view: View) {
|
||||
view.apply {
|
||||
alpha = 0f
|
||||
visibility = View.VISIBLE
|
||||
isClickable = true
|
||||
}.animate().apply {
|
||||
duration = 300
|
||||
alpha(1f)
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun hideView(view: View) {
|
||||
if (view.visibility == View.INVISIBLE) {
|
||||
return
|
||||
}
|
||||
|
||||
view.apply {
|
||||
alpha = 1f
|
||||
isClickable = false
|
||||
}.animate().apply {
|
||||
duration = 300
|
||||
alpha(0f)
|
||||
}.withEndAction {
|
||||
view.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
fun pageForward() {
|
||||
binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1
|
||||
}
|
||||
@ -359,29 +326,15 @@ class SetupFragment : Fragment() {
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
|
||||
val leftPadding = barInsets.left + cutoutInsets.left
|
||||
val topPadding = barInsets.top + cutoutInsets.top
|
||||
val rightPadding = barInsets.right + cutoutInsets.right
|
||||
val bottomPadding = barInsets.bottom + cutoutInsets.bottom
|
||||
|
||||
if (resources.getBoolean(R.bool.small_layout)) {
|
||||
binding.viewPager2
|
||||
.updatePadding(left = leftPadding, top = topPadding, right = rightPadding)
|
||||
binding.constraintButtons
|
||||
.updatePadding(left = leftPadding, right = rightPadding, bottom = bottomPadding)
|
||||
} else {
|
||||
binding.viewPager2.updatePadding(top = topPadding, bottom = bottomPadding)
|
||||
binding.constraintButtons
|
||||
.updatePadding(
|
||||
left = leftPadding,
|
||||
right = rightPadding,
|
||||
bottom = bottomPadding
|
||||
)
|
||||
}
|
||||
view.setPadding(
|
||||
barInsets.left + cutoutInsets.left,
|
||||
barInsets.top + cutoutInsets.top,
|
||||
barInsets.right + cutoutInsets.right,
|
||||
barInsets.bottom + cutoutInsets.bottom
|
||||
)
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,6 @@ class HomeViewModel : ViewModel() {
|
||||
private val _statusBarShadeVisible = MutableLiveData(true)
|
||||
val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible
|
||||
|
||||
private val _shouldPageForward = MutableLiveData(false)
|
||||
val shouldPageForward: LiveData<Boolean> get() = _shouldPageForward
|
||||
|
||||
var navigatedToSetup = false
|
||||
|
||||
init {
|
||||
@ -36,8 +33,4 @@ class HomeViewModel : ViewModel() {
|
||||
}
|
||||
_statusBarShadeVisible.value = visible
|
||||
}
|
||||
|
||||
fun setShouldPageForward(pageForward: Boolean) {
|
||||
_shouldPageForward.value = pageForward
|
||||
}
|
||||
}
|
||||
|
@ -10,20 +10,10 @@ data class SetupPage(
|
||||
val buttonIconId: Int,
|
||||
val leftAlignedIcon: Boolean,
|
||||
val buttonTextId: Int,
|
||||
val buttonAction: (callback: SetupCallback) -> Unit,
|
||||
val buttonAction: () -> Unit,
|
||||
val hasWarning: Boolean,
|
||||
val warningTitleId: Int = 0,
|
||||
val warningDescriptionId: Int = 0,
|
||||
val warningHelpLinkId: Int = 0,
|
||||
val stepCompleted: () -> StepState = { StepState.UNDEFINED }
|
||||
val taskCompleted: () -> Boolean = { true }
|
||||
)
|
||||
|
||||
interface SetupCallback {
|
||||
fun onStepCompleted()
|
||||
}
|
||||
|
||||
enum class StepState {
|
||||
COMPLETE,
|
||||
INCOMPLETE,
|
||||
UNDEFINED
|
||||
}
|
||||
|
@ -266,80 +266,73 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
|
||||
val getGamesDirectory =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||
if (result != null) {
|
||||
processGamesDir(result)
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
contentResolver.takePersistableUriPermission(
|
||||
result,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
|
||||
// When a new directory is picked, we currently will reset the existing games
|
||||
// database. This effectively means that only one game directory is supported.
|
||||
PreferenceManager.getDefaultSharedPreferences(applicationContext).edit()
|
||||
.putString(GameHelper.KEY_GAME_PATH, result.toString())
|
||||
.apply()
|
||||
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.games_dir_selected,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
|
||||
gamesViewModel.reloadGames(true)
|
||||
}
|
||||
|
||||
fun processGamesDir(result: Uri) {
|
||||
contentResolver.takePersistableUriPermission(
|
||||
result,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
|
||||
// When a new directory is picked, we currently will reset the existing games
|
||||
// database. This effectively means that only one game directory is supported.
|
||||
PreferenceManager.getDefaultSharedPreferences(applicationContext).edit()
|
||||
.putString(GameHelper.KEY_GAME_PATH, result.toString())
|
||||
.apply()
|
||||
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.games_dir_selected,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
|
||||
gamesViewModel.reloadGames(true)
|
||||
}
|
||||
|
||||
val getProdKey =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result != null) {
|
||||
processKey(result)
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
}
|
||||
|
||||
fun processKey(result: Uri): Boolean {
|
||||
if (FileUtil.getExtension(result) != "keys") {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.reading_keys_failure,
|
||||
R.string.install_prod_keys_failure_extension_description
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
return false
|
||||
}
|
||||
|
||||
contentResolver.takePersistableUriPermission(
|
||||
result,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
|
||||
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
|
||||
if (FileUtil.copyUriToInternalStorage(
|
||||
applicationContext,
|
||||
result,
|
||||
dstPath,
|
||||
"prod.keys"
|
||||
)
|
||||
) {
|
||||
if (NativeLibrary.reloadKeys()) {
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.install_keys_success,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
gamesViewModel.reloadGames(true)
|
||||
return true
|
||||
} else {
|
||||
if (FileUtil.getExtension(result) != "keys") {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.invalid_keys_error,
|
||||
R.string.install_keys_failure_description,
|
||||
R.string.dumping_keys_quickstart_link
|
||||
R.string.reading_keys_failure,
|
||||
R.string.install_prod_keys_failure_extension_description
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
return false
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
contentResolver.takePersistableUriPermission(
|
||||
result,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
|
||||
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
|
||||
if (FileUtil.copyUriToInternalStorage(
|
||||
applicationContext,
|
||||
result,
|
||||
dstPath,
|
||||
"prod.keys"
|
||||
)
|
||||
) {
|
||||
if (NativeLibrary.reloadKeys()) {
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.install_keys_success,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
gamesViewModel.reloadGames(true)
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.invalid_keys_error,
|
||||
R.string.install_keys_failure_description,
|
||||
R.string.dumping_keys_quickstart_link
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
val getFirmware =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
|
@ -1,35 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.view.View
|
||||
|
||||
object ViewUtils {
|
||||
fun showView(view: View, length: Long = 300) {
|
||||
view.apply {
|
||||
alpha = 0f
|
||||
visibility = View.VISIBLE
|
||||
isClickable = true
|
||||
}.animate().apply {
|
||||
duration = length
|
||||
alpha(1f)
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun hideView(view: View, length: Long = 300) {
|
||||
if (view.visibility == View.INVISIBLE) {
|
||||
return
|
||||
}
|
||||
|
||||
view.apply {
|
||||
alpha = 1f
|
||||
isClickable = false
|
||||
}.animate().apply {
|
||||
duration = length
|
||||
alpha(0f)
|
||||
}.withEndAction {
|
||||
view.visibility = View.INVISIBLE
|
||||
}.start()
|
||||
}
|
||||
}
|
@ -150,17 +150,15 @@ void Config::ReadValues() {
|
||||
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.SetValue(std::nullopt);
|
||||
}
|
||||
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 = std::nullopt;
|
||||
}
|
||||
Settings::values.custom_rtc_enabled = custom_rtc_enabled;
|
||||
|
||||
ReadSetting("System", Settings::values.language_index);
|
||||
ReadSetting("System", Settings::values.region_index);
|
||||
@ -169,7 +167,7 @@ void Config::ReadValues() {
|
||||
|
||||
// Core
|
||||
ReadSetting("Core", Settings::values.use_multi_core);
|
||||
ReadSetting("Core", Settings::values.memory_layout_mode);
|
||||
ReadSetting("Core", Settings::values.use_unsafe_extended_memory_layout);
|
||||
|
||||
// Cpu
|
||||
ReadSetting("Cpu", Settings::values.cpu_accuracy);
|
||||
@ -224,17 +222,14 @@ void Config::ReadValues() {
|
||||
ReadSetting("Renderer", Settings::values.bg_blue);
|
||||
|
||||
// Use GPU accuracy normal by default on Android
|
||||
Settings::values.gpu_accuracy = static_cast<Settings::GpuAccuracy>(config->GetInteger(
|
||||
"Renderer", "gpu_accuracy", static_cast<u32>(Settings::GpuAccuracy::Normal)));
|
||||
Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger(
|
||||
"Renderer", "gpu_accuracy", static_cast<u32>(Settings::GPUAccuracy::Normal)));
|
||||
|
||||
// Use GPU default anisotropic filtering on Android
|
||||
Settings::values.max_anisotropy =
|
||||
static_cast<Settings::AnisotropyMode>(config->GetInteger("Renderer", "max_anisotropy", 1));
|
||||
Settings::values.max_anisotropy = 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);
|
||||
Settings::values.accelerate_astc = config->GetBoolean("Renderer", "accelerate_astc", false);
|
||||
|
||||
// Enable asynchronous presentation by default on Android
|
||||
Settings::values.async_presentation =
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/setup_root"
|
||||
@ -8,39 +8,33 @@
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPager2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:clipToPadding="false" />
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/constraint_buttons"
|
||||
android:layout_width="match_parent"
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:id="@+id/button_next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_margin="8dp">
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/next"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_next"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/next"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_back"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/back"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_back"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/back"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -21,76 +21,45 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_title"
|
||||
style="@style/TextAppearance.Material3.DisplaySmall"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:gravity="center"
|
||||
android:id="@+id/text_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="center"
|
||||
android:textColor="?attr/colorOnSurface"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/text_description"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_weight="2"
|
||||
tools:text="@string/welcome" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:id="@+id/text_description"
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:paddingHorizontal="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
||||
app:layout_constraintVertical_weight="2"
|
||||
app:lineHeight="30sp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingHorizontal="32dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="26sp"
|
||||
app:lineHeight="40sp"
|
||||
tools:text="@string/welcome_description" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_confirmation"
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:gravity="center"
|
||||
android:textSize="30sp"
|
||||
android:visibility="invisible"
|
||||
android:text="@string/step_complete"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
||||
app:layout_constraintVertical_weight="1"
|
||||
app:lineHeight="30sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_action"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:textSize="20sp"
|
||||
app:iconGravity="end"
|
||||
app:iconSize="24sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
||||
app:iconGravity="end"
|
||||
tools:text="Get started" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -5,16 +5,23 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/text_value"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="@dimen/spacing_medlarge"
|
||||
android:layout_marginTop="@dimen/spacing_medlarge"
|
||||
tools:text="75%" />
|
||||
tools:text="75" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_units"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@+id/text_value"
|
||||
android:layout_toEndOf="@+id/text_value"
|
||||
tools:text="%" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/setup_root"
|
||||
@ -8,39 +8,35 @@
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPager2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_next"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:id="@+id/button_next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/constraint_buttons"
|
||||
android:layout_alignParentTop="true"
|
||||
android:clipToPadding="false" />
|
||||
android:layout_margin="12dp"
|
||||
android:text="@string/next"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/constraint_buttons"
|
||||
android:layout_width="match_parent"
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:id="@+id/button_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_alignParentBottom="true">
|
||||
android:layout_margin="12dp"
|
||||
android:text="@string/back"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_next"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/next"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_back"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/back"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -1,10 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
@ -12,40 +11,31 @@
|
||||
android:minHeight="72dp"
|
||||
android:padding="@dimen/spacing_large">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.Material3.HeadlineMedium"
|
||||
android:id="@+id/text_setting_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:textSize="16sp"
|
||||
android:textAlignment="viewStart"
|
||||
app:lineHeight="28dp"
|
||||
tools:text="Setting Name" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_setting_name"
|
||||
style="@style/TextAppearance.Material3.HeadlineMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="viewStart"
|
||||
android:textSize="16sp"
|
||||
app:lineHeight="22dp"
|
||||
tools:text="Setting Name" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_setting_description"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_small"
|
||||
android:textAlignment="viewStart"
|
||||
tools:text="@string/app_disclaimer" />
|
||||
|
||||
<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"
|
||||
tools:text="1x" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:id="@+id/text_setting_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignStart="@+id/text_setting_name"
|
||||
android:layout_below="@+id/text_setting_name"
|
||||
android:layout_marginTop="@dimen/spacing_small"
|
||||
android:visibility="visible"
|
||||
android:textAlignment="viewStart"
|
||||
tools:text="@string/app_disclaimer" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
@ -21,12 +21,11 @@
|
||||
app:layout_constraintVertical_chainStyle="spread"
|
||||
app:layout_constraintWidth_max="220dp"
|
||||
app:layout_constraintWidth_min="110dp"
|
||||
app:layout_constraintVertical_weight="3"
|
||||
tools:src="@drawable/ic_notification" />
|
||||
app:layout_constraintVertical_weight="3" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_title"
|
||||
style="@style/TextAppearance.Material3.DisplaySmall"
|
||||
style="@style/TextAppearance.Material3.DisplayMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:textAlignment="center"
|
||||
@ -45,42 +44,23 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
android:textSize="26sp"
|
||||
android:paddingHorizontal="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
||||
app:layout_constraintVertical_weight="2"
|
||||
app:lineHeight="30sp"
|
||||
app:lineHeight="40sp"
|
||||
tools:text="@string/welcome_description" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_confirmation"
|
||||
style="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="24dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="30sp"
|
||||
android:visibility="invisible"
|
||||
android:text="@string/step_complete"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
||||
app:layout_constraintVertical_weight="1"
|
||||
app:lineHeight="30sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_action"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="56dp"
|
||||
android:textSize="20sp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconGravity="end"
|
||||
app:iconSize="24sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
@ -29,7 +29,6 @@
|
||||
<string name="back">Back</string>
|
||||
<string name="add_games">Add Games</string>
|
||||
<string name="add_games_description">Select your games folder</string>
|
||||
<string name="step_complete">Complete!</string>
|
||||
|
||||
<!-- Home strings -->
|
||||
<string name="home_games">Games</string>
|
||||
@ -150,7 +149,6 @@
|
||||
<string name="frame_limit_slider">Limit speed percent</string>
|
||||
<string name="frame_limit_slider_description">Specifies the percentage to limit emulation speed. 100% is the normal speed. Values higher or lower will increase or decrease the speed limit.</string>
|
||||
<string name="cpu_accuracy">CPU accuracy</string>
|
||||
<string name="value_with_units">%1$s%2$s</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="use_docked_mode">Docked Mode</string>
|
||||
|
@ -15,7 +15,6 @@
|
||||
#endif
|
||||
#include "audio_core/sink/null_sink.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings_enums.h"
|
||||
|
||||
namespace AudioCore::Sink {
|
||||
namespace {
|
||||
@ -25,7 +24,7 @@ struct SinkDetails {
|
||||
using LatencyFn = u32 (*)();
|
||||
|
||||
/// Name for this sink.
|
||||
Settings::AudioEngine id;
|
||||
std::string_view id;
|
||||
/// A method to call to construct an instance of this type of sink.
|
||||
FactoryFn factory;
|
||||
/// A method to call to list available devices.
|
||||
@ -38,7 +37,7 @@ struct SinkDetails {
|
||||
constexpr SinkDetails sink_details[] = {
|
||||
#ifdef HAVE_CUBEB
|
||||
SinkDetails{
|
||||
Settings::AudioEngine::Cubeb,
|
||||
"cubeb",
|
||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||
return std::make_unique<CubebSink>(device_id);
|
||||
},
|
||||
@ -48,7 +47,7 @@ constexpr SinkDetails sink_details[] = {
|
||||
#endif
|
||||
#ifdef HAVE_SDL2
|
||||
SinkDetails{
|
||||
Settings::AudioEngine::Sdl2,
|
||||
"sdl2",
|
||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||
return std::make_unique<SDLSink>(device_id);
|
||||
},
|
||||
@ -56,47 +55,46 @@ constexpr SinkDetails sink_details[] = {
|
||||
&GetSDLLatency,
|
||||
},
|
||||
#endif
|
||||
SinkDetails{Settings::AudioEngine::Null,
|
||||
SinkDetails{"null",
|
||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||
return std::make_unique<NullSink>(device_id);
|
||||
},
|
||||
[](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }},
|
||||
};
|
||||
|
||||
const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
|
||||
const auto find_backend{[](Settings::AudioEngine id) {
|
||||
const SinkDetails& GetOutputSinkDetails(std::string_view sink_id) {
|
||||
const auto find_backend{[](std::string_view id) {
|
||||
return std::find_if(std::begin(sink_details), std::end(sink_details),
|
||||
[&id](const auto& sink_detail) { return sink_detail.id == id; });
|
||||
}};
|
||||
|
||||
auto iter = find_backend(sink_id);
|
||||
|
||||
if (sink_id == Settings::AudioEngine::Auto) {
|
||||
if (sink_id == "auto") {
|
||||
// Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which
|
||||
// causes audio issues, in that case go with SDL.
|
||||
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
|
||||
iter = find_backend(Settings::AudioEngine::Cubeb);
|
||||
iter = find_backend("cubeb");
|
||||
if (iter->latency() > TargetSampleCount * 3) {
|
||||
iter = find_backend(Settings::AudioEngine::Sdl2);
|
||||
iter = find_backend("sdl2");
|
||||
}
|
||||
#else
|
||||
iter = std::begin(sink_details);
|
||||
#endif
|
||||
LOG_INFO(Service_Audio, "Auto-selecting the {} backend",
|
||||
Settings::CanonicalizeEnum(iter->id));
|
||||
LOG_INFO(Service_Audio, "Auto-selecting the {} backend", iter->id);
|
||||
}
|
||||
|
||||
if (iter == std::end(sink_details)) {
|
||||
LOG_ERROR(Audio, "Invalid sink_id {}", Settings::CanonicalizeEnum(sink_id));
|
||||
iter = find_backend(Settings::AudioEngine::Null);
|
||||
LOG_ERROR(Audio, "Invalid sink_id {}", sink_id);
|
||||
iter = find_backend("null");
|
||||
}
|
||||
|
||||
return *iter;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
std::vector<Settings::AudioEngine> GetSinkIDs() {
|
||||
std::vector<Settings::AudioEngine> sink_ids(std::size(sink_details));
|
||||
std::vector<std::string_view> GetSinkIDs() {
|
||||
std::vector<std::string_view> sink_ids(std::size(sink_details));
|
||||
|
||||
std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids),
|
||||
[](const auto& sink) { return sink.id; });
|
||||
@ -104,11 +102,11 @@ std::vector<Settings::AudioEngine> GetSinkIDs() {
|
||||
return sink_ids;
|
||||
}
|
||||
|
||||
std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, bool capture) {
|
||||
std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool capture) {
|
||||
return GetOutputSinkDetails(sink_id).list_devices(capture);
|
||||
}
|
||||
|
||||
std::unique_ptr<Sink> CreateSinkFromID(Settings::AudioEngine sink_id, std::string_view device_id) {
|
||||
std::unique_ptr<Sink> CreateSinkFromID(std::string_view sink_id, std::string_view device_id) {
|
||||
return GetOutputSinkDetails(sink_id).factory(device_id);
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "common/settings_enums.h"
|
||||
|
||||
namespace AudioCore {
|
||||
class AudioManager;
|
||||
@ -21,7 +19,7 @@ class Sink;
|
||||
*
|
||||
* @return Vector of available sink names.
|
||||
*/
|
||||
std::vector<Settings::AudioEngine> GetSinkIDs();
|
||||
std::vector<std::string_view> GetSinkIDs();
|
||||
|
||||
/**
|
||||
* Gets the list of devices for a particular sink identified by the given ID.
|
||||
@ -30,7 +28,7 @@ std::vector<Settings::AudioEngine> GetSinkIDs();
|
||||
* @param capture - Get capture (input) devices, or output devices?
|
||||
* @return Vector of device names.
|
||||
*/
|
||||
std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, bool capture);
|
||||
std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool capture);
|
||||
|
||||
/**
|
||||
* Creates an audio sink identified by the given device ID.
|
||||
@ -39,7 +37,7 @@ std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, boo
|
||||
* @param device_id - Name of the device to create.
|
||||
* @return Pointer to the created sink.
|
||||
*/
|
||||
std::unique_ptr<Sink> CreateSinkFromID(Settings::AudioEngine sink_id, std::string_view device_id);
|
||||
std::unique_ptr<Sink> CreateSinkFromID(std::string_view sink_id, std::string_view device_id);
|
||||
|
||||
} // namespace Sink
|
||||
} // namespace AudioCore
|
||||
|
@ -110,12 +110,8 @@ add_library(common STATIC
|
||||
scratch_buffer.h
|
||||
settings.cpp
|
||||
settings.h
|
||||
settings_common.cpp
|
||||
settings_common.h
|
||||
settings_enums.h
|
||||
settings_input.cpp
|
||||
settings_input.h
|
||||
settings_setting.h
|
||||
socket_types.h
|
||||
spin_lock.cpp
|
||||
spin_lock.h
|
||||
@ -197,16 +193,9 @@ if (MSVC)
|
||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||
)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
else()
|
||||
target_compile_options(common PRIVATE
|
||||
-fsized-deallocation
|
||||
-Werror=unreachable-code-aggressive
|
||||
)
|
||||
target_compile_definitions(common PRIVATE
|
||||
# Clang 14 and earlier have errors when explicitly instantiating Settings::Setting
|
||||
$<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,15>:CANNOT_EXPLICITLY_INSTANTIATE>
|
||||
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -108,7 +108,7 @@ public:
|
||||
|
||||
using namespace Common::Literals;
|
||||
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
|
||||
const auto write_limit = Settings::values.extended_logging.GetValue() ? 1_GiB : 100_MiB;
|
||||
const auto write_limit = Settings::values.extended_logging ? 1_GiB : 100_MiB;
|
||||
const bool write_limit_exceeded = bytes_written > write_limit;
|
||||
if (entry.log_level >= Level::Error || write_limit_exceeded) {
|
||||
if (write_limit_exceeded) {
|
||||
|
@ -7,16 +7,9 @@
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
#include <compare>
|
||||
#include <cstddef>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/fs/fs_util.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
@ -24,50 +17,11 @@
|
||||
|
||||
namespace Settings {
|
||||
|
||||
// Clang 14 and earlier have errors when explicitly instantiating these classes
|
||||
#ifndef CANNOT_EXPLICITLY_INSTANTIATE
|
||||
#define SETTING(TYPE, RANGED) template class Setting<TYPE, RANGED>
|
||||
#define SWITCHABLE(TYPE, RANGED) template class SwitchableSetting<TYPE, RANGED>
|
||||
|
||||
SETTING(AudioEngine, false);
|
||||
SETTING(bool, false);
|
||||
SETTING(int, false);
|
||||
SETTING(std::string, false);
|
||||
SETTING(u16, false);
|
||||
SWITCHABLE(AnisotropyMode, true);
|
||||
SWITCHABLE(AntiAliasing, false);
|
||||
SWITCHABLE(AspectRatio, true);
|
||||
SWITCHABLE(AstcDecodeMode, true);
|
||||
SWITCHABLE(AstcRecompression, true);
|
||||
SWITCHABLE(AudioMode, true);
|
||||
SWITCHABLE(CpuAccuracy, true);
|
||||
SWITCHABLE(FullscreenMode, true);
|
||||
SWITCHABLE(GpuAccuracy, true);
|
||||
SWITCHABLE(Language, true);
|
||||
SWITCHABLE(NvdecEmulation, false);
|
||||
SWITCHABLE(Region, true);
|
||||
SWITCHABLE(RendererBackend, true);
|
||||
SWITCHABLE(ScalingFilter, false);
|
||||
SWITCHABLE(ShaderBackend, true);
|
||||
SWITCHABLE(TimeZone, true);
|
||||
SETTING(VSyncMode, true);
|
||||
SWITCHABLE(bool, false);
|
||||
SWITCHABLE(int, false);
|
||||
SWITCHABLE(int, true);
|
||||
SWITCHABLE(s64, false);
|
||||
SWITCHABLE(u16, true);
|
||||
SWITCHABLE(u32, false);
|
||||
SWITCHABLE(u8, false);
|
||||
SWITCHABLE(u8, true);
|
||||
|
||||
#undef SETTING
|
||||
#undef SWITCHABLE
|
||||
#endif
|
||||
|
||||
Values values;
|
||||
static bool configuring_global = true;
|
||||
|
||||
std::string GetTimeZoneString(TimeZone time_zone) {
|
||||
const auto time_zone_index = static_cast<std::size_t>(time_zone);
|
||||
std::string GetTimeZoneString() {
|
||||
const auto time_zone_index = static_cast<std::size_t>(values.time_zone_index.GetValue());
|
||||
ASSERT(time_zone_index < Common::TimeZone::GetTimeZoneStrings().size());
|
||||
|
||||
std::string location_name;
|
||||
@ -107,35 +61,73 @@ void LogSettings() {
|
||||
};
|
||||
|
||||
LOG_INFO(Config, "yuzu Configuration:");
|
||||
for (auto& [category, settings] : values.linkage.by_category) {
|
||||
for (const auto& setting : settings) {
|
||||
if (setting->Id() == values.yuzu_token.Id()) {
|
||||
// Hide the token secret, for security reasons.
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto name = fmt::format(
|
||||
"{:c}{:c} {}.{}", setting->ToString() == setting->DefaultToString() ? '-' : 'M',
|
||||
setting->UsingGlobal() ? '-' : 'C', TranslateCategory(category),
|
||||
setting->GetLabel());
|
||||
|
||||
log_setting(name, setting->Canonicalize());
|
||||
}
|
||||
}
|
||||
log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue());
|
||||
log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
|
||||
log_setting("System_DeviceName", values.device_name.GetValue());
|
||||
log_setting("System_CurrentUser", values.current_user.GetValue());
|
||||
log_setting("System_LanguageIndex", values.language_index.GetValue());
|
||||
log_setting("System_RegionIndex", values.region_index.GetValue());
|
||||
log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue());
|
||||
log_setting("System_UnsafeMemoryLayout", values.use_unsafe_extended_memory_layout.GetValue());
|
||||
log_setting("Core_UseMultiCore", values.use_multi_core.GetValue());
|
||||
log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue());
|
||||
log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue());
|
||||
log_setting("Renderer_ScalingFilter", values.scaling_filter.GetValue());
|
||||
log_setting("Renderer_FSRSlider", values.fsr_sharpening_slider.GetValue());
|
||||
log_setting("Renderer_AntiAliasing", values.anti_aliasing.GetValue());
|
||||
log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue());
|
||||
log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue());
|
||||
log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue());
|
||||
log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue());
|
||||
log_setting("Renderer_UseAsynchronousGpuEmulation",
|
||||
values.use_asynchronous_gpu_emulation.GetValue());
|
||||
log_setting("Renderer_NvdecEmulation", values.nvdec_emulation.GetValue());
|
||||
log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue());
|
||||
log_setting("Renderer_AsyncASTC", values.async_astc.GetValue());
|
||||
log_setting("Renderer_AstcRecompression", values.astc_recompression.GetValue());
|
||||
log_setting("Renderer_UseVsync", values.vsync_mode.GetValue());
|
||||
log_setting("Renderer_UseReactiveFlushing", values.use_reactive_flushing.GetValue());
|
||||
log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue());
|
||||
log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
|
||||
log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue());
|
||||
log_setting("Audio_OutputEngine", values.sink_id.GetValue());
|
||||
log_setting("Audio_OutputDevice", values.audio_output_device_id.GetValue());
|
||||
log_setting("Audio_InputDevice", values.audio_input_device_id.GetValue());
|
||||
log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd.GetValue());
|
||||
log_path("DataStorage_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir));
|
||||
log_path("DataStorage_ConfigDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir));
|
||||
log_path("DataStorage_LoadDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::LoadDir));
|
||||
log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir));
|
||||
log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir));
|
||||
log_setting("Debugging_ProgramArgs", values.program_args.GetValue());
|
||||
log_setting("Debugging_GDBStub", values.use_gdbstub.GetValue());
|
||||
log_setting("Input_EnableMotion", values.motion_enabled.GetValue());
|
||||
log_setting("Input_EnableVibration", values.vibration_enabled.GetValue());
|
||||
log_setting("Input_EnableTouch", values.touchscreen.enabled);
|
||||
log_setting("Input_EnableMouse", values.mouse_enabled.GetValue());
|
||||
log_setting("Input_EnableKeyboard", values.keyboard_enabled.GetValue());
|
||||
log_setting("Input_EnableRingController", values.enable_ring_controller.GetValue());
|
||||
log_setting("Input_EnableIrSensor", values.enable_ir_sensor.GetValue());
|
||||
log_setting("Input_EnableCustomJoycon", values.enable_joycon_driver.GetValue());
|
||||
log_setting("Input_EnableCustomProController", values.enable_procon_driver.GetValue());
|
||||
log_setting("Input_EnableRawInput", values.enable_raw_input.GetValue());
|
||||
}
|
||||
|
||||
bool IsConfiguringGlobal() {
|
||||
return configuring_global;
|
||||
}
|
||||
|
||||
void SetConfiguringGlobal(bool is_global) {
|
||||
configuring_global = is_global;
|
||||
}
|
||||
|
||||
bool IsGPULevelExtreme() {
|
||||
return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme;
|
||||
return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme;
|
||||
}
|
||||
|
||||
bool IsGPULevelHigh() {
|
||||
return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme ||
|
||||
values.gpu_accuracy.GetValue() == GpuAccuracy::High;
|
||||
return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme ||
|
||||
values.gpu_accuracy.GetValue() == GPUAccuracy::High;
|
||||
}
|
||||
|
||||
bool IsFastmemEnabled() {
|
||||
@ -152,61 +144,6 @@ float Volume() {
|
||||
return values.volume.GetValue() / static_cast<f32>(values.volume.GetDefault());
|
||||
}
|
||||
|
||||
const char* TranslateCategory(Category category) {
|
||||
switch (category) {
|
||||
case Category::Audio:
|
||||
return "Audio";
|
||||
case Category::Core:
|
||||
return "Core";
|
||||
case Category::Cpu:
|
||||
case Category::CpuDebug:
|
||||
case Category::CpuUnsafe:
|
||||
return "Cpu";
|
||||
case Category::Renderer:
|
||||
case Category::RendererAdvanced:
|
||||
case Category::RendererDebug:
|
||||
return "Renderer";
|
||||
case Category::System:
|
||||
case Category::SystemAudio:
|
||||
return "System";
|
||||
case Category::DataStorage:
|
||||
return "Data Storage";
|
||||
case Category::Debugging:
|
||||
case Category::DebuggingGraphics:
|
||||
return "Debugging";
|
||||
case Category::Miscellaneous:
|
||||
return "Miscellaneous";
|
||||
case Category::Network:
|
||||
return "Network";
|
||||
case Category::WebService:
|
||||
return "WebService";
|
||||
case Category::AddOns:
|
||||
return "DisabledAddOns";
|
||||
case Category::Controls:
|
||||
return "Controls";
|
||||
case Category::Ui:
|
||||
case Category::UiGeneral:
|
||||
return "UI";
|
||||
case Category::UiLayout:
|
||||
return "UiLayout";
|
||||
case Category::UiGameList:
|
||||
return "UiGameList";
|
||||
case Category::Screenshots:
|
||||
return "Screenshots";
|
||||
case Category::Shortcuts:
|
||||
return "Shortcuts";
|
||||
case Category::Multiplayer:
|
||||
return "Multiplayer";
|
||||
case Category::Services:
|
||||
return "Services";
|
||||
case Category::Paths:
|
||||
return "Paths";
|
||||
case Category::MaxEnum:
|
||||
break;
|
||||
}
|
||||
return "Miscellaneous";
|
||||
}
|
||||
|
||||
void UpdateRescalingInfo() {
|
||||
const auto setup = values.resolution_setup.GetValue();
|
||||
auto& info = values.resolution_info;
|
||||
@ -275,19 +212,66 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& reset : values.linkage.restore_functions) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
// Audio
|
||||
values.volume.SetGlobal(true);
|
||||
|
||||
static bool configuring_global = true;
|
||||
// Core
|
||||
values.use_multi_core.SetGlobal(true);
|
||||
values.use_unsafe_extended_memory_layout.SetGlobal(true);
|
||||
|
||||
bool IsConfiguringGlobal() {
|
||||
return configuring_global;
|
||||
}
|
||||
// CPU
|
||||
values.cpu_accuracy.SetGlobal(true);
|
||||
values.cpuopt_unsafe_unfuse_fma.SetGlobal(true);
|
||||
values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true);
|
||||
values.cpuopt_unsafe_ignore_standard_fpcr.SetGlobal(true);
|
||||
values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true);
|
||||
values.cpuopt_unsafe_fastmem_check.SetGlobal(true);
|
||||
values.cpuopt_unsafe_ignore_global_monitor.SetGlobal(true);
|
||||
|
||||
void SetConfiguringGlobal(bool is_global) {
|
||||
configuring_global = is_global;
|
||||
// Renderer
|
||||
values.fsr_sharpening_slider.SetGlobal(true);
|
||||
values.renderer_backend.SetGlobal(true);
|
||||
values.async_presentation.SetGlobal(true);
|
||||
values.renderer_force_max_clock.SetGlobal(true);
|
||||
values.vulkan_device.SetGlobal(true);
|
||||
values.fullscreen_mode.SetGlobal(true);
|
||||
values.aspect_ratio.SetGlobal(true);
|
||||
values.resolution_setup.SetGlobal(true);
|
||||
values.scaling_filter.SetGlobal(true);
|
||||
values.anti_aliasing.SetGlobal(true);
|
||||
values.max_anisotropy.SetGlobal(true);
|
||||
values.use_speed_limit.SetGlobal(true);
|
||||
values.speed_limit.SetGlobal(true);
|
||||
values.use_disk_shader_cache.SetGlobal(true);
|
||||
values.gpu_accuracy.SetGlobal(true);
|
||||
values.use_asynchronous_gpu_emulation.SetGlobal(true);
|
||||
values.nvdec_emulation.SetGlobal(true);
|
||||
values.accelerate_astc.SetGlobal(true);
|
||||
values.async_astc.SetGlobal(true);
|
||||
values.astc_recompression.SetGlobal(true);
|
||||
values.use_reactive_flushing.SetGlobal(true);
|
||||
values.shader_backend.SetGlobal(true);
|
||||
values.use_asynchronous_shaders.SetGlobal(true);
|
||||
values.use_fast_gpu_time.SetGlobal(true);
|
||||
values.use_vulkan_driver_pipeline_cache.SetGlobal(true);
|
||||
values.bg_red.SetGlobal(true);
|
||||
values.bg_green.SetGlobal(true);
|
||||
values.bg_blue.SetGlobal(true);
|
||||
values.enable_compute_pipelines.SetGlobal(true);
|
||||
values.use_video_framerate.SetGlobal(true);
|
||||
|
||||
// System
|
||||
values.language_index.SetGlobal(true);
|
||||
values.region_index.SetGlobal(true);
|
||||
values.time_zone_index.SetGlobal(true);
|
||||
values.rng_seed.SetGlobal(true);
|
||||
values.sound_index.SetGlobal(true);
|
||||
|
||||
// Controls
|
||||
values.players.SetGlobal(true);
|
||||
values.use_docked_mode.SetGlobal(true);
|
||||
values.vibration_enabled.SetGlobal(true);
|
||||
values.motion_enabled.SetGlobal(true);
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
|
@ -6,21 +6,95 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings_common.h"
|
||||
#include "common/settings_enums.h"
|
||||
#include "common/settings_input.h"
|
||||
#include "common/settings_setting.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
const char* TranslateCategory(Settings::Category category);
|
||||
enum class VSyncMode : u32 {
|
||||
Immediate = 0,
|
||||
Mailbox = 1,
|
||||
FIFO = 2,
|
||||
FIFORelaxed = 3,
|
||||
};
|
||||
|
||||
enum class RendererBackend : u32 {
|
||||
OpenGL = 0,
|
||||
Vulkan = 1,
|
||||
Null = 2,
|
||||
};
|
||||
|
||||
enum class ShaderBackend : u32 {
|
||||
GLSL = 0,
|
||||
GLASM = 1,
|
||||
SPIRV = 2,
|
||||
};
|
||||
|
||||
enum class GPUAccuracy : u32 {
|
||||
Normal = 0,
|
||||
High = 1,
|
||||
Extreme = 2,
|
||||
};
|
||||
|
||||
enum class CPUAccuracy : u32 {
|
||||
Auto = 0,
|
||||
Accurate = 1,
|
||||
Unsafe = 2,
|
||||
Paranoid = 3,
|
||||
};
|
||||
|
||||
enum class FullscreenMode : u32 {
|
||||
Borderless = 0,
|
||||
Exclusive = 1,
|
||||
};
|
||||
|
||||
enum class NvdecEmulation : u32 {
|
||||
Off = 0,
|
||||
CPU = 1,
|
||||
GPU = 2,
|
||||
};
|
||||
|
||||
enum class ResolutionSetup : u32 {
|
||||
Res1_2X = 0,
|
||||
Res3_4X = 1,
|
||||
Res1X = 2,
|
||||
Res3_2X = 3,
|
||||
Res2X = 4,
|
||||
Res3X = 5,
|
||||
Res4X = 6,
|
||||
Res5X = 7,
|
||||
Res6X = 8,
|
||||
Res7X = 9,
|
||||
Res8X = 10,
|
||||
};
|
||||
|
||||
enum class ScalingFilter : u32 {
|
||||
NearestNeighbor = 0,
|
||||
Bilinear = 1,
|
||||
Bicubic = 2,
|
||||
Gaussian = 3,
|
||||
ScaleForce = 4,
|
||||
Fsr = 5,
|
||||
LastFilter = Fsr,
|
||||
};
|
||||
|
||||
enum class AntiAliasing : u32 {
|
||||
None = 0,
|
||||
Fxaa = 1,
|
||||
Smaa = 2,
|
||||
LastAA = Smaa,
|
||||
};
|
||||
|
||||
enum class AstcRecompression : u32 {
|
||||
Uncompressed = 0,
|
||||
Bc1 = 1,
|
||||
Bc3 = 2,
|
||||
};
|
||||
|
||||
struct ResolutionScalingInfo {
|
||||
u32 up_scale{1};
|
||||
@ -45,47 +119,239 @@ struct ResolutionScalingInfo {
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef CANNOT_EXPLICITLY_INSTANTIATE
|
||||
// Instantiate the classes elsewhere (settings.cpp) to reduce compiler/linker work
|
||||
#define SETTING(TYPE, RANGED) extern template class Setting<TYPE, RANGED>
|
||||
#define SWITCHABLE(TYPE, RANGED) extern template class SwitchableSetting<TYPE, RANGED>
|
||||
/** The Setting class is a simple resource manager. It defines a label and default value alongside
|
||||
* the actual value of the setting for simpler and less-error prone use with frontend
|
||||
* configurations. Specifying a default value and label is required. A minimum and maximum range can
|
||||
* be specified for sanitization.
|
||||
*/
|
||||
template <typename Type, bool ranged = false>
|
||||
class Setting {
|
||||
protected:
|
||||
Setting() = default;
|
||||
|
||||
SETTING(AudioEngine, false);
|
||||
SETTING(bool, false);
|
||||
SETTING(int, false);
|
||||
SETTING(s32, false);
|
||||
SETTING(std::string, false);
|
||||
SETTING(std::string, false);
|
||||
SETTING(u16, false);
|
||||
SWITCHABLE(AnisotropyMode, true);
|
||||
SWITCHABLE(AntiAliasing, false);
|
||||
SWITCHABLE(AspectRatio, true);
|
||||
SWITCHABLE(AstcDecodeMode, true);
|
||||
SWITCHABLE(AstcRecompression, true);
|
||||
SWITCHABLE(AudioMode, true);
|
||||
SWITCHABLE(CpuAccuracy, true);
|
||||
SWITCHABLE(FullscreenMode, true);
|
||||
SWITCHABLE(GpuAccuracy, true);
|
||||
SWITCHABLE(Language, true);
|
||||
SWITCHABLE(NvdecEmulation, false);
|
||||
SWITCHABLE(Region, true);
|
||||
SWITCHABLE(RendererBackend, true);
|
||||
SWITCHABLE(ScalingFilter, false);
|
||||
SWITCHABLE(ShaderBackend, true);
|
||||
SWITCHABLE(TimeZone, true);
|
||||
SETTING(VSyncMode, true);
|
||||
SWITCHABLE(bool, false);
|
||||
SWITCHABLE(int, false);
|
||||
SWITCHABLE(int, true);
|
||||
SWITCHABLE(s64, false);
|
||||
SWITCHABLE(u16, true);
|
||||
SWITCHABLE(u32, false);
|
||||
SWITCHABLE(u8, false);
|
||||
SWITCHABLE(u8, true);
|
||||
/**
|
||||
* Only sets the setting to the given initializer, leaving the other members to their default
|
||||
* initializers.
|
||||
*
|
||||
* @param global_val Initial value of the setting
|
||||
*/
|
||||
explicit Setting(const Type& val) : value{val} {}
|
||||
|
||||
#undef SETTING
|
||||
#undef SWITCHABLE
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, label, and setting value.
|
||||
*
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit Setting(const Type& default_val, const std::string& name)
|
||||
requires(!ranged)
|
||||
: value{default_val}, default_value{default_val}, label{name} {}
|
||||
virtual ~Setting() = default;
|
||||
|
||||
/**
|
||||
* Sets a default value, minimum value, maximum value, and label.
|
||||
*
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param min_val Sets the minimum allowed value of the setting
|
||||
* @param max_val Sets the maximum allowed value of the setting
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val,
|
||||
const std::string& name)
|
||||
requires(ranged)
|
||||
: value{default_val},
|
||||
default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {}
|
||||
|
||||
/**
|
||||
* Returns a reference to the setting's value.
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
[[nodiscard]] virtual const Type& GetValue() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the setting to the given value.
|
||||
*
|
||||
* @param val The desired value
|
||||
*/
|
||||
virtual void SetValue(const Type& val) {
|
||||
Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
|
||||
std::swap(value, temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value that this setting was created with.
|
||||
*
|
||||
* @returns A reference to the default value
|
||||
*/
|
||||
[[nodiscard]] const Type& GetDefault() const {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label this setting was created with.
|
||||
*
|
||||
* @returns A reference to the label
|
||||
*/
|
||||
[[nodiscard]] const std::string& GetLabel() const {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a value to the setting.
|
||||
*
|
||||
* @param val The desired setting value
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
virtual const Type& operator=(const Type& val) {
|
||||
Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
|
||||
std::swap(value, temp);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the setting.
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
explicit virtual operator const Type&() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type value{}; ///< The setting
|
||||
const Type default_value{}; ///< The default value
|
||||
const Type maximum{}; ///< Maximum allowed value of the setting
|
||||
const Type minimum{}; ///< Minimum allowed value of the setting
|
||||
const std::string label{}; ///< The setting's label
|
||||
};
|
||||
|
||||
/**
|
||||
* The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a
|
||||
* custom setting to switch to when a guest application specifically requires it. The effect is that
|
||||
* other components of the emulator can access the setting's intended value without any need for the
|
||||
* component to ask whether the custom or global setting is needed at the moment.
|
||||
*
|
||||
* By default, the global setting is used.
|
||||
*/
|
||||
template <typename Type, bool ranged = false>
|
||||
class SwitchableSetting : virtual public Setting<Type, ranged> {
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, label, and setting value.
|
||||
*
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit SwitchableSetting(const Type& default_val, const std::string& name)
|
||||
requires(!ranged)
|
||||
: Setting<Type>{default_val, name} {}
|
||||
virtual ~SwitchableSetting() = default;
|
||||
|
||||
/**
|
||||
* Sets a default value, minimum value, maximum value, and label.
|
||||
*
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param min_val Sets the minimum allowed value of the setting
|
||||
* @param max_val Sets the maximum allowed value of the setting
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val,
|
||||
const std::string& name)
|
||||
requires(ranged)
|
||||
: Setting<Type, true>{default_val, min_val, max_val, name} {}
|
||||
|
||||
/**
|
||||
* Tells this setting to represent either the global or custom setting when other member
|
||||
* functions are used.
|
||||
*
|
||||
* @param to_global Whether to use the global or custom setting.
|
||||
*/
|
||||
void SetGlobal(bool to_global) {
|
||||
use_global = to_global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this setting is using the global setting or not.
|
||||
*
|
||||
* @returns The global state
|
||||
*/
|
||||
[[nodiscard]] bool UsingGlobal() const {
|
||||
return use_global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns either the global or custom setting depending on the values of this setting's global
|
||||
* state or if the global value was specifically requested.
|
||||
*
|
||||
* @param need_global Request global value regardless of setting's state; defaults to false
|
||||
*
|
||||
* @returns The required value of the setting
|
||||
*/
|
||||
[[nodiscard]] virtual const Type& GetValue() const override {
|
||||
if (use_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
[[nodiscard]] virtual const Type& GetValue(bool need_global) const {
|
||||
if (use_global || need_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current setting value depending on the global state.
|
||||
*
|
||||
* @param val The new value
|
||||
*/
|
||||
void SetValue(const Type& val) override {
|
||||
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
if (use_global) {
|
||||
std::swap(this->value, temp);
|
||||
} else {
|
||||
std::swap(custom, temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the current setting value depending on the global state.
|
||||
*
|
||||
* @param val The new value
|
||||
*
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
const Type& operator=(const Type& val) override {
|
||||
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
if (use_global) {
|
||||
std::swap(this->value, temp);
|
||||
return this->value;
|
||||
}
|
||||
std::swap(custom, temp);
|
||||
return custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current setting value depending on the global state.
|
||||
*
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
virtual explicit operator const Type&() const override {
|
||||
if (use_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool use_global{true}; ///< The setting's global state
|
||||
Type custom{}; ///< The custom value of the setting
|
||||
};
|
||||
|
||||
/**
|
||||
* The InputSetting class allows for getting a reference to either the global or custom members.
|
||||
@ -125,388 +391,208 @@ struct TouchFromButtonMap {
|
||||
};
|
||||
|
||||
struct Values {
|
||||
Linkage linkage{};
|
||||
|
||||
// Audio
|
||||
Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
SwitchableSetting<AudioMode, true> sound_index{
|
||||
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
|
||||
"sound_index", Category::SystemAudio, Specialization::Default, true,
|
||||
true};
|
||||
SwitchableSetting<u8, true> volume{linkage,
|
||||
100,
|
||||
0,
|
||||
200,
|
||||
"volume",
|
||||
Category::Audio,
|
||||
Specialization::Scalar | Specialization::Percentage,
|
||||
true,
|
||||
true};
|
||||
Setting<bool, false> audio_muted{
|
||||
linkage, false, "audio_muted", Category::Audio, Specialization::Default, false, true};
|
||||
Setting<bool, false> dump_audio_commands{
|
||||
linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false};
|
||||
Setting<std::string> sink_id{"auto", "output_engine"};
|
||||
Setting<std::string> audio_output_device_id{"auto", "output_device"};
|
||||
Setting<std::string> audio_input_device_id{"auto", "input_device"};
|
||||
Setting<bool> audio_muted{false, "audio_muted"};
|
||||
SwitchableSetting<u8, true> volume{100, 0, 200, "volume"};
|
||||
Setting<bool> dump_audio_commands{false, "dump_audio_commands"};
|
||||
|
||||
// Core
|
||||
SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core};
|
||||
SwitchableSetting<MemoryLayout, true> memory_layout_mode{linkage,
|
||||
MemoryLayout::Memory_4Gb,
|
||||
MemoryLayout::Memory_4Gb,
|
||||
MemoryLayout::Memory_8Gb,
|
||||
"memory_layout_mode",
|
||||
Category::Core};
|
||||
SwitchableSetting<bool> use_speed_limit{
|
||||
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, false, true};
|
||||
SwitchableSetting<u16, true> speed_limit{linkage,
|
||||
100,
|
||||
0,
|
||||
9999,
|
||||
"speed_limit",
|
||||
Category::Core,
|
||||
Specialization::Countable | Specialization::Percentage,
|
||||
true,
|
||||
true,
|
||||
&use_speed_limit};
|
||||
SwitchableSetting<bool> use_multi_core{true, "use_multi_core"};
|
||||
SwitchableSetting<bool> use_unsafe_extended_memory_layout{false,
|
||||
"use_unsafe_extended_memory_layout"};
|
||||
|
||||
// Cpu
|
||||
SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto,
|
||||
CpuAccuracy::Auto, CpuAccuracy::Paranoid,
|
||||
"cpu_accuracy", Category::Cpu};
|
||||
Setting<bool> cpu_debug_mode{linkage, false, "cpu_debug_mode", Category::CpuDebug};
|
||||
SwitchableSetting<CPUAccuracy, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
|
||||
CPUAccuracy::Paranoid, "cpu_accuracy"};
|
||||
// TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021
|
||||
Setting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"};
|
||||
Setting<bool> cpu_debug_mode{false, "cpu_debug_mode"};
|
||||
|
||||
Setting<bool> cpuopt_page_tables{linkage, true, "cpuopt_page_tables", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_block_linking{linkage, true, "cpuopt_block_linking", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_return_stack_buffer{linkage, true, "cpuopt_return_stack_buffer",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_fast_dispatcher{linkage, true, "cpuopt_fast_dispatcher",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_context_elimination{linkage, true, "cpuopt_context_elimination",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_const_prop{linkage, true, "cpuopt_const_prop", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_misc_ir{linkage, true, "cpuopt_misc_ir", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_reduce_misalign_checks{linkage, true, "cpuopt_reduce_misalign_checks",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_fastmem{linkage, true, "cpuopt_fastmem", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_fastmem_exclusives{linkage, true, "cpuopt_fastmem_exclusives",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_recompile_exclusives{linkage, true, "cpuopt_recompile_exclusives",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_ignore_memory_aborts{linkage, true, "cpuopt_ignore_memory_aborts",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_page_tables{true, "cpuopt_page_tables"};
|
||||
Setting<bool> cpuopt_block_linking{true, "cpuopt_block_linking"};
|
||||
Setting<bool> cpuopt_return_stack_buffer{true, "cpuopt_return_stack_buffer"};
|
||||
Setting<bool> cpuopt_fast_dispatcher{true, "cpuopt_fast_dispatcher"};
|
||||
Setting<bool> cpuopt_context_elimination{true, "cpuopt_context_elimination"};
|
||||
Setting<bool> cpuopt_const_prop{true, "cpuopt_const_prop"};
|
||||
Setting<bool> cpuopt_misc_ir{true, "cpuopt_misc_ir"};
|
||||
Setting<bool> cpuopt_reduce_misalign_checks{true, "cpuopt_reduce_misalign_checks"};
|
||||
Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"};
|
||||
Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"};
|
||||
Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"};
|
||||
Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"};
|
||||
|
||||
SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma",
|
||||
Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{
|
||||
linkage, true, "cpuopt_unsafe_reduce_fp_error", Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{
|
||||
linkage, true, "cpuopt_unsafe_ignore_standard_fpcr", Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{
|
||||
linkage, true, "cpuopt_unsafe_inaccurate_nan", Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{
|
||||
linkage, true, "cpuopt_unsafe_fastmem_check", Category::CpuUnsafe};
|
||||
true, "cpuopt_unsafe_ignore_standard_fpcr"};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{true, "cpuopt_unsafe_inaccurate_nan"};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{
|
||||
linkage, true, "cpuopt_unsafe_ignore_global_monitor", Category::CpuUnsafe};
|
||||
true, "cpuopt_unsafe_ignore_global_monitor"};
|
||||
|
||||
// Renderer
|
||||
SwitchableSetting<RendererBackend, true> renderer_backend{
|
||||
linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null,
|
||||
"backend", Category::Renderer};
|
||||
SwitchableSetting<ShaderBackend, true> shader_backend{
|
||||
linkage, ShaderBackend::Glsl, ShaderBackend::Glsl, ShaderBackend::SpirV,
|
||||
"shader_backend", Category::Renderer, Specialization::RuntimeList};
|
||||
SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer,
|
||||
Specialization::RuntimeList};
|
||||
|
||||
SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache",
|
||||
Category::Renderer};
|
||||
SwitchableSetting<bool> use_asynchronous_gpu_emulation{
|
||||
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
|
||||
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
||||
AstcDecodeMode::Gpu,
|
||||
AstcDecodeMode::Cpu,
|
||||
AstcDecodeMode::CpuAsynchronous,
|
||||
"accelerate_astc",
|
||||
Category::Renderer};
|
||||
Setting<VSyncMode, true> vsync_mode{
|
||||
linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed,
|
||||
"use_vsync", Category::Renderer, Specialization::RuntimeList, true,
|
||||
true};
|
||||
SwitchableSetting<NvdecEmulation> nvdec_emulation{linkage, NvdecEmulation::Gpu,
|
||||
"nvdec_emulation", Category::Renderer};
|
||||
// *nix platforms may have issues with the borderless windowed fullscreen mode.
|
||||
// Default to exclusive fullscreen on these platforms for now.
|
||||
SwitchableSetting<FullscreenMode, true> fullscreen_mode{linkage,
|
||||
#ifdef _WIN32
|
||||
FullscreenMode::Borderless,
|
||||
#else
|
||||
FullscreenMode::Exclusive,
|
||||
#endif
|
||||
FullscreenMode::Borderless,
|
||||
FullscreenMode::Exclusive,
|
||||
"fullscreen_mode",
|
||||
Category::Renderer,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<AspectRatio, true> aspect_ratio{linkage,
|
||||
AspectRatio::R16_9,
|
||||
AspectRatio::R16_9,
|
||||
AspectRatio::Stretch,
|
||||
"aspect_ratio",
|
||||
Category::Renderer,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"};
|
||||
SwitchableSetting<bool> async_presentation{false, "async_presentation"};
|
||||
SwitchableSetting<bool> renderer_force_max_clock{false, "force_max_clock"};
|
||||
Setting<bool> renderer_debug{false, "debug"};
|
||||
Setting<bool> renderer_shader_feedback{false, "shader_feedback"};
|
||||
Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"};
|
||||
Setting<bool> disable_shader_loop_safety_checks{false, "disable_shader_loop_safety_checks"};
|
||||
SwitchableSetting<int> vulkan_device{0, "vulkan_device"};
|
||||
|
||||
ResolutionScalingInfo resolution_info{};
|
||||
SwitchableSetting<ResolutionSetup> resolution_setup{linkage, ResolutionSetup::Res1X,
|
||||
"resolution_setup", Category::Renderer};
|
||||
SwitchableSetting<ScalingFilter> scaling_filter{linkage,
|
||||
ScalingFilter::Bilinear,
|
||||
"scaling_filter",
|
||||
Category::Renderer,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<AntiAliasing> anti_aliasing{linkage,
|
||||
AntiAliasing::None,
|
||||
"anti_aliasing",
|
||||
Category::Renderer,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<int, true> fsr_sharpening_slider{linkage,
|
||||
25,
|
||||
0,
|
||||
200,
|
||||
"fsr_sharpening_slider",
|
||||
Category::Renderer,
|
||||
Specialization::Scalar |
|
||||
Specialization::Percentage,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<ResolutionSetup> resolution_setup{ResolutionSetup::Res1X, "resolution_setup"};
|
||||
SwitchableSetting<ScalingFilter> scaling_filter{ScalingFilter::Bilinear, "scaling_filter"};
|
||||
SwitchableSetting<int, true> fsr_sharpening_slider{25, 0, 200, "fsr_sharpening_slider"};
|
||||
SwitchableSetting<AntiAliasing> anti_aliasing{AntiAliasing::None, "anti_aliasing"};
|
||||
// *nix platforms may have issues with the borderless windowed fullscreen mode.
|
||||
// Default to exclusive fullscreen on these platforms for now.
|
||||
SwitchableSetting<FullscreenMode, true> fullscreen_mode{
|
||||
#ifdef _WIN32
|
||||
FullscreenMode::Borderless,
|
||||
#else
|
||||
FullscreenMode::Exclusive,
|
||||
#endif
|
||||
FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"};
|
||||
SwitchableSetting<int, true> aspect_ratio{0, 0, 4, "aspect_ratio"};
|
||||
SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"};
|
||||
SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"};
|
||||
SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"};
|
||||
SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"};
|
||||
SwitchableSetting<GPUAccuracy, true> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
|
||||
GPUAccuracy::Extreme, "gpu_accuracy"};
|
||||
SwitchableSetting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"};
|
||||
SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
|
||||
SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
|
||||
SwitchableSetting<bool> async_astc{false, "async_astc"};
|
||||
Setting<VSyncMode, true> vsync_mode{VSyncMode::FIFO, VSyncMode::Immediate,
|
||||
VSyncMode::FIFORelaxed, "use_vsync"};
|
||||
SwitchableSetting<bool> use_reactive_flushing{true, "use_reactive_flushing"};
|
||||
SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLSL, ShaderBackend::GLSL,
|
||||
ShaderBackend::SPIRV, "shader_backend"};
|
||||
SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
|
||||
SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
|
||||
SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true,
|
||||
"use_vulkan_driver_pipeline_cache"};
|
||||
SwitchableSetting<bool> enable_compute_pipelines{false, "enable_compute_pipelines"};
|
||||
SwitchableSetting<AstcRecompression, true> astc_recompression{
|
||||
AstcRecompression::Uncompressed, AstcRecompression::Uncompressed, AstcRecompression::Bc3,
|
||||
"astc_recompression"};
|
||||
SwitchableSetting<bool> use_video_framerate{false, "use_video_framerate"};
|
||||
SwitchableSetting<bool> barrier_feedback_loops{true, "barrier_feedback_loops"};
|
||||
|
||||
SwitchableSetting<u8, false> bg_red{
|
||||
linkage, 0, "bg_red", Category::Renderer, Specialization::Default, true, true};
|
||||
SwitchableSetting<u8, false> bg_green{
|
||||
linkage, 0, "bg_green", Category::Renderer, Specialization::Default, true, true};
|
||||
SwitchableSetting<u8, false> bg_blue{
|
||||
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
||||
|
||||
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
||||
GpuAccuracy::High,
|
||||
GpuAccuracy::Normal,
|
||||
GpuAccuracy::Extreme,
|
||||
"gpu_accuracy",
|
||||
Category::RendererAdvanced,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<AnisotropyMode, true> max_anisotropy{
|
||||
linkage, AnisotropyMode::Automatic, AnisotropyMode::Automatic, AnisotropyMode::X16,
|
||||
"max_anisotropy", Category::RendererAdvanced};
|
||||
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
|
||||
AstcRecompression::Uncompressed,
|
||||
AstcRecompression::Uncompressed,
|
||||
AstcRecompression::Bc3,
|
||||
"astc_recompression",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> async_presentation{linkage, false, "async_presentation",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> use_reactive_flushing{linkage, true, "use_reactive_flushing",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> use_fast_gpu_time{
|
||||
linkage, true, "use_fast_gpu_time", Category::RendererAdvanced, Specialization::Default,
|
||||
true, true};
|
||||
SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{linkage,
|
||||
true,
|
||||
"use_vulkan_driver_pipeline_cache",
|
||||
Category::RendererAdvanced,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<bool> enable_compute_pipelines{linkage, false, "enable_compute_pipelines",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> use_video_framerate{linkage, false, "use_video_framerate",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> barrier_feedback_loops{linkage, true, "barrier_feedback_loops",
|
||||
Category::RendererAdvanced};
|
||||
|
||||
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
|
||||
Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback",
|
||||
Category::RendererDebug};
|
||||
Setting<bool> enable_nsight_aftermath{linkage, false, "nsight_aftermath",
|
||||
Category::RendererDebug};
|
||||
Setting<bool> disable_shader_loop_safety_checks{
|
||||
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
||||
SwitchableSetting<u8> bg_red{0, "bg_red"};
|
||||
SwitchableSetting<u8> bg_green{0, "bg_green"};
|
||||
SwitchableSetting<u8> bg_blue{0, "bg_blue"};
|
||||
|
||||
// System
|
||||
SwitchableSetting<Language, true> language_index{linkage,
|
||||
Language::EnglishAmerican,
|
||||
Language::Japanese,
|
||||
Language::PortugueseBrazilian,
|
||||
"language_index",
|
||||
Category::System};
|
||||
SwitchableSetting<Region, true> region_index{linkage, Region::Usa, Region::Japan,
|
||||
Region::Taiwan, "region_index", Category::System};
|
||||
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
|
||||
TimeZone::Auto, TimeZone::Zulu,
|
||||
"time_zone_index", Category::System};
|
||||
SwitchableSetting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"};
|
||||
Setting<std::string> device_name{"Yuzu", "device_name"};
|
||||
// Measured in seconds since epoch
|
||||
SwitchableSetting<bool> custom_rtc_enabled{
|
||||
linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true};
|
||||
SwitchableSetting<s64> custom_rtc{
|
||||
linkage, 0, "custom_rtc", Category::System, Specialization::Time,
|
||||
true, true, &custom_rtc_enabled};
|
||||
std::optional<s64> custom_rtc;
|
||||
// Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
|
||||
s64 custom_rtc_differential;
|
||||
SwitchableSetting<bool> rng_seed_enabled{
|
||||
linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true};
|
||||
SwitchableSetting<u32> rng_seed{
|
||||
linkage, 0, "rng_seed", Category::System, Specialization::Hex,
|
||||
true, true, &rng_seed_enabled};
|
||||
Setting<std::string> device_name{
|
||||
linkage, "yuzu", "device_name", Category::System, Specialization::Default, true, true};
|
||||
|
||||
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
||||
|
||||
SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System};
|
||||
Setting<s32> current_user{0, "current_user"};
|
||||
SwitchableSetting<s32, true> language_index{1, 0, 17, "language_index"};
|
||||
SwitchableSetting<s32, true> region_index{1, 0, 6, "region_index"};
|
||||
SwitchableSetting<s32, true> time_zone_index{0, 0, 45, "time_zone_index"};
|
||||
SwitchableSetting<s32, true> sound_index{1, 0, 2, "sound_index"};
|
||||
|
||||
// Controls
|
||||
InputSetting<std::array<PlayerInput, 10>> players;
|
||||
|
||||
Setting<bool> enable_raw_input{
|
||||
linkage, false, "enable_raw_input", Category::Controls, Specialization::Default,
|
||||
// Only read/write enable_raw_input on Windows platforms
|
||||
#ifdef _WIN32
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
};
|
||||
Setting<bool> controller_navigation{linkage, true, "controller_navigation", Category::Controls};
|
||||
Setting<bool> enable_joycon_driver{linkage, true, "enable_joycon_driver", Category::Controls};
|
||||
Setting<bool> enable_procon_driver{linkage, false, "enable_procon_driver", Category::Controls};
|
||||
SwitchableSetting<bool> use_docked_mode{true, "use_docked_mode"};
|
||||
|
||||
SwitchableSetting<bool> vibration_enabled{linkage, true, "vibration_enabled",
|
||||
Category::Controls};
|
||||
SwitchableSetting<bool> enable_accurate_vibrations{linkage, false, "enable_accurate_vibrations",
|
||||
Category::Controls};
|
||||
Setting<bool> enable_raw_input{false, "enable_raw_input"};
|
||||
Setting<bool> controller_navigation{true, "controller_navigation"};
|
||||
Setting<bool> enable_joycon_driver{true, "enable_joycon_driver"};
|
||||
Setting<bool> enable_procon_driver{false, "enable_procon_driver"};
|
||||
|
||||
SwitchableSetting<bool> motion_enabled{linkage, true, "motion_enabled", Category::Controls};
|
||||
Setting<std::string> udp_input_servers{linkage, "127.0.0.1:26760", "udp_input_servers",
|
||||
Category::Controls};
|
||||
Setting<bool> enable_udp_controller{linkage, false, "enable_udp_controller",
|
||||
Category::Controls};
|
||||
SwitchableSetting<bool> vibration_enabled{true, "vibration_enabled"};
|
||||
SwitchableSetting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"};
|
||||
|
||||
Setting<bool> pause_tas_on_load{linkage, true, "pause_tas_on_load", Category::Controls};
|
||||
Setting<bool> tas_enable{linkage, false, "tas_enable", Category::Controls};
|
||||
Setting<bool> tas_loop{linkage, false, "tas_loop", Category::Controls};
|
||||
SwitchableSetting<bool> motion_enabled{true, "motion_enabled"};
|
||||
Setting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
|
||||
Setting<bool> enable_udp_controller{false, "enable_udp_controller"};
|
||||
|
||||
Setting<bool> mouse_panning{
|
||||
linkage, false, "mouse_panning", Category::Controls, Specialization::Default, false};
|
||||
Setting<u8, true> mouse_panning_sensitivity{
|
||||
linkage, 50, 1, 100, "mouse_panning_sensitivity", Category::Controls};
|
||||
Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls};
|
||||
Setting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
|
||||
Setting<bool> tas_enable{false, "tas_enable"};
|
||||
Setting<bool> tas_loop{false, "tas_loop"};
|
||||
|
||||
Setting<u8, true> mouse_panning_x_sensitivity{
|
||||
linkage, 50, 1, 100, "mouse_panning_x_sensitivity", Category::Controls};
|
||||
Setting<u8, true> mouse_panning_y_sensitivity{
|
||||
linkage, 50, 1, 100, "mouse_panning_y_sensitivity", Category::Controls};
|
||||
Setting<u8, true> mouse_panning_deadzone_counterweight{
|
||||
linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls};
|
||||
Setting<u8, true> mouse_panning_decay_strength{
|
||||
linkage, 18, 0, 100, "mouse_panning_decay_strength", Category::Controls};
|
||||
Setting<u8, true> mouse_panning_min_decay{
|
||||
linkage, 6, 0, 100, "mouse_panning_min_decay", Category::Controls};
|
||||
Setting<bool> mouse_panning{false, "mouse_panning"};
|
||||
Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"};
|
||||
Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"};
|
||||
Setting<u8, true> mouse_panning_deadzone_counterweight{20, 0, 100,
|
||||
"mouse_panning_deadzone_counterweight"};
|
||||
Setting<u8, true> mouse_panning_decay_strength{18, 0, 100, "mouse_panning_decay_strength"};
|
||||
Setting<u8, true> mouse_panning_min_decay{6, 0, 100, "mouse_panning_min_decay"};
|
||||
|
||||
Setting<bool> emulate_analog_keyboard{linkage, false, "emulate_analog_keyboard",
|
||||
Category::Controls};
|
||||
Setting<bool> keyboard_enabled{linkage, false, "keyboard_enabled", Category::Controls};
|
||||
Setting<bool> mouse_enabled{false, "mouse_enabled"};
|
||||
Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
|
||||
Setting<bool> keyboard_enabled{false, "keyboard_enabled"};
|
||||
|
||||
Setting<bool> debug_pad_enabled{linkage, false, "debug_pad_enabled", Category::Controls};
|
||||
Setting<bool> debug_pad_enabled{false, "debug_pad_enabled"};
|
||||
ButtonsRaw debug_pad_buttons;
|
||||
AnalogsRaw debug_pad_analogs;
|
||||
|
||||
TouchscreenInput touchscreen;
|
||||
|
||||
Setting<std::string> touch_device{linkage, "min_x:100,min_y:50,max_x:1800,max_y:850",
|
||||
"touch_device", Category::Controls};
|
||||
Setting<int> touch_from_button_map_index{linkage, 0, "touch_from_button_map",
|
||||
Category::Controls};
|
||||
Setting<std::string> touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850", "touch_device"};
|
||||
Setting<int> touch_from_button_map_index{0, "touch_from_button_map"};
|
||||
std::vector<TouchFromButtonMap> touch_from_button_maps;
|
||||
|
||||
Setting<bool> enable_ring_controller{linkage, true, "enable_ring_controller",
|
||||
Category::Controls};
|
||||
Setting<bool> enable_ring_controller{true, "enable_ring_controller"};
|
||||
RingconRaw ringcon_analogs;
|
||||
|
||||
Setting<bool> enable_ir_sensor{linkage, false, "enable_ir_sensor", Category::Controls};
|
||||
Setting<std::string> ir_sensor_device{linkage, "auto", "ir_sensor_device", Category::Controls};
|
||||
Setting<bool> enable_ir_sensor{false, "enable_ir_sensor"};
|
||||
Setting<std::string> ir_sensor_device{"auto", "ir_sensor_device"};
|
||||
|
||||
Setting<bool> random_amiibo_id{linkage, false, "random_amiibo_id", Category::Controls};
|
||||
Setting<bool> random_amiibo_id{false, "random_amiibo_id"};
|
||||
|
||||
// Data Storage
|
||||
Setting<bool> use_virtual_sd{linkage, true, "use_virtual_sd", Category::DataStorage};
|
||||
Setting<bool> gamecard_inserted{linkage, false, "gamecard_inserted", Category::DataStorage};
|
||||
Setting<bool> gamecard_current_game{linkage, false, "gamecard_current_game",
|
||||
Category::DataStorage};
|
||||
Setting<std::string> gamecard_path{linkage, std::string(), "gamecard_path",
|
||||
Category::DataStorage};
|
||||
Setting<bool> use_virtual_sd{true, "use_virtual_sd"};
|
||||
Setting<bool> gamecard_inserted{false, "gamecard_inserted"};
|
||||
Setting<bool> gamecard_current_game{false, "gamecard_current_game"};
|
||||
Setting<std::string> gamecard_path{std::string(), "gamecard_path"};
|
||||
|
||||
// Debugging
|
||||
bool record_frame_times;
|
||||
Setting<bool> use_gdbstub{linkage, false, "use_gdbstub", Category::Debugging};
|
||||
Setting<u16> gdbstub_port{linkage, 6543, "gdbstub_port", Category::Debugging};
|
||||
Setting<std::string> program_args{linkage, std::string(), "program_args", Category::Debugging};
|
||||
Setting<bool> dump_exefs{linkage, false, "dump_exefs", Category::Debugging};
|
||||
Setting<bool> dump_nso{linkage, false, "dump_nso", Category::Debugging};
|
||||
Setting<bool> dump_shaders{
|
||||
linkage, false, "dump_shaders", Category::DebuggingGraphics, Specialization::Default,
|
||||
false};
|
||||
Setting<bool> dump_macros{
|
||||
linkage, false, "dump_macros", Category::DebuggingGraphics, Specialization::Default, false};
|
||||
Setting<bool> enable_fs_access_log{linkage, false, "enable_fs_access_log", Category::Debugging};
|
||||
Setting<bool> reporting_services{
|
||||
linkage, false, "reporting_services", Category::Debugging, Specialization::Default, false};
|
||||
Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging};
|
||||
Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit",
|
||||
Category::DebuggingGraphics};
|
||||
Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle",
|
||||
Category::DebuggingGraphics};
|
||||
Setting<bool> extended_logging{
|
||||
linkage, false, "extended_logging", Category::Debugging, Specialization::Default, false};
|
||||
Setting<bool> use_debug_asserts{linkage, false, "use_debug_asserts", Category::Debugging};
|
||||
Setting<bool> use_auto_stub{
|
||||
linkage, false, "use_auto_stub", Category::Debugging, Specialization::Default, false};
|
||||
Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers",
|
||||
Category::Debugging};
|
||||
Setting<bool> create_crash_dumps{linkage, false, "create_crash_dumps", Category::Debugging};
|
||||
Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging};
|
||||
Setting<bool> use_gdbstub{false, "use_gdbstub"};
|
||||
Setting<u16> gdbstub_port{6543, "gdbstub_port"};
|
||||
Setting<std::string> program_args{std::string(), "program_args"};
|
||||
Setting<bool> dump_exefs{false, "dump_exefs"};
|
||||
Setting<bool> dump_nso{false, "dump_nso"};
|
||||
Setting<bool> dump_shaders{false, "dump_shaders"};
|
||||
Setting<bool> dump_macros{false, "dump_macros"};
|
||||
Setting<bool> enable_fs_access_log{false, "enable_fs_access_log"};
|
||||
Setting<bool> reporting_services{false, "reporting_services"};
|
||||
Setting<bool> quest_flag{false, "quest_flag"};
|
||||
Setting<bool> disable_macro_jit{false, "disable_macro_jit"};
|
||||
Setting<bool> disable_macro_hle{false, "disable_macro_hle"};
|
||||
Setting<bool> extended_logging{false, "extended_logging"};
|
||||
Setting<bool> use_debug_asserts{false, "use_debug_asserts"};
|
||||
Setting<bool> use_auto_stub{false, "use_auto_stub"};
|
||||
Setting<bool> enable_all_controllers{false, "enable_all_controllers"};
|
||||
Setting<bool> create_crash_dumps{false, "create_crash_dumps"};
|
||||
Setting<bool> perform_vulkan_check{true, "perform_vulkan_check"};
|
||||
|
||||
// Miscellaneous
|
||||
Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
|
||||
Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous};
|
||||
Setting<std::string> log_filter{"*:Info", "log_filter"};
|
||||
Setting<bool> use_dev_keys{false, "use_dev_keys"};
|
||||
|
||||
// Network
|
||||
Setting<std::string> network_interface{linkage, std::string(), "network_interface",
|
||||
Category::Network};
|
||||
Setting<std::string> network_interface{std::string(), "network_interface"};
|
||||
|
||||
// WebService
|
||||
Setting<bool> enable_telemetry{linkage, true, "enable_telemetry", Category::WebService};
|
||||
Setting<std::string> web_api_url{linkage, "https://api.yuzu-emu.org", "web_api_url",
|
||||
Category::WebService};
|
||||
Setting<std::string> yuzu_username{linkage, std::string(), "yuzu_username",
|
||||
Category::WebService};
|
||||
Setting<std::string> yuzu_token{linkage, std::string(), "yuzu_token", Category::WebService};
|
||||
Setting<bool> enable_telemetry{true, "enable_telemetry"};
|
||||
Setting<std::string> web_api_url{"https://api.yuzu-emu.org", "web_api_url"};
|
||||
Setting<std::string> yuzu_username{std::string(), "yuzu_username"};
|
||||
Setting<std::string> yuzu_token{std::string(), "yuzu_token"};
|
||||
|
||||
// Add-Ons
|
||||
std::map<u64, std::vector<std::string>> disabled_addons;
|
||||
@ -514,6 +600,9 @@ struct Values {
|
||||
|
||||
extern Values values;
|
||||
|
||||
bool IsConfiguringGlobal();
|
||||
void SetConfiguringGlobal(bool is_global);
|
||||
|
||||
bool IsGPULevelExtreme();
|
||||
bool IsGPULevelHigh();
|
||||
|
||||
@ -521,7 +610,7 @@ bool IsFastmemEnabled();
|
||||
|
||||
float Volume();
|
||||
|
||||
std::string GetTimeZoneString(TimeZone time_zone);
|
||||
std::string GetTimeZoneString();
|
||||
|
||||
void LogSettings();
|
||||
|
||||
@ -530,7 +619,4 @@ void UpdateRescalingInfo();
|
||||
// Restore the global state of all applicable settings in the Values struct
|
||||
void RestoreGlobalState(bool is_powered_on);
|
||||
|
||||
bool IsConfiguringGlobal();
|
||||
void SetConfiguringGlobal(bool is_global);
|
||||
|
||||
} // namespace Settings
|
||||
|
@ -1,60 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common/settings_common.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
BasicSetting::BasicSetting(Linkage& linkage, const std::string& name, enum Category category_,
|
||||
bool save_, bool runtime_modifiable_, u32 specialization_,
|
||||
BasicSetting* other_setting_)
|
||||
: label{name}, category{category_}, id{linkage.count}, save{save_},
|
||||
runtime_modifiable{runtime_modifiable_}, specialization{specialization_},
|
||||
other_setting{other_setting_} {
|
||||
linkage.by_category[category].push_back(this);
|
||||
linkage.count++;
|
||||
}
|
||||
|
||||
BasicSetting::~BasicSetting() = default;
|
||||
|
||||
std::string BasicSetting::ToStringGlobal() const {
|
||||
return this->ToString();
|
||||
}
|
||||
|
||||
bool BasicSetting::UsingGlobal() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void BasicSetting::SetGlobal(bool global) {}
|
||||
|
||||
bool BasicSetting::Save() const {
|
||||
return save;
|
||||
}
|
||||
|
||||
bool BasicSetting::RuntimeModfiable() const {
|
||||
return runtime_modifiable;
|
||||
}
|
||||
|
||||
Category BasicSetting::GetCategory() const {
|
||||
return category;
|
||||
}
|
||||
|
||||
u32 BasicSetting::Specialization() const {
|
||||
return specialization;
|
||||
}
|
||||
|
||||
BasicSetting* BasicSetting::PairedSetting() const {
|
||||
return other_setting;
|
||||
}
|
||||
|
||||
const std::string& BasicSetting::GetLabel() const {
|
||||
return label;
|
||||
}
|
||||
|
||||
Linkage::Linkage(u32 initial_count) : count{initial_count} {}
|
||||
Linkage::~Linkage() = default;
|
||||
|
||||
} // namespace Settings
|
@ -1,256 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
enum class Category : u32 {
|
||||
Audio,
|
||||
Core,
|
||||
Cpu,
|
||||
CpuDebug,
|
||||
CpuUnsafe,
|
||||
Renderer,
|
||||
RendererAdvanced,
|
||||
RendererDebug,
|
||||
System,
|
||||
SystemAudio,
|
||||
DataStorage,
|
||||
Debugging,
|
||||
DebuggingGraphics,
|
||||
Miscellaneous,
|
||||
Network,
|
||||
WebService,
|
||||
AddOns,
|
||||
Controls,
|
||||
Ui,
|
||||
UiGeneral,
|
||||
UiLayout,
|
||||
UiGameList,
|
||||
Screenshots,
|
||||
Shortcuts,
|
||||
Multiplayer,
|
||||
Services,
|
||||
Paths,
|
||||
MaxEnum,
|
||||
};
|
||||
|
||||
constexpr u8 SpecializationTypeMask = 0xf;
|
||||
constexpr u8 SpecializationAttributeMask = 0xf0;
|
||||
constexpr u8 SpecializationAttributeOffset = 4;
|
||||
|
||||
// Scalar and countable could have better names
|
||||
enum Specialization : u8 {
|
||||
Default = 0,
|
||||
Time = 1, // Duration or specific moment in time
|
||||
Hex = 2, // Hexadecimal number
|
||||
List = 3, // Setting has specific members
|
||||
RuntimeList = 4, // Members of the list are determined during runtime
|
||||
Scalar = 5, // Values are continuous
|
||||
Countable = 6, // Can be stepped through
|
||||
Paired = 7, // Another setting is associated with this setting
|
||||
|
||||
Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage
|
||||
};
|
||||
|
||||
class BasicSetting;
|
||||
|
||||
class Linkage {
|
||||
public:
|
||||
explicit Linkage(u32 initial_count = 0);
|
||||
~Linkage();
|
||||
std::map<Category, std::vector<BasicSetting*>> by_category{};
|
||||
std::vector<std::function<void()>> restore_functions{};
|
||||
u32 count;
|
||||
};
|
||||
|
||||
/**
|
||||
* BasicSetting is an abstract class that only keeps track of metadata. The string methods are
|
||||
* available to get data values out.
|
||||
*/
|
||||
class BasicSetting {
|
||||
protected:
|
||||
explicit BasicSetting(Linkage& linkage, const std::string& name, Category category_, bool save_,
|
||||
bool runtime_modifiable_, u32 specialization,
|
||||
BasicSetting* other_setting);
|
||||
|
||||
public:
|
||||
virtual ~BasicSetting();
|
||||
|
||||
/*
|
||||
* Data retrieval
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a string representation of the internal data. If the Setting is Switchable, it
|
||||
* respects the internal global state: it is based on GetValue().
|
||||
*
|
||||
* @returns A string representation of the internal data.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string ToString() const = 0;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the global version of internal data. If the Setting is
|
||||
* not Switchable, it behaves like ToString.
|
||||
*
|
||||
* @returns A string representation of the global version of internal data.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string ToStringGlobal() const;
|
||||
|
||||
/**
|
||||
* @returns A string representation of the Setting's default value.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string DefaultToString() const = 0;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the minimum value of the setting. If the Setting is not
|
||||
* ranged, the string represents the default initialization of the data type.
|
||||
*
|
||||
* @returns A string representation of the minimum value of the setting.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string MinVal() const = 0;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the maximum value of the setting. If the Setting is not
|
||||
* ranged, the string represents the default initialization of the data type.
|
||||
*
|
||||
* @returns A string representation of the maximum value of the setting.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string MaxVal() const = 0;
|
||||
|
||||
/**
|
||||
* Takes a string input, converts it to the internal data type if necessary, and then runs
|
||||
* SetValue with it.
|
||||
*
|
||||
* @param load String of the input data.
|
||||
*/
|
||||
virtual void LoadString(const std::string& load) = 0;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the data. If the data is an enum, it returns a string of
|
||||
* the enum value. If the internal data type is not an enum, this is equivalent to ToString.
|
||||
*
|
||||
* e.g. renderer_backend.Canonicalize() == "OpenGL"
|
||||
*
|
||||
* @returns Canonicalized string representation of the internal data
|
||||
*/
|
||||
[[nodiscard]] virtual std::string Canonicalize() const = 0;
|
||||
|
||||
/*
|
||||
* Metadata
|
||||
*/
|
||||
|
||||
/**
|
||||
* @returns A unique identifier for the Setting's internal data type.
|
||||
*/
|
||||
[[nodiscard]] virtual std::type_index TypeId() const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the Setting's internal data type is an enum.
|
||||
*
|
||||
* @returns True if the Setting's internal data type is an enum
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr bool IsEnum() const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the current setting is Switchable.
|
||||
*
|
||||
* @returns If the setting is a SwitchableSetting
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr bool Switchable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to suggest that a frontend can read or write the setting to a configuration
|
||||
* file.
|
||||
*
|
||||
* @returns The save preference
|
||||
*/
|
||||
[[nodiscard]] bool Save() const;
|
||||
|
||||
/**
|
||||
* @returns true if the current setting can be changed while the guest is running.
|
||||
*/
|
||||
[[nodiscard]] bool RuntimeModfiable() const;
|
||||
|
||||
/**
|
||||
* @returns A unique number corresponding to the setting.
|
||||
*/
|
||||
[[nodiscard]] constexpr u32 Id() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setting's category AKA INI group.
|
||||
*
|
||||
* @returns The setting's category
|
||||
*/
|
||||
[[nodiscard]] Category GetCategory() const;
|
||||
|
||||
/**
|
||||
* @returns Extra metadata for data representation in frontend implementations.
|
||||
*/
|
||||
[[nodiscard]] u32 Specialization() const;
|
||||
|
||||
/**
|
||||
* @returns Another BasicSetting if one is paired, or nullptr otherwise.
|
||||
*/
|
||||
[[nodiscard]] BasicSetting* PairedSetting() const;
|
||||
|
||||
/**
|
||||
* Returns the label this setting was created with.
|
||||
*
|
||||
* @returns A reference to the label
|
||||
*/
|
||||
[[nodiscard]] const std::string& GetLabel() const;
|
||||
|
||||
/**
|
||||
* @returns If the Setting checks input values for valid ranges.
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr bool Ranged() const = 0;
|
||||
|
||||
/**
|
||||
* @returns The index of the enum if the underlying setting type is an enum, else max of u32.
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr u32 EnumIndex() const = 0;
|
||||
|
||||
/*
|
||||
* Switchable settings
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets a setting's global state. True means use the normal setting, false to use a custom
|
||||
* value. Has no effect if the Setting is not Switchable.
|
||||
*
|
||||
* @param global The desired state
|
||||
*/
|
||||
virtual void SetGlobal(bool global);
|
||||
|
||||
/**
|
||||
* Returns true if the setting is using the normal setting value. Always true if the setting is
|
||||
* not Switchable.
|
||||
*
|
||||
* @returns The Setting's global state
|
||||
*/
|
||||
[[nodiscard]] virtual bool UsingGlobal() const;
|
||||
|
||||
private:
|
||||
const std::string label; ///< The setting's label
|
||||
const Category category; ///< The setting's category AKA INI group
|
||||
const u32 id; ///< Unique integer for the setting
|
||||
const bool save; ///< Suggests if the setting should be saved and read to a frontend config
|
||||
const bool
|
||||
runtime_modifiable; ///< Suggests if the setting can be modified while a guest is running
|
||||
const u32 specialization; ///< Extra data to identify representation of a setting
|
||||
BasicSetting* const other_setting; ///< A paired setting
|
||||
};
|
||||
|
||||
} // namespace Settings
|
@ -1,214 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
template <typename T>
|
||||
struct EnumMetadata {
|
||||
static std::vector<std::pair<std::string, T>> Canonicalizations();
|
||||
static u32 Index();
|
||||
};
|
||||
|
||||
#define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__))
|
||||
#define PAIR_44(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_45(N, __VA_ARGS__))
|
||||
#define PAIR_43(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_44(N, __VA_ARGS__))
|
||||
#define PAIR_42(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_43(N, __VA_ARGS__))
|
||||
#define PAIR_41(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_42(N, __VA_ARGS__))
|
||||
#define PAIR_40(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_41(N, __VA_ARGS__))
|
||||
#define PAIR_39(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_40(N, __VA_ARGS__))
|
||||
#define PAIR_38(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_39(N, __VA_ARGS__))
|
||||
#define PAIR_37(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_38(N, __VA_ARGS__))
|
||||
#define PAIR_36(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_37(N, __VA_ARGS__))
|
||||
#define PAIR_35(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_36(N, __VA_ARGS__))
|
||||
#define PAIR_34(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_35(N, __VA_ARGS__))
|
||||
#define PAIR_33(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_34(N, __VA_ARGS__))
|
||||
#define PAIR_32(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_33(N, __VA_ARGS__))
|
||||
#define PAIR_31(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_32(N, __VA_ARGS__))
|
||||
#define PAIR_30(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_31(N, __VA_ARGS__))
|
||||
#define PAIR_29(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_30(N, __VA_ARGS__))
|
||||
#define PAIR_28(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_29(N, __VA_ARGS__))
|
||||
#define PAIR_27(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_28(N, __VA_ARGS__))
|
||||
#define PAIR_26(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_27(N, __VA_ARGS__))
|
||||
#define PAIR_25(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_26(N, __VA_ARGS__))
|
||||
#define PAIR_24(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_25(N, __VA_ARGS__))
|
||||
#define PAIR_23(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_24(N, __VA_ARGS__))
|
||||
#define PAIR_22(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_23(N, __VA_ARGS__))
|
||||
#define PAIR_21(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_22(N, __VA_ARGS__))
|
||||
#define PAIR_20(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_21(N, __VA_ARGS__))
|
||||
#define PAIR_19(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_20(N, __VA_ARGS__))
|
||||
#define PAIR_18(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_19(N, __VA_ARGS__))
|
||||
#define PAIR_17(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_18(N, __VA_ARGS__))
|
||||
#define PAIR_16(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_17(N, __VA_ARGS__))
|
||||
#define PAIR_15(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_16(N, __VA_ARGS__))
|
||||
#define PAIR_14(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_15(N, __VA_ARGS__))
|
||||
#define PAIR_13(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_14(N, __VA_ARGS__))
|
||||
#define PAIR_12(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_13(N, __VA_ARGS__))
|
||||
#define PAIR_11(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_12(N, __VA_ARGS__))
|
||||
#define PAIR_10(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_11(N, __VA_ARGS__))
|
||||
#define PAIR_9(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_10(N, __VA_ARGS__))
|
||||
#define PAIR_8(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_9(N, __VA_ARGS__))
|
||||
#define PAIR_7(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_8(N, __VA_ARGS__))
|
||||
#define PAIR_6(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_7(N, __VA_ARGS__))
|
||||
#define PAIR_5(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_6(N, __VA_ARGS__))
|
||||
#define PAIR_4(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_5(N, __VA_ARGS__))
|
||||
#define PAIR_3(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_4(N, __VA_ARGS__))
|
||||
#define PAIR_2(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_3(N, __VA_ARGS__))
|
||||
#define PAIR_1(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_2(N, __VA_ARGS__))
|
||||
#define PAIR(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_1(N, __VA_ARGS__))
|
||||
|
||||
#define ENUM(NAME, ...) \
|
||||
enum class NAME : u32 { __VA_ARGS__ }; \
|
||||
template <> \
|
||||
inline std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \
|
||||
return {PAIR(NAME, __VA_ARGS__)}; \
|
||||
} \
|
||||
template <> \
|
||||
inline u32 EnumMetadata<NAME>::Index() { \
|
||||
return __COUNTER__; \
|
||||
}
|
||||
|
||||
// AudioEngine must be specified discretely due to having existing but slightly different
|
||||
// canonicalizations
|
||||
// TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id
|
||||
enum class AudioEngine : u32 {
|
||||
Auto,
|
||||
Cubeb,
|
||||
Sdl2,
|
||||
Null,
|
||||
};
|
||||
|
||||
template <>
|
||||
inline std::vector<std::pair<std::string, AudioEngine>>
|
||||
EnumMetadata<AudioEngine>::Canonicalizations() {
|
||||
return {
|
||||
{"auto", AudioEngine::Auto},
|
||||
{"cubeb", AudioEngine::Cubeb},
|
||||
{"sdl2", AudioEngine::Sdl2},
|
||||
{"null", AudioEngine::Null},
|
||||
};
|
||||
}
|
||||
|
||||
template <>
|
||||
inline u32 EnumMetadata<AudioEngine>::Index() {
|
||||
// This is just a sufficiently large number that is more than the number of other enums declared
|
||||
// here
|
||||
return 100;
|
||||
}
|
||||
|
||||
ENUM(AudioMode, Mono, Stereo, Surround);
|
||||
|
||||
ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch,
|
||||
Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin,
|
||||
ChineseSimplified, ChineseTraditional, PortugueseBrazilian);
|
||||
|
||||
ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan);
|
||||
|
||||
ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt, Gb, GbEire, Gmt,
|
||||
GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica,
|
||||
Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt,
|
||||
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
||||
|
||||
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16);
|
||||
|
||||
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
||||
|
||||
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
||||
|
||||
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
|
||||
|
||||
ENUM(RendererBackend, OpenGL, Vulkan, Null);
|
||||
|
||||
ENUM(ShaderBackend, Glsl, Glasm, SpirV);
|
||||
|
||||
ENUM(GpuAccuracy, Normal, High, Extreme);
|
||||
|
||||
ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid);
|
||||
|
||||
ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb);
|
||||
|
||||
ENUM(FullscreenMode, Borderless, Exclusive);
|
||||
|
||||
ENUM(NvdecEmulation, Off, Cpu, Gpu);
|
||||
|
||||
ENUM(ResolutionSetup, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X,
|
||||
Res8X);
|
||||
|
||||
ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, ScaleForce, Fsr, MaxEnum);
|
||||
|
||||
ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum);
|
||||
|
||||
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
|
||||
|
||||
template <typename Type>
|
||||
inline std::string CanonicalizeEnum(Type id) {
|
||||
const auto group = EnumMetadata<Type>::Canonicalizations();
|
||||
for (auto& [name, value] : group) {
|
||||
if (value == id) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type ToEnum(const std::string& canonicalization) {
|
||||
const auto group = EnumMetadata<Type>::Canonicalizations();
|
||||
for (auto& [name, value] : group) {
|
||||
if (name == canonicalization) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
} // namespace Settings
|
||||
|
||||
#undef ENUM
|
||||
#undef PAIR
|
||||
#undef PAIR_1
|
||||
#undef PAIR_2
|
||||
#undef PAIR_3
|
||||
#undef PAIR_4
|
||||
#undef PAIR_5
|
||||
#undef PAIR_6
|
||||
#undef PAIR_7
|
||||
#undef PAIR_8
|
||||
#undef PAIR_9
|
||||
#undef PAIR_10
|
||||
#undef PAIR_12
|
||||
#undef PAIR_13
|
||||
#undef PAIR_14
|
||||
#undef PAIR_15
|
||||
#undef PAIR_16
|
||||
#undef PAIR_17
|
||||
#undef PAIR_18
|
||||
#undef PAIR_19
|
||||
#undef PAIR_20
|
||||
#undef PAIR_22
|
||||
#undef PAIR_23
|
||||
#undef PAIR_24
|
||||
#undef PAIR_25
|
||||
#undef PAIR_26
|
||||
#undef PAIR_27
|
||||
#undef PAIR_28
|
||||
#undef PAIR_29
|
||||
#undef PAIR_30
|
||||
#undef PAIR_32
|
||||
#undef PAIR_33
|
||||
#undef PAIR_34
|
||||
#undef PAIR_35
|
||||
#undef PAIR_36
|
||||
#undef PAIR_37
|
||||
#undef PAIR_38
|
||||
#undef PAIR_39
|
||||
#undef PAIR_40
|
||||
#undef PAIR_42
|
||||
#undef PAIR_43
|
||||
#undef PAIR_44
|
||||
#undef PAIR_45
|
@ -1,394 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings_common.h"
|
||||
#include "common/settings_enums.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
/** The Setting class is a simple resource manager. It defines a label and default value
|
||||
* alongside the actual value of the setting for simpler and less-error prone use with frontend
|
||||
* configurations. Specifying a default value and label is required. A minimum and maximum range
|
||||
* can be specified for sanitization.
|
||||
*/
|
||||
template <typename Type, bool ranged = false>
|
||||
class Setting : public BasicSetting {
|
||||
protected:
|
||||
Setting() = default;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, label, and setting value.
|
||||
*
|
||||
* @param linkage Setting registry
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param name Label for the setting
|
||||
* @param category_ Category of the setting AKA INI group
|
||||
* @param specialization_ Suggestion for how frontend implementations represent this in a config
|
||||
* @param save_ Suggests that this should or should not be saved to a frontend config file
|
||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||
*/
|
||||
explicit Setting(Linkage& linkage, const Type& default_val, const std::string& name,
|
||||
Category category_, u32 specialization_ = Specialization::Default,
|
||||
bool save_ = true, bool runtime_modifiable_ = false,
|
||||
BasicSetting* other_setting_ = nullptr)
|
||||
requires(!ranged)
|
||||
: BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_,
|
||||
other_setting_),
|
||||
value{default_val}, default_value{default_val} {}
|
||||
virtual ~Setting() = default;
|
||||
|
||||
/**
|
||||
* Sets a default value, minimum value, maximum value, and label.
|
||||
*
|
||||
* @param linkage Setting registry
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param min_val Sets the minimum allowed value of the setting
|
||||
* @param max_val Sets the maximum allowed value of the setting
|
||||
* @param name Label for the setting
|
||||
* @param category_ Category of the setting AKA INI group
|
||||
* @param specialization_ Suggestion for how frontend implementations represent this in a config
|
||||
* @param save_ Suggests that this should or should not be saved to a frontend config file
|
||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||
*/
|
||||
explicit Setting(Linkage& linkage, const Type& default_val, const Type& min_val,
|
||||
const Type& max_val, const std::string& name, Category category_,
|
||||
u32 specialization_ = Specialization::Default, bool save_ = true,
|
||||
bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr)
|
||||
requires(ranged)
|
||||
: BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_,
|
||||
other_setting_),
|
||||
value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val} {}
|
||||
|
||||
/**
|
||||
* Returns a reference to the setting's value.
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
[[nodiscard]] virtual const Type& GetValue() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the setting to the given value.
|
||||
*
|
||||
* @param val The desired value
|
||||
*/
|
||||
virtual void SetValue(const Type& val) {
|
||||
Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
|
||||
std::swap(value, temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value that this setting was created with.
|
||||
*
|
||||
* @returns A reference to the default value
|
||||
*/
|
||||
[[nodiscard]] const Type& GetDefault() const {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool IsEnum() const override {
|
||||
return std::is_enum_v<Type>;
|
||||
}
|
||||
|
||||
protected:
|
||||
[[nodiscard]] std::string ToString(const Type& value_) const {
|
||||
if constexpr (std::is_same_v<Type, std::string>) {
|
||||
return value_;
|
||||
} else if constexpr (std::is_same_v<Type, std::optional<u32>>) {
|
||||
return value_.has_value() ? std::to_string(*value_) : "none";
|
||||
} else if constexpr (std::is_same_v<Type, bool>) {
|
||||
return value_ ? "true" : "false";
|
||||
} else if constexpr (std::is_same_v<Type, AudioEngine>) {
|
||||
// Compatibility with old AudioEngine setting being a string
|
||||
return CanonicalizeEnum(value_);
|
||||
} else {
|
||||
return std::to_string(static_cast<u64>(value_));
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Converts the value of the setting to a std::string. Respects the global state if the setting
|
||||
* has one.
|
||||
*
|
||||
* @returns The current setting as a std::string
|
||||
*/
|
||||
[[nodiscard]] std::string ToString() const override {
|
||||
return ToString(this->GetValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value of the setting as a std::string.
|
||||
*
|
||||
* @returns The default value as a string.
|
||||
*/
|
||||
[[nodiscard]] std::string DefaultToString() const override {
|
||||
return ToString(default_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a value to the setting.
|
||||
*
|
||||
* @param val The desired setting value
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
virtual const Type& operator=(const Type& val) {
|
||||
Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
|
||||
std::swap(value, temp);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the setting.
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
explicit virtual operator const Type&() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given value to the Setting's type of value. Uses SetValue to enter the setting,
|
||||
* thus respecting its constraints.
|
||||
*
|
||||
* @param input The desired value
|
||||
*/
|
||||
void LoadString(const std::string& input) override final {
|
||||
if (input.empty()) {
|
||||
this->SetValue(this->GetDefault());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if constexpr (std::is_same_v<Type, std::string>) {
|
||||
this->SetValue(input);
|
||||
} else if constexpr (std::is_same_v<Type, std::optional<u32>>) {
|
||||
this->SetValue(static_cast<u32>(std::stoul(input)));
|
||||
} else if constexpr (std::is_same_v<Type, bool>) {
|
||||
this->SetValue(input == "true");
|
||||
} else if constexpr (std::is_same_v<Type, AudioEngine>) {
|
||||
this->SetValue(ToEnum<Type>(input));
|
||||
} else {
|
||||
this->SetValue(static_cast<Type>(std::stoll(input)));
|
||||
}
|
||||
} catch (std::invalid_argument&) {
|
||||
this->SetValue(this->GetDefault());
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string Canonicalize() const override final {
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
return CanonicalizeEnum(this->GetValue());
|
||||
} else {
|
||||
return ToString(this->GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives us another way to identify the setting without having to go through a string.
|
||||
*
|
||||
* @returns the type_index of the setting's type
|
||||
*/
|
||||
[[nodiscard]] std::type_index TypeId() const override final {
|
||||
return std::type_index(typeid(Type));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr u32 EnumIndex() const override final {
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
return EnumMetadata<Type>::Index();
|
||||
} else {
|
||||
return std::numeric_limits<u32>::max();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string MinVal() const override final {
|
||||
return this->ToString(minimum);
|
||||
}
|
||||
[[nodiscard]] std::string MaxVal() const override final {
|
||||
return this->ToString(maximum);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool Ranged() const override {
|
||||
return ranged;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type value{}; ///< The setting
|
||||
const Type default_value{}; ///< The default value
|
||||
const Type maximum{}; ///< Maximum allowed value of the setting
|
||||
const Type minimum{}; ///< Minimum allowed value of the setting
|
||||
};
|
||||
|
||||
/**
|
||||
* The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a
|
||||
* custom setting to switch to when a guest application specifically requires it. The effect is that
|
||||
* other components of the emulator can access the setting's intended value without any need for the
|
||||
* component to ask whether the custom or global setting is needed at the moment.
|
||||
*
|
||||
* By default, the global setting is used.
|
||||
*/
|
||||
template <typename Type, bool ranged = false>
|
||||
class SwitchableSetting : virtual public Setting<Type, ranged> {
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, label, and setting value.
|
||||
*
|
||||
* @param linkage Setting registry
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param name Label for the setting
|
||||
* @param category_ Category of the setting AKA INI group
|
||||
* @param specialization_ Suggestion for how frontend implementations represent this in a config
|
||||
* @param save_ Suggests that this should or should not be saved to a frontend config file
|
||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||
*/
|
||||
template <typename T = BasicSetting>
|
||||
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name,
|
||||
Category category_, u32 specialization_ = Specialization::Default,
|
||||
bool save_ = true, bool runtime_modifiable_ = false,
|
||||
typename std::enable_if<!ranged, T*>::type other_setting_ = nullptr)
|
||||
: Setting<Type, false>{
|
||||
linkage, default_val, name, category_, specialization_,
|
||||
save_, runtime_modifiable_, other_setting_} {
|
||||
linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
|
||||
}
|
||||
virtual ~SwitchableSetting() = default;
|
||||
|
||||
/**
|
||||
* Sets a default value, minimum value, maximum value, and label.
|
||||
*
|
||||
* @param linkage Setting registry
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param min_val Sets the minimum allowed value of the setting
|
||||
* @param max_val Sets the maximum allowed value of the setting
|
||||
* @param name Label for the setting
|
||||
* @param category_ Category of the setting AKA INI group
|
||||
* @param specialization_ Suggestion for how frontend implementations represent this in a config
|
||||
* @param save_ Suggests that this should or should not be saved to a frontend config file
|
||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||
*/
|
||||
template <typename T = BasicSetting>
|
||||
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val,
|
||||
const Type& max_val, const std::string& name, Category category_,
|
||||
u32 specialization_ = Specialization::Default, bool save_ = true,
|
||||
bool runtime_modifiable_ = false,
|
||||
typename std::enable_if<ranged, T*>::type other_setting_ = nullptr)
|
||||
: Setting<Type, true>{linkage, default_val, min_val,
|
||||
max_val, name, category_,
|
||||
specialization_, save_, runtime_modifiable_,
|
||||
other_setting_} {
|
||||
linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells this setting to represent either the global or custom setting when other member
|
||||
* functions are used.
|
||||
*
|
||||
* @param to_global Whether to use the global or custom setting.
|
||||
*/
|
||||
void SetGlobal(bool to_global) override final {
|
||||
use_global = to_global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this setting is using the global setting or not.
|
||||
*
|
||||
* @returns The global state
|
||||
*/
|
||||
[[nodiscard]] bool UsingGlobal() const override final {
|
||||
return use_global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns either the global or custom setting depending on the values of this setting's global
|
||||
* state or if the global value was specifically requested.
|
||||
*
|
||||
* @param need_global Request global value regardless of setting's state; defaults to false
|
||||
*
|
||||
* @returns The required value of the setting
|
||||
*/
|
||||
[[nodiscard]] const Type& GetValue() const override final {
|
||||
if (use_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
[[nodiscard]] const Type& GetValue(bool need_global) const {
|
||||
if (use_global || need_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current setting value depending on the global state.
|
||||
*
|
||||
* @param val The new value
|
||||
*/
|
||||
void SetValue(const Type& val) override final {
|
||||
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
if (use_global) {
|
||||
std::swap(this->value, temp);
|
||||
} else {
|
||||
std::swap(custom, temp);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool Switchable() const override final {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string ToStringGlobal() const override final {
|
||||
return this->ToString(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the current setting value depending on the global state.
|
||||
*
|
||||
* @param val The new value
|
||||
*
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
const Type& operator=(const Type& val) override final {
|
||||
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
if (use_global) {
|
||||
std::swap(this->value, temp);
|
||||
return this->value;
|
||||
}
|
||||
std::swap(custom, temp);
|
||||
return custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current setting value depending on the global state.
|
||||
*
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
explicit operator const Type&() const override final {
|
||||
if (use_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool use_global{true}; ///< The setting's global state
|
||||
Type custom{}; ///< The custom value of the setting
|
||||
};
|
||||
|
||||
} // namespace Settings
|
@ -287,7 +287,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
||||
}
|
||||
} else {
|
||||
// Unsafe optimizations
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) {
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
||||
config.unsafe_optimizations = true;
|
||||
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||
@ -307,7 +307,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
||||
}
|
||||
|
||||
// Curated optimizations
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) {
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Auto) {
|
||||
config.unsafe_optimizations = true;
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
|
||||
@ -316,7 +316,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
||||
}
|
||||
|
||||
// Paranoia mode for debugging optimizations
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) {
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Paranoid) {
|
||||
config.unsafe_optimizations = false;
|
||||
config.optimizations = Dynarmic::no_optimizations;
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
||||
}
|
||||
} else {
|
||||
// Unsafe optimizations
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) {
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
||||
config.unsafe_optimizations = true;
|
||||
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||
@ -367,7 +367,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
||||
}
|
||||
|
||||
// Curated optimizations
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Auto) {
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Auto) {
|
||||
config.unsafe_optimizations = true;
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||
config.fastmem_address_space_bits = 64;
|
||||
@ -375,7 +375,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
||||
}
|
||||
|
||||
// Paranoia mode for debugging optimizations
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) {
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Paranoid) {
|
||||
config.unsafe_optimizations = false;
|
||||
config.optimizations = Dynarmic::no_optimizations;
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_enums.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
@ -141,13 +140,16 @@ struct System::Impl {
|
||||
device_memory = std::make_unique<Core::DeviceMemory>();
|
||||
|
||||
is_multicore = Settings::values.use_multi_core.GetValue();
|
||||
extended_memory_layout =
|
||||
Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb;
|
||||
extended_memory_layout = Settings::values.use_unsafe_extended_memory_layout.GetValue();
|
||||
|
||||
core_timing.SetMulticore(is_multicore);
|
||||
core_timing.Initialize([&system]() { system.RegisterHostThread(); });
|
||||
|
||||
RefreshTime();
|
||||
const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
|
||||
const auto current_time =
|
||||
std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
|
||||
Settings::values.custom_rtc_differential =
|
||||
Settings::values.custom_rtc.value_or(current_time) - current_time;
|
||||
|
||||
// Create a default fs if one doesn't already exist.
|
||||
if (virtual_filesystem == nullptr) {
|
||||
@ -170,8 +172,7 @@ struct System::Impl {
|
||||
void ReinitializeIfNecessary(System& system) {
|
||||
const bool must_reinitialize =
|
||||
is_multicore != Settings::values.use_multi_core.GetValue() ||
|
||||
extended_memory_layout != (Settings::values.memory_layout_mode.GetValue() !=
|
||||
Settings::MemoryLayout::Memory_4Gb);
|
||||
extended_memory_layout != Settings::values.use_unsafe_extended_memory_layout.GetValue();
|
||||
|
||||
if (!must_reinitialize) {
|
||||
return;
|
||||
@ -180,22 +181,11 @@ struct System::Impl {
|
||||
LOG_DEBUG(Kernel, "Re-initializing");
|
||||
|
||||
is_multicore = Settings::values.use_multi_core.GetValue();
|
||||
extended_memory_layout =
|
||||
Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb;
|
||||
extended_memory_layout = Settings::values.use_unsafe_extended_memory_layout.GetValue();
|
||||
|
||||
Initialize(system);
|
||||
}
|
||||
|
||||
void RefreshTime() {
|
||||
const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
|
||||
const auto current_time =
|
||||
std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
|
||||
Settings::values.custom_rtc_differential =
|
||||
(Settings::values.custom_rtc_enabled ? Settings::values.custom_rtc.GetValue()
|
||||
: current_time) -
|
||||
current_time;
|
||||
}
|
||||
|
||||
void Run() {
|
||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||
|
||||
@ -1038,8 +1028,6 @@ void System::Exit() {
|
||||
}
|
||||
|
||||
void System::ApplySettings() {
|
||||
impl->RefreshTime();
|
||||
|
||||
if (IsPoweredOn()) {
|
||||
Renderer().RefreshBaseSettings();
|
||||
}
|
||||
|
@ -263,23 +263,6 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
|
||||
|
||||
std::vector<u8> mem(size);
|
||||
if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) {
|
||||
// Restore any bytes belonging to replaced instructions.
|
||||
auto it = replaced_instructions.lower_bound(addr);
|
||||
for (; it != replaced_instructions.end() && it->first < addr + size; it++) {
|
||||
// Get the bytes of the instruction we previously replaced.
|
||||
const u32 original_bytes = it->second;
|
||||
|
||||
// Calculate where to start writing to the output buffer.
|
||||
const size_t output_offset = it->first - addr;
|
||||
|
||||
// Calculate how many bytes to write.
|
||||
// The loop condition ensures output_offset < size.
|
||||
const size_t n = std::min<size_t>(size - output_offset, sizeof(u32));
|
||||
|
||||
// Write the bytes to the output buffer.
|
||||
std::memcpy(mem.data() + output_offset, &original_bytes, n);
|
||||
}
|
||||
|
||||
SendReply(Common::HexToString(mem));
|
||||
} else {
|
||||
SendReply(GDB_STUB_REPLY_ERR);
|
||||
|
@ -68,8 +68,7 @@ NACP::NACP(VirtualFile file) {
|
||||
NACP::~NACP() = default;
|
||||
|
||||
const LanguageEntry& NACP::GetLanguageEntry() const {
|
||||
Language language =
|
||||
language_to_codes[static_cast<s32>(Settings::values.language_index.GetValue())];
|
||||
Language language = language_to_codes[Settings::values.language_index.GetValue()];
|
||||
|
||||
{
|
||||
const auto& language_entry = raw.language_entries.at(static_cast<u8>(language));
|
||||
|
@ -626,8 +626,8 @@ PatchManager::Metadata PatchManager::ParseControlNCA(const NCA& nca) const {
|
||||
auto nacp = nacp_file == nullptr ? nullptr : std::make_unique<NACP>(nacp_file);
|
||||
|
||||
// Get language code from settings
|
||||
const auto language_code = Service::Set::GetLanguageCodeFromIndex(
|
||||
static_cast<u32>(Settings::values.language_index.GetValue()));
|
||||
const auto language_code =
|
||||
Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index.GetValue());
|
||||
|
||||
// Convert to application language and get priority list
|
||||
const auto application_language =
|
||||
|
@ -35,7 +35,7 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw_file) {
|
||||
update_raw = std::move(update_raw_file);
|
||||
}
|
||||
|
||||
VirtualFile RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const {
|
||||
ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const {
|
||||
if (!updatable) {
|
||||
return file;
|
||||
}
|
||||
@ -45,11 +45,12 @@ VirtualFile RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const
|
||||
return patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw);
|
||||
}
|
||||
|
||||
VirtualFile RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const {
|
||||
ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const {
|
||||
auto nca = content_provider.GetEntry(title_id, type);
|
||||
|
||||
if (nca == nullptr) {
|
||||
return nullptr;
|
||||
// TODO: Find the right error code to use here
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
const PatchManager patch_manager{title_id, filesystem_controller, content_provider};
|
||||
@ -57,20 +58,28 @@ VirtualFile RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type)
|
||||
return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type);
|
||||
}
|
||||
|
||||
VirtualFile RomFSFactory::OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index,
|
||||
ContentRecordType type) const {
|
||||
ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFSWithProgramIndex(
|
||||
u64 title_id, u8 program_index, ContentRecordType type) const {
|
||||
const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index);
|
||||
|
||||
return OpenPatchedRomFS(res_title_id, type);
|
||||
}
|
||||
|
||||
VirtualFile RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) const {
|
||||
ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage,
|
||||
ContentRecordType type) const {
|
||||
const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type);
|
||||
if (res == nullptr) {
|
||||
return nullptr;
|
||||
// TODO(DarkLordZach): Find the right error code to use here
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return res->GetRomFS();
|
||||
const auto romfs = res->GetRomFS();
|
||||
if (romfs == nullptr) {
|
||||
// TODO(DarkLordZach): Find the right error code to use here
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return romfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage,
|
||||
|
@ -41,11 +41,13 @@ public:
|
||||
~RomFSFactory();
|
||||
|
||||
void SetPackedUpdate(VirtualFile update_raw_file);
|
||||
[[nodiscard]] VirtualFile OpenCurrentProcess(u64 current_process_title_id) const;
|
||||
[[nodiscard]] VirtualFile OpenPatchedRomFS(u64 title_id, ContentRecordType type) const;
|
||||
[[nodiscard]] VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index,
|
||||
ContentRecordType type) const;
|
||||
[[nodiscard]] VirtualFile Open(u64 title_id, StorageId storage, ContentRecordType type) const;
|
||||
[[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
|
||||
[[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFS(u64 title_id,
|
||||
ContentRecordType type) const;
|
||||
[[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFSWithProgramIndex(
|
||||
u64 title_id, u8 program_index, ContentRecordType type) const;
|
||||
[[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage,
|
||||
ContentRecordType type) const;
|
||||
|
||||
private:
|
||||
[[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage,
|
||||
|
@ -108,16 +108,26 @@ SaveDataFactory::SaveDataFactory(Core::System& system_, VirtualDir save_director
|
||||
|
||||
SaveDataFactory::~SaveDataFactory() = default;
|
||||
|
||||
VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
|
||||
ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
|
||||
const SaveDataAttribute& meta) const {
|
||||
PrintSaveDataAttributeWarnings(meta);
|
||||
|
||||
const auto save_directory =
|
||||
GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
||||
|
||||
return dir->CreateDirectoryRelative(save_directory);
|
||||
auto out = dir->CreateDirectoryRelative(save_directory);
|
||||
|
||||
// Return an error if the save data doesn't actually exist.
|
||||
if (out == nullptr) {
|
||||
// TODO(DarkLordZach): Find out correct error code.
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
|
||||
ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
|
||||
const SaveDataAttribute& meta) const {
|
||||
|
||||
const auto save_directory =
|
||||
GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
||||
@ -128,6 +138,12 @@ VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute&
|
||||
return Create(space, meta);
|
||||
}
|
||||
|
||||
// Return an error if the save data doesn't actually exist.
|
||||
if (out == nullptr) {
|
||||
// TODO(Subv): Find out correct error code.
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -89,8 +89,8 @@ public:
|
||||
explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_);
|
||||
~SaveDataFactory();
|
||||
|
||||
VirtualDir Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
|
||||
VirtualDir Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
|
||||
ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
|
||||
ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
|
||||
|
||||
VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
|
||||
|
||||
|
@ -23,7 +23,7 @@ SDMCFactory::SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_)
|
||||
|
||||
SDMCFactory::~SDMCFactory() = default;
|
||||
|
||||
VirtualDir SDMCFactory::Open() const {
|
||||
ResultVal<VirtualDir> SDMCFactory::Open() const {
|
||||
return sd_dir;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_);
|
||||
~SDMCFactory();
|
||||
|
||||
VirtualDir Open() const;
|
||||
ResultVal<VirtualDir> Open() const;
|
||||
|
||||
VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const;
|
||||
VirtualDir GetSDMCContentDirectory() const;
|
||||
|
@ -289,19 +289,6 @@ enum class GyroscopeZeroDriftMode : u32 {
|
||||
Tight = 2,
|
||||
};
|
||||
|
||||
// This is nn::settings::system::TouchScreenMode
|
||||
enum class TouchScreenMode : u32 {
|
||||
Stylus = 0,
|
||||
Standard = 1,
|
||||
};
|
||||
|
||||
// This is nn::hid::TouchScreenModeForNx
|
||||
enum class TouchScreenModeForNx : u8 {
|
||||
UseSystemSetting,
|
||||
Finger,
|
||||
Heat2,
|
||||
};
|
||||
|
||||
// This is nn::hid::NpadStyleTag
|
||||
struct NpadStyleTag {
|
||||
union {
|
||||
@ -347,14 +334,6 @@ struct TouchState {
|
||||
};
|
||||
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
|
||||
|
||||
// This is nn::hid::TouchScreenConfigurationForNx
|
||||
struct TouchScreenConfigurationForNx {
|
||||
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
|
||||
INSERT_PADDING_BYTES(0xF);
|
||||
};
|
||||
static_assert(sizeof(TouchScreenConfigurationForNx) == 0x10,
|
||||
"TouchScreenConfigurationForNx is an invalid size");
|
||||
|
||||
struct NpadColor {
|
||||
u8 r{};
|
||||
u8 g{};
|
||||
@ -683,11 +662,6 @@ struct MouseState {
|
||||
};
|
||||
static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size");
|
||||
|
||||
struct UniquePadId {
|
||||
u64 id;
|
||||
};
|
||||
static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size");
|
||||
|
||||
/// Converts a NpadIdType to an array index.
|
||||
constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
|
||||
switch (npad_id_type) {
|
||||
|
@ -35,27 +35,13 @@ namespace {
|
||||
using namespace Common::Literals;
|
||||
|
||||
u32 GetMemorySizeForInit() {
|
||||
switch (Settings::values.memory_layout_mode.GetValue()) {
|
||||
case Settings::MemoryLayout::Memory_4Gb:
|
||||
return Smc::MemorySize_4GB;
|
||||
case Settings::MemoryLayout::Memory_6Gb:
|
||||
return Smc::MemorySize_6GB;
|
||||
case Settings::MemoryLayout::Memory_8Gb:
|
||||
return Smc::MemorySize_8GB;
|
||||
}
|
||||
return Smc::MemorySize_4GB;
|
||||
return Settings::values.use_unsafe_extended_memory_layout ? Smc::MemorySize_8GB
|
||||
: Smc::MemorySize_4GB;
|
||||
}
|
||||
|
||||
Smc::MemoryArrangement GetMemoryArrangeForInit() {
|
||||
switch (Settings::values.memory_layout_mode.GetValue()) {
|
||||
case Settings::MemoryLayout::Memory_4Gb:
|
||||
return Smc::MemoryArrangement_4GB;
|
||||
case Settings::MemoryLayout::Memory_6Gb:
|
||||
return Smc::MemoryArrangement_6GB;
|
||||
case Settings::MemoryLayout::Memory_8Gb:
|
||||
return Smc::MemoryArrangement_8GB;
|
||||
}
|
||||
return Smc::MemoryArrangement_4GB;
|
||||
return Settings::values.use_unsafe_extended_memory_layout ? Smc::MemoryArrangement_8GB
|
||||
: Smc::MemoryArrangement_4GB;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
@ -19,7 +19,13 @@ public:
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
s64 GetTick() const;
|
||||
s64 GetCount() const {
|
||||
return GetTick();
|
||||
}
|
||||
|
||||
void RegisterTask(KTimerTask* task, s64 time_from_now) {
|
||||
this->RegisterAbsoluteTask(task, GetTick() + time_from_now);
|
||||
}
|
||||
|
||||
void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) {
|
||||
KScopedDisableDispatch dd{m_kernel};
|
||||
@ -36,6 +42,7 @@ private:
|
||||
void EnableInterrupt(s64 wakeup_time);
|
||||
void DisableInterrupt();
|
||||
bool GetInterruptEnabled();
|
||||
s64 GetTick() const;
|
||||
void DoTask();
|
||||
|
||||
private:
|
||||
|
@ -768,7 +768,7 @@ Result KPageTable::UnmapProcessMemory(KProcessAddress dst_addr, size_t size,
|
||||
m_memory_block_slab_manager, num_allocator_blocks);
|
||||
R_TRY(allocator_result);
|
||||
|
||||
R_TRY(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap));
|
||||
CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap));
|
||||
|
||||
// Apply the memory block update.
|
||||
m_memory_block_manager.Update(std::addressof(allocator), dst_addr, num_pages,
|
||||
|
@ -81,8 +81,7 @@ Result KProcess::Initialize(KProcess* process, Core::System& system, std::string
|
||||
process->m_capabilities.InitializeForMetadatalessProcess();
|
||||
process->m_is_initialized = true;
|
||||
|
||||
std::mt19937 rng(Settings::values.rng_seed_enabled ? Settings::values.rng_seed.GetValue()
|
||||
: static_cast<u32>(std::time(nullptr)));
|
||||
std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr)));
|
||||
std::uniform_int_distribution<u64> distribution;
|
||||
std::generate(process->m_random_entropy.begin(), process->m_random_entropy.end(),
|
||||
[&] { return distribution(rng); });
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "common/overflow.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_resource_limit.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
|
||||
@ -16,7 +15,9 @@ KResourceLimit::KResourceLimit(KernelCore& kernel)
|
||||
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {}
|
||||
KResourceLimit::~KResourceLimit() = default;
|
||||
|
||||
void KResourceLimit::Initialize() {}
|
||||
void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing) {
|
||||
m_core_timing = core_timing;
|
||||
}
|
||||
|
||||
void KResourceLimit::Finalize() {}
|
||||
|
||||
@ -85,7 +86,7 @@ Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
|
||||
}
|
||||
|
||||
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
|
||||
return Reserve(which, value, m_kernel.HardwareTimer().GetTick() + DefaultTimeout);
|
||||
return Reserve(which, value, m_core_timing->GetGlobalTimeNs().count() + DefaultTimeout);
|
||||
}
|
||||
|
||||
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
||||
@ -116,7 +117,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
||||
}
|
||||
|
||||
if (m_current_hints[index] + value <= m_limit_values[index] &&
|
||||
(timeout < 0 || m_kernel.HardwareTimer().GetTick() < timeout)) {
|
||||
(timeout < 0 || m_core_timing->GetGlobalTimeNs().count() < timeout)) {
|
||||
m_waiter_count++;
|
||||
m_cond_var.Wait(std::addressof(m_lock), timeout, false);
|
||||
m_waiter_count--;
|
||||
@ -153,7 +154,7 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
|
||||
|
||||
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) {
|
||||
auto* resource_limit = KResourceLimit::Create(system.Kernel());
|
||||
resource_limit->Initialize();
|
||||
resource_limit->Initialize(std::addressof(system.CoreTiming()));
|
||||
|
||||
// Initialize default resource limit values.
|
||||
// TODO(bunnei): These values are the system defaults, the limits for service processes are
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
explicit KResourceLimit(KernelCore& kernel);
|
||||
~KResourceLimit() override;
|
||||
|
||||
void Initialize();
|
||||
void Initialize(const Core::Timing::CoreTiming* core_timing);
|
||||
void Finalize() override;
|
||||
|
||||
s64 GetLimitValue(LimitableResource which) const;
|
||||
@ -57,6 +57,7 @@ private:
|
||||
mutable KLightLock m_lock;
|
||||
s32 m_waiter_count{};
|
||||
KLightConditionVariable m_cond_var;
|
||||
const Core::Timing::CoreTiming* m_core_timing{};
|
||||
};
|
||||
|
||||
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size);
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
~KScopedSchedulerLockAndSleep() {
|
||||
// Register the sleep.
|
||||
if (m_timeout_tick > 0) {
|
||||
m_timer->RegisterAbsoluteTask(m_thread, m_timeout_tick);
|
||||
m_timer->RegisterTask(m_thread, m_timeout_tick);
|
||||
}
|
||||
|
||||
// Unlock the scheduler.
|
||||
|
@ -231,7 +231,7 @@ struct KernelCore::Impl {
|
||||
void InitializeSystemResourceLimit(KernelCore& kernel,
|
||||
const Core::Timing::CoreTiming& core_timing) {
|
||||
system_resource_limit = KResourceLimit::Create(system.Kernel());
|
||||
system_resource_limit->Initialize();
|
||||
system_resource_limit->Initialize(&core_timing);
|
||||
KResourceLimit::Register(kernel, system_resource_limit);
|
||||
|
||||
const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()};
|
||||
|
@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_memory_layout.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
@ -53,7 +52,7 @@ Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_typ
|
||||
if (timeout_ns > 0) {
|
||||
const s64 offset_tick(timeout_ns);
|
||||
if (offset_tick > 0) {
|
||||
timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2;
|
||||
timeout = offset_tick + 2;
|
||||
if (timeout <= 0) {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_memory_layout.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
@ -26,7 +25,7 @@ Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u
|
||||
if (timeout_ns > 0) {
|
||||
const s64 offset_tick(timeout_ns);
|
||||
if (offset_tick > 0) {
|
||||
timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2;
|
||||
timeout = offset_tick + 2;
|
||||
if (timeout <= 0) {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "common/scratch_buffer.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_client_session.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_server_session.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
@ -83,29 +82,12 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
|
||||
R_TRY(session->SendReply());
|
||||
}
|
||||
|
||||
// Convert the timeout from nanoseconds to ticks.
|
||||
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
|
||||
s64 timeout;
|
||||
if (timeout_ns > 0) {
|
||||
const s64 offset_tick(timeout_ns);
|
||||
if (offset_tick > 0) {
|
||||
timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
|
||||
if (timeout <= 0) {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
} else {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
} else {
|
||||
timeout = timeout_ns;
|
||||
}
|
||||
|
||||
// Wait for a message.
|
||||
while (true) {
|
||||
// Wait for an object.
|
||||
s32 index;
|
||||
Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(),
|
||||
num_handles, timeout);
|
||||
num_handles, timeout_ns);
|
||||
if (result == ResultTimedOut) {
|
||||
R_RETURN(result);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
|
||||
SCOPE_EXIT({ resource_limit->Close(); });
|
||||
|
||||
// Initialize the resource limit.
|
||||
resource_limit->Initialize();
|
||||
resource_limit->Initialize(std::addressof(system.CoreTiming()));
|
||||
|
||||
// Register the limit.
|
||||
KResourceLimit::Register(kernel, resource_limit);
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/scratch_buffer.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
@ -84,20 +83,9 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
|
||||
}
|
||||
});
|
||||
|
||||
// Convert the timeout from nanoseconds to ticks.
|
||||
s64 timeout;
|
||||
if (timeout_ns > 0) {
|
||||
u64 ticks = kernel.HardwareTimer().GetTick();
|
||||
ticks += timeout_ns;
|
||||
ticks += 2;
|
||||
|
||||
timeout = ticks;
|
||||
} else {
|
||||
timeout = timeout_ns;
|
||||
}
|
||||
|
||||
// Wait on the objects.
|
||||
Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout);
|
||||
Result res =
|
||||
KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout_ns);
|
||||
|
||||
R_SUCCEED_IF(res == ResultSessionClosed);
|
||||
R_RETURN(res);
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
@ -43,9 +42,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u
|
||||
R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority);
|
||||
|
||||
// Reserve a new thread from the process resource limit (waiting up to 100ms).
|
||||
KScopedResourceReservation thread_reservation(std::addressof(process),
|
||||
LimitableResource::ThreadCountMax, 1,
|
||||
kernel.HardwareTimer().GetTick() + 100000000);
|
||||
KScopedResourceReservation thread_reservation(
|
||||
std::addressof(process), LimitableResource::ThreadCountMax, 1,
|
||||
system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
|
||||
R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached);
|
||||
|
||||
// Create the thread.
|
||||
@ -103,31 +102,20 @@ void ExitThread(Core::System& system) {
|
||||
}
|
||||
|
||||
/// Sleep the current thread
|
||||
void SleepThread(Core::System& system, s64 ns) {
|
||||
void SleepThread(Core::System& system, s64 nanoseconds) {
|
||||
auto& kernel = system.Kernel();
|
||||
const auto yield_type = static_cast<Svc::YieldType>(ns);
|
||||
const auto yield_type = static_cast<Svc::YieldType>(nanoseconds);
|
||||
|
||||
LOG_TRACE(Kernel_SVC, "called nanoseconds={}", ns);
|
||||
LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
|
||||
|
||||
// When the input tick is positive, sleep.
|
||||
if (ns > 0) {
|
||||
if (nanoseconds > 0) {
|
||||
// Convert the timeout from nanoseconds to ticks.
|
||||
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
|
||||
s64 timeout;
|
||||
|
||||
const s64 offset_tick(ns);
|
||||
if (offset_tick > 0) {
|
||||
timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
|
||||
if (timeout <= 0) {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
} else {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
|
||||
// Sleep.
|
||||
// NOTE: Nintendo does not check the result of this sleep.
|
||||
static_cast<void>(GetCurrentThread(kernel).Sleep(timeout));
|
||||
static_cast<void>(GetCurrentThread(kernel).Sleep(nanoseconds));
|
||||
} else if (yield_type == Svc::YieldType::WithoutCoreMigration) {
|
||||
KScheduler::YieldWithoutCoreMigration(kernel);
|
||||
} else if (yield_type == Svc::YieldType::WithCoreMigration) {
|
||||
@ -136,6 +124,7 @@ void SleepThread(Core::System& system, s64 ns) {
|
||||
KScheduler::YieldToAnyThread(kernel);
|
||||
} else {
|
||||
// Nintendo does nothing at all if an otherwise invalid value is passed.
|
||||
ASSERT_MSG(false, "Unimplemented sleep yield type '{:016X}'!", nanoseconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,6 +283,159 @@ private:
|
||||
u32 description_end;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is an optional value type. It holds a `Result` and, if that code is ResultSuccess, it
|
||||
* also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying
|
||||
* to access the inner value with operator* is undefined behavior and will assert with Unwrap().
|
||||
* Users of this class must be cognizant to check the status of the ResultVal with operator bool(),
|
||||
* Code(), Succeeded() or Failed() prior to accessing the inner value.
|
||||
*
|
||||
* An example of how it could be used:
|
||||
* \code
|
||||
* ResultVal<int> Frobnicate(float strength) {
|
||||
* if (strength < 0.f || strength > 1.0f) {
|
||||
* // Can't frobnicate too weakly or too strongly
|
||||
* return Result{ErrorModule::Common, 1};
|
||||
* } else {
|
||||
* // Frobnicated! Give caller a cookie
|
||||
* return 42;
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \code
|
||||
* auto frob_result = Frobnicate(0.75f);
|
||||
* if (frob_result) {
|
||||
* // Frobbed ok
|
||||
* printf("My cookie is %d\n", *frob_result);
|
||||
* } else {
|
||||
* printf("Guess I overdid it. :( Error code: %ux\n", frob_result.Code().raw);
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
template <typename T>
|
||||
class ResultVal {
|
||||
public:
|
||||
constexpr ResultVal() : expected{} {}
|
||||
|
||||
constexpr ResultVal(Result code) : expected{Common::Unexpected(code)} {}
|
||||
|
||||
constexpr ResultVal(ResultRange range) : expected{Common::Unexpected(range)} {}
|
||||
|
||||
template <typename U>
|
||||
constexpr ResultVal(U&& val) : expected{std::forward<U>(val)} {}
|
||||
|
||||
template <typename... Args>
|
||||
constexpr ResultVal(Args&&... args) : expected{std::in_place, std::forward<Args>(args)...} {}
|
||||
|
||||
~ResultVal() = default;
|
||||
|
||||
constexpr ResultVal(const ResultVal&) = default;
|
||||
constexpr ResultVal(ResultVal&&) = default;
|
||||
|
||||
ResultVal& operator=(const ResultVal&) = default;
|
||||
ResultVal& operator=(ResultVal&&) = default;
|
||||
|
||||
[[nodiscard]] constexpr explicit operator bool() const noexcept {
|
||||
return expected.has_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Result Code() const {
|
||||
return expected.has_value() ? ResultSuccess : expected.error();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool Succeeded() const {
|
||||
return expected.has_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool Failed() const {
|
||||
return !expected.has_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T* operator->() {
|
||||
return std::addressof(expected.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const T* operator->() const {
|
||||
return std::addressof(expected.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T& operator*() & {
|
||||
return *expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const T& operator*() const& {
|
||||
return *expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T&& operator*() && {
|
||||
return *expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const T&& operator*() const&& {
|
||||
return *expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T& Unwrap() & {
|
||||
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
|
||||
return expected.value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const T& Unwrap() const& {
|
||||
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
|
||||
return expected.value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T&& Unwrap() && {
|
||||
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
|
||||
return std::move(expected.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const T&& Unwrap() const&& {
|
||||
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
|
||||
return std::move(expected.value());
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]] constexpr T ValueOr(U&& v) const& {
|
||||
return expected.value_or(v);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]] constexpr T ValueOr(U&& v) && {
|
||||
return expected.value_or(v);
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO (Morph): Replace this with C++23 std::expected.
|
||||
Common::Expected<T, Result> expected;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps
|
||||
* the contained value and assigns it to `target`, which can be either an l-value expression or a
|
||||
* variable declaration. If it fails the return code is returned from the current function. Thus it
|
||||
* can be used to cascade errors out, achieving something akin to exception handling.
|
||||
*/
|
||||
#define CASCADE_RESULT(target, source) \
|
||||
auto CONCAT2(check_result_L, __LINE__) = source; \
|
||||
if (CONCAT2(check_result_L, __LINE__).Failed()) { \
|
||||
return CONCAT2(check_result_L, __LINE__).Code(); \
|
||||
} \
|
||||
target = std::move(*CONCAT2(check_result_L, __LINE__))
|
||||
|
||||
/**
|
||||
* Analogous to CASCADE_RESULT, but for a bare Result. The code will be propagated if
|
||||
* non-success, or discarded otherwise.
|
||||
*/
|
||||
#define CASCADE_CODE(source) \
|
||||
do { \
|
||||
auto CONCAT2(check_result_L, __LINE__) = source; \
|
||||
if (CONCAT2(check_result_L, __LINE__).IsError()) { \
|
||||
return CONCAT2(check_result_L, __LINE__); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess())
|
||||
#define R_FAILED(res) (static_cast<Result>(res).IsFailure())
|
||||
|
||||
|
@ -765,16 +765,15 @@ Result Module::Interface::InitializeApplicationInfoBase() {
|
||||
// TODO(ogniK): This should be changed to reflect the target process for when we have multiple
|
||||
// processes emulated. As we don't actually have pid support we should assume we're just using
|
||||
// our own process
|
||||
Glue::ApplicationLaunchProperty launch_property{};
|
||||
const auto result = system.GetARPManager().GetLaunchProperty(
|
||||
&launch_property, system.GetApplicationProcessProgramID());
|
||||
const auto launch_property =
|
||||
system.GetARPManager().GetLaunchProperty(system.GetApplicationProcessProgramID());
|
||||
|
||||
if (result != ResultSuccess) {
|
||||
if (launch_property.Failed()) {
|
||||
LOG_ERROR(Service_ACC, "Failed to get launch property");
|
||||
return Account::ResultInvalidApplication;
|
||||
}
|
||||
|
||||
switch (launch_property.base_game_storage_id) {
|
||||
switch (launch_property->base_game_storage_id) {
|
||||
case FileSys::StorageId::GameCard:
|
||||
application_info.application_type = ApplicationType::GameCard;
|
||||
break;
|
||||
@ -786,7 +785,7 @@ Result Module::Interface::InitializeApplicationInfoBase() {
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}",
|
||||
launch_property.base_game_storage_id);
|
||||
launch_property->base_game_storage_id);
|
||||
return Account::ResultInvalidApplication;
|
||||
}
|
||||
|
||||
|
@ -1317,50 +1317,6 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
|
||||
rb.PushIpcInterface<IStorage>(system, std::move(memory));
|
||||
}
|
||||
|
||||
ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
|
||||
: ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "PopInData"},
|
||||
{1, nullptr, "PushOutData"},
|
||||
{2, nullptr, "PopInteractiveInData"},
|
||||
{3, nullptr, "PushInteractiveOutData"},
|
||||
{5, nullptr, "GetPopInDataEvent"},
|
||||
{6, nullptr, "GetPopInteractiveInDataEvent"},
|
||||
{10, nullptr, "ExitProcessAndReturn"},
|
||||
{11, nullptr, "GetLibraryAppletInfo"},
|
||||
{12, nullptr, "GetMainAppletIdentityInfo"},
|
||||
{13, nullptr, "CanUseApplicationCore"},
|
||||
{14, nullptr, "GetCallerAppletIdentityInfo"},
|
||||
{15, nullptr, "GetMainAppletApplicationControlProperty"},
|
||||
{16, nullptr, "GetMainAppletStorageId"},
|
||||
{17, nullptr, "GetCallerAppletIdentityInfoStack"},
|
||||
{18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
|
||||
{19, nullptr, "GetDesirableKeyboardLayout"},
|
||||
{20, nullptr, "PopExtraStorage"},
|
||||
{25, nullptr, "GetPopExtraStorageEvent"},
|
||||
{30, nullptr, "UnpopInData"},
|
||||
{31, nullptr, "UnpopExtraStorage"},
|
||||
{40, nullptr, "GetIndirectLayerProducerHandle"},
|
||||
{50, nullptr, "ReportVisibleError"},
|
||||
{51, nullptr, "ReportVisibleErrorWithErrorContext"},
|
||||
{60, nullptr, "GetMainAppletApplicationDesiredLanguage"},
|
||||
{70, nullptr, "GetCurrentApplicationId"},
|
||||
{80, nullptr, "RequestExitToSelf"},
|
||||
{90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
|
||||
{100, nullptr, "CreateGameMovieTrimmer"},
|
||||
{101, nullptr, "ReserveResourceForMovieOperation"},
|
||||
{102, nullptr, "UnreserveResourceForMovieOperation"},
|
||||
{110, nullptr, "GetMainAppletAvailableUsers"},
|
||||
{120, nullptr, "GetLaunchStorageInfoForDebug"},
|
||||
{130, nullptr, "GetGpuErrorDetectedSystemEvent"},
|
||||
{140, nullptr, "SetApplicationMemoryReservation"},
|
||||
{150, nullptr, "ShouldSetGpuTimeSliceManually"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
|
||||
|
||||
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
: ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
|
||||
"IApplicationFunctions"} {
|
||||
@ -1578,13 +1534,11 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
|
||||
attribute.title_id = system.GetApplicationProcessProgramID();
|
||||
attribute.user_id = user_id;
|
||||
attribute.type = FileSys::SaveDataType::SaveData;
|
||||
|
||||
FileSys::VirtualDir save_data{};
|
||||
const auto res = system.GetFileSystemController().CreateSaveData(
|
||||
&save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
|
||||
FileSys::SaveDataSpaceId::NandUser, attribute);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(res.Code());
|
||||
rb.Push<u64>(0);
|
||||
}
|
||||
|
||||
@ -1669,30 +1623,26 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
|
||||
auto app_man = ns_am2->GetApplicationManagerInterface();
|
||||
|
||||
// Get desired application language
|
||||
u8 desired_language{};
|
||||
const auto res_lang =
|
||||
app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
|
||||
if (res_lang != ResultSuccess) {
|
||||
const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages);
|
||||
if (res_lang.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res_lang);
|
||||
rb.Push(res_lang.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert to settings language code.
|
||||
u64 language_code{};
|
||||
const auto res_code =
|
||||
app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
|
||||
if (res_code != ResultSuccess) {
|
||||
const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang);
|
||||
if (res_code.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res_code);
|
||||
rb.Push(res_code.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
|
||||
LOG_DEBUG(Service_AM, "got desired_language={:016X}", *res_code);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(language_code);
|
||||
rb.Push(*res_code);
|
||||
}
|
||||
|
||||
void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
|
||||
|
@ -22,6 +22,30 @@ class Nvnflinger;
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
// This is nn::settings::Language
|
||||
enum SystemLanguage {
|
||||
Japanese = 0,
|
||||
English = 1, // en-US
|
||||
French = 2,
|
||||
German = 3,
|
||||
Italian = 4,
|
||||
Spanish = 5,
|
||||
Chinese = 6,
|
||||
Korean = 7,
|
||||
Dutch = 8,
|
||||
Portuguese = 9,
|
||||
Russian = 10,
|
||||
Taiwanese = 11,
|
||||
BritishEnglish = 12, // en-GB
|
||||
CanadianFrench = 13,
|
||||
LatinAmericanSpanish = 14, // es-419
|
||||
// 4.0.0+
|
||||
SimplifiedChinese = 15,
|
||||
TraditionalChinese = 16,
|
||||
// 10.1.0+
|
||||
BrazilianPortuguese = 17,
|
||||
};
|
||||
|
||||
class AppletMessageQueue {
|
||||
public:
|
||||
// This is nn::am::AppletMessage
|
||||
@ -290,12 +314,6 @@ private:
|
||||
void CreateHandleStorage(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
||||
public:
|
||||
explicit ILibraryAppletSelfAccessor(Core::System& system_);
|
||||
~ILibraryAppletSelfAccessor() override;
|
||||
};
|
||||
|
||||
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
||||
public:
|
||||
explicit IApplicationFunctions(Core::System& system_);
|
||||
|
@ -26,10 +26,8 @@ public:
|
||||
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
|
||||
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
|
||||
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
||||
{20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
|
||||
{20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"},
|
||||
{21, nullptr, "GetAppletCommonFunctions"},
|
||||
{22, nullptr, "GetHomeMenuFunctions"},
|
||||
{23, nullptr, "GetGlobalStateController"},
|
||||
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
||||
};
|
||||
// clang-format on
|
||||
@ -102,12 +100,12 @@ private:
|
||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
||||
}
|
||||
|
||||
void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
|
||||
void GetApplicationFunctions(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
|
||||
rb.PushIpcInterface<IApplicationFunctions>(system);
|
||||
}
|
||||
|
||||
Nvnflinger::Nvnflinger& nvnflinger;
|
||||
|
@ -22,13 +22,13 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
|
||||
{9, nullptr, "GetAudioOutputMode"},
|
||||
{10, nullptr, "SetAudioOutputMode"},
|
||||
{11, nullptr, "SetForceMutePolicy"},
|
||||
{12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
|
||||
{13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
|
||||
{12, nullptr, "GetForceMutePolicy"},
|
||||
{13, nullptr, "GetOutputModeSetting"},
|
||||
{14, nullptr, "SetOutputModeSetting"},
|
||||
{15, nullptr, "SetOutputTarget"},
|
||||
{16, nullptr, "SetInputTargetForceEnabled"},
|
||||
{17, nullptr, "SetHeadphoneOutputLevelMode"},
|
||||
{18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
|
||||
{18, nullptr, "GetHeadphoneOutputLevelMode"},
|
||||
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
|
||||
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
|
||||
{21, nullptr, "GetAudioOutputTargetForPlayReport"},
|
||||
@ -41,7 +41,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
|
||||
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
||||
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
||||
{30, nullptr, "SetSpeakerAutoMuteEnabled"},
|
||||
{31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
|
||||
{31, nullptr, "IsSpeakerAutoMuteEnabled"},
|
||||
{32, nullptr, "GetActiveOutputTarget"},
|
||||
{33, nullptr, "GetTargetDeviceInfo"},
|
||||
{34, nullptr, "AcquireTargetNotification"},
|
||||
@ -96,42 +96,4 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
|
||||
rb.Push(target_max_volume);
|
||||
}
|
||||
|
||||
void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Audio, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(ForceMutePolicy::Disable);
|
||||
}
|
||||
|
||||
void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto value = rp.Pop<u32>();
|
||||
|
||||
LOG_WARNING(Audio, "(STUBBED) called, value={}", value);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(AudioOutputMode::PcmAuto);
|
||||
}
|
||||
|
||||
void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Audio, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(HeadphoneOutputLevelMode::Normal);
|
||||
}
|
||||
|
||||
void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
|
||||
const bool is_speaker_auto_mute_enabled = false;
|
||||
|
||||
LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
|
||||
is_speaker_auto_mute_enabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(is_speaker_auto_mute_enabled);
|
||||
}
|
||||
|
||||
} // namespace Service::Audio
|
||||
|
@ -17,30 +17,8 @@ public:
|
||||
~AudCtl() override;
|
||||
|
||||
private:
|
||||
enum class AudioOutputMode {
|
||||
Invalid,
|
||||
Pcm1ch,
|
||||
Pcm2ch,
|
||||
Pcm6ch,
|
||||
PcmAuto,
|
||||
};
|
||||
|
||||
enum class ForceMutePolicy {
|
||||
Disable,
|
||||
SpeakerMuteOnHeadphoneUnplugged,
|
||||
};
|
||||
|
||||
enum class HeadphoneOutputLevelMode {
|
||||
Normal,
|
||||
HighPower,
|
||||
};
|
||||
|
||||
void GetTargetVolumeMin(HLERequestContext& ctx);
|
||||
void GetTargetVolumeMax(HLERequestContext& ctx);
|
||||
void GetForceMutePolicy(HLERequestContext& ctx);
|
||||
void GetOutputModeSetting(HLERequestContext& ctx);
|
||||
void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
|
||||
void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
} // namespace Service::Audio
|
||||
|
@ -57,8 +57,8 @@ Result VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
FileSys::EntryType entry_type{};
|
||||
if (GetEntryType(&entry_type, path) == ResultSuccess) {
|
||||
const auto entry_type = GetEntryType(path);
|
||||
if (entry_type.Code() == ResultSuccess) {
|
||||
return FileSys::ERROR_PATH_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
@ -210,8 +210,8 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file,
|
||||
const std::string& path_, FileSys::Mode mode) const {
|
||||
ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_,
|
||||
FileSys::Mode mode) const {
|
||||
const std::string path(Common::FS::SanitizePath(path_));
|
||||
std::string_view npath = path;
|
||||
while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) {
|
||||
@ -224,68 +224,50 @@ Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file,
|
||||
}
|
||||
|
||||
if (mode == FileSys::Mode::Append) {
|
||||
*out_file = std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize());
|
||||
} else {
|
||||
*out_file = file;
|
||||
return std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize());
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
return file;
|
||||
}
|
||||
|
||||
Result VfsDirectoryServiceWrapper::OpenDirectory(FileSys::VirtualDir* out_directory,
|
||||
const std::string& path_) {
|
||||
ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) {
|
||||
std::string path(Common::FS::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, path);
|
||||
if (dir == nullptr) {
|
||||
// TODO(DarkLordZach): Find a better error code for this
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
*out_directory = dir;
|
||||
return ResultSuccess;
|
||||
return dir;
|
||||
}
|
||||
|
||||
Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::EntryType* out_entry_type,
|
||||
const std::string& path_) const {
|
||||
ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
|
||||
const std::string& path_) const {
|
||||
std::string path(Common::FS::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
|
||||
if (dir == nullptr) {
|
||||
if (dir == nullptr)
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
auto filename = Common::FS::GetFilename(path);
|
||||
// TODO(Subv): Some games use the '/' path, find out what this means.
|
||||
if (filename.empty()) {
|
||||
*out_entry_type = FileSys::EntryType::Directory;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
if (dir->GetFile(filename) != nullptr) {
|
||||
*out_entry_type = FileSys::EntryType::File;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
if (dir->GetSubdirectory(filename) != nullptr) {
|
||||
*out_entry_type = FileSys::EntryType::Directory;
|
||||
return ResultSuccess;
|
||||
}
|
||||
if (filename.empty())
|
||||
return FileSys::EntryType::Directory;
|
||||
|
||||
if (dir->GetFile(filename) != nullptr)
|
||||
return FileSys::EntryType::File;
|
||||
if (dir->GetSubdirectory(filename) != nullptr)
|
||||
return FileSys::EntryType::Directory;
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw(
|
||||
FileSys::FileTimeStampRaw* out_file_time_stamp_raw, const std::string& path) const {
|
||||
ResultVal<FileSys::FileTimeStampRaw> VfsDirectoryServiceWrapper::GetFileTimeStampRaw(
|
||||
const std::string& path) const {
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
|
||||
if (dir == nullptr) {
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
FileSys::EntryType entry_type;
|
||||
if (GetEntryType(&entry_type, path) != ResultSuccess) {
|
||||
if (GetEntryType(path).Failed()) {
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
*out_file_time_stamp_raw = dir->GetFileTimeStamp(Common::FS::GetFilename(path));
|
||||
return ResultSuccess;
|
||||
return dir->GetFileTimeStamp(Common::FS::GetFilename(path));
|
||||
}
|
||||
|
||||
FileSystemController::FileSystemController(Core::System& system_) : system{system_} {}
|
||||
@ -328,54 +310,57 @@ void FileSystemController::SetPackedUpdate(FileSys::VirtualFile update_raw) {
|
||||
romfs_factory->SetPackedUpdate(std::move(update_raw));
|
||||
}
|
||||
|
||||
FileSys::VirtualFile FileSystemController::OpenRomFSCurrentProcess() const {
|
||||
ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFSCurrentProcess() const {
|
||||
LOG_TRACE(Service_FS, "Opening RomFS for current process");
|
||||
|
||||
if (romfs_factory == nullptr) {
|
||||
return nullptr;
|
||||
// TODO(bunnei): Find a better error code for this
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID());
|
||||
}
|
||||
|
||||
FileSys::VirtualFile FileSystemController::OpenPatchedRomFS(u64 title_id,
|
||||
FileSys::ContentRecordType type) const {
|
||||
ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFS(
|
||||
u64 title_id, FileSys::ContentRecordType type) const {
|
||||
LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id);
|
||||
|
||||
if (romfs_factory == nullptr) {
|
||||
return nullptr;
|
||||
// TODO: Find a better error code for this
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return romfs_factory->OpenPatchedRomFS(title_id, type);
|
||||
}
|
||||
|
||||
FileSys::VirtualFile FileSystemController::OpenPatchedRomFSWithProgramIndex(
|
||||
ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFSWithProgramIndex(
|
||||
u64 title_id, u8 program_index, FileSys::ContentRecordType type) const {
|
||||
LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id,
|
||||
program_index);
|
||||
|
||||
if (romfs_factory == nullptr) {
|
||||
return nullptr;
|
||||
// TODO: Find a better error code for this
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type);
|
||||
}
|
||||
|
||||
FileSys::VirtualFile FileSystemController::OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
|
||||
FileSys::ContentRecordType type) const {
|
||||
ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS(
|
||||
u64 title_id, FileSys::StorageId storage_id, FileSys::ContentRecordType type) const {
|
||||
LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}",
|
||||
title_id, storage_id, type);
|
||||
|
||||
if (romfs_factory == nullptr) {
|
||||
return nullptr;
|
||||
// TODO(bunnei): Find a better error code for this
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return romfs_factory->Open(title_id, storage_id, type);
|
||||
}
|
||||
|
||||
Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data,
|
||||
FileSys::SaveDataSpaceId space,
|
||||
const FileSys::SaveDataAttribute& save_struct) const {
|
||||
ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData(
|
||||
FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const {
|
||||
LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space,
|
||||
save_struct.DebugInfo());
|
||||
|
||||
@ -383,18 +368,11 @@ Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data,
|
||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||
}
|
||||
|
||||
auto save_data = save_data_factory->Create(space, save_struct);
|
||||
if (save_data == nullptr) {
|
||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||
}
|
||||
|
||||
*out_save_data = save_data;
|
||||
return ResultSuccess;
|
||||
return save_data_factory->Create(space, save_struct);
|
||||
}
|
||||
|
||||
Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data,
|
||||
FileSys::SaveDataSpaceId space,
|
||||
const FileSys::SaveDataAttribute& attribute) const {
|
||||
ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData(
|
||||
FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& attribute) const {
|
||||
LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space,
|
||||
attribute.DebugInfo());
|
||||
|
||||
@ -402,50 +380,32 @@ Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data,
|
||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||
}
|
||||
|
||||
auto save_data = save_data_factory->Open(space, attribute);
|
||||
if (save_data == nullptr) {
|
||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||
}
|
||||
|
||||
*out_save_data = save_data;
|
||||
return ResultSuccess;
|
||||
return save_data_factory->Open(space, attribute);
|
||||
}
|
||||
|
||||
Result FileSystemController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space,
|
||||
FileSys::SaveDataSpaceId space) const {
|
||||
ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveDataSpace(
|
||||
FileSys::SaveDataSpaceId space) const {
|
||||
LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space);
|
||||
|
||||
if (save_data_factory == nullptr) {
|
||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||
}
|
||||
|
||||
auto save_data_space = save_data_factory->GetSaveDataSpaceDirectory(space);
|
||||
if (save_data_space == nullptr) {
|
||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||
}
|
||||
|
||||
*out_save_data_space = save_data_space;
|
||||
return ResultSuccess;
|
||||
return save_data_factory->GetSaveDataSpaceDirectory(space);
|
||||
}
|
||||
|
||||
Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const {
|
||||
ResultVal<FileSys::VirtualDir> FileSystemController::OpenSDMC() const {
|
||||
LOG_TRACE(Service_FS, "Opening SDMC");
|
||||
|
||||
if (sdmc_factory == nullptr) {
|
||||
return FileSys::ERROR_SD_CARD_NOT_FOUND;
|
||||
}
|
||||
|
||||
auto sdmc = sdmc_factory->Open();
|
||||
if (sdmc == nullptr) {
|
||||
return FileSys::ERROR_SD_CARD_NOT_FOUND;
|
||||
}
|
||||
|
||||
*out_sdmc = sdmc;
|
||||
return ResultSuccess;
|
||||
return sdmc_factory->Open();
|
||||
}
|
||||
|
||||
Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_partition,
|
||||
FileSys::BisPartitionId id) const {
|
||||
ResultVal<FileSys::VirtualDir> FileSystemController::OpenBISPartition(
|
||||
FileSys::BisPartitionId id) const {
|
||||
LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id);
|
||||
|
||||
if (bis_factory == nullptr) {
|
||||
@ -457,12 +417,11 @@ Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_parti
|
||||
return FileSys::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*out_bis_partition = part;
|
||||
return ResultSuccess;
|
||||
return part;
|
||||
}
|
||||
|
||||
Result FileSystemController::OpenBISPartitionStorage(
|
||||
FileSys::VirtualFile* out_bis_partition_storage, FileSys::BisPartitionId id) const {
|
||||
ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage(
|
||||
FileSys::BisPartitionId id) const {
|
||||
LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id);
|
||||
|
||||
if (bis_factory == nullptr) {
|
||||
@ -474,8 +433,7 @@ Result FileSystemController::OpenBISPartitionStorage(
|
||||
return FileSys::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*out_bis_partition_storage = part;
|
||||
return ResultSuccess;
|
||||
return part;
|
||||
}
|
||||
|
||||
u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const {
|
||||
|
@ -64,24 +64,21 @@ public:
|
||||
Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
|
||||
|
||||
void SetPackedUpdate(FileSys::VirtualFile update_raw);
|
||||
FileSys::VirtualFile OpenRomFSCurrentProcess() const;
|
||||
FileSys::VirtualFile OpenPatchedRomFS(u64 title_id, FileSys::ContentRecordType type) const;
|
||||
FileSys::VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index,
|
||||
FileSys::ContentRecordType type) const;
|
||||
FileSys::VirtualFile OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
|
||||
FileSys::ContentRecordType type) const;
|
||||
|
||||
Result CreateSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space,
|
||||
const FileSys::SaveDataAttribute& save_struct) const;
|
||||
Result OpenSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space,
|
||||
const FileSys::SaveDataAttribute& save_struct) const;
|
||||
Result OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space,
|
||||
FileSys::SaveDataSpaceId space) const;
|
||||
Result OpenSDMC(FileSys::VirtualDir* out_sdmc) const;
|
||||
Result OpenBISPartition(FileSys::VirtualDir* out_bis_partition,
|
||||
FileSys::BisPartitionId id) const;
|
||||
Result OpenBISPartitionStorage(FileSys::VirtualFile* out_bis_partition_storage,
|
||||
FileSys::BisPartitionId id) const;
|
||||
ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const;
|
||||
ResultVal<FileSys::VirtualFile> OpenPatchedRomFS(u64 title_id,
|
||||
FileSys::ContentRecordType type) const;
|
||||
ResultVal<FileSys::VirtualFile> OpenPatchedRomFSWithProgramIndex(
|
||||
u64 title_id, u8 program_index, FileSys::ContentRecordType type) const;
|
||||
ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
|
||||
FileSys::ContentRecordType type) const;
|
||||
ResultVal<FileSys::VirtualDir> CreateSaveData(
|
||||
FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const;
|
||||
ResultVal<FileSys::VirtualDir> OpenSaveData(
|
||||
FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const;
|
||||
ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) const;
|
||||
ResultVal<FileSys::VirtualDir> OpenSDMC() const;
|
||||
ResultVal<FileSys::VirtualDir> OpenBISPartition(FileSys::BisPartitionId id) const;
|
||||
ResultVal<FileSys::VirtualFile> OpenBISPartitionStorage(FileSys::BisPartitionId id) const;
|
||||
|
||||
u64 GetFreeSpaceSize(FileSys::StorageId id) const;
|
||||
u64 GetTotalSpaceSize(FileSys::StorageId id) const;
|
||||
@ -227,28 +224,26 @@ public:
|
||||
* @param mode Mode to open the file with
|
||||
* @return Opened file, or error code
|
||||
*/
|
||||
Result OpenFile(FileSys::VirtualFile* out_file, const std::string& path,
|
||||
FileSys::Mode mode) const;
|
||||
ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const;
|
||||
|
||||
/**
|
||||
* Open a directory specified by its path
|
||||
* @param path Path relative to the archive
|
||||
* @return Opened directory, or error code
|
||||
*/
|
||||
Result OpenDirectory(FileSys::VirtualDir* out_directory, const std::string& path);
|
||||
ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path);
|
||||
|
||||
/**
|
||||
* Get the type of the specified path
|
||||
* @return The type of the specified path or error code
|
||||
*/
|
||||
Result GetEntryType(FileSys::EntryType* out_entry_type, const std::string& path) const;
|
||||
ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const;
|
||||
|
||||
/**
|
||||
* Get the timestamp of the specified path
|
||||
* @return The timestamp of the specified path or error code
|
||||
*/
|
||||
Result GetFileTimeStampRaw(FileSys::FileTimeStampRaw* out_time_stamp_raw,
|
||||
const std::string& path) const;
|
||||
ResultVal<FileSys::FileTimeStampRaw> GetFileTimeStampRaw(const std::string& path) const;
|
||||
|
||||
private:
|
||||
FileSys::VirtualDir backing;
|
||||
|
@ -419,15 +419,14 @@ public:
|
||||
|
||||
LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode);
|
||||
|
||||
FileSys::VirtualFile vfs_file{};
|
||||
auto result = backend.OpenFile(&vfs_file, name, mode);
|
||||
if (result != ResultSuccess) {
|
||||
auto result = backend.OpenFile(name, mode);
|
||||
if (result.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(result.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
auto file = std::make_shared<IFile>(system, vfs_file);
|
||||
auto file = std::make_shared<IFile>(system, result.Unwrap());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -445,15 +444,14 @@ public:
|
||||
|
||||
LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags);
|
||||
|
||||
FileSys::VirtualDir vfs_dir{};
|
||||
auto result = backend.OpenDirectory(&vfs_dir, name);
|
||||
if (result != ResultSuccess) {
|
||||
auto result = backend.OpenDirectory(name);
|
||||
if (result.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(result.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
auto directory = std::make_shared<IDirectory>(system, vfs_dir);
|
||||
auto directory = std::make_shared<IDirectory>(system, result.Unwrap());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -466,17 +464,16 @@ public:
|
||||
|
||||
LOG_DEBUG(Service_FS, "called. file={}", name);
|
||||
|
||||
FileSys::EntryType vfs_entry_type{};
|
||||
auto result = backend.GetEntryType(&vfs_entry_type, name);
|
||||
if (result != ResultSuccess) {
|
||||
auto result = backend.GetEntryType(name);
|
||||
if (result.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(result.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(static_cast<u32>(vfs_entry_type));
|
||||
rb.Push<u32>(static_cast<u32>(*result));
|
||||
}
|
||||
|
||||
void Commit(HLERequestContext& ctx) {
|
||||
@ -508,17 +505,16 @@ public:
|
||||
|
||||
LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name);
|
||||
|
||||
FileSys::FileTimeStampRaw vfs_timestamp{};
|
||||
auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name);
|
||||
if (result != ResultSuccess) {
|
||||
auto result = backend.GetFileTimeStampRaw(name);
|
||||
if (result.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(result.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(vfs_timestamp);
|
||||
rb.PushRaw(*result);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -576,15 +572,14 @@ private:
|
||||
}
|
||||
|
||||
void FindAllSaves(FileSys::SaveDataSpaceId space) {
|
||||
FileSys::VirtualDir save_root{};
|
||||
const auto result = fsc.OpenSaveDataSpace(&save_root, space);
|
||||
const auto save_root = fsc.OpenSaveDataSpace(space);
|
||||
|
||||
if (result != ResultSuccess || save_root == nullptr) {
|
||||
if (save_root.Failed() || *save_root == nullptr) {
|
||||
LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& type : save_root->GetSubdirectories()) {
|
||||
for (const auto& type : (*save_root)->GetSubdirectories()) {
|
||||
if (type->GetName() == "save") {
|
||||
for (const auto& save_id : type->GetSubdirectories()) {
|
||||
for (const auto& user_id : save_id->GetSubdirectories()) {
|
||||
@ -842,11 +837,9 @@ void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) {
|
||||
void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_FS, "called");
|
||||
|
||||
FileSys::VirtualDir sdmc_dir{};
|
||||
fsc.OpenSDMC(&sdmc_dir);
|
||||
|
||||
auto filesystem = std::make_shared<IFileSystem>(
|
||||
system, sdmc_dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard));
|
||||
auto filesystem =
|
||||
std::make_shared<IFileSystem>(system, fsc.OpenSDMC().Unwrap(),
|
||||
SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -863,8 +856,7 @@ void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(),
|
||||
uid[1], uid[0]);
|
||||
|
||||
FileSys::VirtualDir save_data_dir{};
|
||||
fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandUser, save_struct);
|
||||
fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandUser, save_struct);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -882,9 +874,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
|
||||
|
||||
LOG_INFO(Service_FS, "called.");
|
||||
|
||||
FileSys::VirtualDir dir{};
|
||||
auto result = fsc.OpenSaveData(&dir, parameters.space_id, parameters.attribute);
|
||||
if (result != ResultSuccess) {
|
||||
auto dir = fsc.OpenSaveData(parameters.space_id, parameters.attribute);
|
||||
if (dir.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
|
||||
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
|
||||
return;
|
||||
@ -908,8 +899,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
auto filesystem =
|
||||
std::make_shared<IFileSystem>(system, std::move(dir), SizeGetter::FromStorageId(fsc, id));
|
||||
auto filesystem = std::make_shared<IFileSystem>(system, std::move(dir.Unwrap()),
|
||||
SizeGetter::FromStorageId(fsc, id));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -979,7 +970,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) {
|
||||
|
||||
if (!romfs) {
|
||||
auto current_romfs = fsc.OpenRomFSCurrentProcess();
|
||||
if (!current_romfs) {
|
||||
if (current_romfs.Failed()) {
|
||||
// TODO (bunnei): Find the right error code to use here
|
||||
LOG_CRITICAL(Service_FS, "no file system interface available!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -987,7 +978,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
romfs = current_romfs;
|
||||
romfs = current_romfs.Unwrap();
|
||||
}
|
||||
|
||||
auto storage = std::make_shared<IStorage>(system, romfs);
|
||||
@ -1008,7 +999,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
|
||||
|
||||
auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data);
|
||||
|
||||
if (!data) {
|
||||
if (data.Failed()) {
|
||||
const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id);
|
||||
|
||||
if (archive != nullptr) {
|
||||
@ -1030,7 +1021,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
|
||||
const FileSys::PatchManager pm{title_id, fsc, content_provider};
|
||||
|
||||
auto storage = std::make_shared<IStorage>(
|
||||
system, pm.PatchRomFS(std::move(data), 0, FileSys::ContentRecordType::Data));
|
||||
system, pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -1060,7 +1051,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
|
||||
fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index,
|
||||
FileSys::ContentRecordType::Program);
|
||||
|
||||
if (!patched_romfs) {
|
||||
if (patched_romfs.Failed()) {
|
||||
// TODO: Find the right error code to use here
|
||||
LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index);
|
||||
|
||||
@ -1069,7 +1060,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs));
|
||||
auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs.Unwrap()));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
|
@ -65,19 +65,18 @@ void ARP_R::GetApplicationLaunchProperty(HLERequestContext& ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationLaunchProperty launch_property{};
|
||||
const auto res = manager.GetLaunchProperty(&launch_property, *title_id);
|
||||
const auto res = manager.GetLaunchProperty(*title_id);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
if (res.Failed()) {
|
||||
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
rb.Push(res.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(launch_property);
|
||||
rb.PushRaw(*res);
|
||||
}
|
||||
|
||||
void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) {
|
||||
@ -86,19 +85,18 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx
|
||||
|
||||
LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
|
||||
|
||||
ApplicationLaunchProperty launch_property{};
|
||||
const auto res = manager.GetLaunchProperty(&launch_property, title_id);
|
||||
const auto res = manager.GetLaunchProperty(title_id);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
if (res.Failed()) {
|
||||
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
rb.Push(res.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(launch_property);
|
||||
rb.PushRaw(*res);
|
||||
}
|
||||
|
||||
void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) {
|
||||
@ -115,17 +113,16 @@ void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<u8> nacp_data;
|
||||
const auto res = manager.GetControlProperty(&nacp_data, *title_id);
|
||||
const auto res = manager.GetControlProperty(*title_id);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
if (res.Failed()) {
|
||||
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
rb.Push(res.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.WriteBuffer(nacp_data);
|
||||
ctx.WriteBuffer(*res);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -137,17 +134,16 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(HLERequestContext& ct
|
||||
|
||||
LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
|
||||
|
||||
std::vector<u8> nacp_data;
|
||||
const auto res = manager.GetControlProperty(&nacp_data, title_id);
|
||||
const auto res = manager.GetControlProperty(title_id);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
if (res.Failed()) {
|
||||
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
rb.Push(res.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.WriteBuffer(nacp_data);
|
||||
ctx.WriteBuffer(*res);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
|
@ -15,8 +15,7 @@ ARPManager::ARPManager() = default;
|
||||
|
||||
ARPManager::~ARPManager() = default;
|
||||
|
||||
Result ARPManager::GetLaunchProperty(ApplicationLaunchProperty* out_launch_property,
|
||||
u64 title_id) const {
|
||||
ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const {
|
||||
if (title_id == 0) {
|
||||
return Glue::ResultInvalidProcessId;
|
||||
}
|
||||
@ -26,11 +25,10 @@ Result ARPManager::GetLaunchProperty(ApplicationLaunchProperty* out_launch_prope
|
||||
return Glue::ResultProcessIdNotRegistered;
|
||||
}
|
||||
|
||||
*out_launch_property = iter->second.launch;
|
||||
return ResultSuccess;
|
||||
return iter->second.launch;
|
||||
}
|
||||
|
||||
Result ARPManager::GetControlProperty(std::vector<u8>* out_control_property, u64 title_id) const {
|
||||
ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
|
||||
if (title_id == 0) {
|
||||
return Glue::ResultInvalidProcessId;
|
||||
}
|
||||
@ -40,8 +38,7 @@ Result ARPManager::GetControlProperty(std::vector<u8>* out_control_property, u64
|
||||
return Glue::ResultProcessIdNotRegistered;
|
||||
}
|
||||
|
||||
*out_control_property = iter->second.control;
|
||||
return ResultSuccess;
|
||||
return iter->second.control;
|
||||
}
|
||||
|
||||
Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
|
||||
|
@ -32,12 +32,12 @@ public:
|
||||
// Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was
|
||||
// previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or
|
||||
// ResultInvalidProcessId if the title ID is 0.
|
||||
Result GetLaunchProperty(ApplicationLaunchProperty* out_launch_property, u64 title_id) const;
|
||||
ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const;
|
||||
|
||||
// Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to
|
||||
// the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered
|
||||
// if it was never registered or ResultInvalidProcessId if the title ID is 0.
|
||||
Result GetControlProperty(std::vector<u8>* out_control_property, u64 title_id) const;
|
||||
ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const;
|
||||
|
||||
// Adds a new entry to the internal database with the provided parameters, returning
|
||||
// ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate
|
||||
|
@ -16,6 +16,22 @@ class EmulatedConsole;
|
||||
namespace Service::HID {
|
||||
class Controller_Touchscreen final : public ControllerBase {
|
||||
public:
|
||||
// This is nn::hid::TouchScreenModeForNx
|
||||
enum class TouchScreenModeForNx : u8 {
|
||||
UseSystemSetting,
|
||||
Finger,
|
||||
Heat2,
|
||||
};
|
||||
|
||||
// This is nn::hid::TouchScreenConfigurationForNx
|
||||
struct TouchScreenConfigurationForNx {
|
||||
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
|
||||
INSERT_PADDING_BYTES_NOINIT(0x7);
|
||||
INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved
|
||||
};
|
||||
static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
|
||||
"TouchScreenConfigurationForNx is an invalid size");
|
||||
|
||||
explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
||||
~Controller_Touchscreen() override;
|
||||
|
||||
|
@ -2368,7 +2368,7 @@ void Hid::GetNpadCommunicationMode(HLERequestContext& ctx) {
|
||||
|
||||
void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()};
|
||||
const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
|
||||
@ -2543,8 +2543,7 @@ public:
|
||||
|
||||
class HidSys final : public ServiceFramework<HidSys> {
|
||||
public:
|
||||
explicit HidSys(Core::System& system_)
|
||||
: ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"} {
|
||||
explicit HidSys(Core::System& system_) : ServiceFramework{system_, "hid:sys"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{31, nullptr, "SendKeyboardLockKeyEvent"},
|
||||
@ -2569,7 +2568,7 @@ public:
|
||||
{303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
|
||||
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
|
||||
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
|
||||
{306, &HidSys::GetLastActiveNpad, "GetLastActiveNpad"},
|
||||
{306, nullptr, "GetLastActiveNpad"},
|
||||
{307, nullptr, "GetNpadSystemExtStyle"},
|
||||
{308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
|
||||
{309, nullptr, "GetNpadFullKeyGripColor"},
|
||||
@ -2625,7 +2624,7 @@ public:
|
||||
{700, nullptr, "ActivateUniquePad"},
|
||||
{702, nullptr, "AcquireUniquePadConnectionEventHandle"},
|
||||
{703, nullptr, "GetUniquePadIds"},
|
||||
{751, &HidSys::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
||||
{751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
||||
{800, nullptr, "ListSixAxisSensorHandles"},
|
||||
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
|
||||
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
|
||||
@ -2651,7 +2650,7 @@ public:
|
||||
{830, nullptr, "SetNotificationLedPattern"},
|
||||
{831, nullptr, "SetNotificationLedPatternWithTimeout"},
|
||||
{832, nullptr, "PrepareHidsForNotificationWake"},
|
||||
{850, &HidSys::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
|
||||
{850, nullptr, "IsUsbFullKeyControllerEnabled"},
|
||||
{851, nullptr, "EnableUsbFullKeyController"},
|
||||
{852, nullptr, "IsUsbConnected"},
|
||||
{870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
|
||||
@ -2683,7 +2682,7 @@ public:
|
||||
{1150, nullptr, "SetTouchScreenMagnification"},
|
||||
{1151, nullptr, "GetTouchScreenFirmwareVersion"},
|
||||
{1152, nullptr, "SetTouchScreenDefaultConfiguration"},
|
||||
{1153, &HidSys::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
|
||||
{1153, nullptr, "GetTouchScreenDefaultConfiguration"},
|
||||
{1154, nullptr, "IsFirmwareAvailableForNotification"},
|
||||
{1155, nullptr, "SetForceHandheldStyleVibration"},
|
||||
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
|
||||
@ -2750,8 +2749,6 @@ public:
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
|
||||
}
|
||||
|
||||
private:
|
||||
@ -2763,66 +2760,17 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void GetLastActiveNpad(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_HID, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(Core::HID::NpadIdType::Handheld);
|
||||
}
|
||||
|
||||
void GetUniquePadsFromNpad(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
|
||||
|
||||
const s64 total_entries = 0;
|
||||
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()));
|
||||
rb.Push(total_entries);
|
||||
}
|
||||
|
||||
void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void 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 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);
|
||||
}
|
||||
|
||||
Kernel::KEvent* joy_detach_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
};
|
||||
|
||||
void LoopProcess(Core::System& system) {
|
||||
|
@ -357,8 +357,7 @@ public:
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result MapProcessCodeMemory(VAddr* out_map_location, Kernel::KProcess* process, VAddr base_addr,
|
||||
u64 size) {
|
||||
ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) {
|
||||
auto& page_table{process->GetPageTable()};
|
||||
VAddr addr{};
|
||||
|
||||
@ -373,21 +372,20 @@ public:
|
||||
R_TRY(result);
|
||||
|
||||
if (ValidateRegionForMap(page_table, addr, size)) {
|
||||
*out_map_location = addr;
|
||||
return ResultSuccess;
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_INSUFFICIENT_ADDRESS_SPACE;
|
||||
}
|
||||
|
||||
Result MapNro(VAddr* out_map_location, Kernel::KProcess* process, VAddr nro_addr,
|
||||
std::size_t nro_size, VAddr bss_addr, std::size_t bss_size, std::size_t size) {
|
||||
ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size,
|
||||
VAddr bss_addr, std::size_t bss_size, std::size_t size) {
|
||||
for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
|
||||
auto& page_table{process->GetPageTable()};
|
||||
VAddr addr{};
|
||||
|
||||
R_TRY(MapProcessCodeMemory(&addr, process, nro_addr, nro_size));
|
||||
CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size));
|
||||
|
||||
if (bss_size) {
|
||||
auto block_guard = detail::ScopeExit([&] {
|
||||
@ -413,8 +411,7 @@ public:
|
||||
}
|
||||
|
||||
if (ValidateRegionForMap(page_table, addr, size)) {
|
||||
*out_map_location = addr;
|
||||
return ResultSuccess;
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,9 +437,9 @@ public:
|
||||
CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
|
||||
nro_header.segment_headers[DATA_INDEX].memory_size);
|
||||
|
||||
R_TRY(process->GetPageTable().SetProcessMemoryPermission(
|
||||
CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
|
||||
text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute));
|
||||
R_TRY(process->GetPageTable().SetProcessMemoryPermission(
|
||||
CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
|
||||
ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read));
|
||||
|
||||
return process->GetPageTable().SetProcessMemoryPermission(
|
||||
@ -545,32 +542,31 @@ public:
|
||||
}
|
||||
|
||||
// Map memory for the NRO
|
||||
VAddr map_location{};
|
||||
const auto map_result{MapNro(&map_location, system.ApplicationProcess(), nro_address,
|
||||
nro_size, bss_address, bss_size, nro_size + bss_size)};
|
||||
if (map_result != ResultSuccess) {
|
||||
const auto map_result{MapNro(system.ApplicationProcess(), nro_address, nro_size,
|
||||
bss_address, bss_size, nro_size + bss_size)};
|
||||
if (map_result.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(map_result);
|
||||
rb.Push(map_result.Code());
|
||||
}
|
||||
|
||||
// Load the NRO into the mapped memory
|
||||
if (const auto result{
|
||||
LoadNro(system.ApplicationProcess(), header, nro_address, map_location)};
|
||||
LoadNro(system.ApplicationProcess(), header, nro_address, *map_result)};
|
||||
result.IsError()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(map_result.Code());
|
||||
}
|
||||
|
||||
// Track the loaded NRO
|
||||
nro.insert_or_assign(map_location,
|
||||
NROInfo{hash, map_location, nro_size, bss_address, bss_size,
|
||||
nro.insert_or_assign(*map_result,
|
||||
NROInfo{hash, *map_result, nro_size, bss_address, bss_size,
|
||||
header.segment_headers[TEXT_INDEX].memory_size,
|
||||
header.segment_headers[RO_INDEX].memory_size,
|
||||
header.segment_headers[DATA_INDEX].memory_size, nro_address});
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(map_location);
|
||||
rb.Push(*map_result);
|
||||
}
|
||||
|
||||
Result UnmapNro(const NROInfo& info) {
|
||||
@ -578,19 +574,19 @@ public:
|
||||
auto& page_table{system.ApplicationProcess()->GetPageTable()};
|
||||
|
||||
if (info.bss_size != 0) {
|
||||
R_TRY(page_table.UnmapCodeMemory(
|
||||
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||
info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address,
|
||||
info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||
}
|
||||
|
||||
R_TRY(page_table.UnmapCodeMemory(
|
||||
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||
info.nro_address + info.text_size + info.ro_size,
|
||||
info.src_addr + info.text_size + info.ro_size, info.data_size,
|
||||
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||
R_TRY(page_table.UnmapCodeMemory(
|
||||
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||
info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size,
|
||||
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||
R_TRY(page_table.UnmapCodeMemory(
|
||||
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||
info.nro_address, info.src_addr, info.text_size,
|
||||
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||
return ResultSuccess;
|
||||
|
@ -101,14 +101,20 @@ private:
|
||||
|
||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||
|
||||
const auto default_miis{manager.GetDefault(source_flag)};
|
||||
if (default_miis.size() > 0) {
|
||||
ctx.WriteBuffer(SerializeArray(default_miis));
|
||||
const auto result{manager.GetDefault(source_flag)};
|
||||
if (result.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
if (result->size() > 0) {
|
||||
ctx.WriteBuffer(SerializeArray(*result));
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(static_cast<u32>(default_miis.size()));
|
||||
rb.Push<u32>(static_cast<u32>(result->size()));
|
||||
}
|
||||
|
||||
void Get1(HLERequestContext& ctx) {
|
||||
@ -117,10 +123,15 @@ private:
|
||||
|
||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||
|
||||
const auto default_miis{manager.GetDefault(source_flag)};
|
||||
const auto result{manager.GetDefault(source_flag)};
|
||||
if (result.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<CharInfo> values;
|
||||
for (const auto& element : default_miis) {
|
||||
for (const auto& element : *result) {
|
||||
values.emplace_back(element.info);
|
||||
}
|
||||
|
||||
@ -128,7 +139,7 @@ private:
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(static_cast<u32>(default_miis.size()));
|
||||
rb.Push<u32>(static_cast<u32>(result->size()));
|
||||
}
|
||||
|
||||
void UpdateLatest(HLERequestContext& ctx) {
|
||||
@ -138,17 +149,16 @@ private:
|
||||
|
||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||
|
||||
CharInfo new_char_info{};
|
||||
const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)};
|
||||
if (result != ResultSuccess) {
|
||||
const auto result{manager.UpdateLatest(info, source_flag)};
|
||||
if (result.Failed()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(result.Code());
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw<CharInfo>(new_char_info);
|
||||
rb.PushRaw<CharInfo>(*result);
|
||||
}
|
||||
|
||||
void BuildRandom(HLERequestContext& ctx) {
|
||||
|
@ -409,7 +409,8 @@ u32 MiiManager::GetCount(SourceFlag source_flag) const {
|
||||
return static_cast<u32>(count);
|
||||
}
|
||||
|
||||
Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag) {
|
||||
ResultVal<CharInfo> MiiManager::UpdateLatest([[maybe_unused]] const CharInfo& info,
|
||||
SourceFlag source_flag) {
|
||||
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
|
||||
return ERROR_CANNOT_FIND_ENTRY;
|
||||
}
|
||||
@ -671,7 +672,7 @@ bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const {
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
std::vector<MiiInfoElement> MiiManager::GetDefault(SourceFlag source_flag) {
|
||||
ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) {
|
||||
std::vector<MiiInfoElement> result;
|
||||
|
||||
if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
|
||||
|
@ -19,12 +19,12 @@ public:
|
||||
bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
|
||||
bool IsFullDatabase() const;
|
||||
u32 GetCount(SourceFlag source_flag) const;
|
||||
Result UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag);
|
||||
ResultVal<CharInfo> UpdateLatest(const CharInfo& info, SourceFlag source_flag);
|
||||
CharInfo BuildRandom(Age age, Gender gender, Race race);
|
||||
CharInfo BuildDefault(std::size_t index);
|
||||
CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
|
||||
bool ValidateV3Info(const Ver3StoreData& mii_v3) const;
|
||||
std::vector<MiiInfoElement> GetDefault(SourceFlag source_flag);
|
||||
ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag);
|
||||
Result GetIndex(const CharInfo& info, u32& index);
|
||||
|
||||
// This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData
|
||||
|
@ -392,25 +392,24 @@ void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestConte
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto supported_languages = rp.Pop<u32>();
|
||||
|
||||
u8 desired_language{};
|
||||
const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages);
|
||||
if (res == ResultSuccess) {
|
||||
const auto res = GetApplicationDesiredLanguage(supported_languages);
|
||||
if (res.Succeeded()) {
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(desired_language);
|
||||
rb.Push<u32>(*res);
|
||||
} else {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
rb.Push(res.Code());
|
||||
}
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language,
|
||||
const u32 supported_languages) {
|
||||
ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage(
|
||||
const u32 supported_languages) {
|
||||
LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
|
||||
|
||||
// Get language code from settings
|
||||
const auto language_code =
|
||||
Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue()));
|
||||
Set::GetLanguageCodeFromIndex(Settings::values.language_index.GetValue());
|
||||
|
||||
// Convert to application language, get priority list
|
||||
const auto application_language = ConvertToApplicationLanguage(language_code);
|
||||
@ -431,8 +430,7 @@ Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desir
|
||||
for (const auto lang : *priority_list) {
|
||||
const auto supported_flag = GetSupportedLanguageFlag(lang);
|
||||
if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
|
||||
*out_desired_language = static_cast<u8>(lang);
|
||||
return ResultSuccess;
|
||||
return static_cast<u8>(lang);
|
||||
}
|
||||
}
|
||||
|
||||
@ -446,20 +444,19 @@ void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto application_language = rp.Pop<u8>();
|
||||
|
||||
u64 language_code{};
|
||||
const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language);
|
||||
if (res == ResultSuccess) {
|
||||
const auto res = ConvertApplicationLanguageToLanguageCode(application_language);
|
||||
if (res.Succeeded()) {
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(language_code);
|
||||
rb.Push(*res);
|
||||
} else {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
rb.Push(res.Code());
|
||||
}
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||
u64* out_language_code, u8 application_language) {
|
||||
ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||
u8 application_language) {
|
||||
const auto language_code =
|
||||
ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
|
||||
if (language_code == std::nullopt) {
|
||||
@ -467,8 +464,7 @@ Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||
return Service::NS::ResultApplicationLanguageNotFound;
|
||||
}
|
||||
|
||||
*out_language_code = static_cast<u64>(*language_code);
|
||||
return ResultSuccess;
|
||||
return static_cast<u64>(*language_code);
|
||||
}
|
||||
|
||||
IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
|
||||
@ -622,13 +618,12 @@ void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequ
|
||||
static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
std::vector<u8> nacp_data{};
|
||||
const auto parameters{rp.PopRaw<RequestParameters>()};
|
||||
const auto result =
|
||||
system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id);
|
||||
const auto nacp_data{system.GetARPManager().GetControlProperty(parameters.application_id)};
|
||||
const auto result = nacp_data ? ResultSuccess : ResultUnknown;
|
||||
|
||||
if (result == ResultSuccess) {
|
||||
ctx.WriteBuffer(nacp_data.data(), nacp_data.size());
|
||||
if (nacp_data) {
|
||||
ctx.WriteBuffer(nacp_data->data(), nacp_data->size());
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
|
@ -28,9 +28,8 @@ public:
|
||||
explicit IApplicationManagerInterface(Core::System& system_);
|
||||
~IApplicationManagerInterface() override;
|
||||
|
||||
Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages);
|
||||
Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code,
|
||||
u8 application_language);
|
||||
ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages);
|
||||
ResultVal<u64> ConvertApplicationLanguageToLanguageCode(u8 application_language);
|
||||
|
||||
private:
|
||||
void GetApplicationControlData(HLERequestContext& ctx);
|
||||
|
@ -449,7 +449,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
|
||||
case NativeWindowScalingMode::ScaleToWindow:
|
||||
case NativeWindowScalingMode::ScaleCrop:
|
||||
case NativeWindowScalingMode::NoScaleCrop:
|
||||
case NativeWindowScalingMode::PreserveAspectRatio:
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Service_Nvnflinger, "unknown scaling mode {}", scaling_mode);
|
||||
|
@ -183,7 +183,7 @@ std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
|
||||
return layer->GetBinderId();
|
||||
}
|
||||
|
||||
Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) {
|
||||
ResultVal<Kernel::KReadableEvent*> Nvnflinger::FindVsyncEvent(u64 display_id) {
|
||||
const auto lock_guard = Lock();
|
||||
auto* const display = FindDisplay(display_id);
|
||||
|
||||
@ -191,7 +191,7 @@ Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64
|
||||
return VI::ResultNotFound;
|
||||
}
|
||||
|
||||
return display->GetVSyncEvent(out_vsync_event);
|
||||
return display->GetVSyncEvent();
|
||||
}
|
||||
|
||||
VI::Display* Nvnflinger::FindDisplay(u64 display_id) {
|
||||
|
@ -82,7 +82,7 @@ public:
|
||||
///
|
||||
/// If an invalid display ID is provided, then VI::ResultNotFound is returned.
|
||||
/// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned.
|
||||
[[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id);
|
||||
[[nodiscard]] ResultVal<Kernel::KReadableEvent*> FindVsyncEvent(u64 display_id);
|
||||
|
||||
/// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
|
||||
/// finished.
|
||||
|
@ -41,7 +41,6 @@ enum class NativeWindowScalingMode : s32 {
|
||||
ScaleToWindow = 1,
|
||||
ScaleCrop = 2,
|
||||
NoScaleCrop = 3,
|
||||
PreserveAspectRatio = 4,
|
||||
};
|
||||
|
||||
/// Transform parameter for QueueBuffer
|
||||
|
@ -8,16 +8,15 @@
|
||||
|
||||
namespace Service::OLSC {
|
||||
|
||||
class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> {
|
||||
class OLSC final : public ServiceFramework<OLSC> {
|
||||
public:
|
||||
explicit IOlscServiceForApplication(Core::System& system_)
|
||||
: ServiceFramework{system_, "olsc:u"} {
|
||||
explicit OLSC(Core::System& system_) : ServiceFramework{system_, "olsc:u"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IOlscServiceForApplication::Initialize, "Initialize"},
|
||||
{0, &OLSC::Initialize, "Initialize"},
|
||||
{10, nullptr, "VerifySaveDataBackupLicenseAsync"},
|
||||
{13, &IOlscServiceForApplication::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
|
||||
{14, &IOlscServiceForApplication::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
|
||||
{13, &OLSC::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
|
||||
{14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
|
||||
{15, nullptr, "SetCustomData"},
|
||||
{16, nullptr, "DeleteSaveDataBackupSetting"},
|
||||
{18, nullptr, "GetSaveDataBackupInfoCache"},
|
||||
@ -73,155 +72,10 @@ private:
|
||||
bool initialized{};
|
||||
};
|
||||
|
||||
class INativeHandleHolder final : public ServiceFramework<INativeHandleHolder> {
|
||||
public:
|
||||
explicit INativeHandleHolder(Core::System& system_)
|
||||
: ServiceFramework{system_, "INativeHandleHolder"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetNativeHandle"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> {
|
||||
public:
|
||||
explicit ITransferTaskListController(Core::System& system_)
|
||||
: ServiceFramework{system_, "ITransferTaskListController"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Unknown0"},
|
||||
{1, nullptr, "Unknown1"},
|
||||
{2, nullptr, "Unknown2"},
|
||||
{3, nullptr, "Unknown3"},
|
||||
{4, nullptr, "Unknown4"},
|
||||
{5, &ITransferTaskListController::GetNativeHandleHolder , "GetNativeHandleHolder"},
|
||||
{6, nullptr, "Unknown6"},
|
||||
{7, nullptr, "Unknown7"},
|
||||
{8, nullptr, "GetRemoteStorageController"},
|
||||
{9, &ITransferTaskListController::GetNativeHandleHolder, "GetNativeHandleHolder2"},
|
||||
{10, nullptr, "Unknown10"},
|
||||
{11, nullptr, "Unknown11"},
|
||||
{12, nullptr, "Unknown12"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{14, nullptr, "Unknown14"},
|
||||
{15, nullptr, "Unknown15"},
|
||||
{16, nullptr, "Unknown16"},
|
||||
{17, nullptr, "Unknown17"},
|
||||
{18, nullptr, "Unknown18"},
|
||||
{19, nullptr, "Unknown19"},
|
||||
{20, nullptr, "Unknown20"},
|
||||
{21, nullptr, "Unknown21"},
|
||||
{22, nullptr, "Unknown22"},
|
||||
{23, nullptr, "Unknown23"},
|
||||
{24, nullptr, "Unknown24"},
|
||||
{25, nullptr, "Unknown25"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void GetNativeHandleHolder(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_OLSC, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<INativeHandleHolder>(system);
|
||||
}
|
||||
};
|
||||
|
||||
class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> {
|
||||
public:
|
||||
explicit IOlscServiceForSystemService(Core::System& system_)
|
||||
: ServiceFramework{system_, "olsc:s"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IOlscServiceForSystemService::OpenTransferTaskListController, "OpenTransferTaskListController"},
|
||||
{1, nullptr, "OpenRemoteStorageController"},
|
||||
{2, nullptr, "OpenDaemonController"},
|
||||
{10, nullptr, "Unknown10"},
|
||||
{11, nullptr, "Unknown11"},
|
||||
{12, nullptr, "Unknown12"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{100, nullptr, "ListLastTransferTaskErrorInfo"},
|
||||
{101, nullptr, "GetLastErrorInfoCount"},
|
||||
{102, nullptr, "RemoveLastErrorInfoOld"},
|
||||
{103, nullptr, "GetLastErrorInfo"},
|
||||
{104, nullptr, "GetLastErrorEventHolder"},
|
||||
{105, nullptr, "GetLastTransferTaskErrorInfo"},
|
||||
{200, nullptr, "GetDataTransferPolicyInfo"},
|
||||
{201, nullptr, "RemoveDataTransferPolicyInfo"},
|
||||
{202, nullptr, "UpdateDataTransferPolicyOld"},
|
||||
{203, nullptr, "UpdateDataTransferPolicy"},
|
||||
{204, nullptr, "CleanupDataTransferPolicyInfo"},
|
||||
{205, nullptr, "RequestDataTransferPolicy"},
|
||||
{300, nullptr, "GetAutoTransferSeriesInfo"},
|
||||
{301, nullptr, "UpdateAutoTransferSeriesInfo"},
|
||||
{400, nullptr, "CleanupSaveDataArchiveInfoType1"},
|
||||
{900, nullptr, "CleanupTransferTask"},
|
||||
{902, nullptr, "CleanupSeriesInfoType0"},
|
||||
{903, nullptr, "CleanupSaveDataArchiveInfoType0"},
|
||||
{904, nullptr, "CleanupApplicationAutoTransferSetting"},
|
||||
{905, nullptr, "CleanupErrorHistory"},
|
||||
{906, nullptr, "SetLastError"},
|
||||
{907, nullptr, "AddSaveDataArchiveInfoType0"},
|
||||
{908, nullptr, "RemoveSeriesInfoType0"},
|
||||
{909, nullptr, "GetSeriesInfoType0"},
|
||||
{910, nullptr, "RemoveLastErrorInfo"},
|
||||
{911, nullptr, "CleanupSeriesInfoType1"},
|
||||
{912, nullptr, "RemoveSeriesInfoType1"},
|
||||
{913, nullptr, "GetSeriesInfoType1"},
|
||||
{1000, nullptr, "UpdateIssueOld"},
|
||||
{1010, nullptr, "Unknown1010"},
|
||||
{1011, nullptr, "ListIssueInfoOld"},
|
||||
{1012, nullptr, "GetIssueOld"},
|
||||
{1013, nullptr, "GetIssue2Old"},
|
||||
{1014, nullptr, "GetIssue3Old"},
|
||||
{1020, nullptr, "RepairIssueOld"},
|
||||
{1021, nullptr, "RepairIssueWithUserIdOld"},
|
||||
{1022, nullptr, "RepairIssue2Old"},
|
||||
{1023, nullptr, "RepairIssue3Old"},
|
||||
{1024, nullptr, "Unknown1024"},
|
||||
{1100, nullptr, "UpdateIssue"},
|
||||
{1110, nullptr, "Unknown1110"},
|
||||
{1111, nullptr, "ListIssueInfo"},
|
||||
{1112, nullptr, "GetIssue"},
|
||||
{1113, nullptr, "GetIssue2"},
|
||||
{1114, nullptr, "GetIssue3"},
|
||||
{1120, nullptr, "RepairIssue"},
|
||||
{1121, nullptr, "RepairIssueWithUserId"},
|
||||
{1122, nullptr, "RepairIssue2"},
|
||||
{1123, nullptr, "RepairIssue3"},
|
||||
{1124, nullptr, "Unknown1124"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void OpenTransferTaskListController(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_OLSC, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<ITransferTaskListController>(system);
|
||||
}
|
||||
};
|
||||
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
|
||||
server_manager->RegisterNamedService("olsc:u",
|
||||
std::make_shared<IOlscServiceForApplication>(system));
|
||||
server_manager->RegisterNamedService("olsc:s",
|
||||
std::make_shared<IOlscServiceForSystemService>(system));
|
||||
|
||||
server_manager->RegisterNamedService("olsc:u", std::make_shared<OLSC>(system));
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/pctl/pctl.h"
|
||||
#include "core/hle/service/pctl/pctl_module.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
@ -25,8 +24,7 @@ constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
|
||||
class IParentalControlService final : public ServiceFramework<IParentalControlService> {
|
||||
public:
|
||||
explicit IParentalControlService(Core::System& system_, Capability capability_)
|
||||
: ServiceFramework{system_, "IParentalControlService"}, capability{capability_},
|
||||
service_context{system_, "IParentalControlService"} {
|
||||
: ServiceFramework{system_, "IParentalControlService"}, capability{capability_} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, &IParentalControlService::Initialize, "Initialize"},
|
||||
@ -35,7 +33,7 @@ public:
|
||||
{1003, nullptr, "ConfirmResumeApplicationPermission"},
|
||||
{1004, nullptr, "ConfirmSnsPostPermission"},
|
||||
{1005, nullptr, "ConfirmSystemSettingsPermission"},
|
||||
{1006, &IParentalControlService::IsRestrictionTemporaryUnlocked, "IsRestrictionTemporaryUnlocked"},
|
||||
{1006, nullptr, "IsRestrictionTemporaryUnlocked"},
|
||||
{1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
|
||||
{1008, nullptr, "EnterRestrictedSystemSettings"},
|
||||
{1009, nullptr, "LeaveRestrictedSystemSettings"},
|
||||
@ -49,14 +47,14 @@ public:
|
||||
{1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"},
|
||||
{1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"},
|
||||
{1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"},
|
||||
{1032, &IParentalControlService::GetSafetyLevel, "GetSafetyLevel"},
|
||||
{1032, nullptr, "GetSafetyLevel"},
|
||||
{1033, nullptr, "SetSafetyLevel"},
|
||||
{1034, nullptr, "GetSafetyLevelSettings"},
|
||||
{1035, &IParentalControlService::GetCurrentSettings, "GetCurrentSettings"},
|
||||
{1035, nullptr, "GetCurrentSettings"},
|
||||
{1036, nullptr, "SetCustomSafetyLevelSettings"},
|
||||
{1037, nullptr, "GetDefaultRatingOrganization"},
|
||||
{1038, nullptr, "SetDefaultRatingOrganization"},
|
||||
{1039, &IParentalControlService::GetFreeCommunicationApplicationListCount, "GetFreeCommunicationApplicationListCount"},
|
||||
{1039, nullptr, "GetFreeCommunicationApplicationListCount"},
|
||||
{1042, nullptr, "AddToFreeCommunicationApplicationList"},
|
||||
{1043, nullptr, "DeleteSettings"},
|
||||
{1044, nullptr, "GetFreeCommunicationApplicationList"},
|
||||
@ -78,7 +76,7 @@ public:
|
||||
{1206, nullptr, "GetPinCodeLength"},
|
||||
{1207, nullptr, "GetPinCodeChangedEvent"},
|
||||
{1208, nullptr, "GetPinCode"},
|
||||
{1403, &IParentalControlService::IsPairingActive, "IsPairingActive"},
|
||||
{1403, nullptr, "IsPairingActive"},
|
||||
{1406, nullptr, "GetSettingsLastUpdated"},
|
||||
{1411, nullptr, "GetPairingAccountInfo"},
|
||||
{1421, nullptr, "GetAccountNickname"},
|
||||
@ -86,18 +84,18 @@ public:
|
||||
{1425, nullptr, "RequestPostEvents"},
|
||||
{1426, nullptr, "GetPostEventInterval"},
|
||||
{1427, nullptr, "SetPostEventInterval"},
|
||||
{1432, &IParentalControlService::GetSynchronizationEvent, "GetSynchronizationEvent"},
|
||||
{1432, nullptr, "GetSynchronizationEvent"},
|
||||
{1451, nullptr, "StartPlayTimer"},
|
||||
{1452, nullptr, "StopPlayTimer"},
|
||||
{1453, nullptr, "IsPlayTimerEnabled"},
|
||||
{1454, nullptr, "GetPlayTimerRemainingTime"},
|
||||
{1455, nullptr, "IsRestrictedByPlayTimer"},
|
||||
{1456, &IParentalControlService::GetPlayTimerSettings, "GetPlayTimerSettings"},
|
||||
{1457, &IParentalControlService::GetPlayTimerEventToRequestSuspension, "GetPlayTimerEventToRequestSuspension"},
|
||||
{1458, &IParentalControlService::IsPlayTimerAlarmDisabled, "IsPlayTimerAlarmDisabled"},
|
||||
{1456, nullptr, "GetPlayTimerSettings"},
|
||||
{1457, nullptr, "GetPlayTimerEventToRequestSuspension"},
|
||||
{1458, nullptr, "IsPlayTimerAlarmDisabled"},
|
||||
{1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
|
||||
{1472, nullptr, "CancelNetworkRequest"},
|
||||
{1473, &IParentalControlService::GetUnlinkedEvent, "GetUnlinkedEvent"},
|
||||
{1473, nullptr, "GetUnlinkedEvent"},
|
||||
{1474, nullptr, "ClearUnlinkedEvent"},
|
||||
{1601, nullptr, "DisableAllFeatures"},
|
||||
{1602, nullptr, "PostEnableAllFeatures"},
|
||||
@ -133,12 +131,6 @@ public:
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
|
||||
synchronization_event =
|
||||
service_context.CreateEvent("IParentalControlService::SynchronizationEvent");
|
||||
unlinked_event = service_context.CreateEvent("IParentalControlService::UnlinkedEvent");
|
||||
request_suspension_event =
|
||||
service_context.CreateEvent("IParentalControlService::RequestSuspensionEvent");
|
||||
}
|
||||
|
||||
private:
|
||||
@ -236,17 +228,6 @@ private:
|
||||
states.free_communication = true;
|
||||
}
|
||||
|
||||
void IsRestrictionTemporaryUnlocked(HLERequestContext& ctx) {
|
||||
const bool is_temporary_unlocked = false;
|
||||
|
||||
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
|
||||
is_temporary_unlocked);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(is_temporary_unlocked);
|
||||
}
|
||||
|
||||
void ConfirmStereoVisionPermission(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PCTL, "called");
|
||||
states.stereo_vision = true;
|
||||
@ -287,34 +268,6 @@ private:
|
||||
rb.Push(pin_code[0] != '\0');
|
||||
}
|
||||
|
||||
void GetSafetyLevel(HLERequestContext& ctx) {
|
||||
const u32 safety_level = 0;
|
||||
|
||||
LOG_WARNING(Service_PCTL, "(STUBBED) called, safety_level={}", safety_level);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(safety_level);
|
||||
}
|
||||
|
||||
void GetCurrentSettings(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_PCTL, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(restriction_settings);
|
||||
}
|
||||
|
||||
void GetFreeCommunicationApplicationListCount(HLERequestContext& ctx) {
|
||||
const u32 count = 4;
|
||||
|
||||
LOG_WARNING(Service_PCTL, "(STUBBED) called, count={}", count);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PCTL, "called");
|
||||
|
||||
@ -347,61 +300,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void IsPairingActive(HLERequestContext& ctx) {
|
||||
const bool is_pairing_active = false;
|
||||
|
||||
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_pairing_active={}", is_pairing_active);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(is_pairing_active);
|
||||
}
|
||||
|
||||
void GetSynchronizationEvent(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_PCTL, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(synchronization_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void GetPlayTimerSettings(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_PCTL, "(STUBBED) called");
|
||||
|
||||
const PlayTimerSettings timer_settings{};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 15};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(timer_settings);
|
||||
}
|
||||
|
||||
void GetPlayTimerEventToRequestSuspension(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_PCTL, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(request_suspension_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void IsPlayTimerAlarmDisabled(HLERequestContext& ctx) {
|
||||
const bool is_play_timer_alarm_disabled = false;
|
||||
|
||||
LOG_INFO(Service_PCTL, "called, is_play_timer_alarm_disabled={}",
|
||||
is_play_timer_alarm_disabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(is_play_timer_alarm_disabled);
|
||||
}
|
||||
|
||||
void GetUnlinkedEvent(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_PCTL, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(unlinked_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void SetStereoVisionRestriction(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto can_use = rp.Pop<bool>();
|
||||
@ -466,30 +364,10 @@ private:
|
||||
bool disabled{};
|
||||
};
|
||||
|
||||
// This is nn::pctl::RestrictionSettings
|
||||
struct RestrictionSettings {
|
||||
u8 rating_age;
|
||||
bool sns_post_restriction;
|
||||
bool free_communication_restriction;
|
||||
};
|
||||
static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size.");
|
||||
|
||||
// This is nn::pctl::PlayTimerSettings
|
||||
struct PlayTimerSettings {
|
||||
std::array<u32, 13> settings;
|
||||
};
|
||||
static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size.");
|
||||
|
||||
States states{};
|
||||
ParentalControlSettings settings{};
|
||||
RestrictionSettings restriction_settings{};
|
||||
std::array<char, 8> pin_code{};
|
||||
Capability capability{};
|
||||
|
||||
Kernel::KEvent* synchronization_event;
|
||||
Kernel::KEvent* unlinked_event;
|
||||
Kernel::KEvent* request_suspension_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
};
|
||||
|
||||
void Module::Interface::CreateService(HLERequestContext& ctx) {
|
||||
|
@ -102,17 +102,16 @@ Result ServerManager::RegisterNamedService(const std::string& service_name,
|
||||
m_system.ServiceManager().RegisterService(service_name, max_sessions, handler)));
|
||||
|
||||
// Get the registered port.
|
||||
Kernel::KPort* port{};
|
||||
ASSERT(
|
||||
R_SUCCEEDED(m_system.ServiceManager().GetServicePort(std::addressof(port), service_name)));
|
||||
auto port = m_system.ServiceManager().GetServicePort(service_name);
|
||||
ASSERT(port.Succeeded());
|
||||
|
||||
// Open a new reference to the server port.
|
||||
port->GetServerPort().Open();
|
||||
(*port)->GetServerPort().Open();
|
||||
|
||||
// Begin tracking the server port.
|
||||
{
|
||||
std::scoped_lock ll{m_list_mutex};
|
||||
m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler));
|
||||
m_ports.emplace(std::addressof((*port)->GetServerPort()), std::move(handler));
|
||||
}
|
||||
|
||||
// Signal the wakeup event.
|
||||
|
@ -11,6 +11,66 @@
|
||||
|
||||
namespace Service::Set {
|
||||
namespace {
|
||||
constexpr std::array<LanguageCode, 18> available_language_codes = {{
|
||||
LanguageCode::JA,
|
||||
LanguageCode::EN_US,
|
||||
LanguageCode::FR,
|
||||
LanguageCode::DE,
|
||||
LanguageCode::IT,
|
||||
LanguageCode::ES,
|
||||
LanguageCode::ZH_CN,
|
||||
LanguageCode::KO,
|
||||
LanguageCode::NL,
|
||||
LanguageCode::PT,
|
||||
LanguageCode::RU,
|
||||
LanguageCode::ZH_TW,
|
||||
LanguageCode::EN_GB,
|
||||
LanguageCode::FR_CA,
|
||||
LanguageCode::ES_419,
|
||||
LanguageCode::ZH_HANS,
|
||||
LanguageCode::ZH_HANT,
|
||||
LanguageCode::PT_BR,
|
||||
}};
|
||||
|
||||
enum class KeyboardLayout : u64 {
|
||||
Japanese = 0,
|
||||
EnglishUs = 1,
|
||||
EnglishUsInternational = 2,
|
||||
EnglishUk = 3,
|
||||
French = 4,
|
||||
FrenchCa = 5,
|
||||
Spanish = 6,
|
||||
SpanishLatin = 7,
|
||||
German = 8,
|
||||
Italian = 9,
|
||||
Portuguese = 10,
|
||||
Russian = 11,
|
||||
Korean = 12,
|
||||
ChineseSimplified = 13,
|
||||
ChineseTraditional = 14,
|
||||
};
|
||||
|
||||
constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_layout{{
|
||||
{LanguageCode::JA, KeyboardLayout::Japanese},
|
||||
{LanguageCode::EN_US, KeyboardLayout::EnglishUs},
|
||||
{LanguageCode::FR, KeyboardLayout::French},
|
||||
{LanguageCode::DE, KeyboardLayout::German},
|
||||
{LanguageCode::IT, KeyboardLayout::Italian},
|
||||
{LanguageCode::ES, KeyboardLayout::Spanish},
|
||||
{LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified},
|
||||
{LanguageCode::KO, KeyboardLayout::Korean},
|
||||
{LanguageCode::NL, KeyboardLayout::EnglishUsInternational},
|
||||
{LanguageCode::PT, KeyboardLayout::Portuguese},
|
||||
{LanguageCode::RU, KeyboardLayout::Russian},
|
||||
{LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional},
|
||||
{LanguageCode::EN_GB, KeyboardLayout::EnglishUk},
|
||||
{LanguageCode::FR_CA, KeyboardLayout::FrenchCa},
|
||||
{LanguageCode::ES_419, KeyboardLayout::SpanishLatin},
|
||||
{LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified},
|
||||
{LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional},
|
||||
{LanguageCode::PT_BR, KeyboardLayout::Portuguese},
|
||||
}};
|
||||
|
||||
constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF;
|
||||
constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40;
|
||||
|
||||
@ -33,8 +93,7 @@ void GetAvailableLanguageCodesImpl(HLERequestContext& ctx, std::size_t max_entri
|
||||
}
|
||||
|
||||
void GetKeyCodeMapImpl(HLERequestContext& ctx) {
|
||||
const auto language_code =
|
||||
available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())];
|
||||
const auto language_code = available_language_codes[Settings::values.language_index.GetValue()];
|
||||
const auto key_code =
|
||||
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
|
||||
[=](const auto& element) { return element.first == language_code; });
|
||||
@ -103,7 +162,7 @@ void SET::GetQuestFlag(HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(static_cast<s32>(Settings::values.quest_flag.GetValue()));
|
||||
rb.Push(static_cast<u32>(Settings::values.quest_flag.GetValue()));
|
||||
}
|
||||
|
||||
void SET::GetLanguageCode(HLERequestContext& ctx) {
|
||||
@ -111,8 +170,7 @@ void SET::GetLanguageCode(HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(
|
||||
available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]);
|
||||
rb.PushEnum(available_language_codes[Settings::values.language_index.GetValue()]);
|
||||
}
|
||||
|
||||
void SET::GetRegionCode(HLERequestContext& ctx) {
|
||||
@ -120,7 +178,7 @@ void SET::GetRegionCode(HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(static_cast<u32>(Settings::values.region_index.GetValue()));
|
||||
rb.Push(Settings::values.region_index.GetValue());
|
||||
}
|
||||
|
||||
void SET::GetKeyCodeMap(HLERequestContext& ctx) {
|
||||
|
@ -32,67 +32,6 @@ enum class LanguageCode : u64 {
|
||||
ZH_HANT = 0x00746E61482D687A,
|
||||
PT_BR = 0x00000052422D7470,
|
||||
};
|
||||
|
||||
enum class KeyboardLayout : u64 {
|
||||
Japanese = 0,
|
||||
EnglishUs = 1,
|
||||
EnglishUsInternational = 2,
|
||||
EnglishUk = 3,
|
||||
French = 4,
|
||||
FrenchCa = 5,
|
||||
Spanish = 6,
|
||||
SpanishLatin = 7,
|
||||
German = 8,
|
||||
Italian = 9,
|
||||
Portuguese = 10,
|
||||
Russian = 11,
|
||||
Korean = 12,
|
||||
ChineseSimplified = 13,
|
||||
ChineseTraditional = 14,
|
||||
};
|
||||
|
||||
constexpr std::array<LanguageCode, 18> available_language_codes = {{
|
||||
LanguageCode::JA,
|
||||
LanguageCode::EN_US,
|
||||
LanguageCode::FR,
|
||||
LanguageCode::DE,
|
||||
LanguageCode::IT,
|
||||
LanguageCode::ES,
|
||||
LanguageCode::ZH_CN,
|
||||
LanguageCode::KO,
|
||||
LanguageCode::NL,
|
||||
LanguageCode::PT,
|
||||
LanguageCode::RU,
|
||||
LanguageCode::ZH_TW,
|
||||
LanguageCode::EN_GB,
|
||||
LanguageCode::FR_CA,
|
||||
LanguageCode::ES_419,
|
||||
LanguageCode::ZH_HANS,
|
||||
LanguageCode::ZH_HANT,
|
||||
LanguageCode::PT_BR,
|
||||
}};
|
||||
|
||||
static constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_layout{{
|
||||
{LanguageCode::JA, KeyboardLayout::Japanese},
|
||||
{LanguageCode::EN_US, KeyboardLayout::EnglishUs},
|
||||
{LanguageCode::FR, KeyboardLayout::French},
|
||||
{LanguageCode::DE, KeyboardLayout::German},
|
||||
{LanguageCode::IT, KeyboardLayout::Italian},
|
||||
{LanguageCode::ES, KeyboardLayout::Spanish},
|
||||
{LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified},
|
||||
{LanguageCode::KO, KeyboardLayout::Korean},
|
||||
{LanguageCode::NL, KeyboardLayout::EnglishUsInternational},
|
||||
{LanguageCode::PT, KeyboardLayout::Portuguese},
|
||||
{LanguageCode::RU, KeyboardLayout::Russian},
|
||||
{LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional},
|
||||
{LanguageCode::EN_GB, KeyboardLayout::EnglishUk},
|
||||
{LanguageCode::FR_CA, KeyboardLayout::FrenchCa},
|
||||
{LanguageCode::ES_419, KeyboardLayout::SpanishLatin},
|
||||
{LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified},
|
||||
{LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional},
|
||||
{LanguageCode::PT_BR, KeyboardLayout::Portuguese},
|
||||
}};
|
||||
|
||||
LanguageCode GetLanguageCodeFromIndex(std::size_t idx);
|
||||
|
||||
class SET final : public ServiceFramework<SET> {
|
||||
|
@ -4,12 +4,10 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/file_sys/errors.h"
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/set/set.h"
|
||||
#include "core/hle/service/set/set_sys.h"
|
||||
|
||||
namespace Service::Set {
|
||||
@ -75,16 +73,6 @@ void GetFirmwareVersionImpl(HLERequestContext& ctx, GetFirmwareVersionType type)
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
language_code_setting = rp.PopEnum<LanguageCode>();
|
||||
|
||||
LOG_INFO(Service_SET, "called, language_code={}", language_code_setting);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1);
|
||||
@ -95,113 +83,21 @@ void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) {
|
||||
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2);
|
||||
}
|
||||
|
||||
void SET_SYS::GetAccountSettings(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(account_settings);
|
||||
}
|
||||
|
||||
void SET_SYS::SetAccountSettings(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
account_settings = rp.PopRaw<AccountSettings>();
|
||||
|
||||
LOG_INFO(Service_SET, "called, account_settings_flags={}", account_settings.flags);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetEulaVersions(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called");
|
||||
|
||||
ctx.WriteBuffer(eula_versions);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(static_cast<u32>(eula_versions.size()));
|
||||
}
|
||||
|
||||
void SET_SYS::SetEulaVersions(HLERequestContext& ctx) {
|
||||
const auto elements = ctx.GetReadBufferNumElements<EulaVersion>();
|
||||
const auto buffer_data = ctx.ReadBuffer();
|
||||
|
||||
LOG_INFO(Service_SET, "called, elements={}", elements);
|
||||
|
||||
eula_versions.resize(elements);
|
||||
for (std::size_t index = 0; index < elements; index++) {
|
||||
const std::size_t start_index = index * sizeof(EulaVersion);
|
||||
memcpy(eula_versions.data() + start_index, buffer_data.data() + start_index,
|
||||
sizeof(EulaVersion));
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetColorSetId(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(color_set);
|
||||
}
|
||||
|
||||
void SET_SYS::SetColorSetId(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
color_set = rp.PopEnum<ColorSet>();
|
||||
|
||||
LOG_DEBUG(Service_SET, "called, color_set={}", color_set);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetNotificationSettings(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 8};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(notification_settings);
|
||||
}
|
||||
|
||||
void SET_SYS::SetNotificationSettings(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
notification_settings = rp.PopRaw<NotificationSettings>();
|
||||
|
||||
LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}",
|
||||
notification_settings.flags.raw, notification_settings.volume,
|
||||
notification_settings.start_time.hour, notification_settings.start_time.minute,
|
||||
notification_settings.stop_time.hour, notification_settings.stop_time.minute);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetAccountNotificationSettings(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called");
|
||||
|
||||
ctx.WriteBuffer(account_notifications);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(static_cast<u32>(account_notifications.size()));
|
||||
}
|
||||
|
||||
void SET_SYS::SetAccountNotificationSettings(HLERequestContext& ctx) {
|
||||
const auto elements = ctx.GetReadBufferNumElements<AccountNotificationSettings>();
|
||||
const auto buffer_data = ctx.ReadBuffer();
|
||||
|
||||
LOG_INFO(Service_SET, "called, elements={}", elements);
|
||||
|
||||
account_notifications.resize(elements);
|
||||
for (std::size_t index = 0; index < elements; index++) {
|
||||
const std::size_t start_index = index * sizeof(AccountNotificationSettings);
|
||||
memcpy(account_notifications.data() + start_index, buffer_data.data() + start_index,
|
||||
sizeof(AccountNotificationSettings));
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
@ -281,218 +177,17 @@ void SET_SYS::GetSettingsItemValue(HLERequestContext& ctx) {
|
||||
rb.Push(response);
|
||||
}
|
||||
|
||||
void SET_SYS::GetTvSettings(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(tv_settings);
|
||||
}
|
||||
|
||||
void SET_SYS::SetTvSettings(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
tv_settings = rp.PopRaw<TvSettings>();
|
||||
|
||||
LOG_INFO(Service_SET,
|
||||
"called, flags={}, cmu_mode={}, constrast_ratio={}, hdmi_content_type={}, "
|
||||
"rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}",
|
||||
tv_settings.flags.raw, tv_settings.cmu_mode, tv_settings.constrast_ratio,
|
||||
tv_settings.hdmi_content_type, tv_settings.rgb_range, tv_settings.tv_gama,
|
||||
tv_settings.tv_resolution, tv_settings.tv_underscan);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetQuestFlag(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(QuestFlag::Retail);
|
||||
}
|
||||
|
||||
void SET_SYS::SetRegionCode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
region_code = rp.PopEnum<RegionCode>();
|
||||
|
||||
LOG_INFO(Service_SET, "called, region_code={}", region_code);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetPrimaryAlbumStorage(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(PrimaryAlbumStorage::SdCard);
|
||||
}
|
||||
|
||||
void SET_SYS::GetSleepSettings(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 5};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(sleep_settings);
|
||||
}
|
||||
|
||||
void SET_SYS::SetSleepSettings(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
sleep_settings = rp.PopRaw<SleepSettings>();
|
||||
|
||||
LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}",
|
||||
sleep_settings.flags.raw, sleep_settings.handheld_sleep_plan,
|
||||
sleep_settings.console_sleep_plan);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetInitialLaunchSettings(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(launch_settings);
|
||||
}
|
||||
|
||||
void SET_SYS::SetInitialLaunchSettings(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
launch_settings = rp.PopRaw<InitialLaunchSettings>();
|
||||
|
||||
LOG_INFO(Service_SET, "called, flags={}, timestamp={}", launch_settings.flags.raw,
|
||||
launch_settings.timestamp.time_point);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetDeviceNickName(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
ctx.WriteBuffer(::Settings::values.device_name.GetValue());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::SetDeviceNickName(HLERequestContext& ctx) {
|
||||
const std::string device_name = Common::StringFromBuffer(ctx.ReadBuffer());
|
||||
|
||||
LOG_INFO(Service_SET, "called, device_name={}", device_name);
|
||||
|
||||
::Settings::values.device_name = device_name;
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetProductModel(HLERequestContext& ctx) {
|
||||
const u32 product_model = 1;
|
||||
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called, product_model={}", product_model);
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(product_model);
|
||||
}
|
||||
|
||||
void SET_SYS::GetMiiAuthorId(HLERequestContext& ctx) {
|
||||
const auto author_id = Common::UUID::MakeDefault();
|
||||
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called, author_id={}", author_id.FormattedString());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(author_id);
|
||||
}
|
||||
|
||||
void SET_SYS::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
|
||||
u8 auto_update_flag{};
|
||||
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called, auto_update_flag={}", auto_update_flag);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(auto_update_flag);
|
||||
}
|
||||
|
||||
void SET_SYS::GetBatteryPercentageFlag(HLERequestContext& ctx) {
|
||||
u8 battery_percentage_flag{1};
|
||||
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called, battery_percentage_flag={}",
|
||||
battery_percentage_flag);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(battery_percentage_flag);
|
||||
}
|
||||
|
||||
void SET_SYS::GetErrorReportSharePermission(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(ErrorReportSharePermission::Denied);
|
||||
}
|
||||
|
||||
void SET_SYS::GetAppletLaunchFlags(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(applet_launch_flag);
|
||||
}
|
||||
|
||||
void SET_SYS::SetAppletLaunchFlags(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
applet_launch_flag = rp.Pop<u32>();
|
||||
|
||||
LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void SET_SYS::GetKeyboardLayout(HLERequestContext& ctx) {
|
||||
const auto language_code =
|
||||
available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
|
||||
const auto key_code =
|
||||
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
|
||||
[=](const auto& element) { return element.first == language_code; });
|
||||
|
||||
KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs;
|
||||
if (key_code != language_to_layout.end()) {
|
||||
selected_keyboard_layout = key_code->second;
|
||||
}
|
||||
|
||||
LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(static_cast<u32>(selected_keyboard_layout));
|
||||
}
|
||||
|
||||
void SET_SYS::GetChineseTraditionalInputMethod(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(ChineseTraditionalInputMethod::Unknown0);
|
||||
}
|
||||
|
||||
void SET_SYS::GetFieldTestingFlag(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(false);
|
||||
}
|
||||
|
||||
SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &SET_SYS::SetLanguageCode, "SetLanguageCode"},
|
||||
{0, nullptr, "SetLanguageCode"},
|
||||
{1, nullptr, "SetNetworkSettings"},
|
||||
{2, nullptr, "GetNetworkSettings"},
|
||||
{3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"},
|
||||
@ -508,35 +203,35 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
{14, nullptr, "SetExternalSteadyClockSourceId"},
|
||||
{15, nullptr, "GetUserSystemClockContext"},
|
||||
{16, nullptr, "SetUserSystemClockContext"},
|
||||
{17, &SET_SYS::GetAccountSettings, "GetAccountSettings"},
|
||||
{18, &SET_SYS::SetAccountSettings, "SetAccountSettings"},
|
||||
{17, nullptr, "GetAccountSettings"},
|
||||
{18, nullptr, "SetAccountSettings"},
|
||||
{19, nullptr, "GetAudioVolume"},
|
||||
{20, nullptr, "SetAudioVolume"},
|
||||
{21, &SET_SYS::GetEulaVersions, "GetEulaVersions"},
|
||||
{22, &SET_SYS::SetEulaVersions, "SetEulaVersions"},
|
||||
{21, nullptr, "GetEulaVersions"},
|
||||
{22, nullptr, "SetEulaVersions"},
|
||||
{23, &SET_SYS::GetColorSetId, "GetColorSetId"},
|
||||
{24, &SET_SYS::SetColorSetId, "SetColorSetId"},
|
||||
{25, nullptr, "GetConsoleInformationUploadFlag"},
|
||||
{26, nullptr, "SetConsoleInformationUploadFlag"},
|
||||
{27, nullptr, "GetAutomaticApplicationDownloadFlag"},
|
||||
{28, nullptr, "SetAutomaticApplicationDownloadFlag"},
|
||||
{29, &SET_SYS::GetNotificationSettings, "GetNotificationSettings"},
|
||||
{30, &SET_SYS::SetNotificationSettings, "SetNotificationSettings"},
|
||||
{31, &SET_SYS::GetAccountNotificationSettings, "GetAccountNotificationSettings"},
|
||||
{32, &SET_SYS::SetAccountNotificationSettings, "SetAccountNotificationSettings"},
|
||||
{29, nullptr, "GetNotificationSettings"},
|
||||
{30, nullptr, "SetNotificationSettings"},
|
||||
{31, nullptr, "GetAccountNotificationSettings"},
|
||||
{32, nullptr, "SetAccountNotificationSettings"},
|
||||
{35, nullptr, "GetVibrationMasterVolume"},
|
||||
{36, nullptr, "SetVibrationMasterVolume"},
|
||||
{37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"},
|
||||
{38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"},
|
||||
{39, &SET_SYS::GetTvSettings, "GetTvSettings"},
|
||||
{40, &SET_SYS::SetTvSettings, "SetTvSettings"},
|
||||
{39, nullptr, "GetTvSettings"},
|
||||
{40, nullptr, "SetTvSettings"},
|
||||
{41, nullptr, "GetEdid"},
|
||||
{42, nullptr, "SetEdid"},
|
||||
{43, nullptr, "GetAudioOutputMode"},
|
||||
{44, nullptr, "SetAudioOutputMode"},
|
||||
{45, nullptr, "IsForceMuteOnHeadphoneRemoved"},
|
||||
{46, nullptr, "SetForceMuteOnHeadphoneRemoved"},
|
||||
{47, &SET_SYS::GetQuestFlag, "GetQuestFlag"},
|
||||
{47, nullptr, "GetQuestFlag"},
|
||||
{48, nullptr, "SetQuestFlag"},
|
||||
{49, nullptr, "GetDataDeletionSettings"},
|
||||
{50, nullptr, "SetDataDeletionSettings"},
|
||||
@ -546,13 +241,13 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
{54, nullptr, "SetDeviceTimeZoneLocationName"},
|
||||
{55, nullptr, "GetWirelessCertificationFileSize"},
|
||||
{56, nullptr, "GetWirelessCertificationFile"},
|
||||
{57, &SET_SYS::SetRegionCode, "SetRegionCode"},
|
||||
{57, nullptr, "SetRegionCode"},
|
||||
{58, nullptr, "GetNetworkSystemClockContext"},
|
||||
{59, nullptr, "SetNetworkSystemClockContext"},
|
||||
{60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{62, nullptr, "GetDebugModeFlag"},
|
||||
{63, &SET_SYS::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"},
|
||||
{63, nullptr, "GetPrimaryAlbumStorage"},
|
||||
{64, nullptr, "SetPrimaryAlbumStorage"},
|
||||
{65, nullptr, "GetUsb30EnableFlag"},
|
||||
{66, nullptr, "SetUsb30EnableFlag"},
|
||||
@ -560,15 +255,15 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
{68, nullptr, "GetSerialNumber"},
|
||||
{69, nullptr, "GetNfcEnableFlag"},
|
||||
{70, nullptr, "SetNfcEnableFlag"},
|
||||
{71, &SET_SYS::GetSleepSettings, "GetSleepSettings"},
|
||||
{72, &SET_SYS::SetSleepSettings, "SetSleepSettings"},
|
||||
{71, nullptr, "GetSleepSettings"},
|
||||
{72, nullptr, "SetSleepSettings"},
|
||||
{73, nullptr, "GetWirelessLanEnableFlag"},
|
||||
{74, nullptr, "SetWirelessLanEnableFlag"},
|
||||
{75, &SET_SYS::GetInitialLaunchSettings, "GetInitialLaunchSettings"},
|
||||
{76, &SET_SYS::SetInitialLaunchSettings, "SetInitialLaunchSettings"},
|
||||
{75, nullptr, "GetInitialLaunchSettings"},
|
||||
{76, nullptr, "SetInitialLaunchSettings"},
|
||||
{77, &SET_SYS::GetDeviceNickName, "GetDeviceNickName"},
|
||||
{78, &SET_SYS::SetDeviceNickName, "SetDeviceNickName"},
|
||||
{79, &SET_SYS::GetProductModel, "GetProductModel"},
|
||||
{78, nullptr, "SetDeviceNickName"},
|
||||
{79, nullptr, "GetProductModel"},
|
||||
{80, nullptr, "GetLdnChannel"},
|
||||
{81, nullptr, "SetLdnChannel"},
|
||||
{82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"},
|
||||
@ -579,16 +274,16 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
{87, nullptr, "SetPtmFuelGaugeParameter"},
|
||||
{88, nullptr, "GetBluetoothEnableFlag"},
|
||||
{89, nullptr, "SetBluetoothEnableFlag"},
|
||||
{90, &SET_SYS::GetMiiAuthorId, "GetMiiAuthorId"},
|
||||
{90, nullptr, "GetMiiAuthorId"},
|
||||
{91, nullptr, "SetShutdownRtcValue"},
|
||||
{92, nullptr, "GetShutdownRtcValue"},
|
||||
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
|
||||
{94, nullptr, "GetFatalDirtyFlags"},
|
||||
{95, &SET_SYS::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
|
||||
{95, nullptr, "GetAutoUpdateEnableFlag"},
|
||||
{96, nullptr, "SetAutoUpdateEnableFlag"},
|
||||
{97, nullptr, "GetNxControllerSettings"},
|
||||
{98, nullptr, "SetNxControllerSettings"},
|
||||
{99, &SET_SYS::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
|
||||
{99, nullptr, "GetBatteryPercentageFlag"},
|
||||
{100, nullptr, "SetBatteryPercentageFlag"},
|
||||
{101, nullptr, "GetExternalRtcResetFlag"},
|
||||
{102, nullptr, "SetExternalRtcResetFlag"},
|
||||
@ -613,10 +308,10 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
{121, nullptr, "SetPushNotificationActivityModeOnSleep"},
|
||||
{122, nullptr, "GetServiceDiscoveryControlSettings"},
|
||||
{123, nullptr, "SetServiceDiscoveryControlSettings"},
|
||||
{124, &SET_SYS::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
|
||||
{124, nullptr, "GetErrorReportSharePermission"},
|
||||
{125, nullptr, "SetErrorReportSharePermission"},
|
||||
{126, &SET_SYS::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
|
||||
{127, &SET_SYS::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
|
||||
{126, nullptr, "GetAppletLaunchFlags"},
|
||||
{127, nullptr, "SetAppletLaunchFlags"},
|
||||
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
|
||||
{129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"},
|
||||
{130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"},
|
||||
@ -625,7 +320,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
{133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"},
|
||||
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
|
||||
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
|
||||
{136, &SET_SYS::GetKeyboardLayout, "GetKeyboardLayout"},
|
||||
{136, nullptr, "GetKeyboardLayout"},
|
||||
{137, nullptr, "SetKeyboardLayout"},
|
||||
{138, nullptr, "GetWebInspectorFlag"},
|
||||
{139, nullptr, "GetAllowedSslHosts"},
|
||||
@ -659,7 +354,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
{167, nullptr, "SetUsb30DeviceEnableFlag"},
|
||||
{168, nullptr, "GetThemeId"},
|
||||
{169, nullptr, "SetThemeId"},
|
||||
{170, &SET_SYS::GetChineseTraditionalInputMethod, "GetChineseTraditionalInputMethod"},
|
||||
{170, nullptr, "GetChineseTraditionalInputMethod"},
|
||||
{171, nullptr, "SetChineseTraditionalInputMethod"},
|
||||
{172, nullptr, "GetPtmCycleCountReliability"},
|
||||
{173, nullptr, "SetPtmCycleCountReliability"},
|
||||
@ -690,16 +385,12 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||
{198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"},
|
||||
{199, nullptr, "GetButtonConfigRegisteredSettings"},
|
||||
{200, nullptr, "SetButtonConfigRegisteredSettings"},
|
||||
{201, &SET_SYS::GetFieldTestingFlag, "GetFieldTestingFlag"},
|
||||
{201, nullptr, "GetFieldTestingFlag"},
|
||||
{202, nullptr, "SetFieldTestingFlag"},
|
||||
{203, nullptr, "GetPanelCrcMode"},
|
||||
{204, nullptr, "SetPanelCrcMode"},
|
||||
{205, nullptr, "GetNxControllerSettingsEx"},
|
||||
{206, nullptr, "SetNxControllerSettingsEx"},
|
||||
{207, nullptr, "GetHearingProtectionSafeguardFlag"},
|
||||
{208, nullptr, "SetHearingProtectionSafeguardFlag"},
|
||||
{209, nullptr, "GetHearingProtectionSafeguardRemainingTime"},
|
||||
{210, nullptr, "SetHearingProtectionSafeguardRemainingTime"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -3,9 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
@ -25,331 +23,15 @@ private:
|
||||
BasicBlack = 1,
|
||||
};
|
||||
|
||||
/// Indicates the current console is a retail or kiosk unit
|
||||
enum class QuestFlag : u8 {
|
||||
Retail = 0,
|
||||
Kiosk = 1,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::TvResolution
|
||||
enum class TvResolution : u32 {
|
||||
Auto,
|
||||
Resolution1080p,
|
||||
Resolution720p,
|
||||
Resolution480p,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::HdmiContentType
|
||||
enum class HdmiContentType : u32 {
|
||||
None,
|
||||
Graphics,
|
||||
Cinema,
|
||||
Photo,
|
||||
Game,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::RgbRange
|
||||
enum class RgbRange : u32 {
|
||||
Auto,
|
||||
Full,
|
||||
Limited,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::CmuMode
|
||||
enum class CmuMode : u32 {
|
||||
None,
|
||||
ColorInvert,
|
||||
HighContrast,
|
||||
GrayScale,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::PrimaryAlbumStorage
|
||||
enum class PrimaryAlbumStorage : u32 {
|
||||
Nand,
|
||||
SdCard,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::NotificationVolume
|
||||
enum class NotificationVolume : u32 {
|
||||
Mute,
|
||||
Low,
|
||||
High,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::ChineseTraditionalInputMethod
|
||||
enum class ChineseTraditionalInputMethod : u32 {
|
||||
Unknown0 = 0,
|
||||
Unknown1 = 1,
|
||||
Unknown2 = 2,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::ErrorReportSharePermission
|
||||
enum class ErrorReportSharePermission : u32 {
|
||||
NotConfirmed,
|
||||
Granted,
|
||||
Denied,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::FriendPresenceOverlayPermission
|
||||
enum class FriendPresenceOverlayPermission : u8 {
|
||||
NotConfirmed,
|
||||
NoDisplay,
|
||||
FavoriteFriends,
|
||||
Friends,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::HandheldSleepPlan
|
||||
enum class HandheldSleepPlan : u32 {
|
||||
Sleep1Min,
|
||||
Sleep3Min,
|
||||
Sleep5Min,
|
||||
Sleep10Min,
|
||||
Sleep30Min,
|
||||
Never,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::ConsoleSleepPlan
|
||||
enum class ConsoleSleepPlan : u32 {
|
||||
Sleep1Hour,
|
||||
Sleep2Hour,
|
||||
Sleep3Hour,
|
||||
Sleep6Hour,
|
||||
Sleep12Hour,
|
||||
Never,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::RegionCode
|
||||
enum class RegionCode : u32 {
|
||||
Japan,
|
||||
Usa,
|
||||
Europe,
|
||||
Australia,
|
||||
HongKongTaiwanKorea,
|
||||
China,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::EulaVersionClockType
|
||||
enum class EulaVersionClockType : u32 {
|
||||
NetworkSystemClock,
|
||||
SteadyClock,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::SleepFlag
|
||||
struct SleepFlag {
|
||||
union {
|
||||
u32 raw{};
|
||||
|
||||
BitField<0, 1, u32> SleepsWhilePlayingMedia;
|
||||
BitField<1, 1, u32> WakesAtPowerStateChange;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(SleepFlag) == 4, "TvFlag is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::TvFlag
|
||||
struct TvFlag {
|
||||
union {
|
||||
u32 raw{};
|
||||
|
||||
BitField<0, 1, u32> Allows4k;
|
||||
BitField<1, 1, u32> Allows3d;
|
||||
BitField<2, 1, u32> AllowsCec;
|
||||
BitField<3, 1, u32> PreventsScreenBurnIn;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(TvFlag) == 4, "TvFlag is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::InitialLaunchFlag
|
||||
struct InitialLaunchFlag {
|
||||
union {
|
||||
u32 raw{};
|
||||
|
||||
BitField<0, 1, u32> InitialLaunchCompletionFlag;
|
||||
BitField<8, 1, u32> InitialLaunchUserAdditionFlag;
|
||||
BitField<16, 1, u32> InitialLaunchTimestampFlag;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(InitialLaunchFlag) == 4, "InitialLaunchFlag is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::NotificationFlag
|
||||
struct NotificationFlag {
|
||||
union {
|
||||
u32 raw{};
|
||||
|
||||
BitField<0, 1, u32> RingtoneFlag;
|
||||
BitField<1, 1, u32> DownloadCompletionFlag;
|
||||
BitField<8, 1, u32> EnablesNews;
|
||||
BitField<9, 1, u32> IncomingLampFlag;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(NotificationFlag) == 4, "NotificationFlag is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::AccountNotificationFlag
|
||||
struct AccountNotificationFlag {
|
||||
union {
|
||||
u32 raw{};
|
||||
|
||||
BitField<0, 1, u32> FriendOnlineFlag;
|
||||
BitField<1, 1, u32> FriendRequestFlag;
|
||||
BitField<8, 1, u32> CoralInvitationFlag;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(AccountNotificationFlag) == 4,
|
||||
"AccountNotificationFlag is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::TvSettings
|
||||
struct TvSettings {
|
||||
TvFlag flags;
|
||||
TvResolution tv_resolution;
|
||||
HdmiContentType hdmi_content_type;
|
||||
RgbRange rgb_range;
|
||||
CmuMode cmu_mode;
|
||||
u32 tv_underscan;
|
||||
f32 tv_gama;
|
||||
f32 constrast_ratio;
|
||||
};
|
||||
static_assert(sizeof(TvSettings) == 0x20, "TvSettings is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::NotificationTime
|
||||
struct NotificationTime {
|
||||
u32 hour;
|
||||
u32 minute;
|
||||
};
|
||||
static_assert(sizeof(NotificationTime) == 0x8, "NotificationTime is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::NotificationSettings
|
||||
struct NotificationSettings {
|
||||
NotificationFlag flags;
|
||||
NotificationVolume volume;
|
||||
NotificationTime start_time;
|
||||
NotificationTime stop_time;
|
||||
};
|
||||
static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::AccountSettings
|
||||
struct AccountSettings {
|
||||
u32 flags;
|
||||
};
|
||||
static_assert(sizeof(AccountSettings) == 0x4, "AccountSettings is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::AccountNotificationSettings
|
||||
struct AccountNotificationSettings {
|
||||
Common::UUID uid;
|
||||
AccountNotificationFlag flags;
|
||||
FriendPresenceOverlayPermission friend_presence_permission;
|
||||
FriendPresenceOverlayPermission friend_invitation_permission;
|
||||
INSERT_PADDING_BYTES(0x2);
|
||||
};
|
||||
static_assert(sizeof(AccountNotificationSettings) == 0x18,
|
||||
"AccountNotificationSettings is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::InitialLaunchSettings
|
||||
struct SleepSettings {
|
||||
SleepFlag flags;
|
||||
HandheldSleepPlan handheld_sleep_plan;
|
||||
ConsoleSleepPlan console_sleep_plan;
|
||||
};
|
||||
static_assert(sizeof(SleepSettings) == 0xc, "SleepSettings is incorrect size");
|
||||
|
||||
/// This is nn::settings::system::InitialLaunchSettings
|
||||
struct InitialLaunchSettings {
|
||||
InitialLaunchFlag flags;
|
||||
INSERT_PADDING_BYTES(0x4);
|
||||
Time::Clock::SteadyClockTimePoint timestamp;
|
||||
};
|
||||
static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size");
|
||||
|
||||
/// This is nn::settings::system::InitialLaunchSettings
|
||||
struct EulaVersion {
|
||||
u32 version;
|
||||
RegionCode region_code;
|
||||
EulaVersionClockType clock_type;
|
||||
INSERT_PADDING_BYTES(0x4);
|
||||
s64 posix_time;
|
||||
Time::Clock::SteadyClockTimePoint timestamp;
|
||||
};
|
||||
static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size");
|
||||
|
||||
void SetLanguageCode(HLERequestContext& ctx);
|
||||
void GetFirmwareVersion(HLERequestContext& ctx);
|
||||
void GetFirmwareVersion2(HLERequestContext& ctx);
|
||||
void GetAccountSettings(HLERequestContext& ctx);
|
||||
void SetAccountSettings(HLERequestContext& ctx);
|
||||
void GetEulaVersions(HLERequestContext& ctx);
|
||||
void SetEulaVersions(HLERequestContext& ctx);
|
||||
void GetColorSetId(HLERequestContext& ctx);
|
||||
void SetColorSetId(HLERequestContext& ctx);
|
||||
void GetNotificationSettings(HLERequestContext& ctx);
|
||||
void SetNotificationSettings(HLERequestContext& ctx);
|
||||
void GetAccountNotificationSettings(HLERequestContext& ctx);
|
||||
void SetAccountNotificationSettings(HLERequestContext& ctx);
|
||||
void GetSettingsItemValueSize(HLERequestContext& ctx);
|
||||
void GetSettingsItemValue(HLERequestContext& ctx);
|
||||
void GetTvSettings(HLERequestContext& ctx);
|
||||
void SetTvSettings(HLERequestContext& ctx);
|
||||
void GetQuestFlag(HLERequestContext& ctx);
|
||||
void SetRegionCode(HLERequestContext& ctx);
|
||||
void GetPrimaryAlbumStorage(HLERequestContext& ctx);
|
||||
void GetSleepSettings(HLERequestContext& ctx);
|
||||
void SetSleepSettings(HLERequestContext& ctx);
|
||||
void GetInitialLaunchSettings(HLERequestContext& ctx);
|
||||
void SetInitialLaunchSettings(HLERequestContext& ctx);
|
||||
void GetFirmwareVersion(HLERequestContext& ctx);
|
||||
void GetFirmwareVersion2(HLERequestContext& ctx);
|
||||
void GetColorSetId(HLERequestContext& ctx);
|
||||
void SetColorSetId(HLERequestContext& ctx);
|
||||
void GetDeviceNickName(HLERequestContext& ctx);
|
||||
void SetDeviceNickName(HLERequestContext& ctx);
|
||||
void GetProductModel(HLERequestContext& ctx);
|
||||
void GetMiiAuthorId(HLERequestContext& ctx);
|
||||
void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
|
||||
void GetBatteryPercentageFlag(HLERequestContext& ctx);
|
||||
void GetErrorReportSharePermission(HLERequestContext& ctx);
|
||||
void GetAppletLaunchFlags(HLERequestContext& ctx);
|
||||
void SetAppletLaunchFlags(HLERequestContext& ctx);
|
||||
void GetKeyboardLayout(HLERequestContext& ctx);
|
||||
void GetChineseTraditionalInputMethod(HLERequestContext& ctx);
|
||||
void GetFieldTestingFlag(HLERequestContext& ctx);
|
||||
|
||||
AccountSettings account_settings{
|
||||
.flags = {},
|
||||
};
|
||||
|
||||
ColorSet color_set = ColorSet::BasicWhite;
|
||||
|
||||
NotificationSettings notification_settings{
|
||||
.flags = {0x300},
|
||||
.volume = NotificationVolume::High,
|
||||
.start_time = {.hour = 9, .minute = 0},
|
||||
.stop_time = {.hour = 21, .minute = 0},
|
||||
};
|
||||
|
||||
std::vector<AccountNotificationSettings> account_notifications{};
|
||||
|
||||
TvSettings tv_settings{
|
||||
.flags = {0xc},
|
||||
.tv_resolution = TvResolution::Auto,
|
||||
.hdmi_content_type = HdmiContentType::Game,
|
||||
.rgb_range = RgbRange::Auto,
|
||||
.cmu_mode = CmuMode::None,
|
||||
.tv_underscan = {},
|
||||
.tv_gama = 1.0f,
|
||||
.constrast_ratio = 0.5f,
|
||||
};
|
||||
|
||||
InitialLaunchSettings launch_settings{
|
||||
.flags = {0x10001},
|
||||
.timestamp = {},
|
||||
};
|
||||
|
||||
SleepSettings sleep_settings{
|
||||
.flags = {0x3},
|
||||
.handheld_sleep_plan = HandheldSleepPlan::Sleep10Min,
|
||||
.console_sleep_plan = ConsoleSleepPlan::Sleep1Hour,
|
||||
};
|
||||
|
||||
u32 applet_launch_flag{};
|
||||
|
||||
std::vector<EulaVersion> eula_versions{};
|
||||
|
||||
RegionCode region_code;
|
||||
|
||||
LanguageCode language_code_setting;
|
||||
};
|
||||
|
||||
} // namespace Service::Set
|
||||
|
@ -52,7 +52,8 @@ static Result ValidateServiceName(const std::string& name) {
|
||||
|
||||
Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
|
||||
SessionRequestHandlerPtr handler) {
|
||||
R_TRY(ValidateServiceName(name));
|
||||
|
||||
CASCADE_CODE(ValidateServiceName(name));
|
||||
|
||||
std::scoped_lock lk{lock};
|
||||
if (registered_services.find(name) != registered_services.end()) {
|
||||
@ -76,7 +77,7 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
|
||||
}
|
||||
|
||||
Result ServiceManager::UnregisterService(const std::string& name) {
|
||||
R_TRY(ValidateServiceName(name));
|
||||
CASCADE_CODE(ValidateServiceName(name));
|
||||
|
||||
std::scoped_lock lk{lock};
|
||||
const auto iter = registered_services.find(name);
|
||||
@ -91,8 +92,8 @@ Result ServiceManager::UnregisterService(const std::string& name) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::string& name) {
|
||||
R_TRY(ValidateServiceName(name));
|
||||
ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) {
|
||||
CASCADE_CODE(ValidateServiceName(name));
|
||||
|
||||
std::scoped_lock lk{lock};
|
||||
auto it = service_ports.find(name);
|
||||
@ -101,8 +102,7 @@ Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::strin
|
||||
return Service::SM::ResultNotRegistered;
|
||||
}
|
||||
|
||||
*out_port = it->second;
|
||||
return ResultSuccess;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,34 +122,32 @@ void SM::Initialize(HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
void SM::GetService(HLERequestContext& ctx) {
|
||||
Kernel::KClientSession* client_session{};
|
||||
auto result = GetServiceImpl(&client_session, ctx);
|
||||
auto result = GetServiceImpl(ctx);
|
||||
if (ctx.GetIsDeferred()) {
|
||||
// Don't overwrite the command buffer.
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == ResultSuccess) {
|
||||
if (result.Succeeded()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
|
||||
rb.Push(result);
|
||||
rb.PushMoveObjects(client_session);
|
||||
rb.Push(result.Code());
|
||||
rb.PushMoveObjects(result.Unwrap());
|
||||
} else {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
rb.Push(result.Code());
|
||||
}
|
||||
}
|
||||
|
||||
void SM::GetServiceTipc(HLERequestContext& ctx) {
|
||||
Kernel::KClientSession* client_session{};
|
||||
auto result = GetServiceImpl(&client_session, ctx);
|
||||
auto result = GetServiceImpl(ctx);
|
||||
if (ctx.GetIsDeferred()) {
|
||||
// Don't overwrite the command buffer.
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
|
||||
rb.Push(result);
|
||||
rb.PushMoveObjects(result == ResultSuccess ? client_session : nullptr);
|
||||
rb.Push(result.Code());
|
||||
rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr);
|
||||
}
|
||||
|
||||
static std::string PopServiceName(IPC::RequestParser& rp) {
|
||||
@ -163,7 +161,7 @@ static std::string PopServiceName(IPC::RequestParser& rp) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx) {
|
||||
ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) {
|
||||
if (!ctx.GetManager()->GetIsInitializedForSm()) {
|
||||
return Service::SM::ResultInvalidClient;
|
||||
}
|
||||
@ -172,18 +170,18 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
|
||||
std::string name(PopServiceName(rp));
|
||||
|
||||
// Find the named port.
|
||||
Kernel::KPort* port{};
|
||||
auto port_result = service_manager.GetServicePort(&port, name);
|
||||
if (port_result == Service::SM::ResultInvalidServiceName) {
|
||||
auto port_result = service_manager.GetServicePort(name);
|
||||
if (port_result.Code() == Service::SM::ResultInvalidServiceName) {
|
||||
LOG_ERROR(Service_SM, "Invalid service name '{}'", name);
|
||||
return Service::SM::ResultInvalidServiceName;
|
||||
}
|
||||
|
||||
if (port_result != ResultSuccess) {
|
||||
if (port_result.Failed()) {
|
||||
LOG_INFO(Service_SM, "Waiting for service {} to become available", name);
|
||||
ctx.SetIsDeferred();
|
||||
return Service::SM::ResultNotRegistered;
|
||||
}
|
||||
auto& port = port_result.Unwrap();
|
||||
|
||||
// Create a new session.
|
||||
Kernel::KClientSession* session{};
|
||||
@ -194,8 +192,7 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
|
||||
|
||||
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
|
||||
|
||||
*out_client_session = session;
|
||||
return ResultSuccess;
|
||||
return session;
|
||||
}
|
||||
|
||||
void SM::RegisterService(HLERequestContext& ctx) {
|
||||
|
@ -42,7 +42,7 @@ private:
|
||||
void RegisterService(HLERequestContext& ctx);
|
||||
void UnregisterService(HLERequestContext& ctx);
|
||||
|
||||
Result GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx);
|
||||
ResultVal<Kernel::KClientSession*> GetServiceImpl(HLERequestContext& ctx);
|
||||
|
||||
ServiceManager& service_manager;
|
||||
Kernel::KernelCore& kernel;
|
||||
@ -55,7 +55,7 @@ public:
|
||||
|
||||
Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler);
|
||||
Result UnregisterService(const std::string& name);
|
||||
Result GetServicePort(Kernel::KPort** out_port, const std::string& name);
|
||||
ResultVal<Kernel::KPort*> GetServicePort(const std::string& name);
|
||||
|
||||
template <Common::DerivedFrom<SessionRequestHandler> T>
|
||||
std::shared_ptr<T> GetService(const std::string& service_name) const {
|
||||
|
@ -54,7 +54,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
static std::string ResolveImpl(const std::string& fqdn_in) {
|
||||
static ResultVal<std::string> ResolveImpl(const std::string& fqdn_in) {
|
||||
// The real implementation makes various substitutions.
|
||||
// For now we just return the string as-is, which is good enough when not
|
||||
// connecting to real Nintendo servers.
|
||||
@ -64,10 +64,13 @@ static std::string ResolveImpl(const std::string& fqdn_in) {
|
||||
|
||||
static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>& fqdn_out) {
|
||||
const auto res = ResolveImpl(fqdn_in);
|
||||
if (res.size() >= fqdn_out.size()) {
|
||||
if (res.Failed()) {
|
||||
return res.Code();
|
||||
}
|
||||
if (res->size() >= fqdn_out.size()) {
|
||||
return ResultOverflow;
|
||||
}
|
||||
std::memcpy(fqdn_out.data(), res.c_str(), res.size() + 1);
|
||||
std::memcpy(fqdn_out.data(), res->c_str(), res->size() + 1);
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,7 @@ enum class Errno : u32 {
|
||||
AGAIN = 11,
|
||||
INVAL = 22,
|
||||
MFILE = 24,
|
||||
PIPE = 32,
|
||||
MSGSIZE = 90,
|
||||
CONNABORTED = 103,
|
||||
CONNRESET = 104,
|
||||
NOTCONN = 107,
|
||||
TIMEDOUT = 110,
|
||||
|
@ -23,14 +23,10 @@ Errno Translate(Network::Errno value) {
|
||||
return Errno::INVAL;
|
||||
case Network::Errno::MFILE:
|
||||
return Errno::MFILE;
|
||||
case Network::Errno::PIPE:
|
||||
return Errno::PIPE;
|
||||
case Network::Errno::NOTCONN:
|
||||
return Errno::NOTCONN;
|
||||
case Network::Errno::TIMEDOUT:
|
||||
return Errno::TIMEDOUT;
|
||||
case Network::Errno::CONNABORTED:
|
||||
return Errno::CONNABORTED;
|
||||
case Network::Errno::CONNRESET:
|
||||
return Errno::CONNRESET;
|
||||
case Network::Errno::INPROGRESS:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user