Compare commits
1 Commits
android-42
...
android-27
Author | SHA1 | Date | |
---|---|---|---|
27c3d35f2f |
@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
[codespell]
|
[codespell]
|
||||||
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
|
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).
|
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!
|
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.
|
# /volatile:iso - Use strict standards-compliant volatile semantics.
|
||||||
# /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates
|
# /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: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
|
# /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
|
# /GT - Supports fiber safety for data allocated using static thread-local storage
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
@ -49,7 +48,6 @@ if (MSVC)
|
|||||||
/volatile:iso
|
/volatile:iso
|
||||||
/Zc:externConstexpr
|
/Zc:externConstexpr
|
||||||
/Zc:inline
|
/Zc:inline
|
||||||
/Zc:preprocessor
|
|
||||||
/Zc:throwingNew
|
/Zc:throwingNew
|
||||||
/GT
|
/GT
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ class LicenseAdapter(private val activity: AppCompatActivity, var licenses: List
|
|||||||
val context = YuzuApplication.appContext
|
val context = YuzuApplication.appContext
|
||||||
binding.textSettingName.text = context.getString(license.titleId)
|
binding.textSettingName.text = context.getString(license.titleId)
|
||||||
binding.textSettingDescription.text = context.getString(license.descriptionId)
|
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.text.Html
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import org.yuzu.yuzu_emu.databinding.PageSetupBinding
|
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.SetupPage
|
||||||
import org.yuzu.yuzu_emu.model.StepState
|
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
|
||||||
|
|
||||||
class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) :
|
class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) :
|
||||||
RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() {
|
RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() {
|
||||||
@ -32,7 +26,7 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
|||||||
holder.bind(pages[position])
|
holder.bind(pages[position])
|
||||||
|
|
||||||
inner class SetupPageViewHolder(val binding: PageSetupBinding) :
|
inner class SetupPageViewHolder(val binding: PageSetupBinding) :
|
||||||
RecyclerView.ViewHolder(binding.root), SetupCallback {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
lateinit var page: SetupPage
|
lateinit var page: SetupPage
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -41,12 +35,6 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
|||||||
|
|
||||||
fun bind(page: SetupPage) {
|
fun bind(page: SetupPage) {
|
||||||
this.page = page
|
this.page = page
|
||||||
|
|
||||||
if (page.stepCompleted.invoke() == StepState.COMPLETE) {
|
|
||||||
binding.buttonAction.visibility = View.INVISIBLE
|
|
||||||
binding.textConfirmation.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.icon.setImageDrawable(
|
binding.icon.setImageDrawable(
|
||||||
ResourcesCompat.getDrawable(
|
ResourcesCompat.getDrawable(
|
||||||
activity.resources,
|
activity.resources,
|
||||||
@ -74,15 +62,9 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
|||||||
MaterialButton.ICON_GRAVITY_END
|
MaterialButton.ICON_GRAVITY_END
|
||||||
}
|
}
|
||||||
setOnClickListener {
|
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)
|
val sliderBinding = DialogSliderBinding.inflate(inflater)
|
||||||
|
|
||||||
textSliderValue = sliderBinding.textValue
|
textSliderValue = sliderBinding.textValue
|
||||||
textSliderValue!!.text = String.format(
|
textSliderValue!!.text = sliderProgress.toString()
|
||||||
context.getString(R.string.value_with_units),
|
sliderBinding.textUnits.text = item.units
|
||||||
sliderProgress.toString(),
|
|
||||||
item.units
|
|
||||||
)
|
|
||||||
|
|
||||||
sliderBinding.slider.apply {
|
sliderBinding.slider.apply {
|
||||||
valueFrom = item.min.toFloat()
|
valueFrom = item.min.toFloat()
|
||||||
@ -219,11 +216,7 @@ class SettingsAdapter(
|
|||||||
value = sliderProgress.toFloat()
|
value = sliderProgress.toFloat()
|
||||||
addOnChangeListener { _: Slider, value: Float, _: Boolean ->
|
addOnChangeListener { _: Slider, value: Float, _: Boolean ->
|
||||||
sliderProgress = value.toInt()
|
sliderProgress = value.toInt()
|
||||||
textSliderValue!!.text = String.format(
|
textSliderValue!!.text = sliderProgress.toString()
|
||||||
context.getString(R.string.value_with_units),
|
|
||||||
sliderProgress.toString(),
|
|
||||||
item.units
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,6 +225,10 @@ class SettingsAdapter(
|
|||||||
.setView(sliderBinding.root)
|
.setView(sliderBinding.root)
|
||||||
.setPositiveButton(android.R.string.ok, this)
|
.setPositiveButton(android.R.string.ok, this)
|
||||||
.setNegativeButton(android.R.string.cancel, defaultCancelListener)
|
.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()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,17 +25,12 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
|||||||
binding.textSettingDescription.setText(item.descriptionId)
|
binding.textSettingDescription.setText(item.descriptionId)
|
||||||
binding.textSettingDescription.visibility = View.VISIBLE
|
binding.textSettingDescription.visibility = View.VISIBLE
|
||||||
} else {
|
} 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) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -23,9 +23,6 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
|||||||
} else {
|
} else {
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
binding.textSettingValue.visibility = View.GONE
|
|
||||||
|
|
||||||
setStyle(setting.isEditable, binding)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -5,8 +5,6 @@ package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
|||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
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.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
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 onClick(clicked: View)
|
||||||
|
|
||||||
abstract override fun onLongClick(clicked: View): Boolean
|
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) {
|
override fun bind(item: SettingsItem) {
|
||||||
setting = item
|
setting = item
|
||||||
binding.textSettingName.setText(item.nameId)
|
binding.textSettingName.setText(item.nameId)
|
||||||
|
binding.textSettingDescription.visibility = View.VISIBLE
|
||||||
if (item.descriptionId != 0) {
|
if (item.descriptionId != 0) {
|
||||||
binding.textSettingDescription.setText(item.descriptionId)
|
binding.textSettingDescription.setText(item.descriptionId)
|
||||||
binding.textSettingDescription.visibility = View.VISIBLE
|
} else if (item is SingleChoiceSetting) {
|
||||||
} else {
|
val resMgr = binding.textSettingDescription.context.resources
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.textSettingValue.visibility = View.VISIBLE
|
|
||||||
if (item is SingleChoiceSetting) {
|
|
||||||
val resMgr = binding.textSettingValue.context.resources
|
|
||||||
val values = resMgr.getIntArray(item.valuesId)
|
val values = resMgr.getIntArray(item.valuesId)
|
||||||
for (i in values.indices) {
|
for (i in values.indices) {
|
||||||
if (values[i] == item.selectedValue) {
|
if (values[i] == item.selectedValue) {
|
||||||
binding.textSettingValue.text = resMgr.getStringArray(item.choicesId)[i]
|
binding.textSettingDescription.text = resMgr.getStringArray(item.choicesId)[i]
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (item is StringSingleChoiceSetting) {
|
} else if (item is StringSingleChoiceSetting) {
|
||||||
for (i in item.values!!.indices) {
|
for (i in item.values!!.indices) {
|
||||||
if (item.values[i] == item.selectedValue) {
|
if (item.values[i] == item.selectedValue) {
|
||||||
binding.textSettingValue.text = item.choices[i]
|
binding.textSettingDescription.text = item.choices[i]
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
setStyle(setting.isEditable, binding)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import org.yuzu.yuzu_emu.R
|
|
||||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
|
||||||
@ -23,14 +22,6 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
|
|||||||
} else {
|
} else {
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
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) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -22,7 +22,6 @@ class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAd
|
|||||||
} else {
|
} else {
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
binding.textSettingValue.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -25,12 +25,12 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
|
|||||||
binding.textSettingDescription.text = ""
|
binding.textSettingDescription.text = ""
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
binding.switchWidget.isChecked = setting.isChecked
|
||||||
binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean ->
|
binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean ->
|
||||||
adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked)
|
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) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -19,7 +19,6 @@ import androidx.core.content.ContextCompat
|
|||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.navigation.findNavController
|
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.databinding.FragmentSetupBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
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.SetupPage
|
||||||
import org.yuzu.yuzu_emu.model.StepState
|
|
||||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
import org.yuzu.yuzu_emu.utils.GameHelper
|
import org.yuzu.yuzu_emu.utils.GameHelper
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
|
||||||
|
|
||||||
class SetupFragment : Fragment() {
|
class SetupFragment : Fragment() {
|
||||||
private var _binding: FragmentSetupBinding? = null
|
private var _binding: FragmentSetupBinding? = null
|
||||||
@ -116,22 +112,14 @@ class SetupFragment : Fragment() {
|
|||||||
0,
|
0,
|
||||||
false,
|
false,
|
||||||
R.string.give_permission,
|
R.string.give_permission,
|
||||||
{
|
{ permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) },
|
||||||
notificationCallback = it
|
|
||||||
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
R.string.notification_warning,
|
R.string.notification_warning,
|
||||||
R.string.notification_warning_description,
|
R.string.notification_warning_description,
|
||||||
0,
|
0,
|
||||||
{
|
{
|
||||||
if (NotificationManagerCompat.from(requireContext())
|
NotificationManagerCompat.from(requireContext())
|
||||||
.areNotificationsEnabled()
|
.areNotificationsEnabled()
|
||||||
) {
|
|
||||||
StepState.COMPLETE
|
|
||||||
} else {
|
|
||||||
StepState.INCOMPLETE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -145,22 +133,12 @@ class SetupFragment : Fragment() {
|
|||||||
R.drawable.ic_add,
|
R.drawable.ic_add,
|
||||||
true,
|
true,
|
||||||
R.string.select_keys,
|
R.string.select_keys,
|
||||||
{
|
{ mainActivity.getProdKey.launch(arrayOf("*/*")) },
|
||||||
keyCallback = it
|
|
||||||
getProdKey.launch(arrayOf("*/*"))
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
R.string.install_prod_keys_warning,
|
R.string.install_prod_keys_warning,
|
||||||
R.string.install_prod_keys_warning_description,
|
R.string.install_prod_keys_warning_description,
|
||||||
R.string.install_prod_keys_warning_help,
|
R.string.install_prod_keys_warning_help,
|
||||||
{
|
{ File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() }
|
||||||
val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys")
|
|
||||||
if (file.exists()) {
|
|
||||||
StepState.COMPLETE
|
|
||||||
} else {
|
|
||||||
StepState.INCOMPLETE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
add(
|
add(
|
||||||
@ -172,8 +150,9 @@ class SetupFragment : Fragment() {
|
|||||||
true,
|
true,
|
||||||
R.string.add_games,
|
R.string.add_games,
|
||||||
{
|
{
|
||||||
gamesDirCallback = it
|
mainActivity.getGamesDirectory.launch(
|
||||||
getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data)
|
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
|
||||||
|
)
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
R.string.add_games_warning,
|
R.string.add_games_warning,
|
||||||
@ -184,11 +163,7 @@ class SetupFragment : Fragment() {
|
|||||||
PreferenceManager.getDefaultSharedPreferences(
|
PreferenceManager.getDefaultSharedPreferences(
|
||||||
YuzuApplication.appContext
|
YuzuApplication.appContext
|
||||||
)
|
)
|
||||||
if (preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()) {
|
preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()
|
||||||
StepState.COMPLETE
|
|
||||||
} else {
|
|
||||||
StepState.INCOMPLETE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -206,13 +181,6 @@ class SetupFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
homeViewModel.shouldPageForward.observe(viewLifecycleOwner) {
|
|
||||||
if (it) {
|
|
||||||
pageForward()
|
|
||||||
homeViewModel.setShouldPageForward(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.viewPager2.apply {
|
binding.viewPager2.apply {
|
||||||
adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages)
|
adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages)
|
||||||
offscreenPageLimit = 2
|
offscreenPageLimit = 2
|
||||||
@ -226,15 +194,15 @@ class SetupFragment : Fragment() {
|
|||||||
super.onPageSelected(position)
|
super.onPageSelected(position)
|
||||||
|
|
||||||
if (position == 1 && previousPosition == 0) {
|
if (position == 1 && previousPosition == 0) {
|
||||||
ViewUtils.showView(binding.buttonNext)
|
showView(binding.buttonNext)
|
||||||
ViewUtils.showView(binding.buttonBack)
|
showView(binding.buttonBack)
|
||||||
} else if (position == 0 && previousPosition == 1) {
|
} else if (position == 0 && previousPosition == 1) {
|
||||||
ViewUtils.hideView(binding.buttonBack)
|
hideView(binding.buttonBack)
|
||||||
ViewUtils.hideView(binding.buttonNext)
|
hideView(binding.buttonNext)
|
||||||
} else if (position == pages.size - 1 && previousPosition == pages.size - 2) {
|
} 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) {
|
} else if (position == pages.size - 2 && previousPosition == pages.size - 1) {
|
||||||
ViewUtils.showView(binding.buttonNext)
|
showView(binding.buttonNext)
|
||||||
}
|
}
|
||||||
|
|
||||||
previousPosition = position
|
previousPosition = position
|
||||||
@ -247,8 +215,7 @@ class SetupFragment : Fragment() {
|
|||||||
|
|
||||||
// Checks if the user has completed the task on the current page
|
// Checks if the user has completed the task on the current page
|
||||||
if (currentPage.hasWarning) {
|
if (currentPage.hasWarning) {
|
||||||
val stepState = currentPage.stepCompleted.invoke()
|
if (currentPage.taskCompleted.invoke()) {
|
||||||
if (stepState != StepState.INCOMPLETE) {
|
|
||||||
pageForward()
|
pageForward()
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
@ -297,15 +264,9 @@ class SetupFragment : Fragment() {
|
|||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var notificationCallback: SetupCallback
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||||
private val permissionLauncher =
|
private val permissionLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||||
if (it) {
|
|
||||||
notificationCallback.onStepCompleted()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!it &&
|
if (!it &&
|
||||||
!shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)
|
!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() {
|
private fun finishSetup() {
|
||||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
||||||
.putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false)
|
.putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false)
|
||||||
@ -344,6 +284,33 @@ class SetupFragment : Fragment() {
|
|||||||
mainActivity.finishSetup(binding.root.findNavController())
|
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() {
|
fun pageForward() {
|
||||||
binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1
|
binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1
|
||||||
}
|
}
|
||||||
@ -359,29 +326,15 @@ class SetupFragment : Fragment() {
|
|||||||
private fun setInsets() =
|
private fun setInsets() =
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
binding.root
|
binding.root
|
||||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||||
|
view.setPadding(
|
||||||
val leftPadding = barInsets.left + cutoutInsets.left
|
barInsets.left + cutoutInsets.left,
|
||||||
val topPadding = barInsets.top + cutoutInsets.top
|
barInsets.top + cutoutInsets.top,
|
||||||
val rightPadding = barInsets.right + cutoutInsets.right
|
barInsets.right + cutoutInsets.right,
|
||||||
val bottomPadding = barInsets.bottom + cutoutInsets.bottom
|
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,6 @@ class HomeViewModel : ViewModel() {
|
|||||||
private val _statusBarShadeVisible = MutableLiveData(true)
|
private val _statusBarShadeVisible = MutableLiveData(true)
|
||||||
val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible
|
val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible
|
||||||
|
|
||||||
private val _shouldPageForward = MutableLiveData(false)
|
|
||||||
val shouldPageForward: LiveData<Boolean> get() = _shouldPageForward
|
|
||||||
|
|
||||||
var navigatedToSetup = false
|
var navigatedToSetup = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -36,8 +33,4 @@ class HomeViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
_statusBarShadeVisible.value = visible
|
_statusBarShadeVisible.value = visible
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setShouldPageForward(pageForward: Boolean) {
|
|
||||||
_shouldPageForward.value = pageForward
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,20 +10,10 @@ data class SetupPage(
|
|||||||
val buttonIconId: Int,
|
val buttonIconId: Int,
|
||||||
val leftAlignedIcon: Boolean,
|
val leftAlignedIcon: Boolean,
|
||||||
val buttonTextId: Int,
|
val buttonTextId: Int,
|
||||||
val buttonAction: (callback: SetupCallback) -> Unit,
|
val buttonAction: () -> Unit,
|
||||||
val hasWarning: Boolean,
|
val hasWarning: Boolean,
|
||||||
val warningTitleId: Int = 0,
|
val warningTitleId: Int = 0,
|
||||||
val warningDescriptionId: Int = 0,
|
val warningDescriptionId: Int = 0,
|
||||||
val warningHelpLinkId: 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 =
|
val getGamesDirectory =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||||
if (result != null) {
|
if (result == null) {
|
||||||
processGamesDir(result)
|
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 =
|
val getProdKey =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||||
if (result != null) {
|
if (result == null) {
|
||||||
processKey(result)
|
return@registerForActivityResult
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun processKey(result: Uri): Boolean {
|
if (FileUtil.getExtension(result) != "keys") {
|
||||||
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 {
|
|
||||||
MessageDialogFragment.newInstance(
|
MessageDialogFragment.newInstance(
|
||||||
R.string.invalid_keys_error,
|
R.string.reading_keys_failure,
|
||||||
R.string.install_keys_failure_description,
|
R.string.install_prod_keys_failure_extension_description
|
||||||
R.string.dumping_keys_quickstart_link
|
|
||||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
).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 =
|
val getFirmware =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
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) {
|
if (rng_seed_enabled) {
|
||||||
Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0));
|
Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0));
|
||||||
} else {
|
} 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);
|
const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false);
|
||||||
if (custom_rtc_enabled) {
|
if (custom_rtc_enabled) {
|
||||||
Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0);
|
Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0);
|
||||||
} else {
|
} 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.language_index);
|
||||||
ReadSetting("System", Settings::values.region_index);
|
ReadSetting("System", Settings::values.region_index);
|
||||||
@ -169,7 +167,7 @@ void Config::ReadValues() {
|
|||||||
|
|
||||||
// Core
|
// Core
|
||||||
ReadSetting("Core", Settings::values.use_multi_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
|
// Cpu
|
||||||
ReadSetting("Cpu", Settings::values.cpu_accuracy);
|
ReadSetting("Cpu", Settings::values.cpu_accuracy);
|
||||||
@ -224,17 +222,14 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("Renderer", Settings::values.bg_blue);
|
ReadSetting("Renderer", Settings::values.bg_blue);
|
||||||
|
|
||||||
// Use GPU accuracy normal by default on Android
|
// Use GPU accuracy normal by default on Android
|
||||||
Settings::values.gpu_accuracy = static_cast<Settings::GpuAccuracy>(config->GetInteger(
|
Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger(
|
||||||
"Renderer", "gpu_accuracy", static_cast<u32>(Settings::GpuAccuracy::Normal)));
|
"Renderer", "gpu_accuracy", static_cast<u32>(Settings::GPUAccuracy::Normal)));
|
||||||
|
|
||||||
// Use GPU default anisotropic filtering on Android
|
// Use GPU default anisotropic filtering on Android
|
||||||
Settings::values.max_anisotropy =
|
Settings::values.max_anisotropy = config->GetInteger("Renderer", "max_anisotropy", 1);
|
||||||
static_cast<Settings::AnisotropyMode>(config->GetInteger("Renderer", "max_anisotropy", 1));
|
|
||||||
|
|
||||||
// Disable ASTC compute by default on Android
|
// Disable ASTC compute by default on Android
|
||||||
Settings::values.accelerate_astc.SetValue(
|
Settings::values.accelerate_astc = config->GetBoolean("Renderer", "accelerate_astc", false);
|
||||||
config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu
|
|
||||||
: Settings::AstcDecodeMode::Cpu);
|
|
||||||
|
|
||||||
// Enable asynchronous presentation by default on Android
|
// Enable asynchronous presentation by default on Android
|
||||||
Settings::values.async_presentation =
|
Settings::values.async_presentation =
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/setup_root"
|
android:id="@+id/setup_root"
|
||||||
@ -8,39 +8,33 @@
|
|||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/viewPager2"
|
android:id="@+id/viewPager2"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dp"
|
||||||
android:layout_alignParentTop="true"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_alignParentBottom="true"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:clipToPadding="false" />
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/constraint_buttons"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/button_next"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_margin="16dp"
|
||||||
android:layout_margin="8dp">
|
android:text="@string/next"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_next"
|
android:id="@+id/button_back"
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/next"
|
android:layout_margin="16dp"
|
||||||
android:visibility="invisible"
|
android:text="@string/back"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:visibility="invisible"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
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>
|
|
||||||
|
@ -21,76 +21,45 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="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
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/text_title"
|
|
||||||
style="@style/TextAppearance.Material3.DisplaySmall"
|
style="@style/TextAppearance.Material3.DisplaySmall"
|
||||||
android:layout_width="0dp"
|
android:id="@+id/text_title"
|
||||||
android:layout_height="0dp"
|
android:layout_width="match_parent"
|
||||||
android:gravity="center"
|
android:layout_height="wrap_content"
|
||||||
|
android:textAlignment="center"
|
||||||
android:textColor="?attr/colorOnSurface"
|
android:textColor="?attr/colorOnSurface"
|
||||||
android:textStyle="bold"
|
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" />
|
tools:text="@string/welcome" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/TextAppearance.Material3.TitleLarge"
|
||||||
android:id="@+id/text_description"
|
android:id="@+id/text_description"
|
||||||
style="@style/TextAppearance.Material3.TitleLarge"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:layout_marginTop="16dp"
|
||||||
android:gravity="center"
|
android:paddingHorizontal="32dp"
|
||||||
android:textSize="20sp"
|
android:textAlignment="center"
|
||||||
android:paddingHorizontal="16dp"
|
android:textSize="26sp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
app:lineHeight="40sp"
|
||||||
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"
|
|
||||||
tools:text="@string/welcome_description" />
|
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
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_action"
|
android:id="@+id/button_action"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="32dp"
|
||||||
android:layout_marginBottom="48dp"
|
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
app:iconGravity="end"
|
|
||||||
app:iconSize="24sp"
|
app:iconSize="24sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:iconGravity="end"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
|
||||||
tools:text="Get started" />
|
tools:text="Get started" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -5,16 +5,23 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/text_value"
|
android:id="@+id/text_value"
|
||||||
style="@style/TextAppearance.Material3.LabelMedium"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_marginBottom="@dimen/spacing_medlarge"
|
android:layout_marginBottom="@dimen/spacing_medlarge"
|
||||||
android:layout_marginTop="@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
|
<com.google.android.material.slider.Slider
|
||||||
android:id="@+id/slider"
|
android:id="@+id/slider"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/setup_root"
|
android:id="@+id/setup_root"
|
||||||
@ -8,39 +8,35 @@
|
|||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/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_height="wrap_content"
|
||||||
android:layout_above="@+id/constraint_buttons"
|
android:layout_margin="12dp"
|
||||||
android:layout_alignParentTop="true"
|
android:text="@string/next"
|
||||||
android:clipToPadding="false" />
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/constraint_buttons"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/button_back"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="12dp"
|
||||||
android:layout_alignParentBottom="true">
|
android:text="@string/back"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
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>
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
@ -12,40 +11,31 @@
|
|||||||
android:minHeight="72dp"
|
android:minHeight="72dp"
|
||||||
android:padding="@dimen/spacing_large">
|
android:padding="@dimen/spacing_large">
|
||||||
|
|
||||||
<LinearLayout
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:layout_width="match_parent"
|
style="@style/TextAppearance.Material3.HeadlineMedium"
|
||||||
|
android:id="@+id/text_setting_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
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
|
<TextView
|
||||||
android:id="@+id/text_setting_name"
|
style="@style/TextAppearance.Material3.BodySmall"
|
||||||
style="@style/TextAppearance.Material3.HeadlineMedium"
|
android:id="@+id/text_setting_description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="viewStart"
|
android:layout_alignParentEnd="true"
|
||||||
android:textSize="16sp"
|
android:layout_alignParentStart="true"
|
||||||
app:lineHeight="22dp"
|
android:layout_alignStart="@+id/text_setting_name"
|
||||||
tools:text="Setting Name" />
|
android:layout_below="@+id/text_setting_name"
|
||||||
|
android:layout_marginTop="@dimen/spacing_small"
|
||||||
<com.google.android.material.textview.MaterialTextView
|
android:visibility="visible"
|
||||||
android:id="@+id/text_setting_description"
|
android:textAlignment="viewStart"
|
||||||
style="@style/TextAppearance.Material3.BodySmall"
|
tools:text="@string/app_disclaimer" />
|
||||||
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>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -21,12 +21,11 @@
|
|||||||
app:layout_constraintVertical_chainStyle="spread"
|
app:layout_constraintVertical_chainStyle="spread"
|
||||||
app:layout_constraintWidth_max="220dp"
|
app:layout_constraintWidth_max="220dp"
|
||||||
app:layout_constraintWidth_min="110dp"
|
app:layout_constraintWidth_min="110dp"
|
||||||
app:layout_constraintVertical_weight="3"
|
app:layout_constraintVertical_weight="3" />
|
||||||
tools:src="@drawable/ic_notification" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/text_title"
|
android:id="@+id/text_title"
|
||||||
style="@style/TextAppearance.Material3.DisplaySmall"
|
style="@style/TextAppearance.Material3.DisplayMedium"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
@ -45,42 +44,23 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textSize="20sp"
|
android:textSize="26sp"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
||||||
app:layout_constraintVertical_weight="2"
|
app:layout_constraintVertical_weight="2"
|
||||||
app:lineHeight="30sp"
|
app:lineHeight="40sp"
|
||||||
tools:text="@string/welcome_description" />
|
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
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_action"
|
android:id="@+id/button_action"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
|
android:textSize="20sp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginBottom="48dp"
|
android:layout_marginBottom="48dp"
|
||||||
android:textSize="20sp"
|
|
||||||
app:iconGravity="end"
|
app:iconGravity="end"
|
||||||
app:iconSize="24sp"
|
app:iconSize="24sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
<string name="back">Back</string>
|
<string name="back">Back</string>
|
||||||
<string name="add_games">Add Games</string>
|
<string name="add_games">Add Games</string>
|
||||||
<string name="add_games_description">Select your games folder</string>
|
<string name="add_games_description">Select your games folder</string>
|
||||||
<string name="step_complete">Complete!</string>
|
|
||||||
|
|
||||||
<!-- Home strings -->
|
<!-- Home strings -->
|
||||||
<string name="home_games">Games</string>
|
<string name="home_games">Games</string>
|
||||||
@ -150,7 +149,6 @@
|
|||||||
<string name="frame_limit_slider">Limit speed percent</string>
|
<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="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="cpu_accuracy">CPU accuracy</string>
|
||||||
<string name="value_with_units">%1$s%2$s</string>
|
|
||||||
|
|
||||||
<!-- System settings strings -->
|
<!-- System settings strings -->
|
||||||
<string name="use_docked_mode">Docked Mode</string>
|
<string name="use_docked_mode">Docked Mode</string>
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "audio_core/sink/null_sink.h"
|
#include "audio_core/sink/null_sink.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/settings_enums.h"
|
|
||||||
|
|
||||||
namespace AudioCore::Sink {
|
namespace AudioCore::Sink {
|
||||||
namespace {
|
namespace {
|
||||||
@ -25,7 +24,7 @@ struct SinkDetails {
|
|||||||
using LatencyFn = u32 (*)();
|
using LatencyFn = u32 (*)();
|
||||||
|
|
||||||
/// Name for this sink.
|
/// Name for this sink.
|
||||||
Settings::AudioEngine id;
|
std::string_view id;
|
||||||
/// A method to call to construct an instance of this type of sink.
|
/// A method to call to construct an instance of this type of sink.
|
||||||
FactoryFn factory;
|
FactoryFn factory;
|
||||||
/// A method to call to list available devices.
|
/// A method to call to list available devices.
|
||||||
@ -38,7 +37,7 @@ struct SinkDetails {
|
|||||||
constexpr SinkDetails sink_details[] = {
|
constexpr SinkDetails sink_details[] = {
|
||||||
#ifdef HAVE_CUBEB
|
#ifdef HAVE_CUBEB
|
||||||
SinkDetails{
|
SinkDetails{
|
||||||
Settings::AudioEngine::Cubeb,
|
"cubeb",
|
||||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||||
return std::make_unique<CubebSink>(device_id);
|
return std::make_unique<CubebSink>(device_id);
|
||||||
},
|
},
|
||||||
@ -48,7 +47,7 @@ constexpr SinkDetails sink_details[] = {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
SinkDetails{
|
SinkDetails{
|
||||||
Settings::AudioEngine::Sdl2,
|
"sdl2",
|
||||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||||
return std::make_unique<SDLSink>(device_id);
|
return std::make_unique<SDLSink>(device_id);
|
||||||
},
|
},
|
||||||
@ -56,47 +55,46 @@ constexpr SinkDetails sink_details[] = {
|
|||||||
&GetSDLLatency,
|
&GetSDLLatency,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
SinkDetails{Settings::AudioEngine::Null,
|
SinkDetails{"null",
|
||||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||||
return std::make_unique<NullSink>(device_id);
|
return std::make_unique<NullSink>(device_id);
|
||||||
},
|
},
|
||||||
[](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }},
|
[](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }},
|
||||||
};
|
};
|
||||||
|
|
||||||
const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
|
const SinkDetails& GetOutputSinkDetails(std::string_view sink_id) {
|
||||||
const auto find_backend{[](Settings::AudioEngine id) {
|
const auto find_backend{[](std::string_view id) {
|
||||||
return std::find_if(std::begin(sink_details), std::end(sink_details),
|
return std::find_if(std::begin(sink_details), std::end(sink_details),
|
||||||
[&id](const auto& sink_detail) { return sink_detail.id == id; });
|
[&id](const auto& sink_detail) { return sink_detail.id == id; });
|
||||||
}};
|
}};
|
||||||
|
|
||||||
auto iter = find_backend(sink_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
|
// Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which
|
||||||
// causes audio issues, in that case go with SDL.
|
// causes audio issues, in that case go with SDL.
|
||||||
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
|
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
|
||||||
iter = find_backend(Settings::AudioEngine::Cubeb);
|
iter = find_backend("cubeb");
|
||||||
if (iter->latency() > TargetSampleCount * 3) {
|
if (iter->latency() > TargetSampleCount * 3) {
|
||||||
iter = find_backend(Settings::AudioEngine::Sdl2);
|
iter = find_backend("sdl2");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
iter = std::begin(sink_details);
|
iter = std::begin(sink_details);
|
||||||
#endif
|
#endif
|
||||||
LOG_INFO(Service_Audio, "Auto-selecting the {} backend",
|
LOG_INFO(Service_Audio, "Auto-selecting the {} backend", iter->id);
|
||||||
Settings::CanonicalizeEnum(iter->id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter == std::end(sink_details)) {
|
if (iter == std::end(sink_details)) {
|
||||||
LOG_ERROR(Audio, "Invalid sink_id {}", Settings::CanonicalizeEnum(sink_id));
|
LOG_ERROR(Audio, "Invalid sink_id {}", sink_id);
|
||||||
iter = find_backend(Settings::AudioEngine::Null);
|
iter = find_backend("null");
|
||||||
}
|
}
|
||||||
|
|
||||||
return *iter;
|
return *iter;
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
std::vector<Settings::AudioEngine> GetSinkIDs() {
|
std::vector<std::string_view> GetSinkIDs() {
|
||||||
std::vector<Settings::AudioEngine> sink_ids(std::size(sink_details));
|
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),
|
std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids),
|
||||||
[](const auto& sink) { return sink.id; });
|
[](const auto& sink) { return sink.id; });
|
||||||
@ -104,11 +102,11 @@ std::vector<Settings::AudioEngine> GetSinkIDs() {
|
|||||||
return sink_ids;
|
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);
|
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);
|
return GetOutputSinkDetails(sink_id).factory(device_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/settings_enums.h"
|
|
||||||
|
|
||||||
namespace AudioCore {
|
namespace AudioCore {
|
||||||
class AudioManager;
|
class AudioManager;
|
||||||
@ -21,7 +19,7 @@ class Sink;
|
|||||||
*
|
*
|
||||||
* @return Vector of available sink names.
|
* @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.
|
* 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?
|
* @param capture - Get capture (input) devices, or output devices?
|
||||||
* @return Vector of device names.
|
* @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.
|
* 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.
|
* @param device_id - Name of the device to create.
|
||||||
* @return Pointer to the created sink.
|
* @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 Sink
|
||||||
} // namespace AudioCore
|
} // namespace AudioCore
|
||||||
|
@ -110,12 +110,8 @@ add_library(common STATIC
|
|||||||
scratch_buffer.h
|
scratch_buffer.h
|
||||||
settings.cpp
|
settings.cpp
|
||||||
settings.h
|
settings.h
|
||||||
settings_common.cpp
|
|
||||||
settings_common.h
|
|
||||||
settings_enums.h
|
|
||||||
settings_input.cpp
|
settings_input.cpp
|
||||||
settings_input.h
|
settings_input.h
|
||||||
settings_setting.h
|
|
||||||
socket_types.h
|
socket_types.h
|
||||||
spin_lock.cpp
|
spin_lock.cpp
|
||||||
spin_lock.h
|
spin_lock.h
|
||||||
@ -197,16 +193,9 @@ if (MSVC)
|
|||||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
/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
|
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||||
)
|
)
|
||||||
endif()
|
else()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|
||||||
target_compile_options(common PRIVATE
|
target_compile_options(common PRIVATE
|
||||||
-fsized-deallocation
|
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>
|
||||||
-Werror=unreachable-code-aggressive
|
|
||||||
)
|
|
||||||
target_compile_definitions(common PRIVATE
|
|
||||||
# Clang 14 and earlier have errors when explicitly instantiating Settings::Setting
|
|
||||||
$<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,15>:CANNOT_EXPLICITLY_INSTANTIATE>
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ public:
|
|||||||
|
|
||||||
using namespace Common::Literals;
|
using namespace Common::Literals;
|
||||||
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
|
// 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;
|
const bool write_limit_exceeded = bytes_written > write_limit;
|
||||||
if (entry.log_level >= Level::Error || write_limit_exceeded) {
|
if (entry.log_level >= Level::Error || write_limit_exceeded) {
|
||||||
if (write_limit_exceeded) {
|
if (write_limit_exceeded) {
|
||||||
|
@ -7,16 +7,9 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#endif
|
#endif
|
||||||
#include <compare>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <functional>
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <type_traits>
|
|
||||||
#include <fmt/core.h>
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/fs/fs_util.h"
|
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
@ -24,50 +17,11 @@
|
|||||||
|
|
||||||
namespace Settings {
|
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;
|
Values values;
|
||||||
|
static bool configuring_global = true;
|
||||||
|
|
||||||
std::string GetTimeZoneString(TimeZone time_zone) {
|
std::string GetTimeZoneString() {
|
||||||
const auto time_zone_index = static_cast<std::size_t>(time_zone);
|
const auto time_zone_index = static_cast<std::size_t>(values.time_zone_index.GetValue());
|
||||||
ASSERT(time_zone_index < Common::TimeZone::GetTimeZoneStrings().size());
|
ASSERT(time_zone_index < Common::TimeZone::GetTimeZoneStrings().size());
|
||||||
|
|
||||||
std::string location_name;
|
std::string location_name;
|
||||||
@ -107,35 +61,73 @@ void LogSettings() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
LOG_INFO(Config, "yuzu Configuration:");
|
LOG_INFO(Config, "yuzu Configuration:");
|
||||||
for (auto& [category, settings] : values.linkage.by_category) {
|
log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue());
|
||||||
for (const auto& setting : settings) {
|
log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
|
||||||
if (setting->Id() == values.yuzu_token.Id()) {
|
log_setting("System_DeviceName", values.device_name.GetValue());
|
||||||
// Hide the token secret, for security reasons.
|
log_setting("System_CurrentUser", values.current_user.GetValue());
|
||||||
continue;
|
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());
|
||||||
const auto name = fmt::format(
|
log_setting("System_UnsafeMemoryLayout", values.use_unsafe_extended_memory_layout.GetValue());
|
||||||
"{:c}{:c} {}.{}", setting->ToString() == setting->DefaultToString() ? '-' : 'M',
|
log_setting("Core_UseMultiCore", values.use_multi_core.GetValue());
|
||||||
setting->UsingGlobal() ? '-' : 'C', TranslateCategory(category),
|
log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue());
|
||||||
setting->GetLabel());
|
log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue());
|
||||||
|
log_setting("Renderer_ScalingFilter", values.scaling_filter.GetValue());
|
||||||
log_setting(name, setting->Canonicalize());
|
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_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir));
|
||||||
log_path("DataStorage_ConfigDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir));
|
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_LoadDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::LoadDir));
|
||||||
log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir));
|
log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir));
|
||||||
log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir));
|
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() {
|
bool IsGPULevelExtreme() {
|
||||||
return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme;
|
return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsGPULevelHigh() {
|
bool IsGPULevelHigh() {
|
||||||
return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme ||
|
return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme ||
|
||||||
values.gpu_accuracy.GetValue() == GpuAccuracy::High;
|
values.gpu_accuracy.GetValue() == GPUAccuracy::High;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsFastmemEnabled() {
|
bool IsFastmemEnabled() {
|
||||||
@ -152,61 +144,6 @@ float Volume() {
|
|||||||
return values.volume.GetValue() / static_cast<f32>(values.volume.GetDefault());
|
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() {
|
void UpdateRescalingInfo() {
|
||||||
const auto setup = values.resolution_setup.GetValue();
|
const auto setup = values.resolution_setup.GetValue();
|
||||||
auto& info = values.resolution_info;
|
auto& info = values.resolution_info;
|
||||||
@ -275,19 +212,66 @@ void RestoreGlobalState(bool is_powered_on) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& reset : values.linkage.restore_functions) {
|
// Audio
|
||||||
reset();
|
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() {
|
// CPU
|
||||||
return configuring_global;
|
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) {
|
// Renderer
|
||||||
configuring_global = is_global;
|
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
|
} // namespace Settings
|
||||||
|
@ -6,21 +6,95 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <optional>
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/settings_common.h"
|
|
||||||
#include "common/settings_enums.h"
|
|
||||||
#include "common/settings_input.h"
|
#include "common/settings_input.h"
|
||||||
#include "common/settings_setting.h"
|
|
||||||
|
|
||||||
namespace Settings {
|
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 {
|
struct ResolutionScalingInfo {
|
||||||
u32 up_scale{1};
|
u32 up_scale{1};
|
||||||
@ -45,47 +119,239 @@ struct ResolutionScalingInfo {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef CANNOT_EXPLICITLY_INSTANTIATE
|
/** The Setting class is a simple resource manager. It defines a label and default value alongside
|
||||||
// Instantiate the classes elsewhere (settings.cpp) to reduce compiler/linker work
|
* the actual value of the setting for simpler and less-error prone use with frontend
|
||||||
#define SETTING(TYPE, RANGED) extern template class Setting<TYPE, RANGED>
|
* configurations. Specifying a default value and label is required. A minimum and maximum range can
|
||||||
#define SWITCHABLE(TYPE, RANGED) extern template class SwitchableSetting<TYPE, RANGED>
|
* be specified for sanitization.
|
||||||
|
*/
|
||||||
|
template <typename Type, bool ranged = false>
|
||||||
|
class Setting {
|
||||||
|
protected:
|
||||||
|
Setting() = default;
|
||||||
|
|
||||||
SETTING(AudioEngine, false);
|
/**
|
||||||
SETTING(bool, false);
|
* Only sets the setting to the given initializer, leaving the other members to their default
|
||||||
SETTING(int, false);
|
* initializers.
|
||||||
SETTING(s32, false);
|
*
|
||||||
SETTING(std::string, false);
|
* @param global_val Initial value of the setting
|
||||||
SETTING(std::string, false);
|
*/
|
||||||
SETTING(u16, false);
|
explicit Setting(const Type& val) : value{val} {}
|
||||||
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
|
public:
|
||||||
#undef SWITCHABLE
|
/**
|
||||||
#endif
|
* 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.
|
* The InputSetting class allows for getting a reference to either the global or custom members.
|
||||||
@ -125,388 +391,208 @@ struct TouchFromButtonMap {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Values {
|
struct Values {
|
||||||
Linkage linkage{};
|
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio,
|
Setting<std::string> sink_id{"auto", "output_engine"};
|
||||||
Specialization::RuntimeList};
|
Setting<std::string> audio_output_device_id{"auto", "output_device"};
|
||||||
Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio,
|
Setting<std::string> audio_input_device_id{"auto", "input_device"};
|
||||||
Specialization::RuntimeList};
|
Setting<bool> audio_muted{false, "audio_muted"};
|
||||||
Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio,
|
SwitchableSetting<u8, true> volume{100, 0, 200, "volume"};
|
||||||
Specialization::RuntimeList};
|
Setting<bool> dump_audio_commands{false, "dump_audio_commands"};
|
||||||
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};
|
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core};
|
SwitchableSetting<bool> use_multi_core{true, "use_multi_core"};
|
||||||
SwitchableSetting<MemoryLayout, true> memory_layout_mode{linkage,
|
SwitchableSetting<bool> use_unsafe_extended_memory_layout{false,
|
||||||
MemoryLayout::Memory_4Gb,
|
"use_unsafe_extended_memory_layout"};
|
||||||
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};
|
|
||||||
|
|
||||||
// Cpu
|
// Cpu
|
||||||
SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto,
|
SwitchableSetting<CPUAccuracy, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
|
||||||
CpuAccuracy::Auto, CpuAccuracy::Paranoid,
|
CPUAccuracy::Paranoid, "cpu_accuracy"};
|
||||||
"cpu_accuracy", Category::Cpu};
|
// TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021
|
||||||
Setting<bool> cpu_debug_mode{linkage, false, "cpu_debug_mode", Category::CpuDebug};
|
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_page_tables{true, "cpuopt_page_tables"};
|
||||||
Setting<bool> cpuopt_block_linking{linkage, true, "cpuopt_block_linking", Category::CpuDebug};
|
Setting<bool> cpuopt_block_linking{true, "cpuopt_block_linking"};
|
||||||
Setting<bool> cpuopt_return_stack_buffer{linkage, true, "cpuopt_return_stack_buffer",
|
Setting<bool> cpuopt_return_stack_buffer{true, "cpuopt_return_stack_buffer"};
|
||||||
Category::CpuDebug};
|
Setting<bool> cpuopt_fast_dispatcher{true, "cpuopt_fast_dispatcher"};
|
||||||
Setting<bool> cpuopt_fast_dispatcher{linkage, true, "cpuopt_fast_dispatcher",
|
Setting<bool> cpuopt_context_elimination{true, "cpuopt_context_elimination"};
|
||||||
Category::CpuDebug};
|
Setting<bool> cpuopt_const_prop{true, "cpuopt_const_prop"};
|
||||||
Setting<bool> cpuopt_context_elimination{linkage, true, "cpuopt_context_elimination",
|
Setting<bool> cpuopt_misc_ir{true, "cpuopt_misc_ir"};
|
||||||
Category::CpuDebug};
|
Setting<bool> cpuopt_reduce_misalign_checks{true, "cpuopt_reduce_misalign_checks"};
|
||||||
Setting<bool> cpuopt_const_prop{linkage, true, "cpuopt_const_prop", Category::CpuDebug};
|
Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"};
|
||||||
Setting<bool> cpuopt_misc_ir{linkage, true, "cpuopt_misc_ir", Category::CpuDebug};
|
Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"};
|
||||||
Setting<bool> cpuopt_reduce_misalign_checks{linkage, true, "cpuopt_reduce_misalign_checks",
|
Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"};
|
||||||
Category::CpuDebug};
|
Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"};
|
||||||
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};
|
|
||||||
|
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma",
|
SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"};
|
||||||
Category::CpuUnsafe};
|
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{
|
|
||||||
linkage, true, "cpuopt_unsafe_reduce_fp_error", Category::CpuUnsafe};
|
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{
|
SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{
|
||||||
linkage, true, "cpuopt_unsafe_ignore_standard_fpcr", Category::CpuUnsafe};
|
true, "cpuopt_unsafe_ignore_standard_fpcr"};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{
|
SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{true, "cpuopt_unsafe_inaccurate_nan"};
|
||||||
linkage, true, "cpuopt_unsafe_inaccurate_nan", Category::CpuUnsafe};
|
SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{
|
|
||||||
linkage, true, "cpuopt_unsafe_fastmem_check", Category::CpuUnsafe};
|
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{
|
SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{
|
||||||
linkage, true, "cpuopt_unsafe_ignore_global_monitor", Category::CpuUnsafe};
|
true, "cpuopt_unsafe_ignore_global_monitor"};
|
||||||
|
|
||||||
// Renderer
|
// Renderer
|
||||||
SwitchableSetting<RendererBackend, true> renderer_backend{
|
SwitchableSetting<RendererBackend, true> renderer_backend{
|
||||||
linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null,
|
RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"};
|
||||||
"backend", Category::Renderer};
|
SwitchableSetting<bool> async_presentation{false, "async_presentation"};
|
||||||
SwitchableSetting<ShaderBackend, true> shader_backend{
|
SwitchableSetting<bool> renderer_force_max_clock{false, "force_max_clock"};
|
||||||
linkage, ShaderBackend::Glsl, ShaderBackend::Glsl, ShaderBackend::SpirV,
|
Setting<bool> renderer_debug{false, "debug"};
|
||||||
"shader_backend", Category::Renderer, Specialization::RuntimeList};
|
Setting<bool> renderer_shader_feedback{false, "shader_feedback"};
|
||||||
SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer,
|
Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"};
|
||||||
Specialization::RuntimeList};
|
Setting<bool> disable_shader_loop_safety_checks{false, "disable_shader_loop_safety_checks"};
|
||||||
|
SwitchableSetting<int> vulkan_device{0, "vulkan_device"};
|
||||||
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};
|
|
||||||
|
|
||||||
ResolutionScalingInfo resolution_info{};
|
ResolutionScalingInfo resolution_info{};
|
||||||
SwitchableSetting<ResolutionSetup> resolution_setup{linkage, ResolutionSetup::Res1X,
|
SwitchableSetting<ResolutionSetup> resolution_setup{ResolutionSetup::Res1X, "resolution_setup"};
|
||||||
"resolution_setup", Category::Renderer};
|
SwitchableSetting<ScalingFilter> scaling_filter{ScalingFilter::Bilinear, "scaling_filter"};
|
||||||
SwitchableSetting<ScalingFilter> scaling_filter{linkage,
|
SwitchableSetting<int, true> fsr_sharpening_slider{25, 0, 200, "fsr_sharpening_slider"};
|
||||||
ScalingFilter::Bilinear,
|
SwitchableSetting<AntiAliasing> anti_aliasing{AntiAliasing::None, "anti_aliasing"};
|
||||||
"scaling_filter",
|
// *nix platforms may have issues with the borderless windowed fullscreen mode.
|
||||||
Category::Renderer,
|
// Default to exclusive fullscreen on these platforms for now.
|
||||||
Specialization::Default,
|
SwitchableSetting<FullscreenMode, true> fullscreen_mode{
|
||||||
true,
|
#ifdef _WIN32
|
||||||
true};
|
FullscreenMode::Borderless,
|
||||||
SwitchableSetting<AntiAliasing> anti_aliasing{linkage,
|
#else
|
||||||
AntiAliasing::None,
|
FullscreenMode::Exclusive,
|
||||||
"anti_aliasing",
|
#endif
|
||||||
Category::Renderer,
|
FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"};
|
||||||
Specialization::Default,
|
SwitchableSetting<int, true> aspect_ratio{0, 0, 4, "aspect_ratio"};
|
||||||
true,
|
SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"};
|
||||||
true};
|
SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"};
|
||||||
SwitchableSetting<int, true> fsr_sharpening_slider{linkage,
|
SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"};
|
||||||
25,
|
SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"};
|
||||||
0,
|
SwitchableSetting<GPUAccuracy, true> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
|
||||||
200,
|
GPUAccuracy::Extreme, "gpu_accuracy"};
|
||||||
"fsr_sharpening_slider",
|
SwitchableSetting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"};
|
||||||
Category::Renderer,
|
SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
|
||||||
Specialization::Scalar |
|
SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
|
||||||
Specialization::Percentage,
|
SwitchableSetting<bool> async_astc{false, "async_astc"};
|
||||||
true,
|
Setting<VSyncMode, true> vsync_mode{VSyncMode::FIFO, VSyncMode::Immediate,
|
||||||
true};
|
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{
|
SwitchableSetting<u8> bg_red{0, "bg_red"};
|
||||||
linkage, 0, "bg_red", Category::Renderer, Specialization::Default, true, true};
|
SwitchableSetting<u8> bg_green{0, "bg_green"};
|
||||||
SwitchableSetting<u8, false> bg_green{
|
SwitchableSetting<u8> bg_blue{0, "bg_blue"};
|
||||||
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};
|
|
||||||
|
|
||||||
// System
|
// System
|
||||||
SwitchableSetting<Language, true> language_index{linkage,
|
SwitchableSetting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"};
|
||||||
Language::EnglishAmerican,
|
Setting<std::string> device_name{"Yuzu", "device_name"};
|
||||||
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};
|
|
||||||
// Measured in seconds since epoch
|
// Measured in seconds since epoch
|
||||||
SwitchableSetting<bool> custom_rtc_enabled{
|
std::optional<s64> custom_rtc;
|
||||||
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};
|
|
||||||
// Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
|
// Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
|
||||||
s64 custom_rtc_differential;
|
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};
|
Setting<s32> current_user{0, "current_user"};
|
||||||
|
SwitchableSetting<s32, true> language_index{1, 0, 17, "language_index"};
|
||||||
SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System};
|
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
|
// Controls
|
||||||
InputSetting<std::array<PlayerInput, 10>> players;
|
InputSetting<std::array<PlayerInput, 10>> players;
|
||||||
|
|
||||||
Setting<bool> enable_raw_input{
|
SwitchableSetting<bool> use_docked_mode{true, "use_docked_mode"};
|
||||||
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> vibration_enabled{linkage, true, "vibration_enabled",
|
Setting<bool> enable_raw_input{false, "enable_raw_input"};
|
||||||
Category::Controls};
|
Setting<bool> controller_navigation{true, "controller_navigation"};
|
||||||
SwitchableSetting<bool> enable_accurate_vibrations{linkage, false, "enable_accurate_vibrations",
|
Setting<bool> enable_joycon_driver{true, "enable_joycon_driver"};
|
||||||
Category::Controls};
|
Setting<bool> enable_procon_driver{false, "enable_procon_driver"};
|
||||||
|
|
||||||
SwitchableSetting<bool> motion_enabled{linkage, true, "motion_enabled", Category::Controls};
|
SwitchableSetting<bool> vibration_enabled{true, "vibration_enabled"};
|
||||||
Setting<std::string> udp_input_servers{linkage, "127.0.0.1:26760", "udp_input_servers",
|
SwitchableSetting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"};
|
||||||
Category::Controls};
|
|
||||||
Setting<bool> enable_udp_controller{linkage, false, "enable_udp_controller",
|
|
||||||
Category::Controls};
|
|
||||||
|
|
||||||
Setting<bool> pause_tas_on_load{linkage, true, "pause_tas_on_load", Category::Controls};
|
SwitchableSetting<bool> motion_enabled{true, "motion_enabled"};
|
||||||
Setting<bool> tas_enable{linkage, false, "tas_enable", Category::Controls};
|
Setting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
|
||||||
Setting<bool> tas_loop{linkage, false, "tas_loop", Category::Controls};
|
Setting<bool> enable_udp_controller{false, "enable_udp_controller"};
|
||||||
|
|
||||||
Setting<bool> mouse_panning{
|
Setting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
|
||||||
linkage, false, "mouse_panning", Category::Controls, Specialization::Default, false};
|
Setting<bool> tas_enable{false, "tas_enable"};
|
||||||
Setting<u8, true> mouse_panning_sensitivity{
|
Setting<bool> tas_loop{false, "tas_loop"};
|
||||||
linkage, 50, 1, 100, "mouse_panning_sensitivity", Category::Controls};
|
|
||||||
Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls};
|
|
||||||
|
|
||||||
Setting<u8, true> mouse_panning_x_sensitivity{
|
Setting<bool> mouse_panning{false, "mouse_panning"};
|
||||||
linkage, 50, 1, 100, "mouse_panning_x_sensitivity", Category::Controls};
|
Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"};
|
||||||
Setting<u8, true> mouse_panning_y_sensitivity{
|
Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"};
|
||||||
linkage, 50, 1, 100, "mouse_panning_y_sensitivity", Category::Controls};
|
Setting<u8, true> mouse_panning_deadzone_counterweight{20, 0, 100,
|
||||||
Setting<u8, true> mouse_panning_deadzone_counterweight{
|
"mouse_panning_deadzone_counterweight"};
|
||||||
linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls};
|
Setting<u8, true> mouse_panning_decay_strength{18, 0, 100, "mouse_panning_decay_strength"};
|
||||||
Setting<u8, true> mouse_panning_decay_strength{
|
Setting<u8, true> mouse_panning_min_decay{6, 0, 100, "mouse_panning_min_decay"};
|
||||||
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> emulate_analog_keyboard{linkage, false, "emulate_analog_keyboard",
|
Setting<bool> mouse_enabled{false, "mouse_enabled"};
|
||||||
Category::Controls};
|
Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
|
||||||
Setting<bool> keyboard_enabled{linkage, false, "keyboard_enabled", Category::Controls};
|
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;
|
ButtonsRaw debug_pad_buttons;
|
||||||
AnalogsRaw debug_pad_analogs;
|
AnalogsRaw debug_pad_analogs;
|
||||||
|
|
||||||
TouchscreenInput touchscreen;
|
TouchscreenInput touchscreen;
|
||||||
|
|
||||||
Setting<std::string> touch_device{linkage, "min_x:100,min_y:50,max_x:1800,max_y:850",
|
Setting<std::string> touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850", "touch_device"};
|
||||||
"touch_device", Category::Controls};
|
Setting<int> touch_from_button_map_index{0, "touch_from_button_map"};
|
||||||
Setting<int> touch_from_button_map_index{linkage, 0, "touch_from_button_map",
|
|
||||||
Category::Controls};
|
|
||||||
std::vector<TouchFromButtonMap> touch_from_button_maps;
|
std::vector<TouchFromButtonMap> touch_from_button_maps;
|
||||||
|
|
||||||
Setting<bool> enable_ring_controller{linkage, true, "enable_ring_controller",
|
Setting<bool> enable_ring_controller{true, "enable_ring_controller"};
|
||||||
Category::Controls};
|
|
||||||
RingconRaw ringcon_analogs;
|
RingconRaw ringcon_analogs;
|
||||||
|
|
||||||
Setting<bool> enable_ir_sensor{linkage, false, "enable_ir_sensor", Category::Controls};
|
Setting<bool> enable_ir_sensor{false, "enable_ir_sensor"};
|
||||||
Setting<std::string> ir_sensor_device{linkage, "auto", "ir_sensor_device", Category::Controls};
|
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
|
// Data Storage
|
||||||
Setting<bool> use_virtual_sd{linkage, true, "use_virtual_sd", Category::DataStorage};
|
Setting<bool> use_virtual_sd{true, "use_virtual_sd"};
|
||||||
Setting<bool> gamecard_inserted{linkage, false, "gamecard_inserted", Category::DataStorage};
|
Setting<bool> gamecard_inserted{false, "gamecard_inserted"};
|
||||||
Setting<bool> gamecard_current_game{linkage, false, "gamecard_current_game",
|
Setting<bool> gamecard_current_game{false, "gamecard_current_game"};
|
||||||
Category::DataStorage};
|
Setting<std::string> gamecard_path{std::string(), "gamecard_path"};
|
||||||
Setting<std::string> gamecard_path{linkage, std::string(), "gamecard_path",
|
|
||||||
Category::DataStorage};
|
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
bool record_frame_times;
|
bool record_frame_times;
|
||||||
Setting<bool> use_gdbstub{linkage, false, "use_gdbstub", Category::Debugging};
|
Setting<bool> use_gdbstub{false, "use_gdbstub"};
|
||||||
Setting<u16> gdbstub_port{linkage, 6543, "gdbstub_port", Category::Debugging};
|
Setting<u16> gdbstub_port{6543, "gdbstub_port"};
|
||||||
Setting<std::string> program_args{linkage, std::string(), "program_args", Category::Debugging};
|
Setting<std::string> program_args{std::string(), "program_args"};
|
||||||
Setting<bool> dump_exefs{linkage, false, "dump_exefs", Category::Debugging};
|
Setting<bool> dump_exefs{false, "dump_exefs"};
|
||||||
Setting<bool> dump_nso{linkage, false, "dump_nso", Category::Debugging};
|
Setting<bool> dump_nso{false, "dump_nso"};
|
||||||
Setting<bool> dump_shaders{
|
Setting<bool> dump_shaders{false, "dump_shaders"};
|
||||||
linkage, false, "dump_shaders", Category::DebuggingGraphics, Specialization::Default,
|
Setting<bool> dump_macros{false, "dump_macros"};
|
||||||
false};
|
Setting<bool> enable_fs_access_log{false, "enable_fs_access_log"};
|
||||||
Setting<bool> dump_macros{
|
Setting<bool> reporting_services{false, "reporting_services"};
|
||||||
linkage, false, "dump_macros", Category::DebuggingGraphics, Specialization::Default, false};
|
Setting<bool> quest_flag{false, "quest_flag"};
|
||||||
Setting<bool> enable_fs_access_log{linkage, false, "enable_fs_access_log", Category::Debugging};
|
Setting<bool> disable_macro_jit{false, "disable_macro_jit"};
|
||||||
Setting<bool> reporting_services{
|
Setting<bool> disable_macro_hle{false, "disable_macro_hle"};
|
||||||
linkage, false, "reporting_services", Category::Debugging, Specialization::Default, false};
|
Setting<bool> extended_logging{false, "extended_logging"};
|
||||||
Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging};
|
Setting<bool> use_debug_asserts{false, "use_debug_asserts"};
|
||||||
Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit",
|
Setting<bool> use_auto_stub{false, "use_auto_stub"};
|
||||||
Category::DebuggingGraphics};
|
Setting<bool> enable_all_controllers{false, "enable_all_controllers"};
|
||||||
Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle",
|
Setting<bool> create_crash_dumps{false, "create_crash_dumps"};
|
||||||
Category::DebuggingGraphics};
|
Setting<bool> perform_vulkan_check{true, "perform_vulkan_check"};
|
||||||
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};
|
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
|
Setting<std::string> log_filter{"*:Info", "log_filter"};
|
||||||
Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous};
|
Setting<bool> use_dev_keys{false, "use_dev_keys"};
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
Setting<std::string> network_interface{linkage, std::string(), "network_interface",
|
Setting<std::string> network_interface{std::string(), "network_interface"};
|
||||||
Category::Network};
|
|
||||||
|
|
||||||
// WebService
|
// WebService
|
||||||
Setting<bool> enable_telemetry{linkage, true, "enable_telemetry", Category::WebService};
|
Setting<bool> enable_telemetry{true, "enable_telemetry"};
|
||||||
Setting<std::string> web_api_url{linkage, "https://api.yuzu-emu.org", "web_api_url",
|
Setting<std::string> web_api_url{"https://api.yuzu-emu.org", "web_api_url"};
|
||||||
Category::WebService};
|
Setting<std::string> yuzu_username{std::string(), "yuzu_username"};
|
||||||
Setting<std::string> yuzu_username{linkage, std::string(), "yuzu_username",
|
Setting<std::string> yuzu_token{std::string(), "yuzu_token"};
|
||||||
Category::WebService};
|
|
||||||
Setting<std::string> yuzu_token{linkage, std::string(), "yuzu_token", Category::WebService};
|
|
||||||
|
|
||||||
// Add-Ons
|
// Add-Ons
|
||||||
std::map<u64, std::vector<std::string>> disabled_addons;
|
std::map<u64, std::vector<std::string>> disabled_addons;
|
||||||
@ -514,6 +600,9 @@ struct Values {
|
|||||||
|
|
||||||
extern Values values;
|
extern Values values;
|
||||||
|
|
||||||
|
bool IsConfiguringGlobal();
|
||||||
|
void SetConfiguringGlobal(bool is_global);
|
||||||
|
|
||||||
bool IsGPULevelExtreme();
|
bool IsGPULevelExtreme();
|
||||||
bool IsGPULevelHigh();
|
bool IsGPULevelHigh();
|
||||||
|
|
||||||
@ -521,7 +610,7 @@ bool IsFastmemEnabled();
|
|||||||
|
|
||||||
float Volume();
|
float Volume();
|
||||||
|
|
||||||
std::string GetTimeZoneString(TimeZone time_zone);
|
std::string GetTimeZoneString();
|
||||||
|
|
||||||
void LogSettings();
|
void LogSettings();
|
||||||
|
|
||||||
@ -530,7 +619,4 @@ void UpdateRescalingInfo();
|
|||||||
// Restore the global state of all applicable settings in the Values struct
|
// Restore the global state of all applicable settings in the Values struct
|
||||||
void RestoreGlobalState(bool is_powered_on);
|
void RestoreGlobalState(bool is_powered_on);
|
||||||
|
|
||||||
bool IsConfiguringGlobal();
|
|
||||||
void SetConfiguringGlobal(bool is_global);
|
|
||||||
|
|
||||||
} // namespace Settings
|
} // 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 {
|
} else {
|
||||||
// Unsafe optimizations
|
// Unsafe optimizations
|
||||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) {
|
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
||||||
config.unsafe_optimizations = true;
|
config.unsafe_optimizations = true;
|
||||||
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
|
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||||
@ -307,7 +307,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Curated optimizations
|
// 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.unsafe_optimizations = true;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
|
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
|
// 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.unsafe_optimizations = false;
|
||||||
config.optimizations = Dynarmic::no_optimizations;
|
config.optimizations = Dynarmic::no_optimizations;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Unsafe optimizations
|
// Unsafe optimizations
|
||||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) {
|
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
||||||
config.unsafe_optimizations = true;
|
config.unsafe_optimizations = true;
|
||||||
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
|
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||||
@ -367,7 +367,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Curated optimizations
|
// 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.unsafe_optimizations = true;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||||
config.fastmem_address_space_bits = 64;
|
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
|
// 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.unsafe_optimizations = false;
|
||||||
config.optimizations = Dynarmic::no_optimizations;
|
config.optimizations = Dynarmic::no_optimizations;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/settings_enums.h"
|
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/arm/exclusive_monitor.h"
|
#include "core/arm/exclusive_monitor.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
@ -141,13 +140,16 @@ struct System::Impl {
|
|||||||
device_memory = std::make_unique<Core::DeviceMemory>();
|
device_memory = std::make_unique<Core::DeviceMemory>();
|
||||||
|
|
||||||
is_multicore = Settings::values.use_multi_core.GetValue();
|
is_multicore = Settings::values.use_multi_core.GetValue();
|
||||||
extended_memory_layout =
|
extended_memory_layout = Settings::values.use_unsafe_extended_memory_layout.GetValue();
|
||||||
Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb;
|
|
||||||
|
|
||||||
core_timing.SetMulticore(is_multicore);
|
core_timing.SetMulticore(is_multicore);
|
||||||
core_timing.Initialize([&system]() { system.RegisterHostThread(); });
|
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.
|
// Create a default fs if one doesn't already exist.
|
||||||
if (virtual_filesystem == nullptr) {
|
if (virtual_filesystem == nullptr) {
|
||||||
@ -170,8 +172,7 @@ struct System::Impl {
|
|||||||
void ReinitializeIfNecessary(System& system) {
|
void ReinitializeIfNecessary(System& system) {
|
||||||
const bool must_reinitialize =
|
const bool must_reinitialize =
|
||||||
is_multicore != Settings::values.use_multi_core.GetValue() ||
|
is_multicore != Settings::values.use_multi_core.GetValue() ||
|
||||||
extended_memory_layout != (Settings::values.memory_layout_mode.GetValue() !=
|
extended_memory_layout != Settings::values.use_unsafe_extended_memory_layout.GetValue();
|
||||||
Settings::MemoryLayout::Memory_4Gb);
|
|
||||||
|
|
||||||
if (!must_reinitialize) {
|
if (!must_reinitialize) {
|
||||||
return;
|
return;
|
||||||
@ -180,22 +181,11 @@ struct System::Impl {
|
|||||||
LOG_DEBUG(Kernel, "Re-initializing");
|
LOG_DEBUG(Kernel, "Re-initializing");
|
||||||
|
|
||||||
is_multicore = Settings::values.use_multi_core.GetValue();
|
is_multicore = Settings::values.use_multi_core.GetValue();
|
||||||
extended_memory_layout =
|
extended_memory_layout = Settings::values.use_unsafe_extended_memory_layout.GetValue();
|
||||||
Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb;
|
|
||||||
|
|
||||||
Initialize(system);
|
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() {
|
void Run() {
|
||||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||||
|
|
||||||
@ -1038,8 +1028,6 @@ void System::Exit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void System::ApplySettings() {
|
void System::ApplySettings() {
|
||||||
impl->RefreshTime();
|
|
||||||
|
|
||||||
if (IsPoweredOn()) {
|
if (IsPoweredOn()) {
|
||||||
Renderer().RefreshBaseSettings();
|
Renderer().RefreshBaseSettings();
|
||||||
}
|
}
|
||||||
|
@ -263,23 +263,6 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
|
|||||||
|
|
||||||
std::vector<u8> mem(size);
|
std::vector<u8> mem(size);
|
||||||
if (system.ApplicationMemory().ReadBlock(addr, mem.data(), 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));
|
SendReply(Common::HexToString(mem));
|
||||||
} else {
|
} else {
|
||||||
SendReply(GDB_STUB_REPLY_ERR);
|
SendReply(GDB_STUB_REPLY_ERR);
|
||||||
|
@ -68,8 +68,7 @@ NACP::NACP(VirtualFile file) {
|
|||||||
NACP::~NACP() = default;
|
NACP::~NACP() = default;
|
||||||
|
|
||||||
const LanguageEntry& NACP::GetLanguageEntry() const {
|
const LanguageEntry& NACP::GetLanguageEntry() const {
|
||||||
Language language =
|
Language language = language_to_codes[Settings::values.language_index.GetValue()];
|
||||||
language_to_codes[static_cast<s32>(Settings::values.language_index.GetValue())];
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto& language_entry = raw.language_entries.at(static_cast<u8>(language));
|
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);
|
auto nacp = nacp_file == nullptr ? nullptr : std::make_unique<NACP>(nacp_file);
|
||||||
|
|
||||||
// Get language code from settings
|
// Get language code from settings
|
||||||
const auto language_code = Service::Set::GetLanguageCodeFromIndex(
|
const auto language_code =
|
||||||
static_cast<u32>(Settings::values.language_index.GetValue()));
|
Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index.GetValue());
|
||||||
|
|
||||||
// Convert to application language and get priority list
|
// Convert to application language and get priority list
|
||||||
const auto application_language =
|
const auto application_language =
|
||||||
|
@ -35,7 +35,7 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw_file) {
|
|||||||
update_raw = std::move(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) {
|
if (!updatable) {
|
||||||
return file;
|
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);
|
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);
|
auto nca = content_provider.GetEntry(title_id, type);
|
||||||
|
|
||||||
if (nca == nullptr) {
|
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};
|
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);
|
return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RomFSFactory::OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index,
|
ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFSWithProgramIndex(
|
||||||
ContentRecordType type) const {
|
u64 title_id, u8 program_index, ContentRecordType type) const {
|
||||||
const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index);
|
const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index);
|
||||||
|
|
||||||
return OpenPatchedRomFS(res_title_id, type);
|
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);
|
const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type);
|
||||||
if (res == nullptr) {
|
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,
|
std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage,
|
||||||
|
@ -41,11 +41,13 @@ public:
|
|||||||
~RomFSFactory();
|
~RomFSFactory();
|
||||||
|
|
||||||
void SetPackedUpdate(VirtualFile update_raw_file);
|
void SetPackedUpdate(VirtualFile update_raw_file);
|
||||||
[[nodiscard]] VirtualFile OpenCurrentProcess(u64 current_process_title_id) const;
|
[[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
|
||||||
[[nodiscard]] VirtualFile OpenPatchedRomFS(u64 title_id, ContentRecordType type) const;
|
[[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFS(u64 title_id,
|
||||||
[[nodiscard]] VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index,
|
ContentRecordType type) const;
|
||||||
ContentRecordType type) const;
|
[[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFSWithProgramIndex(
|
||||||
[[nodiscard]] VirtualFile Open(u64 title_id, StorageId storage, ContentRecordType type) const;
|
u64 title_id, u8 program_index, ContentRecordType type) const;
|
||||||
|
[[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage,
|
||||||
|
ContentRecordType type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage,
|
[[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;
|
SaveDataFactory::~SaveDataFactory() = default;
|
||||||
|
|
||||||
VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
|
ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
|
||||||
|
const SaveDataAttribute& meta) const {
|
||||||
PrintSaveDataAttributeWarnings(meta);
|
PrintSaveDataAttributeWarnings(meta);
|
||||||
|
|
||||||
const auto save_directory =
|
const auto save_directory =
|
||||||
GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
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 =
|
const auto save_directory =
|
||||||
GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
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 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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +89,8 @@ public:
|
|||||||
explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_);
|
explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_);
|
||||||
~SaveDataFactory();
|
~SaveDataFactory();
|
||||||
|
|
||||||
VirtualDir Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
|
ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
|
||||||
VirtualDir Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
|
ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
|
||||||
|
|
||||||
VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
|
VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ SDMCFactory::SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_)
|
|||||||
|
|
||||||
SDMCFactory::~SDMCFactory() = default;
|
SDMCFactory::~SDMCFactory() = default;
|
||||||
|
|
||||||
VirtualDir SDMCFactory::Open() const {
|
ResultVal<VirtualDir> SDMCFactory::Open() const {
|
||||||
return sd_dir;
|
return sd_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ public:
|
|||||||
explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_);
|
explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_);
|
||||||
~SDMCFactory();
|
~SDMCFactory();
|
||||||
|
|
||||||
VirtualDir Open() const;
|
ResultVal<VirtualDir> Open() const;
|
||||||
|
|
||||||
VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const;
|
VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const;
|
||||||
VirtualDir GetSDMCContentDirectory() const;
|
VirtualDir GetSDMCContentDirectory() const;
|
||||||
|
@ -289,19 +289,6 @@ enum class GyroscopeZeroDriftMode : u32 {
|
|||||||
Tight = 2,
|
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
|
// This is nn::hid::NpadStyleTag
|
||||||
struct NpadStyleTag {
|
struct NpadStyleTag {
|
||||||
union {
|
union {
|
||||||
@ -347,14 +334,6 @@ struct TouchState {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
|
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 {
|
struct NpadColor {
|
||||||
u8 r{};
|
u8 r{};
|
||||||
u8 g{};
|
u8 g{};
|
||||||
@ -683,11 +662,6 @@ struct MouseState {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size");
|
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.
|
/// Converts a NpadIdType to an array index.
|
||||||
constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
|
constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
|
||||||
switch (npad_id_type) {
|
switch (npad_id_type) {
|
||||||
|
@ -35,27 +35,13 @@ namespace {
|
|||||||
using namespace Common::Literals;
|
using namespace Common::Literals;
|
||||||
|
|
||||||
u32 GetMemorySizeForInit() {
|
u32 GetMemorySizeForInit() {
|
||||||
switch (Settings::values.memory_layout_mode.GetValue()) {
|
return Settings::values.use_unsafe_extended_memory_layout ? Smc::MemorySize_8GB
|
||||||
case Settings::MemoryLayout::Memory_4Gb:
|
: Smc::MemorySize_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Smc::MemoryArrangement GetMemoryArrangeForInit() {
|
Smc::MemoryArrangement GetMemoryArrangeForInit() {
|
||||||
switch (Settings::values.memory_layout_mode.GetValue()) {
|
return Settings::values.use_unsafe_extended_memory_layout ? Smc::MemoryArrangement_8GB
|
||||||
case Settings::MemoryLayout::Memory_4Gb:
|
: Smc::MemoryArrangement_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;
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -768,7 +768,7 @@ Result KPageTable::UnmapProcessMemory(KProcessAddress dst_addr, size_t size,
|
|||||||
m_memory_block_slab_manager, num_allocator_blocks);
|
m_memory_block_slab_manager, num_allocator_blocks);
|
||||||
R_TRY(allocator_result);
|
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.
|
// Apply the memory block update.
|
||||||
m_memory_block_manager.Update(std::addressof(allocator), dst_addr, num_pages,
|
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_capabilities.InitializeForMetadatalessProcess();
|
||||||
process->m_is_initialized = true;
|
process->m_is_initialized = true;
|
||||||
|
|
||||||
std::mt19937 rng(Settings::values.rng_seed_enabled ? Settings::values.rng_seed.GetValue()
|
std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr)));
|
||||||
: static_cast<u32>(std::time(nullptr)));
|
|
||||||
std::uniform_int_distribution<u64> distribution;
|
std::uniform_int_distribution<u64> distribution;
|
||||||
std::generate(process->m_random_entropy.begin(), process->m_random_entropy.end(),
|
std::generate(process->m_random_entropy.begin(), process->m_random_entropy.end(),
|
||||||
[&] { return distribution(rng); });
|
[&] { return distribution(rng); });
|
||||||
|
@ -283,6 +283,159 @@ private:
|
|||||||
u32 description_end;
|
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_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess())
|
||||||
#define R_FAILED(res) (static_cast<Result>(res).IsFailure())
|
#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
|
// 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
|
// processes emulated. As we don't actually have pid support we should assume we're just using
|
||||||
// our own process
|
// our own process
|
||||||
Glue::ApplicationLaunchProperty launch_property{};
|
const auto launch_property =
|
||||||
const auto result = system.GetARPManager().GetLaunchProperty(
|
system.GetARPManager().GetLaunchProperty(system.GetApplicationProcessProgramID());
|
||||||
&launch_property, system.GetApplicationProcessProgramID());
|
|
||||||
|
|
||||||
if (result != ResultSuccess) {
|
if (launch_property.Failed()) {
|
||||||
LOG_ERROR(Service_ACC, "Failed to get launch property");
|
LOG_ERROR(Service_ACC, "Failed to get launch property");
|
||||||
return Account::ResultInvalidApplication;
|
return Account::ResultInvalidApplication;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (launch_property.base_game_storage_id) {
|
switch (launch_property->base_game_storage_id) {
|
||||||
case FileSys::StorageId::GameCard:
|
case FileSys::StorageId::GameCard:
|
||||||
application_info.application_type = ApplicationType::GameCard;
|
application_info.application_type = ApplicationType::GameCard;
|
||||||
break;
|
break;
|
||||||
@ -786,7 +785,7 @@ Result Module::Interface::InitializeApplicationInfoBase() {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}",
|
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;
|
return Account::ResultInvalidApplication;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1317,50 +1317,6 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
|
|||||||
rb.PushIpcInterface<IStorage>(system, std::move(memory));
|
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_)
|
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||||
: ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
|
: ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
|
||||||
"IApplicationFunctions"} {
|
"IApplicationFunctions"} {
|
||||||
@ -1578,13 +1534,11 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
|
|||||||
attribute.title_id = system.GetApplicationProcessProgramID();
|
attribute.title_id = system.GetApplicationProcessProgramID();
|
||||||
attribute.user_id = user_id;
|
attribute.user_id = user_id;
|
||||||
attribute.type = FileSys::SaveDataType::SaveData;
|
attribute.type = FileSys::SaveDataType::SaveData;
|
||||||
|
|
||||||
FileSys::VirtualDir save_data{};
|
|
||||||
const auto res = system.GetFileSystemController().CreateSaveData(
|
const auto res = system.GetFileSystemController().CreateSaveData(
|
||||||
&save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
|
FileSys::SaveDataSpaceId::NandUser, attribute);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
rb.Push<u64>(0);
|
rb.Push<u64>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1669,30 +1623,26 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
|
|||||||
auto app_man = ns_am2->GetApplicationManagerInterface();
|
auto app_man = ns_am2->GetApplicationManagerInterface();
|
||||||
|
|
||||||
// Get desired application language
|
// Get desired application language
|
||||||
u8 desired_language{};
|
const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages);
|
||||||
const auto res_lang =
|
if (res_lang.Failed()) {
|
||||||
app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
|
|
||||||
if (res_lang != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res_lang);
|
rb.Push(res_lang.Code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to settings language code.
|
// Convert to settings language code.
|
||||||
u64 language_code{};
|
const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang);
|
||||||
const auto res_code =
|
if (res_code.Failed()) {
|
||||||
app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
|
|
||||||
if (res_code != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res_code);
|
rb.Push(res_code.Code());
|
||||||
return;
|
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};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(language_code);
|
rb.Push(*res_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
|
void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
|
||||||
|
@ -22,6 +22,30 @@ class Nvnflinger;
|
|||||||
|
|
||||||
namespace Service::AM {
|
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 {
|
class AppletMessageQueue {
|
||||||
public:
|
public:
|
||||||
// This is nn::am::AppletMessage
|
// This is nn::am::AppletMessage
|
||||||
@ -290,12 +314,6 @@ private:
|
|||||||
void CreateHandleStorage(HLERequestContext& ctx);
|
void CreateHandleStorage(HLERequestContext& ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
|
||||||
public:
|
|
||||||
explicit ILibraryAppletSelfAccessor(Core::System& system_);
|
|
||||||
~ILibraryAppletSelfAccessor() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationFunctions(Core::System& system_);
|
explicit IApplicationFunctions(Core::System& system_);
|
||||||
|
@ -26,10 +26,8 @@ public:
|
|||||||
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
|
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
|
||||||
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
|
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
|
||||||
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
||||||
{20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
|
{20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"},
|
||||||
{21, nullptr, "GetAppletCommonFunctions"},
|
{21, nullptr, "GetAppletCommonFunctions"},
|
||||||
{22, nullptr, "GetHomeMenuFunctions"},
|
|
||||||
{23, nullptr, "GetGlobalStateController"},
|
|
||||||
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
@ -102,12 +100,12 @@ private:
|
|||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
|
void GetApplicationFunctions(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
|
rb.PushIpcInterface<IApplicationFunctions>(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
|
@ -22,13 +22,13 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
|
|||||||
{9, nullptr, "GetAudioOutputMode"},
|
{9, nullptr, "GetAudioOutputMode"},
|
||||||
{10, nullptr, "SetAudioOutputMode"},
|
{10, nullptr, "SetAudioOutputMode"},
|
||||||
{11, nullptr, "SetForceMutePolicy"},
|
{11, nullptr, "SetForceMutePolicy"},
|
||||||
{12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
|
{12, nullptr, "GetForceMutePolicy"},
|
||||||
{13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
|
{13, nullptr, "GetOutputModeSetting"},
|
||||||
{14, nullptr, "SetOutputModeSetting"},
|
{14, nullptr, "SetOutputModeSetting"},
|
||||||
{15, nullptr, "SetOutputTarget"},
|
{15, nullptr, "SetOutputTarget"},
|
||||||
{16, nullptr, "SetInputTargetForceEnabled"},
|
{16, nullptr, "SetInputTargetForceEnabled"},
|
||||||
{17, nullptr, "SetHeadphoneOutputLevelMode"},
|
{17, nullptr, "SetHeadphoneOutputLevelMode"},
|
||||||
{18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
|
{18, nullptr, "GetHeadphoneOutputLevelMode"},
|
||||||
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
|
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
|
||||||
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
|
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
|
||||||
{21, nullptr, "GetAudioOutputTargetForPlayReport"},
|
{21, nullptr, "GetAudioOutputTargetForPlayReport"},
|
||||||
@ -41,7 +41,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
|
|||||||
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
||||||
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
||||||
{30, nullptr, "SetSpeakerAutoMuteEnabled"},
|
{30, nullptr, "SetSpeakerAutoMuteEnabled"},
|
||||||
{31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
|
{31, nullptr, "IsSpeakerAutoMuteEnabled"},
|
||||||
{32, nullptr, "GetActiveOutputTarget"},
|
{32, nullptr, "GetActiveOutputTarget"},
|
||||||
{33, nullptr, "GetTargetDeviceInfo"},
|
{33, nullptr, "GetTargetDeviceInfo"},
|
||||||
{34, nullptr, "AcquireTargetNotification"},
|
{34, nullptr, "AcquireTargetNotification"},
|
||||||
@ -96,42 +96,4 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
|
|||||||
rb.Push(target_max_volume);
|
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
|
} // namespace Service::Audio
|
||||||
|
@ -17,30 +17,8 @@ public:
|
|||||||
~AudCtl() override;
|
~AudCtl() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class AudioOutputMode {
|
|
||||||
Invalid,
|
|
||||||
Pcm1ch,
|
|
||||||
Pcm2ch,
|
|
||||||
Pcm6ch,
|
|
||||||
PcmAuto,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ForceMutePolicy {
|
|
||||||
Disable,
|
|
||||||
SpeakerMuteOnHeadphoneUnplugged,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class HeadphoneOutputLevelMode {
|
|
||||||
Normal,
|
|
||||||
HighPower,
|
|
||||||
};
|
|
||||||
|
|
||||||
void GetTargetVolumeMin(HLERequestContext& ctx);
|
void GetTargetVolumeMin(HLERequestContext& ctx);
|
||||||
void GetTargetVolumeMax(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
|
} // namespace Service::Audio
|
||||||
|
@ -57,8 +57,8 @@ Result VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size
|
|||||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSys::EntryType entry_type{};
|
const auto entry_type = GetEntryType(path);
|
||||||
if (GetEntryType(&entry_type, path) == ResultSuccess) {
|
if (entry_type.Code() == ResultSuccess) {
|
||||||
return FileSys::ERROR_PATH_ALREADY_EXISTS;
|
return FileSys::ERROR_PATH_ALREADY_EXISTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,8 +210,8 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,
|
|||||||
return ResultUnknown;
|
return ResultUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file,
|
ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_,
|
||||||
const std::string& path_, FileSys::Mode mode) const {
|
FileSys::Mode mode) const {
|
||||||
const std::string path(Common::FS::SanitizePath(path_));
|
const std::string path(Common::FS::SanitizePath(path_));
|
||||||
std::string_view npath = path;
|
std::string_view npath = path;
|
||||||
while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) {
|
while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) {
|
||||||
@ -224,68 +224,50 @@ Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mode == FileSys::Mode::Append) {
|
if (mode == FileSys::Mode::Append) {
|
||||||
*out_file = std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize());
|
return std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize());
|
||||||
} else {
|
|
||||||
*out_file = file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result VfsDirectoryServiceWrapper::OpenDirectory(FileSys::VirtualDir* out_directory,
|
ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) {
|
||||||
const std::string& path_) {
|
|
||||||
std::string path(Common::FS::SanitizePath(path_));
|
std::string path(Common::FS::SanitizePath(path_));
|
||||||
auto dir = GetDirectoryRelativeWrapped(backing, path);
|
auto dir = GetDirectoryRelativeWrapped(backing, path);
|
||||||
if (dir == nullptr) {
|
if (dir == nullptr) {
|
||||||
// TODO(DarkLordZach): Find a better error code for this
|
// TODO(DarkLordZach): Find a better error code for this
|
||||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
*out_directory = dir;
|
return dir;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::EntryType* out_entry_type,
|
ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
|
||||||
const std::string& path_) const {
|
const std::string& path_) const {
|
||||||
std::string path(Common::FS::SanitizePath(path_));
|
std::string path(Common::FS::SanitizePath(path_));
|
||||||
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
|
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
|
||||||
if (dir == nullptr) {
|
if (dir == nullptr)
|
||||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||||
}
|
|
||||||
|
|
||||||
auto filename = Common::FS::GetFilename(path);
|
auto filename = Common::FS::GetFilename(path);
|
||||||
// TODO(Subv): Some games use the '/' path, find out what this means.
|
// TODO(Subv): Some games use the '/' path, find out what this means.
|
||||||
if (filename.empty()) {
|
if (filename.empty())
|
||||||
*out_entry_type = FileSys::EntryType::Directory;
|
return 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 (dir->GetFile(filename) != nullptr)
|
||||||
|
return FileSys::EntryType::File;
|
||||||
|
if (dir->GetSubdirectory(filename) != nullptr)
|
||||||
|
return FileSys::EntryType::Directory;
|
||||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw(
|
ResultVal<FileSys::FileTimeStampRaw> VfsDirectoryServiceWrapper::GetFileTimeStampRaw(
|
||||||
FileSys::FileTimeStampRaw* out_file_time_stamp_raw, const std::string& path) const {
|
const std::string& path) const {
|
||||||
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
|
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
|
||||||
if (dir == nullptr) {
|
if (dir == nullptr) {
|
||||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
if (GetEntryType(path).Failed()) {
|
||||||
FileSys::EntryType entry_type;
|
|
||||||
if (GetEntryType(&entry_type, path) != ResultSuccess) {
|
|
||||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
return dir->GetFileTimeStamp(Common::FS::GetFilename(path));
|
||||||
*out_file_time_stamp_raw = dir->GetFileTimeStamp(Common::FS::GetFilename(path));
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystemController::FileSystemController(Core::System& system_) : system{system_} {}
|
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));
|
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");
|
LOG_TRACE(Service_FS, "Opening RomFS for current process");
|
||||||
|
|
||||||
if (romfs_factory == nullptr) {
|
if (romfs_factory == nullptr) {
|
||||||
return nullptr;
|
// TODO(bunnei): Find a better error code for this
|
||||||
|
return ResultUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID());
|
return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID());
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSys::VirtualFile FileSystemController::OpenPatchedRomFS(u64 title_id,
|
ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFS(
|
||||||
FileSys::ContentRecordType type) const {
|
u64 title_id, FileSys::ContentRecordType type) const {
|
||||||
LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id);
|
LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id);
|
||||||
|
|
||||||
if (romfs_factory == nullptr) {
|
if (romfs_factory == nullptr) {
|
||||||
return nullptr;
|
// TODO: Find a better error code for this
|
||||||
|
return ResultUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
return romfs_factory->OpenPatchedRomFS(title_id, type);
|
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 {
|
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,
|
LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id,
|
||||||
program_index);
|
program_index);
|
||||||
|
|
||||||
if (romfs_factory == nullptr) {
|
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);
|
return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSys::VirtualFile FileSystemController::OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
|
ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS(
|
||||||
FileSys::ContentRecordType type) const {
|
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}",
|
LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}",
|
||||||
title_id, storage_id, type);
|
title_id, storage_id, type);
|
||||||
|
|
||||||
if (romfs_factory == nullptr) {
|
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);
|
return romfs_factory->Open(title_id, storage_id, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data,
|
ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData(
|
||||||
FileSys::SaveDataSpaceId space,
|
FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const {
|
||||||
const FileSys::SaveDataAttribute& save_struct) const {
|
|
||||||
LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space,
|
LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space,
|
||||||
save_struct.DebugInfo());
|
save_struct.DebugInfo());
|
||||||
|
|
||||||
@ -383,18 +368,11 @@ Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data,
|
|||||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto save_data = save_data_factory->Create(space, save_struct);
|
return save_data_factory->Create(space, save_struct);
|
||||||
if (save_data == nullptr) {
|
|
||||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_save_data = save_data;
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data,
|
ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData(
|
||||||
FileSys::SaveDataSpaceId space,
|
FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& attribute) const {
|
||||||
const FileSys::SaveDataAttribute& attribute) const {
|
|
||||||
LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space,
|
LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space,
|
||||||
attribute.DebugInfo());
|
attribute.DebugInfo());
|
||||||
|
|
||||||
@ -402,50 +380,32 @@ Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data,
|
|||||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto save_data = save_data_factory->Open(space, attribute);
|
return save_data_factory->Open(space, attribute);
|
||||||
if (save_data == nullptr) {
|
|
||||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_save_data = save_data;
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FileSystemController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space,
|
ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveDataSpace(
|
||||||
FileSys::SaveDataSpaceId space) const {
|
FileSys::SaveDataSpaceId space) const {
|
||||||
LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space);
|
LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space);
|
||||||
|
|
||||||
if (save_data_factory == nullptr) {
|
if (save_data_factory == nullptr) {
|
||||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto save_data_space = save_data_factory->GetSaveDataSpaceDirectory(space);
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const {
|
ResultVal<FileSys::VirtualDir> FileSystemController::OpenSDMC() const {
|
||||||
LOG_TRACE(Service_FS, "Opening SDMC");
|
LOG_TRACE(Service_FS, "Opening SDMC");
|
||||||
|
|
||||||
if (sdmc_factory == nullptr) {
|
if (sdmc_factory == nullptr) {
|
||||||
return FileSys::ERROR_SD_CARD_NOT_FOUND;
|
return FileSys::ERROR_SD_CARD_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sdmc = sdmc_factory->Open();
|
return sdmc_factory->Open();
|
||||||
if (sdmc == nullptr) {
|
|
||||||
return FileSys::ERROR_SD_CARD_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_sdmc = sdmc;
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_partition,
|
ResultVal<FileSys::VirtualDir> FileSystemController::OpenBISPartition(
|
||||||
FileSys::BisPartitionId id) const {
|
FileSys::BisPartitionId id) const {
|
||||||
LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id);
|
LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id);
|
||||||
|
|
||||||
if (bis_factory == nullptr) {
|
if (bis_factory == nullptr) {
|
||||||
@ -457,12 +417,11 @@ Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_parti
|
|||||||
return FileSys::ERROR_INVALID_ARGUMENT;
|
return FileSys::ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_bis_partition = part;
|
return part;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FileSystemController::OpenBISPartitionStorage(
|
ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage(
|
||||||
FileSys::VirtualFile* out_bis_partition_storage, FileSys::BisPartitionId id) const {
|
FileSys::BisPartitionId id) const {
|
||||||
LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id);
|
LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id);
|
||||||
|
|
||||||
if (bis_factory == nullptr) {
|
if (bis_factory == nullptr) {
|
||||||
@ -474,8 +433,7 @@ Result FileSystemController::OpenBISPartitionStorage(
|
|||||||
return FileSys::ERROR_INVALID_ARGUMENT;
|
return FileSys::ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_bis_partition_storage = part;
|
return part;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const {
|
u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const {
|
||||||
|
@ -64,24 +64,21 @@ public:
|
|||||||
Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
|
Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
|
||||||
|
|
||||||
void SetPackedUpdate(FileSys::VirtualFile update_raw);
|
void SetPackedUpdate(FileSys::VirtualFile update_raw);
|
||||||
FileSys::VirtualFile OpenRomFSCurrentProcess() const;
|
ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const;
|
||||||
FileSys::VirtualFile OpenPatchedRomFS(u64 title_id, FileSys::ContentRecordType type) const;
|
ResultVal<FileSys::VirtualFile> OpenPatchedRomFS(u64 title_id,
|
||||||
FileSys::VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index,
|
FileSys::ContentRecordType type) const;
|
||||||
FileSys::ContentRecordType type) const;
|
ResultVal<FileSys::VirtualFile> OpenPatchedRomFSWithProgramIndex(
|
||||||
FileSys::VirtualFile OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
|
u64 title_id, u8 program_index, FileSys::ContentRecordType type) const;
|
||||||
FileSys::ContentRecordType type) const;
|
ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
|
||||||
|
FileSys::ContentRecordType type) const;
|
||||||
Result CreateSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space,
|
ResultVal<FileSys::VirtualDir> CreateSaveData(
|
||||||
const FileSys::SaveDataAttribute& save_struct) const;
|
FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const;
|
||||||
Result OpenSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space,
|
ResultVal<FileSys::VirtualDir> OpenSaveData(
|
||||||
const FileSys::SaveDataAttribute& save_struct) const;
|
FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const;
|
||||||
Result OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space,
|
ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) const;
|
||||||
FileSys::SaveDataSpaceId space) const;
|
ResultVal<FileSys::VirtualDir> OpenSDMC() const;
|
||||||
Result OpenSDMC(FileSys::VirtualDir* out_sdmc) const;
|
ResultVal<FileSys::VirtualDir> OpenBISPartition(FileSys::BisPartitionId id) const;
|
||||||
Result OpenBISPartition(FileSys::VirtualDir* out_bis_partition,
|
ResultVal<FileSys::VirtualFile> OpenBISPartitionStorage(FileSys::BisPartitionId id) const;
|
||||||
FileSys::BisPartitionId id) const;
|
|
||||||
Result OpenBISPartitionStorage(FileSys::VirtualFile* out_bis_partition_storage,
|
|
||||||
FileSys::BisPartitionId id) const;
|
|
||||||
|
|
||||||
u64 GetFreeSpaceSize(FileSys::StorageId id) const;
|
u64 GetFreeSpaceSize(FileSys::StorageId id) const;
|
||||||
u64 GetTotalSpaceSize(FileSys::StorageId id) const;
|
u64 GetTotalSpaceSize(FileSys::StorageId id) const;
|
||||||
@ -227,28 +224,26 @@ public:
|
|||||||
* @param mode Mode to open the file with
|
* @param mode Mode to open the file with
|
||||||
* @return Opened file, or error code
|
* @return Opened file, or error code
|
||||||
*/
|
*/
|
||||||
Result OpenFile(FileSys::VirtualFile* out_file, const std::string& path,
|
ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const;
|
||||||
FileSys::Mode mode) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a directory specified by its path
|
* Open a directory specified by its path
|
||||||
* @param path Path relative to the archive
|
* @param path Path relative to the archive
|
||||||
* @return Opened directory, or error code
|
* @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
|
* Get the type of the specified path
|
||||||
* @return The type of the specified path or error code
|
* @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
|
* Get the timestamp of the specified path
|
||||||
* @return The timestamp of the specified path or error code
|
* @return The timestamp of the specified path or error code
|
||||||
*/
|
*/
|
||||||
Result GetFileTimeStampRaw(FileSys::FileTimeStampRaw* out_time_stamp_raw,
|
ResultVal<FileSys::FileTimeStampRaw> GetFileTimeStampRaw(const std::string& path) const;
|
||||||
const std::string& path) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileSys::VirtualDir backing;
|
FileSys::VirtualDir backing;
|
||||||
|
@ -419,15 +419,14 @@ public:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode);
|
LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode);
|
||||||
|
|
||||||
FileSys::VirtualFile vfs_file{};
|
auto result = backend.OpenFile(name, mode);
|
||||||
auto result = backend.OpenFile(&vfs_file, name, mode);
|
if (result.Failed()) {
|
||||||
if (result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result.Code());
|
||||||
return;
|
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};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
@ -445,15 +444,14 @@ public:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags);
|
LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags);
|
||||||
|
|
||||||
FileSys::VirtualDir vfs_dir{};
|
auto result = backend.OpenDirectory(name);
|
||||||
auto result = backend.OpenDirectory(&vfs_dir, name);
|
if (result.Failed()) {
|
||||||
if (result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result.Code());
|
||||||
return;
|
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};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
@ -466,17 +464,16 @@ public:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_FS, "called. file={}", name);
|
LOG_DEBUG(Service_FS, "called. file={}", name);
|
||||||
|
|
||||||
FileSys::EntryType vfs_entry_type{};
|
auto result = backend.GetEntryType(name);
|
||||||
auto result = backend.GetEntryType(&vfs_entry_type, name);
|
if (result.Failed()) {
|
||||||
if (result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result.Code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u32>(static_cast<u32>(vfs_entry_type));
|
rb.Push<u32>(static_cast<u32>(*result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Commit(HLERequestContext& ctx) {
|
void Commit(HLERequestContext& ctx) {
|
||||||
@ -508,17 +505,16 @@ public:
|
|||||||
|
|
||||||
LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name);
|
LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name);
|
||||||
|
|
||||||
FileSys::FileTimeStampRaw vfs_timestamp{};
|
auto result = backend.GetFileTimeStampRaw(name);
|
||||||
auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name);
|
if (result.Failed()) {
|
||||||
if (result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result.Code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 10};
|
IPC::ResponseBuilder rb{ctx, 10};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw(vfs_timestamp);
|
rb.PushRaw(*result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -576,15 +572,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FindAllSaves(FileSys::SaveDataSpaceId space) {
|
void FindAllSaves(FileSys::SaveDataSpaceId space) {
|
||||||
FileSys::VirtualDir save_root{};
|
const auto save_root = fsc.OpenSaveDataSpace(space);
|
||||||
const auto result = fsc.OpenSaveDataSpace(&save_root, 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);
|
LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& type : save_root->GetSubdirectories()) {
|
for (const auto& type : (*save_root)->GetSubdirectories()) {
|
||||||
if (type->GetName() == "save") {
|
if (type->GetName() == "save") {
|
||||||
for (const auto& save_id : type->GetSubdirectories()) {
|
for (const auto& save_id : type->GetSubdirectories()) {
|
||||||
for (const auto& user_id : save_id->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) {
|
void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_FS, "called");
|
LOG_DEBUG(Service_FS, "called");
|
||||||
|
|
||||||
FileSys::VirtualDir sdmc_dir{};
|
auto filesystem =
|
||||||
fsc.OpenSDMC(&sdmc_dir);
|
std::make_shared<IFileSystem>(system, fsc.OpenSDMC().Unwrap(),
|
||||||
|
SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard));
|
||||||
auto filesystem = std::make_shared<IFileSystem>(
|
|
||||||
system, sdmc_dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard));
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
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(),
|
LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(),
|
||||||
uid[1], uid[0]);
|
uid[1], uid[0]);
|
||||||
|
|
||||||
FileSys::VirtualDir save_data_dir{};
|
fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandUser, save_struct);
|
||||||
fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandUser, save_struct);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
@ -882,9 +874,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
LOG_INFO(Service_FS, "called.");
|
LOG_INFO(Service_FS, "called.");
|
||||||
|
|
||||||
FileSys::VirtualDir dir{};
|
auto dir = fsc.OpenSaveData(parameters.space_id, parameters.attribute);
|
||||||
auto result = fsc.OpenSaveData(&dir, parameters.space_id, parameters.attribute);
|
if (dir.Failed()) {
|
||||||
if (result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
|
||||||
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
|
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
@ -908,8 +899,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
|
|||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto filesystem =
|
auto filesystem = std::make_shared<IFileSystem>(system, std::move(dir.Unwrap()),
|
||||||
std::make_shared<IFileSystem>(system, std::move(dir), SizeGetter::FromStorageId(fsc, id));
|
SizeGetter::FromStorageId(fsc, id));
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
@ -979,7 +970,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
if (!romfs) {
|
if (!romfs) {
|
||||||
auto current_romfs = fsc.OpenRomFSCurrentProcess();
|
auto current_romfs = fsc.OpenRomFSCurrentProcess();
|
||||||
if (!current_romfs) {
|
if (current_romfs.Failed()) {
|
||||||
// TODO (bunnei): Find the right error code to use here
|
// TODO (bunnei): Find the right error code to use here
|
||||||
LOG_CRITICAL(Service_FS, "no file system interface available!");
|
LOG_CRITICAL(Service_FS, "no file system interface available!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
@ -987,7 +978,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
romfs = current_romfs;
|
romfs = current_romfs.Unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto storage = std::make_shared<IStorage>(system, romfs);
|
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);
|
auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data);
|
||||||
|
|
||||||
if (!data) {
|
if (data.Failed()) {
|
||||||
const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id);
|
const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id);
|
||||||
|
|
||||||
if (archive != nullptr) {
|
if (archive != nullptr) {
|
||||||
@ -1030,7 +1021,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
|
|||||||
const FileSys::PatchManager pm{title_id, fsc, content_provider};
|
const FileSys::PatchManager pm{title_id, fsc, content_provider};
|
||||||
|
|
||||||
auto storage = std::make_shared<IStorage>(
|
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};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
@ -1060,7 +1051,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
|
|||||||
fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index,
|
fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index,
|
||||||
FileSys::ContentRecordType::Program);
|
FileSys::ContentRecordType::Program);
|
||||||
|
|
||||||
if (!patched_romfs) {
|
if (patched_romfs.Failed()) {
|
||||||
// TODO: Find the right error code to use here
|
// TODO: Find the right error code to use here
|
||||||
LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index);
|
LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index);
|
||||||
|
|
||||||
@ -1069,7 +1060,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
|
|||||||
return;
|
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};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -65,19 +65,18 @@ void ARP_R::GetApplicationLaunchProperty(HLERequestContext& ctx) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationLaunchProperty launch_property{};
|
const auto res = manager.GetLaunchProperty(*title_id);
|
||||||
const auto res = manager.GetLaunchProperty(&launch_property, *title_id);
|
|
||||||
|
|
||||||
if (res != ResultSuccess) {
|
if (res.Failed()) {
|
||||||
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw(launch_property);
|
rb.PushRaw(*res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) {
|
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);
|
LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
|
||||||
|
|
||||||
ApplicationLaunchProperty launch_property{};
|
const auto res = manager.GetLaunchProperty(title_id);
|
||||||
const auto res = manager.GetLaunchProperty(&launch_property, title_id);
|
|
||||||
|
|
||||||
if (res != ResultSuccess) {
|
if (res.Failed()) {
|
||||||
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw(launch_property);
|
rb.PushRaw(*res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) {
|
void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) {
|
||||||
@ -115,17 +113,16 @@ void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> nacp_data;
|
const auto res = manager.GetControlProperty(*title_id);
|
||||||
const auto res = manager.GetControlProperty(&nacp_data, *title_id);
|
|
||||||
|
|
||||||
if (res != ResultSuccess) {
|
if (res.Failed()) {
|
||||||
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.WriteBuffer(nacp_data);
|
ctx.WriteBuffer(*res);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
@ -137,17 +134,16 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(HLERequestContext& ct
|
|||||||
|
|
||||||
LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
|
LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
|
||||||
|
|
||||||
std::vector<u8> nacp_data;
|
const auto res = manager.GetControlProperty(title_id);
|
||||||
const auto res = manager.GetControlProperty(&nacp_data, title_id);
|
|
||||||
|
|
||||||
if (res != ResultSuccess) {
|
if (res.Failed()) {
|
||||||
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.WriteBuffer(nacp_data);
|
ctx.WriteBuffer(*res);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -15,8 +15,7 @@ ARPManager::ARPManager() = default;
|
|||||||
|
|
||||||
ARPManager::~ARPManager() = default;
|
ARPManager::~ARPManager() = default;
|
||||||
|
|
||||||
Result ARPManager::GetLaunchProperty(ApplicationLaunchProperty* out_launch_property,
|
ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const {
|
||||||
u64 title_id) const {
|
|
||||||
if (title_id == 0) {
|
if (title_id == 0) {
|
||||||
return Glue::ResultInvalidProcessId;
|
return Glue::ResultInvalidProcessId;
|
||||||
}
|
}
|
||||||
@ -26,11 +25,10 @@ Result ARPManager::GetLaunchProperty(ApplicationLaunchProperty* out_launch_prope
|
|||||||
return Glue::ResultProcessIdNotRegistered;
|
return Glue::ResultProcessIdNotRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_launch_property = iter->second.launch;
|
return iter->second.launch;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if (title_id == 0) {
|
||||||
return Glue::ResultInvalidProcessId;
|
return Glue::ResultInvalidProcessId;
|
||||||
}
|
}
|
||||||
@ -40,8 +38,7 @@ Result ARPManager::GetControlProperty(std::vector<u8>* out_control_property, u64
|
|||||||
return Glue::ResultProcessIdNotRegistered;
|
return Glue::ResultProcessIdNotRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_control_property = iter->second.control;
|
return iter->second.control;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
|
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
|
// Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was
|
||||||
// previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or
|
// previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or
|
||||||
// ResultInvalidProcessId if the title ID is 0.
|
// 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
|
// 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
|
// the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered
|
||||||
// if it was never registered or ResultInvalidProcessId if the title ID is 0.
|
// 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
|
// 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
|
// ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate
|
||||||
|
@ -16,6 +16,22 @@ class EmulatedConsole;
|
|||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
class Controller_Touchscreen final : public ControllerBase {
|
class Controller_Touchscreen final : public ControllerBase {
|
||||||
public:
|
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_);
|
explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
||||||
~Controller_Touchscreen() override;
|
~Controller_Touchscreen() override;
|
||||||
|
|
||||||
|
@ -2368,7 +2368,7 @@ void Hid::GetNpadCommunicationMode(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) {
|
void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{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>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
|
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
|
LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
|
||||||
@ -2543,8 +2543,7 @@ public:
|
|||||||
|
|
||||||
class HidSys final : public ServiceFramework<HidSys> {
|
class HidSys final : public ServiceFramework<HidSys> {
|
||||||
public:
|
public:
|
||||||
explicit HidSys(Core::System& system_)
|
explicit HidSys(Core::System& system_) : ServiceFramework{system_, "hid:sys"} {
|
||||||
: ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{31, nullptr, "SendKeyboardLockKeyEvent"},
|
{31, nullptr, "SendKeyboardLockKeyEvent"},
|
||||||
@ -2569,7 +2568,7 @@ public:
|
|||||||
{303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
|
{303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
|
||||||
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
|
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
|
||||||
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
|
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
|
||||||
{306, &HidSys::GetLastActiveNpad, "GetLastActiveNpad"},
|
{306, nullptr, "GetLastActiveNpad"},
|
||||||
{307, nullptr, "GetNpadSystemExtStyle"},
|
{307, nullptr, "GetNpadSystemExtStyle"},
|
||||||
{308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
|
{308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
|
||||||
{309, nullptr, "GetNpadFullKeyGripColor"},
|
{309, nullptr, "GetNpadFullKeyGripColor"},
|
||||||
@ -2625,7 +2624,7 @@ public:
|
|||||||
{700, nullptr, "ActivateUniquePad"},
|
{700, nullptr, "ActivateUniquePad"},
|
||||||
{702, nullptr, "AcquireUniquePadConnectionEventHandle"},
|
{702, nullptr, "AcquireUniquePadConnectionEventHandle"},
|
||||||
{703, nullptr, "GetUniquePadIds"},
|
{703, nullptr, "GetUniquePadIds"},
|
||||||
{751, &HidSys::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
{751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
||||||
{800, nullptr, "ListSixAxisSensorHandles"},
|
{800, nullptr, "ListSixAxisSensorHandles"},
|
||||||
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
|
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
|
||||||
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
|
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
|
||||||
@ -2651,7 +2650,7 @@ public:
|
|||||||
{830, nullptr, "SetNotificationLedPattern"},
|
{830, nullptr, "SetNotificationLedPattern"},
|
||||||
{831, nullptr, "SetNotificationLedPatternWithTimeout"},
|
{831, nullptr, "SetNotificationLedPatternWithTimeout"},
|
||||||
{832, nullptr, "PrepareHidsForNotificationWake"},
|
{832, nullptr, "PrepareHidsForNotificationWake"},
|
||||||
{850, &HidSys::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
|
{850, nullptr, "IsUsbFullKeyControllerEnabled"},
|
||||||
{851, nullptr, "EnableUsbFullKeyController"},
|
{851, nullptr, "EnableUsbFullKeyController"},
|
||||||
{852, nullptr, "IsUsbConnected"},
|
{852, nullptr, "IsUsbConnected"},
|
||||||
{870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
|
{870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
|
||||||
@ -2683,7 +2682,7 @@ public:
|
|||||||
{1150, nullptr, "SetTouchScreenMagnification"},
|
{1150, nullptr, "SetTouchScreenMagnification"},
|
||||||
{1151, nullptr, "GetTouchScreenFirmwareVersion"},
|
{1151, nullptr, "GetTouchScreenFirmwareVersion"},
|
||||||
{1152, nullptr, "SetTouchScreenDefaultConfiguration"},
|
{1152, nullptr, "SetTouchScreenDefaultConfiguration"},
|
||||||
{1153, &HidSys::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
|
{1153, nullptr, "GetTouchScreenDefaultConfiguration"},
|
||||||
{1154, nullptr, "IsFirmwareAvailableForNotification"},
|
{1154, nullptr, "IsFirmwareAvailableForNotification"},
|
||||||
{1155, nullptr, "SetForceHandheldStyleVibration"},
|
{1155, nullptr, "SetForceHandheldStyleVibration"},
|
||||||
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
|
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
|
||||||
@ -2750,8 +2749,6 @@ public:
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -2763,66 +2760,17 @@ private:
|
|||||||
rb.Push(ResultSuccess);
|
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) {
|
void GetUniquePadsFromNpad(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
|
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);
|
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};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
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) {
|
void LoopProcess(Core::System& system) {
|
||||||
|
@ -357,8 +357,7 @@ public:
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MapProcessCodeMemory(VAddr* out_map_location, Kernel::KProcess* process, VAddr base_addr,
|
ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) {
|
||||||
u64 size) {
|
|
||||||
auto& page_table{process->GetPageTable()};
|
auto& page_table{process->GetPageTable()};
|
||||||
VAddr addr{};
|
VAddr addr{};
|
||||||
|
|
||||||
@ -373,21 +372,20 @@ public:
|
|||||||
R_TRY(result);
|
R_TRY(result);
|
||||||
|
|
||||||
if (ValidateRegionForMap(page_table, addr, size)) {
|
if (ValidateRegionForMap(page_table, addr, size)) {
|
||||||
*out_map_location = addr;
|
return addr;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_INSUFFICIENT_ADDRESS_SPACE;
|
return ERROR_INSUFFICIENT_ADDRESS_SPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MapNro(VAddr* out_map_location, Kernel::KProcess* process, VAddr nro_addr,
|
ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size,
|
||||||
std::size_t nro_size, VAddr bss_addr, std::size_t bss_size, std::size_t size) {
|
VAddr bss_addr, std::size_t bss_size, std::size_t size) {
|
||||||
for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
|
for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
|
||||||
auto& page_table{process->GetPageTable()};
|
auto& page_table{process->GetPageTable()};
|
||||||
VAddr addr{};
|
VAddr addr{};
|
||||||
|
|
||||||
R_TRY(MapProcessCodeMemory(&addr, process, nro_addr, nro_size));
|
CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size));
|
||||||
|
|
||||||
if (bss_size) {
|
if (bss_size) {
|
||||||
auto block_guard = detail::ScopeExit([&] {
|
auto block_guard = detail::ScopeExit([&] {
|
||||||
@ -413,8 +411,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ValidateRegionForMap(page_table, addr, size)) {
|
if (ValidateRegionForMap(page_table, addr, size)) {
|
||||||
*out_map_location = addr;
|
return addr;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,9 +437,9 @@ public:
|
|||||||
CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
|
CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
|
||||||
nro_header.segment_headers[DATA_INDEX].memory_size);
|
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));
|
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));
|
ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read));
|
||||||
|
|
||||||
return process->GetPageTable().SetProcessMemoryPermission(
|
return process->GetPageTable().SetProcessMemoryPermission(
|
||||||
@ -545,32 +542,31 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Map memory for the NRO
|
// Map memory for the NRO
|
||||||
VAddr map_location{};
|
const auto map_result{MapNro(system.ApplicationProcess(), nro_address, nro_size,
|
||||||
const auto map_result{MapNro(&map_location, system.ApplicationProcess(), nro_address,
|
bss_address, bss_size, nro_size + bss_size)};
|
||||||
nro_size, bss_address, bss_size, nro_size + bss_size)};
|
if (map_result.Failed()) {
|
||||||
if (map_result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(map_result);
|
rb.Push(map_result.Code());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the NRO into the mapped memory
|
// Load the NRO into the mapped memory
|
||||||
if (const auto result{
|
if (const auto result{
|
||||||
LoadNro(system.ApplicationProcess(), header, nro_address, map_location)};
|
LoadNro(system.ApplicationProcess(), header, nro_address, *map_result)};
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(map_result.Code());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track the loaded NRO
|
// Track the loaded NRO
|
||||||
nro.insert_or_assign(map_location,
|
nro.insert_or_assign(*map_result,
|
||||||
NROInfo{hash, map_location, nro_size, bss_address, bss_size,
|
NROInfo{hash, *map_result, nro_size, bss_address, bss_size,
|
||||||
header.segment_headers[TEXT_INDEX].memory_size,
|
header.segment_headers[TEXT_INDEX].memory_size,
|
||||||
header.segment_headers[RO_INDEX].memory_size,
|
header.segment_headers[RO_INDEX].memory_size,
|
||||||
header.segment_headers[DATA_INDEX].memory_size, nro_address});
|
header.segment_headers[DATA_INDEX].memory_size, nro_address});
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(map_location);
|
rb.Push(*map_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result UnmapNro(const NROInfo& info) {
|
Result UnmapNro(const NROInfo& info) {
|
||||||
@ -578,19 +574,19 @@ public:
|
|||||||
auto& page_table{system.ApplicationProcess()->GetPageTable()};
|
auto& page_table{system.ApplicationProcess()->GetPageTable()};
|
||||||
|
|
||||||
if (info.bss_size != 0) {
|
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.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address,
|
||||||
info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
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.nro_address + info.text_size + info.ro_size,
|
||||||
info.src_addr + info.text_size + info.ro_size, info.data_size,
|
info.src_addr + info.text_size + info.ro_size, info.data_size,
|
||||||
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
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,
|
info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size,
|
||||||
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||||
R_TRY(page_table.UnmapCodeMemory(
|
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||||
info.nro_address, info.src_addr, info.text_size,
|
info.nro_address, info.src_addr, info.text_size,
|
||||||
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
|
@ -101,14 +101,20 @@ private:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
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 (default_miis.size() > 0) {
|
if (result.Failed()) {
|
||||||
ctx.WriteBuffer(SerializeArray(default_miis));
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(result.Code());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->size() > 0) {
|
||||||
|
ctx.WriteBuffer(SerializeArray(*result));
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u32>(static_cast<u32>(default_miis.size()));
|
rb.Push<u32>(static_cast<u32>(result->size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get1(HLERequestContext& ctx) {
|
void Get1(HLERequestContext& ctx) {
|
||||||
@ -117,10 +123,15 @@ private:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
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;
|
std::vector<CharInfo> values;
|
||||||
for (const auto& element : default_miis) {
|
for (const auto& element : *result) {
|
||||||
values.emplace_back(element.info);
|
values.emplace_back(element.info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +139,7 @@ private:
|
|||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u32>(static_cast<u32>(default_miis.size()));
|
rb.Push<u32>(static_cast<u32>(result->size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateLatest(HLERequestContext& ctx) {
|
void UpdateLatest(HLERequestContext& ctx) {
|
||||||
@ -138,17 +149,16 @@ private:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||||
|
|
||||||
CharInfo new_char_info{};
|
const auto result{manager.UpdateLatest(info, source_flag)};
|
||||||
const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)};
|
if (result.Failed()) {
|
||||||
if (result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result.Code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw<CharInfo>(new_char_info);
|
rb.PushRaw<CharInfo>(*result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildRandom(HLERequestContext& ctx) {
|
void BuildRandom(HLERequestContext& ctx) {
|
||||||
|
@ -409,7 +409,8 @@ u32 MiiManager::GetCount(SourceFlag source_flag) const {
|
|||||||
return static_cast<u32>(count);
|
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) {
|
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
|
||||||
return ERROR_CANNOT_FIND_ENTRY;
|
return ERROR_CANNOT_FIND_ENTRY;
|
||||||
}
|
}
|
||||||
@ -671,7 +672,7 @@ bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const {
|
|||||||
return is_valid;
|
return is_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MiiInfoElement> MiiManager::GetDefault(SourceFlag source_flag) {
|
ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) {
|
||||||
std::vector<MiiInfoElement> result;
|
std::vector<MiiInfoElement> result;
|
||||||
|
|
||||||
if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
|
if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
|
||||||
|
@ -19,12 +19,12 @@ public:
|
|||||||
bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
|
bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
|
||||||
bool IsFullDatabase() const;
|
bool IsFullDatabase() const;
|
||||||
u32 GetCount(SourceFlag source_flag) 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 BuildRandom(Age age, Gender gender, Race race);
|
||||||
CharInfo BuildDefault(std::size_t index);
|
CharInfo BuildDefault(std::size_t index);
|
||||||
CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
|
CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
|
||||||
bool ValidateV3Info(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);
|
Result GetIndex(const CharInfo& info, u32& index);
|
||||||
|
|
||||||
// This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData
|
// This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData
|
||||||
|
@ -392,25 +392,24 @@ void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestConte
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto supported_languages = rp.Pop<u32>();
|
const auto supported_languages = rp.Pop<u32>();
|
||||||
|
|
||||||
u8 desired_language{};
|
const auto res = GetApplicationDesiredLanguage(supported_languages);
|
||||||
const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages);
|
if (res.Succeeded()) {
|
||||||
if (res == ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u32>(desired_language);
|
rb.Push<u32>(*res);
|
||||||
} else {
|
} else {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language,
|
ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage(
|
||||||
const u32 supported_languages) {
|
const u32 supported_languages) {
|
||||||
LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
|
LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
|
||||||
|
|
||||||
// Get language code from settings
|
// Get language code from settings
|
||||||
const auto language_code =
|
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
|
// Convert to application language, get priority list
|
||||||
const auto application_language = ConvertToApplicationLanguage(language_code);
|
const auto application_language = ConvertToApplicationLanguage(language_code);
|
||||||
@ -431,8 +430,7 @@ Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desir
|
|||||||
for (const auto lang : *priority_list) {
|
for (const auto lang : *priority_list) {
|
||||||
const auto supported_flag = GetSupportedLanguageFlag(lang);
|
const auto supported_flag = GetSupportedLanguageFlag(lang);
|
||||||
if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
|
if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
|
||||||
*out_desired_language = static_cast<u8>(lang);
|
return static_cast<u8>(lang);
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,20 +444,19 @@ void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto application_language = rp.Pop<u8>();
|
const auto application_language = rp.Pop<u8>();
|
||||||
|
|
||||||
u64 language_code{};
|
const auto res = ConvertApplicationLanguageToLanguageCode(application_language);
|
||||||
const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language);
|
if (res.Succeeded()) {
|
||||||
if (res == ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(language_code);
|
rb.Push(*res);
|
||||||
} else {
|
} else {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||||
u64* out_language_code, u8 application_language) {
|
u8 application_language) {
|
||||||
const auto language_code =
|
const auto language_code =
|
||||||
ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
|
ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
|
||||||
if (language_code == std::nullopt) {
|
if (language_code == std::nullopt) {
|
||||||
@ -467,8 +464,7 @@ Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
|||||||
return Service::NS::ResultApplicationLanguageNotFound;
|
return Service::NS::ResultApplicationLanguageNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_language_code = static_cast<u64>(*language_code);
|
return static_cast<u64>(*language_code);
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
|
IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
|
||||||
@ -622,13 +618,12 @@ void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequ
|
|||||||
static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size.");
|
static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size.");
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
std::vector<u8> nacp_data{};
|
|
||||||
const auto parameters{rp.PopRaw<RequestParameters>()};
|
const auto parameters{rp.PopRaw<RequestParameters>()};
|
||||||
const auto result =
|
const auto nacp_data{system.GetARPManager().GetControlProperty(parameters.application_id)};
|
||||||
system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id);
|
const auto result = nacp_data ? ResultSuccess : ResultUnknown;
|
||||||
|
|
||||||
if (result == ResultSuccess) {
|
if (nacp_data) {
|
||||||
ctx.WriteBuffer(nacp_data.data(), nacp_data.size());
|
ctx.WriteBuffer(nacp_data->data(), nacp_data->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
@ -28,9 +28,8 @@ public:
|
|||||||
explicit IApplicationManagerInterface(Core::System& system_);
|
explicit IApplicationManagerInterface(Core::System& system_);
|
||||||
~IApplicationManagerInterface() override;
|
~IApplicationManagerInterface() override;
|
||||||
|
|
||||||
Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages);
|
ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages);
|
||||||
Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code,
|
ResultVal<u64> ConvertApplicationLanguageToLanguageCode(u8 application_language);
|
||||||
u8 application_language);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetApplicationControlData(HLERequestContext& ctx);
|
void GetApplicationControlData(HLERequestContext& ctx);
|
||||||
|
@ -449,7 +449,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
|
|||||||
case NativeWindowScalingMode::ScaleToWindow:
|
case NativeWindowScalingMode::ScaleToWindow:
|
||||||
case NativeWindowScalingMode::ScaleCrop:
|
case NativeWindowScalingMode::ScaleCrop:
|
||||||
case NativeWindowScalingMode::NoScaleCrop:
|
case NativeWindowScalingMode::NoScaleCrop:
|
||||||
case NativeWindowScalingMode::PreserveAspectRatio:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Service_Nvnflinger, "unknown scaling mode {}", scaling_mode);
|
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();
|
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();
|
const auto lock_guard = Lock();
|
||||||
auto* const display = FindDisplay(display_id);
|
auto* const display = FindDisplay(display_id);
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64
|
|||||||
return VI::ResultNotFound;
|
return VI::ResultNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
return display->GetVSyncEvent(out_vsync_event);
|
return display->GetVSyncEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
VI::Display* Nvnflinger::FindDisplay(u64 display_id) {
|
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 an invalid display ID is provided, then VI::ResultNotFound is returned.
|
||||||
/// If the vsync event has already been retrieved, then VI::ResultPermissionDenied 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
|
/// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
|
||||||
/// finished.
|
/// finished.
|
||||||
|
@ -41,7 +41,6 @@ enum class NativeWindowScalingMode : s32 {
|
|||||||
ScaleToWindow = 1,
|
ScaleToWindow = 1,
|
||||||
ScaleCrop = 2,
|
ScaleCrop = 2,
|
||||||
NoScaleCrop = 3,
|
NoScaleCrop = 3,
|
||||||
PreserveAspectRatio = 4,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Transform parameter for QueueBuffer
|
/// Transform parameter for QueueBuffer
|
||||||
|
@ -8,16 +8,15 @@
|
|||||||
|
|
||||||
namespace Service::OLSC {
|
namespace Service::OLSC {
|
||||||
|
|
||||||
class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> {
|
class OLSC final : public ServiceFramework<OLSC> {
|
||||||
public:
|
public:
|
||||||
explicit IOlscServiceForApplication(Core::System& system_)
|
explicit OLSC(Core::System& system_) : ServiceFramework{system_, "olsc:u"} {
|
||||||
: ServiceFramework{system_, "olsc:u"} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IOlscServiceForApplication::Initialize, "Initialize"},
|
{0, &OLSC::Initialize, "Initialize"},
|
||||||
{10, nullptr, "VerifySaveDataBackupLicenseAsync"},
|
{10, nullptr, "VerifySaveDataBackupLicenseAsync"},
|
||||||
{13, &IOlscServiceForApplication::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
|
{13, &OLSC::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
|
||||||
{14, &IOlscServiceForApplication::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
|
{14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
|
||||||
{15, nullptr, "SetCustomData"},
|
{15, nullptr, "SetCustomData"},
|
||||||
{16, nullptr, "DeleteSaveDataBackupSetting"},
|
{16, nullptr, "DeleteSaveDataBackupSetting"},
|
||||||
{18, nullptr, "GetSaveDataBackupInfoCache"},
|
{18, nullptr, "GetSaveDataBackupInfoCache"},
|
||||||
@ -73,155 +72,10 @@ private:
|
|||||||
bool initialized{};
|
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) {
|
void LoopProcess(Core::System& system) {
|
||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
|
|
||||||
server_manager->RegisterNamedService("olsc:u",
|
server_manager->RegisterNamedService("olsc:u", std::make_shared<OLSC>(system));
|
||||||
std::make_shared<IOlscServiceForApplication>(system));
|
|
||||||
server_manager->RegisterNamedService("olsc:s",
|
|
||||||
std::make_shared<IOlscServiceForSystemService>(system));
|
|
||||||
|
|
||||||
ServerManager::RunServer(std::move(server_manager));
|
ServerManager::RunServer(std::move(server_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
#include "core/hle/service/ipc_helpers.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.h"
|
||||||
#include "core/hle/service/pctl/pctl_module.h"
|
#include "core/hle/service/pctl/pctl_module.h"
|
||||||
#include "core/hle/service/server_manager.h"
|
#include "core/hle/service/server_manager.h"
|
||||||
@ -25,8 +24,7 @@ constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
|
|||||||
class IParentalControlService final : public ServiceFramework<IParentalControlService> {
|
class IParentalControlService final : public ServiceFramework<IParentalControlService> {
|
||||||
public:
|
public:
|
||||||
explicit IParentalControlService(Core::System& system_, Capability capability_)
|
explicit IParentalControlService(Core::System& system_, Capability capability_)
|
||||||
: ServiceFramework{system_, "IParentalControlService"}, capability{capability_},
|
: ServiceFramework{system_, "IParentalControlService"}, capability{capability_} {
|
||||||
service_context{system_, "IParentalControlService"} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{1, &IParentalControlService::Initialize, "Initialize"},
|
{1, &IParentalControlService::Initialize, "Initialize"},
|
||||||
@ -35,7 +33,7 @@ public:
|
|||||||
{1003, nullptr, "ConfirmResumeApplicationPermission"},
|
{1003, nullptr, "ConfirmResumeApplicationPermission"},
|
||||||
{1004, nullptr, "ConfirmSnsPostPermission"},
|
{1004, nullptr, "ConfirmSnsPostPermission"},
|
||||||
{1005, nullptr, "ConfirmSystemSettingsPermission"},
|
{1005, nullptr, "ConfirmSystemSettingsPermission"},
|
||||||
{1006, &IParentalControlService::IsRestrictionTemporaryUnlocked, "IsRestrictionTemporaryUnlocked"},
|
{1006, nullptr, "IsRestrictionTemporaryUnlocked"},
|
||||||
{1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
|
{1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
|
||||||
{1008, nullptr, "EnterRestrictedSystemSettings"},
|
{1008, nullptr, "EnterRestrictedSystemSettings"},
|
||||||
{1009, nullptr, "LeaveRestrictedSystemSettings"},
|
{1009, nullptr, "LeaveRestrictedSystemSettings"},
|
||||||
@ -49,14 +47,14 @@ public:
|
|||||||
{1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"},
|
{1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"},
|
||||||
{1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"},
|
{1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"},
|
||||||
{1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"},
|
{1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"},
|
||||||
{1032, &IParentalControlService::GetSafetyLevel, "GetSafetyLevel"},
|
{1032, nullptr, "GetSafetyLevel"},
|
||||||
{1033, nullptr, "SetSafetyLevel"},
|
{1033, nullptr, "SetSafetyLevel"},
|
||||||
{1034, nullptr, "GetSafetyLevelSettings"},
|
{1034, nullptr, "GetSafetyLevelSettings"},
|
||||||
{1035, &IParentalControlService::GetCurrentSettings, "GetCurrentSettings"},
|
{1035, nullptr, "GetCurrentSettings"},
|
||||||
{1036, nullptr, "SetCustomSafetyLevelSettings"},
|
{1036, nullptr, "SetCustomSafetyLevelSettings"},
|
||||||
{1037, nullptr, "GetDefaultRatingOrganization"},
|
{1037, nullptr, "GetDefaultRatingOrganization"},
|
||||||
{1038, nullptr, "SetDefaultRatingOrganization"},
|
{1038, nullptr, "SetDefaultRatingOrganization"},
|
||||||
{1039, &IParentalControlService::GetFreeCommunicationApplicationListCount, "GetFreeCommunicationApplicationListCount"},
|
{1039, nullptr, "GetFreeCommunicationApplicationListCount"},
|
||||||
{1042, nullptr, "AddToFreeCommunicationApplicationList"},
|
{1042, nullptr, "AddToFreeCommunicationApplicationList"},
|
||||||
{1043, nullptr, "DeleteSettings"},
|
{1043, nullptr, "DeleteSettings"},
|
||||||
{1044, nullptr, "GetFreeCommunicationApplicationList"},
|
{1044, nullptr, "GetFreeCommunicationApplicationList"},
|
||||||
@ -78,7 +76,7 @@ public:
|
|||||||
{1206, nullptr, "GetPinCodeLength"},
|
{1206, nullptr, "GetPinCodeLength"},
|
||||||
{1207, nullptr, "GetPinCodeChangedEvent"},
|
{1207, nullptr, "GetPinCodeChangedEvent"},
|
||||||
{1208, nullptr, "GetPinCode"},
|
{1208, nullptr, "GetPinCode"},
|
||||||
{1403, &IParentalControlService::IsPairingActive, "IsPairingActive"},
|
{1403, nullptr, "IsPairingActive"},
|
||||||
{1406, nullptr, "GetSettingsLastUpdated"},
|
{1406, nullptr, "GetSettingsLastUpdated"},
|
||||||
{1411, nullptr, "GetPairingAccountInfo"},
|
{1411, nullptr, "GetPairingAccountInfo"},
|
||||||
{1421, nullptr, "GetAccountNickname"},
|
{1421, nullptr, "GetAccountNickname"},
|
||||||
@ -86,18 +84,18 @@ public:
|
|||||||
{1425, nullptr, "RequestPostEvents"},
|
{1425, nullptr, "RequestPostEvents"},
|
||||||
{1426, nullptr, "GetPostEventInterval"},
|
{1426, nullptr, "GetPostEventInterval"},
|
||||||
{1427, nullptr, "SetPostEventInterval"},
|
{1427, nullptr, "SetPostEventInterval"},
|
||||||
{1432, &IParentalControlService::GetSynchronizationEvent, "GetSynchronizationEvent"},
|
{1432, nullptr, "GetSynchronizationEvent"},
|
||||||
{1451, nullptr, "StartPlayTimer"},
|
{1451, nullptr, "StartPlayTimer"},
|
||||||
{1452, nullptr, "StopPlayTimer"},
|
{1452, nullptr, "StopPlayTimer"},
|
||||||
{1453, nullptr, "IsPlayTimerEnabled"},
|
{1453, nullptr, "IsPlayTimerEnabled"},
|
||||||
{1454, nullptr, "GetPlayTimerRemainingTime"},
|
{1454, nullptr, "GetPlayTimerRemainingTime"},
|
||||||
{1455, nullptr, "IsRestrictedByPlayTimer"},
|
{1455, nullptr, "IsRestrictedByPlayTimer"},
|
||||||
{1456, &IParentalControlService::GetPlayTimerSettings, "GetPlayTimerSettings"},
|
{1456, nullptr, "GetPlayTimerSettings"},
|
||||||
{1457, &IParentalControlService::GetPlayTimerEventToRequestSuspension, "GetPlayTimerEventToRequestSuspension"},
|
{1457, nullptr, "GetPlayTimerEventToRequestSuspension"},
|
||||||
{1458, &IParentalControlService::IsPlayTimerAlarmDisabled, "IsPlayTimerAlarmDisabled"},
|
{1458, nullptr, "IsPlayTimerAlarmDisabled"},
|
||||||
{1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
|
{1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
|
||||||
{1472, nullptr, "CancelNetworkRequest"},
|
{1472, nullptr, "CancelNetworkRequest"},
|
||||||
{1473, &IParentalControlService::GetUnlinkedEvent, "GetUnlinkedEvent"},
|
{1473, nullptr, "GetUnlinkedEvent"},
|
||||||
{1474, nullptr, "ClearUnlinkedEvent"},
|
{1474, nullptr, "ClearUnlinkedEvent"},
|
||||||
{1601, nullptr, "DisableAllFeatures"},
|
{1601, nullptr, "DisableAllFeatures"},
|
||||||
{1602, nullptr, "PostEnableAllFeatures"},
|
{1602, nullptr, "PostEnableAllFeatures"},
|
||||||
@ -133,12 +131,6 @@ public:
|
|||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
RegisterHandlers(functions);
|
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:
|
private:
|
||||||
@ -236,17 +228,6 @@ private:
|
|||||||
states.free_communication = true;
|
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) {
|
void ConfirmStereoVisionPermission(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_PCTL, "called");
|
LOG_DEBUG(Service_PCTL, "called");
|
||||||
states.stereo_vision = true;
|
states.stereo_vision = true;
|
||||||
@ -287,34 +268,6 @@ private:
|
|||||||
rb.Push(pin_code[0] != '\0');
|
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) {
|
void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_PCTL, "called");
|
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) {
|
void SetStereoVisionRestriction(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto can_use = rp.Pop<bool>();
|
const auto can_use = rp.Pop<bool>();
|
||||||
@ -466,30 +364,10 @@ private:
|
|||||||
bool disabled{};
|
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{};
|
States states{};
|
||||||
ParentalControlSettings settings{};
|
ParentalControlSettings settings{};
|
||||||
RestrictionSettings restriction_settings{};
|
|
||||||
std::array<char, 8> pin_code{};
|
std::array<char, 8> pin_code{};
|
||||||
Capability capability{};
|
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) {
|
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)));
|
m_system.ServiceManager().RegisterService(service_name, max_sessions, handler)));
|
||||||
|
|
||||||
// Get the registered port.
|
// Get the registered port.
|
||||||
Kernel::KPort* port{};
|
auto port = m_system.ServiceManager().GetServicePort(service_name);
|
||||||
ASSERT(
|
ASSERT(port.Succeeded());
|
||||||
R_SUCCEEDED(m_system.ServiceManager().GetServicePort(std::addressof(port), service_name)));
|
|
||||||
|
|
||||||
// Open a new reference to the server port.
|
// Open a new reference to the server port.
|
||||||
port->GetServerPort().Open();
|
(*port)->GetServerPort().Open();
|
||||||
|
|
||||||
// Begin tracking the server port.
|
// Begin tracking the server port.
|
||||||
{
|
{
|
||||||
std::scoped_lock ll{m_list_mutex};
|
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.
|
// Signal the wakeup event.
|
||||||
|
@ -11,6 +11,66 @@
|
|||||||
|
|
||||||
namespace Service::Set {
|
namespace Service::Set {
|
||||||
namespace {
|
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 PRE_4_0_0_MAX_ENTRIES = 0xF;
|
||||||
constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40;
|
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) {
|
void GetKeyCodeMapImpl(HLERequestContext& ctx) {
|
||||||
const auto language_code =
|
const auto language_code = available_language_codes[Settings::values.language_index.GetValue()];
|
||||||
available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())];
|
|
||||||
const auto key_code =
|
const auto key_code =
|
||||||
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
|
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
|
||||||
[=](const auto& element) { return element.first == language_code; });
|
[=](const auto& element) { return element.first == language_code; });
|
||||||
@ -103,7 +162,7 @@ void SET::GetQuestFlag(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
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) {
|
void SET::GetLanguageCode(HLERequestContext& ctx) {
|
||||||
@ -111,8 +170,7 @@ void SET::GetLanguageCode(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushEnum(
|
rb.PushEnum(available_language_codes[Settings::values.language_index.GetValue()]);
|
||||||
available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SET::GetRegionCode(HLERequestContext& ctx) {
|
void SET::GetRegionCode(HLERequestContext& ctx) {
|
||||||
@ -120,7 +178,7 @@ void SET::GetRegionCode(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
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) {
|
void SET::GetKeyCodeMap(HLERequestContext& ctx) {
|
||||||
|
@ -32,67 +32,6 @@ enum class LanguageCode : u64 {
|
|||||||
ZH_HANT = 0x00746E61482D687A,
|
ZH_HANT = 0x00746E61482D687A,
|
||||||
PT_BR = 0x00000052422D7470,
|
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);
|
LanguageCode GetLanguageCodeFromIndex(std::size_t idx);
|
||||||
|
|
||||||
class SET final : public ServiceFramework<SET> {
|
class SET final : public ServiceFramework<SET> {
|
||||||
|
@ -4,12 +4,10 @@
|
|||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/string_util.h"
|
|
||||||
#include "core/file_sys/errors.h"
|
#include "core/file_sys/errors.h"
|
||||||
#include "core/file_sys/system_archive/system_version.h"
|
#include "core/file_sys/system_archive/system_version.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/hle/service/set/set.h"
|
|
||||||
#include "core/hle/service/set/set_sys.h"
|
#include "core/hle/service/set/set_sys.h"
|
||||||
|
|
||||||
namespace Service::Set {
|
namespace Service::Set {
|
||||||
@ -75,16 +73,6 @@ void GetFirmwareVersionImpl(HLERequestContext& ctx, GetFirmwareVersionType type)
|
|||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // 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) {
|
void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_SET, "called");
|
LOG_DEBUG(Service_SET, "called");
|
||||||
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1);
|
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1);
|
||||||
@ -95,113 +83,21 @@ void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) {
|
|||||||
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2);
|
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) {
|
void SET_SYS::GetColorSetId(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_SET, "called");
|
LOG_DEBUG(Service_SET, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushEnum(color_set);
|
rb.PushEnum(color_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SET_SYS::SetColorSetId(HLERequestContext& ctx) {
|
void SET_SYS::SetColorSetId(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_SET, "called");
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
color_set = rp.PopEnum<ColorSet>();
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
@ -281,218 +177,17 @@ void SET_SYS::GetSettingsItemValue(HLERequestContext& ctx) {
|
|||||||
rb.Push(response);
|
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) {
|
void SET_SYS::GetDeviceNickName(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_SET, "called");
|
LOG_DEBUG(Service_SET, "called");
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
ctx.WriteBuffer(::Settings::values.device_name.GetValue());
|
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"} {
|
SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &SET_SYS::SetLanguageCode, "SetLanguageCode"},
|
{0, nullptr, "SetLanguageCode"},
|
||||||
{1, nullptr, "SetNetworkSettings"},
|
{1, nullptr, "SetNetworkSettings"},
|
||||||
{2, nullptr, "GetNetworkSettings"},
|
{2, nullptr, "GetNetworkSettings"},
|
||||||
{3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"},
|
{3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"},
|
||||||
@ -508,35 +203,35 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
|||||||
{14, nullptr, "SetExternalSteadyClockSourceId"},
|
{14, nullptr, "SetExternalSteadyClockSourceId"},
|
||||||
{15, nullptr, "GetUserSystemClockContext"},
|
{15, nullptr, "GetUserSystemClockContext"},
|
||||||
{16, nullptr, "SetUserSystemClockContext"},
|
{16, nullptr, "SetUserSystemClockContext"},
|
||||||
{17, &SET_SYS::GetAccountSettings, "GetAccountSettings"},
|
{17, nullptr, "GetAccountSettings"},
|
||||||
{18, &SET_SYS::SetAccountSettings, "SetAccountSettings"},
|
{18, nullptr, "SetAccountSettings"},
|
||||||
{19, nullptr, "GetAudioVolume"},
|
{19, nullptr, "GetAudioVolume"},
|
||||||
{20, nullptr, "SetAudioVolume"},
|
{20, nullptr, "SetAudioVolume"},
|
||||||
{21, &SET_SYS::GetEulaVersions, "GetEulaVersions"},
|
{21, nullptr, "GetEulaVersions"},
|
||||||
{22, &SET_SYS::SetEulaVersions, "SetEulaVersions"},
|
{22, nullptr, "SetEulaVersions"},
|
||||||
{23, &SET_SYS::GetColorSetId, "GetColorSetId"},
|
{23, &SET_SYS::GetColorSetId, "GetColorSetId"},
|
||||||
{24, &SET_SYS::SetColorSetId, "SetColorSetId"},
|
{24, &SET_SYS::SetColorSetId, "SetColorSetId"},
|
||||||
{25, nullptr, "GetConsoleInformationUploadFlag"},
|
{25, nullptr, "GetConsoleInformationUploadFlag"},
|
||||||
{26, nullptr, "SetConsoleInformationUploadFlag"},
|
{26, nullptr, "SetConsoleInformationUploadFlag"},
|
||||||
{27, nullptr, "GetAutomaticApplicationDownloadFlag"},
|
{27, nullptr, "GetAutomaticApplicationDownloadFlag"},
|
||||||
{28, nullptr, "SetAutomaticApplicationDownloadFlag"},
|
{28, nullptr, "SetAutomaticApplicationDownloadFlag"},
|
||||||
{29, &SET_SYS::GetNotificationSettings, "GetNotificationSettings"},
|
{29, nullptr, "GetNotificationSettings"},
|
||||||
{30, &SET_SYS::SetNotificationSettings, "SetNotificationSettings"},
|
{30, nullptr, "SetNotificationSettings"},
|
||||||
{31, &SET_SYS::GetAccountNotificationSettings, "GetAccountNotificationSettings"},
|
{31, nullptr, "GetAccountNotificationSettings"},
|
||||||
{32, &SET_SYS::SetAccountNotificationSettings, "SetAccountNotificationSettings"},
|
{32, nullptr, "SetAccountNotificationSettings"},
|
||||||
{35, nullptr, "GetVibrationMasterVolume"},
|
{35, nullptr, "GetVibrationMasterVolume"},
|
||||||
{36, nullptr, "SetVibrationMasterVolume"},
|
{36, nullptr, "SetVibrationMasterVolume"},
|
||||||
{37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"},
|
{37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"},
|
||||||
{38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"},
|
{38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"},
|
||||||
{39, &SET_SYS::GetTvSettings, "GetTvSettings"},
|
{39, nullptr, "GetTvSettings"},
|
||||||
{40, &SET_SYS::SetTvSettings, "SetTvSettings"},
|
{40, nullptr, "SetTvSettings"},
|
||||||
{41, nullptr, "GetEdid"},
|
{41, nullptr, "GetEdid"},
|
||||||
{42, nullptr, "SetEdid"},
|
{42, nullptr, "SetEdid"},
|
||||||
{43, nullptr, "GetAudioOutputMode"},
|
{43, nullptr, "GetAudioOutputMode"},
|
||||||
{44, nullptr, "SetAudioOutputMode"},
|
{44, nullptr, "SetAudioOutputMode"},
|
||||||
{45, nullptr, "IsForceMuteOnHeadphoneRemoved"},
|
{45, nullptr, "IsForceMuteOnHeadphoneRemoved"},
|
||||||
{46, nullptr, "SetForceMuteOnHeadphoneRemoved"},
|
{46, nullptr, "SetForceMuteOnHeadphoneRemoved"},
|
||||||
{47, &SET_SYS::GetQuestFlag, "GetQuestFlag"},
|
{47, nullptr, "GetQuestFlag"},
|
||||||
{48, nullptr, "SetQuestFlag"},
|
{48, nullptr, "SetQuestFlag"},
|
||||||
{49, nullptr, "GetDataDeletionSettings"},
|
{49, nullptr, "GetDataDeletionSettings"},
|
||||||
{50, nullptr, "SetDataDeletionSettings"},
|
{50, nullptr, "SetDataDeletionSettings"},
|
||||||
@ -546,13 +241,13 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
|||||||
{54, nullptr, "SetDeviceTimeZoneLocationName"},
|
{54, nullptr, "SetDeviceTimeZoneLocationName"},
|
||||||
{55, nullptr, "GetWirelessCertificationFileSize"},
|
{55, nullptr, "GetWirelessCertificationFileSize"},
|
||||||
{56, nullptr, "GetWirelessCertificationFile"},
|
{56, nullptr, "GetWirelessCertificationFile"},
|
||||||
{57, &SET_SYS::SetRegionCode, "SetRegionCode"},
|
{57, nullptr, "SetRegionCode"},
|
||||||
{58, nullptr, "GetNetworkSystemClockContext"},
|
{58, nullptr, "GetNetworkSystemClockContext"},
|
||||||
{59, nullptr, "SetNetworkSystemClockContext"},
|
{59, nullptr, "SetNetworkSystemClockContext"},
|
||||||
{60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"},
|
{60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"},
|
||||||
{61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"},
|
{61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"},
|
||||||
{62, nullptr, "GetDebugModeFlag"},
|
{62, nullptr, "GetDebugModeFlag"},
|
||||||
{63, &SET_SYS::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"},
|
{63, nullptr, "GetPrimaryAlbumStorage"},
|
||||||
{64, nullptr, "SetPrimaryAlbumStorage"},
|
{64, nullptr, "SetPrimaryAlbumStorage"},
|
||||||
{65, nullptr, "GetUsb30EnableFlag"},
|
{65, nullptr, "GetUsb30EnableFlag"},
|
||||||
{66, nullptr, "SetUsb30EnableFlag"},
|
{66, nullptr, "SetUsb30EnableFlag"},
|
||||||
@ -560,15 +255,15 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
|||||||
{68, nullptr, "GetSerialNumber"},
|
{68, nullptr, "GetSerialNumber"},
|
||||||
{69, nullptr, "GetNfcEnableFlag"},
|
{69, nullptr, "GetNfcEnableFlag"},
|
||||||
{70, nullptr, "SetNfcEnableFlag"},
|
{70, nullptr, "SetNfcEnableFlag"},
|
||||||
{71, &SET_SYS::GetSleepSettings, "GetSleepSettings"},
|
{71, nullptr, "GetSleepSettings"},
|
||||||
{72, &SET_SYS::SetSleepSettings, "SetSleepSettings"},
|
{72, nullptr, "SetSleepSettings"},
|
||||||
{73, nullptr, "GetWirelessLanEnableFlag"},
|
{73, nullptr, "GetWirelessLanEnableFlag"},
|
||||||
{74, nullptr, "SetWirelessLanEnableFlag"},
|
{74, nullptr, "SetWirelessLanEnableFlag"},
|
||||||
{75, &SET_SYS::GetInitialLaunchSettings, "GetInitialLaunchSettings"},
|
{75, nullptr, "GetInitialLaunchSettings"},
|
||||||
{76, &SET_SYS::SetInitialLaunchSettings, "SetInitialLaunchSettings"},
|
{76, nullptr, "SetInitialLaunchSettings"},
|
||||||
{77, &SET_SYS::GetDeviceNickName, "GetDeviceNickName"},
|
{77, &SET_SYS::GetDeviceNickName, "GetDeviceNickName"},
|
||||||
{78, &SET_SYS::SetDeviceNickName, "SetDeviceNickName"},
|
{78, nullptr, "SetDeviceNickName"},
|
||||||
{79, &SET_SYS::GetProductModel, "GetProductModel"},
|
{79, nullptr, "GetProductModel"},
|
||||||
{80, nullptr, "GetLdnChannel"},
|
{80, nullptr, "GetLdnChannel"},
|
||||||
{81, nullptr, "SetLdnChannel"},
|
{81, nullptr, "SetLdnChannel"},
|
||||||
{82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"},
|
{82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"},
|
||||||
@ -579,16 +274,16 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
|||||||
{87, nullptr, "SetPtmFuelGaugeParameter"},
|
{87, nullptr, "SetPtmFuelGaugeParameter"},
|
||||||
{88, nullptr, "GetBluetoothEnableFlag"},
|
{88, nullptr, "GetBluetoothEnableFlag"},
|
||||||
{89, nullptr, "SetBluetoothEnableFlag"},
|
{89, nullptr, "SetBluetoothEnableFlag"},
|
||||||
{90, &SET_SYS::GetMiiAuthorId, "GetMiiAuthorId"},
|
{90, nullptr, "GetMiiAuthorId"},
|
||||||
{91, nullptr, "SetShutdownRtcValue"},
|
{91, nullptr, "SetShutdownRtcValue"},
|
||||||
{92, nullptr, "GetShutdownRtcValue"},
|
{92, nullptr, "GetShutdownRtcValue"},
|
||||||
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
|
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
|
||||||
{94, nullptr, "GetFatalDirtyFlags"},
|
{94, nullptr, "GetFatalDirtyFlags"},
|
||||||
{95, &SET_SYS::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
|
{95, nullptr, "GetAutoUpdateEnableFlag"},
|
||||||
{96, nullptr, "SetAutoUpdateEnableFlag"},
|
{96, nullptr, "SetAutoUpdateEnableFlag"},
|
||||||
{97, nullptr, "GetNxControllerSettings"},
|
{97, nullptr, "GetNxControllerSettings"},
|
||||||
{98, nullptr, "SetNxControllerSettings"},
|
{98, nullptr, "SetNxControllerSettings"},
|
||||||
{99, &SET_SYS::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
|
{99, nullptr, "GetBatteryPercentageFlag"},
|
||||||
{100, nullptr, "SetBatteryPercentageFlag"},
|
{100, nullptr, "SetBatteryPercentageFlag"},
|
||||||
{101, nullptr, "GetExternalRtcResetFlag"},
|
{101, nullptr, "GetExternalRtcResetFlag"},
|
||||||
{102, nullptr, "SetExternalRtcResetFlag"},
|
{102, nullptr, "SetExternalRtcResetFlag"},
|
||||||
@ -613,10 +308,10 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
|||||||
{121, nullptr, "SetPushNotificationActivityModeOnSleep"},
|
{121, nullptr, "SetPushNotificationActivityModeOnSleep"},
|
||||||
{122, nullptr, "GetServiceDiscoveryControlSettings"},
|
{122, nullptr, "GetServiceDiscoveryControlSettings"},
|
||||||
{123, nullptr, "SetServiceDiscoveryControlSettings"},
|
{123, nullptr, "SetServiceDiscoveryControlSettings"},
|
||||||
{124, &SET_SYS::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
|
{124, nullptr, "GetErrorReportSharePermission"},
|
||||||
{125, nullptr, "SetErrorReportSharePermission"},
|
{125, nullptr, "SetErrorReportSharePermission"},
|
||||||
{126, &SET_SYS::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
|
{126, nullptr, "GetAppletLaunchFlags"},
|
||||||
{127, &SET_SYS::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
|
{127, nullptr, "SetAppletLaunchFlags"},
|
||||||
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
|
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
|
||||||
{129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"},
|
{129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"},
|
||||||
{130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"},
|
{130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"},
|
||||||
@ -625,7 +320,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
|||||||
{133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"},
|
{133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"},
|
||||||
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
|
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
|
||||||
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
|
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
|
||||||
{136, &SET_SYS::GetKeyboardLayout, "GetKeyboardLayout"},
|
{136, nullptr, "GetKeyboardLayout"},
|
||||||
{137, nullptr, "SetKeyboardLayout"},
|
{137, nullptr, "SetKeyboardLayout"},
|
||||||
{138, nullptr, "GetWebInspectorFlag"},
|
{138, nullptr, "GetWebInspectorFlag"},
|
||||||
{139, nullptr, "GetAllowedSslHosts"},
|
{139, nullptr, "GetAllowedSslHosts"},
|
||||||
@ -659,7 +354,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
|||||||
{167, nullptr, "SetUsb30DeviceEnableFlag"},
|
{167, nullptr, "SetUsb30DeviceEnableFlag"},
|
||||||
{168, nullptr, "GetThemeId"},
|
{168, nullptr, "GetThemeId"},
|
||||||
{169, nullptr, "SetThemeId"},
|
{169, nullptr, "SetThemeId"},
|
||||||
{170, &SET_SYS::GetChineseTraditionalInputMethod, "GetChineseTraditionalInputMethod"},
|
{170, nullptr, "GetChineseTraditionalInputMethod"},
|
||||||
{171, nullptr, "SetChineseTraditionalInputMethod"},
|
{171, nullptr, "SetChineseTraditionalInputMethod"},
|
||||||
{172, nullptr, "GetPtmCycleCountReliability"},
|
{172, nullptr, "GetPtmCycleCountReliability"},
|
||||||
{173, nullptr, "SetPtmCycleCountReliability"},
|
{173, nullptr, "SetPtmCycleCountReliability"},
|
||||||
@ -690,16 +385,12 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
|
|||||||
{198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"},
|
{198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"},
|
||||||
{199, nullptr, "GetButtonConfigRegisteredSettings"},
|
{199, nullptr, "GetButtonConfigRegisteredSettings"},
|
||||||
{200, nullptr, "SetButtonConfigRegisteredSettings"},
|
{200, nullptr, "SetButtonConfigRegisteredSettings"},
|
||||||
{201, &SET_SYS::GetFieldTestingFlag, "GetFieldTestingFlag"},
|
{201, nullptr, "GetFieldTestingFlag"},
|
||||||
{202, nullptr, "SetFieldTestingFlag"},
|
{202, nullptr, "SetFieldTestingFlag"},
|
||||||
{203, nullptr, "GetPanelCrcMode"},
|
{203, nullptr, "GetPanelCrcMode"},
|
||||||
{204, nullptr, "SetPanelCrcMode"},
|
{204, nullptr, "SetPanelCrcMode"},
|
||||||
{205, nullptr, "GetNxControllerSettingsEx"},
|
{205, nullptr, "GetNxControllerSettingsEx"},
|
||||||
{206, nullptr, "SetNxControllerSettingsEx"},
|
{206, nullptr, "SetNxControllerSettingsEx"},
|
||||||
{207, nullptr, "GetHearingProtectionSafeguardFlag"},
|
|
||||||
{208, nullptr, "SetHearingProtectionSafeguardFlag"},
|
|
||||||
{209, nullptr, "GetHearingProtectionSafeguardRemainingTime"},
|
|
||||||
{210, nullptr, "SetHearingProtectionSafeguardRemainingTime"},
|
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/uuid.h"
|
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
@ -25,331 +23,15 @@ private:
|
|||||||
BasicBlack = 1,
|
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 GetSettingsItemValueSize(HLERequestContext& ctx);
|
||||||
void GetSettingsItemValue(HLERequestContext& ctx);
|
void GetSettingsItemValue(HLERequestContext& ctx);
|
||||||
void GetTvSettings(HLERequestContext& ctx);
|
void GetFirmwareVersion(HLERequestContext& ctx);
|
||||||
void SetTvSettings(HLERequestContext& ctx);
|
void GetFirmwareVersion2(HLERequestContext& ctx);
|
||||||
void GetQuestFlag(HLERequestContext& ctx);
|
void GetColorSetId(HLERequestContext& ctx);
|
||||||
void SetRegionCode(HLERequestContext& ctx);
|
void SetColorSetId(HLERequestContext& ctx);
|
||||||
void GetPrimaryAlbumStorage(HLERequestContext& ctx);
|
|
||||||
void GetSleepSettings(HLERequestContext& ctx);
|
|
||||||
void SetSleepSettings(HLERequestContext& ctx);
|
|
||||||
void GetInitialLaunchSettings(HLERequestContext& ctx);
|
|
||||||
void SetInitialLaunchSettings(HLERequestContext& ctx);
|
|
||||||
void GetDeviceNickName(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;
|
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
|
} // namespace Service::Set
|
||||||
|
@ -52,7 +52,8 @@ static Result ValidateServiceName(const std::string& name) {
|
|||||||
|
|
||||||
Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
|
Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
|
||||||
SessionRequestHandlerPtr handler) {
|
SessionRequestHandlerPtr handler) {
|
||||||
R_TRY(ValidateServiceName(name));
|
|
||||||
|
CASCADE_CODE(ValidateServiceName(name));
|
||||||
|
|
||||||
std::scoped_lock lk{lock};
|
std::scoped_lock lk{lock};
|
||||||
if (registered_services.find(name) != registered_services.end()) {
|
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) {
|
Result ServiceManager::UnregisterService(const std::string& name) {
|
||||||
R_TRY(ValidateServiceName(name));
|
CASCADE_CODE(ValidateServiceName(name));
|
||||||
|
|
||||||
std::scoped_lock lk{lock};
|
std::scoped_lock lk{lock};
|
||||||
const auto iter = registered_services.find(name);
|
const auto iter = registered_services.find(name);
|
||||||
@ -91,8 +92,8 @@ Result ServiceManager::UnregisterService(const std::string& name) {
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::string& name) {
|
ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) {
|
||||||
R_TRY(ValidateServiceName(name));
|
CASCADE_CODE(ValidateServiceName(name));
|
||||||
|
|
||||||
std::scoped_lock lk{lock};
|
std::scoped_lock lk{lock};
|
||||||
auto it = service_ports.find(name);
|
auto it = service_ports.find(name);
|
||||||
@ -101,8 +102,7 @@ Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::strin
|
|||||||
return Service::SM::ResultNotRegistered;
|
return Service::SM::ResultNotRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_port = it->second;
|
return it->second;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,34 +122,32 @@ void SM::Initialize(HLERequestContext& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SM::GetService(HLERequestContext& ctx) {
|
void SM::GetService(HLERequestContext& ctx) {
|
||||||
Kernel::KClientSession* client_session{};
|
auto result = GetServiceImpl(ctx);
|
||||||
auto result = GetServiceImpl(&client_session, ctx);
|
|
||||||
if (ctx.GetIsDeferred()) {
|
if (ctx.GetIsDeferred()) {
|
||||||
// Don't overwrite the command buffer.
|
// Don't overwrite the command buffer.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == ResultSuccess) {
|
if (result.Succeeded()) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
|
||||||
rb.Push(result);
|
rb.Push(result.Code());
|
||||||
rb.PushMoveObjects(client_session);
|
rb.PushMoveObjects(result.Unwrap());
|
||||||
} else {
|
} else {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result.Code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SM::GetServiceTipc(HLERequestContext& ctx) {
|
void SM::GetServiceTipc(HLERequestContext& ctx) {
|
||||||
Kernel::KClientSession* client_session{};
|
auto result = GetServiceImpl(ctx);
|
||||||
auto result = GetServiceImpl(&client_session, ctx);
|
|
||||||
if (ctx.GetIsDeferred()) {
|
if (ctx.GetIsDeferred()) {
|
||||||
// Don't overwrite the command buffer.
|
// Don't overwrite the command buffer.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
|
||||||
rb.Push(result);
|
rb.Push(result.Code());
|
||||||
rb.PushMoveObjects(result == ResultSuccess ? client_session : nullptr);
|
rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string PopServiceName(IPC::RequestParser& rp) {
|
static std::string PopServiceName(IPC::RequestParser& rp) {
|
||||||
@ -163,7 +161,7 @@ static std::string PopServiceName(IPC::RequestParser& rp) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx) {
|
ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) {
|
||||||
if (!ctx.GetManager()->GetIsInitializedForSm()) {
|
if (!ctx.GetManager()->GetIsInitializedForSm()) {
|
||||||
return Service::SM::ResultInvalidClient;
|
return Service::SM::ResultInvalidClient;
|
||||||
}
|
}
|
||||||
@ -172,18 +170,18 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
|
|||||||
std::string name(PopServiceName(rp));
|
std::string name(PopServiceName(rp));
|
||||||
|
|
||||||
// Find the named port.
|
// Find the named port.
|
||||||
Kernel::KPort* port{};
|
auto port_result = service_manager.GetServicePort(name);
|
||||||
auto port_result = service_manager.GetServicePort(&port, name);
|
if (port_result.Code() == Service::SM::ResultInvalidServiceName) {
|
||||||
if (port_result == Service::SM::ResultInvalidServiceName) {
|
|
||||||
LOG_ERROR(Service_SM, "Invalid service name '{}'", name);
|
LOG_ERROR(Service_SM, "Invalid service name '{}'", name);
|
||||||
return Service::SM::ResultInvalidServiceName;
|
return Service::SM::ResultInvalidServiceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port_result != ResultSuccess) {
|
if (port_result.Failed()) {
|
||||||
LOG_INFO(Service_SM, "Waiting for service {} to become available", name);
|
LOG_INFO(Service_SM, "Waiting for service {} to become available", name);
|
||||||
ctx.SetIsDeferred();
|
ctx.SetIsDeferred();
|
||||||
return Service::SM::ResultNotRegistered;
|
return Service::SM::ResultNotRegistered;
|
||||||
}
|
}
|
||||||
|
auto& port = port_result.Unwrap();
|
||||||
|
|
||||||
// Create a new session.
|
// Create a new session.
|
||||||
Kernel::KClientSession* 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());
|
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
|
||||||
|
|
||||||
*out_client_session = session;
|
return session;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SM::RegisterService(HLERequestContext& ctx) {
|
void SM::RegisterService(HLERequestContext& ctx) {
|
||||||
|
@ -42,7 +42,7 @@ private:
|
|||||||
void RegisterService(HLERequestContext& ctx);
|
void RegisterService(HLERequestContext& ctx);
|
||||||
void UnregisterService(HLERequestContext& ctx);
|
void UnregisterService(HLERequestContext& ctx);
|
||||||
|
|
||||||
Result GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx);
|
ResultVal<Kernel::KClientSession*> GetServiceImpl(HLERequestContext& ctx);
|
||||||
|
|
||||||
ServiceManager& service_manager;
|
ServiceManager& service_manager;
|
||||||
Kernel::KernelCore& kernel;
|
Kernel::KernelCore& kernel;
|
||||||
@ -55,7 +55,7 @@ public:
|
|||||||
|
|
||||||
Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler);
|
Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler);
|
||||||
Result UnregisterService(const std::string& name);
|
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>
|
template <Common::DerivedFrom<SessionRequestHandler> T>
|
||||||
std::shared_ptr<T> GetService(const std::string& service_name) const {
|
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);
|
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.
|
// The real implementation makes various substitutions.
|
||||||
// For now we just return the string as-is, which is good enough when not
|
// For now we just return the string as-is, which is good enough when not
|
||||||
// connecting to real Nintendo servers.
|
// 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) {
|
static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>& fqdn_out) {
|
||||||
const auto res = ResolveImpl(fqdn_in);
|
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;
|
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;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,7 @@ namespace Service::SPL {
|
|||||||
Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_,
|
Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_,
|
||||||
const char* name)
|
const char* name)
|
||||||
: ServiceFramework{system_, name}, module{std::move(module_)},
|
: ServiceFramework{system_, name}, module{std::move(module_)},
|
||||||
rng(Settings::values.rng_seed_enabled ? Settings::values.rng_seed.GetValue()
|
rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))) {}
|
||||||
: static_cast<u32>(std::time(nullptr))) {}
|
|
||||||
|
|
||||||
Module::Interface::~Interface() = default;
|
Module::Interface::~Interface() = default;
|
||||||
|
|
||||||
@ -30,10 +29,10 @@ void Module::Interface::GetConfig(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
// This should call svcCallSecureMonitor with the appropriate args.
|
// This should call svcCallSecureMonitor with the appropriate args.
|
||||||
// Since we do not have it implemented yet, we will use this for now.
|
// Since we do not have it implemented yet, we will use this for now.
|
||||||
u64 smc_result{};
|
const auto smc_result = GetConfigImpl(config_item);
|
||||||
const auto result_code = GetConfigImpl(&smc_result, config_item);
|
const auto result_code = smc_result.Code();
|
||||||
|
|
||||||
if (result_code != ResultSuccess) {
|
if (smc_result.Failed()) {
|
||||||
LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item,
|
LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item,
|
||||||
result_code.raw);
|
result_code.raw);
|
||||||
|
|
||||||
@ -42,11 +41,11 @@ void Module::Interface::GetConfig(HLERequestContext& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item,
|
LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item,
|
||||||
result_code.raw, smc_result);
|
result_code.raw, *smc_result);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(result_code);
|
rb.Push(result_code);
|
||||||
rb.Push(smc_result);
|
rb.Push(*smc_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::ModularExponentiate(HLERequestContext& ctx) {
|
void Module::Interface::ModularExponentiate(HLERequestContext& ctx) {
|
||||||
@ -99,7 +98,7 @@ void Module::Interface::GetBootReason(HLERequestContext& ctx) {
|
|||||||
rb.Push(ResultSecureMonitorNotImplemented);
|
rb.Push(ResultSecureMonitorNotImplemented);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Module::Interface::GetConfigImpl(u64* out_config, ConfigItem config_item) const {
|
ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const {
|
||||||
switch (config_item) {
|
switch (config_item) {
|
||||||
case ConfigItem::DisableProgramVerification:
|
case ConfigItem::DisableProgramVerification:
|
||||||
case ConfigItem::DramId:
|
case ConfigItem::DramId:
|
||||||
@ -121,50 +120,40 @@ Result Module::Interface::GetConfigImpl(u64* out_config, ConfigItem config_item)
|
|||||||
return ResultSecureMonitorNotImplemented;
|
return ResultSecureMonitorNotImplemented;
|
||||||
case ConfigItem::ExosphereApiVersion:
|
case ConfigItem::ExosphereApiVersion:
|
||||||
// Get information about the current exosphere version.
|
// Get information about the current exosphere version.
|
||||||
*out_config = (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) |
|
return (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) |
|
||||||
(u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) |
|
(u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) |
|
||||||
(u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) |
|
(u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) |
|
||||||
(static_cast<u64>(HLE::ApiVersion::GetTargetFirmware()));
|
(static_cast<u64>(HLE::ApiVersion::GetTargetFirmware()));
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExosphereNeedsReboot:
|
case ConfigItem::ExosphereNeedsReboot:
|
||||||
// We are executing, so we aren't in the process of rebooting.
|
// We are executing, so we aren't in the process of rebooting.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExosphereNeedsShutdown:
|
case ConfigItem::ExosphereNeedsShutdown:
|
||||||
// We are executing, so we aren't in the process of shutting down.
|
// We are executing, so we aren't in the process of shutting down.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExosphereGitCommitHash:
|
case ConfigItem::ExosphereGitCommitHash:
|
||||||
// Get information about the current exosphere git commit hash.
|
// Get information about the current exosphere git commit hash.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExosphereHasRcmBugPatch:
|
case ConfigItem::ExosphereHasRcmBugPatch:
|
||||||
// Get information about whether this unit has the RCM bug patched.
|
// Get information about whether this unit has the RCM bug patched.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExosphereBlankProdInfo:
|
case ConfigItem::ExosphereBlankProdInfo:
|
||||||
// Get whether this unit should simulate a "blanked" PRODINFO.
|
// Get whether this unit should simulate a "blanked" PRODINFO.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExosphereAllowCalWrites:
|
case ConfigItem::ExosphereAllowCalWrites:
|
||||||
// Get whether this unit should allow writing to the calibration partition.
|
// Get whether this unit should allow writing to the calibration partition.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExosphereEmummcType:
|
case ConfigItem::ExosphereEmummcType:
|
||||||
// Get what kind of emummc this unit has active.
|
// Get what kind of emummc this unit has active.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExospherePayloadAddress:
|
case ConfigItem::ExospherePayloadAddress:
|
||||||
// Gets the physical address of the reboot payload buffer, if one exists.
|
// Gets the physical address of the reboot payload buffer, if one exists.
|
||||||
return ResultSecureMonitorNotInitialized;
|
return ResultSecureMonitorNotInitialized;
|
||||||
case ConfigItem::ExosphereLogConfiguration:
|
case ConfigItem::ExosphereLogConfiguration:
|
||||||
// Get the log configuration.
|
// Get the log configuration.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
case ConfigItem::ExosphereForceEnableUsb30:
|
case ConfigItem::ExosphereForceEnableUsb30:
|
||||||
// Get whether usb 3.0 should be force-enabled.
|
// Get whether usb 3.0 should be force-enabled.
|
||||||
*out_config = u64{0};
|
return u64{0};
|
||||||
return ResultSuccess;
|
|
||||||
default:
|
default:
|
||||||
return ResultSecureMonitorInvalidArgument;
|
return ResultSecureMonitorInvalidArgument;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
std::shared_ptr<Module> module;
|
std::shared_ptr<Module> module;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result GetConfigImpl(u64* out_config, ConfigItem config_item) const;
|
ResultVal<u64> GetConfigImpl(ConfigItem config_item) const;
|
||||||
|
|
||||||
std::mt19937 rng;
|
std::mt19937 rng;
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/result.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/hle/service/server_manager.h"
|
#include "core/hle/service/server_manager.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
@ -142,12 +141,12 @@ private:
|
|||||||
bool did_set_host_name = false;
|
bool did_set_host_name = false;
|
||||||
bool did_handshake = false;
|
bool did_handshake = false;
|
||||||
|
|
||||||
Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) {
|
ResultVal<s32> SetSocketDescriptorImpl(s32 fd) {
|
||||||
LOG_DEBUG(Service_SSL, "called, fd={}", fd);
|
LOG_DEBUG(Service_SSL, "called, fd={}", fd);
|
||||||
ASSERT(!did_handshake);
|
ASSERT(!did_handshake);
|
||||||
auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
|
auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
|
||||||
ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
|
ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
|
||||||
|
s32 ret_fd;
|
||||||
// Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor
|
// Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor
|
||||||
if (do_not_close_socket) {
|
if (do_not_close_socket) {
|
||||||
auto res = bsd->DuplicateSocketImpl(fd);
|
auto res = bsd->DuplicateSocketImpl(fd);
|
||||||
@ -157,9 +156,9 @@ private:
|
|||||||
}
|
}
|
||||||
fd = *res;
|
fd = *res;
|
||||||
fd_to_close = fd;
|
fd_to_close = fd;
|
||||||
*out_fd = fd;
|
ret_fd = fd;
|
||||||
} else {
|
} else {
|
||||||
*out_fd = -1;
|
ret_fd = -1;
|
||||||
}
|
}
|
||||||
std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd);
|
std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd);
|
||||||
if (!sock.has_value()) {
|
if (!sock.has_value()) {
|
||||||
@ -168,7 +167,7 @@ private:
|
|||||||
}
|
}
|
||||||
socket = std::move(*sock);
|
socket = std::move(*sock);
|
||||||
backend->SetSocket(socket);
|
backend->SetSocket(socket);
|
||||||
return ResultSuccess;
|
return ret_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SetHostNameImpl(const std::string& hostname) {
|
Result SetHostNameImpl(const std::string& hostname) {
|
||||||
@ -248,36 +247,34 @@ private:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ReadImpl(std::vector<u8>* out_data, size_t size) {
|
ResultVal<std::vector<u8>> ReadImpl(size_t size) {
|
||||||
ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
|
ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
|
||||||
size_t actual_size{};
|
std::vector<u8> res(size);
|
||||||
Result res = backend->Read(&actual_size, *out_data);
|
ResultVal<size_t> actual = backend->Read(res);
|
||||||
if (res != ResultSuccess) {
|
if (actual.Failed()) {
|
||||||
return res;
|
return actual.Code();
|
||||||
}
|
}
|
||||||
out_data->resize(actual_size);
|
res.resize(*actual);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result WriteImpl(size_t* out_size, std::span<const u8> data) {
|
ResultVal<size_t> WriteImpl(std::span<const u8> data) {
|
||||||
ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
|
ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
|
||||||
return backend->Write(out_size, data);
|
return backend->Write(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result PendingImpl(s32* out_pending) {
|
ResultVal<s32> PendingImpl() {
|
||||||
LOG_WARNING(Service_SSL, "(STUBBED) called.");
|
LOG_WARNING(Service_SSL, "(STUBBED) called.");
|
||||||
*out_pending = 0;
|
return 0;
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSocketDescriptor(HLERequestContext& ctx) {
|
void SetSocketDescriptor(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const s32 in_fd = rp.Pop<s32>();
|
const s32 fd = rp.Pop<s32>();
|
||||||
s32 out_fd{-1};
|
const ResultVal<s32> res = SetSocketDescriptorImpl(fd);
|
||||||
const Result res = SetSocketDescriptorImpl(&out_fd, in_fd);
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
rb.Push<s32>(out_fd);
|
rb.Push<s32>(res.ValueOr(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHostName(HLERequestContext& ctx) {
|
void SetHostName(HLERequestContext& ctx) {
|
||||||
@ -316,15 +313,14 @@ private:
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(OutputParameters) == 0x8);
|
static_assert(sizeof(OutputParameters) == 0x8);
|
||||||
|
|
||||||
Result res = DoHandshakeImpl();
|
const Result res = DoHandshakeImpl();
|
||||||
OutputParameters out{};
|
OutputParameters out{};
|
||||||
if (res == ResultSuccess) {
|
if (res == ResultSuccess) {
|
||||||
std::vector<std::vector<u8>> certs;
|
auto certs = backend->GetServerCerts();
|
||||||
res = backend->GetServerCerts(&certs);
|
if (certs.Succeeded()) {
|
||||||
if (res == ResultSuccess) {
|
const std::vector<u8> certs_buf = SerializeServerCerts(*certs);
|
||||||
const std::vector<u8> certs_buf = SerializeServerCerts(certs);
|
|
||||||
ctx.WriteBuffer(certs_buf);
|
ctx.WriteBuffer(certs_buf);
|
||||||
out.certs_count = static_cast<u32>(certs.size());
|
out.certs_count = static_cast<u32>(certs->size());
|
||||||
out.certs_size = static_cast<u32>(certs_buf.size());
|
out.certs_size = static_cast<u32>(certs_buf.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -334,32 +330,29 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Read(HLERequestContext& ctx) {
|
void Read(HLERequestContext& ctx) {
|
||||||
std::vector<u8> output_bytes;
|
const ResultVal<std::vector<u8>> res = ReadImpl(ctx.GetWriteBufferSize());
|
||||||
const Result res = ReadImpl(&output_bytes, ctx.GetWriteBufferSize());
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
if (res == ResultSuccess) {
|
if (res.Succeeded()) {
|
||||||
rb.Push(static_cast<u32>(output_bytes.size()));
|
rb.Push(static_cast<u32>(res->size()));
|
||||||
ctx.WriteBuffer(output_bytes);
|
ctx.WriteBuffer(*res);
|
||||||
} else {
|
} else {
|
||||||
rb.Push(static_cast<u32>(0));
|
rb.Push(static_cast<u32>(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(HLERequestContext& ctx) {
|
void Write(HLERequestContext& ctx) {
|
||||||
size_t write_size{0};
|
const ResultVal<size_t> res = WriteImpl(ctx.ReadBuffer());
|
||||||
const Result res = WriteImpl(&write_size, ctx.ReadBuffer());
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
rb.Push(static_cast<u32>(write_size));
|
rb.Push(static_cast<u32>(res.ValueOr(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pending(HLERequestContext& ctx) {
|
void Pending(HLERequestContext& ctx) {
|
||||||
s32 pending_size{0};
|
const ResultVal<s32> res = PendingImpl();
|
||||||
const Result res = PendingImpl(&pending_size);
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(res);
|
rb.Push(res.Code());
|
||||||
rb.Push<s32>(pending_size);
|
rb.Push<s32>(res.ValueOr(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSessionCacheMode(HLERequestContext& ctx) {
|
void SetSessionCacheMode(HLERequestContext& ctx) {
|
||||||
@ -445,14 +438,13 @@ private:
|
|||||||
void CreateConnection(HLERequestContext& ctx) {
|
void CreateConnection(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_SSL, "called");
|
LOG_WARNING(Service_SSL, "called");
|
||||||
|
|
||||||
std::unique_ptr<SSLConnectionBackend> backend;
|
auto backend_res = CreateSSLConnectionBackend();
|
||||||
const Result res = CreateSSLConnectionBackend(&backend);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(res);
|
rb.Push(backend_res.Code());
|
||||||
if (res == ResultSuccess) {
|
if (backend_res.Succeeded()) {
|
||||||
rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data,
|
rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data,
|
||||||
std::move(backend));
|
std::move(*backend_res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ public:
|
|||||||
virtual void SetSocket(std::shared_ptr<Network::SocketBase> socket) = 0;
|
virtual void SetSocket(std::shared_ptr<Network::SocketBase> socket) = 0;
|
||||||
virtual Result SetHostName(const std::string& hostname) = 0;
|
virtual Result SetHostName(const std::string& hostname) = 0;
|
||||||
virtual Result DoHandshake() = 0;
|
virtual Result DoHandshake() = 0;
|
||||||
virtual Result Read(size_t* out_size, std::span<u8> data) = 0;
|
virtual ResultVal<size_t> Read(std::span<u8> data) = 0;
|
||||||
virtual Result Write(size_t* out_size, std::span<const u8> data) = 0;
|
virtual ResultVal<size_t> Write(std::span<const u8> data) = 0;
|
||||||
virtual Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) = 0;
|
virtual ResultVal<std::vector<std::vector<u8>>> GetServerCerts() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend);
|
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend();
|
||||||
|
|
||||||
} // namespace Service::SSL
|
} // namespace Service::SSL
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace Service::SSL {
|
namespace Service::SSL {
|
||||||
|
|
||||||
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) {
|
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
|
||||||
LOG_ERROR(Service_SSL,
|
LOG_ERROR(Service_SSL,
|
||||||
"Can't create SSL connection because no SSL backend is available on this platform");
|
"Can't create SSL connection because no SSL backend is available on this platform");
|
||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
|
@ -105,30 +105,31 @@ public:
|
|||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return HandleReturn("SSL_do_handshake", 0, ret);
|
return HandleReturn("SSL_do_handshake", 0, ret).Code();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Read(size_t* out_size, std::span<u8> data) override {
|
ResultVal<size_t> Read(std::span<u8> data) override {
|
||||||
const int ret = SSL_read_ex(ssl, data.data(), data.size(), out_size);
|
size_t actual;
|
||||||
return HandleReturn("SSL_read_ex", out_size, ret);
|
const int ret = SSL_read_ex(ssl, data.data(), data.size(), &actual);
|
||||||
|
return HandleReturn("SSL_read_ex", actual, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Write(size_t* out_size, std::span<const u8> data) override {
|
ResultVal<size_t> Write(std::span<const u8> data) override {
|
||||||
const int ret = SSL_write_ex(ssl, data.data(), data.size(), out_size);
|
size_t actual;
|
||||||
return HandleReturn("SSL_write_ex", out_size, ret);
|
const int ret = SSL_write_ex(ssl, data.data(), data.size(), &actual);
|
||||||
|
return HandleReturn("SSL_write_ex", actual, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HandleReturn(const char* what, size_t* actual, int ret) {
|
ResultVal<size_t> HandleReturn(const char* what, size_t actual, int ret) {
|
||||||
const int ssl_err = SSL_get_error(ssl, ret);
|
const int ssl_err = SSL_get_error(ssl, ret);
|
||||||
CheckOpenSSLErrors();
|
CheckOpenSSLErrors();
|
||||||
switch (ssl_err) {
|
switch (ssl_err) {
|
||||||
case SSL_ERROR_NONE:
|
case SSL_ERROR_NONE:
|
||||||
return ResultSuccess;
|
return actual;
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_ZERO_RETURN", what);
|
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_ZERO_RETURN", what);
|
||||||
// DoHandshake special-cases this, but for Read and Write:
|
// DoHandshake special-cases this, but for Read and Write:
|
||||||
*actual = 0;
|
return size_t(0);
|
||||||
return ResultSuccess;
|
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_READ", what);
|
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_READ", what);
|
||||||
return ResultWouldBlock;
|
return ResultWouldBlock;
|
||||||
@ -138,20 +139,20 @@ public:
|
|||||||
default:
|
default:
|
||||||
if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) {
|
if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) {
|
||||||
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what);
|
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what);
|
||||||
*actual = 0;
|
return size_t(0);
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
LOG_ERROR(Service_SSL, "{} => other SSL_get_error return value {}", what, ssl_err);
|
LOG_ERROR(Service_SSL, "{} => other SSL_get_error return value {}", what, ssl_err);
|
||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override {
|
ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
|
||||||
STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
|
STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
|
||||||
if (!chain) {
|
if (!chain) {
|
||||||
LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr");
|
LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr");
|
||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
}
|
}
|
||||||
|
std::vector<std::vector<u8>> ret;
|
||||||
int count = sk_X509_num(chain);
|
int count = sk_X509_num(chain);
|
||||||
ASSERT(count >= 0);
|
ASSERT(count >= 0);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
@ -160,10 +161,10 @@ public:
|
|||||||
unsigned char* buf = nullptr;
|
unsigned char* buf = nullptr;
|
||||||
int len = i2d_X509(x509, &buf);
|
int len = i2d_X509(x509, &buf);
|
||||||
ASSERT_OR_EXECUTE(len >= 0 && buf, { continue; });
|
ASSERT_OR_EXECUTE(len >= 0 && buf, { continue; });
|
||||||
out_certs->emplace_back(buf, buf + len);
|
ret.emplace_back(buf, buf + len);
|
||||||
OPENSSL_free(buf);
|
OPENSSL_free(buf);
|
||||||
}
|
}
|
||||||
return ResultSuccess;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
~SSLConnectionBackendOpenSSL() {
|
~SSLConnectionBackendOpenSSL() {
|
||||||
@ -252,13 +253,13 @@ public:
|
|||||||
std::shared_ptr<Network::SocketBase> socket;
|
std::shared_ptr<Network::SocketBase> socket;
|
||||||
};
|
};
|
||||||
|
|
||||||
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) {
|
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
|
||||||
auto conn = std::make_unique<SSLConnectionBackendOpenSSL>();
|
auto conn = std::make_unique<SSLConnectionBackendOpenSSL>();
|
||||||
|
const Result res = conn->Init();
|
||||||
R_TRY(conn->Init());
|
if (res.IsFailure()) {
|
||||||
|
return res;
|
||||||
*out_backend = std::move(conn);
|
}
|
||||||
return ResultSuccess;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -299,22 +299,21 @@ public:
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Read(size_t* out_size, std::span<u8> data) override {
|
ResultVal<size_t> Read(std::span<u8> data) override {
|
||||||
*out_size = 0;
|
|
||||||
if (handshake_state != HandshakeState::Connected) {
|
if (handshake_state != HandshakeState::Connected) {
|
||||||
LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake");
|
LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake");
|
||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
}
|
}
|
||||||
if (data.size() == 0 || got_read_eof) {
|
if (data.size() == 0 || got_read_eof) {
|
||||||
return ResultSuccess;
|
return size_t(0);
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!cleartext_read_buf.empty()) {
|
if (!cleartext_read_buf.empty()) {
|
||||||
*out_size = std::min(cleartext_read_buf.size(), data.size());
|
const size_t read_size = std::min(cleartext_read_buf.size(), data.size());
|
||||||
std::memcpy(data.data(), cleartext_read_buf.data(), *out_size);
|
std::memcpy(data.data(), cleartext_read_buf.data(), read_size);
|
||||||
cleartext_read_buf.erase(cleartext_read_buf.begin(),
|
cleartext_read_buf.erase(cleartext_read_buf.begin(),
|
||||||
cleartext_read_buf.begin() + *out_size);
|
cleartext_read_buf.begin() + read_size);
|
||||||
return ResultSuccess;
|
return read_size;
|
||||||
}
|
}
|
||||||
if (!ciphertext_read_buf.empty()) {
|
if (!ciphertext_read_buf.empty()) {
|
||||||
SecBuffer empty{
|
SecBuffer empty{
|
||||||
@ -367,8 +366,7 @@ public:
|
|||||||
case SEC_I_CONTEXT_EXPIRED:
|
case SEC_I_CONTEXT_EXPIRED:
|
||||||
// Server hung up by sending close_notify.
|
// Server hung up by sending close_notify.
|
||||||
got_read_eof = true;
|
got_read_eof = true;
|
||||||
*out_size = 0;
|
return size_t(0);
|
||||||
return ResultSuccess;
|
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Service_SSL, "DecryptMessage failed: {}",
|
LOG_ERROR(Service_SSL, "DecryptMessage failed: {}",
|
||||||
Common::NativeErrorToString(ret));
|
Common::NativeErrorToString(ret));
|
||||||
@ -381,21 +379,18 @@ public:
|
|||||||
}
|
}
|
||||||
if (ciphertext_read_buf.empty()) {
|
if (ciphertext_read_buf.empty()) {
|
||||||
got_read_eof = true;
|
got_read_eof = true;
|
||||||
*out_size = 0;
|
return size_t(0);
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Write(size_t* out_size, std::span<const u8> data) override {
|
ResultVal<size_t> Write(std::span<const u8> data) override {
|
||||||
*out_size = 0;
|
|
||||||
|
|
||||||
if (handshake_state != HandshakeState::Connected) {
|
if (handshake_state != HandshakeState::Connected) {
|
||||||
LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake");
|
LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake");
|
||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
}
|
}
|
||||||
if (data.size() == 0) {
|
if (data.size() == 0) {
|
||||||
return ResultSuccess;
|
return size_t(0);
|
||||||
}
|
}
|
||||||
data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage));
|
data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage));
|
||||||
if (!cleartext_write_buf.empty()) {
|
if (!cleartext_write_buf.empty()) {
|
||||||
@ -407,7 +402,7 @@ public:
|
|||||||
LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer");
|
LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer");
|
||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
}
|
}
|
||||||
return WriteAlreadyEncryptedData(out_size);
|
return WriteAlreadyEncryptedData();
|
||||||
} else {
|
} else {
|
||||||
cleartext_write_buf.assign(data.begin(), data.end());
|
cleartext_write_buf.assign(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
@ -453,21 +448,21 @@ public:
|
|||||||
tmp_data_buf.end());
|
tmp_data_buf.end());
|
||||||
ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(),
|
ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(),
|
||||||
trailer_buf.end());
|
trailer_buf.end());
|
||||||
return WriteAlreadyEncryptedData(out_size);
|
return WriteAlreadyEncryptedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result WriteAlreadyEncryptedData(size_t* out_size) {
|
ResultVal<size_t> WriteAlreadyEncryptedData() {
|
||||||
const Result r = FlushCiphertextWriteBuf();
|
const Result r = FlushCiphertextWriteBuf();
|
||||||
if (r != ResultSuccess) {
|
if (r != ResultSuccess) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
// write buf is empty
|
// write buf is empty
|
||||||
*out_size = cleartext_write_buf.size();
|
const size_t cleartext_bytes_written = cleartext_write_buf.size();
|
||||||
cleartext_write_buf.clear();
|
cleartext_write_buf.clear();
|
||||||
return ResultSuccess;
|
return cleartext_bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override {
|
ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
|
||||||
PCCERT_CONTEXT returned_cert = nullptr;
|
PCCERT_CONTEXT returned_cert = nullptr;
|
||||||
const SECURITY_STATUS ret =
|
const SECURITY_STATUS ret =
|
||||||
QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert);
|
QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert);
|
||||||
@ -478,15 +473,16 @@ public:
|
|||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
}
|
}
|
||||||
PCCERT_CONTEXT some_cert = nullptr;
|
PCCERT_CONTEXT some_cert = nullptr;
|
||||||
|
std::vector<std::vector<u8>> certs;
|
||||||
while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) {
|
while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) {
|
||||||
out_certs->emplace_back(static_cast<u8*>(some_cert->pbCertEncoded),
|
certs.emplace_back(static_cast<u8*>(some_cert->pbCertEncoded),
|
||||||
static_cast<u8*>(some_cert->pbCertEncoded) +
|
static_cast<u8*>(some_cert->pbCertEncoded) +
|
||||||
some_cert->cbCertEncoded);
|
some_cert->cbCertEncoded);
|
||||||
}
|
}
|
||||||
std::reverse(out_certs->begin(),
|
std::reverse(certs.begin(),
|
||||||
out_certs->end()); // Windows returns certs in reverse order from what we want
|
certs.end()); // Windows returns certs in reverse order from what we want
|
||||||
CertFreeCertificateContext(returned_cert);
|
CertFreeCertificateContext(returned_cert);
|
||||||
return ResultSuccess;
|
return certs;
|
||||||
}
|
}
|
||||||
|
|
||||||
~SSLConnectionBackendSchannel() {
|
~SSLConnectionBackendSchannel() {
|
||||||
@ -536,13 +532,13 @@ public:
|
|||||||
size_t read_buf_fill_size = 0;
|
size_t read_buf_fill_size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) {
|
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
|
||||||
auto conn = std::make_unique<SSLConnectionBackendSchannel>();
|
auto conn = std::make_unique<SSLConnectionBackendSchannel>();
|
||||||
|
const Result res = conn->Init();
|
||||||
R_TRY(conn->Init());
|
if (res.IsFailure()) {
|
||||||
|
return res;
|
||||||
*out_backend = std::move(conn);
|
}
|
||||||
return ResultSuccess;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::SSL
|
} // namespace Service::SSL
|
||||||
|
@ -100,23 +100,27 @@ public:
|
|||||||
|
|
||||||
Result DoHandshake() override {
|
Result DoHandshake() override {
|
||||||
OSStatus status = SSLHandshake(context);
|
OSStatus status = SSLHandshake(context);
|
||||||
return HandleReturn("SSLHandshake", 0, status);
|
return HandleReturn("SSLHandshake", 0, status).Code();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Read(size_t* out_size, std::span<u8> data) override {
|
ResultVal<size_t> Read(std::span<u8> data) override {
|
||||||
OSStatus status = SSLRead(context, data.data(), data.size(), out_size);
|
size_t actual;
|
||||||
return HandleReturn("SSLRead", out_size, status);
|
OSStatus status = SSLRead(context, data.data(), data.size(), &actual);
|
||||||
|
;
|
||||||
|
return HandleReturn("SSLRead", actual, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Write(size_t* out_size, std::span<const u8> data) override {
|
ResultVal<size_t> Write(std::span<const u8> data) override {
|
||||||
OSStatus status = SSLWrite(context, data.data(), data.size(), out_size);
|
size_t actual;
|
||||||
return HandleReturn("SSLWrite", out_size, status);
|
OSStatus status = SSLWrite(context, data.data(), data.size(), &actual);
|
||||||
|
;
|
||||||
|
return HandleReturn("SSLWrite", actual, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HandleReturn(const char* what, size_t* actual, OSStatus status) {
|
ResultVal<size_t> HandleReturn(const char* what, size_t actual, OSStatus status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 0:
|
case 0:
|
||||||
return ResultSuccess;
|
return actual;
|
||||||
case errSSLWouldBlock:
|
case errSSLWouldBlock:
|
||||||
return ResultWouldBlock;
|
return ResultWouldBlock;
|
||||||
default: {
|
default: {
|
||||||
@ -132,21 +136,22 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override {
|
ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
|
||||||
CFReleaser<SecTrustRef> trust;
|
CFReleaser<SecTrustRef> trust;
|
||||||
OSStatus status = SSLCopyPeerTrust(context, &trust.ptr);
|
OSStatus status = SSLCopyPeerTrust(context, &trust.ptr);
|
||||||
if (status) {
|
if (status) {
|
||||||
LOG_ERROR(Service_SSL, "SSLCopyPeerTrust failed: {}", OSStatusToString(status));
|
LOG_ERROR(Service_SSL, "SSLCopyPeerTrust failed: {}", OSStatusToString(status));
|
||||||
return ResultInternalError;
|
return ResultInternalError;
|
||||||
}
|
}
|
||||||
|
std::vector<std::vector<u8>> ret;
|
||||||
for (CFIndex i = 0, count = SecTrustGetCertificateCount(trust); i < count; i++) {
|
for (CFIndex i = 0, count = SecTrustGetCertificateCount(trust); i < count; i++) {
|
||||||
SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
|
SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
|
||||||
CFReleaser<CFDataRef> data(SecCertificateCopyData(cert));
|
CFReleaser<CFDataRef> data(SecCertificateCopyData(cert));
|
||||||
ASSERT_OR_EXECUTE(data, { return ResultInternalError; });
|
ASSERT_OR_EXECUTE(data, { return ResultInternalError; });
|
||||||
const u8* ptr = CFDataGetBytePtr(data);
|
const u8* ptr = CFDataGetBytePtr(data);
|
||||||
out_certs->emplace_back(ptr, ptr + CFDataGetLength(data));
|
ret.emplace_back(ptr, ptr + CFDataGetLength(data));
|
||||||
}
|
}
|
||||||
return ResultSuccess;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static OSStatus ReadCallback(SSLConnectionRef connection, void* data, size_t* dataLength) {
|
static OSStatus ReadCallback(SSLConnectionRef connection, void* data, size_t* dataLength) {
|
||||||
@ -205,13 +210,13 @@ private:
|
|||||||
std::shared_ptr<Network::SocketBase> socket;
|
std::shared_ptr<Network::SocketBase> socket;
|
||||||
};
|
};
|
||||||
|
|
||||||
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) {
|
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
|
||||||
auto conn = std::make_unique<SSLConnectionBackendSecureTransport>();
|
auto conn = std::make_unique<SSLConnectionBackendSecureTransport>();
|
||||||
|
const Result res = conn->Init();
|
||||||
R_TRY(conn->Init());
|
if (res.IsFailure()) {
|
||||||
|
return res;
|
||||||
*out_backend = std::move(conn);
|
}
|
||||||
return ResultSuccess;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::SSL
|
} // namespace Service::SSL
|
||||||
|
@ -78,8 +78,7 @@ TimeZoneContentManager::TimeZoneContentManager(Core::System& system_)
|
|||||||
location_name_cache{BuildLocationNameCache(time_zone_binary)} {}
|
location_name_cache{BuildLocationNameCache(time_zone_binary)} {}
|
||||||
|
|
||||||
void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
|
void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
|
||||||
const auto timezone_setting =
|
const auto timezone_setting = Settings::GetTimeZoneString();
|
||||||
Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
|
|
||||||
|
|
||||||
if (FileSys::VirtualFile vfs_file;
|
if (FileSys::VirtualFile vfs_file;
|
||||||
GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) {
|
GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) {
|
||||||
|
@ -58,15 +58,14 @@ const Layer& Display::GetLayer(std::size_t index) const {
|
|||||||
return *layers.at(index);
|
return *layers.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) {
|
ResultVal<Kernel::KReadableEvent*> Display::GetVSyncEvent() {
|
||||||
if (got_vsync_event) {
|
if (got_vsync_event) {
|
||||||
return ResultPermissionDenied;
|
return ResultPermissionDenied;
|
||||||
}
|
}
|
||||||
|
|
||||||
got_vsync_event = true;
|
got_vsync_event = true;
|
||||||
|
|
||||||
*out_vsync_event = GetVSyncEventUnchecked();
|
return GetVSyncEventUnchecked();
|
||||||
return ResultSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {
|
Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {
|
||||||
|
@ -85,7 +85,7 @@ public:
|
|||||||
* @returns The internal Vsync event if it has not yet been retrieved,
|
* @returns The internal Vsync event if it has not yet been retrieved,
|
||||||
* VI::ResultPermissionDenied otherwise.
|
* VI::ResultPermissionDenied otherwise.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] Result GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event);
|
[[nodiscard]] ResultVal<Kernel::KReadableEvent*> GetVSyncEvent();
|
||||||
|
|
||||||
/// Gets the internal vsync event.
|
/// Gets the internal vsync event.
|
||||||
Kernel::KReadableEvent* GetVSyncEventUnchecked();
|
Kernel::KReadableEvent* GetVSyncEventUnchecked();
|
||||||
|
@ -683,9 +683,9 @@ private:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
|
LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
|
||||||
|
|
||||||
Kernel::KReadableEvent* vsync_event{};
|
const auto vsync_event = nv_flinger.FindVsyncEvent(display_id);
|
||||||
const auto result = nv_flinger.FindVsyncEvent(&vsync_event, display_id);
|
if (vsync_event.Failed()) {
|
||||||
if (result != ResultSuccess) {
|
const auto result = vsync_event.Code();
|
||||||
if (result == ResultNotFound) {
|
if (result == ResultNotFound) {
|
||||||
LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
|
LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
|
||||||
}
|
}
|
||||||
@ -697,7 +697,7 @@ private:
|
|||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(vsync_event);
|
rb.PushCopyObjects(*vsync_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConvertScalingMode(HLERequestContext& ctx) {
|
void ConvertScalingMode(HLERequestContext& ctx) {
|
||||||
@ -705,16 +705,15 @@ private:
|
|||||||
const auto mode = rp.PopEnum<NintendoScaleMode>();
|
const auto mode = rp.PopEnum<NintendoScaleMode>();
|
||||||
LOG_DEBUG(Service_VI, "called mode={}", mode);
|
LOG_DEBUG(Service_VI, "called mode={}", mode);
|
||||||
|
|
||||||
ConvertedScaleMode converted_mode{};
|
const auto converted_mode = ConvertScalingModeImpl(mode);
|
||||||
const auto result = ConvertScalingModeImpl(&converted_mode, mode);
|
|
||||||
|
|
||||||
if (result == ResultSuccess) {
|
if (converted_mode.Succeeded()) {
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushEnum(converted_mode);
|
rb.PushEnum(*converted_mode);
|
||||||
} else {
|
} else {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(converted_mode.Code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,24 +760,18 @@ private:
|
|||||||
rb.Push(alignment);
|
rb.Push(alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode,
|
static ResultVal<ConvertedScaleMode> ConvertScalingModeImpl(NintendoScaleMode mode) {
|
||||||
NintendoScaleMode mode) {
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case NintendoScaleMode::None:
|
case NintendoScaleMode::None:
|
||||||
*out_scaling_mode = ConvertedScaleMode::None;
|
return ConvertedScaleMode::None;
|
||||||
return ResultSuccess;
|
|
||||||
case NintendoScaleMode::Freeze:
|
case NintendoScaleMode::Freeze:
|
||||||
*out_scaling_mode = ConvertedScaleMode::Freeze;
|
return ConvertedScaleMode::Freeze;
|
||||||
return ResultSuccess;
|
|
||||||
case NintendoScaleMode::ScaleToWindow:
|
case NintendoScaleMode::ScaleToWindow:
|
||||||
*out_scaling_mode = ConvertedScaleMode::ScaleToWindow;
|
return ConvertedScaleMode::ScaleToWindow;
|
||||||
return ResultSuccess;
|
|
||||||
case NintendoScaleMode::ScaleAndCrop:
|
case NintendoScaleMode::ScaleAndCrop:
|
||||||
*out_scaling_mode = ConvertedScaleMode::ScaleAndCrop;
|
return ConvertedScaleMode::ScaleAndCrop;
|
||||||
return ResultSuccess;
|
|
||||||
case NintendoScaleMode::PreserveAspectRatio:
|
case NintendoScaleMode::PreserveAspectRatio:
|
||||||
*out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio;
|
return ConvertedScaleMode::PreserveAspectRatio;
|
||||||
return ResultSuccess;
|
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
|
LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
|
||||||
return ResultOperationFailed;
|
return ResultOperationFailed;
|
||||||
|
@ -476,13 +476,7 @@ NetworkInstance::~NetworkInstance() {
|
|||||||
std::optional<IPv4Address> GetHostIPv4Address() {
|
std::optional<IPv4Address> GetHostIPv4Address() {
|
||||||
const auto network_interface = Network::GetSelectedNetworkInterface();
|
const auto network_interface = Network::GetSelectedNetworkInterface();
|
||||||
if (!network_interface.has_value()) {
|
if (!network_interface.has_value()) {
|
||||||
// Only print the error once to avoid log spam
|
LOG_DEBUG(Network, "GetSelectedNetworkInterface returned no interface");
|
||||||
static bool print_error = true;
|
|
||||||
if (print_error) {
|
|
||||||
LOG_ERROR(Network, "GetSelectedNetworkInterface returned no interface");
|
|
||||||
print_error = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user