diff options
226 files changed, 5492 insertions, 3655 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt index d35de80c4..a84ac77a2 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt @@ -64,17 +64,17 @@ data class PlayerInput(      fun hasMapping(): Boolean {          var hasMapping = false          buttons.forEach { -            if (it != "[empty]") { +            if (it != "[empty]" && it.isNotEmpty()) {                  hasMapping = true              }          }          analogs.forEach { -            if (it != "[empty]") { +            if (it != "[empty]" && it.isNotEmpty()) {                  hasMapping = true              }          }          motions.forEach { -            if (it != "[empty]") { +            if (it != "[empty]" && it.isNotEmpty()) {                  hasMapping = true              }          } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt index a0d8cfede..6f16cf5b1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt @@ -6,7 +6,8 @@ package org.yuzu.yuzu_emu.features.settings.model  import org.yuzu.yuzu_emu.utils.NativeConfig  enum class StringSetting(override val key: String) : AbstractStringSetting { -    DRIVER_PATH("driver_path"); +    DRIVER_PATH("driver_path"), +    DEVICE_NAME("device_name");      override fun getString(needsGlobal: Boolean): String = NativeConfig.getString(key, needsGlobal) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 8f724835e..5fdf98318 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -16,6 +16,7 @@ import org.yuzu.yuzu_emu.features.settings.model.ByteSetting  import org.yuzu.yuzu_emu.features.settings.model.IntSetting  import org.yuzu.yuzu_emu.features.settings.model.LongSetting  import org.yuzu.yuzu_emu.features.settings.model.ShortSetting +import org.yuzu.yuzu_emu.features.settings.model.StringSetting  import org.yuzu.yuzu_emu.utils.NativeConfig  /** @@ -75,6 +76,9 @@ abstract class SettingsItem(          get() = NativeLibrary.isRunning() && !setting.global &&              !NativeConfig.isPerGameConfigLoaded() +    val clearable: Boolean +        get() = !setting.global && NativeConfig.isPerGameConfigLoaded() +      companion object {          const val TYPE_HEADER = 0          const val TYPE_SWITCH = 1 @@ -87,6 +91,7 @@ abstract class SettingsItem(          const val TYPE_INPUT = 8          const val TYPE_INT_SINGLE_CHOICE = 9          const val TYPE_INPUT_PROFILE = 10 +        const val TYPE_STRING_INPUT = 11          const val FASTMEM_COMBINED = "fastmem_combined" @@ -105,6 +110,7 @@ abstract class SettingsItem(          // List of all general          val settingsItems = HashMap<String, SettingsItem>().apply { +            put(StringInputSetting(StringSetting.DEVICE_NAME, titleId = R.string.device_name))              put(                  SwitchSetting(                      BooleanSetting.RENDERER_USE_SPEED_LIMIT, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt new file mode 100644 index 000000000..1eb999416 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.features.settings.model.view + +import androidx.annotation.StringRes +import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting + +class StringInputSetting( +    setting: AbstractStringSetting, +    @StringRes titleId: Int = 0, +    titleString: String = "", +    @StringRes descriptionId: Int = 0, +    descriptionString: String = "" +) : SettingsItem(setting, titleId, titleString, descriptionId, descriptionString) { +    override val type = TYPE_STRING_INPUT + +    fun getSelectedValue(needsGlobal: Boolean = false) = setting.getValueAsString(needsGlobal) + +    fun setSelectedValue(selection: String) = +        (setting as AbstractStringSetting).setString(selection) +} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt index 45c8faa10..500ac6e66 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt @@ -85,6 +85,10 @@ class SettingsAdapter(                  InputProfileViewHolder(ListItemSettingBinding.inflate(inflater), this)              } +            SettingsItem.TYPE_STRING_INPUT -> { +                StringInputViewHolder(ListItemSettingBinding.inflate(inflater), this) +            } +              else -> {                  HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this)              } @@ -392,6 +396,15 @@ class SettingsAdapter(          popup.show()      } +    fun onStringInputClick(item: StringInputSetting, position: Int) { +        SettingsDialogFragment.newInstance( +            settingsViewModel, +            item, +            SettingsItem.TYPE_STRING_INPUT, +            position +        ).show(fragment.childFragmentManager, SettingsDialogFragment.TAG) +    } +      fun onLongClick(item: SettingsItem, position: Int): Boolean {          SettingsDialogFragment.newInstance(              settingsViewModel, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt index a81ff6b1a..7f562a1f4 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt @@ -14,6 +14,7 @@ import androidx.fragment.app.activityViewModels  import com.google.android.material.dialog.MaterialAlertDialogBuilder  import com.google.android.material.slider.Slider  import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.DialogEditTextBinding  import org.yuzu.yuzu_emu.databinding.DialogSliderBinding  import org.yuzu.yuzu_emu.features.input.NativeInput  import org.yuzu.yuzu_emu.features.input.model.AnalogDirection @@ -23,6 +24,7 @@ import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting  import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting +import org.yuzu.yuzu_emu.features.settings.model.view.StringInputSetting  import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting  import org.yuzu.yuzu_emu.utils.ParamPackage  import org.yuzu.yuzu_emu.utils.collect @@ -37,6 +39,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener      private val settingsViewModel: SettingsViewModel by activityViewModels()      private lateinit var sliderBinding: DialogSliderBinding +    private lateinit var stringInputBinding: DialogEditTextBinding      override fun onCreate(savedInstanceState: Bundle?) {          super.onCreate(savedInstanceState) @@ -131,6 +134,18 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener                      .create()              } +            SettingsItem.TYPE_STRING_INPUT -> { +                stringInputBinding = DialogEditTextBinding.inflate(layoutInflater) +                val item = settingsViewModel.clickedItem as StringInputSetting +                stringInputBinding.editText.setText(item.getSelectedValue()) +                MaterialAlertDialogBuilder(requireContext()) +                    .setTitle(item.title) +                    .setView(stringInputBinding.root) +                    .setPositiveButton(android.R.string.ok, this) +                    .setNegativeButton(android.R.string.cancel, defaultCancelListener) +                    .create() +            } +              SettingsItem.TYPE_STRING_SINGLE_CHOICE -> {                  val item = settingsViewModel.clickedItem as StringSingleChoiceSetting                  MaterialAlertDialogBuilder(requireContext()) @@ -158,6 +173,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener      ): View? {          return when (type) {              SettingsItem.TYPE_SLIDER -> sliderBinding.root +            SettingsItem.TYPE_STRING_INPUT -> stringInputBinding.root              else -> super.onCreateView(inflater, container, savedInstanceState)          }      } @@ -200,6 +216,13 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener                  val sliderSetting = settingsViewModel.clickedItem as SliderSetting                  sliderSetting.setSelectedValue(settingsViewModel.sliderProgress.value)              } + +            is StringInputSetting -> { +                val stringInputSetting = settingsViewModel.clickedItem as StringInputSetting +                stringInputSetting.setSelectedValue( +                    (stringInputBinding.editText.text ?: "").toString() +                ) +            }          }          closeDialog()      } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index e491c29a2..3ea5f5008 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -23,6 +23,7 @@ import org.yuzu.yuzu_emu.features.settings.model.LongSetting  import org.yuzu.yuzu_emu.features.settings.model.Settings  import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag  import org.yuzu.yuzu_emu.features.settings.model.ShortSetting +import org.yuzu.yuzu_emu.features.settings.model.StringSetting  import org.yuzu.yuzu_emu.features.settings.model.view.*  import org.yuzu.yuzu_emu.utils.InputHandler  import org.yuzu.yuzu_emu.utils.NativeConfig @@ -153,6 +154,7 @@ class SettingsFragmentPresenter(      private fun addSystemSettings(sl: ArrayList<SettingsItem>) {          sl.apply { +            add(StringSetting.DEVICE_NAME.key)              add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key)              add(ShortSetting.RENDERER_SPEED_LIMIT.key)              add(BooleanSetting.USE_DOCKED_MODE.key) @@ -778,7 +780,7 @@ class SettingsFragmentPresenter(          playerIndex: Int,          paramName: String,          stick: NativeAnalog, -        defaultValue: Int +        defaultValue: Float      ): AbstractIntSetting =          object : AbstractIntSetting {              val params get() = NativeInput.getStickParam(playerIndex, stick) @@ -786,7 +788,7 @@ class SettingsFragmentPresenter(              override val key = ""              override fun getInt(needsGlobal: Boolean): Int = -                (params.get(paramName, 0.15f) * 100).toInt() +                (params.get(paramName, defaultValue) * 100).toInt()              override fun setInt(value: Int) {                  val tempParams = params @@ -794,12 +796,12 @@ class SettingsFragmentPresenter(                  NativeInput.setStickParam(playerIndex, stick, tempParams)              } -            override val defaultValue = defaultValue +            override val defaultValue = (defaultValue * 100).toInt()              override fun getValueAsString(needsGlobal: Boolean): String =                  getInt(needsGlobal).toString() -            override fun reset() = setInt(defaultValue) +            override fun reset() = setInt(this.defaultValue)          }      private fun getExtraStickSettings( @@ -809,11 +811,11 @@ class SettingsFragmentPresenter(          val stickIsController =              NativeInput.isController(NativeInput.getStickParam(playerIndex, nativeAnalog))          val modifierRangeSetting = -            getStickIntSettingFromParam(playerIndex, "modifier_scale", nativeAnalog, 50) +            getStickIntSettingFromParam(playerIndex, "modifier_scale", nativeAnalog, 0.5f)          val stickRangeSetting = -            getStickIntSettingFromParam(playerIndex, "range", nativeAnalog, 95) +            getStickIntSettingFromParam(playerIndex, "range", nativeAnalog, 0.95f)          val stickDeadzoneSetting = -            getStickIntSettingFromParam(playerIndex, "deadzone", nativeAnalog, 15) +            getStickIntSettingFromParam(playerIndex, "deadzone", nativeAnalog, 0.15f)          val out = mutableListOf<SettingsItem>().apply {              if (stickIsController) { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt index 367db7fd2..0309fad59 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt @@ -13,7 +13,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding  import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -import org.yuzu.yuzu_emu.utils.NativeConfig  import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible  class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : @@ -32,9 +31,7 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA          val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)          binding.textSettingValue.text = dateFormatter.format(zonedTime) -        binding.buttonClear.setVisible( -            !setting.setting.global || NativeConfig.isPerGameConfigLoaded() -        ) +        binding.buttonClear.setVisible(setting.clearable)          binding.buttonClear.setOnClickListener {              adapter.onClearClick(setting, bindingAdapterPosition)          } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt index e2fe0b072..489f55455 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt @@ -10,7 +10,6 @@ import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting  import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -import org.yuzu.yuzu_emu.utils.NativeConfig  import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible  class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : @@ -48,9 +47,7 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti              binding.textSettingValue.setVisible(false)          } -        binding.buttonClear.setVisible( -            !setting.setting.global || NativeConfig.isPerGameConfigLoaded() -        ) +        binding.buttonClear.setVisible(setting.clearable)          binding.buttonClear.setOnClickListener {              adapter.onClearClick(setting, bindingAdapterPosition)          } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt index a37b59b44..90a7138cb 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt @@ -9,7 +9,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -import org.yuzu.yuzu_emu.utils.NativeConfig  import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible  class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : @@ -28,9 +27,7 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda              setting.units          ) -        binding.buttonClear.setVisible( -            !setting.setting.global || NativeConfig.isPerGameConfigLoaded() -        ) +        binding.buttonClear.setVisible(setting.clearable)          binding.buttonClear.setOnClickListener {              adapter.onClearClick(setting, bindingAdapterPosition)          } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt new file mode 100644 index 000000000..a4fd36f62 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.features.settings.ui.viewholder + +import android.view.View +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.StringInputSetting +import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter +import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible + +class StringInputViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : +    SettingViewHolder(binding.root, adapter) { +    private lateinit var setting: StringInputSetting + +    override fun bind(item: SettingsItem) { +        setting = item as StringInputSetting +        binding.textSettingName.text = setting.title +        binding.textSettingDescription.setVisible(setting.description.isNotEmpty()) +        binding.textSettingDescription.text = setting.description +        binding.textSettingValue.setVisible(true) +        binding.textSettingValue.text = setting.getSelectedValue() + +        binding.buttonClear.setVisible(setting.clearable) +        binding.buttonClear.setOnClickListener { +            adapter.onClearClick(setting, bindingAdapterPosition) +        } + +        setStyle(setting.isEditable, binding) +    } + +    override fun onClick(clicked: View) { +        if (setting.isEditable) { +            adapter.onStringInputClick(setting, bindingAdapterPosition) +        } +    } + +    override fun onLongClick(clicked: View): Boolean { +        if (setting.isEditable) { +            return adapter.onLongClick(setting, bindingAdapterPosition) +        } +        return false +    } +} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt index 53f7b301f..e5763264a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt @@ -9,7 +9,6 @@ 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.SwitchSetting  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -import org.yuzu.yuzu_emu.utils.NativeConfig  import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible  class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter: SettingsAdapter) : @@ -29,9 +28,7 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter              adapter.onBooleanClick(setting, binding.switchWidget.isChecked, bindingAdapterPosition)          } -        binding.buttonClear.setVisible( -            !setting.setting.global || NativeConfig.isPerGameConfigLoaded() -        ) +        binding.buttonClear.setVisible(setting.clearable)          binding.buttonClear.setOnClickListener {              adapter.onClearClick(setting, bindingAdapterPosition)          } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index c3b2b11f8..bcc880e17 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -810,7 +810,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {                      }              }          } -        binding.doneControlConfig.setVisible(false) +        binding.doneControlConfig.setVisible(true)          binding.surfaceInputOverlay.setIsInEditMode(true)      } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt index 66907085a..737e03584 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt @@ -28,6 +28,7 @@ import org.yuzu.yuzu_emu.features.input.NativeInput  import org.yuzu.yuzu_emu.R  import org.yuzu.yuzu_emu.features.input.model.NativeAnalog  import org.yuzu.yuzu_emu.features.input.model.NativeButton +import org.yuzu.yuzu_emu.features.input.model.NpadStyleIndex  import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting  import org.yuzu.yuzu_emu.features.settings.model.IntSetting  import org.yuzu.yuzu_emu.overlay.model.OverlayControl @@ -99,12 +100,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :          }          var shouldUpdateView = false -        val playerIndex = -            if (NativeInput.isHandheldOnly()) { -                NativeInput.ConsoleDevice -            } else { -                NativeInput.Player1Device -            } +        val playerIndex = when (NativeInput.getStyleIndex(0)) { +            NpadStyleIndex.Handheld -> 8 +            else -> 0 +        }          for (button in overlayButtons) {              if (!button.updateStatus(event)) { @@ -664,7 +663,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :          val overlayControlData = NativeConfig.getOverlayControlData()          overlayControlData.forEach { -            it.enabled = OverlayControl.from(it.id)?.defaultVisibility == false +            it.enabled = OverlayControl.from(it.id)?.defaultVisibility == true          }          NativeConfig.setOverlayControlData(overlayControlData) diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 50cef5d2a..1226219ad 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -292,6 +292,9 @@ void EmulationSession::ShutdownEmulation() {      // Unload user input.      m_system.HIDCore().UnloadInputDevices(); +    // Enable all controllers +    m_system.HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); +      // Shutdown the main emulated process      if (m_load_result == Core::SystemResultStatus::Success) {          m_system.DetachDebugger(); @@ -404,7 +407,9 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,                                               const size_t program_index,                                               const bool frontend_initiated) {      MicroProfileOnThreadCreate("EmuThread"); -    SCOPE_EXIT({ MicroProfileShutdown(); }); +    SCOPE_EXIT { +        MicroProfileShutdown(); +    };      LOG_INFO(Frontend, "starting"); @@ -413,7 +418,9 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,          return Core::SystemResultStatus::ErrorLoader;      } -    SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); }); +    SCOPE_EXIT { +        EmulationSession::GetInstance().ShutdownEmulation(); +    };      jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,                                                                          frontend_initiated); diff --git a/src/android/app/src/main/jni/native_input.cpp b/src/android/app/src/main/jni/native_input.cpp index 37a65f2b8..4935a4607 100644 --- a/src/android/app/src/main/jni/native_input.cpp +++ b/src/android/app/src/main/jni/native_input.cpp @@ -102,8 +102,50 @@ void ApplyControllerConfig(size_t player_index,      }  } +std::vector<s32> GetSupportedStyles(int player_index) { +    auto& hid_core = EmulationSession::GetInstance().System().HIDCore(); +    const auto npad_style_set = hid_core.GetSupportedStyleTag(); +    std::vector<s32> supported_indexes; +    if (npad_style_set.fullkey == 1) { +        supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::Fullkey)); +    } + +    if (npad_style_set.joycon_dual == 1) { +        supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconDual)); +    } + +    if (npad_style_set.joycon_left == 1) { +        supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconLeft)); +    } + +    if (npad_style_set.joycon_right == 1) { +        supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconRight)); +    } + +    if (player_index == 0 && npad_style_set.handheld == 1) { +        supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::Handheld)); +    } + +    if (npad_style_set.gamecube == 1) { +        supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::GameCube)); +    } + +    return supported_indexes; +} +  void ConnectController(size_t player_index, bool connected) {      auto& hid_core = EmulationSession::GetInstance().System().HIDCore(); +    ApplyControllerConfig(player_index, [&](Core::HID::EmulatedController* controller) { +        auto supported_styles = GetSupportedStyles(player_index); +        auto controller_style = controller->GetNpadStyleIndex(true); +        auto style = std::find(supported_styles.begin(), supported_styles.end(), +                               static_cast<int>(controller_style)); +        if (style == supported_styles.end() && !supported_styles.empty()) { +            controller->SetNpadStyleIndex( +                static_cast<Core::HID::NpadStyleIndex>(supported_styles[0])); +        } +    }); +      if (player_index == 0) {          auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);          auto* player_one = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); @@ -522,36 +564,10 @@ jint Java_org_yuzu_yuzu_1emu_features_input_NativeInput_getButtonNameImpl(JNIEnv  jintArray Java_org_yuzu_yuzu_1emu_features_input_NativeInput_getSupportedStyleTagsImpl(      JNIEnv* env, jobject j_obj, jint j_player_index) { -    auto& hid_core = EmulationSession::GetInstance().System().HIDCore(); -    const auto npad_style_set = hid_core.GetSupportedStyleTag(); -    std::vector<s32> supported_indexes; -    if (npad_style_set.fullkey == 1) { -        supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::Fullkey)); -    } - -    if (npad_style_set.joycon_dual == 1) { -        supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconDual)); -    } - -    if (npad_style_set.joycon_left == 1) { -        supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconLeft)); -    } - -    if (npad_style_set.joycon_right == 1) { -        supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconRight)); -    } - -    if (j_player_index == 0 && npad_style_set.handheld == 1) { -        supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::Handheld)); -    } - -    if (npad_style_set.gamecube == 1) { -        supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::GameCube)); -    } - -    jintArray j_supported_indexes = env->NewIntArray(supported_indexes.size()); -    env->SetIntArrayRegion(j_supported_indexes, 0, supported_indexes.size(), -                           supported_indexes.data()); +    auto supported_styles = GetSupportedStyles(j_player_index); +    jintArray j_supported_indexes = env->NewIntArray(supported_styles.size()); +    env->SetIntArrayRegion(j_supported_indexes, 0, supported_styles.size(), +                           supported_styles.data());      return j_supported_indexes;  } diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 6a631f664..f7f19cdad 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -209,6 +209,7 @@      <string name="value_with_units">%1$s%2$s</string>      <!-- System settings strings --> +    <string name="device_name">Device name</string>      <string name="use_docked_mode">Docked Mode</string>      <string name="use_docked_mode_description">Increases resolution, decreasing performance. Handheld Mode is used when disabled, lowering resolution and increasing performance.</string>      <string name="emulated_region">Emulated region</string> diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp index d97ca2a40..49efae8e3 100644 --- a/src/audio_core/sink/cubeb_sink.cpp +++ b/src/audio_core/sink/cubeb_sink.cpp @@ -357,7 +357,9 @@ bool IsCubebSuitable() {          return false;      } -    SCOPE_EXIT({ cubeb_destroy(ctx); }); +    SCOPE_EXIT { +        cubeb_destroy(ctx); +    };  #ifdef _WIN32      if (SUCCEEDED(com_init_result)) { diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index c047b0668..0a98eb31e 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -20,10 +20,10 @@  namespace AudioCore::Sink {  void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          queue.enqueue(buffer);          ++queued_buffers; -    }); +    };      if (type == StreamType::In) {          return; diff --git a/src/common/demangle.cpp b/src/common/demangle.cpp index 6e117cb41..b2c9d126a 100644 --- a/src/common/demangle.cpp +++ b/src/common/demangle.cpp @@ -20,7 +20,9 @@ std::string DemangleSymbol(const std::string& mangled) {      }      char* demangled = nullptr; -    SCOPE_EXIT({ std::free(demangled); }); +    SCOPE_EXIT { +        std::free(demangled); +    };      if (is_itanium(mangled)) {          demangled = llvm::itaniumDemangle(mangled.c_str()); diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 860c39e6a..e0b5a6a67 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -430,11 +430,11 @@ public:      explicit Impl(size_t backing_size_, size_t virtual_size_)          : backing_size{backing_size_}, virtual_size{virtual_size_} {          bool good = false; -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (!good) {                  Release();              } -        }); +        };          long page_size = sysconf(_SC_PAGESIZE);          if (page_size != 0x1000) { diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp index 85dc18c11..3205eb7da 100644 --- a/src/common/page_table.cpp +++ b/src/common/page_table.cpp @@ -24,10 +24,10 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c      out_entry->block_size = page_size;      // Regardless of whether the page was mapped, advance on exit. -    SCOPE_EXIT({ +    SCOPE_EXIT {          context->next_page += 1;          context->next_offset += page_size; -    }); +    };      // Validate that we can read the actual entry.      const auto page = context->next_page; diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h index e9c789c88..f3e88cde9 100644 --- a/src/common/scope_exit.h +++ b/src/common/scope_exit.h @@ -7,29 +7,61 @@  #include "common/common_funcs.h"  namespace detail { -template <typename Func> -struct ScopeExitHelper { -    explicit ScopeExitHelper(Func&& func_) : func(std::move(func_)) {} -    ~ScopeExitHelper() { +template <class F> +class ScopeGuard { +    YUZU_NON_COPYABLE(ScopeGuard); + +private: +    F f; +    bool active; + +public: +    constexpr ScopeGuard(F f_) : f(std::move(f_)), active(true) {} +    constexpr ~ScopeGuard() {          if (active) { -            func(); +            f();          }      } - -    void Cancel() { +    constexpr void Cancel() {          active = false;      } -    Func func; -    bool active{true}; +    constexpr ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) { +        rhs.Cancel(); +    } + +    ScopeGuard& operator=(ScopeGuard&& rhs) = delete;  }; -template <typename Func> -ScopeExitHelper<Func> ScopeExit(Func&& func) { -    return ScopeExitHelper<Func>(std::forward<Func>(func)); +template <class F> +constexpr ScopeGuard<F> MakeScopeGuard(F f) { +    return ScopeGuard<F>(std::move(f));  } + +enum class ScopeGuardOnExit {}; + +template <typename F> +constexpr ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) { +    return ScopeGuard<F>(std::forward<F>(f)); +} +  } // namespace detail +#define CONCATENATE_IMPL(s1, s2) s1##s2 +#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2) + +#ifdef __COUNTER__ +#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__) +#else +#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __LINE__) +#endif + +/** + * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be + * used when the caller might want to cancel the ScopeExit. + */ +#define SCOPE_GUARD detail::ScopeGuardOnExit() + [&]() +  /**   * This macro allows you to conveniently specify a block of code that will run on scope exit. Handy   * for doing ad-hoc clean-up tasks in a function with multiple returns. @@ -38,7 +70,7 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {   * \code   * const int saved_val = g_foo;   * g_foo = 55; - * SCOPE_EXIT({ g_foo = saved_val; }); + * SCOPE_EXIT{ g_foo = saved_val; };   *   * if (Bar()) {   *     return 0; @@ -47,10 +79,4 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {   * }   * \endcode   */ -#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body) - -/** - * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be - * used when the caller might want to cancel the ScopeExit. - */ -#define SCOPE_GUARD(body) detail::ScopeExit([&]() body) +#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = SCOPE_GUARD diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index df47033e3..f67a12f8f 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -2,8 +2,8 @@  # SPDX-License-Identifier: GPL-2.0-or-later  add_library(core STATIC -    arm/arm_interface.h      arm/arm_interface.cpp +    arm/arm_interface.h      arm/debug.cpp      arm/debug.h      arm/exclusive_monitor.cpp @@ -37,10 +37,10 @@ add_library(core STATIC      debugger/gdbstub.h      debugger/gdbstub_arch.cpp      debugger/gdbstub_arch.h -    device_memory_manager.h -    device_memory_manager.inc      device_memory.cpp      device_memory.h +    device_memory_manager.h +    device_memory_manager.inc      file_sys/bis_factory.cpp      file_sys/bis_factory.h      file_sys/card_image.cpp @@ -390,6 +390,20 @@ add_library(core STATIC      hle/service/acc/errors.h      hle/service/acc/profile_manager.cpp      hle/service/acc/profile_manager.h +    hle/service/am/am.cpp +    hle/service/am/am.h +    hle/service/am/am_results.h +    hle/service/am/am_types.h +    hle/service/am/applet.cpp +    hle/service/am/applet.h +    hle/service/am/applet_data_broker.cpp +    hle/service/am/applet_data_broker.h +    hle/service/am/applet_manager.cpp +    hle/service/am/applet_manager.h +    hle/service/am/applet_message_queue.cpp +    hle/service/am/applet_message_queue.h +    hle/service/am/display_layer_manager.cpp +    hle/service/am/display_layer_manager.h      hle/service/am/frontend/applet_cabinet.cpp      hle/service/am/frontend/applet_cabinet.h      hle/service/am/frontend/applet_controller.cpp @@ -411,24 +425,10 @@ add_library(core STATIC      hle/service/am/frontend/applet_web_browser_types.h      hle/service/am/frontend/applets.cpp      hle/service/am/frontend/applets.h -    hle/service/am/am.cpp -    hle/service/am/am.h -    hle/service/am/am_results.h -    hle/service/am/am_types.h -    hle/service/am/applet.cpp -    hle/service/am/applet.h -    hle/service/am/applet_manager.cpp -    hle/service/am/applet_data_broker.cpp -    hle/service/am/applet_data_broker.h -    hle/service/am/applet_manager.h -    hle/service/am/applet_message_queue.cpp -    hle/service/am/applet_message_queue.h      hle/service/am/hid_registration.cpp      hle/service/am/hid_registration.h      hle/service/am/library_applet_storage.cpp      hle/service/am/library_applet_storage.h -    hle/service/am/managed_layer_holder.cpp -    hle/service/am/managed_layer_holder.h      hle/service/am/process.cpp      hle/service/am/process.h      hle/service/am/service/all_system_applet_proxies_service.cpp @@ -441,10 +441,10 @@ add_library(core STATIC      hle/service/am/service/application_creator.h      hle/service/am/service/application_functions.cpp      hle/service/am/service/application_functions.h -    hle/service/am/service/application_proxy_service.cpp -    hle/service/am/service/application_proxy_service.h      hle/service/am/service/application_proxy.cpp      hle/service/am/service/application_proxy.h +    hle/service/am/service/application_proxy_service.cpp +    hle/service/am/service/application_proxy_service.h      hle/service/am/service/audio_controller.cpp      hle/service/am/service/audio_controller.h      hle/service/am/service/common_state_getter.cpp @@ -473,16 +473,14 @@ add_library(core STATIC      hle/service/am/service/process_winding_controller.h      hle/service/am/service/self_controller.cpp      hle/service/am/service/self_controller.h -    hle/service/am/service/storage_accessor.cpp -    hle/service/am/service/storage_accessor.h      hle/service/am/service/storage.cpp      hle/service/am/service/storage.h +    hle/service/am/service/storage_accessor.cpp +    hle/service/am/service/storage_accessor.h      hle/service/am/service/system_applet_proxy.cpp      hle/service/am/service/system_applet_proxy.h      hle/service/am/service/window_controller.cpp      hle/service/am/service/window_controller.h -    hle/service/am/system_buffer_manager.cpp -    hle/service/am/system_buffer_manager.h      hle/service/aoc/aoc_u.cpp      hle/service/aoc/aoc_u.h      hle/service/apm/apm.cpp @@ -510,18 +508,6 @@ add_library(core STATIC      hle/service/audio/hwopus.h      hle/service/bcat/backend/backend.cpp      hle/service/bcat/backend/backend.h -    hle/service/bcat/news/newly_arrived_event_holder.cpp -    hle/service/bcat/news/newly_arrived_event_holder.h -    hle/service/bcat/news/news_data_service.cpp -    hle/service/bcat/news/news_data_service.h -    hle/service/bcat/news/news_database_service.cpp -    hle/service/bcat/news/news_database_service.h -    hle/service/bcat/news/news_service.cpp -    hle/service/bcat/news/news_service.h -    hle/service/bcat/news/overwrite_event_holder.cpp -    hle/service/bcat/news/overwrite_event_holder.h -    hle/service/bcat/news/service_creator.cpp -    hle/service/bcat/news/service_creator.h      hle/service/bcat/bcat.cpp      hle/service/bcat/bcat.h      hle/service/bcat/bcat_result.h @@ -537,6 +523,18 @@ add_library(core STATIC      hle/service/bcat/delivery_cache_progress_service.h      hle/service/bcat/delivery_cache_storage_service.cpp      hle/service/bcat/delivery_cache_storage_service.h +    hle/service/bcat/news/newly_arrived_event_holder.cpp +    hle/service/bcat/news/newly_arrived_event_holder.h +    hle/service/bcat/news/news_data_service.cpp +    hle/service/bcat/news/news_data_service.h +    hle/service/bcat/news/news_database_service.cpp +    hle/service/bcat/news/news_database_service.h +    hle/service/bcat/news/news_service.cpp +    hle/service/bcat/news/news_service.h +    hle/service/bcat/news/overwrite_event_holder.cpp +    hle/service/bcat/news/overwrite_event_holder.h +    hle/service/bcat/news/service_creator.cpp +    hle/service/bcat/news/service_creator.h      hle/service/bcat/service_creator.cpp      hle/service/bcat/service_creator.h      hle/service/bpc/bpc.cpp @@ -545,6 +543,16 @@ add_library(core STATIC      hle/service/btdrv/btdrv.h      hle/service/btm/btm.cpp      hle/service/btm/btm.h +    hle/service/btm/btm_debug.cpp +    hle/service/btm/btm_debug.h +    hle/service/btm/btm_system.cpp +    hle/service/btm/btm_system.h +    hle/service/btm/btm_system_core.cpp +    hle/service/btm/btm_system_core.h +    hle/service/btm/btm_user.cpp +    hle/service/btm/btm_user.h +    hle/service/btm/btm_user_core.cpp +    hle/service/btm/btm_user_core.h      hle/service/caps/caps.cpp      hle/service/caps/caps.h      hle/service/caps/caps_a.cpp @@ -600,8 +608,6 @@ add_library(core STATIC      hle/service/filesystem/romfs_controller.h      hle/service/filesystem/save_data_controller.cpp      hle/service/filesystem/save_data_controller.h -    hle/service/fgm/fgm.cpp -    hle/service/fgm/fgm.h      hle/service/friend/friend.cpp      hle/service/friend/friend.h      hle/service/friend/friend_interface.cpp @@ -739,15 +745,48 @@ add_library(core STATIC      hle/service/nim/nim.h      hle/service/npns/npns.cpp      hle/service/npns/npns.h -    hle/service/ns/errors.h -    hle/service/ns/iplatform_service_manager.cpp -    hle/service/ns/iplatform_service_manager.h +    hle/service/ns/account_proxy_interface.cpp +    hle/service/ns/account_proxy_interface.h +    hle/service/ns/application_manager_interface.cpp +    hle/service/ns/application_manager_interface.h +    hle/service/ns/application_version_interface.cpp +    hle/service/ns/application_version_interface.h +    hle/service/ns/content_management_interface.cpp +    hle/service/ns/content_management_interface.h +    hle/service/ns/develop_interface.cpp +    hle/service/ns/develop_interface.h +    hle/service/ns/document_interface.cpp +    hle/service/ns/document_interface.h +    hle/service/ns/download_task_interface.cpp +    hle/service/ns/download_task_interface.h +    hle/service/ns/dynamic_rights_interface.cpp +    hle/service/ns/dynamic_rights_interface.h +    hle/service/ns/ecommerce_interface.cpp +    hle/service/ns/ecommerce_interface.h +    hle/service/ns/factory_reset_interface.cpp +    hle/service/ns/factory_reset_interface.h      hle/service/ns/language.cpp      hle/service/ns/language.h      hle/service/ns/ns.cpp      hle/service/ns/ns.h -    hle/service/ns/pdm_qry.cpp -    hle/service/ns/pdm_qry.h +    hle/service/ns/ns_results.h +    hle/service/ns/ns_types.h +    hle/service/ns/platform_service_manager.cpp +    hle/service/ns/platform_service_manager.h +    hle/service/ns/query_service.cpp +    hle/service/ns/query_service.h +    hle/service/ns/read_only_application_control_data_interface.cpp +    hle/service/ns/read_only_application_control_data_interface.h +    hle/service/ns/read_only_application_record_interface.cpp +    hle/service/ns/read_only_application_record_interface.h +    hle/service/ns/service_getter_interface.cpp +    hle/service/ns/service_getter_interface.h +    hle/service/ns/system_update_control.cpp +    hle/service/ns/system_update_control.h +    hle/service/ns/system_update_interface.cpp +    hle/service/ns/system_update_interface.h +    hle/service/ns/vulnerability_manager_interface.cpp +    hle/service/ns/vulnerability_manager_interface.h      hle/service/nvdrv/core/container.cpp      hle/service/nvdrv/core/container.h      hle/service/nvdrv/core/heap_mapper.cpp @@ -800,14 +839,14 @@ add_library(core STATIC      hle/service/nvnflinger/consumer_base.cpp      hle/service/nvnflinger/consumer_base.h      hle/service/nvnflinger/consumer_listener.h -    hle/service/nvnflinger/fb_share_buffer_manager.cpp -    hle/service/nvnflinger/fb_share_buffer_manager.h      hle/service/nvnflinger/graphic_buffer_producer.cpp      hle/service/nvnflinger/graphic_buffer_producer.h -    hle/service/nvnflinger/hos_binder_driver_server.cpp -    hle/service/nvnflinger/hos_binder_driver_server.h      hle/service/nvnflinger/hardware_composer.cpp      hle/service/nvnflinger/hardware_composer.h +    hle/service/nvnflinger/hos_binder_driver.cpp +    hle/service/nvnflinger/hos_binder_driver.h +    hle/service/nvnflinger/hos_binder_driver_server.cpp +    hle/service/nvnflinger/hos_binder_driver_server.h      hle/service/nvnflinger/hwc_layer.h      hle/service/nvnflinger/nvnflinger.cpp      hle/service/nvnflinger/nvnflinger.h @@ -815,6 +854,8 @@ add_library(core STATIC      hle/service/nvnflinger/pixel_format.h      hle/service/nvnflinger/producer_listener.h      hle/service/nvnflinger/status.h +    hle/service/nvnflinger/surface_flinger.cpp +    hle/service/nvnflinger/surface_flinger.h      hle/service/nvnflinger/ui/fence.h      hle/service/nvnflinger/ui/graphic_buffer.cpp      hle/service/nvnflinger/ui/graphic_buffer.h @@ -831,11 +872,11 @@ add_library(core STATIC      hle/service/omm/power_state_interface.h      hle/service/os/event.cpp      hle/service/os/event.h +    hle/service/os/multi_wait.cpp +    hle/service/os/multi_wait.h      hle/service/os/multi_wait_holder.cpp      hle/service/os/multi_wait_holder.h      hle/service/os/multi_wait_utils.h -    hle/service/os/multi_wait.cpp -    hle/service/os/multi_wait.h      hle/service/os/mutex.cpp      hle/service/os/mutex.h      hle/service/pcie/pcie.cpp @@ -873,15 +914,17 @@ add_library(core STATIC      hle/service/psc/time/common.cpp      hle/service/psc/time/common.h      hle/service/psc/time/errors.h -    hle/service/psc/time/shared_memory.cpp -    hle/service/psc/time/shared_memory.h -    hle/service/psc/time/static.cpp -    hle/service/psc/time/static.h      hle/service/psc/time/manager.h +    hle/service/psc/time/power_state_request_manager.cpp +    hle/service/psc/time/power_state_request_manager.h      hle/service/psc/time/power_state_service.cpp      hle/service/psc/time/power_state_service.h      hle/service/psc/time/service_manager.cpp      hle/service/psc/time/service_manager.h +    hle/service/psc/time/shared_memory.cpp +    hle/service/psc/time/shared_memory.h +    hle/service/psc/time/static.cpp +    hle/service/psc/time/static.h      hle/service/psc/time/steady_clock.cpp      hle/service/psc/time/steady_clock.h      hle/service/psc/time/system_clock.cpp @@ -890,8 +933,6 @@ add_library(core STATIC      hle/service/psc/time/time_zone.h      hle/service/psc/time/time_zone_service.cpp      hle/service/psc/time/time_zone_service.h -    hle/service/psc/time/power_state_request_manager.cpp -    hle/service/psc/time/power_state_request_manager.h      hle/service/ptm/psm.cpp      hle/service/ptm/psm.h      hle/service/ptm/ptm.cpp @@ -908,19 +949,21 @@ add_library(core STATIC      hle/service/server_manager.h      hle/service/service.cpp      hle/service/service.h +    hle/service/services.cpp +    hle/service/services.h +    hle/service/set/factory_settings_server.cpp +    hle/service/set/factory_settings_server.h +    hle/service/set/firmware_debug_settings_server.cpp +    hle/service/set/firmware_debug_settings_server.h +    hle/service/set/key_code_map.h      hle/service/set/setting_formats/appln_settings.cpp      hle/service/set/setting_formats/appln_settings.h      hle/service/set/setting_formats/device_settings.cpp      hle/service/set/setting_formats/device_settings.h -    hle/service/set/setting_formats/system_settings.cpp -    hle/service/set/setting_formats/system_settings.h      hle/service/set/setting_formats/private_settings.cpp      hle/service/set/setting_formats/private_settings.h -    hle/service/set/factory_settings_server.cpp -    hle/service/set/factory_settings_server.h -    hle/service/set/firmware_debug_settings_server.cpp -    hle/service/set/firmware_debug_settings_server.h -    hle/service/set/key_code_map.h +    hle/service/set/setting_formats/system_settings.cpp +    hle/service/set/setting_formats/system_settings.h      hle/service/set/settings.cpp      hle/service/set/settings.h      hle/service/set/settings_server.cpp @@ -955,30 +998,36 @@ add_library(core STATIC      hle/service/ssl/ssl_backend.h      hle/service/usb/usb.cpp      hle/service/usb/usb.h -    hle/service/vi/display/vi_display.cpp -    hle/service/vi/display/vi_display.h -    hle/service/vi/layer/vi_layer.cpp -    hle/service/vi/layer/vi_layer.h      hle/service/vi/application_display_service.cpp      hle/service/vi/application_display_service.h      hle/service/vi/application_root_service.cpp      hle/service/vi/application_root_service.h -    hle/service/vi/hos_binder_driver.cpp -    hle/service/vi/hos_binder_driver.h +    hle/service/vi/conductor.cpp +    hle/service/vi/conductor.h +    hle/service/vi/container.cpp +    hle/service/vi/container.h +    hle/service/vi/display.h +    hle/service/vi/display_list.h +    hle/service/vi/layer.h +    hle/service/vi/layer_list.h      hle/service/vi/manager_display_service.cpp      hle/service/vi/manager_display_service.h      hle/service/vi/manager_root_service.cpp      hle/service/vi/manager_root_service.h      hle/service/vi/service_creator.cpp      hle/service/vi/service_creator.h +    hle/service/vi/shared_buffer_manager.cpp +    hle/service/vi/shared_buffer_manager.h      hle/service/vi/system_display_service.cpp      hle/service/vi/system_display_service.h      hle/service/vi/system_root_service.cpp      hle/service/vi/system_root_service.h -    hle/service/vi/vi_results.h -    hle/service/vi/vi_types.h      hle/service/vi/vi.cpp      hle/service/vi/vi.h +    hle/service/vi/vi_results.h +    hle/service/vi/vi_types.h +    hle/service/vi/vsync_manager.cpp +    hle/service/vi/vsync_manager.h      internal_network/network.cpp      internal_network/network.h      internal_network/network_interface.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index bd5f11d53..9e8936728 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -47,6 +47,7 @@  #include "core/hle/service/psc/time/system_clock.h"  #include "core/hle/service/psc/time/time_zone_service.h"  #include "core/hle/service/service.h" +#include "core/hle/service/services.h"  #include "core/hle/service/set/system_settings_server.h"  #include "core/hle/service/sm/sm.h"  #include "core/internal_network/network.h" @@ -310,7 +311,8 @@ struct System::Impl {          audio_core = std::make_unique<AudioCore::AudioCore>(system);          service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); -        services = std::make_unique<Service::Services>(service_manager, system); +        services = +            std::make_unique<Service::Services>(service_manager, system, stop_event.get_token());          is_powered_on = true;          exit_locked = false; @@ -458,11 +460,10 @@ struct System::Impl {              gpu_core->NotifyShutdown();          } +        stop_event.request_stop(); +        core_timing.SyncPause(false);          Network::CancelPendingSocketOperations();          kernel.SuspendEmulation(true); -        if (services) { -            services->KillNVNFlinger(); -        }          kernel.CloseServices();          kernel.ShutdownCores();          applet_manager.Reset(); @@ -480,6 +481,7 @@ struct System::Impl {          cpu_manager.Shutdown();          debugger.reset();          kernel.Shutdown(); +        stop_event = {};          Network::RestartSocketOperations();          if (auto room_member = room_network.GetRoomMember().lock()) { @@ -615,6 +617,7 @@ struct System::Impl {      ExecuteProgramCallback execute_program_callback;      ExitCallback exit_callback; +    std::stop_source stop_event;      std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};      std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 7a5c22f78..9b1c77387 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -199,10 +199,10 @@ void CpuManager::RunThread(std::stop_token token, std::size_t core) {      data.host_context = Common::Fiber::ThreadToFiber();      // Cleanup -    SCOPE_EXIT({ +    SCOPE_EXIT {          data.host_context->Exit();          MicroProfileOnThreadExit(); -    }); +    };      // Running      if (!gpu_barrier->Sync(token)) { diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc index 6dfee806c..37c1e69c3 100644 --- a/src/core/device_memory_manager.inc +++ b/src/core/device_memory_manager.inc @@ -391,12 +391,12 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o              std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);          const auto current_vaddr =              static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset); -        SCOPE_EXIT({ +        SCOPE_EXIT{              page_index += next_pages;              page_offset = 0;              increment(copy_amount);              remaining_size -= copy_amount; -        }); +        };          auto phys_addr = compressed_physical_ptr[page_index];          if (phys_addr == 0) { diff --git a/src/core/file_sys/fs_directory.h b/src/core/file_sys/fs_directory.h index 25c9cb18a..3f90abb8f 100644 --- a/src/core/file_sys/fs_directory.h +++ b/src/core/file_sys/fs_directory.h @@ -3,6 +3,10 @@  #pragma once +#include <string_view> +#include "common/common_funcs.h" +#include "common/common_types.h" +  namespace FileSys {  constexpr inline size_t EntryNameLengthMax = 0x300; diff --git a/src/core/file_sys/fs_path_utility.h b/src/core/file_sys/fs_path_utility.h index e9011d065..5643141f9 100644 --- a/src/core/file_sys/fs_path_utility.h +++ b/src/core/file_sys/fs_path_utility.h @@ -447,7 +447,7 @@ public:          char* replacement_path = nullptr;          size_t replacement_path_size = 0; -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (replacement_path != nullptr) {                  if (std::is_constant_evaluated()) {                      delete[] replacement_path; @@ -455,7 +455,7 @@ public:                      Deallocate(replacement_path, replacement_path_size);                  }              } -        }); +        };          // Perform path replacement, if necessary          if (IsParentDirectoryPathReplacementNeeded(cur_path)) { @@ -1102,8 +1102,8 @@ public:          R_SUCCEED();      } -    static Result Normalize(char* dst, size_t dst_size, const char* path, size_t path_len, -                            const PathFlags& flags) { +    static constexpr Result Normalize(char* dst, size_t dst_size, const char* path, size_t path_len, +                                      const PathFlags& flags) {          // Use StringTraits names for remainder of scope          using namespace StringTraits; @@ -1199,7 +1199,7 @@ public:              const size_t replaced_src_len = path_len - (src - path);              char* replaced_src = nullptr; -            SCOPE_EXIT({ +            SCOPE_EXIT {                  if (replaced_src != nullptr) {                      if (std::is_constant_evaluated()) {                          delete[] replaced_src; @@ -1207,7 +1207,7 @@ public:                          Deallocate(replaced_src, replaced_src_len);                      }                  } -            }); +            };              if (std::is_constant_evaluated()) {                  replaced_src = new char[replaced_src_len]; diff --git a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h index f342efb57..0e83ca1b9 100644 --- a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h +++ b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h @@ -3,6 +3,7 @@  #pragma once +#include <mutex>  #include <optional>  #include "core/crypto/aes_util.h" diff --git a/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp b/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp index caea0b8f8..a68fd973c 100644 --- a/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp +++ b/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp @@ -36,7 +36,9 @@ Result HierarchicalSha256Storage::Initialize(VirtualFile* base_storages, s32 lay      // Get the base storage size.      m_base_storage_size = base_storages[2]->GetSize();      { -        auto size_guard = SCOPE_GUARD({ m_base_storage_size = 0; }); +        auto size_guard = SCOPE_GUARD { +            m_base_storage_size = 0; +        };          R_UNLESS(m_base_storage_size <= static_cast<s64>(HashSize)                                              << m_log_size_ratio << m_log_size_ratio,                   ResultHierarchicalSha256BaseStorageTooLarge); diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp index ae4e441c9..289969cc4 100644 --- a/src/core/file_sys/program_metadata.cpp +++ b/src/core/file_sys/program_metadata.cpp @@ -98,7 +98,9 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {  Loader::ResultStatus ProgramMetadata::Reload(VirtualFile file) {      const u64 original_program_id = aci_header.title_id; -    SCOPE_EXIT({ aci_header.title_id = original_program_id; }); +    SCOPE_EXIT { +        aci_header.title_id = original_program_id; +    };      return this->Load(file);  } diff --git a/src/core/file_sys/system_archive/shared_font.cpp b/src/core/file_sys/system_archive/shared_font.cpp index deb52069d..9ea16aa59 100644 --- a/src/core/file_sys/system_archive/shared_font.cpp +++ b/src/core/file_sys/system_archive/shared_font.cpp @@ -9,7 +9,7 @@  #include "core/file_sys/system_archive/data/font_standard.h"  #include "core/file_sys/system_archive/shared_font.h"  #include "core/file_sys/vfs/vfs_vector.h" -#include "core/hle/service/ns/iplatform_service_manager.h" +#include "core/hle/service/ns/platform_service_manager.h"  namespace FileSys::SystemArchive { diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp index 472e8571c..3e01e3b67 100644 --- a/src/core/hle/kernel/k_client_session.cpp +++ b/src/core/hle/kernel/k_client_session.cpp @@ -24,7 +24,9 @@ Result KClientSession::SendSyncRequest(uintptr_t address, size_t size) {      // Create a session request.      KSessionRequest* request = KSessionRequest::Create(m_kernel);      R_UNLESS(request != nullptr, ResultOutOfResource); -    SCOPE_EXIT({ request->Close(); }); +    SCOPE_EXIT { +        request->Close(); +    };      // Initialize the request.      request->Initialize(nullptr, address, size); @@ -37,7 +39,9 @@ Result KClientSession::SendAsyncRequest(KEvent* event, uintptr_t address, size_t      // Create a session request.      KSessionRequest* request = KSessionRequest::Create(m_kernel);      R_UNLESS(request != nullptr, ResultOutOfResource); -    SCOPE_EXIT({ request->Close(); }); +    SCOPE_EXIT { +        request->Close(); +    };      // Initialize the request.      request->Initialize(event, address, size); diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 1dd86fb3c..19cdf4f3a 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -1305,11 +1305,11 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr      // Ensure that we maintain the instruction cache.      bool reprotected_pages = false; -    SCOPE_EXIT({ +    SCOPE_EXIT {          if (reprotected_pages && any_code_pages) {              InvalidateInstructionCache(m_kernel, this, dst_address, size);          } -    }); +    };      // Unmap.      { @@ -1397,7 +1397,9 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {      // Close the opened pages when we're done with them.      // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed      // automatically. -    SCOPE_EXIT({ pg.Close(); }); +    SCOPE_EXIT { +        pg.Close(); +    };      // Clear all the newly allocated pages.      for (const auto& it : pg) { @@ -1603,7 +1605,9 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce          m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option));      // Ensure that the page group is closed when we're done working with it. -    SCOPE_EXIT({ pg.Close(); }); +    SCOPE_EXIT { +        pg.Close(); +    };      // Clear all pages.      for (const auto& it : pg) { @@ -2191,7 +2195,9 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) {      // Close the opened pages when we're done with them.      // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed      // automatically. -    SCOPE_EXIT({ pg.Close(); }); +    SCOPE_EXIT { +        pg.Close(); +    };      // Clear all the newly allocated pages.      for (const auto& it : pg) { @@ -2592,7 +2598,9 @@ Result KPageTableBase::UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddre          // Temporarily unlock ourselves, so that other operations can occur while we flush the          // region.          m_general_lock.Unlock(); -        SCOPE_EXIT({ m_general_lock.Lock(); }); +        SCOPE_EXIT { +            m_general_lock.Lock(); +        };          // Flush the region.          R_ASSERT(FlushDataCache(dst_address, size)); @@ -3311,10 +3319,10 @@ Result KPageTableBase::ReadIoMemoryImpl(KProcessAddress dst_addr, KPhysicalAddre      // Ensure we unmap the io memory when we're done with it.      const KPageProperties unmap_properties =          KPageProperties{KMemoryPermission::None, false, false, DisableMergeAttribute::None}; -    SCOPE_EXIT({ +    SCOPE_EXIT {          R_ASSERT(this->Operate(updater.GetPageList(), io_addr, map_size / PageSize, 0, false,                                 unmap_properties, OperationType::Unmap, true)); -    }); +    };      // Read the memory.      const KProcessAddress read_addr = io_addr + (GetInteger(phys_addr) & (PageSize - 1)); @@ -3347,10 +3355,10 @@ Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, KProcessAdd      // Ensure we unmap the io memory when we're done with it.      const KPageProperties unmap_properties =          KPageProperties{KMemoryPermission::None, false, false, DisableMergeAttribute::None}; -    SCOPE_EXIT({ +    SCOPE_EXIT {          R_ASSERT(this->Operate(updater.GetPageList(), io_addr, map_size / PageSize, 0, false,                                 unmap_properties, OperationType::Unmap, true)); -    }); +    };      // Write the memory.      const KProcessAddress write_addr = io_addr + (GetInteger(phys_addr) & (PageSize - 1)); @@ -4491,14 +4499,14 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,      // If the partial pages are mapped, an extra reference will have been opened. Otherwise, they'll      // free on scope exit. -    SCOPE_EXIT({ +    SCOPE_EXIT {          if (start_partial_page != 0) {              m_kernel.MemoryManager().Close(start_partial_page, 1);          }          if (end_partial_page != 0) {              m_kernel.MemoryManager().Close(end_partial_page, 1);          } -    }); +    };      ON_RESULT_FAILURE {          if (cur_mapped_addr != dst_addr) { @@ -5166,10 +5174,10 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {                  GetCurrentProcess(m_kernel).GetId(), m_heap_fill_value));              // If we fail in the next bit (or retry), we need to cleanup the pages. -            auto pg_guard = SCOPE_GUARD({ +            auto pg_guard = SCOPE_GUARD {                  pg.OpenFirst();                  pg.Close(); -            }); +            };              // Map the memory.              { @@ -5694,7 +5702,9 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a          // Ensure that any pages we track are closed on exit.          KPageGroup pages_to_close(m_kernel, this->GetBlockInfoManager()); -        SCOPE_EXIT({ pages_to_close.CloseAndReset(); }); +        SCOPE_EXIT { +            pages_to_close.CloseAndReset(); +        };          // Make a page group representing the region to unmap.          this->MakePageGroup(pages_to_close, virt_addr, num_pages); diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 1bcc42890..cb9a11a63 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -77,7 +77,9 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process,          }          // Terminate and close the thread. -        SCOPE_EXIT({ cur_child->Close(); }); +        SCOPE_EXIT { +            cur_child->Close(); +        };          if (const Result terminate_result = cur_child->Terminate();              ResultTerminationRequested == terminate_result) { @@ -466,11 +468,11 @@ void KProcess::DoWorkerTaskImpl() {  Result KProcess::StartTermination() {      // Finalize the handle table when we're done, if the process isn't immortal. -    SCOPE_EXIT({ +    SCOPE_EXIT {          if (!m_is_immortal) {              this->FinalizeHandleTable();          } -    }); +    };      // Terminate child threads other than the current one.      R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel))); @@ -964,7 +966,9 @@ Result KProcess::Run(s32 priority, size_t stack_size) {      // Create a new thread for the process.      KThread* main_thread = KThread::Create(m_kernel);      R_UNLESS(main_thread != nullptr, ResultOutOfResource); -    SCOPE_EXIT({ main_thread->Close(); }); +    SCOPE_EXIT { +        main_thread->Close(); +    };      // Initialize the thread.      R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0, @@ -1155,7 +1159,9 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:          Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size);      // Ensure we maintain a clean state on exit. -    SCOPE_EXIT({ res_limit->Close(); }); +    SCOPE_EXIT { +        res_limit->Close(); +    };      // Declare flags and code address.      Svc::CreateProcessFlag flag{}; diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index adaabdd6d..40c3323ef 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -651,11 +651,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m      // Process any special data.      if (src_header.GetHasSpecialHeader()) {          // After we process, make sure we track whether the receive list is broken. -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (offset > dst_recv_list_idx) {                  recv_list_broken = true;              } -        }); +        };          // Process special data.          R_TRY(ProcessMessageSpecialData<false>(offset, dst_process, src_process, src_thread, @@ -665,11 +665,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m      // Process any pointer buffers.      for (auto i = 0; i < src_header.GetPointerCount(); ++i) {          // After we process, make sure we track whether the receive list is broken. -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (offset > dst_recv_list_idx) {                  recv_list_broken = true;              } -        }); +        };          R_TRY(ProcessReceiveMessagePointerDescriptors(              offset, pointer_key, dst_page_table, src_page_table, dst_msg, src_msg, dst_recv_list, @@ -680,11 +680,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m      // Process any map alias buffers.      for (auto i = 0; i < src_header.GetMapAliasCount(); ++i) {          // After we process, make sure we track whether the receive list is broken. -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (offset > dst_recv_list_idx) {                  recv_list_broken = true;              } -        }); +        };          // We process in order send, recv, exch. Buffers after send (recv/exch) are ReadWrite.          const KMemoryPermission perm = (i >= src_header.GetSendCount()) @@ -702,11 +702,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m      // Process any raw data.      if (const auto raw_count = src_header.GetRawCount(); raw_count != 0) {          // After we process, make sure we track whether the receive list is broken. -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (offset + raw_count > dst_recv_list_idx) {                  recv_list_broken = true;              } -        }); +        };          // Get the offset and size.          const size_t offset_words = offset * sizeof(u32); @@ -1124,7 +1124,9 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server          client_thread->Open();      } -    SCOPE_EXIT({ client_thread->Close(); }); +    SCOPE_EXIT { +        client_thread->Close(); +    };      // Set the request as our current.      m_current_request = request; @@ -1174,7 +1176,9 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server          // Reply to the client.          {              // After we reply, close our reference to the request. -            SCOPE_EXIT({ request->Close(); }); +            SCOPE_EXIT { +                request->Close(); +            };              // Get the event to check whether the request is async.              if (KEvent* event = request->GetEvent(); event != nullptr) { @@ -1236,7 +1240,9 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff      }      // Close reference to the request once we're done processing it. -    SCOPE_EXIT({ request->Close(); }); +    SCOPE_EXIT { +        request->Close(); +    };      // Extract relevant information from the request.      const uint64_t client_message = request->GetAddress(); @@ -1394,7 +1400,9 @@ void KServerSession::CleanupRequests() {          }          // Close a reference to the request once it's cleaned up. -        SCOPE_EXIT({ request->Close(); }); +        SCOPE_EXIT { +            request->Close(); +        };          // Extract relevant information from the request.          const uint64_t client_message = request->GetAddress(); @@ -1491,7 +1499,9 @@ void KServerSession::OnClientClosed() {          ASSERT(thread != nullptr);          // Ensure that we close the request when done. -        SCOPE_EXIT({ request->Close(); }); +        SCOPE_EXIT { +            request->Close(); +        };          // If we're terminating, close a reference to the thread and event.          if (terminate) { diff --git a/src/core/hle/kernel/k_thread_local_page.cpp b/src/core/hle/kernel/k_thread_local_page.cpp index a632d1634..1952c0083 100644 --- a/src/core/hle/kernel/k_thread_local_page.cpp +++ b/src/core/hle/kernel/k_thread_local_page.cpp @@ -21,7 +21,9 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {      // Allocate a new page.      KPageBuffer* page_buf = KPageBuffer::Allocate(kernel);      R_UNLESS(page_buf != nullptr, ResultOutOfMemory); -    auto page_buf_guard = SCOPE_GUARD({ KPageBuffer::Free(kernel, page_buf); }); +    auto page_buf_guard = SCOPE_GUARD { +        KPageBuffer::Free(kernel, page_buf); +    };      // Map the address in.      const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf); diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp index cbb1b02bb..09295e8ad 100644 --- a/src/core/hle/kernel/k_transfer_memory.cpp +++ b/src/core/hle/kernel/k_transfer_memory.cpp @@ -24,7 +24,9 @@ Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size,      // Construct the page group, guarding to make sure our state is valid on exit.      m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); -    auto pg_guard = SCOPE_GUARD({ m_page_group.reset(); }); +    auto pg_guard = SCOPE_GUARD { +        m_page_group.reset(); +    };      // Lock the memory.      R_TRY(page_table.LockForTransferMemory(std::addressof(*m_page_group), addr, size, diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 4f4b02fac..9e5eaeec4 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -109,7 +109,9 @@ struct KernelCore::Impl {      void Shutdown() {          is_shutting_down.store(true, std::memory_order_relaxed); -        SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); }); +        SCOPE_EXIT { +            is_shutting_down.store(false, std::memory_order_relaxed); +        };          CloseServices(); @@ -1080,7 +1082,9 @@ std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name,          process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false)));      // Ensure that we don't hold onto any extra references. -    SCOPE_EXIT({ process->Close(); }); +    SCOPE_EXIT { +        process->Close(); +    };      // Register the new process.      KProcess::Register(*this, process); @@ -1108,7 +1112,9 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function          process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false)));      // Ensure that we don't hold onto any extra references. -    SCOPE_EXIT({ process->Close(); }); +    SCOPE_EXIT { +        process->Close(); +    };      // Register the new process.      KProcess::Register(*this, process); diff --git a/src/core/hle/kernel/svc/svc_code_memory.cpp b/src/core/hle/kernel/svc/svc_code_memory.cpp index bae4cb0cd..7be2802f0 100644 --- a/src/core/hle/kernel/svc/svc_code_memory.cpp +++ b/src/core/hle/kernel/svc/svc_code_memory.cpp @@ -45,7 +45,9 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t      KCodeMemory* code_mem = KCodeMemory::Create(kernel);      R_UNLESS(code_mem != nullptr, ResultOutOfResource); -    SCOPE_EXIT({ code_mem->Close(); }); +    SCOPE_EXIT { +        code_mem->Close(); +    };      // Verify that the region is in range.      R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size), diff --git a/src/core/hle/kernel/svc/svc_device_address_space.cpp b/src/core/hle/kernel/svc/svc_device_address_space.cpp index 42add9473..ac828320f 100644 --- a/src/core/hle/kernel/svc/svc_device_address_space.cpp +++ b/src/core/hle/kernel/svc/svc_device_address_space.cpp @@ -28,7 +28,9 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_      // Create the device address space.      KDeviceAddressSpace* das = KDeviceAddressSpace::Create(system.Kernel());      R_UNLESS(das != nullptr, ResultOutOfResource); -    SCOPE_EXIT({ das->Close(); }); +    SCOPE_EXIT { +        das->Close(); +    };      // Initialize the device address space.      R_TRY(das->Initialize(das_address, das_size)); diff --git a/src/core/hle/kernel/svc/svc_event.cpp b/src/core/hle/kernel/svc/svc_event.cpp index 901202e6a..8e4beb396 100644 --- a/src/core/hle/kernel/svc/svc_event.cpp +++ b/src/core/hle/kernel/svc/svc_event.cpp @@ -72,10 +72,10 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {      event_reservation.Commit();      // Ensure that we clean up the event (and its only references are handle table) on function end. -    SCOPE_EXIT({ +    SCOPE_EXIT {          event->GetReadableEvent().Close();          event->Close(); -    }); +    };      // Register the event.      KEvent::Register(kernel, event); diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index 85cc4f561..b619bd70a 100644 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp @@ -129,11 +129,11 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes      }      // Ensure handles are closed when we're done. -    SCOPE_EXIT({ +    SCOPE_EXIT {          for (auto i = 0; i < num_handles; ++i) {              objs[i]->Close();          } -    }); +    };      R_RETURN(ReplyAndReceiveImpl(kernel, out_index, message, buffer_size, message_paddr, objs,                                   num_handles, reply_target, timeout_ns)); @@ -208,10 +208,10 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha      event_reservation.Commit();      // At end of scope, kill the standing references to the sub events. -    SCOPE_EXIT({ +    SCOPE_EXIT {          event->GetReadableEvent().Close();          event->Close(); -    }); +    };      // Register the event.      KEvent::Register(system.Kernel(), event); diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp index 737749f7d..9a22dadaf 100644 --- a/src/core/hle/kernel/svc/svc_port.cpp +++ b/src/core/hle/kernel/svc/svc_port.cpp @@ -68,10 +68,10 @@ Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,      port->Initialize(max_sessions, is_light, name);      // Ensure that we clean up the port (and its only references are handle table) on function end. -    SCOPE_EXIT({ +    SCOPE_EXIT {          port->GetServerPort().Close();          port->GetClientPort().Close(); -    }); +    };      // Register the port.      KPort::Register(kernel, port); @@ -150,10 +150,10 @@ Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t          KPort::Register(system.Kernel(), port);          // Ensure that our only reference to the port is in the handle table when we're done. -        SCOPE_EXIT({ +        SCOPE_EXIT {              port->GetClientPort().Close();              port->GetServerPort().Close(); -        }); +        };          // Register the handle in the table.          R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort()))); diff --git a/src/core/hle/kernel/svc/svc_resource_limit.cpp b/src/core/hle/kernel/svc/svc_resource_limit.cpp index c8e820b6a..6f3972482 100644 --- a/src/core/hle/kernel/svc/svc_resource_limit.cpp +++ b/src/core/hle/kernel/svc/svc_resource_limit.cpp @@ -18,7 +18,9 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {      R_UNLESS(resource_limit != nullptr, ResultOutOfResource);      // Ensure we don't leak a reference to the limit. -    SCOPE_EXIT({ resource_limit->Close(); }); +    SCOPE_EXIT { +        resource_limit->Close(); +    };      // Initialize the resource limit.      resource_limit->Initialize(); diff --git a/src/core/hle/kernel/svc/svc_session.cpp b/src/core/hle/kernel/svc/svc_session.cpp index 2f5905f32..b034d21d1 100644 --- a/src/core/hle/kernel/svc/svc_session.cpp +++ b/src/core/hle/kernel/svc/svc_session.cpp @@ -69,10 +69,10 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien      // Ensure that we clean up the session (and its only references are handle table) on function      // end. -    SCOPE_EXIT({ +    SCOPE_EXIT {          session->GetClientSession().Close();          session->GetServerSession().Close(); -    }); +    };      // Register the session.      T::Register(system.Kernel(), session); diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index 6c79cfd8d..fb03908d7 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -78,11 +78,11 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha      }      // Ensure handles are closed when we're done. -    SCOPE_EXIT({ +    SCOPE_EXIT {          for (auto i = 0; i < num_handles; ++i) {              objs[i]->Close();          } -    }); +    };      // Convert the timeout from nanoseconds to ticks.      s64 timeout; diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 7681afa33..7517bb9d3 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -51,7 +51,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u      // Create the thread.      KThread* thread = KThread::Create(kernel);      R_UNLESS(thread != nullptr, ResultOutOfResource) -    SCOPE_EXIT({ thread->Close(); }); +    SCOPE_EXIT { +        thread->Close(); +    };      // Initialize the thread.      { diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp index 671bca23f..2ea0d4421 100644 --- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp +++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp @@ -52,7 +52,9 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64      R_UNLESS(trmem != nullptr, ResultOutOfResource);      // Ensure the only reference is in the handle table when we're done. -    SCOPE_EXIT({ trmem->Close(); }); +    SCOPE_EXIT { +        trmem->Close(); +    };      // Ensure that the region is in range.      R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 9dc710ba9..8c4e14f08 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -8,13 +8,13 @@  namespace Service::AM { -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { +void LoopProcess(Core::System& system) {      auto server_manager = std::make_unique<ServerManager>(system); -    server_manager->RegisterNamedService( -        "appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, nvnflinger)); -    server_manager->RegisterNamedService( -        "appletOE", std::make_shared<IApplicationProxyService>(system, nvnflinger)); +    server_manager->RegisterNamedService("appletAE", +                                         std::make_shared<IAllSystemAppletProxiesService>(system)); +    server_manager->RegisterNamedService("appletOE", +                                         std::make_shared<IApplicationProxyService>(system));      ServerManager::RunServer(std::move(server_manager));  } diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 4a2d797bd..1afe253ae 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -7,12 +7,8 @@ namespace Core {  class System;  } -namespace Service::Nvnflinger { -class Nvnflinger; -} -  namespace Service::AM { -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); +void LoopProcess(Core::System& system);  } // namespace Service::AM diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h index 4f34d4811..ad602153e 100644 --- a/src/core/hle/service/am/applet.h +++ b/src/core/hle/service/am/applet.h @@ -14,10 +14,9 @@  #include "core/hle/service/am/am_types.h"  #include "core/hle/service/am/applet_message_queue.h" +#include "core/hle/service/am/display_layer_manager.h"  #include "core/hle/service/am/hid_registration.h" -#include "core/hle/service/am/managed_layer_holder.h"  #include "core/hle/service/am/process.h" -#include "core/hle/service/am/system_buffer_manager.h"  namespace Service::AM { @@ -54,8 +53,7 @@ struct Applet {      HidRegistration hid_registration;      // vi state -    SystemBufferManager system_buffer_manager{}; -    ManagedLayerHolder managed_layer_holder{}; +    DisplayLayerManager display_layer_manager{};      // Applet common functions      Result terminate_result{}; diff --git a/src/core/hle/service/am/applet_data_broker.cpp b/src/core/hle/service/am/applet_data_broker.cpp index 4d58c4db5..9057244a9 100644 --- a/src/core/hle/service/am/applet_data_broker.cpp +++ b/src/core/hle/service/am/applet_data_broker.cpp @@ -24,11 +24,11 @@ void AppletStorageChannel::Push(std::shared_ptr<IStorage> storage) {  Result AppletStorageChannel::Pop(std::shared_ptr<IStorage>* out_storage) {      std::scoped_lock lk{m_lock}; -    SCOPE_EXIT({ +    SCOPE_EXIT {          if (m_data.empty()) {              m_event.Clear();          } -    }); +    };      R_UNLESS(!m_data.empty(), AM::ResultNoDataInChannel); diff --git a/src/core/hle/service/am/display_layer_manager.cpp b/src/core/hle/service/am/display_layer_manager.cpp new file mode 100644 index 000000000..85ff6fb88 --- /dev/null +++ b/src/core/hle/service/am/display_layer_manager.cpp @@ -0,0 +1,151 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/am/display_layer_manager.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/manager_display_service.h" +#include "core/hle/service/vi/manager_root_service.h" +#include "core/hle/service/vi/shared_buffer_manager.h" +#include "core/hle/service/vi/vi_results.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::AM { + +DisplayLayerManager::DisplayLayerManager() = default; +DisplayLayerManager::~DisplayLayerManager() { +    this->Finalize(); +} + +void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* process, +                                     AppletId applet_id, LibraryAppletMode mode) { +    R_ASSERT(system.ServiceManager() +                 .GetService<VI::IManagerRootService>("vi:m", true) +                 ->GetDisplayService(&m_display_service, VI::Policy::Compositor)); +    R_ASSERT(m_display_service->GetManagerDisplayService(&m_manager_display_service)); + +    m_process = process; +    m_system_shared_buffer_id = 0; +    m_system_shared_layer_id = 0; +    m_applet_id = applet_id; +    m_buffer_sharing_enabled = false; +    m_blending_enabled = mode == LibraryAppletMode::PartialForeground || +                         mode == LibraryAppletMode::PartialForegroundIndirectDisplay; +} + +void DisplayLayerManager::Finalize() { +    if (!m_manager_display_service) { +        return; +    } + +    // Clean up managed layers. +    for (const auto& layer : m_managed_display_layers) { +        m_manager_display_service->DestroyManagedLayer(layer); +    } + +    for (const auto& layer : m_managed_display_recording_layers) { +        m_manager_display_service->DestroyManagedLayer(layer); +    } + +    // Clean up shared layers. +    if (m_buffer_sharing_enabled) { +        m_manager_display_service->DestroySharedLayerSession(m_process); +    } + +    m_manager_display_service = nullptr; +    m_display_service = nullptr; +} + +Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) { +    R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); + +    // TODO(Subv): Find out how AM determines the display to use, for now just +    // create the layer in the Default display. +    u64 display_id; +    R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"})); +    R_TRY(m_manager_display_service->CreateManagedLayer( +        out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()})); + +    m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id); +    m_managed_display_layers.emplace(*out_layer_id); + +    R_SUCCEED(); +} + +Result DisplayLayerManager::CreateManagedDisplaySeparableLayer(u64* out_layer_id, +                                                               u64* out_recording_layer_id) { +    R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); + +    // TODO(Subv): Find out how AM determines the display to use, for now just +    // create the layer in the Default display. +    // This calls nn::vi::CreateRecordingLayer() which creates another layer. +    // Currently we do not support more than 1 layer per display, output 1 layer id for now. +    // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse +    // side effects. +    *out_recording_layer_id = 0; +    R_RETURN(this->CreateManagedDisplayLayer(out_layer_id)); +} + +Result DisplayLayerManager::IsSystemBufferSharingEnabled() { +    // Succeed if already enabled. +    R_SUCCEED_IF(m_buffer_sharing_enabled); + +    // Ensure we can access shared layers. +    R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); +    R_UNLESS(m_applet_id != AppletId::Application, VI::ResultPermissionDenied); + +    // Create the shared layer. +    u64 display_id; +    R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"})); +    R_TRY(m_manager_display_service->CreateSharedLayerSession(m_process, &m_system_shared_buffer_id, +                                                              &m_system_shared_layer_id, display_id, +                                                              m_blending_enabled)); + +    // We succeeded, so set up remaining state. +    m_buffer_sharing_enabled = true; +    m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); +    R_SUCCEED(); +} + +Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, +                                                       u64* out_system_shared_layer_id) { +    R_TRY(this->IsSystemBufferSharingEnabled()); + +    *out_system_shared_buffer_id = m_system_shared_buffer_id; +    *out_system_shared_layer_id = m_system_shared_layer_id; + +    R_SUCCEED(); +} + +void DisplayLayerManager::SetWindowVisibility(bool visible) { +    if (m_visible == visible) { +        return; +    } + +    m_visible = visible; + +    if (m_manager_display_service) { +        if (m_system_shared_layer_id) { +            m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); +        } + +        for (const auto layer_id : m_managed_display_layers) { +            m_manager_display_service->SetLayerVisibility(m_visible, layer_id); +        } +    } +} + +bool DisplayLayerManager::GetWindowVisibility() const { +    return m_visible; +} + +Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written, +                                                     s32* out_fbshare_layer_index) { +    R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied); +    R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer( +        out_was_written, out_fbshare_layer_index)); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/display_layer_manager.h b/src/core/hle/service/am/display_layer_manager.h new file mode 100644 index 000000000..a66509c04 --- /dev/null +++ b/src/core/hle/service/am/display_layer_manager.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <set> + +#include "common/common_types.h" +#include "core/hle/result.h" +#include "core/hle/service/am/am_types.h" + +namespace Core { +class System; +} + +namespace Kernel { +class KProcess; +} + +namespace Service::VI { +class IApplicationDisplayService; +class IManagerDisplayService; +} // namespace Service::VI + +namespace Service::AM { + +class DisplayLayerManager { +public: +    explicit DisplayLayerManager(); +    ~DisplayLayerManager(); + +    void Initialize(Core::System& system, Kernel::KProcess* process, AppletId applet_id, +                    LibraryAppletMode mode); +    void Finalize(); + +    Result CreateManagedDisplayLayer(u64* out_layer_id); +    Result CreateManagedDisplaySeparableLayer(u64* out_layer_id, u64* out_recording_layer_id); + +    Result IsSystemBufferSharingEnabled(); +    Result GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, +                                      u64* out_system_shared_layer_id); + +    void SetWindowVisibility(bool visible); +    bool GetWindowVisibility() const; + +    Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); + +private: +    Kernel::KProcess* m_process{}; +    std::shared_ptr<VI::IApplicationDisplayService> m_display_service{}; +    std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{}; +    std::set<u64> m_managed_display_layers{}; +    std::set<u64> m_managed_display_recording_layers{}; +    u64 m_system_shared_buffer_id{}; +    u64 m_system_shared_layer_id{}; +    AppletId m_applet_id{}; +    bool m_buffer_sharing_enabled{}; +    bool m_blending_enabled{}; +    bool m_visible{true}; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/frontend/applet_web_browser.cpp b/src/core/hle/service/am/frontend/applet_web_browser.cpp index bb60260b4..835c20c4e 100644 --- a/src/core/hle/service/am/frontend/applet_web_browser.cpp +++ b/src/core/hle/service/am/frontend/applet_web_browser.cpp @@ -22,7 +22,7 @@  #include "core/hle/service/am/frontend/applet_web_browser.h"  #include "core/hle/service/am/service/storage.h"  #include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/ns/iplatform_service_manager.h" +#include "core/hle/service/ns/platform_service_manager.h"  #include "core/loader/loader.h"  namespace Service::AM::Frontend { diff --git a/src/core/hle/service/am/managed_layer_holder.cpp b/src/core/hle/service/am/managed_layer_holder.cpp deleted file mode 100644 index 61eb8641a..000000000 --- a/src/core/hle/service/am/managed_layer_holder.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/managed_layer_holder.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" - -namespace Service::AM { - -ManagedLayerHolder::ManagedLayerHolder() = default; -ManagedLayerHolder::~ManagedLayerHolder() { -    if (!m_nvnflinger) { -        return; -    } - -    for (const auto& layer : m_managed_display_layers) { -        m_nvnflinger->DestroyLayer(layer); -    } - -    for (const auto& layer : m_managed_display_recording_layers) { -        m_nvnflinger->DestroyLayer(layer); -    } - -    m_nvnflinger = nullptr; -} - -void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) { -    m_nvnflinger = nvnflinger; -} - -void ManagedLayerHolder::CreateManagedDisplayLayer(u64* out_layer) { -    // TODO(Subv): Find out how AM determines the display to use, for now just -    // create the layer in the Default display. -    const auto display_id = m_nvnflinger->OpenDisplay("Default"); -    const auto layer_id = m_nvnflinger->CreateLayer(*display_id); - -    m_managed_display_layers.emplace(*layer_id); - -    *out_layer = *layer_id; -} - -void ManagedLayerHolder::CreateManagedDisplaySeparableLayer(u64* out_layer, -                                                            u64* out_recording_layer) { -    // TODO(Subv): Find out how AM determines the display to use, for now just -    // create the layer in the Default display. -    // This calls nn::vi::CreateRecordingLayer() which creates another layer. -    // Currently we do not support more than 1 layer per display, output 1 layer id for now. -    // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse -    // side effects. -    // TODO: Support multiple layers -    const auto display_id = m_nvnflinger->OpenDisplay("Default"); -    const auto layer_id = m_nvnflinger->CreateLayer(*display_id); - -    m_managed_display_layers.emplace(*layer_id); - -    *out_layer = *layer_id; -    *out_recording_layer = 0; -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/managed_layer_holder.h b/src/core/hle/service/am/managed_layer_holder.h deleted file mode 100644 index f7fe03f24..000000000 --- a/src/core/hle/service/am/managed_layer_holder.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <set> - -#include "common/common_funcs.h" -#include "common/common_types.h" - -namespace Service::Nvnflinger { -class Nvnflinger; -} - -namespace Service::AM { - -class ManagedLayerHolder { -public: -    ManagedLayerHolder(); -    ~ManagedLayerHolder(); - -    void Initialize(Nvnflinger::Nvnflinger* nvnflinger); -    void CreateManagedDisplayLayer(u64* out_layer); -    void CreateManagedDisplaySeparableLayer(u64* out_layer, u64* out_recording_layer); - -private: -    Nvnflinger::Nvnflinger* m_nvnflinger{}; -    std::set<u64> m_managed_display_layers{}; -    std::set<u64> m_managed_display_recording_layers{}; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/process.cpp b/src/core/hle/service/am/process.cpp index 992c50713..388d2045c 100644 --- a/src/core/hle/service/am/process.cpp +++ b/src/core/hle/service/am/process.cpp @@ -68,7 +68,9 @@ bool Process::Initialize(u64 program_id, u8 minimum_key_generation, u8 maximum_k      Kernel::KProcess::Register(m_system.Kernel(), process);      // On exit, ensure we free the additional reference to the process. -    SCOPE_EXIT({ process->Close(); }); +    SCOPE_EXIT { +        process->Close(); +    };      // Insert process modules into memory.      const auto [load_result, load_parameters] = app_loader->Load(*process, m_system); diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp index eebd90ba2..21747783a 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp @@ -10,9 +10,8 @@  namespace Service::AM { -IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_, -                                                               Nvnflinger::Nvnflinger& nvnflinger) -    : ServiceFramework{system_, "appletAE"}, m_nvnflinger{nvnflinger} { +IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_) +    : ServiceFramework{system_, "appletAE"} {      // clang-format off      static const FunctionInfo functions[] = {          {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, @@ -37,8 +36,8 @@ Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(      LOG_DEBUG(Service_AM, "called");      if (const auto applet = this->GetAppletFromProcessId(pid); applet) { -        *out_system_applet_proxy = std::make_shared<ISystemAppletProxy>( -            system, applet, process_handle.Get(), m_nvnflinger); +        *out_system_applet_proxy = +            std::make_shared<ISystemAppletProxy>(system, applet, process_handle.Get());          R_SUCCEED();      } else {          UNIMPLEMENTED(); @@ -53,8 +52,8 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(      LOG_DEBUG(Service_AM, "called");      if (const auto applet = this->GetAppletFromProcessId(pid); applet) { -        *out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>( -            system, applet, process_handle.Get(), m_nvnflinger); +        *out_library_applet_proxy = +            std::make_shared<ILibraryAppletProxy>(system, applet, process_handle.Get());          R_SUCCEED();      } else {          UNIMPLEMENTED(); diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.h b/src/core/hle/service/am/service/all_system_applet_proxies_service.h index 38b1ca2ea..0e2dcb86d 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.h +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.h @@ -8,10 +8,6 @@  namespace Service { -namespace Nvnflinger { -class Nvnflinger; -} -  namespace AM {  struct Applet; @@ -22,8 +18,7 @@ class ISystemAppletProxy;  class IAllSystemAppletProxiesService final      : public ServiceFramework<IAllSystemAppletProxiesService> {  public: -    explicit IAllSystemAppletProxiesService(Core::System& system_, -                                            Nvnflinger::Nvnflinger& nvnflinger); +    explicit IAllSystemAppletProxiesService(Core::System& system_);      ~IAllSystemAppletProxiesService() override;  private: @@ -40,7 +35,6 @@ private:  private:      std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); -    Nvnflinger::Nvnflinger& m_nvnflinger;  };  } // namespace AM diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp index 63dd12a47..cb53b07e0 100644 --- a/src/core/hle/service/am/service/application_functions.cpp +++ b/src/core/hle/service/am/service/application_functions.cpp @@ -16,7 +16,8 @@  #include "core/hle/service/filesystem/filesystem.h"  #include "core/hle/service/filesystem/save_data_controller.h"  #include "core/hle/service/glue/glue_manager.h" -#include "core/hle/service/ns/ns.h" +#include "core/hle/service/ns/application_manager_interface.h" +#include "core/hle/service/ns/service_getter_interface.h"  #include "core/hle/service/sm/sm.h"  namespace Service::AM { @@ -163,11 +164,13 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {      // Call IApplicationManagerInterface implementation.      auto& service_manager = system.ServiceManager(); -    auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); -    auto app_man = ns_am2->GetApplicationManagerInterface(); +    auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2"); + +    std::shared_ptr<NS::IApplicationManagerInterface> app_man; +    R_TRY(ns_am2->GetApplicationManagerInterface(&app_man));      // Get desired application language -    u8 desired_language{}; +    NS::ApplicationLanguage desired_language{};      R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));      // Convert to settings language code. diff --git a/src/core/hle/service/am/service/application_proxy.cpp b/src/core/hle/service/am/service/application_proxy.cpp index 776f4552b..19d6a3b89 100644 --- a/src/core/hle/service/am/service/application_proxy.cpp +++ b/src/core/hle/service/am/service/application_proxy.cpp @@ -17,9 +17,9 @@  namespace Service::AM {  IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, -                                     Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger) -    : ServiceFramework{system_, "IApplicationProxy"}, -      m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} { +                                     Kernel::KProcess* process) +    : ServiceFramework{system_, "IApplicationProxy"}, m_process{process}, m_applet{ +                                                                              std::move(applet)} {      // clang-format off      static const FunctionInfo functions[] = {          {0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, @@ -77,8 +77,7 @@ Result IApplicationProxy::GetWindowController(  Result IApplicationProxy::GetSelfController(      Out<SharedPointer<ISelfController>> out_self_controller) {      LOG_DEBUG(Service_AM, "called"); -    *out_self_controller = -        std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger); +    *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);      R_SUCCEED();  } diff --git a/src/core/hle/service/am/service/application_proxy.h b/src/core/hle/service/am/service/application_proxy.h index 1ebc593ba..6da350df7 100644 --- a/src/core/hle/service/am/service/application_proxy.h +++ b/src/core/hle/service/am/service/application_proxy.h @@ -22,7 +22,7 @@ class IWindowController;  class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {  public:      explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, -                               Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); +                               Kernel::KProcess* process);      ~IApplicationProxy();  private: @@ -40,7 +40,6 @@ private:          Out<SharedPointer<IApplicationFunctions>> out_application_functions);  private: -    Nvnflinger::Nvnflinger& m_nvnflinger;      Kernel::KProcess* const m_process;      const std::shared_ptr<Applet> m_applet;  }; diff --git a/src/core/hle/service/am/service/application_proxy_service.cpp b/src/core/hle/service/am/service/application_proxy_service.cpp index 36d4478df..fd66e77b9 100644 --- a/src/core/hle/service/am/service/application_proxy_service.cpp +++ b/src/core/hle/service/am/service/application_proxy_service.cpp @@ -10,9 +10,8 @@  namespace Service::AM { -IApplicationProxyService::IApplicationProxyService(Core::System& system_, -                                                   Nvnflinger::Nvnflinger& nvnflinger) -    : ServiceFramework{system_, "appletOE"}, m_nvnflinger{nvnflinger} { +IApplicationProxyService::IApplicationProxyService(Core::System& system_) +    : ServiceFramework{system_, "appletOE"} {      static const FunctionInfo functions[] = {          {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},      }; @@ -28,7 +27,7 @@ Result IApplicationProxyService::OpenApplicationProxy(      if (const auto applet = this->GetAppletFromProcessId(pid)) {          *out_application_proxy = -            std::make_shared<IApplicationProxy>(system, applet, process_handle.Get(), m_nvnflinger); +            std::make_shared<IApplicationProxy>(system, applet, process_handle.Get());          R_SUCCEED();      } else {          UNIMPLEMENTED(); diff --git a/src/core/hle/service/am/service/application_proxy_service.h b/src/core/hle/service/am/service/application_proxy_service.h index 1c1d32d0b..8efafa31a 100644 --- a/src/core/hle/service/am/service/application_proxy_service.h +++ b/src/core/hle/service/am/service/application_proxy_service.h @@ -8,10 +8,6 @@  namespace Service { -namespace Nvnflinger { -class Nvnflinger; -} -  namespace AM {  struct Applet; @@ -19,7 +15,7 @@ class IApplicationProxy;  class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {  public: -    explicit IApplicationProxyService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); +    explicit IApplicationProxyService(Core::System& system_);      ~IApplicationProxyService() override;  private: @@ -28,7 +24,6 @@ private:  private:      std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); -    Nvnflinger::Nvnflinger& m_nvnflinger;  };  } // namespace AM diff --git a/src/core/hle/service/am/service/display_controller.cpp b/src/core/hle/service/am/service/display_controller.cpp index 249c73dfb..ed71f9093 100644 --- a/src/core/hle/service/am/service/display_controller.cpp +++ b/src/core/hle/service/am/service/display_controller.cpp @@ -69,7 +69,7 @@ Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_i  Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(      Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {      LOG_WARNING(Service_AM, "(STUBBED) called"); -    R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, +    R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,                                                                      out_fbshare_layer_index));  } @@ -81,7 +81,7 @@ Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {  Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(      Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {      LOG_WARNING(Service_AM, "(STUBBED) called"); -    R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, +    R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,                                                                      out_fbshare_layer_index));  } @@ -93,7 +93,7 @@ Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {  Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(      Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {      LOG_WARNING(Service_AM, "(STUBBED) called"); -    R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, +    R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,                                                                      out_fbshare_layer_index));  } diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 166637d60..c97358d81 100644 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -135,7 +135,7 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,      case LibraryAppletMode::AllForegroundInitiallyHidden:          applet->hid_registration.EnableAppletToGetInput(false);          applet->focus_state = FocusState::NotInFocus; -        applet->system_buffer_manager.SetWindowVisibility(false); +        applet->display_layer_manager.SetWindowVisibility(false);          applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground);          break;      } diff --git a/src/core/hle/service/am/service/library_applet_proxy.cpp b/src/core/hle/service/am/service/library_applet_proxy.cpp index bcb44a71c..58e709347 100644 --- a/src/core/hle/service/am/service/library_applet_proxy.cpp +++ b/src/core/hle/service/am/service/library_applet_proxy.cpp @@ -19,10 +19,9 @@  namespace Service::AM {  ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, -                                         Kernel::KProcess* process, -                                         Nvnflinger::Nvnflinger& nvnflinger) -    : ServiceFramework{system_, "ILibraryAppletProxy"}, -      m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} { +                                         Kernel::KProcess* process) +    : ServiceFramework{system_, "ILibraryAppletProxy"}, m_process{process}, m_applet{ +                                                                                std::move(applet)} {      // clang-format off      static const FunctionInfo functions[] = {          {0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, @@ -83,8 +82,7 @@ Result ILibraryAppletProxy::GetWindowController(  Result ILibraryAppletProxy::GetSelfController(      Out<SharedPointer<ISelfController>> out_self_controller) {      LOG_DEBUG(Service_AM, "called"); -    *out_self_controller = -        std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger); +    *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);      R_SUCCEED();  } diff --git a/src/core/hle/service/am/service/library_applet_proxy.h b/src/core/hle/service/am/service/library_applet_proxy.h index 23e64e295..7d0714b85 100644 --- a/src/core/hle/service/am/service/library_applet_proxy.h +++ b/src/core/hle/service/am/service/library_applet_proxy.h @@ -25,7 +25,7 @@ class IWindowController;  class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {  public:      explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, -                                 Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); +                                 Kernel::KProcess* process);      ~ILibraryAppletProxy();  private: @@ -47,7 +47,6 @@ private:      Result GetGlobalStateController(          Out<SharedPointer<IGlobalStateController>> out_global_state_controller); -    Nvnflinger::Nvnflinger& m_nvnflinger;      Kernel::KProcess* const m_process;      const std::shared_ptr<Applet> m_applet;  }; diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp index 94bd4dae6..330eb26f0 100644 --- a/src/core/hle/service/am/service/library_applet_self_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp @@ -14,7 +14,8 @@  #include "core/hle/service/cmif_serialization.h"  #include "core/hle/service/filesystem/filesystem.h"  #include "core/hle/service/glue/glue_manager.h" -#include "core/hle/service/ns/ns.h" +#include "core/hle/service/ns/application_manager_interface.h" +#include "core/hle/service/ns/service_getter_interface.h"  #include "core/hle/service/sm/sm.h"  namespace Service::AM { @@ -256,11 +257,13 @@ Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(      // Call IApplicationManagerInterface implementation.      auto& service_manager = system.ServiceManager(); -    auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); -    auto app_man = ns_am2->GetApplicationManagerInterface(); +    auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2"); + +    std::shared_ptr<NS::IApplicationManagerInterface> app_man; +    R_TRY(ns_am2->GetApplicationManagerInterface(&app_man));      // Get desired application language -    u8 desired_language{}; +    NS::ApplicationLanguage desired_language{};      R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));      // Convert to settings language code. diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp index 5c4c13de1..06314407c 100644 --- a/src/core/hle/service/am/service/self_controller.cpp +++ b/src/core/hle/service/am/service/self_controller.cpp @@ -15,9 +15,9 @@  namespace Service::AM {  ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, -                                 Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger) -    : ServiceFramework{system_, "ISelfController"}, -      m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} { +                                 Kernel::KProcess* process) +    : ServiceFramework{system_, "ISelfController"}, m_process{process}, m_applet{ +                                                                            std::move(applet)} {      // clang-format off      static const FunctionInfo functions[] = {          {0, D<&ISelfController::Exit>, "Exit"}, @@ -72,9 +72,16 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>      // clang-format on      RegisterHandlers(functions); + +    std::scoped_lock lk{m_applet->lock}; +    m_applet->display_layer_manager.Initialize(system, m_process, m_applet->applet_id, +                                               m_applet->library_applet_mode);  } -ISelfController::~ISelfController() = default; +ISelfController::~ISelfController() { +    std::scoped_lock lk{m_applet->lock}; +    m_applet->display_layer_manager.Finalize(); +}  Result ISelfController::Exit() {      LOG_DEBUG(Service_AM, "called"); @@ -212,48 +219,42 @@ Result ISelfController::SetAlbumImageOrientation(  Result ISelfController::IsSystemBufferSharingEnabled() {      LOG_INFO(Service_AM, "called"); -    R_SUCCEED_IF(m_applet->system_buffer_manager.Initialize( -        &m_nvnflinger, m_process, m_applet->applet_id, m_applet->library_applet_mode)); -    R_THROW(VI::ResultOperationFailed); + +    std::scoped_lock lk{m_applet->lock}; +    R_RETURN(m_applet->display_layer_manager.IsSystemBufferSharingEnabled());  }  Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) { -    LOG_WARNING(Service_AM, "(STUBBED) called"); - -    R_TRY(this->IsSystemBufferSharingEnabled()); +    LOG_INFO(Service_AM, "called");      u64 layer_id; -    m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id); -    R_SUCCEED(); + +    std::scoped_lock lk{m_applet->lock}; +    R_RETURN(m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id));  }  Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) { -    LOG_INFO(Service_AM, "(STUBBED) called"); - -    R_TRY(this->IsSystemBufferSharingEnabled()); +    LOG_INFO(Service_AM, "called"); -    m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id); -    R_SUCCEED(); +    std::scoped_lock lk{m_applet->lock}; +    R_RETURN( +        m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id));  }  Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) {      LOG_INFO(Service_AM, "called"); -    m_applet->managed_layer_holder.Initialize(&m_nvnflinger); -    m_applet->managed_layer_holder.CreateManagedDisplayLayer(out_layer_id); - -    R_SUCCEED(); +    std::scoped_lock lk{m_applet->lock}; +    R_RETURN(m_applet->display_layer_manager.CreateManagedDisplayLayer(out_layer_id));  }  Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id,                                                             Out<u64> out_recording_layer_id) {      LOG_WARNING(Service_AM, "(STUBBED) called"); -    m_applet->managed_layer_holder.Initialize(&m_nvnflinger); -    m_applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(out_layer_id, -                                                                      out_recording_layer_id); - -    R_SUCCEED(); +    std::scoped_lock lk{m_applet->lock}; +    R_RETURN(m_applet->display_layer_manager.CreateManagedDisplaySeparableLayer( +        out_layer_id, out_recording_layer_id));  }  Result ISelfController::SetHandlesRequestToDisplay(bool enable) { diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h index 01fa381a3..eca083cfe 100644 --- a/src/core/hle/service/am/service/self_controller.h +++ b/src/core/hle/service/am/service/self_controller.h @@ -23,7 +23,7 @@ struct Applet;  class ISelfController final : public ServiceFramework<ISelfController> {  public:      explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, -                             Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); +                             Kernel::KProcess* process);      ~ISelfController() override;  private: @@ -64,7 +64,6 @@ private:      Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option);      Result SetRecordVolumeMuted(bool muted); -    Nvnflinger::Nvnflinger& m_nvnflinger;      Kernel::KProcess* const m_process;      const std::shared_ptr<Applet> m_applet;  }; diff --git a/src/core/hle/service/am/service/system_applet_proxy.cpp b/src/core/hle/service/am/service/system_applet_proxy.cpp index 5ec509d2e..d1871ef9b 100644 --- a/src/core/hle/service/am/service/system_applet_proxy.cpp +++ b/src/core/hle/service/am/service/system_applet_proxy.cpp @@ -19,10 +19,9 @@  namespace Service::AM {  ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, -                                       Kernel::KProcess* process, -                                       Nvnflinger::Nvnflinger& nvnflinger) -    : ServiceFramework{system_, "ISystemAppletProxy"}, -      m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} { +                                       Kernel::KProcess* process) +    : ServiceFramework{system_, "ISystemAppletProxy"}, m_process{process}, m_applet{ +                                                                               std::move(applet)} {      // clang-format off      static const FunctionInfo functions[] = {          {0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, @@ -83,8 +82,7 @@ Result ISystemAppletProxy::GetWindowController(  Result ISystemAppletProxy::GetSelfController(      Out<SharedPointer<ISelfController>> out_self_controller) {      LOG_DEBUG(Service_AM, "called"); -    *out_self_controller = -        std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger); +    *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);      R_SUCCEED();  } diff --git a/src/core/hle/service/am/service/system_applet_proxy.h b/src/core/hle/service/am/service/system_applet_proxy.h index 3d5040315..67cd50e03 100644 --- a/src/core/hle/service/am/service/system_applet_proxy.h +++ b/src/core/hle/service/am/service/system_applet_proxy.h @@ -25,7 +25,7 @@ class IWindowController;  class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {  public:      explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet, -                                Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); +                                Kernel::KProcess* process);      ~ISystemAppletProxy();  private: @@ -46,7 +46,6 @@ private:      Result GetGlobalStateController(          Out<SharedPointer<IGlobalStateController>> out_global_state_controller); -    Nvnflinger::Nvnflinger& m_nvnflinger;      Kernel::KProcess* const m_process;      const std::shared_ptr<Applet> m_applet;  }; diff --git a/src/core/hle/service/am/service/window_controller.cpp b/src/core/hle/service/am/service/window_controller.cpp index b874ecb91..99a4f50a2 100644 --- a/src/core/hle/service/am/service/window_controller.cpp +++ b/src/core/hle/service/am/service/window_controller.cpp @@ -63,7 +63,7 @@ Result IWindowController::RejectToChangeIntoBackground() {  }  Result IWindowController::SetAppletWindowVisibility(bool visible) { -    m_applet->system_buffer_manager.SetWindowVisibility(visible); +    m_applet->display_layer_manager.SetWindowVisibility(visible);      m_applet->hid_registration.EnableAppletToGetInput(visible);      if (visible) { diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp deleted file mode 100644 index 48923fe41..000000000 --- a/src/core/hle/service/am/system_buffer_manager.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/system_buffer_manager.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/vi/vi_results.h" - -namespace Service::AM { - -SystemBufferManager::SystemBufferManager() = default; - -SystemBufferManager::~SystemBufferManager() { -    if (!m_nvnflinger) { -        return; -    } - -    // Clean up shared layers. -    if (m_buffer_sharing_enabled) { -        m_nvnflinger->GetSystemBufferManager().Finalize(m_process); -    } -} - -bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process, -                                     AppletId applet_id, LibraryAppletMode mode) { -    if (m_nvnflinger) { -        return m_buffer_sharing_enabled; -    } - -    m_process = process; -    m_nvnflinger = nvnflinger; -    m_buffer_sharing_enabled = false; -    m_system_shared_buffer_id = 0; -    m_system_shared_layer_id = 0; - -    if (applet_id <= AppletId::Application) { -        return false; -    } - -    Nvnflinger::LayerBlending blending = Nvnflinger::LayerBlending::None; -    if (mode == LibraryAppletMode::PartialForeground || -        mode == LibraryAppletMode::PartialForegroundIndirectDisplay) { -        blending = Nvnflinger::LayerBlending::Coverage; -    } - -    const auto display_id = m_nvnflinger->OpenDisplay("Default").value(); -    const auto res = m_nvnflinger->GetSystemBufferManager().Initialize( -        m_process, &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id, blending); - -    if (res.IsSuccess()) { -        m_buffer_sharing_enabled = true; -        m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); -    } - -    return m_buffer_sharing_enabled; -} - -void SystemBufferManager::SetWindowVisibility(bool visible) { -    if (m_visible == visible) { -        return; -    } - -    m_visible = visible; - -    if (m_nvnflinger) { -        m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); -    } -} - -Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, -                                                     s32* out_fbshare_layer_index) { -    if (!m_buffer_sharing_enabled) { -        return VI::ResultPermissionDenied; -    } - -    return m_nvnflinger->GetSystemBufferManager().WriteAppletCaptureBuffer(out_was_written, -                                                                           out_fbshare_layer_index); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h deleted file mode 100644 index 0690f68b6..000000000 --- a/src/core/hle/service/am/system_buffer_manager.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <set> - -#include "common/common_funcs.h" -#include "common/common_types.h" - -#include "core/hle/service/am/am_types.h" - -namespace Kernel { -class KProcess; -} - -namespace Service::Nvnflinger { -class Nvnflinger; -} - -union Result; - -namespace Service::AM { - -class SystemBufferManager { -public: -    SystemBufferManager(); -    ~SystemBufferManager(); - -    bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id, -                    LibraryAppletMode mode); - -    void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, -                                    u64* out_system_shared_layer_id) { -        *out_system_shared_buffer_id = m_system_shared_buffer_id; -        *out_system_shared_layer_id = m_system_shared_layer_id; -    } - -    void SetWindowVisibility(bool visible); - -    Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); - -private: -    Kernel::KProcess* m_process{}; -    Nvnflinger::Nvnflinger* m_nvnflinger{}; -    bool m_buffer_sharing_enabled{}; -    bool m_visible{true}; -    u64 m_system_shared_buffer_id{}; -    u64 m_system_shared_layer_id{}; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 2dc23e674..d120dade8 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp @@ -3,141 +3,18 @@  #include <memory> -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hle/kernel/k_event.h"  #include "core/hle/service/btm/btm.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/btm/btm_debug.h" +#include "core/hle/service/btm/btm_system.h" +#include "core/hle/service/btm/btm_user.h"  #include "core/hle/service/server_manager.h"  #include "core/hle/service/service.h"  namespace Service::BTM { -class IBtmUserCore final : public ServiceFramework<IBtmUserCore> { +class IBtm final : public ServiceFramework<IBtm> {  public: -    explicit IBtmUserCore(Core::System& system_) -        : ServiceFramework{system_, "IBtmUserCore"}, service_context{system_, "IBtmUserCore"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, &IBtmUserCore::AcquireBleScanEvent, "AcquireBleScanEvent"}, -            {1, nullptr, "GetBleScanFilterParameter"}, -            {2, nullptr, "GetBleScanFilterParameter2"}, -            {3, nullptr, "StartBleScanForGeneral"}, -            {4, nullptr, "StopBleScanForGeneral"}, -            {5, nullptr, "GetBleScanResultsForGeneral"}, -            {6, nullptr, "StartBleScanForPaired"}, -            {7, nullptr, "StopBleScanForPaired"}, -            {8, nullptr, "StartBleScanForSmartDevice"}, -            {9, nullptr, "StopBleScanForSmartDevice"}, -            {10, nullptr, "GetBleScanResultsForSmartDevice"}, -            {17, &IBtmUserCore::AcquireBleConnectionEvent, "AcquireBleConnectionEvent"}, -            {18, nullptr, "BleConnect"}, -            {19, nullptr, "BleDisconnect"}, -            {20, nullptr, "BleGetConnectionState"}, -            {21, nullptr, "AcquireBlePairingEvent"}, -            {22, nullptr, "BlePairDevice"}, -            {23, nullptr, "BleUnPairDevice"}, -            {24, nullptr, "BleUnPairDevice2"}, -            {25, nullptr, "BleGetPairedDevices"}, -            {26, &IBtmUserCore::AcquireBleServiceDiscoveryEvent, "AcquireBleServiceDiscoveryEvent"}, -            {27, nullptr, "GetGattServices"}, -            {28, nullptr, "GetGattService"}, -            {29, nullptr, "GetGattIncludedServices"}, -            {30, nullptr, "GetBelongingGattService"}, -            {31, nullptr, "GetGattCharacteristics"}, -            {32, nullptr, "GetGattDescriptors"}, -            {33, &IBtmUserCore::AcquireBleMtuConfigEvent, "AcquireBleMtuConfigEvent"}, -            {34, nullptr, "ConfigureBleMtu"}, -            {35, nullptr, "GetBleMtu"}, -            {36, nullptr, "RegisterBleGattDataPath"}, -            {37, nullptr, "UnregisterBleGattDataPath"}, -        }; -        // clang-format on -        RegisterHandlers(functions); - -        scan_event = service_context.CreateEvent("IBtmUserCore:ScanEvent"); -        connection_event = service_context.CreateEvent("IBtmUserCore:ConnectionEvent"); -        service_discovery_event = service_context.CreateEvent("IBtmUserCore:DiscoveryEvent"); -        config_event = service_context.CreateEvent("IBtmUserCore:ConfigEvent"); -    } - -    ~IBtmUserCore() override { -        service_context.CloseEvent(scan_event); -        service_context.CloseEvent(connection_event); -        service_context.CloseEvent(service_discovery_event); -        service_context.CloseEvent(config_event); -    } - -private: -    void AcquireBleScanEvent(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); - -        IPC::ResponseBuilder rb{ctx, 3, 1}; -        rb.Push(ResultSuccess); -        rb.Push(true); -        rb.PushCopyObjects(scan_event->GetReadableEvent()); -    } - -    void AcquireBleConnectionEvent(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); - -        IPC::ResponseBuilder rb{ctx, 3, 1}; -        rb.Push(ResultSuccess); -        rb.Push(true); -        rb.PushCopyObjects(connection_event->GetReadableEvent()); -    } - -    void AcquireBleServiceDiscoveryEvent(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); - -        IPC::ResponseBuilder rb{ctx, 3, 1}; -        rb.Push(ResultSuccess); -        rb.Push(true); -        rb.PushCopyObjects(service_discovery_event->GetReadableEvent()); -    } - -    void AcquireBleMtuConfigEvent(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); - -        IPC::ResponseBuilder rb{ctx, 3, 1}; -        rb.Push(ResultSuccess); -        rb.Push(true); -        rb.PushCopyObjects(config_event->GetReadableEvent()); -    } - -    KernelHelpers::ServiceContext service_context; - -    Kernel::KEvent* scan_event; -    Kernel::KEvent* connection_event; -    Kernel::KEvent* service_discovery_event; -    Kernel::KEvent* config_event; -}; - -class BTM_USR final : public ServiceFramework<BTM_USR> { -public: -    explicit BTM_USR(Core::System& system_) : ServiceFramework{system_, "btm:u"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, &BTM_USR::GetCore, "GetCore"}, -        }; -        // clang-format on -        RegisterHandlers(functions); -    } - -private: -    void GetCore(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "called"); - -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(ResultSuccess); -        rb.PushIpcInterface<IBtmUserCore>(system); -    } -}; - -class BTM final : public ServiceFramework<BTM> { -public: -    explicit BTM(Core::System& system_) : ServiceFramework{system_, "btm"} { +    explicit IBtm(Core::System& system_) : ServiceFramework{system_, "btm"} {          // clang-format off          static const FunctionInfo functions[] = {              {0, nullptr, "GetState"}, @@ -232,144 +109,13 @@ public:      }  }; -class BTM_DBG final : public ServiceFramework<BTM_DBG> { -public: -    explicit BTM_DBG(Core::System& system_) : ServiceFramework{system_, "btm:dbg"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "AcquireDiscoveryEvent"}, -            {1, nullptr, "StartDiscovery"}, -            {2, nullptr, "CancelDiscovery"}, -            {3, nullptr, "GetDeviceProperty"}, -            {4, nullptr, "CreateBond"}, -            {5, nullptr, "CancelBond"}, -            {6, nullptr, "SetTsiMode"}, -            {7, nullptr, "GeneralTest"}, -            {8, nullptr, "HidConnect"}, -            {9, nullptr, "GeneralGet"}, -            {10, nullptr, "GetGattClientDisconnectionReason"}, -            {11, nullptr, "GetBleConnectionParameter"}, -            {12, nullptr, "GetBleConnectionParameterRequest"}, -            {13, nullptr, "Unknown13"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } -}; - -class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> { -public: -    explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, &IBtmSystemCore::StartGamepadPairing, "StartGamepadPairing"}, -            {1, &IBtmSystemCore::CancelGamepadPairing, "CancelGamepadPairing"}, -            {2, nullptr, "ClearGamepadPairingDatabase"}, -            {3, nullptr, "GetPairedGamepadCount"}, -            {4, nullptr, "EnableRadio"}, -            {5, nullptr, "DisableRadio"}, -            {6, &IBtmSystemCore::IsRadioEnabled, "IsRadioEnabled"}, -            {7, nullptr, "AcquireRadioEvent"}, -            {8, nullptr, "AcquireGamepadPairingEvent"}, -            {9, nullptr, "IsGamepadPairingStarted"}, -            {10, nullptr, "StartAudioDeviceDiscovery"}, -            {11, nullptr, "StopAudioDeviceDiscovery"}, -            {12, nullptr, "IsDiscoveryingAudioDevice"}, -            {13, nullptr, "GetDiscoveredAudioDevice"}, -            {14, nullptr, "AcquireAudioDeviceConnectionEvent"}, -            {15, nullptr, "ConnectAudioDevice"}, -            {16, nullptr, "IsConnectingAudioDevice"}, -            {17, &IBtmSystemCore::GetConnectedAudioDevices, "GetConnectedAudioDevices"}, -            {18, nullptr, "DisconnectAudioDevice"}, -            {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"}, -            {20, &IBtmSystemCore::GetPairedAudioDevices, "GetPairedAudioDevices"}, -            {21, nullptr, "RemoveAudioDevicePairing"}, -            {22, &IBtmSystemCore::RequestAudioDeviceConnectionRejection, "RequestAudioDeviceConnectionRejection"}, -            {23, &IBtmSystemCore::CancelAudioDeviceConnectionRejection, "CancelAudioDeviceConnectionRejection"} -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } - -private: -    void IsRadioEnabled(HLERequestContext& ctx) { -        LOG_DEBUG(Service_BTM, "(STUBBED) called"); // Spams a lot when controller applet is running - -        IPC::ResponseBuilder rb{ctx, 3}; -        rb.Push(ResultSuccess); -        rb.Push(true); -    } - -    void StartGamepadPairing(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } - -    void CancelGamepadPairing(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } - -    void CancelAudioDeviceConnectionRejection(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } - -    void GetConnectedAudioDevices(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); -        IPC::ResponseBuilder rb{ctx, 3}; -        rb.Push(ResultSuccess); -        rb.Push<u32>(0); -    } - -    void GetPairedAudioDevices(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); -        IPC::ResponseBuilder rb{ctx, 3}; -        rb.Push(ResultSuccess); -        rb.Push<u32>(0); -    } - -    void RequestAudioDeviceConnectionRejection(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "(STUBBED) called"); -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } -}; - -class BTM_SYS final : public ServiceFramework<BTM_SYS> { -public: -    explicit BTM_SYS(Core::System& system_) : ServiceFramework{system_, "btm:sys"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, &BTM_SYS::GetCore, "GetCore"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } - -private: -    void GetCore(HLERequestContext& ctx) { -        LOG_WARNING(Service_BTM, "called"); - -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(ResultSuccess); -        rb.PushIpcInterface<IBtmSystemCore>(system); -    } -}; -  void LoopProcess(Core::System& system) {      auto server_manager = std::make_unique<ServerManager>(system); -    server_manager->RegisterNamedService("btm", std::make_shared<BTM>(system)); -    server_manager->RegisterNamedService("btm:dbg", std::make_shared<BTM_DBG>(system)); -    server_manager->RegisterNamedService("btm:sys", std::make_shared<BTM_SYS>(system)); -    server_manager->RegisterNamedService("btm:u", std::make_shared<BTM_USR>(system)); +    server_manager->RegisterNamedService("btm", std::make_shared<IBtm>(system)); +    server_manager->RegisterNamedService("btm:dbg", std::make_shared<IBtmDebug>(system)); +    server_manager->RegisterNamedService("btm:sys", std::make_shared<IBtmSystem>(system)); +    server_manager->RegisterNamedService("btm:u", std::make_shared<IBtmUser>(system));      ServerManager::RunServer(std::move(server_manager));  } diff --git a/src/core/hle/service/btm/btm.h b/src/core/hle/service/btm/btm.h index a99b34364..0bf77d053 100644 --- a/src/core/hle/service/btm/btm.h +++ b/src/core/hle/service/btm/btm.h @@ -3,10 +3,6 @@  #pragma once -namespace Service::SM { -class ServiceManager; -} -  namespace Core {  class System;  }; diff --git a/src/core/hle/service/btm/btm_debug.cpp b/src/core/hle/service/btm/btm_debug.cpp new file mode 100644 index 000000000..4d61d2641 --- /dev/null +++ b/src/core/hle/service/btm/btm_debug.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/btm/btm_debug.h" + +namespace Service::BTM { + +IBtmDebug::IBtmDebug(Core::System& system_) : ServiceFramework{system_, "btm:dbg"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "AcquireDiscoveryEvent"}, +        {1, nullptr, "StartDiscovery"}, +        {2, nullptr, "CancelDiscovery"}, +        {3, nullptr, "GetDeviceProperty"}, +        {4, nullptr, "CreateBond"}, +        {5, nullptr, "CancelBond"}, +        {6, nullptr, "SetTsiMode"}, +        {7, nullptr, "GeneralTest"}, +        {8, nullptr, "HidConnect"}, +        {9, nullptr, "GeneralGet"}, +        {10, nullptr, "GetGattClientDisconnectionReason"}, +        {11, nullptr, "GetBleConnectionParameter"}, +        {12, nullptr, "GetBleConnectionParameterRequest"}, +        {13, nullptr, "Unknown13"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IBtmDebug::~IBtmDebug() = default; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_debug.h b/src/core/hle/service/btm/btm_debug.h new file mode 100644 index 000000000..bf4f7e14f --- /dev/null +++ b/src/core/hle/service/btm/btm_debug.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::BTM { + +class IBtmDebug final : public ServiceFramework<IBtmDebug> { +public: +    explicit IBtmDebug(Core::System& system_); +    ~IBtmDebug() override; +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_system.cpp b/src/core/hle/service/btm/btm_system.cpp new file mode 100644 index 000000000..99718a7b0 --- /dev/null +++ b/src/core/hle/service/btm/btm_system.cpp @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/btm/btm_system.h" +#include "core/hle/service/btm/btm_system_core.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/service.h" + +namespace Service::BTM { + +IBtmSystem::IBtmSystem(Core::System& system_) : ServiceFramework{system_, "btm:sys"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, C<&IBtmSystem::GetCore>, "GetCore"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IBtmSystem::~IBtmSystem() = default; + +Result IBtmSystem::GetCore(OutInterface<IBtmSystemCore> out_interface) { +    LOG_WARNING(Service_BTM, "called"); + +    *out_interface = std::make_shared<IBtmSystemCore>(system); +    R_SUCCEED(); +} + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_system.h b/src/core/hle/service/btm/btm_system.h new file mode 100644 index 000000000..fe1c6dbd7 --- /dev/null +++ b/src/core/hle/service/btm/btm_system.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::BTM { +class IBtmSystemCore; + +class IBtmSystem final : public ServiceFramework<IBtmSystem> { +public: +    explicit IBtmSystem(Core::System& system_); +    ~IBtmSystem() override; + +private: +    Result GetCore(OutInterface<IBtmSystemCore> out_interface); +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_system_core.cpp b/src/core/hle/service/btm/btm_system_core.cpp new file mode 100644 index 000000000..4bc8a9e8b --- /dev/null +++ b/src/core/hle/service/btm/btm_system_core.cpp @@ -0,0 +1,127 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/btm/btm_system_core.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/set/system_settings_server.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::BTM { + +IBtmSystemCore::IBtmSystemCore(Core::System& system_) +    : ServiceFramework{system_, "IBtmSystemCore"}, service_context{system_, "IBtmSystemCore"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, C<&IBtmSystemCore::StartGamepadPairing>, "StartGamepadPairing"}, +        {1, C<&IBtmSystemCore::CancelGamepadPairing>, "CancelGamepadPairing"}, +        {2, nullptr, "ClearGamepadPairingDatabase"}, +        {3, nullptr, "GetPairedGamepadCount"}, +        {4, C<&IBtmSystemCore::EnableRadio>, "EnableRadio"}, +        {5, C<&IBtmSystemCore::DisableRadio>, "DisableRadio"}, +        {6, C<&IBtmSystemCore::IsRadioEnabled>, "IsRadioEnabled"}, +        {7, C<&IBtmSystemCore::AcquireRadioEvent>, "AcquireRadioEvent"}, +        {8, nullptr, "AcquireGamepadPairingEvent"}, +        {9, nullptr, "IsGamepadPairingStarted"}, +        {10, nullptr, "StartAudioDeviceDiscovery"}, +        {11, nullptr, "StopAudioDeviceDiscovery"}, +        {12, nullptr, "IsDiscoveryingAudioDevice"}, +        {13, nullptr, "GetDiscoveredAudioDevice"}, +        {14, C<&IBtmSystemCore::AcquireAudioDeviceConnectionEvent>, "AcquireAudioDeviceConnectionEvent"}, +        {15, nullptr, "ConnectAudioDevice"}, +        {16, nullptr, "IsConnectingAudioDevice"}, +        {17, C<&IBtmSystemCore::GetConnectedAudioDevices>, "GetConnectedAudioDevices"}, +        {18, nullptr, "DisconnectAudioDevice"}, +        {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"}, +        {20, C<&IBtmSystemCore::GetPairedAudioDevices>, "GetPairedAudioDevices"}, +        {21, nullptr, "RemoveAudioDevicePairing"}, +        {22, C<&IBtmSystemCore::RequestAudioDeviceConnectionRejection>, "RequestAudioDeviceConnectionRejection"}, +        {23, C<&IBtmSystemCore::CancelAudioDeviceConnectionRejection>, "CancelAudioDeviceConnectionRejection"} +    }; +    // clang-format on + +    RegisterHandlers(functions); +    radio_event = service_context.CreateEvent("IBtmSystemCore::RadioEvent"); +    audio_device_connection_event = +        service_context.CreateEvent("IBtmSystemCore::AudioDeviceConnectionEvent"); + +    m_set_sys = +        system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); +} + +IBtmSystemCore::~IBtmSystemCore() { +    service_context.CloseEvent(radio_event); +    service_context.CloseEvent(audio_device_connection_event); +} + +Result IBtmSystemCore::StartGamepadPairing() { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); +    R_SUCCEED(); +} + +Result IBtmSystemCore::CancelGamepadPairing() { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); +    R_SUCCEED(); +} + +Result IBtmSystemCore::EnableRadio() { +    LOG_DEBUG(Service_BTM, "called"); + +    R_RETURN(m_set_sys->SetBluetoothEnableFlag(true)); +} +Result IBtmSystemCore::DisableRadio() { +    LOG_DEBUG(Service_BTM, "called"); + +    R_RETURN(m_set_sys->SetBluetoothEnableFlag(false)); +} + +Result IBtmSystemCore::IsRadioEnabled(Out<bool> out_is_enabled) { +    LOG_DEBUG(Service_BTM, "called"); + +    R_RETURN(m_set_sys->GetBluetoothEnableFlag(out_is_enabled)); +} + +Result IBtmSystemCore::AcquireRadioEvent(Out<bool> out_is_valid, +                                         OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); + +    *out_is_valid = true; +    *out_event = &radio_event->GetReadableEvent(); +    R_SUCCEED(); +} + +Result IBtmSystemCore::AcquireAudioDeviceConnectionEvent( +    OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); + +    *out_event = &audio_device_connection_event->GetReadableEvent(); +    R_SUCCEED(); +} + +Result IBtmSystemCore::GetConnectedAudioDevices( +    Out<s32> out_count, OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices) { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); + +    *out_count = 0; +    R_SUCCEED(); +} + +Result IBtmSystemCore::GetPairedAudioDevices( +    Out<s32> out_count, OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices) { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); + +    *out_count = 0; +    R_SUCCEED(); +} + +Result IBtmSystemCore::RequestAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid) { +    LOG_WARNING(Service_BTM, "(STUBBED) called, applet_resource_user_id={}", aruid.pid); +    R_SUCCEED(); +} + +Result IBtmSystemCore::CancelAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid) { +    LOG_WARNING(Service_BTM, "(STUBBED) called, applet_resource_user_id={}", aruid.pid); +    R_SUCCEED(); +} + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_system_core.h b/src/core/hle/service/btm/btm_system_core.h new file mode 100644 index 000000000..06498b21e --- /dev/null +++ b/src/core/hle/service/btm/btm_system_core.h @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KEvent; +class KReadableEvent; +} // namespace Kernel + +namespace Core { +class System; +} + +namespace Service::Set { +class ISystemSettingsServer; +} + +namespace Service::BTM { + +class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> { +public: +    explicit IBtmSystemCore(Core::System& system_); +    ~IBtmSystemCore() override; + +private: +    Result StartGamepadPairing(); +    Result CancelGamepadPairing(); +    Result EnableRadio(); +    Result DisableRadio(); +    Result IsRadioEnabled(Out<bool> out_is_enabled); + +    Result AcquireRadioEvent(Out<bool> out_is_valid, +                             OutCopyHandle<Kernel::KReadableEvent> out_event); + +    Result AcquireAudioDeviceConnectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + +    Result GetConnectedAudioDevices( +        Out<s32> out_count, +        OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices); + +    Result GetPairedAudioDevices( +        Out<s32> out_count, +        OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices); + +    Result RequestAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid); +    Result CancelAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid); + +    KernelHelpers::ServiceContext service_context; + +    Kernel::KEvent* radio_event; +    Kernel::KEvent* audio_device_connection_event; +    std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_user.cpp b/src/core/hle/service/btm/btm_user.cpp new file mode 100644 index 000000000..d2e228f8d --- /dev/null +++ b/src/core/hle/service/btm/btm_user.cpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/btm/btm_user.h" +#include "core/hle/service/btm/btm_user_core.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::BTM { + +IBtmUser::IBtmUser(Core::System& system_) : ServiceFramework{system_, "btm:u"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, C<&IBtmUser::GetCore>, "GetCore"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IBtmUser::~IBtmUser() = default; + +Result IBtmUser::GetCore(OutInterface<IBtmUserCore> out_interface) { +    LOG_WARNING(Service_BTM, "called"); + +    *out_interface = std::make_shared<IBtmUserCore>(system); +    R_SUCCEED(); +} + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_user.h b/src/core/hle/service/btm/btm_user.h new file mode 100644 index 000000000..d9ee5db45 --- /dev/null +++ b/src/core/hle/service/btm/btm_user.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::BTM { +class IBtmUserCore; + +class IBtmUser final : public ServiceFramework<IBtmUser> { +public: +    explicit IBtmUser(Core::System& system_); +    ~IBtmUser() override; + +private: +    Result GetCore(OutInterface<IBtmUserCore> out_interface); +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_user_core.cpp b/src/core/hle/service/btm/btm_user_core.cpp new file mode 100644 index 000000000..6f9fa589b --- /dev/null +++ b/src/core/hle/service/btm/btm_user_core.cpp @@ -0,0 +1,103 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <memory> + +#include "common/logging/log.h" +#include "core/core.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/btm/btm_user_core.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::BTM { + +IBtmUserCore::IBtmUserCore(Core::System& system_) +    : ServiceFramework{system_, "IBtmUserCore"}, service_context{system_, "IBtmUserCore"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, C<&IBtmUserCore::AcquireBleScanEvent>, "AcquireBleScanEvent"}, +        {1, nullptr, "GetBleScanFilterParameter"}, +        {2, nullptr, "GetBleScanFilterParameter2"}, +        {3, nullptr, "StartBleScanForGeneral"}, +        {4, nullptr, "StopBleScanForGeneral"}, +        {5, nullptr, "GetBleScanResultsForGeneral"}, +        {6, nullptr, "StartBleScanForPaired"}, +        {7, nullptr, "StopBleScanForPaired"}, +        {8, nullptr, "StartBleScanForSmartDevice"}, +        {9, nullptr, "StopBleScanForSmartDevice"}, +        {10, nullptr, "GetBleScanResultsForSmartDevice"}, +        {17, C<&IBtmUserCore::AcquireBleConnectionEvent>, "AcquireBleConnectionEvent"}, +        {18, nullptr, "BleConnect"}, +        {19, nullptr, "BleDisconnect"}, +        {20, nullptr, "BleGetConnectionState"}, +        {21, nullptr, "AcquireBlePairingEvent"}, +        {22, nullptr, "BlePairDevice"}, +        {23, nullptr, "BleUnPairDevice"}, +        {24, nullptr, "BleUnPairDevice2"}, +        {25, nullptr, "BleGetPairedDevices"}, +        {26, C<&IBtmUserCore::AcquireBleServiceDiscoveryEvent>, "AcquireBleServiceDiscoveryEvent"}, +        {27, nullptr, "GetGattServices"}, +        {28, nullptr, "GetGattService"}, +        {29, nullptr, "GetGattIncludedServices"}, +        {30, nullptr, "GetBelongingGattService"}, +        {31, nullptr, "GetGattCharacteristics"}, +        {32, nullptr, "GetGattDescriptors"}, +        {33, C<&IBtmUserCore::AcquireBleMtuConfigEvent>, "AcquireBleMtuConfigEvent"}, +        {34, nullptr, "ConfigureBleMtu"}, +        {35, nullptr, "GetBleMtu"}, +        {36, nullptr, "RegisterBleGattDataPath"}, +        {37, nullptr, "UnregisterBleGattDataPath"}, +    }; +    // clang-format on +    RegisterHandlers(functions); + +    scan_event = service_context.CreateEvent("IBtmUserCore:ScanEvent"); +    connection_event = service_context.CreateEvent("IBtmUserCore:ConnectionEvent"); +    service_discovery_event = service_context.CreateEvent("IBtmUserCore:DiscoveryEvent"); +    config_event = service_context.CreateEvent("IBtmUserCore:ConfigEvent"); +} + +IBtmUserCore::~IBtmUserCore() { +    service_context.CloseEvent(scan_event); +    service_context.CloseEvent(connection_event); +    service_context.CloseEvent(service_discovery_event); +    service_context.CloseEvent(config_event); +} + +Result IBtmUserCore::AcquireBleScanEvent(Out<bool> out_is_valid, +                                         OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); + +    *out_is_valid = true; +    *out_event = &scan_event->GetReadableEvent(); +    R_SUCCEED(); +} + +Result IBtmUserCore::AcquireBleConnectionEvent(Out<bool> out_is_valid, +                                               OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); + +    *out_is_valid = true; +    *out_event = &connection_event->GetReadableEvent(); +    R_SUCCEED(); +} + +Result IBtmUserCore::AcquireBleServiceDiscoveryEvent( +    Out<bool> out_is_valid, OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); + +    *out_is_valid = true; +    *out_event = &service_discovery_event->GetReadableEvent(); +    R_SUCCEED(); +} + +Result IBtmUserCore::AcquireBleMtuConfigEvent(Out<bool> out_is_valid, +                                              OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_BTM, "(STUBBED) called"); + +    *out_is_valid = true; +    *out_event = &config_event->GetReadableEvent(); +    R_SUCCEED(); +} + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_user_core.h b/src/core/hle/service/btm/btm_user_core.h new file mode 100644 index 000000000..dc0a22e81 --- /dev/null +++ b/src/core/hle/service/btm/btm_user_core.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KEvent; +class KReadableEvent; +} // namespace Kernel + +namespace Core { +class System; +} + +namespace Service::BTM { + +class IBtmUserCore final : public ServiceFramework<IBtmUserCore> { +public: +    explicit IBtmUserCore(Core::System& system_); +    ~IBtmUserCore() override; + +private: +    Result AcquireBleScanEvent(Out<bool> out_is_valid, +                               OutCopyHandle<Kernel::KReadableEvent> out_event); + +    Result AcquireBleConnectionEvent(Out<bool> out_is_valid, +                                     OutCopyHandle<Kernel::KReadableEvent> out_event); + +    Result AcquireBleServiceDiscoveryEvent(Out<bool> out_is_valid, +                                           OutCopyHandle<Kernel::KReadableEvent> out_event); + +    Result AcquireBleMtuConfigEvent(Out<bool> out_is_valid, +                                    OutCopyHandle<Kernel::KReadableEvent> out_event); + +    KernelHelpers::ServiceContext service_context; + +    Kernel::KEvent* scan_event; +    Kernel::KEvent* connection_event; +    Kernel::KEvent* service_discovery_event; +    Kernel::KEvent* config_event; +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/glue/time/static.cpp b/src/core/hle/service/glue/time/static.cpp index ec9b0efb1..b801faef2 100644 --- a/src/core/hle/service/glue/time/static.cpp +++ b/src/core/hle/service/glue/time/static.cpp @@ -142,16 +142,18 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {  }  Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); +    };      R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value));  }  Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(      Out<bool> out_automatic_correction) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction); -    }); +    };      R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled(          out_automatic_correction)); @@ -166,21 +168,27 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(  }  Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); +    };      R_RETURN(m_set_sys->GetSettingsItemValueImpl<s32>(*out_year, "time",                                                        "standard_user_clock_initial_year"));  }  Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); +    };      R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient));  }  Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(      Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); +    };      R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(          out_time_point)); @@ -188,15 +196,18 @@ Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(  Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(      Out<s64> out_time, const Service::PSC::Time::SystemClockContext& context) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); +    };      R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context));  }  Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot,                                         Service::PSC::Time::TimeType type) { -    SCOPE_EXIT( -        { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); +    };      R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type));  } @@ -205,11 +216,11 @@ Result StaticService::GetClockSnapshotFromSystemClockContext(      Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot,      const Service::PSC::Time::SystemClockContext& user_context,      const Service::PSC::Time::SystemClockContext& network_context) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time,                    "called. type={} out_snapshot={} user_context={} network_context={}", type,                    *out_snapshot, user_context, network_context); -    }); +    };      R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(          type, out_snapshot, user_context, network_context)); @@ -218,14 +229,18 @@ Result StaticService::GetClockSnapshotFromSystemClockContext(  Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_time,                                                                         InClockSnapshot a,                                                                         InClockSnapshot b) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); +    };      R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b));  }  Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,                                             InClockSnapshot b) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); +    };      R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b));  } diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index 36f163419..f4d0c87d5 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp @@ -57,7 +57,9 @@ TimeZoneService::~TimeZoneService() = default;  Result TimeZoneService::GetDeviceLocationName(      Out<Service::PSC::Time::LocationName> out_location_name) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); +    };      R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name));  } @@ -94,7 +96,9 @@ Result TimeZoneService::SetDeviceLocationName(  }  Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); +    };      R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count));  } @@ -102,10 +106,10 @@ Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {  Result TimeZoneService::LoadLocationNameList(      Out<u32> out_count,      OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}",                    index, *out_count, out_names[0], out_names[1]); -    }); +    };      std::scoped_lock l{m_mutex};      R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index)); @@ -124,7 +128,9 @@ Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule,  Result TimeZoneService::GetTimeZoneRuleVersion(      Out<Service::PSC::Time::RuleVersion> out_rule_version) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); +    };      R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version));  } @@ -132,10 +138,10 @@ Result TimeZoneService::GetTimeZoneRuleVersion(  Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(      Out<Service::PSC::Time::LocationName> location_name,      Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. location_name={} out_time_point={}", *location_name,                    *out_time_point); -    }); +    };      R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(location_name, out_time_point));  } @@ -178,10 +184,10 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(  Result TimeZoneService::ToCalendarTime(      Out<Service::PSC::Time::CalendarTime> out_calendar_time,      Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,                    *out_calendar_time, *out_additional_info); -    }); +    };      R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule));  } @@ -189,10 +195,10 @@ Result TimeZoneService::ToCalendarTime(  Result TimeZoneService::ToCalendarTimeWithMyRule(      Out<Service::PSC::Time::CalendarTime> out_calendar_time,      Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,                    *out_calendar_time, *out_additional_info); -    }); +    };      R_RETURN(          m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); @@ -202,11 +208,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,                                      OutArray<s64, BufferAttr_HipcPointer> out_times,                                      const Service::PSC::Time::CalendarTime& calendar_time,                                      InRule rule) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time,                    "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",                    calendar_time, *out_count, out_times[0], out_times[1]); -    }); +    };      R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule));  } @@ -214,11 +220,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,  Result TimeZoneService::ToPosixTimeWithMyRule(      Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,      const Service::PSC::Time::CalendarTime& calendar_time) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time,                    "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",                    calendar_time, *out_count, out_times[0], out_times[1]); -    }); +    };      R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time));  } diff --git a/src/core/hle/service/ns/account_proxy_interface.cpp b/src/core/hle/service/ns/account_proxy_interface.cpp new file mode 100644 index 000000000..e5041af66 --- /dev/null +++ b/src/core/hle/service/ns/account_proxy_interface.cpp @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/account_proxy_interface.h" + +namespace Service::NS { + +IAccountProxyInterface::IAccountProxyInterface(Core::System& system_) +    : ServiceFramework{system_, "IAccountProxyInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "CreateUserAccount"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IAccountProxyInterface::~IAccountProxyInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/account_proxy_interface.h b/src/core/hle/service/ns/account_proxy_interface.h new file mode 100644 index 000000000..e944d2a75 --- /dev/null +++ b/src/core/hle/service/ns/account_proxy_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { +public: +    explicit IAccountProxyInterface(Core::System& system_); +    ~IAccountProxyInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/application_manager_interface.cpp b/src/core/hle/service/ns/application_manager_interface.cpp new file mode 100644 index 000000000..7a91727f9 --- /dev/null +++ b/src/core/hle/service/ns/application_manager_interface.cpp @@ -0,0 +1,519 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/file_sys/nca_metadata.h" +#include "core/file_sys/registered_cache.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ns/application_manager_interface.h" +#include "core/hle/service/ns/content_management_interface.h" +#include "core/hle/service/ns/read_only_application_control_data_interface.h" + +namespace Service::NS { + +IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_) +    : ServiceFramework{system_, "IApplicationManagerInterface"}, +      service_context{system, "IApplicationManagerInterface"}, +      record_update_system_event{service_context}, sd_card_mount_status_event{service_context}, +      gamecard_update_detection_event{service_context}, +      gamecard_mount_status_event{service_context}, gamecard_mount_failure_event{service_context} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, D<&IApplicationManagerInterface::ListApplicationRecord>, "ListApplicationRecord"}, +        {1, nullptr, "GenerateApplicationRecordCount"}, +        {2, D<&IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent>, "GetApplicationRecordUpdateSystemEvent"}, +        {3, nullptr, "GetApplicationViewDeprecated"}, +        {4, nullptr, "DeleteApplicationEntity"}, +        {5, nullptr, "DeleteApplicationCompletely"}, +        {6, nullptr, "IsAnyApplicationEntityRedundant"}, +        {7, nullptr, "DeleteRedundantApplicationEntity"}, +        {8, nullptr, "IsApplicationEntityMovable"}, +        {9, nullptr, "MoveApplicationEntity"}, +        {11, nullptr, "CalculateApplicationOccupiedSize"}, +        {16, nullptr, "PushApplicationRecord"}, +        {17, nullptr, "ListApplicationRecordContentMeta"}, +        {19, nullptr, "LaunchApplicationOld"}, +        {21, nullptr, "GetApplicationContentPath"}, +        {22, nullptr, "TerminateApplication"}, +        {23, nullptr, "ResolveApplicationContentPath"}, +        {26, nullptr, "BeginInstallApplication"}, +        {27, nullptr, "DeleteApplicationRecord"}, +        {30, nullptr, "RequestApplicationUpdateInfo"}, +        {31, nullptr, "Unknown31"}, +        {32, nullptr, "CancelApplicationDownload"}, +        {33, nullptr, "ResumeApplicationDownload"}, +        {35, nullptr, "UpdateVersionList"}, +        {36, nullptr, "PushLaunchVersion"}, +        {37, nullptr, "ListRequiredVersion"}, +        {38, D<&IApplicationManagerInterface::CheckApplicationLaunchVersion>, "CheckApplicationLaunchVersion"}, +        {39, nullptr, "CheckApplicationLaunchRights"}, +        {40, nullptr, "GetApplicationLogoData"}, +        {41, nullptr, "CalculateApplicationDownloadRequiredSize"}, +        {42, nullptr, "CleanupSdCard"}, +        {43, D<&IApplicationManagerInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"}, +        {44, D<&IApplicationManagerInterface::GetSdCardMountStatusChangedEvent>, "GetSdCardMountStatusChangedEvent"}, +        {45, nullptr, "GetGameCardAttachmentEvent"}, +        {46, nullptr, "GetGameCardAttachmentInfo"}, +        {47, nullptr, "GetTotalSpaceSize"}, +        {48, D<&IApplicationManagerInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"}, +        {49, nullptr, "GetSdCardRemovedEvent"}, +        {52, D<&IApplicationManagerInterface::GetGameCardUpdateDetectionEvent>, "GetGameCardUpdateDetectionEvent"}, +        {53, nullptr, "DisableApplicationAutoDelete"}, +        {54, nullptr, "EnableApplicationAutoDelete"}, +        {55, D<&IApplicationManagerInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"}, +        {56, nullptr, "SetApplicationTerminateResult"}, +        {57, nullptr, "ClearApplicationTerminateResult"}, +        {58, nullptr, "GetLastSdCardMountUnexpectedResult"}, +        {59, D<&IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"}, +        {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, +        {61, nullptr, "GetBackgroundDownloadStressTaskInfo"}, +        {62, nullptr, "GetGameCardStopper"}, +        {63, nullptr, "IsSystemProgramInstalled"}, +        {64, nullptr, "StartApplyDeltaTask"}, +        {65, nullptr, "GetRequestServerStopper"}, +        {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, +        {67, nullptr, "CancelApplicationApplyDelta"}, +        {68, nullptr, "ResumeApplicationApplyDelta"}, +        {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"}, +        {70, D<&IApplicationManagerInterface::ResumeAll>, "ResumeAll"}, +        {71, D<&IApplicationManagerInterface::GetStorageSize>, "GetStorageSize"}, +        {80, nullptr, "RequestDownloadApplication"}, +        {81, nullptr, "RequestDownloadAddOnContent"}, +        {82, nullptr, "DownloadApplication"}, +        {83, nullptr, "CheckApplicationResumeRights"}, +        {84, nullptr, "GetDynamicCommitEvent"}, +        {85, nullptr, "RequestUpdateApplication2"}, +        {86, nullptr, "EnableApplicationCrashReport"}, +        {87, nullptr, "IsApplicationCrashReportEnabled"}, +        {90, nullptr, "BoostSystemMemoryResourceLimit"}, +        {91, nullptr, "DeprecatedLaunchApplication"}, +        {92, nullptr, "GetRunningApplicationProgramId"}, +        {93, nullptr, "GetMainApplicationProgramIndex"}, +        {94, nullptr, "LaunchApplication"}, +        {95, nullptr, "GetApplicationLaunchInfo"}, +        {96, nullptr, "AcquireApplicationLaunchInfo"}, +        {97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"}, +        {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, +        {99, nullptr, "LaunchDevMenu"}, +        {100, nullptr, "ResetToFactorySettings"}, +        {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, +        {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, +        {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"}, +        {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"}, +        {105, nullptr, "RequestResetToFactorySettingsSecurely"}, +        {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"}, +        {200, nullptr, "CalculateUserSaveDataStatistics"}, +        {201, nullptr, "DeleteUserSaveDataAll"}, +        {210, nullptr, "DeleteUserSystemSaveData"}, +        {211, nullptr, "DeleteSaveData"}, +        {220, nullptr, "UnregisterNetworkServiceAccount"}, +        {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"}, +        {300, nullptr, "GetApplicationShellEvent"}, +        {301, nullptr, "PopApplicationShellEventInfo"}, +        {302, nullptr, "LaunchLibraryApplet"}, +        {303, nullptr, "TerminateLibraryApplet"}, +        {304, nullptr, "LaunchSystemApplet"}, +        {305, nullptr, "TerminateSystemApplet"}, +        {306, nullptr, "LaunchOverlayApplet"}, +        {307, nullptr, "TerminateOverlayApplet"}, +        {400, D<&IApplicationManagerInterface::GetApplicationControlData>, "GetApplicationControlData"}, +        {401, nullptr, "InvalidateAllApplicationControlCache"}, +        {402, nullptr, "RequestDownloadApplicationControlData"}, +        {403, nullptr, "GetMaxApplicationControlCacheCount"}, +        {404, nullptr, "InvalidateApplicationControlCache"}, +        {405, nullptr, "ListApplicationControlCacheEntryInfo"}, +        {406, nullptr, "GetApplicationControlProperty"}, +        {407, nullptr, "ListApplicationTitle"}, +        {408, nullptr, "ListApplicationIcon"}, +        {502, nullptr, "RequestCheckGameCardRegistration"}, +        {503, nullptr, "RequestGameCardRegistrationGoldPoint"}, +        {504, nullptr, "RequestRegisterGameCard"}, +        {505, D<&IApplicationManagerInterface::GetGameCardMountFailureEvent>, "GetGameCardMountFailureEvent"}, +        {506, nullptr, "IsGameCardInserted"}, +        {507, nullptr, "EnsureGameCardAccess"}, +        {508, nullptr, "GetLastGameCardMountFailureResult"}, +        {509, nullptr, "ListApplicationIdOnGameCard"}, +        {510, nullptr, "GetGameCardPlatformRegion"}, +        {600, nullptr, "CountApplicationContentMeta"}, +        {601, nullptr, "ListApplicationContentMetaStatus"}, +        {602, nullptr, "ListAvailableAddOnContent"}, +        {603, nullptr, "GetOwnedApplicationContentMetaStatus"}, +        {604, nullptr, "RegisterContentsExternalKey"}, +        {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, +        {606, nullptr, "GetContentMetaStorage"}, +        {607, nullptr, "ListAvailableAddOnContent"}, +        {609, nullptr, "ListAvailabilityAssuredAddOnContent"}, +        {610, nullptr, "GetInstalledContentMetaStorage"}, +        {611, nullptr, "PrepareAddOnContent"}, +        {700, nullptr, "PushDownloadTaskList"}, +        {701, nullptr, "ClearTaskStatusList"}, +        {702, nullptr, "RequestDownloadTaskList"}, +        {703, nullptr, "RequestEnsureDownloadTask"}, +        {704, nullptr, "ListDownloadTaskStatus"}, +        {705, nullptr, "RequestDownloadTaskListData"}, +        {800, nullptr, "RequestVersionList"}, +        {801, nullptr, "ListVersionList"}, +        {802, nullptr, "RequestVersionListData"}, +        {900, nullptr, "GetApplicationRecord"}, +        {901, nullptr, "GetApplicationRecordProperty"}, +        {902, nullptr, "EnableApplicationAutoUpdate"}, +        {903, nullptr, "DisableApplicationAutoUpdate"}, +        {904, nullptr, "TouchApplication"}, +        {905, nullptr, "RequestApplicationUpdate"}, +        {906, D<&IApplicationManagerInterface::IsApplicationUpdateRequested>, "IsApplicationUpdateRequested"}, +        {907, nullptr, "WithdrawApplicationUpdateRequest"}, +        {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, +        {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, +        {910, nullptr, "HasApplicationRecord"}, +        {911, nullptr, "SetPreInstalledApplication"}, +        {912, nullptr, "ClearPreInstalledApplicationFlag"}, +        {913, nullptr, "ListAllApplicationRecord"}, +        {914, nullptr, "HideApplicationRecord"}, +        {915, nullptr, "ShowApplicationRecord"}, +        {916, nullptr, "IsApplicationAutoDeleteDisabled"}, +        {1000, nullptr, "RequestVerifyApplicationDeprecated"}, +        {1001, nullptr, "CorruptApplicationForDebug"}, +        {1002, nullptr, "RequestVerifyAddOnContentsRights"}, +        {1003, nullptr, "RequestVerifyApplication"}, +        {1004, nullptr, "CorruptContentForDebug"}, +        {1200, nullptr, "NeedsUpdateVulnerability"}, +        {1300, D<&IApplicationManagerInterface::IsAnyApplicationEntityInstalled>, "IsAnyApplicationEntityInstalled"}, +        {1301, nullptr, "DeleteApplicationContentEntities"}, +        {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, +        {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, +        {1304, nullptr, "DeleteApplicationContentEntity"}, +        {1305, nullptr, "TryDeleteRunningApplicationEntity"}, +        {1306, nullptr, "TryDeleteRunningApplicationCompletely"}, +        {1307, nullptr, "TryDeleteRunningApplicationContentEntities"}, +        {1308, nullptr, "DeleteApplicationCompletelyForDebug"}, +        {1309, nullptr, "CleanupUnavailableAddOnContents"}, +        {1310, nullptr, "RequestMoveApplicationEntity"}, +        {1311, nullptr, "EstimateSizeToMove"}, +        {1312, nullptr, "HasMovableEntity"}, +        {1313, nullptr, "CleanupOrphanContents"}, +        {1314, nullptr, "CheckPreconditionSatisfiedToMove"}, +        {1400, nullptr, "PrepareShutdown"}, +        {1500, nullptr, "FormatSdCard"}, +        {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, +        {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"}, +        {1504, nullptr, "InsertSdCard"}, +        {1505, nullptr, "RemoveSdCard"}, +        {1506, nullptr, "GetSdCardStartupStatus"}, +        {1600, nullptr, "GetSystemSeedForPseudoDeviceId"}, +        {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"}, +        {1700, nullptr, "ListApplicationDownloadingContentMeta"}, +        {1701, D<&IApplicationManagerInterface::GetApplicationView>, "GetApplicationView"}, +        {1702, nullptr, "GetApplicationDownloadTaskStatus"}, +        {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, +        {1704, D<&IApplicationManagerInterface::GetApplicationViewWithPromotionInfo>, "GetApplicationViewWithPromotionInfo"}, +        {1705, nullptr, "IsPatchAutoDeletableApplication"}, +        {1800, nullptr, "IsNotificationSetupCompleted"}, +        {1801, nullptr, "GetLastNotificationInfoCount"}, +        {1802, nullptr, "ListLastNotificationInfo"}, +        {1803, nullptr, "ListNotificationTask"}, +        {1900, nullptr, "IsActiveAccount"}, +        {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, +        {1902, nullptr, "GetApplicationTicketInfo"}, +        {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"}, +        {2000, nullptr, "GetSystemDeliveryInfo"}, +        {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, +        {2002, nullptr, "VerifyDeliveryProtocolVersion"}, +        {2003, nullptr, "GetApplicationDeliveryInfo"}, +        {2004, nullptr, "HasAllContentsToDeliver"}, +        {2005, nullptr, "CompareApplicationDeliveryInfo"}, +        {2006, nullptr, "CanDeliverApplication"}, +        {2007, nullptr, "ListContentMetaKeyToDeliverApplication"}, +        {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"}, +        {2009, nullptr, "EstimateRequiredSize"}, +        {2010, nullptr, "RequestReceiveApplication"}, +        {2011, nullptr, "CommitReceiveApplication"}, +        {2012, nullptr, "GetReceiveApplicationProgress"}, +        {2013, nullptr, "RequestSendApplication"}, +        {2014, nullptr, "GetSendApplicationProgress"}, +        {2015, nullptr, "CompareSystemDeliveryInfo"}, +        {2016, nullptr, "ListNotCommittedContentMeta"}, +        {2017, nullptr, "CreateDownloadTask"}, +        {2018, nullptr, "GetApplicationDeliveryInfoHash"}, +        {2050, D<&IApplicationManagerInterface::GetApplicationRightsOnClient>, "GetApplicationRightsOnClient"}, +        {2051, nullptr, "InvalidateRightsIdCache"}, +        {2100, D<&IApplicationManagerInterface::GetApplicationTerminateResult>, "GetApplicationTerminateResult"}, +        {2101, nullptr, "GetRawApplicationTerminateResult"}, +        {2150, nullptr, "CreateRightsEnvironment"}, +        {2151, nullptr, "DestroyRightsEnvironment"}, +        {2152, nullptr, "ActivateRightsEnvironment"}, +        {2153, nullptr, "DeactivateRightsEnvironment"}, +        {2154, nullptr, "ForceActivateRightsContextForExit"}, +        {2155, nullptr, "UpdateRightsEnvironmentStatus"}, +        {2156, nullptr, "CreateRightsEnvironmentForMicroApplication"}, +        {2160, nullptr, "AddTargetApplicationToRightsEnvironment"}, +        {2161, nullptr, "SetUsersToRightsEnvironment"}, +        {2170, nullptr, "GetRightsEnvironmentStatus"}, +        {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"}, +        {2180, nullptr, "RequestExtendRightsInRightsEnvironment"}, +        {2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"}, +        {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, +        {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, +        {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, +        {2200, nullptr, "GetGameCardApplicationCopyIdentifier"}, +        {2201, nullptr, "GetInstalledApplicationCopyIdentifier"}, +        {2250, nullptr, "RequestReportActiveELicence"}, +        {2300, nullptr, "ListEventLog"}, +        {2350, nullptr, "PerformAutoUpdateByApplicationId"}, +        {2351, nullptr, "RequestNoDownloadRightsErrorResolution"}, +        {2352, nullptr, "RequestResolveNoDownloadRightsError"}, +        {2353, nullptr, "GetApplicationDownloadTaskInfo"}, +        {2354, nullptr, "PrioritizeApplicationBackgroundTask"}, +        {2355, nullptr, "PreferStorageEfficientUpdate"}, +        {2356, nullptr, "RequestStorageEfficientUpdatePreferable"}, +        {2357, nullptr, "EnableMultiCoreDownload"}, +        {2358, nullptr, "DisableMultiCoreDownload"}, +        {2359, nullptr, "IsMultiCoreDownloadEnabled"}, +        {2400, nullptr, "GetPromotionInfo"}, +        {2401, nullptr, "CountPromotionInfo"}, +        {2402, nullptr, "ListPromotionInfo"}, +        {2403, nullptr, "ImportPromotionJsonForDebug"}, +        {2404, nullptr, "ClearPromotionInfoForDebug"}, +        {2500, nullptr, "ConfirmAvailableTime"}, +        {2510, nullptr, "CreateApplicationResource"}, +        {2511, nullptr, "GetApplicationResource"}, +        {2513, nullptr, "LaunchMicroApplication"}, +        {2514, nullptr, "ClearTaskOfAsyncTaskManager"}, +        {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"}, +        {2516, nullptr, "EnsureApplicationCertificate"}, +        {2517, nullptr, "CreateApplicationInstance"}, +        {2518, nullptr, "UpdateQualificationForDebug"}, +        {2519, nullptr, "IsQualificationTransitionSupported"}, +        {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"}, +        {2521, nullptr, "GetRightsUserChangedEvent"}, +        {2522, nullptr, "IsRomRedirectionAvailable"}, +        {2800, nullptr, "GetApplicationIdOfPreomia"}, +        {3000, nullptr, "RegisterDeviceLockKey"}, +        {3001, nullptr, "UnregisterDeviceLockKey"}, +        {3002, nullptr, "VerifyDeviceLockKey"}, +        {3003, nullptr, "HideApplicationIcon"}, +        {3004, nullptr, "ShowApplicationIcon"}, +        {3005, nullptr, "HideApplicationTitle"}, +        {3006, nullptr, "ShowApplicationTitle"}, +        {3007, nullptr, "EnableGameCard"}, +        {3008, nullptr, "DisableGameCard"}, +        {3009, nullptr, "EnableLocalContentShare"}, +        {3010, nullptr, "DisableLocalContentShare"}, +        {3011, nullptr, "IsApplicationIconHidden"}, +        {3012, nullptr, "IsApplicationTitleHidden"}, +        {3013, nullptr, "IsGameCardEnabled"}, +        {3014, nullptr, "IsLocalContentShareEnabled"}, +        {3050, nullptr, "ListAssignELicenseTaskResult"}, +        {9999, nullptr, "GetApplicationCertificate"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IApplicationManagerInterface::~IApplicationManagerInterface() = default; + +Result IApplicationManagerInterface::GetApplicationControlData( +    OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size, +    ApplicationControlSource application_control_source, u64 application_id) { +    LOG_DEBUG(Service_NS, "called"); +    R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlData( +        out_buffer, out_actual_size, application_control_source, application_id)); +} + +Result IApplicationManagerInterface::GetApplicationDesiredLanguage( +    Out<ApplicationLanguage> out_desired_language, u32 supported_languages) { +    LOG_DEBUG(Service_NS, "called"); +    R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationDesiredLanguage( +        out_desired_language, supported_languages)); +} + +Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( +    Out<u64> out_language_code, ApplicationLanguage application_language) { +    LOG_DEBUG(Service_NS, "called"); +    R_RETURN( +        IReadOnlyApplicationControlDataInterface(system).ConvertApplicationLanguageToLanguageCode( +            out_language_code, application_language)); +} + +Result IApplicationManagerInterface::ListApplicationRecord( +    OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records, Out<s32> out_count, +    s32 offset) { +    const auto limit = out_records.size(); + +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    const auto& cache = system.GetContentProviderUnion(); +    const auto installed_games = cache.ListEntriesFilterOrigin( +        std::nullopt, FileSys::TitleType::Application, FileSys::ContentRecordType::Program); + +    size_t i = 0; +    u8 ii = 24; + +    for (const auto& [slot, game] : installed_games) { +        if (i >= limit) { +            break; +        } +        if (game.title_id == 0 || game.title_id < 0x0100000000001FFFull) { +            continue; +        } +        if (offset > 0) { +            offset--; +            continue; +        } + +        ApplicationRecord record{}; +        record.application_id = game.title_id; +        record.type = ApplicationRecordType::Installed; +        record.unknown = 0; // 2 = needs update +        record.unknown2 = ii++; + +        out_records[i++] = record; +    } + +    *out_count = static_cast<s32>(i); +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent( +    OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_NS, "(STUBBED) called"); + +    record_update_system_event.Signal(); +    *out_event = record_update_system_event.GetHandle(); + +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetGameCardMountFailureEvent( +    OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    *out_event = gamecard_mount_failure_event.GetHandle(); +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled( +    Out<bool> out_is_any_application_entity_installed) { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    *out_is_any_application_entity_installed = true; +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationView( +    OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views, +    InArray<u64, BufferAttr_HipcMapAlias> application_ids) { +    const auto size = std::min(out_application_views.size(), application_ids.size()); +    LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size()); + +    for (size_t i = 0; i < size; i++) { +        ApplicationView view{}; +        view.application_id = application_ids[i]; +        view.unk = 0x70000; +        view.flags = 0x401f17; + +        out_application_views[i] = view; +    } + +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo( +    OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views, +    InArray<u64, BufferAttr_HipcMapAlias> application_ids) { +    const auto size = std::min(out_application_views.size(), application_ids.size()); +    LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size()); + +    for (size_t i = 0; i < size; i++) { +        ApplicationViewWithPromotionInfo view{}; +        view.view.application_id = application_ids[i]; +        view.view.unk = 0x70000; +        view.view.flags = 0x401f17; +        view.promotion = {}; + +        out_application_views[i] = view; +    } + +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationRightsOnClient( +    OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count, +    u32 flags, u64 application_id, Uid account_id) { +    LOG_WARNING(Service_NS, "(STUBBED) called, flags={}, application_id={:016X}, account_id={}", +                flags, application_id, account_id.uuid.FormattedString()); + +    if (!out_rights.empty()) { +        ApplicationRightsOnClient rights{}; +        rights.application_id = application_id; +        rights.uid = account_id.uuid; +        rights.flags = 0; +        rights.flags2 = 0; + +        out_rights[0] = rights; +        *out_count = 1; +    } else { +        *out_count = 0; +    } + +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::CheckSdCardMountStatus() { +    LOG_DEBUG(Service_NS, "called"); +    R_RETURN(IContentManagementInterface(system).CheckSdCardMountStatus()); +} + +Result IApplicationManagerInterface::GetSdCardMountStatusChangedEvent( +    OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    *out_event = sd_card_mount_status_event.GetHandle(); +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetFreeSpaceSize(Out<s64> out_free_space_size, +                                                      FileSys::StorageId storage_id) { +    LOG_DEBUG(Service_NS, "called"); +    R_RETURN(IContentManagementInterface(system).GetFreeSpaceSize(out_free_space_size, storage_id)); +} + +Result IApplicationManagerInterface::GetGameCardUpdateDetectionEvent( +    OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    *out_event = gamecard_update_detection_event.GetHandle(); +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::ResumeAll() { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetStorageSize(Out<s64> out_total_space_size, +                                                    Out<s64> out_free_space_size, +                                                    FileSys::StorageId storage_id) { +    LOG_INFO(Service_NS, "called, storage_id={}", storage_id); +    *out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id); +    *out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id); +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::IsApplicationUpdateRequested(Out<bool> out_update_required, +                                                                  Out<u32> out_update_version, +                                                                  u64 application_id) { +    LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id); +    *out_update_required = false; +    *out_update_version = 0; +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::CheckApplicationLaunchVersion(u64 application_id) { +    LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id); +    R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationTerminateResult(Out<Result> out_result, +                                                                   u64 application_id) { +    LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id); +    *out_result = ResultSuccess; +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/application_manager_interface.h b/src/core/hle/service/ns/application_manager_interface.h new file mode 100644 index 000000000..f33d269b3 --- /dev/null +++ b/src/core/hle/service/ns/application_manager_interface.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/language.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { +public: +    explicit IApplicationManagerInterface(Core::System& system_); +    ~IApplicationManagerInterface() override; + +    Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, +                                     Out<u32> out_actual_size, +                                     ApplicationControlSource application_control_source, +                                     u64 application_id); +    Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language, +                                         u32 supported_languages); +    Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code, +                                                    ApplicationLanguage application_language); +    Result ListApplicationRecord(OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records, +                                 Out<s32> out_count, s32 offset); +    Result GetApplicationRecordUpdateSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); +    Result GetGameCardMountFailureEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); +    Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed); +    Result GetApplicationView( +        OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views, +        InArray<u64, BufferAttr_HipcMapAlias> application_ids); +    Result GetApplicationViewWithPromotionInfo( +        OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views, +        InArray<u64, BufferAttr_HipcMapAlias> application_ids); +    Result GetApplicationRightsOnClient( +        OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count, +        u32 flags, u64 application_id, Uid account_id); +    Result CheckSdCardMountStatus(); +    Result GetSdCardMountStatusChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); +    Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id); +    Result GetGameCardUpdateDetectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); +    Result ResumeAll(); +    Result GetStorageSize(Out<s64> out_total_space_size, Out<s64> out_free_space_size, +                          FileSys::StorageId storage_id); +    Result IsApplicationUpdateRequested(Out<bool> out_update_required, Out<u32> out_update_version, +                                        u64 application_id); +    Result CheckApplicationLaunchVersion(u64 application_id); +    Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id); + +private: +    KernelHelpers::ServiceContext service_context; +    Event record_update_system_event; +    Event sd_card_mount_status_event; +    Event gamecard_update_detection_event; +    Event gamecard_mount_status_event; +    Event gamecard_mount_failure_event; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/application_version_interface.cpp b/src/core/hle/service/ns/application_version_interface.cpp new file mode 100644 index 000000000..b89e127db --- /dev/null +++ b/src/core/hle/service/ns/application_version_interface.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/application_version_interface.h" + +namespace Service::NS { + +IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) +    : ServiceFramework{system_, "IApplicationVersionInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "GetLaunchRequiredVersion"}, +        {1, nullptr, "UpgradeLaunchRequiredVersion"}, +        {35, nullptr, "UpdateVersionList"}, +        {36, nullptr, "PushLaunchVersion"}, +        {37, nullptr, "ListRequiredVersion"}, +        {800, nullptr, "RequestVersionList"}, +        {801, nullptr, "ListVersionList"}, +        {802, nullptr, "RequestVersionListData"}, +        {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"}, +        {901, nullptr, "ListDefaultAutoUpdatePolicy"}, +        {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"}, +        {1000, nullptr, "PerformAutoUpdate"}, +        {1001, nullptr, "ListAutoUpdateSchedule"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IApplicationVersionInterface::~IApplicationVersionInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/application_version_interface.h b/src/core/hle/service/ns/application_version_interface.h new file mode 100644 index 000000000..b288cff1b --- /dev/null +++ b/src/core/hle/service/ns/application_version_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { +public: +    explicit IApplicationVersionInterface(Core::System& system_); +    ~IApplicationVersionInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/content_management_interface.cpp b/src/core/hle/service/ns/content_management_interface.cpp new file mode 100644 index 000000000..69bb3f6e4 --- /dev/null +++ b/src/core/hle/service/ns/content_management_interface.cpp @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/common_funcs.h" +#include "core/core.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ns/content_management_interface.h" +#include "core/hle/service/ns/ns_types.h" + +namespace Service::NS { + +IContentManagementInterface::IContentManagementInterface(Core::System& system_) +    : ServiceFramework{system_, "IContentManagementInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {11, D<&IContentManagementInterface::CalculateApplicationOccupiedSize>, "CalculateApplicationOccupiedSize"}, +        {43, D<&IContentManagementInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"}, +        {47, D<&IContentManagementInterface::GetTotalSpaceSize>, "GetTotalSpaceSize"}, +        {48, D<&IContentManagementInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"}, +        {600, nullptr, "CountApplicationContentMeta"}, +        {601, nullptr, "ListApplicationContentMetaStatus"}, +        {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, +        {607, nullptr, "IsAnyApplicationRunning"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IContentManagementInterface::~IContentManagementInterface() = default; + +Result IContentManagementInterface::CalculateApplicationOccupiedSize( +    Out<ApplicationOccupiedSize> out_size, u64 application_id) { +    LOG_WARNING(Service_NS, "(STUBBED) called, application_id={:016X}", application_id); + +    using namespace Common::Literals; + +    constexpr ApplicationOccupiedSizeEntity stub_entity{ +        .storage_id = FileSys::StorageId::SdCard, +        .app_size = 8_GiB, +        .patch_size = 2_GiB, +        .aoc_size = 12_MiB, +    }; + +    for (auto& entity : out_size->entities) { +        entity = stub_entity; +    } + +    R_SUCCEED(); +} + +Result IContentManagementInterface::CheckSdCardMountStatus() { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    R_SUCCEED(); +} + +Result IContentManagementInterface::GetTotalSpaceSize(Out<s64> out_total_space_size, +                                                      FileSys::StorageId storage_id) { +    LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id); +    *out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id); +    R_SUCCEED(); +} + +Result IContentManagementInterface::GetFreeSpaceSize(Out<s64> out_free_space_size, +                                                     FileSys::StorageId storage_id) { +    LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id); +    *out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id); +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/content_management_interface.h b/src/core/hle/service/ns/content_management_interface.h new file mode 100644 index 000000000..2894628e5 --- /dev/null +++ b/src/core/hle/service/ns/content_management_interface.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> { +public: +    explicit IContentManagementInterface(Core::System& system_); +    ~IContentManagementInterface() override; + +public: +    Result CalculateApplicationOccupiedSize(Out<ApplicationOccupiedSize> out_size, +                                            u64 application_id); +    Result CheckSdCardMountStatus(); +    Result GetTotalSpaceSize(Out<s64> out_total_space_size, FileSys::StorageId storage_id); +    Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/develop_interface.cpp b/src/core/hle/service/ns/develop_interface.cpp new file mode 100644 index 000000000..880bdbebb --- /dev/null +++ b/src/core/hle/service/ns/develop_interface.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/develop_interface.h" + +namespace Service::NS { + +IDevelopInterface::IDevelopInterface(Core::System& system_) : ServiceFramework{system_, "ns:dev"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "LaunchProgram"}, +        {1, nullptr, "TerminateProcess"}, +        {2, nullptr, "TerminateProgram"}, +        {4, nullptr, "GetShellEvent"}, +        {5, nullptr, "GetShellEventInfo"}, +        {6, nullptr, "TerminateApplication"}, +        {7, nullptr, "PrepareLaunchProgramFromHost"}, +        {8, nullptr, "LaunchApplicationFromHost"}, +        {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"}, +        {10, nullptr, "IsSystemMemoryResourceLimitBoosted"}, +        {11, nullptr, "GetRunningApplicationProcessIdForDevelop"}, +        {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"}, +        {13, nullptr, "CreateApplicationResourceForDevelop"}, +        {14, nullptr, "IsPreomiaForDevelop"}, +        {15, nullptr, "GetApplicationProgramIdFromHost"}, +        {16, nullptr, "RefreshCachedDebugValues"}, +        {17, nullptr, "PrepareLaunchApplicationFromHost"}, +        {18, nullptr, "GetLaunchEvent"}, +        {19, nullptr, "GetLaunchResult"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IDevelopInterface::~IDevelopInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/develop_interface.h b/src/core/hle/service/ns/develop_interface.h new file mode 100644 index 000000000..a9f81ccd6 --- /dev/null +++ b/src/core/hle/service/ns/develop_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDevelopInterface final : public ServiceFramework<IDevelopInterface> { +public: +    explicit IDevelopInterface(Core::System& system_); +    ~IDevelopInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/document_interface.cpp b/src/core/hle/service/ns/document_interface.cpp new file mode 100644 index 000000000..51a1e46c0 --- /dev/null +++ b/src/core/hle/service/ns/document_interface.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/document_interface.h" + +namespace Service::NS { + +IDocumentInterface::IDocumentInterface(Core::System& system_) +    : ServiceFramework{system_, "IDocumentInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {21, nullptr, "GetApplicationContentPath"}, +        {23, D<&IDocumentInterface::ResolveApplicationContentPath>, "ResolveApplicationContentPath"}, +        {92, D<&IDocumentInterface::GetRunningApplicationProgramId>, "GetRunningApplicationProgramId"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IDocumentInterface::~IDocumentInterface() = default; + +Result IDocumentInterface::ResolveApplicationContentPath(ContentPath content_path) { +    LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}", +                content_path.file_system_proxy_type, content_path.program_id); +    R_SUCCEED(); +} + +Result IDocumentInterface::GetRunningApplicationProgramId(Out<u64> out_program_id, +                                                          u64 caller_program_id) { +    LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id); +    *out_program_id = system.GetApplicationProcessProgramID(); +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/document_interface.h b/src/core/hle/service/ns/document_interface.h new file mode 100644 index 000000000..cd461652c --- /dev/null +++ b/src/core/hle/service/ns/document_interface.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { +public: +    explicit IDocumentInterface(Core::System& system_); +    ~IDocumentInterface() override; + +private: +    Result ResolveApplicationContentPath(ContentPath content_path); +    Result GetRunningApplicationProgramId(Out<u64> out_program_id, u64 caller_program_id); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/download_task_interface.cpp b/src/core/hle/service/ns/download_task_interface.cpp new file mode 100644 index 000000000..62dc7f187 --- /dev/null +++ b/src/core/hle/service/ns/download_task_interface.cpp @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/download_task_interface.h" + +namespace Service::NS { + +IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) +    : ServiceFramework{system_, "IDownloadTaskInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {701, nullptr, "ClearTaskStatusList"}, +        {702, nullptr, "RequestDownloadTaskList"}, +        {703, nullptr, "RequestEnsureDownloadTask"}, +        {704, nullptr, "ListDownloadTaskStatus"}, +        {705, nullptr, "RequestDownloadTaskListData"}, +        {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, +        {707, D<&IDownloadTaskInterface::EnableAutoCommit>, "EnableAutoCommit"}, +        {708, D<&IDownloadTaskInterface::DisableAutoCommit>, "DisableAutoCommit"}, +        {709, nullptr, "TriggerDynamicCommitEvent"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IDownloadTaskInterface::~IDownloadTaskInterface() = default; + +Result IDownloadTaskInterface::EnableAutoCommit() { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    R_SUCCEED(); +} +Result IDownloadTaskInterface::DisableAutoCommit() { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/download_task_interface.h b/src/core/hle/service/ns/download_task_interface.h new file mode 100644 index 000000000..b1cb69cb8 --- /dev/null +++ b/src/core/hle/service/ns/download_task_interface.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { +public: +    explicit IDownloadTaskInterface(Core::System& system_); +    ~IDownloadTaskInterface() override; + +private: +    Result EnableAutoCommit(); +    Result DisableAutoCommit(); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/dynamic_rights_interface.cpp b/src/core/hle/service/ns/dynamic_rights_interface.cpp new file mode 100644 index 000000000..ce81e203f --- /dev/null +++ b/src/core/hle/service/ns/dynamic_rights_interface.cpp @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/dynamic_rights_interface.h" + +namespace Service::NS { + +IDynamicRightsInterface::IDynamicRightsInterface(Core::System& system_) +    : ServiceFramework{system_, "DynamicRightsInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "RequestApplicationRightsOnServer"}, +        {1, nullptr, "RequestAssignRights"}, +        {4, nullptr, "DeprecatedRequestAssignRightsToResume"}, +        {5, D<&IDynamicRightsInterface::VerifyActivatedRightsOwners>, "VerifyActivatedRightsOwners"}, +        {6, nullptr, "DeprecatedGetApplicationRightsStatus"}, +        {7, nullptr, "RequestPrefetchForDynamicRights"}, +        {8, nullptr, "GetDynamicRightsState"}, +        {9, nullptr, "RequestApplicationRightsOnServerToResume"}, +        {10, nullptr, "RequestAssignRightsToResume"}, +        {11, nullptr, "GetActivatedRightsUsers"}, +        {12, nullptr, "GetApplicationRightsStatus"}, +        {13, D<&IDynamicRightsInterface::GetRunningApplicationStatus>, "GetRunningApplicationStatus"}, +        {14, nullptr, "SelectApplicationLicense"}, +        {15, nullptr, "RequestContentsAuthorizationToken"}, +        {16, nullptr, "QualifyUser"}, +        {17, nullptr, "QualifyUserWithProcessId"}, +        {18, D<&IDynamicRightsInterface::NotifyApplicationRightsCheckStart>, "NotifyApplicationRightsCheckStart"}, +        {19, nullptr, "UpdateUserList"}, +        {20, nullptr, "IsRightsLostUser"}, +        {21, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"}, +        {22, nullptr, "GetLimitedApplicationLicense"}, +        {23, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, +        {24, nullptr, "NotifyLimitedApplicationLicenseUpgradableEventForDebug"}, +        {25, nullptr, "RequestProceedDynamicRightsState"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IDynamicRightsInterface::~IDynamicRightsInterface() = default; + +Result IDynamicRightsInterface::NotifyApplicationRightsCheckStart() { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    R_SUCCEED(); +} + +Result IDynamicRightsInterface::GetRunningApplicationStatus(Out<u32> out_status, +                                                            u64 rights_handle) { +    LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle); +    *out_status = 0; +    R_SUCCEED(); +} + +Result IDynamicRightsInterface::VerifyActivatedRightsOwners(u64 rights_handle) { +    LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle); +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/dynamic_rights_interface.h b/src/core/hle/service/ns/dynamic_rights_interface.h new file mode 100644 index 000000000..877e009b0 --- /dev/null +++ b/src/core/hle/service/ns/dynamic_rights_interface.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDynamicRightsInterface final : public ServiceFramework<IDynamicRightsInterface> { +public: +    explicit IDynamicRightsInterface(Core::System& system_); +    ~IDynamicRightsInterface() override; + +private: +    Result NotifyApplicationRightsCheckStart(); +    Result GetRunningApplicationStatus(Out<u32> out_status, u64 rights_handle); +    Result VerifyActivatedRightsOwners(u64 rights_handle); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/ecommerce_interface.cpp b/src/core/hle/service/ns/ecommerce_interface.cpp new file mode 100644 index 000000000..76fc425f0 --- /dev/null +++ b/src/core/hle/service/ns/ecommerce_interface.cpp @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/ecommerce_interface.h" + +namespace Service::NS { + +IECommerceInterface::IECommerceInterface(Core::System& system_) +    : ServiceFramework{system_, "IECommerceInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "RequestLinkDevice"}, +        {1, nullptr, "RequestCleanupAllPreInstalledApplications"}, +        {2, nullptr, "RequestCleanupPreInstalledApplication"}, +        {3, nullptr, "RequestSyncRights"}, +        {4, nullptr, "RequestUnlinkDevice"}, +        {5, nullptr, "RequestRevokeAllELicense"}, +        {6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IECommerceInterface::~IECommerceInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/ecommerce_interface.h b/src/core/hle/service/ns/ecommerce_interface.h new file mode 100644 index 000000000..4352101f4 --- /dev/null +++ b/src/core/hle/service/ns/ecommerce_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { +public: +    explicit IECommerceInterface(Core::System& system_); +    ~IECommerceInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/factory_reset_interface.cpp b/src/core/hle/service/ns/factory_reset_interface.cpp new file mode 100644 index 000000000..fd5cf7e1f --- /dev/null +++ b/src/core/hle/service/ns/factory_reset_interface.cpp @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/factory_reset_interface.h" + +namespace Service::NS { + +IFactoryResetInterface::IFactoryResetInterface(Core::System& system_) +    : ServiceFramework{system_, "IFactoryResetInterface"} { +    // clang-format off +        static const FunctionInfo functions[] = { +            {100, nullptr, "ResetToFactorySettings"}, +            {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, +            {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, +            {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"}, +            {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"}, +            {105, nullptr, "RequestResetToFactorySettingsSecurely"}, +            {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"}, +        }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IFactoryResetInterface::~IFactoryResetInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/factory_reset_interface.h b/src/core/hle/service/ns/factory_reset_interface.h new file mode 100644 index 000000000..50d125123 --- /dev/null +++ b/src/core/hle/service/ns/factory_reset_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { +public: +    explicit IFactoryResetInterface(Core::System& system_); +    ~IFactoryResetInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 19c3ff01b..8402e83cb 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -1,893 +1,38 @@  // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/logging/log.h" -#include "common/settings.h" -#include "core/arm/debug.h" -#include "core/core.h" -#include "core/file_sys/control_metadata.h" -#include "core/file_sys/patch_manager.h" -#include "core/file_sys/vfs/vfs.h" -#include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/glue/glue_manager.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ns/errors.h" -#include "core/hle/service/ns/iplatform_service_manager.h" -#include "core/hle/service/ns/language.h" +#include "core/hle/service/ns/develop_interface.h"  #include "core/hle/service/ns/ns.h" -#include "core/hle/service/ns/pdm_qry.h" +#include "core/hle/service/ns/platform_service_manager.h" +#include "core/hle/service/ns/query_service.h" +#include "core/hle/service/ns/service_getter_interface.h" +#include "core/hle/service/ns/system_update_interface.h" +#include "core/hle/service/ns/vulnerability_manager_interface.h"  #include "core/hle/service/server_manager.h" -#include "core/hle/service/set/settings_server.h"  namespace Service::NS { -IAccountProxyInterface::IAccountProxyInterface(Core::System& system_) -    : ServiceFramework{system_, "IAccountProxyInterface"} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {0, nullptr, "CreateUserAccount"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IAccountProxyInterface::~IAccountProxyInterface() = default; - -IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_) -    : ServiceFramework{system_, "IApplicationManagerInterface"} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {0, nullptr, "ListApplicationRecord"}, -        {1, nullptr, "GenerateApplicationRecordCount"}, -        {2, nullptr, "GetApplicationRecordUpdateSystemEvent"}, -        {3, nullptr, "GetApplicationViewDeprecated"}, -        {4, nullptr, "DeleteApplicationEntity"}, -        {5, nullptr, "DeleteApplicationCompletely"}, -        {6, nullptr, "IsAnyApplicationEntityRedundant"}, -        {7, nullptr, "DeleteRedundantApplicationEntity"}, -        {8, nullptr, "IsApplicationEntityMovable"}, -        {9, nullptr, "MoveApplicationEntity"}, -        {11, nullptr, "CalculateApplicationOccupiedSize"}, -        {16, nullptr, "PushApplicationRecord"}, -        {17, nullptr, "ListApplicationRecordContentMeta"}, -        {19, nullptr, "LaunchApplicationOld"}, -        {21, nullptr, "GetApplicationContentPath"}, -        {22, nullptr, "TerminateApplication"}, -        {23, nullptr, "ResolveApplicationContentPath"}, -        {26, nullptr, "BeginInstallApplication"}, -        {27, nullptr, "DeleteApplicationRecord"}, -        {30, nullptr, "RequestApplicationUpdateInfo"}, -        {31, nullptr, "Unknown31"}, -        {32, nullptr, "CancelApplicationDownload"}, -        {33, nullptr, "ResumeApplicationDownload"}, -        {35, nullptr, "UpdateVersionList"}, -        {36, nullptr, "PushLaunchVersion"}, -        {37, nullptr, "ListRequiredVersion"}, -        {38, nullptr, "CheckApplicationLaunchVersion"}, -        {39, nullptr, "CheckApplicationLaunchRights"}, -        {40, nullptr, "GetApplicationLogoData"}, -        {41, nullptr, "CalculateApplicationDownloadRequiredSize"}, -        {42, nullptr, "CleanupSdCard"}, -        {43, nullptr, "CheckSdCardMountStatus"}, -        {44, nullptr, "GetSdCardMountStatusChangedEvent"}, -        {45, nullptr, "GetGameCardAttachmentEvent"}, -        {46, nullptr, "GetGameCardAttachmentInfo"}, -        {47, nullptr, "GetTotalSpaceSize"}, -        {48, nullptr, "GetFreeSpaceSize"}, -        {49, nullptr, "GetSdCardRemovedEvent"}, -        {52, nullptr, "GetGameCardUpdateDetectionEvent"}, -        {53, nullptr, "DisableApplicationAutoDelete"}, -        {54, nullptr, "EnableApplicationAutoDelete"}, -        {55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"}, -        {56, nullptr, "SetApplicationTerminateResult"}, -        {57, nullptr, "ClearApplicationTerminateResult"}, -        {58, nullptr, "GetLastSdCardMountUnexpectedResult"}, -        {59, &IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode, "ConvertApplicationLanguageToLanguageCode"}, -        {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, -        {61, nullptr, "GetBackgroundDownloadStressTaskInfo"}, -        {62, nullptr, "GetGameCardStopper"}, -        {63, nullptr, "IsSystemProgramInstalled"}, -        {64, nullptr, "StartApplyDeltaTask"}, -        {65, nullptr, "GetRequestServerStopper"}, -        {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, -        {67, nullptr, "CancelApplicationApplyDelta"}, -        {68, nullptr, "ResumeApplicationApplyDelta"}, -        {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"}, -        {70, nullptr, "ResumeAll"}, -        {71, nullptr, "GetStorageSize"}, -        {80, nullptr, "RequestDownloadApplication"}, -        {81, nullptr, "RequestDownloadAddOnContent"}, -        {82, nullptr, "DownloadApplication"}, -        {83, nullptr, "CheckApplicationResumeRights"}, -        {84, nullptr, "GetDynamicCommitEvent"}, -        {85, nullptr, "RequestUpdateApplication2"}, -        {86, nullptr, "EnableApplicationCrashReport"}, -        {87, nullptr, "IsApplicationCrashReportEnabled"}, -        {90, nullptr, "BoostSystemMemoryResourceLimit"}, -        {91, nullptr, "DeprecatedLaunchApplication"}, -        {92, nullptr, "GetRunningApplicationProgramId"}, -        {93, nullptr, "GetMainApplicationProgramIndex"}, -        {94, nullptr, "LaunchApplication"}, -        {95, nullptr, "GetApplicationLaunchInfo"}, -        {96, nullptr, "AcquireApplicationLaunchInfo"}, -        {97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"}, -        {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, -        {99, nullptr, "LaunchDevMenu"}, -        {100, nullptr, "ResetToFactorySettings"}, -        {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, -        {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, -        {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"}, -        {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"}, -        {105, nullptr, "RequestResetToFactorySettingsSecurely"}, -        {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"}, -        {200, nullptr, "CalculateUserSaveDataStatistics"}, -        {201, nullptr, "DeleteUserSaveDataAll"}, -        {210, nullptr, "DeleteUserSystemSaveData"}, -        {211, nullptr, "DeleteSaveData"}, -        {220, nullptr, "UnregisterNetworkServiceAccount"}, -        {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"}, -        {300, nullptr, "GetApplicationShellEvent"}, -        {301, nullptr, "PopApplicationShellEventInfo"}, -        {302, nullptr, "LaunchLibraryApplet"}, -        {303, nullptr, "TerminateLibraryApplet"}, -        {304, nullptr, "LaunchSystemApplet"}, -        {305, nullptr, "TerminateSystemApplet"}, -        {306, nullptr, "LaunchOverlayApplet"}, -        {307, nullptr, "TerminateOverlayApplet"}, -        {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, -        {401, nullptr, "InvalidateAllApplicationControlCache"}, -        {402, nullptr, "RequestDownloadApplicationControlData"}, -        {403, nullptr, "GetMaxApplicationControlCacheCount"}, -        {404, nullptr, "InvalidateApplicationControlCache"}, -        {405, nullptr, "ListApplicationControlCacheEntryInfo"}, -        {406, nullptr, "GetApplicationControlProperty"}, -        {407, nullptr, "ListApplicationTitle"}, -        {408, nullptr, "ListApplicationIcon"}, -        {502, nullptr, "RequestCheckGameCardRegistration"}, -        {503, nullptr, "RequestGameCardRegistrationGoldPoint"}, -        {504, nullptr, "RequestRegisterGameCard"}, -        {505, nullptr, "GetGameCardMountFailureEvent"}, -        {506, nullptr, "IsGameCardInserted"}, -        {507, nullptr, "EnsureGameCardAccess"}, -        {508, nullptr, "GetLastGameCardMountFailureResult"}, -        {509, nullptr, "ListApplicationIdOnGameCard"}, -        {510, nullptr, "GetGameCardPlatformRegion"}, -        {600, nullptr, "CountApplicationContentMeta"}, -        {601, nullptr, "ListApplicationContentMetaStatus"}, -        {602, nullptr, "ListAvailableAddOnContent"}, -        {603, nullptr, "GetOwnedApplicationContentMetaStatus"}, -        {604, nullptr, "RegisterContentsExternalKey"}, -        {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, -        {606, nullptr, "GetContentMetaStorage"}, -        {607, nullptr, "ListAvailableAddOnContent"}, -        {609, nullptr, "ListAvailabilityAssuredAddOnContent"}, -        {610, nullptr, "GetInstalledContentMetaStorage"}, -        {611, nullptr, "PrepareAddOnContent"}, -        {700, nullptr, "PushDownloadTaskList"}, -        {701, nullptr, "ClearTaskStatusList"}, -        {702, nullptr, "RequestDownloadTaskList"}, -        {703, nullptr, "RequestEnsureDownloadTask"}, -        {704, nullptr, "ListDownloadTaskStatus"}, -        {705, nullptr, "RequestDownloadTaskListData"}, -        {800, nullptr, "RequestVersionList"}, -        {801, nullptr, "ListVersionList"}, -        {802, nullptr, "RequestVersionListData"}, -        {900, nullptr, "GetApplicationRecord"}, -        {901, nullptr, "GetApplicationRecordProperty"}, -        {902, nullptr, "EnableApplicationAutoUpdate"}, -        {903, nullptr, "DisableApplicationAutoUpdate"}, -        {904, nullptr, "TouchApplication"}, -        {905, nullptr, "RequestApplicationUpdate"}, -        {906, nullptr, "IsApplicationUpdateRequested"}, -        {907, nullptr, "WithdrawApplicationUpdateRequest"}, -        {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, -        {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, -        {910, nullptr, "HasApplicationRecord"}, -        {911, nullptr, "SetPreInstalledApplication"}, -        {912, nullptr, "ClearPreInstalledApplicationFlag"}, -        {913, nullptr, "ListAllApplicationRecord"}, -        {914, nullptr, "HideApplicationRecord"}, -        {915, nullptr, "ShowApplicationRecord"}, -        {916, nullptr, "IsApplicationAutoDeleteDisabled"}, -        {1000, nullptr, "RequestVerifyApplicationDeprecated"}, -        {1001, nullptr, "CorruptApplicationForDebug"}, -        {1002, nullptr, "RequestVerifyAddOnContentsRights"}, -        {1003, nullptr, "RequestVerifyApplication"}, -        {1004, nullptr, "CorruptContentForDebug"}, -        {1200, nullptr, "NeedsUpdateVulnerability"}, -        {1300, nullptr, "IsAnyApplicationEntityInstalled"}, -        {1301, nullptr, "DeleteApplicationContentEntities"}, -        {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, -        {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, -        {1304, nullptr, "DeleteApplicationContentEntity"}, -        {1305, nullptr, "TryDeleteRunningApplicationEntity"}, -        {1306, nullptr, "TryDeleteRunningApplicationCompletely"}, -        {1307, nullptr, "TryDeleteRunningApplicationContentEntities"}, -        {1308, nullptr, "DeleteApplicationCompletelyForDebug"}, -        {1309, nullptr, "CleanupUnavailableAddOnContents"}, -        {1310, nullptr, "RequestMoveApplicationEntity"}, -        {1311, nullptr, "EstimateSizeToMove"}, -        {1312, nullptr, "HasMovableEntity"}, -        {1313, nullptr, "CleanupOrphanContents"}, -        {1314, nullptr, "CheckPreconditionSatisfiedToMove"}, -        {1400, nullptr, "PrepareShutdown"}, -        {1500, nullptr, "FormatSdCard"}, -        {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, -        {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"}, -        {1504, nullptr, "InsertSdCard"}, -        {1505, nullptr, "RemoveSdCard"}, -        {1506, nullptr, "GetSdCardStartupStatus"}, -        {1600, nullptr, "GetSystemSeedForPseudoDeviceId"}, -        {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"}, -        {1700, nullptr, "ListApplicationDownloadingContentMeta"}, -        {1701, nullptr, "GetApplicationView"}, -        {1702, nullptr, "GetApplicationDownloadTaskStatus"}, -        {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, -        {1704, nullptr, "GetApplicationViewWithPromotionInfo"}, -        {1705, nullptr, "IsPatchAutoDeletableApplication"}, -        {1800, nullptr, "IsNotificationSetupCompleted"}, -        {1801, nullptr, "GetLastNotificationInfoCount"}, -        {1802, nullptr, "ListLastNotificationInfo"}, -        {1803, nullptr, "ListNotificationTask"}, -        {1900, nullptr, "IsActiveAccount"}, -        {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, -        {1902, nullptr, "GetApplicationTicketInfo"}, -        {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"}, -        {2000, nullptr, "GetSystemDeliveryInfo"}, -        {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, -        {2002, nullptr, "VerifyDeliveryProtocolVersion"}, -        {2003, nullptr, "GetApplicationDeliveryInfo"}, -        {2004, nullptr, "HasAllContentsToDeliver"}, -        {2005, nullptr, "CompareApplicationDeliveryInfo"}, -        {2006, nullptr, "CanDeliverApplication"}, -        {2007, nullptr, "ListContentMetaKeyToDeliverApplication"}, -        {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"}, -        {2009, nullptr, "EstimateRequiredSize"}, -        {2010, nullptr, "RequestReceiveApplication"}, -        {2011, nullptr, "CommitReceiveApplication"}, -        {2012, nullptr, "GetReceiveApplicationProgress"}, -        {2013, nullptr, "RequestSendApplication"}, -        {2014, nullptr, "GetSendApplicationProgress"}, -        {2015, nullptr, "CompareSystemDeliveryInfo"}, -        {2016, nullptr, "ListNotCommittedContentMeta"}, -        {2017, nullptr, "CreateDownloadTask"}, -        {2018, nullptr, "GetApplicationDeliveryInfoHash"}, -        {2050, nullptr, "GetApplicationRightsOnClient"}, -        {2051, nullptr, "InvalidateRightsIdCache"}, -        {2100, nullptr, "GetApplicationTerminateResult"}, -        {2101, nullptr, "GetRawApplicationTerminateResult"}, -        {2150, nullptr, "CreateRightsEnvironment"}, -        {2151, nullptr, "DestroyRightsEnvironment"}, -        {2152, nullptr, "ActivateRightsEnvironment"}, -        {2153, nullptr, "DeactivateRightsEnvironment"}, -        {2154, nullptr, "ForceActivateRightsContextForExit"}, -        {2155, nullptr, "UpdateRightsEnvironmentStatus"}, -        {2156, nullptr, "CreateRightsEnvironmentForMicroApplication"}, -        {2160, nullptr, "AddTargetApplicationToRightsEnvironment"}, -        {2161, nullptr, "SetUsersToRightsEnvironment"}, -        {2170, nullptr, "GetRightsEnvironmentStatus"}, -        {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"}, -        {2180, nullptr, "RequestExtendRightsInRightsEnvironment"}, -        {2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"}, -        {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, -        {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, -        {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, -        {2200, nullptr, "GetGameCardApplicationCopyIdentifier"}, -        {2201, nullptr, "GetInstalledApplicationCopyIdentifier"}, -        {2250, nullptr, "RequestReportActiveELicence"}, -        {2300, nullptr, "ListEventLog"}, -        {2350, nullptr, "PerformAutoUpdateByApplicationId"}, -        {2351, nullptr, "RequestNoDownloadRightsErrorResolution"}, -        {2352, nullptr, "RequestResolveNoDownloadRightsError"}, -        {2353, nullptr, "GetApplicationDownloadTaskInfo"}, -        {2354, nullptr, "PrioritizeApplicationBackgroundTask"}, -        {2355, nullptr, "PreferStorageEfficientUpdate"}, -        {2356, nullptr, "RequestStorageEfficientUpdatePreferable"}, -        {2357, nullptr, "EnableMultiCoreDownload"}, -        {2358, nullptr, "DisableMultiCoreDownload"}, -        {2359, nullptr, "IsMultiCoreDownloadEnabled"}, -        {2400, nullptr, "GetPromotionInfo"}, -        {2401, nullptr, "CountPromotionInfo"}, -        {2402, nullptr, "ListPromotionInfo"}, -        {2403, nullptr, "ImportPromotionJsonForDebug"}, -        {2404, nullptr, "ClearPromotionInfoForDebug"}, -        {2500, nullptr, "ConfirmAvailableTime"}, -        {2510, nullptr, "CreateApplicationResource"}, -        {2511, nullptr, "GetApplicationResource"}, -        {2513, nullptr, "LaunchMicroApplication"}, -        {2514, nullptr, "ClearTaskOfAsyncTaskManager"}, -        {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"}, -        {2516, nullptr, "EnsureApplicationCertificate"}, -        {2517, nullptr, "CreateApplicationInstance"}, -        {2518, nullptr, "UpdateQualificationForDebug"}, -        {2519, nullptr, "IsQualificationTransitionSupported"}, -        {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"}, -        {2521, nullptr, "GetRightsUserChangedEvent"}, -        {2522, nullptr, "IsRomRedirectionAvailable"}, -        {2800, nullptr, "GetApplicationIdOfPreomia"}, -        {3000, nullptr, "RegisterDeviceLockKey"}, -        {3001, nullptr, "UnregisterDeviceLockKey"}, -        {3002, nullptr, "VerifyDeviceLockKey"}, -        {3003, nullptr, "HideApplicationIcon"}, -        {3004, nullptr, "ShowApplicationIcon"}, -        {3005, nullptr, "HideApplicationTitle"}, -        {3006, nullptr, "ShowApplicationTitle"}, -        {3007, nullptr, "EnableGameCard"}, -        {3008, nullptr, "DisableGameCard"}, -        {3009, nullptr, "EnableLocalContentShare"}, -        {3010, nullptr, "DisableLocalContentShare"}, -        {3011, nullptr, "IsApplicationIconHidden"}, -        {3012, nullptr, "IsApplicationTitleHidden"}, -        {3013, nullptr, "IsGameCardEnabled"}, -        {3014, nullptr, "IsLocalContentShareEnabled"}, -        {3050, nullptr, "ListAssignELicenseTaskResult"}, -        {9999, nullptr, "GetApplicationCertificate"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IApplicationManagerInterface::~IApplicationManagerInterface() = default; - -void IApplicationManagerInterface::GetApplicationControlData(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const auto flag = rp.PopRaw<u64>(); -    LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); - -    const auto title_id = rp.PopRaw<u64>(); - -    const auto size = ctx.GetWriteBufferSize(); - -    const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), -                                   system.GetContentProvider()}; -    const auto control = pm.GetControlMetadata(); - -    std::vector<u8> out; - -    if (control.first != nullptr) { -        if (size < 0x4000) { -            LOG_ERROR(Service_NS, -                      "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size); -            IPC::ResponseBuilder rb{ctx, 2}; -            // TODO(DarkLordZach): Find a better error code for this. -            rb.Push(ResultUnknown); -            return; -        } - -        out.resize(0x4000); -        const auto bytes = control.first->GetRawBytes(); -        std::memcpy(out.data(), bytes.data(), bytes.size()); -    } else { -        LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", -                    title_id); -        out.resize(std::min<u64>(0x4000, size)); -    } - -    if (control.second != nullptr) { -        if (size < 0x4000 + control.second->GetSize()) { -            LOG_ERROR(Service_NS, -                      "output buffer is too small! (actual={:016X}, expected_min={:016X})", size, -                      0x4000 + control.second->GetSize()); -            IPC::ResponseBuilder rb{ctx, 2}; -            // TODO(DarkLordZach): Find a better error code for this. -            rb.Push(ResultUnknown); -            return; -        } - -        out.resize(0x4000 + control.second->GetSize()); -        control.second->Read(out.data() + 0x4000, control.second->GetSize()); -    } else { -        LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", -                    title_id); -    } - -    ctx.WriteBuffer(out); - -    IPC::ResponseBuilder rb{ctx, 3}; -    rb.Push(ResultSuccess); -    rb.Push<u32>(static_cast<u32>(out.size())); -} - -void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const auto supported_languages = rp.Pop<u32>(); - -    u8 desired_language{}; -    const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages); -    if (res == ResultSuccess) { -        IPC::ResponseBuilder rb{ctx, 3}; -        rb.Push(ResultSuccess); -        rb.Push<u32>(desired_language); -    } else { -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(res); -    } -} - -Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language, -                                                                   const u32 supported_languages) { -    LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); - -    // Get language code from settings -    const auto language_code = -        Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue())); - -    // Convert to application language, get priority list -    const auto application_language = ConvertToApplicationLanguage(language_code); -    if (application_language == std::nullopt) { -        LOG_ERROR(Service_NS, "Could not convert application language! language_code={}", -                  language_code); -        return Service::NS::ResultApplicationLanguageNotFound; -    } -    const auto priority_list = GetApplicationLanguagePriorityList(*application_language); -    if (!priority_list) { -        LOG_ERROR(Service_NS, -                  "Could not find application language priorities! application_language={}", -                  *application_language); -        return Service::NS::ResultApplicationLanguageNotFound; -    } - -    // Try to find a valid language. -    for (const auto lang : *priority_list) { -        const auto supported_flag = GetSupportedLanguageFlag(lang); -        if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { -            *out_desired_language = static_cast<u8>(lang); -            return ResultSuccess; -        } -    } - -    LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}", -              supported_languages); -    return Service::NS::ResultApplicationLanguageNotFound; -} - -void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( -    HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const auto application_language = rp.Pop<u8>(); - -    u64 language_code{}; -    const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language); -    if (res == ResultSuccess) { -        IPC::ResponseBuilder rb{ctx, 4}; -        rb.Push(ResultSuccess); -        rb.Push(language_code); -    } else { -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(res); -    } -} - -Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( -    u64* out_language_code, u8 application_language) { -    const auto language_code = -        ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); -    if (language_code == std::nullopt) { -        LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language); -        return Service::NS::ResultApplicationLanguageNotFound; -    } - -    *out_language_code = static_cast<u64>(*language_code); -    return ResultSuccess; -} - -IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) -    : ServiceFramework{system_, "IApplicationVersionInterface"} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {0, nullptr, "GetLaunchRequiredVersion"}, -        {1, nullptr, "UpgradeLaunchRequiredVersion"}, -        {35, nullptr, "UpdateVersionList"}, -        {36, nullptr, "PushLaunchVersion"}, -        {37, nullptr, "ListRequiredVersion"}, -        {800, nullptr, "RequestVersionList"}, -        {801, nullptr, "ListVersionList"}, -        {802, nullptr, "RequestVersionListData"}, -        {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"}, -        {901, nullptr, "ListDefaultAutoUpdatePolicy"}, -        {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"}, -        {1000, nullptr, "PerformAutoUpdate"}, -        {1001, nullptr, "ListAutoUpdateSchedule"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IApplicationVersionInterface::~IApplicationVersionInterface() = default; - -IContentManagementInterface::IContentManagementInterface(Core::System& system_) -    : ServiceFramework{system_, "IContentManagementInterface"} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {11, nullptr, "CalculateApplicationOccupiedSize"}, -        {43, nullptr, "CheckSdCardMountStatus"}, -        {47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"}, -        {48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"}, -        {600, nullptr, "CountApplicationContentMeta"}, -        {601, nullptr, "ListApplicationContentMetaStatus"}, -        {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, -        {607, nullptr, "IsAnyApplicationRunning"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IContentManagementInterface::~IContentManagementInterface() = default; - -void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const auto storage{rp.PopEnum<FileSys::StorageId>()}; - -    LOG_INFO(Service_Capture, "called, storage={}", storage); - -    IPC::ResponseBuilder rb{ctx, 4}; -    rb.Push(ResultSuccess); -    rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage)); -} - -void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const auto storage{rp.PopEnum<FileSys::StorageId>()}; - -    LOG_INFO(Service_Capture, "called, storage={}", storage); - -    IPC::ResponseBuilder rb{ctx, 4}; -    rb.Push(ResultSuccess); -    rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage)); -} - -IDocumentInterface::IDocumentInterface(Core::System& system_) -    : ServiceFramework{system_, "IDocumentInterface"} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {21, nullptr, "GetApplicationContentPath"}, -        {23, &IDocumentInterface::ResolveApplicationContentPath, "ResolveApplicationContentPath"}, -        {92, &IDocumentInterface::GetRunningApplicationProgramId, "GetRunningApplicationProgramId"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IDocumentInterface::~IDocumentInterface() = default; - -void IDocumentInterface::ResolveApplicationContentPath(HLERequestContext& ctx) { -    struct ContentPath { -        u8 file_system_proxy_type; -        u64 program_id; -    }; -    static_assert(sizeof(ContentPath) == 0x10, "ContentPath has wrong size"); - -    IPC::RequestParser rp{ctx}; -    auto content_path = rp.PopRaw<ContentPath>(); -    LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}", -                content_path.file_system_proxy_type, content_path.program_id); - -    IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); -} - -void IDocumentInterface::GetRunningApplicationProgramId(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const auto caller_program_id = rp.PopRaw<u64>(); -    LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id); - -    IPC::ResponseBuilder rb{ctx, 4}; -    rb.Push(ResultSuccess); -    rb.Push<u64>(system.GetApplicationProcessProgramID()); -} - -IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) -    : ServiceFramework{system_, "IDownloadTaskInterface"} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {701, nullptr, "ClearTaskStatusList"}, -        {702, nullptr, "RequestDownloadTaskList"}, -        {703, nullptr, "RequestEnsureDownloadTask"}, -        {704, nullptr, "ListDownloadTaskStatus"}, -        {705, nullptr, "RequestDownloadTaskListData"}, -        {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, -        {707, nullptr, "EnableAutoCommit"}, -        {708, nullptr, "DisableAutoCommit"}, -        {709, nullptr, "TriggerDynamicCommitEvent"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IDownloadTaskInterface::~IDownloadTaskInterface() = default; - -IECommerceInterface::IECommerceInterface(Core::System& system_) -    : ServiceFramework{system_, "IECommerceInterface"} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {0, nullptr, "RequestLinkDevice"}, -        {1, nullptr, "RequestCleanupAllPreInstalledApplications"}, -        {2, nullptr, "RequestCleanupPreInstalledApplication"}, -        {3, nullptr, "RequestSyncRights"}, -        {4, nullptr, "RequestUnlinkDevice"}, -        {5, nullptr, "RequestRevokeAllELicense"}, -        {6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IECommerceInterface::~IECommerceInterface() = default; - -IFactoryResetInterface::IFactoryResetInterface(Core::System& system_) -    : ServiceFramework{system_, "IFactoryResetInterface"} { -    // clang-format off -        static const FunctionInfo functions[] = { -            {100, nullptr, "ResetToFactorySettings"}, -            {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, -            {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, -            {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"}, -            {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"}, -            {105, nullptr, "RequestResetToFactorySettingsSecurely"}, -            {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"}, -        }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IFactoryResetInterface::~IFactoryResetInterface() = default; - -IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_) -    : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} { -    static const FunctionInfo functions[] = { -        {0, &IReadOnlyApplicationRecordInterface::HasApplicationRecord, "HasApplicationRecord"}, -        {1, nullptr, "NotifyApplicationFailure"}, -        {2, &IReadOnlyApplicationRecordInterface::IsDataCorruptedResult, "IsDataCorruptedResult"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default; - -void IReadOnlyApplicationRecordInterface::HasApplicationRecord(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const u64 program_id = rp.PopRaw<u64>(); -    LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:X}", program_id); - -    IPC::ResponseBuilder rb{ctx, 3}; -    rb.Push(ResultSuccess); -    rb.Push<u8>(1); -} - -void IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const auto result = rp.PopRaw<Result>(); -    LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue()); - -    IPC::ResponseBuilder rb{ctx, 3}; -    rb.Push(ResultSuccess); -    rb.Push<u8>(0); -} - -IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface( -    Core::System& system_) -    : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"}, -        {1, nullptr, "GetApplicationDesiredLanguage"}, -        {2, nullptr, "ConvertApplicationLanguageToLanguageCode"}, -        {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, -        {4, nullptr, "SelectApplicationDesiredLanguage"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default; - -void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequestContext& ctx) { -    enum class ApplicationControlSource : u8 { -        CacheOnly, -        Storage, -        StorageOnly, -    }; - -    struct RequestParameters { -        ApplicationControlSource source; -        u64 application_id; -    }; -    static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); - -    IPC::RequestParser rp{ctx}; -    std::vector<u8> nacp_data{}; -    const auto parameters{rp.PopRaw<RequestParameters>()}; -    const auto result = -        system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id); - -    if (result == ResultSuccess) { -        ctx.WriteBuffer(nacp_data.data(), nacp_data.size()); -    } - -    IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(result); -} - -NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { -    // clang-format off -    static const FunctionInfo functions[] = { -        {7988, nullptr, "GetDynamicRightsInterface"}, -        {7989, &NS::PushInterface<IReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"}, -        {7991, &NS::PushInterface<IReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"}, -        {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, -        {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, -        {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, -        {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, -        {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"}, -        {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, -        {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"}, -        {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, -    }; -    // clang-format on - -    RegisterHandlers(functions); -} - -NS::~NS() = default; - -std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const { -    return GetInterface<IApplicationManagerInterface>(system); -} - -class NS_DEV final : public ServiceFramework<NS_DEV> { -public: -    explicit NS_DEV(Core::System& system_) : ServiceFramework{system_, "ns:dev"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "LaunchProgram"}, -            {1, nullptr, "TerminateProcess"}, -            {2, nullptr, "TerminateProgram"}, -            {4, nullptr, "GetShellEvent"}, -            {5, nullptr, "GetShellEventInfo"}, -            {6, nullptr, "TerminateApplication"}, -            {7, nullptr, "PrepareLaunchProgramFromHost"}, -            {8, nullptr, "LaunchApplicationFromHost"}, -            {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"}, -            {10, nullptr, "IsSystemMemoryResourceLimitBoosted"}, -            {11, nullptr, "GetRunningApplicationProcessIdForDevelop"}, -            {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"}, -            {13, nullptr, "CreateApplicationResourceForDevelop"}, -            {14, nullptr, "IsPreomiaForDevelop"}, -            {15, nullptr, "GetApplicationProgramIdFromHost"}, -            {16, nullptr, "RefreshCachedDebugValues"}, -            {17, nullptr, "PrepareLaunchApplicationFromHost"}, -            {18, nullptr, "GetLaunchEvent"}, -            {19, nullptr, "GetLaunchResult"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } -}; - -class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> { -public: -    explicit ISystemUpdateControl(Core::System& system_) -        : ServiceFramework{system_, "ISystemUpdateControl"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "HasDownloaded"}, -            {1, nullptr, "RequestCheckLatestUpdate"}, -            {2, nullptr, "RequestDownloadLatestUpdate"}, -            {3, nullptr, "GetDownloadProgress"}, -            {4, nullptr, "ApplyDownloadedUpdate"}, -            {5, nullptr, "RequestPrepareCardUpdate"}, -            {6, nullptr, "GetPrepareCardUpdateProgress"}, -            {7, nullptr, "HasPreparedCardUpdate"}, -            {8, nullptr, "ApplyCardUpdate"}, -            {9, nullptr, "GetDownloadedEulaDataSize"}, -            {10, nullptr, "GetDownloadedEulaData"}, -            {11, nullptr, "SetupCardUpdate"}, -            {12, nullptr, "GetPreparedCardUpdateEulaDataSize"}, -            {13, nullptr, "GetPreparedCardUpdateEulaData"}, -            {14, nullptr, "SetupCardUpdateViaSystemUpdater"}, -            {15, nullptr, "HasReceived"}, -            {16, nullptr, "RequestReceiveSystemUpdate"}, -            {17, nullptr, "GetReceiveProgress"}, -            {18, nullptr, "ApplyReceivedUpdate"}, -            {19, nullptr, "GetReceivedEulaDataSize"}, -            {20, nullptr, "GetReceivedEulaData"}, -            {21, nullptr, "SetupToReceiveSystemUpdate"}, -            {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } -}; - -class NS_SU final : public ServiceFramework<NS_SU> { -public: -    explicit NS_SU(Core::System& system_) : ServiceFramework{system_, "ns:su"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "GetBackgroundNetworkUpdateState"}, -            {1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"}, -            {2, nullptr, "NotifyExFatDriverRequired"}, -            {3, nullptr, "ClearExFatDriverStatusForDebug"}, -            {4, nullptr, "RequestBackgroundNetworkUpdate"}, -            {5, nullptr, "NotifyBackgroundNetworkUpdate"}, -            {6, nullptr, "NotifyExFatDriverDownloadedForDebug"}, -            {9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"}, -            {10, nullptr, "NotifySystemUpdateForContentDelivery"}, -            {11, nullptr, "PrepareShutdown"}, -            {12, nullptr, "Unknown12"}, -            {13, nullptr, "Unknown13"}, -            {14, nullptr, "Unknown14"}, -            {15, nullptr, "Unknown15"}, -            {16, nullptr, "DestroySystemUpdateTask"}, -            {17, nullptr, "RequestSendSystemUpdate"}, -            {18, nullptr, "GetSendSystemUpdateProgress"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } - -private: -    void OpenSystemUpdateControl(HLERequestContext& ctx) { -        LOG_DEBUG(Service_NS, "called"); - -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(ResultSuccess); -        rb.PushIpcInterface<ISystemUpdateControl>(system); -    } -}; - -class NS_VM final : public ServiceFramework<NS_VM> { -public: -    explicit NS_VM(Core::System& system_) : ServiceFramework{system_, "ns:vm"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {1200, &NS_VM::NeedsUpdateVulnerability, "NeedsUpdateVulnerability"}, -            {1201, nullptr, "UpdateSafeSystemVersionForDebug"}, -            {1202, nullptr, "GetSafeSystemVersion"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } - -private: -    void NeedsUpdateVulnerability(HLERequestContext& ctx) { -        LOG_WARNING(Service_NS, "(STUBBED) called"); - -        IPC::ResponseBuilder rb{ctx, 3}; -        rb.Push(ResultSuccess); -        rb.Push(false); -    } -}; -  void LoopProcess(Core::System& system) {      auto server_manager = std::make_unique<ServerManager>(system); -    server_manager->RegisterNamedService("ns:am2", std::make_shared<NS>("ns:am2", system)); -    server_manager->RegisterNamedService("ns:ec", std::make_shared<NS>("ns:ec", system)); -    server_manager->RegisterNamedService("ns:rid", std::make_shared<NS>("ns:rid", system)); -    server_manager->RegisterNamedService("ns:rt", std::make_shared<NS>("ns:rt", system)); -    server_manager->RegisterNamedService("ns:web", std::make_shared<NS>("ns:web", system)); -    server_manager->RegisterNamedService("ns:ro", std::make_shared<NS>("ns:ro", system)); - -    server_manager->RegisterNamedService("ns:dev", std::make_shared<NS_DEV>(system)); -    server_manager->RegisterNamedService("ns:su", std::make_shared<NS_SU>(system)); -    server_manager->RegisterNamedService("ns:vm", std::make_shared<NS_VM>(system)); -    server_manager->RegisterNamedService("pdm:qry", std::make_shared<PDM_QRY>(system)); +    server_manager->RegisterNamedService( +        "ns:am2", std::make_shared<IServiceGetterInterface>(system, "ns:am2")); +    server_manager->RegisterNamedService( +        "ns:ec", std::make_shared<IServiceGetterInterface>(system, "ns:ec")); +    server_manager->RegisterNamedService( +        "ns:rid", std::make_shared<IServiceGetterInterface>(system, "ns:rid")); +    server_manager->RegisterNamedService( +        "ns:rt", std::make_shared<IServiceGetterInterface>(system, "ns:rt")); +    server_manager->RegisterNamedService( +        "ns:web", std::make_shared<IServiceGetterInterface>(system, "ns:web")); +    server_manager->RegisterNamedService( +        "ns:ro", std::make_shared<IServiceGetterInterface>(system, "ns:ro")); + +    server_manager->RegisterNamedService("ns:dev", std::make_shared<IDevelopInterface>(system)); +    server_manager->RegisterNamedService("ns:su", std::make_shared<ISystemUpdateInterface>(system)); +    server_manager->RegisterNamedService("ns:vm", +                                         std::make_shared<IVulnerabilityManagerInterface>(system)); +    server_manager->RegisterNamedService("pdm:qry", std::make_shared<IQueryService>(system));      server_manager->RegisterNamedService("pl:s",                                           std::make_shared<IPlatformServiceManager>(system, "pl:s")); diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 9ee306ef9..f79b4ae3d 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -3,141 +3,12 @@  #pragma once -#include "core/hle/service/service.h" -  namespace Core {  class System;  } -namespace Service { - -namespace FileSystem { -class FileSystemController; -} // namespace FileSystem - -namespace NS { - -class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { -public: -    explicit IAccountProxyInterface(Core::System& system_); -    ~IAccountProxyInterface() override; -}; - -class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { -public: -    explicit IApplicationManagerInterface(Core::System& system_); -    ~IApplicationManagerInterface() override; - -    Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages); -    Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code, -                                                    u8 application_language); - -private: -    void GetApplicationControlData(HLERequestContext& ctx); -    void GetApplicationDesiredLanguage(HLERequestContext& ctx); -    void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx); -}; - -class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { -public: -    explicit IApplicationVersionInterface(Core::System& system_); -    ~IApplicationVersionInterface() override; -}; - -class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> { -public: -    explicit IContentManagementInterface(Core::System& system_); -    ~IContentManagementInterface() override; - -private: -    void GetTotalSpaceSize(HLERequestContext& ctx); -    void GetFreeSpaceSize(HLERequestContext& ctx); -}; - -class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { -public: -    explicit IDocumentInterface(Core::System& system_); -    ~IDocumentInterface() override; - -private: -    void ResolveApplicationContentPath(HLERequestContext& ctx); -    void GetRunningApplicationProgramId(HLERequestContext& ctx); -}; - -class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { -public: -    explicit IDownloadTaskInterface(Core::System& system_); -    ~IDownloadTaskInterface() override; -}; - -class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { -public: -    explicit IECommerceInterface(Core::System& system_); -    ~IECommerceInterface() override; -}; - -class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { -public: -    explicit IFactoryResetInterface(Core::System& system_); -    ~IFactoryResetInterface() override; -}; - -class IReadOnlyApplicationRecordInterface final -    : public ServiceFramework<IReadOnlyApplicationRecordInterface> { -public: -    explicit IReadOnlyApplicationRecordInterface(Core::System& system_); -    ~IReadOnlyApplicationRecordInterface() override; - -private: -    void HasApplicationRecord(HLERequestContext& ctx); -    void IsDataCorruptedResult(HLERequestContext& ctx); -}; - -class IReadOnlyApplicationControlDataInterface final -    : public ServiceFramework<IReadOnlyApplicationControlDataInterface> { -public: -    explicit IReadOnlyApplicationControlDataInterface(Core::System& system_); -    ~IReadOnlyApplicationControlDataInterface() override; - -private: -    void GetApplicationControlData(HLERequestContext& ctx); -}; - -class NS final : public ServiceFramework<NS> { -public: -    explicit NS(const char* name, Core::System& system_); -    ~NS() override; - -    std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const; - -private: -    template <typename T, typename... Args> -    void PushInterface(HLERequestContext& ctx) { -        LOG_DEBUG(Service_NS, "called"); - -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(ResultSuccess); -        rb.PushIpcInterface<T>(system); -    } - -    void PushIApplicationManagerInterface(HLERequestContext& ctx) { -        LOG_DEBUG(Service_NS, "called"); - -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(ResultSuccess); -        rb.PushIpcInterface<IApplicationManagerInterface>(system); -    } - -    template <typename T, typename... Args> -    std::shared_ptr<T> GetInterface(Args&&... args) const { -        static_assert(std::is_base_of_v<SessionRequestHandler, T>, -                      "Not a base of ServiceFrameworkBase"); - -        return std::make_shared<T>(std::forward<Args>(args)...); -    } -}; +namespace Service::NS {  void LoopProcess(Core::System& system); -} // namespace NS -} // namespace Service +} // namespace Service::NS diff --git a/src/core/hle/service/ns/errors.h b/src/core/hle/service/ns/ns_results.h index 16d2ea6f7..16d2ea6f7 100644 --- a/src/core/hle/service/ns/errors.h +++ b/src/core/hle/service/ns/ns_results.h diff --git a/src/core/hle/service/ns/ns_types.h b/src/core/hle/service/ns/ns_types.h new file mode 100644 index 000000000..2dd664c4e --- /dev/null +++ b/src/core/hle/service/ns/ns_types.h @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_funcs.h" +#include "common/uuid.h" +#include "core/file_sys/romfs_factory.h" + +namespace Service::NS { + +enum class ApplicationRecordType : u8 { +    Installing = 2, +    Installed = 3, +    GameCardNotInserted = 5, +    Archived = 11, +    GameCard = 16, +}; + +enum class ApplicationControlSource : u8 { +    CacheOnly = 0, +    Storage = 1, +    StorageOnly = 2, +}; + +enum class BackgroundNetworkUpdateState : u8 { +    None, +    InProgress, +    Ready, +}; + +struct ApplicationRecord { +    u64 application_id; +    ApplicationRecordType type; +    u8 unknown; +    INSERT_PADDING_BYTES_NOINIT(0x6); +    u8 unknown2; +    INSERT_PADDING_BYTES_NOINIT(0x7); +}; +static_assert(sizeof(ApplicationRecord) == 0x18, "ApplicationRecord has incorrect size."); + +/// ApplicationView +struct ApplicationView { +    u64 application_id;           ///< ApplicationId. +    u32 unk;                      ///< Unknown. +    u32 flags;                    ///< Flags. +    std::array<u8, 0x10> unk_x10; ///< Unknown. +    u32 unk_x20;                  ///< Unknown. +    u16 unk_x24;                  ///< Unknown. +    std::array<u8, 0x2> unk_x26;  ///< Unknown. +    std::array<u8, 0x8> unk_x28;  ///< Unknown. +    std::array<u8, 0x10> unk_x30; ///< Unknown. +    u32 unk_x40;                  ///< Unknown. +    u8 unk_x44;                   ///< Unknown. +    std::array<u8, 0xb> unk_x45;  ///< Unknown. +}; +static_assert(sizeof(ApplicationView) == 0x50, "ApplicationView has incorrect size."); + +struct ApplicationRightsOnClient { +    u64 application_id; +    Common::UUID uid; +    u8 flags; +    u8 flags2; +    INSERT_PADDING_BYTES_NOINIT(0x6); +}; +static_assert(sizeof(ApplicationRightsOnClient) == 0x20, +              "ApplicationRightsOnClient has incorrect size."); + +/// NsPromotionInfo +struct PromotionInfo { +    u64 start_timestamp; ///< POSIX timestamp for the promotion start. +    u64 end_timestamp;   ///< POSIX timestamp for the promotion end. +    s64 remaining_time;  ///< Remaining time until the promotion ends, in nanoseconds +                         ///< ({end_timestamp - current_time} converted to nanoseconds). +    INSERT_PADDING_BYTES_NOINIT(0x4); +    u8 flags; ///< Flags. Bit0: whether the PromotionInfo is valid (including bit1). Bit1 clear: +              ///< remaining_time is set. +    INSERT_PADDING_BYTES_NOINIT(0x3); +}; +static_assert(sizeof(PromotionInfo) == 0x20, "PromotionInfo has incorrect size."); + +/// NsApplicationViewWithPromotionInfo +struct ApplicationViewWithPromotionInfo { +    ApplicationView view;    ///< \ref NsApplicationView +    PromotionInfo promotion; ///< \ref NsPromotionInfo +}; +static_assert(sizeof(ApplicationViewWithPromotionInfo) == 0x70, +              "ApplicationViewWithPromotionInfo has incorrect size."); + +struct ApplicationOccupiedSizeEntity { +    FileSys::StorageId storage_id; +    u64 app_size; +    u64 patch_size; +    u64 aoc_size; +}; +static_assert(sizeof(ApplicationOccupiedSizeEntity) == 0x20, +              "ApplicationOccupiedSizeEntity has incorrect size."); + +struct ApplicationOccupiedSize { +    std::array<ApplicationOccupiedSizeEntity, 4> entities; +}; +static_assert(sizeof(ApplicationOccupiedSize) == 0x80, +              "ApplicationOccupiedSize has incorrect size."); + +struct ContentPath { +    u8 file_system_proxy_type; +    u64 program_id; +}; +static_assert(sizeof(ContentPath) == 0x10, "ContentPath has incorrect size."); + +struct Uid { +    alignas(8) Common::UUID uuid; +}; +static_assert(sizeof(Uid) == 0x10, "Uid has incorrect size."); + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/pdm_qry.cpp b/src/core/hle/service/ns/pdm_qry.cpp deleted file mode 100644 index ce0ee30e0..000000000 --- a/src/core/hle/service/ns/pdm_qry.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <memory> - -#include "common/logging/log.h" -#include "common/uuid.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ns/pdm_qry.h" -#include "core/hle/service/service.h" - -namespace Service::NS { - -PDM_QRY::PDM_QRY(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} { -    // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "QueryAppletEvent"}, -            {1, nullptr, "QueryPlayStatistics"}, -            {2, nullptr, "QueryPlayStatisticsByUserAccountId"}, -            {3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"}, -            {4, nullptr, "QueryPlayStatisticsByApplicationId"}, -            {5, &PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId, "QueryPlayStatisticsByApplicationIdAndUserAccountId"}, -            {6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"}, -            {7, nullptr, "QueryLastPlayTimeV0"}, -            {8, nullptr, "QueryPlayEvent"}, -            {9, nullptr, "GetAvailablePlayEventRange"}, -            {10, nullptr, "QueryAccountEvent"}, -            {11, nullptr, "QueryAccountPlayEvent"}, -            {12, nullptr, "GetAvailableAccountPlayEventRange"}, -            {13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"}, -            {14, nullptr, "QueryRecentlyPlayedApplication"}, -            {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"}, -            {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"}, -            {17, nullptr, "QueryLastPlayTime"}, -            {18, nullptr, "QueryApplicationPlayStatisticsForSystem"}, -            {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"}, -        }; -    // clang-format on - -    RegisterHandlers(functions); -} - -PDM_QRY::~PDM_QRY() = default; - -void PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const auto unknown = rp.Pop<bool>(); -    rp.Pop<u8>(); // Padding -    const auto application_id = rp.Pop<u64>(); -    const auto user_account_uid = rp.PopRaw<Common::UUID>(); - -    // TODO(German77): Read statistics of the game -    PlayStatistics statistics{ -        .application_id = application_id, -        .total_launches = 1, -    }; - -    LOG_WARNING(Service_NS, -                "(STUBBED) called. unknown={}. application_id=0x{:016X}, user_account_uid=0x{}", -                unknown, application_id, user_account_uid.RawString()); - -    IPC::ResponseBuilder rb{ctx, 12}; -    rb.Push(ResultSuccess); -    rb.PushRaw(statistics); -} - -} // namespace Service::NS diff --git a/src/core/hle/service/ns/iplatform_service_manager.cpp b/src/core/hle/service/ns/platform_service_manager.cpp index 46268be95..23cf05005 100644 --- a/src/core/hle/service/ns/iplatform_service_manager.cpp +++ b/src/core/hle/service/ns/platform_service_manager.cpp @@ -18,9 +18,9 @@  #include "core/hle/kernel/k_shared_memory.h"  #include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/physical_memory.h" +#include "core/hle/service/cmif_serialization.h"  #include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ns/iplatform_service_manager.h" +#include "core/hle/service/ns/platform_service_manager.h"  namespace Service::NS { @@ -37,11 +37,6 @@ constexpr u32 EXPECTED_MAGIC{0x36f81a1e};  // What we expect the encrypted bfttf  constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000};  constexpr FontRegion EMPTY_REGION{0, 0}; -enum class LoadState : u32 { -    Loading = 0, -    Done = 1, -}; -  static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMemory& output,                                std::size_t& offset) {      ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE, @@ -138,13 +133,13 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch      : ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} {      // clang-format off      static const FunctionInfo functions[] = { -        {0, &IPlatformServiceManager::RequestLoad, "RequestLoad"}, -        {1, &IPlatformServiceManager::GetLoadState, "GetLoadState"}, -        {2, &IPlatformServiceManager::GetSize, "GetSize"}, -        {3, &IPlatformServiceManager::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"}, -        {4, &IPlatformServiceManager::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, -        {5, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"}, -        {6, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriorityForSystem"}, +        {0, D<&IPlatformServiceManager::RequestLoad>, "RequestLoad"}, +        {1, D<&IPlatformServiceManager::GetLoadState>, "GetLoadState"}, +        {2, D<&IPlatformServiceManager::GetSize>, "GetSize"}, +        {3, D<&IPlatformServiceManager::GetSharedMemoryAddressOffset>, "GetSharedMemoryAddressOffset"}, +        {4, D<&IPlatformServiceManager::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"}, +        {5, D<&IPlatformServiceManager::GetSharedFontInOrderOfPriority>, "GetSharedFontInOrderOfPriority"}, +        {6, D<&IPlatformServiceManager::GetSharedFontInOrderOfPriority>, "GetSharedFontInOrderOfPriorityForSystem"},          {100, nullptr, "RequestApplicationFunctionAuthorization"},          {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},          {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"}, @@ -208,47 +203,33 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch  IPlatformServiceManager::~IPlatformServiceManager() = default; -void IPlatformServiceManager::RequestLoad(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const u32 shared_font_type{rp.Pop<u32>()}; +Result IPlatformServiceManager::RequestLoad(SharedFontType type) {      // Games don't call this so all fonts should be loaded -    LOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type); - -    IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); +    R_SUCCEED();  } -void IPlatformServiceManager::GetLoadState(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const u32 font_id{rp.Pop<u32>()}; -    LOG_DEBUG(Service_NS, "called, font_id={}", font_id); - -    IPC::ResponseBuilder rb{ctx, 3}; -    rb.Push(ResultSuccess); -    rb.Push<u32>(static_cast<u32>(LoadState::Done)); +Result IPlatformServiceManager::GetLoadState(Out<LoadState> out_load_state, SharedFontType type) { +    LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); +    *out_load_state = LoadState::Loaded; +    R_SUCCEED();  } -void IPlatformServiceManager::GetSize(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const u32 font_id{rp.Pop<u32>()}; -    LOG_DEBUG(Service_NS, "called, font_id={}", font_id); - -    IPC::ResponseBuilder rb{ctx, 3}; -    rb.Push(ResultSuccess); -    rb.Push<u32>(impl->GetSharedFontRegion(font_id).size); +Result IPlatformServiceManager::GetSize(Out<u32> out_size, SharedFontType type) { +    LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); +    *out_size = impl->GetSharedFontRegion(static_cast<size_t>(type)).size; +    R_SUCCEED();  } -void IPlatformServiceManager::GetSharedMemoryAddressOffset(HLERequestContext& ctx) { -    IPC::RequestParser rp{ctx}; -    const u32 font_id{rp.Pop<u32>()}; -    LOG_DEBUG(Service_NS, "called, font_id={}", font_id); - -    IPC::ResponseBuilder rb{ctx, 3}; -    rb.Push(ResultSuccess); -    rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset); +Result IPlatformServiceManager::GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset, +                                                             SharedFontType type) { +    LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); +    *out_shared_memory_offset = impl->GetSharedFontRegion(static_cast<size_t>(type)).offset; +    R_SUCCEED();  } -void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx) { +Result IPlatformServiceManager::GetSharedMemoryNativeHandle( +    OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle) {      // Map backing memory for the font data      LOG_DEBUG(Service_NS, "called"); @@ -256,50 +237,37 @@ void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx      std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(),                  impl->shared_font->size()); -    IPC::ResponseBuilder rb{ctx, 2, 1}; -    rb.Push(ResultSuccess); -    rb.PushCopyObjects(&kernel.GetFontSharedMem()); +    // FIXME: this shouldn't belong to the kernel +    *out_shared_memory_native_handle = &kernel.GetFontSharedMem(); +    R_SUCCEED();  } -void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext& ctx) { +Result IPlatformServiceManager::GetSharedFontInOrderOfPriority( +    OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes, +    OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets, +    OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes, Out<bool> out_fonts_are_loaded, +    Out<u32> out_font_count, Set::LanguageCode language_code) { +    LOG_DEBUG(Service_NS, "called, language_code={:#x}", language_code); +      // The maximum number of elements that can be returned is 6. Regardless of the available fonts      // or buffer size. -    constexpr std::size_t MaxElementCount = 6; -    IPC::RequestParser rp{ctx}; -    const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for -    const std::size_t font_codes_count = -        std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(0)); -    const std::size_t font_offsets_count = -        std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(1)); -    const std::size_t font_sizes_count = -        std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(2)); -    LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code); - -    IPC::ResponseBuilder rb{ctx, 4}; -    std::vector<u32> font_codes; -    std::vector<u32> font_offsets; -    std::vector<u32> font_sizes; +    constexpr size_t MaxElementCount = 6;      // TODO(ogniK): Have actual priority order -    for (std::size_t i = 0; i < impl->shared_font_regions.size(); i++) { -        font_codes.push_back(static_cast<u32>(i)); -        auto region = impl->GetSharedFontRegion(i); -        font_offsets.push_back(region.offset); -        font_sizes.push_back(region.size); -    } +    const auto max_size = std::min({MaxElementCount, out_font_codes.size(), out_font_offsets.size(), +                                    out_font_sizes.size(), impl->shared_font_regions.size()}); -    // Resize buffers if game requests smaller size output -    font_codes.resize(std::min(font_codes.size(), font_codes_count)); -    font_offsets.resize(std::min(font_offsets.size(), font_offsets_count)); -    font_sizes.resize(std::min(font_sizes.size(), font_sizes_count)); +    for (size_t i = 0; i < max_size; i++) { +        auto region = impl->GetSharedFontRegion(i); -    ctx.WriteBuffer(font_codes, 0); -    ctx.WriteBuffer(font_offsets, 1); -    ctx.WriteBuffer(font_sizes, 2); +        out_font_codes[i] = static_cast<u32>(i); +        out_font_offsets[i] = region.offset; +        out_font_sizes[i] = region.size; +    } -    rb.Push(ResultSuccess); -    rb.Push<u8>(static_cast<u8>(LoadState::Done)); // Fonts Loaded -    rb.Push<u32>(static_cast<u32>(font_codes.size())); +    *out_fonts_are_loaded = true; +    *out_font_count = static_cast<u32>(max_size); +    R_SUCCEED();  }  } // namespace Service::NS diff --git a/src/core/hle/service/ns/iplatform_service_manager.h b/src/core/hle/service/ns/platform_service_manager.h index 03071e02b..b82c385a6 100644 --- a/src/core/hle/service/ns/iplatform_service_manager.h +++ b/src/core/hle/service/ns/platform_service_manager.h @@ -5,7 +5,9 @@  #include <memory>  #include <vector> +#include "core/hle/service/cmif_types.h"  #include "core/hle/service/service.h" +#include "core/hle/service/set/settings_types.h"  namespace Service { @@ -23,6 +25,20 @@ enum class FontArchives : u64 {      ChineseSimple = 0x0100000000000814,  }; +enum class SharedFontType : u32 { +    JapanUSEuropeStandard = 0, +    ChineseSimplified = 1, +    ExtendedChineseSimplified = 2, +    ChineseTraditional = 3, +    KoreanHangul = 4, +    NintendoExtended = 5, +}; + +enum class LoadState : u32 { +    Loading = 0, +    Loaded = 1, +}; +  constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{      std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"),      std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"), @@ -42,12 +58,17 @@ public:      ~IPlatformServiceManager() override;  private: -    void RequestLoad(HLERequestContext& ctx); -    void GetLoadState(HLERequestContext& ctx); -    void GetSize(HLERequestContext& ctx); -    void GetSharedMemoryAddressOffset(HLERequestContext& ctx); -    void GetSharedMemoryNativeHandle(HLERequestContext& ctx); -    void GetSharedFontInOrderOfPriority(HLERequestContext& ctx); +    Result RequestLoad(SharedFontType type); +    Result GetLoadState(Out<LoadState> out_load_state, SharedFontType type); +    Result GetSize(Out<u32> out_size, SharedFontType type); +    Result GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset, SharedFontType type); +    Result GetSharedMemoryNativeHandle( +        OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle); +    Result GetSharedFontInOrderOfPriority(OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes, +                                          OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets, +                                          OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes, +                                          Out<bool> out_fonts_are_loaded, Out<u32> out_font_count, +                                          Set::LanguageCode language_code);      struct Impl;      std::unique_ptr<Impl> impl; diff --git a/src/core/hle/service/ns/query_service.cpp b/src/core/hle/service/ns/query_service.cpp new file mode 100644 index 000000000..138400541 --- /dev/null +++ b/src/core/hle/service/ns/query_service.cpp @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "common/uuid.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/query_service.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +IQueryService::IQueryService(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "QueryAppletEvent"}, +        {1, nullptr, "QueryPlayStatistics"}, +        {2, nullptr, "QueryPlayStatisticsByUserAccountId"}, +        {3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"}, +        {4, nullptr, "QueryPlayStatisticsByApplicationId"}, +        {5, D<&IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId>, "QueryPlayStatisticsByApplicationIdAndUserAccountId"}, +        {6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"}, +        {7, nullptr, "QueryLastPlayTimeV0"}, +        {8, nullptr, "QueryPlayEvent"}, +        {9, nullptr, "GetAvailablePlayEventRange"}, +        {10, nullptr, "QueryAccountEvent"}, +        {11, nullptr, "QueryAccountPlayEvent"}, +        {12, nullptr, "GetAvailableAccountPlayEventRange"}, +        {13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"}, +        {14, nullptr, "QueryRecentlyPlayedApplication"}, +        {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"}, +        {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"}, +        {17, nullptr, "QueryLastPlayTime"}, +        {18, nullptr, "QueryApplicationPlayStatisticsForSystem"}, +        {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IQueryService::~IQueryService() = default; + +Result IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId( +    Out<PlayStatistics> out_play_statistics, bool unknown, u64 application_id, Uid account_id) { +    // TODO(German77): Read statistics of the game +    *out_play_statistics = { +        .application_id = application_id, +        .total_launches = 1, +    }; + +    LOG_WARNING(Service_NS, "(STUBBED) called. unknown={}. application_id={:016X}, account_id={}", +                unknown, application_id, account_id.uuid.FormattedString()); +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/pdm_qry.h b/src/core/hle/service/ns/query_service.h index c98e01660..c4c82b752 100644 --- a/src/core/hle/service/ns/pdm_qry.h +++ b/src/core/hle/service/ns/query_service.h @@ -3,6 +3,9 @@  #pragma once +#include "common/uuid.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/ns_types.h"  #include "core/hle/service/service.h"  namespace Service::NS { @@ -20,13 +23,14 @@ struct PlayStatistics {  };  static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size"); -class PDM_QRY final : public ServiceFramework<PDM_QRY> { +class IQueryService final : public ServiceFramework<IQueryService> {  public: -    explicit PDM_QRY(Core::System& system_); -    ~PDM_QRY() override; +    explicit IQueryService(Core::System& system_); +    ~IQueryService() override;  private: -    void QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx); +    Result QueryPlayStatisticsByApplicationIdAndUserAccountId( +        Out<PlayStatistics> out_play_statistics, bool unknown, u64 application_id, Uid account_id);  };  } // namespace Service::NS diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp new file mode 100644 index 000000000..9b2ca94a4 --- /dev/null +++ b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp @@ -0,0 +1,122 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/vfs/vfs.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/language.h" +#include "core/hle/service/ns/ns_results.h" +#include "core/hle/service/ns/read_only_application_control_data_interface.h" +#include "core/hle/service/set/settings_server.h" + +namespace Service::NS { + +IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface( +    Core::System& system_) +    : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData>, "GetApplicationControlData"}, +        {1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"}, +        {2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"}, +        {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, +        {4, nullptr, "SelectApplicationDesiredLanguage"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default; + +Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData( +    OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size, +    ApplicationControlSource application_control_source, u64 application_id) { +    LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}", +             application_control_source, application_id); + +    const FileSys::PatchManager pm{application_id, system.GetFileSystemController(), +                                   system.GetContentProvider()}; +    const auto control = pm.GetControlMetadata(); +    const auto size = out_buffer.size(); + +    const auto icon_size = control.second ? control.second->GetSize() : 0; +    const auto total_size = sizeof(FileSys::RawNACP) + icon_size; + +    if (size < total_size) { +        LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)", +                  size); +        R_THROW(ResultUnknown); +    } + +    if (control.first != nullptr) { +        const auto bytes = control.first->GetRawBytes(); +        std::memcpy(out_buffer.data(), bytes.data(), bytes.size()); +    } else { +        LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero", +                    application_id); +        std::memset(out_buffer.data(), 0, sizeof(FileSys::RawNACP)); +    } + +    if (control.second != nullptr) { +        control.second->Read(out_buffer.data() + sizeof(FileSys::RawNACP), icon_size); +    } else { +        LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id); +    } + +    *out_actual_size = static_cast<u32>(total_size); +    R_SUCCEED(); +} + +Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage( +    Out<ApplicationLanguage> out_desired_language, u32 supported_languages) { +    LOG_INFO(Service_NS, "called with supported_languages={:08X}", supported_languages); + +    // Get language code from settings +    const auto language_code = +        Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue())); + +    // Convert to application language, get priority list +    const auto application_language = ConvertToApplicationLanguage(language_code); +    if (application_language == std::nullopt) { +        LOG_ERROR(Service_NS, "Could not convert application language! language_code={}", +                  language_code); +        R_THROW(Service::NS::ResultApplicationLanguageNotFound); +    } +    const auto priority_list = GetApplicationLanguagePriorityList(*application_language); +    if (!priority_list) { +        LOG_ERROR(Service_NS, +                  "Could not find application language priorities! application_language={}", +                  *application_language); +        R_THROW(Service::NS::ResultApplicationLanguageNotFound); +    } + +    // Try to find a valid language. +    for (const auto lang : *priority_list) { +        const auto supported_flag = GetSupportedLanguageFlag(lang); +        if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { +            *out_desired_language = lang; +            R_SUCCEED(); +        } +    } + +    LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}", +              supported_languages); +    R_THROW(Service::NS::ResultApplicationLanguageNotFound); +} + +Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode( +    Out<u64> out_language_code, ApplicationLanguage application_language) { +    const auto language_code = ConvertToLanguageCode(application_language); +    if (language_code == std::nullopt) { +        LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language); +        R_THROW(Service::NS::ResultApplicationLanguageNotFound); +    } + +    *out_language_code = static_cast<u64>(*language_code); +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.h b/src/core/hle/service/ns/read_only_application_control_data_interface.h new file mode 100644 index 000000000..ac099435a --- /dev/null +++ b/src/core/hle/service/ns/read_only_application_control_data_interface.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/language.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IReadOnlyApplicationControlDataInterface final +    : public ServiceFramework<IReadOnlyApplicationControlDataInterface> { +public: +    explicit IReadOnlyApplicationControlDataInterface(Core::System& system_); +    ~IReadOnlyApplicationControlDataInterface() override; + +public: +    Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, +                                     Out<u32> out_actual_size, +                                     ApplicationControlSource application_control_source, +                                     u64 application_id); +    Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language, +                                         u32 supported_languages); +    Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code, +                                                    ApplicationLanguage application_language); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/read_only_application_record_interface.cpp b/src/core/hle/service/ns/read_only_application_record_interface.cpp new file mode 100644 index 000000000..816a1e1dc --- /dev/null +++ b/src/core/hle/service/ns/read_only_application_record_interface.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/read_only_application_record_interface.h" + +namespace Service::NS { + +IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_) +    : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} { +    static const FunctionInfo functions[] = { +        {0, D<&IReadOnlyApplicationRecordInterface::HasApplicationRecord>, "HasApplicationRecord"}, +        {1, nullptr, "NotifyApplicationFailure"}, +        {2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>, +         "IsDataCorruptedResult"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default; + +Result IReadOnlyApplicationRecordInterface::HasApplicationRecord( +    Out<bool> out_has_application_record, u64 program_id) { +    LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:016X}", program_id); +    *out_has_application_record = true; +    R_SUCCEED(); +} + +Result IReadOnlyApplicationRecordInterface::IsDataCorruptedResult( +    Out<bool> out_is_data_corrupted_result, Result result) { +    LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue()); +    *out_is_data_corrupted_result = false; +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/read_only_application_record_interface.h b/src/core/hle/service/ns/read_only_application_record_interface.h new file mode 100644 index 000000000..d06e8f5e6 --- /dev/null +++ b/src/core/hle/service/ns/read_only_application_record_interface.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IReadOnlyApplicationRecordInterface final +    : public ServiceFramework<IReadOnlyApplicationRecordInterface> { +public: +    explicit IReadOnlyApplicationRecordInterface(Core::System& system_); +    ~IReadOnlyApplicationRecordInterface() override; + +private: +    Result HasApplicationRecord(Out<bool> out_has_application_record, u64 program_id); +    Result IsDataCorruptedResult(Out<bool> out_is_data_corrupted_result, Result result); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/service_getter_interface.cpp b/src/core/hle/service/ns/service_getter_interface.cpp new file mode 100644 index 000000000..1a3dd7166 --- /dev/null +++ b/src/core/hle/service/ns/service_getter_interface.cpp @@ -0,0 +1,120 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/account_proxy_interface.h" +#include "core/hle/service/ns/application_manager_interface.h" +#include "core/hle/service/ns/application_version_interface.h" +#include "core/hle/service/ns/content_management_interface.h" +#include "core/hle/service/ns/document_interface.h" +#include "core/hle/service/ns/download_task_interface.h" +#include "core/hle/service/ns/dynamic_rights_interface.h" +#include "core/hle/service/ns/ecommerce_interface.h" +#include "core/hle/service/ns/factory_reset_interface.h" +#include "core/hle/service/ns/read_only_application_control_data_interface.h" +#include "core/hle/service/ns/read_only_application_record_interface.h" +#include "core/hle/service/ns/service_getter_interface.h" + +namespace Service::NS { + +IServiceGetterInterface::IServiceGetterInterface(Core::System& system_, const char* name) +    : ServiceFramework{system_, name} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {7988, D<&IServiceGetterInterface::GetDynamicRightsInterface>, "GetDynamicRightsInterface"}, +        {7989, D<&IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"}, +        {7991, D<&IServiceGetterInterface::GetReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"}, +        {7992, D<&IServiceGetterInterface::GetECommerceInterface>, "GetECommerceInterface"}, +        {7993, D<&IServiceGetterInterface::GetApplicationVersionInterface>, "GetApplicationVersionInterface"}, +        {7994, D<&IServiceGetterInterface::GetFactoryResetInterface>, "GetFactoryResetInterface"}, +        {7995, D<&IServiceGetterInterface::GetAccountProxyInterface>, "GetAccountProxyInterface"}, +        {7996, D<&IServiceGetterInterface::GetApplicationManagerInterface>, "GetApplicationManagerInterface"}, +        {7997, D<&IServiceGetterInterface::GetDownloadTaskInterface>, "GetDownloadTaskInterface"}, +        {7998, D<&IServiceGetterInterface::GetContentManagementInterface>, "GetContentManagementInterface"}, +        {7999, D<&IServiceGetterInterface::GetDocumentInterface>, "GetDocumentInterface"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IServiceGetterInterface::~IServiceGetterInterface() = default; + +Result IServiceGetterInterface::GetDynamicRightsInterface( +    Out<SharedPointer<IDynamicRightsInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IDynamicRightsInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface( +    Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IReadOnlyApplicationControlDataInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetReadOnlyApplicationRecordInterface( +    Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IReadOnlyApplicationRecordInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetECommerceInterface( +    Out<SharedPointer<IECommerceInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IECommerceInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetApplicationVersionInterface( +    Out<SharedPointer<IApplicationVersionInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IApplicationVersionInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetFactoryResetInterface( +    Out<SharedPointer<IFactoryResetInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IFactoryResetInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetAccountProxyInterface( +    Out<SharedPointer<IAccountProxyInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IAccountProxyInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetApplicationManagerInterface( +    Out<SharedPointer<IApplicationManagerInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IApplicationManagerInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetDownloadTaskInterface( +    Out<SharedPointer<IDownloadTaskInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IDownloadTaskInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetContentManagementInterface( +    Out<SharedPointer<IContentManagementInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IContentManagementInterface>(system); +    R_SUCCEED(); +} + +Result IServiceGetterInterface::GetDocumentInterface( +    Out<SharedPointer<IDocumentInterface>> out_interface) { +    LOG_DEBUG(Service_NS, "called"); +    *out_interface = std::make_shared<IDocumentInterface>(system); +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/service_getter_interface.h b/src/core/hle/service/ns/service_getter_interface.h new file mode 100644 index 000000000..bbc18d444 --- /dev/null +++ b/src/core/hle/service/ns/service_getter_interface.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDynamicRightsInterface; +class IReadOnlyApplicationControlDataInterface; +class IReadOnlyApplicationRecordInterface; +class IECommerceInterface; +class IApplicationVersionInterface; +class IFactoryResetInterface; +class IAccountProxyInterface; +class IApplicationManagerInterface; +class IDownloadTaskInterface; +class IContentManagementInterface; +class IDocumentInterface; + +class IServiceGetterInterface : public ServiceFramework<IServiceGetterInterface> { +public: +    explicit IServiceGetterInterface(Core::System& system_, const char* name); +    ~IServiceGetterInterface() override; + +public: +    Result GetDynamicRightsInterface(Out<SharedPointer<IDynamicRightsInterface>> out_interface); +    Result GetReadOnlyApplicationControlDataInterface( +        Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface); +    Result GetReadOnlyApplicationRecordInterface( +        Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface); +    Result GetECommerceInterface(Out<SharedPointer<IECommerceInterface>> out_interface); +    Result GetApplicationVersionInterface( +        Out<SharedPointer<IApplicationVersionInterface>> out_interface); +    Result GetFactoryResetInterface(Out<SharedPointer<IFactoryResetInterface>> out_interface); +    Result GetAccountProxyInterface(Out<SharedPointer<IAccountProxyInterface>> out_interface); +    Result GetApplicationManagerInterface( +        Out<SharedPointer<IApplicationManagerInterface>> out_interface); +    Result GetDownloadTaskInterface(Out<SharedPointer<IDownloadTaskInterface>> out_interface); +    Result GetContentManagementInterface( +        Out<SharedPointer<IContentManagementInterface>> out_interface); +    Result GetDocumentInterface(Out<SharedPointer<IDocumentInterface>> out_interface); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/system_update_control.cpp b/src/core/hle/service/ns/system_update_control.cpp new file mode 100644 index 000000000..f5f5cfd90 --- /dev/null +++ b/src/core/hle/service/ns/system_update_control.cpp @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/system_update_control.h" + +namespace Service::NS { + +ISystemUpdateControl::ISystemUpdateControl(Core::System& system_) +    : ServiceFramework{system_, "ISystemUpdateControl"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "HasDownloaded"}, +        {1, nullptr, "RequestCheckLatestUpdate"}, +        {2, nullptr, "RequestDownloadLatestUpdate"}, +        {3, nullptr, "GetDownloadProgress"}, +        {4, nullptr, "ApplyDownloadedUpdate"}, +        {5, nullptr, "RequestPrepareCardUpdate"}, +        {6, nullptr, "GetPrepareCardUpdateProgress"}, +        {7, nullptr, "HasPreparedCardUpdate"}, +        {8, nullptr, "ApplyCardUpdate"}, +        {9, nullptr, "GetDownloadedEulaDataSize"}, +        {10, nullptr, "GetDownloadedEulaData"}, +        {11, nullptr, "SetupCardUpdate"}, +        {12, nullptr, "GetPreparedCardUpdateEulaDataSize"}, +        {13, nullptr, "GetPreparedCardUpdateEulaData"}, +        {14, nullptr, "SetupCardUpdateViaSystemUpdater"}, +        {15, nullptr, "HasReceived"}, +        {16, nullptr, "RequestReceiveSystemUpdate"}, +        {17, nullptr, "GetReceiveProgress"}, +        {18, nullptr, "ApplyReceivedUpdate"}, +        {19, nullptr, "GetReceivedEulaDataSize"}, +        {20, nullptr, "GetReceivedEulaData"}, +        {21, nullptr, "SetupToReceiveSystemUpdate"}, +        {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +ISystemUpdateControl::~ISystemUpdateControl() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/system_update_control.h b/src/core/hle/service/ns/system_update_control.h new file mode 100644 index 000000000..a30a09000 --- /dev/null +++ b/src/core/hle/service/ns/system_update_control.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> { +public: +    explicit ISystemUpdateControl(Core::System& system_); +    ~ISystemUpdateControl() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/system_update_interface.cpp b/src/core/hle/service/ns/system_update_interface.cpp new file mode 100644 index 000000000..7e22ca3db --- /dev/null +++ b/src/core/hle/service/ns/system_update_interface.cpp @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/system_update_control.h" +#include "core/hle/service/ns/system_update_interface.h" + +namespace Service::NS { + +ISystemUpdateInterface::ISystemUpdateInterface(Core::System& system_) +    : ServiceFramework{system_, "ns:su"}, service_context{system_, "ns:su"}, +      update_notification_event{service_context} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, D<&ISystemUpdateInterface::GetBackgroundNetworkUpdateState>, "GetBackgroundNetworkUpdateState"}, +        {1, D<&ISystemUpdateInterface::OpenSystemUpdateControl>, "OpenSystemUpdateControl"}, +        {2, nullptr, "NotifyExFatDriverRequired"}, +        {3, nullptr, "ClearExFatDriverStatusForDebug"}, +        {4, nullptr, "RequestBackgroundNetworkUpdate"}, +        {5, nullptr, "NotifyBackgroundNetworkUpdate"}, +        {6, nullptr, "NotifyExFatDriverDownloadedForDebug"}, +        {9, D<&ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery>, "GetSystemUpdateNotificationEventForContentDelivery"}, +        {10, nullptr, "NotifySystemUpdateForContentDelivery"}, +        {11, nullptr, "PrepareShutdown"}, +        {12, nullptr, "Unknown12"}, +        {13, nullptr, "Unknown13"}, +        {14, nullptr, "Unknown14"}, +        {15, nullptr, "Unknown15"}, +        {16, nullptr, "DestroySystemUpdateTask"}, +        {17, nullptr, "RequestSendSystemUpdate"}, +        {18, nullptr, "GetSendSystemUpdateProgress"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +ISystemUpdateInterface::~ISystemUpdateInterface() = default; + +Result ISystemUpdateInterface::GetBackgroundNetworkUpdateState( +    Out<BackgroundNetworkUpdateState> out_background_network_update_state) { +    LOG_WARNING(Service_AM, "(STUBBED) called"); +    *out_background_network_update_state = BackgroundNetworkUpdateState::None; +    R_SUCCEED(); +} + +Result ISystemUpdateInterface::OpenSystemUpdateControl( +    Out<SharedPointer<ISystemUpdateControl>> out_system_update_control) { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    *out_system_update_control = std::make_shared<ISystemUpdateControl>(system); +    R_SUCCEED(); +} + +Result ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery( +    OutCopyHandle<Kernel::KReadableEvent> out_event) { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    *out_event = update_notification_event.GetHandle(); +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/system_update_interface.h b/src/core/hle/service/ns/system_update_interface.h new file mode 100644 index 000000000..36a2880ec --- /dev/null +++ b/src/core/hle/service/ns/system_update_interface.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::NS { + +class ISystemUpdateControl; + +class ISystemUpdateInterface final : public ServiceFramework<ISystemUpdateInterface> { +public: +    explicit ISystemUpdateInterface(Core::System& system_); +    ~ISystemUpdateInterface() override; + +private: +    Result GetBackgroundNetworkUpdateState( +        Out<BackgroundNetworkUpdateState> out_background_network_update_state); +    Result OpenSystemUpdateControl( +        Out<SharedPointer<ISystemUpdateControl>> out_system_update_control); +    Result GetSystemUpdateNotificationEventForContentDelivery( +        OutCopyHandle<Kernel::KReadableEvent> out_event); + +private: +    KernelHelpers::ServiceContext service_context; +    Event update_notification_event; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/vulnerability_manager_interface.cpp b/src/core/hle/service/ns/vulnerability_manager_interface.cpp new file mode 100644 index 000000000..69c21fb89 --- /dev/null +++ b/src/core/hle/service/ns/vulnerability_manager_interface.cpp @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/vulnerability_manager_interface.h" + +namespace Service::NS { + +IVulnerabilityManagerInterface::IVulnerabilityManagerInterface(Core::System& system_) +    : ServiceFramework{system_, "ns:vm"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {1200, D<&IVulnerabilityManagerInterface::NeedsUpdateVulnerability>, "NeedsUpdateVulnerability"}, +        {1201, nullptr, "UpdateSafeSystemVersionForDebug"}, +        {1202, nullptr, "GetSafeSystemVersion"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IVulnerabilityManagerInterface::~IVulnerabilityManagerInterface() = default; + +Result IVulnerabilityManagerInterface::NeedsUpdateVulnerability( +    Out<bool> out_needs_update_vulnerability) { +    LOG_WARNING(Service_NS, "(STUBBED) called"); +    *out_needs_update_vulnerability = false; +    R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/vulnerability_manager_interface.h b/src/core/hle/service/ns/vulnerability_manager_interface.h new file mode 100644 index 000000000..c689cf7ec --- /dev/null +++ b/src/core/hle/service/ns/vulnerability_manager_interface.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IVulnerabilityManagerInterface final +    : public ServiceFramework<IVulnerabilityManagerInterface> { +public: +    explicit IVulnerabilityManagerInterface(Core::System& system_); +    ~IVulnerabilityManagerInterface() override; + +private: +    Result NeedsUpdateVulnerability(Out<bool> out_needs_update_vulnerability); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 250d01de3..0265d55f2 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -92,11 +92,11 @@ NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_a      bool must_unmark_fail = !is_allocation;      const u32 event_id = params.value.raw; -    SCOPE_EXIT({ +    SCOPE_EXIT {          if (must_unmark_fail) {              events[event_id].fails = 0;          } -    }); +    };      const u32 fence_id = static_cast<u32>(params.fence.id); diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index cb256e5b4..03eb507b9 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -42,7 +42,7 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) {      module.service_context.CloseEvent(event);  } -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { +void LoopProcess(Core::System& system) {      auto server_manager = std::make_unique<ServerManager>(system);      auto module = std::make_shared<Module>(system);      const auto NvdrvInterfaceFactoryForApplication = [&, module] { @@ -62,7 +62,6 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {      server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules);      server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting);      server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system)); -    nvnflinger.SetNVDrvInstance(module);      ServerManager::RunServer(std::move(server_manager));  } diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index c594f0e5e..b76f81e59 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -10,13 +10,11 @@  #include <span>  #include <string>  #include <unordered_map> -#include <vector>  #include "common/common_types.h"  #include "core/hle/service/kernel_helpers.h"  #include "core/hle/service/nvdrv/core/container.h"  #include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvnflinger/ui/fence.h"  #include "core/hle/service/service.h"  namespace Core { @@ -27,10 +25,6 @@ namespace Kernel {  class KEvent;  } -namespace Service::Nvnflinger { -class Nvnflinger; -} -  namespace Service::Nvidia {  namespace NvCore { @@ -99,7 +93,6 @@ public:  private:      friend class EventInterface; -    friend class Service::Nvnflinger::Nvnflinger;      /// Manages syncpoints on the host      NvCore::Container container; @@ -118,6 +111,6 @@ private:      std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;  }; -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); +void LoopProcess(Core::System& system);  } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index ffe72f281..258970fd5 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -154,10 +154,10 @@ void NVDRV::Close(HLERequestContext& ctx) {  void NVDRV::Initialize(HLERequestContext& ctx) {      LOG_WARNING(Service_NVDRV, "(STUBBED) called");      IPC::ResponseBuilder rb{ctx, 3}; -    SCOPE_EXIT({ +    SCOPE_EXIT {          rb.Push(ResultSuccess);          rb.PushEnum(NvResult::Success); -    }); +    };      if (is_initialized) {          // No need to initialize again @@ -263,8 +263,10 @@ NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char*  }  NVDRV::~NVDRV() { -    auto& container = nvdrv->GetContainer(); -    container.CloseSession(session_id); +    if (is_initialized) { +        auto& container = nvdrv->GetContainer(); +        container.CloseSession(session_id); +    }  }  } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index f2195ae1e..c72f92597 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h @@ -16,6 +16,10 @@ public:      explicit NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name);      ~NVDRV() override; +    std::shared_ptr<Module> GetModule() const { +        return nvdrv; +    } +  private:      void Open(HLERequestContext& ctx);      void Ioctl1(HLERequestContext& ctx); diff --git a/src/core/hle/service/nvnflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h index 179938192..124accb94 100644 --- a/src/core/hle/service/nvnflinger/binder.h +++ b/src/core/hle/service/nvnflinger/binder.h @@ -20,29 +20,12 @@ class HLERequestContext;  namespace Service::android { -enum class TransactionId { -    RequestBuffer = 1, -    SetBufferCount = 2, -    DequeueBuffer = 3, -    DetachBuffer = 4, -    DetachNextBuffer = 5, -    AttachBuffer = 6, -    QueueBuffer = 7, -    CancelBuffer = 8, -    Query = 9, -    Connect = 10, -    Disconnect = 11, -    AllocateBuffers = 13, -    SetPreallocatedBuffer = 14, -    GetBufferHistory = 17, -}; -  class IBinder {  public:      virtual ~IBinder() = default; -    virtual void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data, -                          std::span<u8> parcel_reply) = 0; -    virtual Kernel::KReadableEvent& GetNativeHandle() = 0; +    virtual void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, +                          u32 flags) = 0; +    virtual Kernel::KReadableEvent* GetNativeHandle(u32 type_id) = 0;  };  } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp index cf151ea3a..123507123 100644 --- a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp @@ -12,7 +12,7 @@  namespace Service::android { -BufferItemConsumer::BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer_) +BufferItemConsumer::BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer_)      : ConsumerBase{std::move(consumer_)} {}  Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.h b/src/core/hle/service/nvnflinger/buffer_item_consumer.h index e0c6b3604..9f95c9280 100644 --- a/src/core/hle/service/nvnflinger/buffer_item_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.h @@ -19,7 +19,7 @@ class BufferItem;  class BufferItemConsumer final : public ConsumerBase {  public: -    explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer); +    explicit BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer);      Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,                           bool wait_for_fence = true);      Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence); diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index bbe8e06d4..3bc23aa97 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp @@ -4,12 +4,13 @@  // Parts of this implementation were based on:  // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp +#include "common/assert.h"  #include "common/logging/log.h"  #include "core/hle/service/nvnflinger/buffer_item.h"  #include "core/hle/service/nvnflinger/buffer_queue_consumer.h"  #include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/parcel.h"  #include "core/hle/service/nvnflinger/producer_listener.h" -#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"  namespace Service::android { @@ -254,4 +255,77 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {      return Status::NoError;  } +void BufferQueueConsumer::Transact(u32 code, std::span<const u8> parcel_data, +                                   std::span<u8> parcel_reply, u32 flags) { +    // Values used by BnGraphicBufferConsumer onTransact +    enum class TransactionId { +        AcquireBuffer = 1, +        DetachBuffer = 2, +        AttachBuffer = 3, +        ReleaseBuffer = 4, +        ConsumerConnect = 5, +        ConsumerDisconnect = 6, +        GetReleasedBuffers = 7, +        SetDefaultBufferSize = 8, +        SetDefaultMaxBufferCount = 9, +        DisableAsyncBuffer = 10, +        SetMaxAcquiredBufferCount = 11, +        SetConsumerName = 12, +        SetDefaultBufferFormat = 13, +        SetConsumerUsageBits = 14, +        SetTransformHint = 15, +        GetSidebandStream = 16, +        Unknown18 = 18, +        Unknown20 = 20, +    }; + +    Status status{Status::NoError}; +    InputParcel parcel_in{parcel_data}; +    OutputParcel parcel_out{}; + +    switch (static_cast<TransactionId>(code)) { +    case TransactionId::AcquireBuffer: { +        BufferItem item; +        const s64 present_when = parcel_in.Read<s64>(); + +        status = AcquireBuffer(&item, std::chrono::nanoseconds{present_when}); + +        // TODO: can't write this directly, needs a flattener for the sp<GraphicBuffer> +        // parcel_out.WriteFlattened(item); +        UNREACHABLE(); +    } +    case TransactionId::ReleaseBuffer: { +        const s32 slot = parcel_in.Read<s32>(); +        const u64 frame_number = parcel_in.Read<u64>(); +        const auto release_fence = parcel_in.ReadFlattened<Fence>(); + +        status = ReleaseBuffer(slot, frame_number, release_fence); + +        break; +    } +    case TransactionId::GetReleasedBuffers: { +        u64 slot_mask = 0; + +        status = GetReleasedBuffers(&slot_mask); + +        parcel_out.Write(slot_mask); +        break; +    } +    default: +        ASSERT_MSG(false, "called, code={} flags={}", code, flags); +        break; +    } + +    parcel_out.Write(status); + +    const auto serialized = parcel_out.Serialize(); +    std::memcpy(parcel_reply.data(), serialized.data(), +                std::min(parcel_reply.size(), serialized.size())); +} + +Kernel::KReadableEvent* BufferQueueConsumer::GetNativeHandle(u32 type_id) { +    ASSERT_MSG(false, "called, type_id={}", type_id); +    return nullptr; +} +  } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h index 0a61e8dbd..a9226f1c3 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h @@ -10,6 +10,7 @@  #include <memory>  #include "common/common_types.h" +#include "core/hle/service/nvnflinger/binder.h"  #include "core/hle/service/nvnflinger/buffer_queue_defs.h"  #include "core/hle/service/nvnflinger/status.h" @@ -19,10 +20,10 @@ class BufferItem;  class BufferQueueCore;  class IConsumerListener; -class BufferQueueConsumer final { +class BufferQueueConsumer final : public IBinder {  public:      explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_); -    ~BufferQueueConsumer(); +    ~BufferQueueConsumer() override;      Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);      Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); @@ -30,6 +31,11 @@ public:      Status Disconnect();      Status GetReleasedBuffers(u64* out_slot_mask); +    void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, +                  u32 flags) override; + +    Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override; +  private:      std::shared_ptr<BufferQueueCore> core;      BufferQueueDefs::SlotsType& slots; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index ec83beb9b..9e5091eeb 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -6,12 +6,9 @@  #include "common/assert.h"  #include "common/logging/log.h" -#include "common/settings.h" -#include "core/core.h"  #include "core/hle/kernel/k_event.h"  #include "core/hle/kernel/k_readable_event.h"  #include "core/hle/kernel/kernel.h" -#include "core/hle/service/hle_ipc.h"  #include "core/hle/service/kernel_helpers.h"  #include "core/hle/service/nvnflinger/buffer_queue_core.h"  #include "core/hle/service/nvnflinger/buffer_queue_producer.h" @@ -19,7 +16,6 @@  #include "core/hle/service/nvnflinger/parcel.h"  #include "core/hle/service/nvnflinger/ui/graphic_buffer.h"  #include "core/hle/service/nvnflinger/window.h" -#include "core/hle/service/vi/vi.h"  namespace Service::android { @@ -807,13 +803,31 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,      return Status::NoError;  } -void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<const u8> parcel_data, -                                   std::span<u8> parcel_reply) { +void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data, +                                   std::span<u8> parcel_reply, u32 flags) { +    // Values used by BnGraphicBufferProducer onTransact +    enum class TransactionId { +        RequestBuffer = 1, +        SetBufferCount = 2, +        DequeueBuffer = 3, +        DetachBuffer = 4, +        DetachNextBuffer = 5, +        AttachBuffer = 6, +        QueueBuffer = 7, +        CancelBuffer = 8, +        Query = 9, +        Connect = 10, +        Disconnect = 11, +        AllocateBuffers = 13, +        SetPreallocatedBuffer = 14, +        GetBufferHistory = 17, +    }; +      Status status{Status::NoError};      InputParcel parcel_in{parcel_data};      OutputParcel parcel_out{}; -    switch (code) { +    switch (static_cast<TransactionId>(code)) {      case TransactionId::Connect: {          const auto enable_listener = parcel_in.Read<bool>();          const auto api = parcel_in.Read<NativeWindowApi>(); @@ -923,8 +937,8 @@ void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<cons                  std::min(parcel_reply.size(), serialized.size()));  } -Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { -    return buffer_wait_event->GetReadableEvent(); +Kernel::KReadableEvent* BufferQueueProducer::GetNativeHandle(u32 type_id) { +    return &buffer_wait_event->GetReadableEvent();  }  } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 4682b0f84..048523514 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -45,12 +45,12 @@ public:      explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,                                   std::shared_ptr<BufferQueueCore> buffer_queue_core_,                                   Service::Nvidia::NvCore::NvMap& nvmap_); -    ~BufferQueueProducer(); +    ~BufferQueueProducer() override; -    void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data, -                  std::span<u8> parcel_reply) override; +    void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, +                  u32 flags) override; -    Kernel::KReadableEvent& GetNativeHandle() override; +    Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;  public:      Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf); diff --git a/src/core/hle/service/nvnflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp index 1059e72bf..e360ebfd8 100644 --- a/src/core/hle/service/nvnflinger/consumer_base.cpp +++ b/src/core/hle/service/nvnflinger/consumer_base.cpp @@ -14,7 +14,7 @@  namespace Service::android { -ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_) +ConsumerBase::ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_)      : consumer{std::move(consumer_)} {}  ConsumerBase::~ConsumerBase() { diff --git a/src/core/hle/service/nvnflinger/consumer_base.h b/src/core/hle/service/nvnflinger/consumer_base.h index ea3e9e97a..b29c16f86 100644 --- a/src/core/hle/service/nvnflinger/consumer_base.h +++ b/src/core/hle/service/nvnflinger/consumer_base.h @@ -27,7 +27,7 @@ public:      void Abandon();  protected: -    explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); +    explicit ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_);      ~ConsumerBase() override;      void OnFrameAvailable(const BufferItem& item) override; @@ -54,7 +54,7 @@ protected:      bool is_abandoned{}; -    std::unique_ptr<BufferQueueConsumer> consumer; +    std::shared_ptr<BufferQueueConsumer> consumer;      mutable std::mutex mutex;  }; diff --git a/src/core/hle/service/nvnflinger/display.h b/src/core/hle/service/nvnflinger/display.h new file mode 100644 index 000000000..40aa59787 --- /dev/null +++ b/src/core/hle/service/nvnflinger/display.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/nvnflinger/buffer_item_consumer.h" +#include "core/hle/service/nvnflinger/hwc_layer.h" + +namespace Service::Nvnflinger { + +struct Layer { +    explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_, +                   s32 consumer_id_) +        : buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_), +          blending(LayerBlending::None), visible(true) {} +    ~Layer() { +        buffer_item_consumer->Abandon(); +    } + +    std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer; +    s32 consumer_id; +    LayerBlending blending; +    bool visible; +}; + +struct LayerStack { +    std::vector<std::shared_ptr<Layer>> layers; + +    std::shared_ptr<Layer> FindLayer(s32 consumer_id) { +        for (auto& layer : layers) { +            if (layer->consumer_id == consumer_id) { +                return layer; +            } +        } + +        return nullptr; +    } + +    bool HasLayers() { +        return !layers.empty(); +    } +}; + +struct Display { +    explicit Display(u64 id_) { +        id = id_; +    } + +    u64 id; +    LayerStack stack; +}; + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp index be7eb97a3..f2dfe85a9 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.cpp +++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp @@ -10,8 +10,6 @@  #include "core/hle/service/nvnflinger/hardware_composer.h"  #include "core/hle/service/nvnflinger/hwc_layer.h"  #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" -#include "core/hle/service/vi/display/vi_display.h" -#include "core/hle/service/vi/layer/vi_layer.h"  namespace Service::Nvnflinger { @@ -44,7 +42,7 @@ s32 NormalizeSwapInterval(f32* out_speed_scale, s32 swap_interval) {  HardwareComposer::HardwareComposer() = default;  HardwareComposer::~HardwareComposer() = default; -u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, +u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,                                      Nvidia::Devices::nvdisp_disp0& nvdisp) {      boost::container::small_vector<HwcLayer, 2> composition_stack; @@ -56,12 +54,11 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,      bool has_acquired_buffer{};      // Acquire all necessary framebuffers. -    for (size_t i = 0; i < display.GetNumLayers(); i++) { -        auto& layer = display.GetLayer(i); -        auto layer_id = layer.GetLayerId(); +    for (auto& layer : display.stack.layers) { +        auto consumer_id = layer->consumer_id;          // Try to fetch the framebuffer (either new or stale). -        const auto result = this->CacheFramebufferLocked(layer, layer_id); +        const auto result = this->CacheFramebufferLocked(*layer, consumer_id);          // If we failed, skip this layer.          if (result == CacheStatus::NoBufferAvailable) { @@ -73,24 +70,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,              has_acquired_buffer = true;          } -        const auto& buffer = m_framebuffers[layer_id]; +        const auto& buffer = m_framebuffers[consumer_id];          const auto& item = buffer.item;          const auto& igbp_buffer = *item.graphic_buffer;          // TODO: get proper Z-index from layer -        composition_stack.emplace_back(HwcLayer{ -            .buffer_handle = igbp_buffer.BufferId(), -            .offset = igbp_buffer.Offset(), -            .format = igbp_buffer.ExternalFormat(), -            .width = igbp_buffer.Width(), -            .height = igbp_buffer.Height(), -            .stride = igbp_buffer.Stride(), -            .z_index = 0, -            .blending = layer.GetBlending(), -            .transform = static_cast<android::BufferTransformFlags>(item.transform), -            .crop_rect = item.crop, -            .acquire_fence = item.fence, -        }); +        if (layer->visible) { +            composition_stack.emplace_back(HwcLayer{ +                .buffer_handle = igbp_buffer.BufferId(), +                .offset = igbp_buffer.Offset(), +                .format = igbp_buffer.ExternalFormat(), +                .width = igbp_buffer.Width(), +                .height = igbp_buffer.Height(), +                .stride = igbp_buffer.Stride(), +                .z_index = 0, +                .blending = layer->blending, +                .transform = static_cast<android::BufferTransformFlags>(item.transform), +                .crop_rect = item.crop, +                .acquire_fence = item.fence, +            }); +        }          // We need to compose again either before this frame is supposed to          // be released, or exactly on the vsync period it should be released. @@ -135,10 +134,10 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,              continue;          } -        if (auto* layer = display.FindLayer(layer_id); layer != nullptr) { +        if (const auto layer = display.stack.FindLayer(layer_id); layer != nullptr) {              // TODO: support release fence              // This is needed to prevent screen tearing -            layer->GetConsumer().ReleaseBuffer(framebuffer.item, android::Fence::NoFence()); +            layer->buffer_item_consumer->ReleaseBuffer(framebuffer.item, android::Fence::NoFence());              framebuffer.is_acquired = false;          }      } @@ -146,26 +145,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,      return frame_advance;  } -void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) { -    // Check if we are tracking a slot with this layer_id. -    const auto it = m_framebuffers.find(layer_id); +void HardwareComposer::RemoveLayerLocked(Display& display, ConsumerId consumer_id) { +    // Check if we are tracking a slot with this consumer_id. +    const auto it = m_framebuffers.find(consumer_id);      if (it == m_framebuffers.end()) {          return;      }      // Try to release the buffer item. -    auto* const layer = display.FindLayer(layer_id); +    const auto layer = display.stack.FindLayer(consumer_id);      if (layer && it->second.is_acquired) { -        layer->GetConsumer().ReleaseBuffer(it->second.item, android::Fence::NoFence()); +        layer->buffer_item_consumer->ReleaseBuffer(it->second.item, android::Fence::NoFence());      }      // Erase the slot.      m_framebuffers.erase(it);  } -bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer) { +bool HardwareComposer::TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer) {      // Attempt the update. -    const auto status = layer.GetConsumer().AcquireBuffer(&framebuffer.item, {}, false); +    const auto status = layer.buffer_item_consumer->AcquireBuffer(&framebuffer.item, {}, false);      if (status != android::Status::NoError) {          return false;      } @@ -178,10 +177,10 @@ bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer      return true;  } -HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer& layer, -                                                                       LayerId layer_id) { +HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(Layer& layer, +                                                                       ConsumerId consumer_id) {      // Check if this framebuffer is already present. -    const auto it = m_framebuffers.find(layer_id); +    const auto it = m_framebuffers.find(consumer_id);      if (it != m_framebuffers.end()) {          // If it's currently still acquired, we are done.          if (it->second.is_acquired) { @@ -203,7 +202,7 @@ HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer      if (this->TryAcquireFramebufferLocked(layer, framebuffer)) {          // Move the buffer item into a new slot. -        m_framebuffers.emplace(layer_id, std::move(framebuffer)); +        m_framebuffers.emplace(consumer_id, std::move(framebuffer));          // We succeeded.          return CacheStatus::BufferAcquired; diff --git a/src/core/hle/service/nvnflinger/hardware_composer.h b/src/core/hle/service/nvnflinger/hardware_composer.h index 28392c512..c5b830468 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.h +++ b/src/core/hle/service/nvnflinger/hardware_composer.h @@ -3,35 +3,29 @@  #pragma once -#include <memory>  #include <boost/container/flat_map.hpp>  #include "core/hle/service/nvnflinger/buffer_item.h" +#include "core/hle/service/nvnflinger/display.h"  namespace Service::Nvidia::Devices {  class nvdisp_disp0;  } -namespace Service::VI { -class Display; -class Layer; -} // namespace Service::VI -  namespace Service::Nvnflinger { -using LayerId = u64; +using ConsumerId = s32;  class HardwareComposer {  public:      explicit HardwareComposer();      ~HardwareComposer(); -    u32 ComposeLocked(f32* out_speed_scale, VI::Display& display, +    u32 ComposeLocked(f32* out_speed_scale, Display& display,                        Nvidia::Devices::nvdisp_disp0& nvdisp); -    void RemoveLayerLocked(VI::Display& display, LayerId layer_id); +    void RemoveLayerLocked(Display& display, ConsumerId consumer_id);  private: -    // TODO: do we want to track frame number in vi instead?      u64 m_frame_number{0};  private: @@ -49,11 +43,11 @@ private:          CachedBufferReused,      }; -    boost::container::flat_map<LayerId, Framebuffer> m_framebuffers{}; +    boost::container::flat_map<ConsumerId, Framebuffer> m_framebuffers{};  private: -    bool TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer); -    CacheStatus CacheFramebufferLocked(VI::Layer& layer, LayerId layer_id); +    bool TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer); +    CacheStatus CacheFramebufferLocked(Layer& layer, ConsumerId consumer_id);  };  } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/vi/hos_binder_driver.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp index ba0317245..8629a2e89 100644 --- a/src/core/hle/service/vi/hos_binder_driver.cpp +++ b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp @@ -3,13 +3,16 @@  #include "core/hle/service/cmif_serialization.h"  #include "core/hle/service/nvnflinger/binder.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h"  #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" -#include "core/hle/service/vi/hos_binder_driver.h" -namespace Service::VI { +namespace Service::Nvnflinger { -IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server) -    : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server) { +IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, +                                   std::shared_ptr<HosBinderDriverServer> server, +                                   std::shared_ptr<SurfaceFlinger> surface_flinger) +    : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server), +      m_surface_flinger(surface_flinger) {      static const FunctionInfo functions[] = {          {0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"},          {1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"}, @@ -21,13 +24,18 @@ IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderD  IHOSBinderDriver::~IHOSBinderDriver() = default; -Result IHOSBinderDriver::TransactParcel(s32 binder_id, android::TransactionId transaction_id, +Result IHOSBinderDriver::TransactParcel(s32 binder_id, u32 transaction_id,                                          InBuffer<BufferAttr_HipcMapAlias> parcel_data,                                          OutBuffer<BufferAttr_HipcMapAlias> parcel_reply,                                          u32 flags) {      LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id,                flags); -    m_server.TryGetProducer(binder_id)->Transact(transaction_id, flags, parcel_data, parcel_reply); + +    const auto binder = m_server->TryGetBinder(binder_id); +    R_SUCCEED_IF(binder == nullptr); + +    binder->Transact(transaction_id, parcel_data, parcel_reply, flags); +      R_SUCCEED();  } @@ -39,15 +47,20 @@ Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) {  Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id,                                           OutCopyHandle<Kernel::KReadableEvent> out_handle) {      LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id); -    *out_handle = &m_server.TryGetProducer(binder_id)->GetNativeHandle(); + +    const auto binder = m_server->TryGetBinder(binder_id); +    R_UNLESS(binder != nullptr, ResultUnknown); + +    *out_handle = binder->GetNativeHandle(type_id); +      R_SUCCEED();  } -Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, +Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, u32 transaction_id,                                              InBuffer<BufferAttr_HipcAutoSelect> parcel_data,                                              OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply,                                              u32 flags) {      R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags));  } -} // namespace Service::VI +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/vi/hos_binder_driver.h b/src/core/hle/service/nvnflinger/hos_binder_driver.h index ed6e8cdbe..b7fb07bd2 100644 --- a/src/core/hle/service/vi/hos_binder_driver.h +++ b/src/core/hle/service/nvnflinger/hos_binder_driver.h @@ -2,29 +2,45 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "core/hle/service/cmif_types.h" -#include "core/hle/service/nvnflinger/binder.h"  #include "core/hle/service/service.h" -namespace Service::VI { +namespace Kernel { +class KReadableEvent; +} + +namespace Service::Nvnflinger { + +class HosBinderDriverServer; +class SurfaceFlinger;  class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {  public: -    explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server); +    explicit IHOSBinderDriver(Core::System& system_, std::shared_ptr<HosBinderDriverServer> server, +                              std::shared_ptr<SurfaceFlinger> surface_flinger);      ~IHOSBinderDriver() override; +    std::shared_ptr<SurfaceFlinger> GetSurfaceFlinger() { +        return m_surface_flinger; +    } + +    std::shared_ptr<HosBinderDriverServer> GetServer() { +        return m_server; +    } +  private: -    Result TransactParcel(s32 binder_id, android::TransactionId transaction_id, +    Result TransactParcel(s32 binder_id, u32 transaction_id,                            InBuffer<BufferAttr_HipcMapAlias> parcel_data,                            OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags);      Result AdjustRefcount(s32 binder_id, s32 addval, s32 type);      Result GetNativeHandle(s32 binder_id, u32 type_id,                             OutCopyHandle<Kernel::KReadableEvent> out_handle); -    Result TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, +    Result TransactParcelAuto(s32 binder_id, u32 transaction_id,                                InBuffer<BufferAttr_HipcAutoSelect> parcel_data,                                OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags);  private: -    Nvnflinger::HosBinderDriverServer& m_server; +    const std::shared_ptr<HosBinderDriverServer> m_server; +    const std::shared_ptr<SurfaceFlinger> m_surface_flinger;  }; -} // namespace Service::VI +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp index b86a79ec9..29addda44 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp @@ -8,26 +8,30 @@  namespace Service::Nvnflinger { -HosBinderDriverServer::HosBinderDriverServer(Core::System& system_) -    : service_context(system_, "HosBinderDriverServer") {} +HosBinderDriverServer::HosBinderDriverServer() = default; +HosBinderDriverServer::~HosBinderDriverServer() = default; -HosBinderDriverServer::~HosBinderDriverServer() {} - -u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) { +s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr<android::IBinder>&& binder) {      std::scoped_lock lk{lock};      last_id++; -    producers[last_id] = std::move(binder); +    binders[last_id] = std::move(binder);      return last_id;  } -android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) { +void HosBinderDriverServer::UnregisterBinder(s32 binder_id) { +    std::scoped_lock lk{lock}; + +    binders.erase(binder_id); +} + +std::shared_ptr<android::IBinder> HosBinderDriverServer::TryGetBinder(s32 id) const {      std::scoped_lock lk{lock}; -    if (auto search = producers.find(id); search != producers.end()) { -        return search->second.get(); +    if (auto search = binders.find(id); search != binders.end()) { +        return search->second;      }      return {}; diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h index 58bb9469a..d72b50833 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h @@ -8,7 +8,6 @@  #include <unordered_map>  #include "common/common_types.h" -#include "core/hle/service/kernel_helpers.h"  #include "core/hle/service/nvnflinger/binder.h"  namespace Core { @@ -19,19 +18,18 @@ namespace Service::Nvnflinger {  class HosBinderDriverServer final {  public: -    explicit HosBinderDriverServer(Core::System& system_); +    explicit HosBinderDriverServer();      ~HosBinderDriverServer(); -    u64 RegisterProducer(std::unique_ptr<android::IBinder>&& binder); +    s32 RegisterBinder(std::shared_ptr<android::IBinder>&& binder); +    void UnregisterBinder(s32 binder_id); -    android::IBinder* TryGetProducer(u64 id); +    std::shared_ptr<android::IBinder> TryGetBinder(s32 id) const;  private: -    KernelHelpers::ServiceContext service_context; - -    std::unordered_map<u64, std::unique_ptr<android::IBinder>> producers; -    std::mutex lock; -    u64 last_id{}; +    std::unordered_map<s32, std::shared_ptr<android::IBinder>> binders; +    mutable std::mutex lock; +    s32 last_id{};  };  } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 687ccc9f9..9e3b68b8a 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -1,335 +1,24 @@  // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project  // SPDX-License-Identifier: GPL-3.0-or-later -#include <algorithm> -#include <optional> - -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/microprofile.h" -#include "common/scope_exit.h" -#include "common/settings.h" -#include "common/thread.h"  #include "core/core.h" -#include "core/core_timing.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" -#include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvnflinger/buffer_item_consumer.h" -#include "core/hle/service/nvnflinger/buffer_queue_core.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" -#include "core/hle/service/nvnflinger/hardware_composer.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h"  #include "core/hle/service/nvnflinger/hos_binder_driver_server.h"  #include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" -#include "core/hle/service/vi/display/vi_display.h" -#include "core/hle/service/vi/layer/vi_layer.h" -#include "core/hle/service/vi/vi_results.h" -#include "video_core/gpu.h" -#include "video_core/host1x/host1x.h" -#include "video_core/host1x/syncpoint_manager.h" +#include "core/hle/service/nvnflinger/surface_flinger.h" +#include "core/hle/service/server_manager.h" +#include "core/hle/service/sm/sm.h"  namespace Service::Nvnflinger { -constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60}; - -void Nvnflinger::SplitVSync(std::stop_token stop_token) { -    system.RegisterHostThread(); -    std::string name = "VSyncThread"; -    MicroProfileOnThreadCreate(name.c_str()); - -    // Cleanup -    SCOPE_EXIT({ MicroProfileOnThreadExit(); }); - -    Common::SetCurrentThreadName(name.c_str()); -    Common::SetCurrentThreadPriority(Common::ThreadPriority::High); - -    while (!stop_token.stop_requested()) { -        vsync_signal.Wait(); - -        const auto lock_guard = Lock(); - -        if (!is_abandoned) { -            Compose(); -        } -    } -} - -Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_) -    : system(system_), service_context(system_, "nvnflinger"), -      hos_binder_driver_server(hos_binder_driver_server_) { -    displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system); -    displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system); -    displays.emplace_back(2, "Edid", hos_binder_driver_server, service_context, system); -    displays.emplace_back(3, "Internal", hos_binder_driver_server, service_context, system); -    displays.emplace_back(4, "Null", hos_binder_driver_server, service_context, system); -    guard = std::make_shared<std::mutex>(); - -    // Schedule the screen composition events -    multi_composition_event = Core::Timing::CreateEvent( -        "ScreenComposition", -        [this](s64 time, -               std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { -            vsync_signal.Set(); -            return std::chrono::nanoseconds(GetNextTicks()); -        }); - -    single_composition_event = Core::Timing::CreateEvent( -        "ScreenComposition", -        [this](s64 time, -               std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { -            const auto lock_guard = Lock(); -            Compose(); - -            return std::chrono::nanoseconds(GetNextTicks()); -        }); - -    if (system.IsMulticore()) { -        system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event); -        vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); -    } else { -        system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event); -    } -} - -Nvnflinger::~Nvnflinger() { -    if (system.IsMulticore()) { -        system.CoreTiming().UnscheduleEvent(multi_composition_event); -        vsync_thread.request_stop(); -        vsync_signal.Set(); -    } else { -        system.CoreTiming().UnscheduleEvent(single_composition_event); -    } - -    ShutdownLayers(); - -    if (nvdrv) { -        nvdrv->Close(disp_fd); -    } -} - -void Nvnflinger::ShutdownLayers() { -    // Abandon consumers. -    { -        const auto lock_guard = Lock(); -        for (auto& display : displays) { -            display.Abandon(); -        } - -        is_abandoned = true; -    } - -    // Join the vsync thread, if it exists. -    vsync_thread = {}; -} - -void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { -    nvdrv = std::move(instance); -    disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); -} - -std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) { -    const auto lock_guard = Lock(); - -    LOG_DEBUG(Service_Nvnflinger, "Opening \"{}\" display", name); - -    const auto itr = -        std::find_if(displays.begin(), displays.end(), -                     [&](const VI::Display& display) { return display.GetName() == name; }); - -    if (itr == displays.end()) { -        return std::nullopt; -    } - -    return itr->GetID(); -} - -bool Nvnflinger::CloseDisplay(u64 display_id) { -    const auto lock_guard = Lock(); -    auto* const display = FindDisplay(display_id); - -    if (display == nullptr) { -        return false; -    } - -    display->Reset(); - -    return true; -} - -std::optional<u64> Nvnflinger::CreateLayer(u64 display_id, LayerBlending blending) { -    const auto lock_guard = Lock(); -    auto* const display = FindDisplay(display_id); - -    if (display == nullptr) { -        return std::nullopt; -    } - -    const u64 layer_id = next_layer_id++; -    CreateLayerAtId(*display, layer_id, blending); -    return layer_id; -} - -void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending) { -    const auto buffer_id = next_buffer_queue_id++; -    display.CreateLayer(layer_id, buffer_id, nvdrv->container); -    display.FindLayer(layer_id)->SetBlending(blending); -} - -bool Nvnflinger::OpenLayer(u64 layer_id) { -    const auto lock_guard = Lock(); - -    for (auto& display : displays) { -        if (auto* layer = display.FindLayer(layer_id); layer) { -            return layer->Open(); -        } -    } - -    return false; -} - -bool Nvnflinger::CloseLayer(u64 layer_id) { -    const auto lock_guard = Lock(); - -    for (auto& display : displays) { -        if (auto* layer = display.FindLayer(layer_id); layer) { -            return layer->Close(); -        } -    } - -    return false; -} - -void Nvnflinger::SetLayerVisibility(u64 layer_id, bool visible) { -    const auto lock_guard = Lock(); - -    for (auto& display : displays) { -        if (auto* layer = display.FindLayer(layer_id); layer) { -            layer->SetVisibility(visible); -        } -    } -} - -void Nvnflinger::DestroyLayer(u64 layer_id) { -    const auto lock_guard = Lock(); - -    for (auto& display : displays) { -        display.DestroyLayer(layer_id); -    } -} - -std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) { -    const auto lock_guard = Lock(); -    const auto* const layer = FindLayer(display_id, layer_id); - -    if (layer == nullptr) { -        return std::nullopt; -    } - -    return layer->GetBinderId(); -} - -Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) { -    const auto lock_guard = Lock(); -    auto* const display = FindDisplay(display_id); - -    if (display == nullptr) { -        return VI::ResultNotFound; -    } - -    *out_vsync_event = display->GetVSyncEvent(); -    return ResultSuccess; -} - -VI::Display* Nvnflinger::FindDisplay(u64 display_id) { -    const auto itr = -        std::find_if(displays.begin(), displays.end(), -                     [&](const VI::Display& display) { return display.GetID() == display_id; }); - -    if (itr == displays.end()) { -        return nullptr; -    } - -    return &*itr; -} - -const VI::Display* Nvnflinger::FindDisplay(u64 display_id) const { -    const auto itr = -        std::find_if(displays.begin(), displays.end(), -                     [&](const VI::Display& display) { return display.GetID() == display_id; }); - -    if (itr == displays.end()) { -        return nullptr; -    } - -    return &*itr; -} - -VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) { -    auto* const display = FindDisplay(display_id); - -    if (display == nullptr) { -        return nullptr; -    } - -    return display->FindLayer(layer_id); -} - -void Nvnflinger::Compose() { -    for (auto& display : displays) { -        // Trigger vsync for this display at the end of drawing -        SCOPE_EXIT({ display.SignalVSyncEvent(); }); - -        // Don't do anything for displays without layers. -        if (!display.HasLayers()) { -            continue; -        } - -        if (!system.IsPoweredOn()) { -            return; // We are likely shutting down -        } - -        auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd); -        ASSERT(nvdisp); - -        swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp); -    } -} - -s64 Nvnflinger::GetNextTicks() const { -    const auto& settings = Settings::values; -    auto speed_scale = 1.f; -    if (settings.use_multi_core.GetValue()) { -        if (settings.use_speed_limit.GetValue()) { -            // Scales the speed based on speed_limit setting on MC. SC is handled by -            // SpeedLimiter::DoSpeedLimiting. -            speed_scale = 100.f / settings.speed_limit.GetValue(); -        } else { -            // Run at unlocked framerate. -            speed_scale = 0.01f; -        } -    } - -    // Adjust by speed limit determined during composition. -    speed_scale /= compose_speed_scale; - -    if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) { -        // Run at intended presentation rate during video playback. -        speed_scale = 1.f; -    } - -    const f32 effective_fps = 60.f / static_cast<f32>(swap_interval); -    return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); -} - -FbShareBufferManager& Nvnflinger::GetSystemBufferManager() { -    const auto lock_guard = Lock(); - -    if (!system_buffer_manager) { -        system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv); -    } +void LoopProcess(Core::System& system) { +    const auto binder_server = std::make_shared<HosBinderDriverServer>(); +    const auto surface_flinger = std::make_shared<SurfaceFlinger>(system, *binder_server); -    return *system_buffer_manager; +    auto server_manager = std::make_unique<ServerManager>(system); +    server_manager->RegisterNamedService( +        "dispdrv", std::make_shared<IHOSBinderDriver>(system, binder_server, surface_flinger)); +    ServerManager::RunServer(std::move(server_manager));  }  } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 4cf4f069d..5c41f3013 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -3,170 +3,12 @@  #pragma once -#include <list> -#include <memory> -#include <mutex> -#include <optional> -#include <thread> -#include <vector> - -#include "common/common_types.h" -#include "common/polyfill_thread.h" -#include "common/thread.h" -#include "core/hle/result.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nvnflinger/hwc_layer.h" - -namespace Common { -class Event; -} // namespace Common - -namespace Core::Timing { -class CoreTiming; -struct EventType; -} // namespace Core::Timing - -namespace Kernel { -class KReadableEvent; -} // namespace Kernel - -namespace Service::Nvidia { -class Module; -} // namespace Service::Nvidia - -namespace Service::VI { -class Display; -class Layer; -} // namespace Service::VI - -namespace Service::android { -class BufferQueueCore; -class BufferQueueProducer; -} // namespace Service::android +namespace Core { +class System; +}  namespace Service::Nvnflinger { -class FbShareBufferManager; -class HardwareComposer; -class HosBinderDriverServer; - -class Nvnflinger final { -public: -    explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); -    ~Nvnflinger(); - -    void ShutdownLayers(); - -    /// Sets the NVDrv module instance to use to send buffers to the GPU. -    void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance); - -    /// Opens the specified display and returns the ID. -    /// -    /// If an invalid display name is provided, then an empty optional is returned. -    [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name); - -    /// Closes the specified display by its ID. -    /// -    /// Returns false if an invalid display ID is provided. -    [[nodiscard]] bool CloseDisplay(u64 display_id); - -    /// Creates a layer on the specified display and returns the layer ID. -    /// -    /// If an invalid display ID is specified, then an empty optional is returned. -    [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id, -                                                 LayerBlending blending = LayerBlending::None); - -    /// Opens a layer on all displays for the given layer ID. -    bool OpenLayer(u64 layer_id); - -    /// Closes a layer on all displays for the given layer ID. -    bool CloseLayer(u64 layer_id); - -    /// Makes a layer visible on all displays for the given layer ID. -    void SetLayerVisibility(u64 layer_id, bool visible); - -    /// Destroys the given layer ID. -    void DestroyLayer(u64 layer_id); - -    /// Finds the buffer queue ID of the specified layer in the specified display. -    /// -    /// If an invalid display ID or layer ID is provided, then an empty optional is returned. -    [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id); - -    /// Gets the vsync event for the specified display. -    /// -    /// If an invalid display ID is provided, then VI::ResultNotFound is returned. -    /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. -    [[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id); - -    /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when -    /// finished. -    void Compose(); - -    [[nodiscard]] s64 GetNextTicks() const; - -    FbShareBufferManager& GetSystemBufferManager(); - -private: -    struct Layer { -        std::unique_ptr<android::BufferQueueCore> core; -        std::unique_ptr<android::BufferQueueProducer> producer; -    }; - -    friend class FbShareBufferManager; - -private: -    [[nodiscard]] std::unique_lock<std::mutex> Lock() const { -        return std::unique_lock{*guard}; -    } - -    /// Finds the display identified by the specified ID. -    [[nodiscard]] VI::Display* FindDisplay(u64 display_id); - -    /// Finds the display identified by the specified ID. -    [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const; - -    /// Finds the layer identified by the specified ID in the desired display. -    [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id); - -    /// Creates a layer with the specified layer ID in the desired display. -    void CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending); - -    void SplitVSync(std::stop_token stop_token); - -    std::shared_ptr<Nvidia::Module> nvdrv; -    s32 disp_fd; - -    std::list<VI::Display> displays; - -    /// Id to use for the next layer that is created, this counter is shared among all displays. -    u64 next_layer_id = 1; -    /// Id to use for the next buffer queue that is created, this counter is shared among all -    /// layers. -    u32 next_buffer_queue_id = 1; - -    s32 swap_interval = 1; -    f32 compose_speed_scale = 1.0f; - -    bool is_abandoned = false; - -    /// Event that handles screen composition. -    std::shared_ptr<Core::Timing::EventType> multi_composition_event; -    std::shared_ptr<Core::Timing::EventType> single_composition_event; - -    std::unique_ptr<FbShareBufferManager> system_buffer_manager; - -    std::shared_ptr<std::mutex> guard; - -    Core::System& system; - -    Common::Event vsync_signal; - -    std::jthread vsync_thread; - -    KernelHelpers::ServiceContext service_context; - -    HosBinderDriverServer& hos_binder_driver_server; -}; +void LoopProcess(Core::System& system);  } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/surface_flinger.cpp b/src/core/hle/service/nvnflinger/surface_flinger.cpp new file mode 100644 index 000000000..8362b65e5 --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.cpp @@ -0,0 +1,139 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" +#include "core/hle/service/nvdrv/nvdrv_interface.h" +#include "core/hle/service/nvnflinger/display.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/surface_flinger.h" +#include "core/hle/service/sm/sm.h" + +#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" + +namespace Service::Nvnflinger { + +SurfaceFlinger::SurfaceFlinger(Core::System& system, HosBinderDriverServer& server) +    : m_system(system), m_server(server), m_context(m_system, "SurfaceFlinger") { +    nvdrv = m_system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule(); +    disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); +} + +SurfaceFlinger::~SurfaceFlinger() { +    nvdrv->Close(disp_fd); +} + +void SurfaceFlinger::AddDisplay(u64 display_id) { +    m_displays.emplace_back(display_id); +} + +void SurfaceFlinger::RemoveDisplay(u64 display_id) { +    std::erase_if(m_displays, [&](auto& display) { return display.id == display_id; }); +} + +bool SurfaceFlinger::ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, +                                    u64 display_id) { +    auto* const display = this->FindDisplay(display_id); +    if (!display || !display->stack.HasLayers()) { +        return false; +    } + +    *out_swap_interval = +        m_composer.ComposeLocked(out_compose_speed_scale, *display, +                                 *nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd)); +    return true; +} + +void SurfaceFlinger::CreateLayer(s32 consumer_binder_id) { +    auto binder = std::static_pointer_cast<android::BufferQueueConsumer>( +        m_server.TryGetBinder(consumer_binder_id)); +    if (!binder) { +        return; +    } + +    auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(binder)); +    buffer_item_consumer->Connect(false); + +    m_layers.layers.emplace_back( +        std::make_shared<Layer>(std::move(buffer_item_consumer), consumer_binder_id)); +} + +void SurfaceFlinger::DestroyLayer(s32 consumer_binder_id) { +    std::erase_if(m_layers.layers, +                  [&](auto& layer) { return layer->consumer_id == consumer_binder_id; }); +} + +void SurfaceFlinger::AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id) { +    auto* const display = this->FindDisplay(display_id); +    auto layer = this->FindLayer(consumer_binder_id); + +    if (!display || !layer) { +        return; +    } + +    display->stack.layers.emplace_back(std::move(layer)); +} + +void SurfaceFlinger::RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id) { +    auto* const display = this->FindDisplay(display_id); +    if (!display) { +        return; +    } + +    m_composer.RemoveLayerLocked(*display, consumer_binder_id); +    std::erase_if(display->stack.layers, +                  [&](auto& layer) { return layer->consumer_id == consumer_binder_id; }); +} + +void SurfaceFlinger::SetLayerVisibility(s32 consumer_binder_id, bool visible) { +    if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) { +        layer->visible = visible; +        return; +    } +} + +void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blending) { +    if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) { +        layer->blending = blending; +        return; +    } +} + +Display* SurfaceFlinger::FindDisplay(u64 display_id) { +    for (auto& display : m_displays) { +        if (display.id == display_id) { +            return &display; +        } +    } + +    return nullptr; +} + +std::shared_ptr<Layer> SurfaceFlinger::FindLayer(s32 consumer_binder_id) { +    for (auto& layer : m_layers.layers) { +        if (layer->consumer_id == consumer_binder_id) { +            return layer; +        } +    } + +    return nullptr; +} + +void SurfaceFlinger::CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id) { +    auto& nvmap = nvdrv->GetContainer().GetNvMapFile(); +    auto core = std::make_shared<android::BufferQueueCore>(); +    auto producer = std::make_shared<android::BufferQueueProducer>(m_context, core, nvmap); +    auto consumer = std::make_shared<android::BufferQueueConsumer>(core); + +    *out_consumer_binder_id = m_server.RegisterBinder(std::move(consumer)); +    *out_producer_binder_id = m_server.RegisterBinder(std::move(producer)); +} + +void SurfaceFlinger::DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id) { +    m_server.UnregisterBinder(producer_binder_id); +    m_server.UnregisterBinder(consumer_binder_id); +} + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/surface_flinger.h b/src/core/hle/service/nvnflinger/surface_flinger.h new file mode 100644 index 000000000..406281c83 --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.h @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <vector> + +#include "common/common_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nvnflinger/hardware_composer.h" + +namespace Core { +class System; +} + +namespace Service::Nvidia { +class Module; +} + +// TODO: ISurfaceComposer +// TODO: ISurfaceComposerClient + +namespace Service::Nvnflinger { + +struct Display; +class HosBinderDriverServer; +enum class LayerBlending : u32; +struct Layer; + +class SurfaceFlinger { +public: +    explicit SurfaceFlinger(Core::System& system, HosBinderDriverServer& server); +    ~SurfaceFlinger(); + +    void AddDisplay(u64 display_id); +    void RemoveDisplay(u64 display_id); +    bool ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id); + +    void CreateLayer(s32 consumer_binder_id); +    void DestroyLayer(s32 consumer_binder_id); + +    void AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id); +    void RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id); + +    void SetLayerVisibility(s32 consumer_binder_id, bool visible); +    void SetLayerBlending(s32 consumer_binder_id, LayerBlending blending); + +private: +    Display* FindDisplay(u64 display_id); +    std::shared_ptr<Layer> FindLayer(s32 consumer_binder_id); + +public: +    // TODO: these don't belong here +    void CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id); +    void DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id); + +private: +    Core::System& m_system; +    HosBinderDriverServer& m_server; +    KernelHelpers::ServiceContext m_context; + +    std::vector<Display> m_displays; +    LayerStack m_layers; +    std::shared_ptr<Nvidia::Module> nvdrv; +    s32 disp_fd; +    HardwareComposer m_composer; +}; + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp index 24b85cc61..9a0adb295 100644 --- a/src/core/hle/service/psc/time/static.cpp +++ b/src/core/hle/service/psc/time/static.cpp @@ -144,7 +144,9 @@ Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {  Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(      Out<bool> out_is_enabled) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); +    };      R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); @@ -180,7 +182,9 @@ Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {  }  Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); +    };      *out_is_sufficient = m_network_system_clock.IsAccuracySufficient(); @@ -189,7 +193,9 @@ Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> o  Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(      Out<SteadyClockTimePoint> out_time_point) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); +    };      R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); @@ -200,7 +206,9 @@ Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(  Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(      Out<s64> out_time, const SystemClockContext& context) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); +    };      R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized); @@ -219,8 +227,9 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(  }  Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) { -    SCOPE_EXIT( -        { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); +    };      SystemClockContext user_context{};      R_TRY(m_user_system_clock.GetContext(user_context)); @@ -234,11 +243,11 @@ Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType t  Result StaticService::GetClockSnapshotFromSystemClockContext(      TimeType type, OutClockSnapshot out_snapshot, const SystemClockContext& user_context,      const SystemClockContext& network_context) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time,                    "called. type={} user_context={} network_context={} out_snapshot={}", type,                    user_context, network_context, *out_snapshot); -    }); +    };      R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));  } @@ -246,9 +255,9 @@ Result StaticService::GetClockSnapshotFromSystemClockContext(  Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,                                                                         InClockSnapshot a,                                                                         InClockSnapshot b) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference); -    }); +    };      auto diff_s =          std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset); @@ -276,7 +285,9 @@ Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64>  Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,                                             InClockSnapshot b) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); +    };      s64 time_s{};      auto res = diff --git a/src/core/hle/service/psc/time/steady_clock.cpp b/src/core/hle/service/psc/time/steady_clock.cpp index 948610a2b..78dcf532c 100644 --- a/src/core/hle/service/psc/time/steady_clock.cpp +++ b/src/core/hle/service/psc/time/steady_clock.cpp @@ -29,7 +29,9 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man  }  Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); +    };      R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),               ResultClockUninitialized); @@ -38,7 +40,9 @@ Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point  }  Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); +    };      R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),               ResultClockUninitialized); @@ -59,7 +63,9 @@ Result SteadyClock::SetTestOffset(s64 test_offset) {  }  Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); +    };      R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),               ResultClockUninitialized); @@ -68,7 +74,9 @@ Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) {  }  Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); +    };      R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),               ResultClockUninitialized); @@ -78,7 +86,9 @@ Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) {  }  Result SteadyClock::GetSetupResultValue(Out<Result> out_result) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); +    };      R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),               ResultClockUninitialized); @@ -88,8 +98,9 @@ Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {  }  Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) { -    SCOPE_EXIT( -        { LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); +    };      R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),               ResultClockUninitialized); diff --git a/src/core/hle/service/psc/time/system_clock.cpp b/src/core/hle/service/psc/time/system_clock.cpp index b4e9264d8..9f841d8e0 100644 --- a/src/core/hle/service/psc/time/system_clock.cpp +++ b/src/core/hle/service/psc/time/system_clock.cpp @@ -26,7 +26,9 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo  }  Result SystemClock::GetCurrentTime(Out<s64> out_time) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); +    };      R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),               ResultClockUninitialized); @@ -45,7 +47,9 @@ Result SystemClock::SetCurrentTime(s64 time) {  }  Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); +    };      R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),               ResultClockUninitialized); diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp index 2f80030a4..9e0674f27 100644 --- a/src/core/hle/service/psc/time/time_zone_service.cpp +++ b/src/core/hle/service/psc/time/time_zone_service.cpp @@ -37,7 +37,9 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore&  }  Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); +    };      R_RETURN(m_time_zone.GetLocationName(*out_location_name));  } @@ -50,7 +52,9 @@ Result TimeZoneService::SetDeviceLocationName(const LocationName& location_name)  }  Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); +    };      R_RETURN(m_time_zone.GetTotalLocationCount(*out_count));  } @@ -69,17 +73,19 @@ Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, const LocationName& l  }  Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) { -    SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); +    SCOPE_EXIT { +        LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); +    };      R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version));  }  Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(      Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}",                    *out_location_name, *out_time_point); -    }); +    };      R_TRY(m_time_zone.GetLocationName(*out_location_name));      R_RETURN(m_time_zone.GetTimePoint(*out_time_point)); @@ -116,10 +122,10 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(  Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time,                                         Out<CalendarAdditionalInfo> out_additional_info, s64 time,                                         InRule rule) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,                    *out_calendar_time, *out_additional_info); -    }); +    };      R_RETURN(          m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get())); @@ -128,10 +134,10 @@ Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time,  Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,                                                   Out<CalendarAdditionalInfo> out_additional_info,                                                   s64 time) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,                    *out_calendar_time, *out_additional_info); -    }); +    };      R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time));  } @@ -139,11 +145,11 @@ Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_  Result TimeZoneService::ToPosixTime(Out<u32> out_count,                                      OutArray<s64, BufferAttr_HipcPointer> out_times,                                      const CalendarTime& calendar_time, InRule rule) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time,                    "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",                    calendar_time, *out_count, out_times[0], out_times[1]); -    }); +    };      R_RETURN(          m_time_zone.ToPosixTime(*out_count, out_times, out_times.size(), calendar_time, *rule)); @@ -152,11 +158,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,  Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,                                                OutArray<s64, BufferAttr_HipcPointer> out_times,                                                const CalendarTime& calendar_time) { -    SCOPE_EXIT({ +    SCOPE_EXIT {          LOG_DEBUG(Service_Time,                    "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",                    calendar_time, *out_count, out_times[0], out_times[1]); -    }); +    };      R_RETURN(          m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time)); diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index 8c7f94c8c..0b41bbcb9 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp @@ -177,10 +177,10 @@ Result ServerManager::ManageNamedPort(const std::string& service_name,      Kernel::KPort::Register(m_system.Kernel(), port);      // Ensure that our reference to the port is closed if we fail to register it. -    SCOPE_EXIT({ +    SCOPE_EXIT {          port->GetClientPort().Close();          port->GetServerPort().Close(); -    }); +    };      // Register the object name with the kernel.      R_TRY(Kernel::KObjectName::NewFromName(m_system.Kernel(), std::addressof(port->GetClientPort()), @@ -237,7 +237,9 @@ void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_thre  }  Result ServerManager::LoopProcess() { -    SCOPE_EXIT({ m_stopped.Set(); }); +    SCOPE_EXIT { +        m_stopped.Set(); +    };      R_RETURN(this->LoopProcessImpl());  } diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index fbdf217ba..ce5e3b5b4 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -7,68 +7,10 @@  #include "common/settings.h"  #include "core/core.h"  #include "core/hle/ipc.h" -#include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/k_server_port.h"  #include "core/hle/kernel/kernel.h" -#include "core/hle/service/acc/acc.h" -#include "core/hle/service/am/am.h" -#include "core/hle/service/aoc/aoc_u.h" -#include "core/hle/service/apm/apm.h" -#include "core/hle/service/audio/audio.h" -#include "core/hle/service/bcat/bcat.h" -#include "core/hle/service/bpc/bpc.h" -#include "core/hle/service/btdrv/btdrv.h" -#include "core/hle/service/btm/btm.h" -#include "core/hle/service/caps/caps.h" -#include "core/hle/service/erpt/erpt.h" -#include "core/hle/service/es/es.h" -#include "core/hle/service/eupld/eupld.h" -#include "core/hle/service/fatal/fatal.h" -#include "core/hle/service/fgm/fgm.h" -#include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/friend/friend.h" -#include "core/hle/service/glue/glue.h" -#include "core/hle/service/grc/grc.h" -#include "core/hle/service/hid/hid.h"  #include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/jit/jit.h" -#include "core/hle/service/lbl/lbl.h" -#include "core/hle/service/ldn/ldn.h" -#include "core/hle/service/ldr/ldr.h" -#include "core/hle/service/lm/lm.h" -#include "core/hle/service/mig/mig.h" -#include "core/hle/service/mii/mii.h" -#include "core/hle/service/mm/mm_u.h" -#include "core/hle/service/mnpp/mnpp_app.h" -#include "core/hle/service/ncm/ncm.h" -#include "core/hle/service/nfc/nfc.h" -#include "core/hle/service/nfp/nfp.h" -#include "core/hle/service/ngc/ngc.h" -#include "core/hle/service/nifm/nifm.h" -#include "core/hle/service/nim/nim.h" -#include "core/hle/service/npns/npns.h" -#include "core/hle/service/ns/ns.h" -#include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/olsc/olsc.h" -#include "core/hle/service/omm/omm.h" -#include "core/hle/service/pcie/pcie.h" -#include "core/hle/service/pctl/pctl_module.h" -#include "core/hle/service/pcv/pcv.h" -#include "core/hle/service/pm/pm.h" -#include "core/hle/service/prepo/prepo.h" -#include "core/hle/service/psc/psc.h" -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/ro/ro.h"  #include "core/hle/service/service.h" -#include "core/hle/service/set/settings.h"  #include "core/hle/service/sm/sm.h" -#include "core/hle/service/sockets/sockets.h" -#include "core/hle/service/spl/spl_module.h" -#include "core/hle/service/ssl/ssl.h" -#include "core/hle/service/usb/usb.h" -#include "core/hle/service/vi/vi.h"  #include "core/reporter.h"  namespace Service { @@ -209,82 +151,4 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,      return result;  } -/// Initialize Services -Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) -    : hos_binder_driver_server{std::make_unique<Nvnflinger::HosBinderDriverServer>(system)}, -      nv_flinger{std::make_unique<Nvnflinger::Nvnflinger>(system, *hos_binder_driver_server)} { - -    auto& kernel = system.Kernel(); - -    // Nvnflinger needs to be accessed by several services like Vi and AppletOE so we instantiate it -    // here and pass it into the respective InstallInterfaces functions. -    system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); - -    // clang-format off -    kernel.RunOnHostCoreProcess("audio",      [&] { Audio::LoopProcess(system); }).detach(); -    kernel.RunOnHostCoreProcess("FS",         [&] { FileSystem::LoopProcess(system); }).detach(); -    kernel.RunOnHostCoreProcess("jit",        [&] { JIT::LoopProcess(system); }).detach(); -    kernel.RunOnHostCoreProcess("ldn",        [&] { LDN::LoopProcess(system); }).detach(); -    kernel.RunOnHostCoreProcess("Loader",     [&] { LDR::LoopProcess(system); }).detach(); -    kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(*nv_flinger, system); }).detach(); -    kernel.RunOnHostCoreProcess("bsdsocket",  [&] { Sockets::LoopProcess(system); }).detach(); -    kernel.RunOnHostCoreProcess("vi",         [&] { VI::LoopProcess(system, *nv_flinger, *hos_binder_driver_server); }).detach(); - -    kernel.RunOnGuestCoreProcess("sm",         [&] { SM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("account",    [&] { Account::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("am",         [&] { AM::LoopProcess(*nv_flinger, system); }); -    kernel.RunOnGuestCoreProcess("aoc",        [&] { AOC::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("apm",        [&] { APM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("bcat",       [&] { BCAT::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("bpc",        [&] { BPC::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("btdrv",      [&] { BtDrv::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("btm",        [&] { BTM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("capsrv",     [&] { Capture::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("erpt",       [&] { ERPT::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("es",         [&] { ES::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("eupld",      [&] { EUPLD::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("fatal",      [&] { Fatal::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("fgm",        [&] { FGM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("friends",    [&] { Friend::LoopProcess(system); }); -    // glue depends on settings and psc, so they must come first -    kernel.RunOnGuestCoreProcess("settings",   [&] { Set::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("psc",        [&] { PSC::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("glue",       [&] { Glue::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("grc",        [&] { GRC::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("hid",        [&] { HID::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("lbl",        [&] { LBL::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("mig",        [&] { Migration::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("mii",        [&] { Mii::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("mm",         [&] { MM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("mnpp",       [&] { MNPP::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("NCM",        [&] { NCM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("nfc",        [&] { NFC::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("nfp",        [&] { NFP::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("ngc",        [&] { NGC::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("nifm",       [&] { NIFM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("nim",        [&] { NIM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("npns",       [&] { NPNS::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("ns",         [&] { NS::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("olsc",       [&] { OLSC::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("omm",        [&] { OMM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("pcie",       [&] { PCIe::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("pctl",       [&] { PCTL::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("pcv",        [&] { PCV::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("prepo",      [&] { PlayReport::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("ptm",        [&] { PTM::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("ro",         [&] { RO::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("spl",        [&] { SPL::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("ssl",        [&] { SSL::LoopProcess(system); }); -    kernel.RunOnGuestCoreProcess("usb",        [&] { USB::LoopProcess(system); }); -    // clang-format on -} - -Services::~Services() = default; - -void Services::KillNVNFlinger() { -    nv_flinger->ShutdownLayers(); -} -  } // namespace Service diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 22d1343d5..36aae1c79 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -28,11 +28,6 @@ namespace FileSystem {  class FileSystemController;  } -namespace Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Nvnflinger -  namespace SM {  class ServiceManager;  } @@ -236,20 +231,4 @@ private:      }  }; -/** - * The purpose of this class is to own any objects that need to be shared across the other service - * implementations. Will be torn down when the global system instance is shutdown. - */ -class Services final { -public: -    explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); -    ~Services(); - -    void KillNVNFlinger(); - -private: -    std::unique_ptr<Nvnflinger::HosBinderDriverServer> hos_binder_driver_server; -    std::unique_ptr<Nvnflinger::Nvnflinger> nv_flinger; -}; -  } // namespace Service diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp new file mode 100644 index 000000000..d6c6eff50 --- /dev/null +++ b/src/core/hle/service/services.cpp @@ -0,0 +1,136 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/services.h" + +#include "core/hle/service/acc/acc.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/aoc/aoc_u.h" +#include "core/hle/service/apm/apm.h" +#include "core/hle/service/audio/audio.h" +#include "core/hle/service/bcat/bcat.h" +#include "core/hle/service/bpc/bpc.h" +#include "core/hle/service/btdrv/btdrv.h" +#include "core/hle/service/btm/btm.h" +#include "core/hle/service/caps/caps.h" +#include "core/hle/service/erpt/erpt.h" +#include "core/hle/service/es/es.h" +#include "core/hle/service/eupld/eupld.h" +#include "core/hle/service/fatal/fatal.h" +#include "core/hle/service/fgm/fgm.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/friend/friend.h" +#include "core/hle/service/glue/glue.h" +#include "core/hle/service/grc/grc.h" +#include "core/hle/service/hid/hid.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/jit/jit.h" +#include "core/hle/service/lbl/lbl.h" +#include "core/hle/service/ldn/ldn.h" +#include "core/hle/service/ldr/ldr.h" +#include "core/hle/service/lm/lm.h" +#include "core/hle/service/mig/mig.h" +#include "core/hle/service/mii/mii.h" +#include "core/hle/service/mm/mm_u.h" +#include "core/hle/service/mnpp/mnpp_app.h" +#include "core/hle/service/ncm/ncm.h" +#include "core/hle/service/nfc/nfc.h" +#include "core/hle/service/nfp/nfp.h" +#include "core/hle/service/ngc/ngc.h" +#include "core/hle/service/nifm/nifm.h" +#include "core/hle/service/nim/nim.h" +#include "core/hle/service/npns/npns.h" +#include "core/hle/service/ns/ns.h" +#include "core/hle/service/nvdrv/nvdrv.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/olsc/olsc.h" +#include "core/hle/service/omm/omm.h" +#include "core/hle/service/pcie/pcie.h" +#include "core/hle/service/pctl/pctl_module.h" +#include "core/hle/service/pcv/pcv.h" +#include "core/hle/service/pm/pm.h" +#include "core/hle/service/prepo/prepo.h" +#include "core/hle/service/psc/psc.h" +#include "core/hle/service/ptm/ptm.h" +#include "core/hle/service/ro/ro.h" +#include "core/hle/service/service.h" +#include "core/hle/service/set/settings.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/sockets/sockets.h" +#include "core/hle/service/spl/spl_module.h" +#include "core/hle/service/ssl/ssl.h" +#include "core/hle/service/usb/usb.h" +#include "core/hle/service/vi/vi.h" + +namespace Service { + +Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, +                   std::stop_token token) { +    auto& kernel = system.Kernel(); + +    system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); + +    // clang-format off +    kernel.RunOnHostCoreProcess("audio",      [&] { Audio::LoopProcess(system); }).detach(); +    kernel.RunOnHostCoreProcess("FS",         [&] { FileSystem::LoopProcess(system); }).detach(); +    kernel.RunOnHostCoreProcess("jit",        [&] { JIT::LoopProcess(system); }).detach(); +    kernel.RunOnHostCoreProcess("ldn",        [&] { LDN::LoopProcess(system); }).detach(); +    kernel.RunOnHostCoreProcess("Loader",     [&] { LDR::LoopProcess(system); }).detach(); +    kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(system); }).detach(); +    kernel.RunOnHostCoreProcess("bsdsocket",  [&] { Sockets::LoopProcess(system); }).detach(); +    kernel.RunOnHostCoreProcess("vi",         [&, token] { VI::LoopProcess(system, token); }).detach(); + +    kernel.RunOnGuestCoreProcess("sm",         [&] { SM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("account",    [&] { Account::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("am",         [&] { AM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("aoc",        [&] { AOC::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("apm",        [&] { APM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("bcat",       [&] { BCAT::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("bpc",        [&] { BPC::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("btdrv",      [&] { BtDrv::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("btm",        [&] { BTM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("capsrv",     [&] { Capture::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("erpt",       [&] { ERPT::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("es",         [&] { ES::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("eupld",      [&] { EUPLD::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("fatal",      [&] { Fatal::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("fgm",        [&] { FGM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("friends",    [&] { Friend::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("settings",   [&] { Set::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("psc",        [&] { PSC::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("glue",       [&] { Glue::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("grc",        [&] { GRC::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("hid",        [&] { HID::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("lbl",        [&] { LBL::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("mig",        [&] { Migration::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("mii",        [&] { Mii::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("mm",         [&] { MM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("mnpp",       [&] { MNPP::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("nvnflinger", [&] { Nvnflinger::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("NCM",        [&] { NCM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("nfc",        [&] { NFC::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("nfp",        [&] { NFP::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("ngc",        [&] { NGC::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("nifm",       [&] { NIFM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("nim",        [&] { NIM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("npns",       [&] { NPNS::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("ns",         [&] { NS::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("olsc",       [&] { OLSC::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("omm",        [&] { OMM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("pcie",       [&] { PCIe::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("pctl",       [&] { PCTL::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("pcv",        [&] { PCV::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("prepo",      [&] { PlayReport::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("ptm",        [&] { PTM::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("ro",         [&] { RO::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("spl",        [&] { SPL::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("ssl",        [&] { SSL::LoopProcess(system); }); +    kernel.RunOnGuestCoreProcess("usb",        [&] { USB::LoopProcess(system); }); +    // clang-format on +} + +Services::~Services() = default; + +} // namespace Service diff --git a/src/core/hle/service/services.h b/src/core/hle/service/services.h new file mode 100644 index 000000000..a99fa1e53 --- /dev/null +++ b/src/core/hle/service/services.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/polyfill_thread.h" +#include "core/hle/service/sm/sm.h" + +namespace Service { + +/** + * The purpose of this class is to own any objects that need to be shared across the other service + * implementations. Will be torn down when the global system instance is shutdown. + */ +class Services final { +public: +    explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, +                      std::stop_token token); +    ~Services(); +}; + +} // namespace Service diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp index 78229e30f..6b0bcb536 100644 --- a/src/core/hle/service/vi/application_display_service.cpp +++ b/src/core/hle/service/vi/application_display_service.cpp @@ -2,22 +2,21 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "core/hle/service/cmif_serialization.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h"  #include "core/hle/service/nvnflinger/parcel.h" +#include "core/hle/service/os/event.h"  #include "core/hle/service/vi/application_display_service.h" -#include "core/hle/service/vi/hos_binder_driver.h" +#include "core/hle/service/vi/container.h"  #include "core/hle/service/vi/manager_display_service.h"  #include "core/hle/service/vi/system_display_service.h"  #include "core/hle/service/vi/vi_results.h"  namespace Service::VI { -IApplicationDisplayService::IApplicationDisplayService( -    Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, -    Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) -    : ServiceFramework{system_, "IApplicationDisplayService"}, m_nvnflinger{nvnflinger}, -      m_hos_binder_driver_server{hos_binder_driver_server} { - +IApplicationDisplayService::IApplicationDisplayService(Core::System& system_, +                                                       std::shared_ptr<Container> container) +    : ServiceFramework{system_, "IApplicationDisplayService"}, +      m_container{std::move(container)}, m_context{system, "IApplicationDisplayService"} {      // clang-format off      static const FunctionInfo functions[] = {          {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, @@ -48,38 +47,41 @@ IApplicationDisplayService::IApplicationDisplayService(  }  IApplicationDisplayService::~IApplicationDisplayService() { +    for (auto& [display_id, event] : m_display_vsync_events) { +        m_container->UnlinkVsyncEvent(display_id, &event); +    } +    for (const auto layer_id : m_open_layer_ids) { +        m_container->CloseLayer(layer_id); +    }      for (const auto layer_id : m_stray_layer_ids) { -        m_nvnflinger.DestroyLayer(layer_id); +        m_container->DestroyStrayLayer(layer_id);      }  }  Result IApplicationDisplayService::GetRelayService( -    Out<SharedPointer<IHOSBinderDriver>> out_relay_service) { +    Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service) {      LOG_WARNING(Service_VI, "(STUBBED) called"); -    *out_relay_service = std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server); -    R_SUCCEED(); +    R_RETURN(m_container->GetBinderDriver(out_relay_service));  }  Result IApplicationDisplayService::GetSystemDisplayService(      Out<SharedPointer<ISystemDisplayService>> out_system_display_service) {      LOG_WARNING(Service_VI, "(STUBBED) called"); -    *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_nvnflinger); +    *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_container);      R_SUCCEED();  }  Result IApplicationDisplayService::GetManagerDisplayService(      Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) {      LOG_WARNING(Service_VI, "(STUBBED) called"); -    *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_nvnflinger); +    *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_container);      R_SUCCEED();  }  Result IApplicationDisplayService::GetIndirectDisplayTransactionService( -    Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service) { +    Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service) {      LOG_WARNING(Service_VI, "(STUBBED) called"); -    *out_indirect_display_transaction_service = -        std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server); -    R_SUCCEED(); +    R_RETURN(m_container->GetBinderDriver(out_indirect_display_transaction_service));  }  Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { @@ -89,14 +91,7 @@ Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayN      ASSERT_MSG(strcmp(display_name.data(), "Default") == 0,                 "Non-default displays aren't supported yet"); -    const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); -    if (!display_id) { -        LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data()); -        R_THROW(VI::ResultNotFound); -    } - -    *out_display_id = *display_id; -    R_SUCCEED(); +    R_RETURN(m_container->OpenDisplay(out_display_id, display_name));  }  Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { @@ -106,8 +101,7 @@ Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) {  Result IApplicationDisplayService::CloseDisplay(u64 display_id) {      LOG_DEBUG(Service_VI, "called"); -    R_SUCCEED_IF(m_nvnflinger.CloseDisplay(display_id)); -    R_THROW(ResultUnknown); +    R_RETURN(m_container->CloseDisplay(display_id));  }  Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { @@ -168,25 +162,19 @@ Result IApplicationDisplayService::OpenLayer(Out<u64> out_size,      LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid); -    const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); -    if (!display_id) { -        LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); -        R_THROW(VI::ResultNotFound); -    } +    u64 display_id; +    R_TRY(m_container->OpenDisplay(&display_id, display_name)); -    const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(*display_id, layer_id); -    if (!buffer_queue_id) { -        LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); -        R_THROW(VI::ResultNotFound); -    } +    s32 producer_binder_id; +    R_TRY(m_container->OpenLayer(&producer_binder_id, layer_id, aruid.pid)); -    if (!m_nvnflinger.OpenLayer(layer_id)) { -        LOG_WARNING(Service_VI, "Tried to open layer which was already open"); -        R_THROW(VI::ResultOperationFailed); +    { +        std::scoped_lock lk{m_lock}; +        m_open_layer_ids.insert(layer_id);      }      android::OutputParcel parcel; -    parcel.WriteInterface(NativeWindow{*buffer_queue_id}); +    parcel.WriteInterface(NativeWindow{producer_binder_id});      const auto buffer = parcel.Serialize();      std::memcpy(out_native_window.data(), buffer.data(), @@ -199,12 +187,13 @@ Result IApplicationDisplayService::OpenLayer(Out<u64> out_size,  Result IApplicationDisplayService::CloseLayer(u64 layer_id) {      LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); -    if (!m_nvnflinger.CloseLayer(layer_id)) { -        LOG_WARNING(Service_VI, "Tried to close layer which was not open"); -        R_THROW(VI::ResultOperationFailed); +    { +        std::scoped_lock lk{m_lock}; +        R_UNLESS(m_open_layer_ids.contains(layer_id), VI::ResultNotFound); +        m_open_layer_ids.erase(layer_id);      } -    R_SUCCEED(); +    R_RETURN(m_container->CloseLayer(layer_id));  }  Result IApplicationDisplayService::CreateStrayLayer( @@ -212,27 +201,19 @@ Result IApplicationDisplayService::CreateStrayLayer(      u32 flags, u64 display_id) {      LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); -    const auto layer_id = m_nvnflinger.CreateLayer(display_id); -    if (!layer_id) { -        LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); -        R_THROW(VI::ResultNotFound); -    } +    s32 producer_binder_id; +    R_TRY(m_container->CreateStrayLayer(&producer_binder_id, out_layer_id, display_id)); -    m_stray_layer_ids.push_back(*layer_id); -    const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(display_id, *layer_id); -    if (!buffer_queue_id) { -        LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); -        R_THROW(VI::ResultNotFound); -    } +    std::scoped_lock lk{m_lock}; +    m_stray_layer_ids.insert(*out_layer_id);      android::OutputParcel parcel; -    parcel.WriteInterface(NativeWindow{*buffer_queue_id}); +    parcel.WriteInterface(NativeWindow{producer_binder_id});      const auto buffer = parcel.Serialize();      std::memcpy(out_native_window.data(), buffer.data(),                  std::min(out_native_window.size(), buffer.size())); -    *out_layer_id = *layer_id;      *out_size = buffer.size();      R_SUCCEED(); @@ -240,25 +221,27 @@ Result IApplicationDisplayService::CreateStrayLayer(  Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) {      LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); -    m_nvnflinger.DestroyLayer(layer_id); -    R_SUCCEED(); + +    { +        std::scoped_lock lk{m_lock}; +        R_UNLESS(m_stray_layer_ids.contains(layer_id), VI::ResultNotFound); +        m_stray_layer_ids.erase(layer_id); +    } + +    R_RETURN(m_container->DestroyStrayLayer(layer_id));  }  Result IApplicationDisplayService::GetDisplayVsyncEvent(      OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) {      LOG_DEBUG(Service_VI, "called. display_id={}", display_id); -    const auto result = m_nvnflinger.FindVsyncEvent(out_vsync_event, display_id); -    if (result != ResultSuccess) { -        if (result == ResultNotFound) { -            LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); -        } +    std::scoped_lock lk{m_lock}; -        R_THROW(result); -    } +    auto [it, created] = m_display_vsync_events.emplace(display_id, m_context); +    R_UNLESS(created, VI::ResultPermissionDenied); -    R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied); -    m_vsync_event_fetched = true; +    m_container->LinkVsyncEvent(display_id, &it->second); +    *out_vsync_event = it->second.GetHandle();      R_SUCCEED();  } diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h index 5dff4bb31..1bdeb8f84 100644 --- a/src/core/hle/service/vi/application_display_service.h +++ b/src/core/hle/service/vi/application_display_service.h @@ -1,7 +1,12 @@  // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include <map> +#include <set> +  #include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/os/event.h"  #include "core/hle/service/service.h"  #include "core/hle/service/vi/vi_types.h" @@ -9,26 +14,33 @@ namespace Kernel {  class KReadableEvent;  } +namespace Service::Nvnflinger { +class IHOSBinderDriver; +} +  namespace Service::VI { -class IHOSBinderDriver; +class Container;  class IManagerDisplayService;  class ISystemDisplayService;  class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {  public: -    IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, -                               Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); +    IApplicationDisplayService(Core::System& system_, std::shared_ptr<Container> container);      ~IApplicationDisplayService() override; -private: -    Result GetRelayService(Out<SharedPointer<IHOSBinderDriver>> out_relay_service); +    std::shared_ptr<Container> GetContainer() const { +        return m_container; +    } + +public: +    Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service);      Result GetSystemDisplayService(          Out<SharedPointer<ISystemDisplayService>> out_system_display_service);      Result GetManagerDisplayService(          Out<SharedPointer<IManagerDisplayService>> out_manager_display_service);      Result GetIndirectDisplayTransactionService( -        Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service); +        Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service);      Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name);      Result OpenDefaultDisplay(Out<u64> out_display_id);      Result CloseDisplay(u64 display_id); @@ -56,9 +68,13 @@ private:                                                     s64 width, s64 height);  private: -    Nvnflinger::Nvnflinger& m_nvnflinger; -    Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; -    std::vector<u64> m_stray_layer_ids; +    const std::shared_ptr<Container> m_container; + +    KernelHelpers::ServiceContext m_context; +    std::mutex m_lock{}; +    std::set<u64> m_open_layer_ids{}; +    std::set<u64> m_stray_layer_ids{}; +    std::map<u64, Event> m_display_vsync_events{};      bool m_vsync_event_fetched{false};  }; diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp index 7af7f062c..7f35a048d 100644 --- a/src/core/hle/service/vi/application_root_service.cpp +++ b/src/core/hle/service/vi/application_root_service.cpp @@ -4,17 +4,16 @@  #include "core/hle/service/cmif_serialization.h"  #include "core/hle/service/vi/application_display_service.h"  #include "core/hle/service/vi/application_root_service.h" +#include "core/hle/service/vi/container.h"  #include "core/hle/service/vi/service_creator.h"  #include "core/hle/service/vi/vi.h"  #include "core/hle/service/vi/vi_types.h"  namespace Service::VI { -IApplicationRootService::IApplicationRootService( -    Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, -    Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) -    : ServiceFramework{system_, "vi:u"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ -                                                                       hos_binder_driver_server} { +IApplicationRootService::IApplicationRootService(Core::System& system_, +                                                 std::shared_ptr<Container> container) +    : ServiceFramework{system_, "vi:u"}, m_container{std::move(container)} {      static const FunctionInfo functions[] = {          {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"},          {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -27,8 +26,8 @@ IApplicationRootService::~IApplicationRootService() = default;  Result IApplicationRootService::GetDisplayService(      Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {      LOG_DEBUG(Service_VI, "called"); -    R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, -                                          m_hos_binder_driver_server, Permission::User, policy)); +    R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, +                                          Permission::User, policy));  }  } // namespace Service::VI diff --git a/src/core/hle/service/vi/application_root_service.h b/src/core/hle/service/vi/application_root_service.h index 9dbf28cb4..15aa4483d 100644 --- a/src/core/hle/service/vi/application_root_service.h +++ b/src/core/hle/service/vi/application_root_service.h @@ -10,20 +10,15 @@ namespace Core {  class System;  } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger -  namespace Service::VI { +class Container;  class IApplicationDisplayService;  enum class Policy : u32;  class IApplicationRootService final : public ServiceFramework<IApplicationRootService> {  public: -    explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, -                                     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); +    explicit IApplicationRootService(Core::System& system_, std::shared_ptr<Container> container);      ~IApplicationRootService() override;  private: @@ -32,8 +27,7 @@ private:          Policy policy);  private: -    Nvnflinger::Nvnflinger& m_nvnflinger; -    Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; +    const std::shared_ptr<Container> m_container;  };  } // namespace Service::VI diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp new file mode 100644 index 000000000..c8ce4fca0 --- /dev/null +++ b/src/core/hle/service/vi/conductor.cpp @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "core/core.h" +#include "core/core_timing.h" +#include "core/hle/service/vi/conductor.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/display_list.h" +#include "core/hle/service/vi/vsync_manager.h" + +constexpr auto FrameNs = std::chrono::nanoseconds{1000000000 / 60}; + +namespace Service::VI { + +Conductor::Conductor(Core::System& system, Container& container, DisplayList& displays) +    : m_system(system), m_container(container) { +    displays.ForEachDisplay([&](Display& display) { +        m_vsync_managers.insert({display.GetId(), VsyncManager{}}); +    }); + +    if (system.IsMulticore()) { +        m_event = Core::Timing::CreateEvent( +            "ScreenComposition", +            [this](s64 time, +                   std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { +                m_signal.Set(); +                return std::chrono::nanoseconds(this->GetNextTicks()); +            }); + +        system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); +        m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); }); +    } else { +        m_event = Core::Timing::CreateEvent( +            "ScreenComposition", +            [this](s64 time, +                   std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { +                this->ProcessVsync(); +                return std::chrono::nanoseconds(this->GetNextTicks()); +            }); + +        system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); +    } +} + +Conductor::~Conductor() { +    m_system.CoreTiming().UnscheduleEvent(m_event); + +    if (m_system.IsMulticore()) { +        m_thread.request_stop(); +        m_signal.Set(); +    } +} + +void Conductor::LinkVsyncEvent(u64 display_id, Event* event) { +    if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) { +        it->second.LinkVsyncEvent(event); +    } +} + +void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) { +    if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) { +        it->second.UnlinkVsyncEvent(event); +    } +} + +void Conductor::ProcessVsync() { +    for (auto& [display_id, manager] : m_vsync_managers) { +        m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id); +        manager.SignalVsync(); +    } +} + +void Conductor::VsyncThread(std::stop_token token) { +    Common::SetCurrentThreadName("VSyncThread"); + +    while (!token.stop_requested()) { +        m_signal.Wait(); + +        if (m_system.IsShuttingDown()) { +            return; +        } + +        this->ProcessVsync(); +    } +} + +s64 Conductor::GetNextTicks() const { +    const auto& settings = Settings::values; +    auto speed_scale = 1.f; +    if (settings.use_multi_core.GetValue()) { +        if (settings.use_speed_limit.GetValue()) { +            // Scales the speed based on speed_limit setting on MC. SC is handled by +            // SpeedLimiter::DoSpeedLimiting. +            speed_scale = 100.f / settings.speed_limit.GetValue(); +        } else { +            // Run at unlocked framerate. +            speed_scale = 0.01f; +        } +    } + +    // Adjust by speed limit determined during composition. +    speed_scale /= m_compose_speed_scale; + +    if (m_system.GetNVDECActive() && settings.use_video_framerate.GetValue()) { +        // Run at intended presentation rate during video playback. +        speed_scale = 1.f; +    } + +    const f32 effective_fps = 60.f / static_cast<f32>(m_swap_interval); +    return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/conductor.h b/src/core/hle/service/vi/conductor.h new file mode 100644 index 000000000..52e3595d2 --- /dev/null +++ b/src/core/hle/service/vi/conductor.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <memory> +#include <unordered_map> + +#include "common/common_types.h" +#include "common/polyfill_thread.h" +#include "common/thread.h" + +namespace Core { +class System; +} + +namespace Core::Timing { +struct EventType; +} + +namespace Service { +class Event; +} + +namespace Service::VI { + +class Container; +class DisplayList; +class VsyncManager; + +class Conductor { +public: +    explicit Conductor(Core::System& system, Container& container, DisplayList& displays); +    ~Conductor(); + +    void LinkVsyncEvent(u64 display_id, Event* event); +    void UnlinkVsyncEvent(u64 display_id, Event* event); + +private: +    void ProcessVsync(); +    void VsyncThread(std::stop_token token); +    s64 GetNextTicks() const; + +private: +    Core::System& m_system; +    Container& m_container; +    std::unordered_map<u64, VsyncManager> m_vsync_managers; +    std::shared_ptr<Core::Timing::EventType> m_event; +    Common::Event m_signal; +    std::jthread m_thread; + +private: +    s32 m_swap_interval = 1; +    f32 m_compose_speed_scale = 1.0f; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/container.cpp b/src/core/hle/service/vi/container.cpp new file mode 100644 index 000000000..9074f4ae0 --- /dev/null +++ b/src/core/hle/service/vi/container.cpp @@ -0,0 +1,226 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/nvdrv/nvdrv_interface.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/surface_flinger.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/vi_results.h" + +namespace Service::VI { + +Container::Container(Core::System& system) { +    m_displays.CreateDisplay(DisplayName{"Default"}); +    m_displays.CreateDisplay(DisplayName{"External"}); +    m_displays.CreateDisplay(DisplayName{"Edid"}); +    m_displays.CreateDisplay(DisplayName{"Internal"}); +    m_displays.CreateDisplay(DisplayName{"Null"}); + +    m_binder_driver = +        system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true); +    m_surface_flinger = m_binder_driver->GetSurfaceFlinger(); + +    const auto nvdrv = +        system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule(); +    m_shared_buffer_manager.emplace(system, *this, nvdrv); + +    m_displays.ForEachDisplay( +        [&](auto& display) { m_surface_flinger->AddDisplay(display.GetId()); }); + +    m_conductor.emplace(system, *this, m_displays); +} + +Container::~Container() { +    this->OnTerminate(); +} + +void Container::OnTerminate() { +    std::scoped_lock lk{m_lock}; + +    m_is_shut_down = true; + +    m_layers.ForEachLayer([&](auto& layer) { this->DestroyLayerLocked(layer.GetId()); }); + +    m_displays.ForEachDisplay( +        [&](auto& display) { m_surface_flinger->RemoveDisplay(display.GetId()); }); +} + +SharedBufferManager* Container::GetSharedBufferManager() { +    return std::addressof(*m_shared_buffer_manager); +} + +Result Container::GetBinderDriver( +    std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver) { +    *out_binder_driver = m_binder_driver; +    R_SUCCEED(); +} + +Result Container::GetLayerProducerHandle( +    std::shared_ptr<android::BufferQueueProducer>* out_producer, u64 layer_id) { +    std::scoped_lock lk{m_lock}; + +    auto* const layer = m_layers.GetLayerById(layer_id); +    R_UNLESS(layer != nullptr, VI::ResultNotFound); + +    const auto binder = m_binder_driver->GetServer()->TryGetBinder(layer->GetProducerBinderId()); +    R_UNLESS(binder != nullptr, VI::ResultNotFound); + +    *out_producer = std::static_pointer_cast<android::BufferQueueProducer>(binder); +    R_SUCCEED(); +} + +Result Container::OpenDisplay(u64* out_display_id, const DisplayName& display_name) { +    auto* const display = m_displays.GetDisplayByName(display_name); +    R_UNLESS(display != nullptr, VI::ResultNotFound); + +    *out_display_id = display->GetId(); +    R_SUCCEED(); +} + +Result Container::CloseDisplay(u64 display_id) { +    R_SUCCEED(); +} + +Result Container::CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid) { +    std::scoped_lock lk{m_lock}; +    R_RETURN(this->CreateLayerLocked(out_layer_id, display_id, owner_aruid)); +} + +Result Container::DestroyManagedLayer(u64 layer_id) { +    std::scoped_lock lk{m_lock}; + +    // Try to close, if open, but don't fail if not. +    this->CloseLayerLocked(layer_id); + +    R_RETURN(this->DestroyLayerLocked(layer_id)); +} + +Result Container::OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid) { +    std::scoped_lock lk{m_lock}; +    R_RETURN(this->OpenLayerLocked(out_producer_binder_id, layer_id, aruid)); +} + +Result Container::CloseLayer(u64 layer_id) { +    std::scoped_lock lk{m_lock}; +    R_RETURN(this->CloseLayerLocked(layer_id)); +} + +Result Container::SetLayerVisibility(u64 layer_id, bool visible) { +    std::scoped_lock lk{m_lock}; + +    auto* const layer = m_layers.GetLayerById(layer_id); +    R_UNLESS(layer != nullptr, VI::ResultNotFound); + +    m_surface_flinger->SetLayerVisibility(layer->GetConsumerBinderId(), visible); +    R_SUCCEED(); +} + +Result Container::SetLayerBlending(u64 layer_id, bool enabled) { +    std::scoped_lock lk{m_lock}; + +    auto* const layer = m_layers.GetLayerById(layer_id); +    R_UNLESS(layer != nullptr, VI::ResultNotFound); + +    m_surface_flinger->SetLayerBlending(layer->GetConsumerBinderId(), +                                        enabled ? Nvnflinger::LayerBlending::Coverage +                                                : Nvnflinger::LayerBlending::None); +    R_SUCCEED(); +} + +void Container::LinkVsyncEvent(u64 display_id, Event* event) { +    std::scoped_lock lk{m_lock}; +    m_conductor->LinkVsyncEvent(display_id, event); +} + +void Container::UnlinkVsyncEvent(u64 display_id, Event* event) { +    std::scoped_lock lk{m_lock}; +    m_conductor->UnlinkVsyncEvent(display_id, event); +} + +Result Container::CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id) { +    std::scoped_lock lk{m_lock}; +    R_TRY(this->CreateLayerLocked(out_layer_id, display_id, {})); +    R_RETURN(this->OpenLayerLocked(out_producer_binder_id, *out_layer_id, {})); +} + +Result Container::DestroyStrayLayer(u64 layer_id) { +    std::scoped_lock lk{m_lock}; +    R_TRY(this->CloseLayerLocked(layer_id)); +    R_RETURN(this->DestroyLayerLocked(layer_id)); +} + +Result Container::CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid) { +    auto* const display = m_displays.GetDisplayById(display_id); +    R_UNLESS(display != nullptr, VI::ResultNotFound); + +    s32 consumer_binder_id, producer_binder_id; +    m_surface_flinger->CreateBufferQueue(&consumer_binder_id, &producer_binder_id); + +    auto* const layer = +        m_layers.CreateLayer(owner_aruid, display, consumer_binder_id, producer_binder_id); +    R_UNLESS(layer != nullptr, VI::ResultNotFound); + +    m_surface_flinger->CreateLayer(consumer_binder_id); + +    *out_layer_id = layer->GetId(); +    R_SUCCEED(); +} + +Result Container::DestroyLayerLocked(u64 layer_id) { +    auto* const layer = m_layers.GetLayerById(layer_id); +    R_UNLESS(layer != nullptr, VI::ResultNotFound); + +    m_surface_flinger->DestroyLayer(layer->GetConsumerBinderId()); +    m_surface_flinger->DestroyBufferQueue(layer->GetConsumerBinderId(), +                                          layer->GetProducerBinderId()); +    m_layers.DestroyLayer(layer_id); + +    R_SUCCEED(); +} + +Result Container::OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid) { +    R_UNLESS(!m_is_shut_down, VI::ResultOperationFailed); + +    auto* const layer = m_layers.GetLayerById(layer_id); +    R_UNLESS(layer != nullptr, VI::ResultNotFound); +    R_UNLESS(!layer->IsOpen(), VI::ResultOperationFailed); +    R_UNLESS(layer->GetOwnerAruid() == aruid, VI::ResultPermissionDenied); + +    layer->Open(); + +    if (auto* display = layer->GetDisplay(); display != nullptr) { +        m_surface_flinger->AddLayerToDisplayStack(display->GetId(), layer->GetConsumerBinderId()); +    } + +    *out_producer_binder_id = layer->GetProducerBinderId(); + +    R_SUCCEED(); +} + +Result Container::CloseLayerLocked(u64 layer_id) { +    auto* const layer = m_layers.GetLayerById(layer_id); +    R_UNLESS(layer != nullptr, VI::ResultNotFound); +    R_UNLESS(layer->IsOpen(), VI::ResultOperationFailed); + +    if (auto* display = layer->GetDisplay(); display != nullptr) { +        m_surface_flinger->RemoveLayerFromDisplayStack(display->GetId(), +                                                       layer->GetConsumerBinderId()); +    } + +    layer->Close(); + +    R_SUCCEED(); +} + +bool Container::ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, +                                 u64 display_id) { +    std::scoped_lock lk{m_lock}; +    return m_surface_flinger->ComposeDisplay(out_swap_interval, out_compose_speed_scale, +                                             display_id); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/container.h b/src/core/hle/service/vi/container.h new file mode 100644 index 000000000..5eac4d77d --- /dev/null +++ b/src/core/hle/service/vi/container.h @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <memory> +#include <mutex> +#include <optional> + +#include "core/hle/service/vi/conductor.h" +#include "core/hle/service/vi/display_list.h" +#include "core/hle/service/vi/layer_list.h" +#include "core/hle/service/vi/shared_buffer_manager.h" + +union Result; + +namespace Service::android { +class BufferQueueProducer; +} + +namespace Service::Nvnflinger { +class IHOSBinderDriver; +class SurfaceFlinger; +} // namespace Service::Nvnflinger + +namespace Service { +class Event; +} + +namespace Service::VI { + +class SharedBufferManager; + +class Container { +public: +    explicit Container(Core::System& system); +    ~Container(); + +    void OnTerminate(); + +    SharedBufferManager* GetSharedBufferManager(); + +    Result GetBinderDriver(std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver); +    Result GetLayerProducerHandle(std::shared_ptr<android::BufferQueueProducer>* out_producer, +                                  u64 layer_id); + +    Result OpenDisplay(u64* out_display_id, const DisplayName& display_name); +    Result CloseDisplay(u64 display_id); + +    // Managed layers are created by the interaction between am and ommdisp +    // on behalf of an applet. Their lifetime ends with the lifetime of the +    // applet's ISelfController. +    Result CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid); +    Result DestroyManagedLayer(u64 layer_id); +    Result OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid); +    Result CloseLayer(u64 layer_id); + +    // Stray layers are created by non-applet sysmodules. Their lifetime ends +    // with the lifetime of the IApplicationDisplayService which created them. +    Result CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id); +    Result DestroyStrayLayer(u64 layer_id); + +    Result SetLayerVisibility(u64 layer_id, bool visible); +    Result SetLayerBlending(u64 layer_id, bool enabled); + +    void LinkVsyncEvent(u64 display_id, Event* event); +    void UnlinkVsyncEvent(u64 display_id, Event* event); + +private: +    Result CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid); +    Result DestroyLayerLocked(u64 layer_id); +    Result OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid); +    Result CloseLayerLocked(u64 layer_id); + +public: +    bool ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id); + +private: +    std::mutex m_lock{}; +    DisplayList m_displays{}; +    LayerList m_layers{}; +    std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_driver{}; +    std::shared_ptr<Nvnflinger::SurfaceFlinger> m_surface_flinger{}; +    std::optional<SharedBufferManager> m_shared_buffer_manager{}; +    std::optional<Conductor> m_conductor{}; +    bool m_is_shut_down{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/display.h b/src/core/hle/service/vi/display.h new file mode 100644 index 000000000..fceda75e3 --- /dev/null +++ b/src/core/hle/service/vi/display.h @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +class Display { +public: +    constexpr Display() = default; + +    void Initialize(u64 id, const DisplayName& display_name) { +        m_id = id; +        m_display_name = display_name; +        m_is_initialized = true; +    } + +    void Finalize() { +        m_id = {}; +        m_display_name = {}; +        m_is_initialized = {}; +    } + +    u64 GetId() const { +        return m_id; +    } + +    const DisplayName& GetDisplayName() const { +        return m_display_name; +    } + +    bool IsInitialized() const { +        return m_is_initialized; +    } + +private: +    u64 m_id{}; +    DisplayName m_display_name{}; +    bool m_is_initialized{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp deleted file mode 100644 index 7f2af9acc..000000000 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <utility> - -#include <fmt/format.h> - -#include "common/assert.h" -#include "core/core.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nvdrv/core/container.h" -#include "core/hle/service/nvnflinger/buffer_item_consumer.h" -#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" -#include "core/hle/service/nvnflinger/buffer_queue_core.h" -#include "core/hle/service/nvnflinger/buffer_queue_producer.h" -#include "core/hle/service/nvnflinger/hardware_composer.h" -#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" -#include "core/hle/service/vi/display/vi_display.h" -#include "core/hle/service/vi/layer/vi_layer.h" -#include "core/hle/service/vi/vi_results.h" - -namespace Service::VI { - -struct BufferQueue { -    std::shared_ptr<android::BufferQueueCore> core; -    std::unique_ptr<android::BufferQueueProducer> producer; -    std::unique_ptr<android::BufferQueueConsumer> consumer; -}; - -static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context, -                                     Service::Nvidia::NvCore::NvMap& nvmap) { -    auto buffer_queue_core = std::make_shared<android::BufferQueueCore>(); -    return { -        buffer_queue_core, -        std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), -        std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)}; -} - -Display::Display(u64 id, std::string name_, -                 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_, -                 KernelHelpers::ServiceContext& service_context_, Core::System& system_) -    : display_id{id}, name{std::move(name_)}, hos_binder_driver_server{hos_binder_driver_server_}, -      service_context{service_context_} { -    hardware_composer = std::make_unique<Nvnflinger::HardwareComposer>(); -    vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id)); -} - -Display::~Display() { -    service_context.CloseEvent(vsync_event); -} - -Layer& Display::GetLayer(std::size_t index) { -    size_t i = 0; -    for (auto& layer : layers) { -        if (!layer->IsOpen() || !layer->IsVisible()) { -            continue; -        } - -        if (i == index) { -            return *layer; -        } - -        i++; -    } - -    UNREACHABLE(); -} - -size_t Display::GetNumLayers() const { -    return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen() && l->IsVisible(); }); -} - -Kernel::KReadableEvent* Display::GetVSyncEvent() { -    return &vsync_event->GetReadableEvent(); -} - -void Display::SignalVSyncEvent() { -    vsync_event->Signal(); -} - -void Display::CreateLayer(u64 layer_id, u32 binder_id, -                          Service::Nvidia::NvCore::Container& nv_core) { -    auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile()); - -    auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer)); -    buffer_item_consumer->Connect(false); - -    layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, -                                                std::move(buffer_item_consumer))); - -    if (is_abandoned) { -        this->FindLayer(layer_id)->GetConsumer().Abandon(); -    } - -    hos_binder_driver_server.RegisterProducer(std::move(producer)); -} - -void Display::DestroyLayer(u64 layer_id) { -    if (auto* layer = this->FindLayer(layer_id); layer != nullptr) { -        layer->GetConsumer().Abandon(); -    } - -    std::erase_if(layers, -                  [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); -} - -void Display::Abandon() { -    for (auto& layer : layers) { -        layer->GetConsumer().Abandon(); -    } -    is_abandoned = true; -} - -Layer* Display::FindLayer(u64 layer_id) { -    const auto itr = -        std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { -            return layer->GetLayerId() == layer_id; -        }); - -    if (itr == layers.end()) { -        return nullptr; -    } - -    return itr->get(); -} - -const Layer* Display::FindLayer(u64 layer_id) const { -    const auto itr = -        std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { -            return layer->GetLayerId() == layer_id; -        }); - -    if (itr == layers.end()) { -        return nullptr; -    } - -    return itr->get(); -} - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h deleted file mode 100644 index 220292cff..000000000 --- a/src/core/hle/service/vi/display/vi_display.h +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> -#include <string> -#include <vector> - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "core/hle/result.h" - -namespace Core { -class System; -} - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Service::android { -class BufferQueueProducer; -} - -namespace Service::KernelHelpers { -class ServiceContext; -} - -namespace Service::Nvnflinger { -class HardwareComposer; -class HosBinderDriverServer; -} // namespace Service::Nvnflinger - -namespace Service::Nvidia::NvCore { -class Container; -class NvMap; -} // namespace Service::Nvidia::NvCore - -namespace Service::VI { - -class Layer; - -/// Represents a single display type -class Display { -public: -    YUZU_NON_COPYABLE(Display); -    YUZU_NON_MOVEABLE(Display); - -    /// Constructs a display with a given unique ID and name. -    /// -    /// @param id The unique ID for this display. -    /// @param hos_binder_driver_server_ Nvnflinger HOSBinderDriver server instance. -    /// @param service_context_ The ServiceContext for the owning service. -    /// @param name_ The name for this display. -    /// @param system_ The global system instance. -    /// -    Display(u64 id, std::string name_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_, -            KernelHelpers::ServiceContext& service_context_, Core::System& system_); -    ~Display(); - -    /// Gets the unique ID assigned to this display. -    u64 GetID() const { -        return display_id; -    } - -    /// Gets the name of this display -    const std::string& GetName() const { -        return name; -    } - -    /// Whether or not this display has any layers added to it. -    bool HasLayers() const { -        return GetNumLayers() > 0; -    } - -    /// Gets a layer for this display based off an index. -    Layer& GetLayer(std::size_t index); - -    std::size_t GetNumLayers() const; - -    /// Gets the internal vsync event. -    Kernel::KReadableEvent* GetVSyncEvent(); - -    /// Signals the internal vsync event. -    void SignalVSyncEvent(); - -    /// Creates and adds a layer to this display with the given ID. -    /// -    /// @param layer_id The ID to assign to the created layer. -    /// @param binder_id The ID assigned to the buffer queue. -    /// -    void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core); - -    /// Removes a layer from this display with the given ID. -    /// -    /// @param layer_id The ID assigned to the layer to destroy. -    /// -    void DestroyLayer(u64 layer_id); - -    /// Resets the display for a new connection. -    void Reset() { -        layers.clear(); -    } - -    void Abandon(); - -    /// Attempts to find a layer with the given ID. -    /// -    /// @param layer_id The layer ID. -    /// -    /// @returns If found, the Layer instance with the given ID. -    ///          If not found, then nullptr is returned. -    /// -    Layer* FindLayer(u64 layer_id); - -    /// Attempts to find a layer with the given ID. -    /// -    /// @param layer_id The layer ID. -    /// -    /// @returns If found, the Layer instance with the given ID. -    ///          If not found, then nullptr is returned. -    /// -    const Layer* FindLayer(u64 layer_id) const; - -    Nvnflinger::HardwareComposer& GetComposer() const { -        return *hardware_composer; -    } - -private: -    u64 display_id; -    std::string name; -    Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; -    KernelHelpers::ServiceContext& service_context; - -    std::vector<std::unique_ptr<Layer>> layers; -    std::unique_ptr<Nvnflinger::HardwareComposer> hardware_composer; -    Kernel::KEvent* vsync_event{}; -    bool is_abandoned{}; -}; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/display_list.h b/src/core/hle/service/vi/display_list.h new file mode 100644 index 000000000..f710ac472 --- /dev/null +++ b/src/core/hle/service/vi/display_list.h @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <cstring> + +#include "core/hle/service/vi/display.h" + +namespace Service::VI { + +class DisplayList { +public: +    constexpr DisplayList() = default; + +    bool CreateDisplay(const DisplayName& name) { +        Display* const display = this->GetFreeDisplay(); +        if (!display) { +            return false; +        } + +        display->Initialize(m_next_id++, name); +        return true; +    } + +    bool DestroyDisplay(u64 display_id) { +        Display* display = this->GetDisplayById(display_id); +        if (!display) { +            return false; +        } + +        display->Finalize(); +        return true; +    } + +    Display* GetDisplayByName(const DisplayName& name) { +        for (auto& display : m_displays) { +            if (display.IsInitialized() && +                std::strncmp(name.data(), display.GetDisplayName().data(), sizeof(DisplayName)) == +                    0) { +                return &display; +            } +        } + +        return nullptr; +    } + +    Display* GetDisplayById(u64 display_id) { +        for (auto& display : m_displays) { +            if (display.IsInitialized() && display.GetId() == display_id) { +                return &display; +            } +        } + +        return nullptr; +    } + +    template <typename F> +    void ForEachDisplay(F&& cb) { +        for (auto& display : m_displays) { +            if (display.IsInitialized()) { +                cb(display); +            } +        } +    } + +private: +    Display* GetFreeDisplay() { +        for (auto& display : m_displays) { +            if (!display.IsInitialized()) { +                return &display; +            } +        } + +        return nullptr; +    } + +private: +    std::array<Display, 8> m_displays{}; +    u64 m_next_id{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/layer.h b/src/core/hle/service/vi/layer.h new file mode 100644 index 000000000..e4c9c9864 --- /dev/null +++ b/src/core/hle/service/vi/layer.h @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_types.h" + +namespace Service::VI { + +class Display; + +class Layer { +public: +    constexpr Layer() = default; + +    void Initialize(u64 id, u64 owner_aruid, Display* display, s32 consumer_binder_id, +                    s32 producer_binder_id) { +        m_id = id; +        m_owner_aruid = owner_aruid; +        m_display = display; +        m_consumer_binder_id = consumer_binder_id; +        m_producer_binder_id = producer_binder_id; +        m_is_initialized = true; +    } + +    void Finalize() { +        m_id = {}; +        m_owner_aruid = {}; +        m_display = {}; +        m_consumer_binder_id = {}; +        m_producer_binder_id = {}; +        m_is_initialized = {}; +    } + +    void Open() { +        m_is_open = true; +    } + +    void Close() { +        m_is_open = false; +    } + +    u64 GetId() const { +        return m_id; +    } + +    u64 GetOwnerAruid() const { +        return m_owner_aruid; +    } + +    Display* GetDisplay() const { +        return m_display; +    } + +    s32 GetConsumerBinderId() const { +        return m_consumer_binder_id; +    } + +    s32 GetProducerBinderId() const { +        return m_producer_binder_id; +    } + +    bool IsInitialized() const { +        return m_is_initialized; +    } + +    bool IsOpen() const { +        return m_is_open; +    } + +private: +    u64 m_id{}; +    u64 m_owner_aruid{}; +    Display* m_display{}; +    s32 m_consumer_binder_id{}; +    s32 m_producer_binder_id{}; +    bool m_is_initialized{}; +    bool m_is_open{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp deleted file mode 100644 index eca35d82a..000000000 --- a/src/core/hle/service/vi/layer/vi_layer.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/nvnflinger/hwc_layer.h" -#include "core/hle/service/vi/layer/vi_layer.h" - -namespace Service::VI { - -Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, -             android::BufferQueueProducer& binder_, -             std::shared_ptr<android::BufferItemConsumer>&& consumer_) -    : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move( -                                                                                    consumer_)}, -      blending{Nvnflinger::LayerBlending::None}, open{false}, visible{true} {} - -Layer::~Layer() = default; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h deleted file mode 100644 index 14e229903..000000000 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> -#include <utility> - -#include "common/common_types.h" - -namespace Service::android { -class BufferItemConsumer; -class BufferQueueCore; -class BufferQueueProducer; -} // namespace Service::android - -namespace Service::Nvnflinger { -enum class LayerBlending : u32; -} - -namespace Service::VI { - -/// Represents a single display layer. -class Layer { -public: -    /// Constructs a layer with a given ID and buffer queue. -    /// -    /// @param layer_id_ The ID to assign to this layer. -    /// @param binder_id_ The binder ID to assign to this layer. -    /// @param binder_ The buffer producer queue for this layer to use. -    /// -    Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, -          android::BufferQueueProducer& binder_, -          std::shared_ptr<android::BufferItemConsumer>&& consumer_); -    ~Layer(); - -    Layer(const Layer&) = delete; -    Layer& operator=(const Layer&) = delete; - -    Layer(Layer&&) = default; -    Layer& operator=(Layer&&) = delete; - -    /// Gets the ID for this layer. -    u64 GetLayerId() const { -        return layer_id; -    } - -    /// Gets the binder ID for this layer. -    u32 GetBinderId() const { -        return binder_id; -    } - -    /// Gets a reference to the buffer queue this layer is using. -    android::BufferQueueProducer& GetBufferQueue() { -        return binder; -    } - -    /// Gets a const reference to the buffer queue this layer is using. -    const android::BufferQueueProducer& GetBufferQueue() const { -        return binder; -    } - -    android::BufferItemConsumer& GetConsumer() { -        return *consumer; -    } - -    const android::BufferItemConsumer& GetConsumer() const { -        return *consumer; -    } - -    android::BufferQueueCore& Core() { -        return core; -    } - -    const android::BufferQueueCore& Core() const { -        return core; -    } - -    bool IsVisible() const { -        return visible; -    } - -    void SetVisibility(bool v) { -        visible = v; -    } - -    bool IsOpen() const { -        return open; -    } - -    bool Close() { -        return std::exchange(open, false); -    } - -    bool Open() { -        return !std::exchange(open, true); -    } - -    Nvnflinger::LayerBlending GetBlending() { -        return blending; -    } - -    void SetBlending(Nvnflinger::LayerBlending b) { -        blending = b; -    } - -private: -    const u64 layer_id; -    const u32 binder_id; -    android::BufferQueueCore& core; -    android::BufferQueueProducer& binder; -    std::shared_ptr<android::BufferItemConsumer> consumer; -    Service::Nvnflinger::LayerBlending blending; -    bool open; -    bool visible; -}; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/layer_list.h b/src/core/hle/service/vi/layer_list.h new file mode 100644 index 000000000..4afca6f40 --- /dev/null +++ b/src/core/hle/service/vi/layer_list.h @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/vi/layer.h" + +namespace Service::VI { + +class LayerList { +public: +    constexpr LayerList() = default; + +    Layer* CreateLayer(u64 owner_aruid, Display* display, s32 consumer_binder_id, +                       s32 producer_binder_id) { +        Layer* const layer = GetFreeLayer(); +        if (!layer) { +            return nullptr; +        } + +        layer->Initialize(++m_next_id, owner_aruid, display, consumer_binder_id, +                          producer_binder_id); +        return layer; +    } + +    bool DestroyLayer(u64 layer_id) { +        Layer* const layer = GetLayerById(layer_id); +        if (!layer) { +            return false; +        } + +        layer->Finalize(); +        return true; +    } + +    Layer* GetLayerById(u64 layer_id) { +        for (auto& layer : m_layers) { +            if (layer.IsInitialized() && layer.GetId() == layer_id) { +                return &layer; +            } +        } + +        return nullptr; +    } + +    template <typename F> +    void ForEachLayer(F&& cb) { +        for (auto& layer : m_layers) { +            if (layer.IsInitialized()) { +                cb(layer); +            } +        } +    } + +private: +    Layer* GetFreeLayer() { +        for (auto& layer : m_layers) { +            if (!layer.IsInitialized()) { +                return &layer; +            } +        } + +        return nullptr; +    } + +private: +    std::array<Layer, 8> m_layers{}; +    u64 m_next_id{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_display_service.cpp b/src/core/hle/service/vi/manager_display_service.cpp index 17f2f3b8f..9f856282e 100644 --- a/src/core/hle/service/vi/manager_display_service.cpp +++ b/src/core/hle/service/vi/manager_display_service.cpp @@ -2,22 +2,21 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "core/hle/service/cmif_serialization.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/vi/container.h"  #include "core/hle/service/vi/manager_display_service.h" -#include "core/hle/service/vi/vi_results.h"  namespace Service::VI {  IManagerDisplayService::IManagerDisplayService(Core::System& system_, -                                               Nvnflinger::Nvnflinger& nvnflinger) -    : ServiceFramework{system_, "IManagerDisplayService"}, m_nvnflinger{nvnflinger} { +                                               std::shared_ptr<Container> container) +    : ServiceFramework{system_, "IManagerDisplayService"}, m_container{std::move(container)} {      // clang-format off      static const FunctionInfo functions[] = {          {200, nullptr, "AllocateProcessHeapBlock"},          {201, nullptr, "FreeProcessHeapBlock"},          {1102, nullptr, "GetDisplayResolution"},          {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"}, -        {2011, nullptr, "DestroyManagedLayer"}, +        {2011, C<&IManagerDisplayService::DestroyManagedLayer>, "DestroyManagedLayer"},          {2012, nullptr, "CreateStrayLayer"},          {2050, nullptr, "CreateIndirectLayer"},          {2051, nullptr, "DestroyIndirectLayer"}, @@ -102,19 +101,30 @@ IManagerDisplayService::IManagerDisplayService(Core::System& system_,  IManagerDisplayService::~IManagerDisplayService() = default; -Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, -                                                  u64 display_id, AppletResourceUserId aruid) { -    LOG_WARNING(Service_VI, "(STUBBED) called. unknown={}, display={}, aruid={}", unknown, -                display_id, aruid.pid); +Result IManagerDisplayService::CreateSharedLayerSession(Kernel::KProcess* owner_process, +                                                        u64* out_buffer_id, u64* out_layer_handle, +                                                        u64 display_id, bool enable_blending) { +    R_RETURN(m_container->GetSharedBufferManager()->CreateSession( +        owner_process, out_buffer_id, out_layer_handle, display_id, enable_blending)); +} -    const auto layer_id = m_nvnflinger.CreateLayer(display_id); -    if (!layer_id) { -        LOG_ERROR(Service_VI, "Layer not found! display={}", display_id); -        R_THROW(VI::ResultNotFound); -    } +void IManagerDisplayService::DestroySharedLayerSession(Kernel::KProcess* owner_process) { +    m_container->GetSharedBufferManager()->DestroySession(owner_process); +} -    *out_layer_id = *layer_id; -    R_SUCCEED(); +Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) { +    R_RETURN(m_container->SetLayerBlending(layer_id, enabled)); +} + +Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id, +                                                  AppletResourceUserId aruid) { +    LOG_DEBUG(Service_VI, "called. flags={}, display={}, aruid={}", flags, display_id, aruid.pid); +    R_RETURN(m_container->CreateManagedLayer(out_layer_id, display_id, aruid.pid)); +} + +Result IManagerDisplayService::DestroyManagedLayer(u64 layer_id) { +    LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); +    R_RETURN(m_container->DestroyManagedLayer(layer_id));  }  Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { @@ -123,8 +133,8 @@ Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) {  }  Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { -    LOG_WARNING(Service_VI, "(STUBBED) called, layer_id={}, visible={}", layer_id, visible); -    R_SUCCEED(); +    LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible); +    R_RETURN(m_container->SetLayerVisibility(layer_id, visible));  }  } // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_display_service.h b/src/core/hle/service/vi/manager_display_service.h index 60e646ee0..b1bdf7f41 100644 --- a/src/core/hle/service/vi/manager_display_service.h +++ b/src/core/hle/service/vi/manager_display_service.h @@ -4,21 +4,34 @@  #include "core/hle/service/cmif_types.h"  #include "core/hle/service/service.h" +namespace Kernel { +class KProcess; +} +  namespace Service::VI { +class Container; +  class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {  public: -    explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); +    explicit IManagerDisplayService(Core::System& system_, std::shared_ptr<Container> container);      ~IManagerDisplayService() override; -private: -    Result CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, u64 display_id, +    Result CreateSharedLayerSession(Kernel::KProcess* owner_process, u64* out_buffer_id, +                                    u64* out_layer_handle, u64 display_id, bool enable_blending); +    void DestroySharedLayerSession(Kernel::KProcess* owner_process); + +    Result SetLayerBlending(bool enabled, u64 layer_id); + +public: +    Result CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id,                                AppletResourceUserId aruid); +    Result DestroyManagedLayer(u64 layer_id);      Result AddToLayerStack(u32 stack_id, u64 layer_id);      Result SetLayerVisibility(bool visible, u64 layer_id);  private: -    Nvnflinger::Nvnflinger& m_nvnflinger; +    const std::shared_ptr<Container> m_container;  };  } // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_root_service.cpp b/src/core/hle/service/vi/manager_root_service.cpp index a7eee4f04..0f16a15b4 100644 --- a/src/core/hle/service/vi/manager_root_service.cpp +++ b/src/core/hle/service/vi/manager_root_service.cpp @@ -2,7 +2,9 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h"  #include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/container.h"  #include "core/hle/service/vi/manager_root_service.h"  #include "core/hle/service/vi/service_creator.h"  #include "core/hle/service/vi/vi.h" @@ -10,11 +12,9 @@  namespace Service::VI { -IManagerRootService::IManagerRootService( -    Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, -    Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) -    : ServiceFramework{system_, "vi:m"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ -                                                                       hos_binder_driver_server} { +IManagerRootService::IManagerRootService(Core::System& system_, +                                         std::shared_ptr<Container> container) +    : ServiceFramework{system_, "vi:m"}, m_container{std::move(container)} {      static const FunctionInfo functions[] = {          {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"},          {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -31,8 +31,8 @@ IManagerRootService::~IManagerRootService() = default;  Result IManagerRootService::GetDisplayService(      Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {      LOG_DEBUG(Service_VI, "called"); -    R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, -                                          m_hos_binder_driver_server, Permission::Manager, policy)); +    R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, +                                          Permission::Manager, policy));  }  } // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_root_service.h b/src/core/hle/service/vi/manager_root_service.h index e6cb77aeb..77cd32869 100644 --- a/src/core/hle/service/vi/manager_root_service.h +++ b/src/core/hle/service/vi/manager_root_service.h @@ -10,29 +10,23 @@ namespace Core {  class System;  } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger -  namespace Service::VI { +class Container;  class IApplicationDisplayService;  enum class Policy : u32;  class IManagerRootService final : public ServiceFramework<IManagerRootService> {  public: -    explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, -                                 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); +    explicit IManagerRootService(Core::System& system_, std::shared_ptr<Container> container);      ~IManagerRootService() override; -private:      Result GetDisplayService(          Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,          Policy policy); -    Nvnflinger::Nvnflinger& m_nvnflinger; -    Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; +private: +    const std::shared_ptr<Container> m_container;  };  } // namespace Service::VI diff --git a/src/core/hle/service/vi/service_creator.cpp b/src/core/hle/service/vi/service_creator.cpp index 1de9d61a4..2b8e5f957 100644 --- a/src/core/hle/service/vi/service_creator.cpp +++ b/src/core/hle/service/vi/service_creator.cpp @@ -22,8 +22,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) {  Result GetApplicationDisplayService(      std::shared_ptr<IApplicationDisplayService>* out_application_display_service, -    Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, -    Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, +    Core::System& system, std::shared_ptr<Container> container, Permission permission,      Policy policy) {      if (!IsValidServiceAccess(permission, policy)) { @@ -32,7 +31,7 @@ Result GetApplicationDisplayService(      }      *out_application_display_service = -        std::make_shared<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server); +        std::make_shared<IApplicationDisplayService>(system, std::move(container));      R_SUCCEED();  } diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h index 8963bcd26..c6ba1797d 100644 --- a/src/core/hle/service/vi/service_creator.h +++ b/src/core/hle/service/vi/service_creator.h @@ -11,23 +11,18 @@ namespace Core {  class System;  } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger -  union Result;  namespace Service::VI { +class Container;  class IApplicationDisplayService;  enum class Permission;  enum class Policy : u32;  Result GetApplicationDisplayService(      std::shared_ptr<IApplicationDisplayService>* out_application_display_service, -    Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, -    Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, +    Core::System& system, std::shared_ptr<Container> container, Permission permission,      Policy policy);  } // namespace Service::VI diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp index 90f7248a0..12cba16fa 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp @@ -9,15 +9,15 @@  #include "core/hle/service/nvdrv/devices/nvmap.h"  #include "core/hle/service/nvdrv/nvdrv.h"  #include "core/hle/service/nvnflinger/buffer_queue_producer.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"  #include "core/hle/service/nvnflinger/pixel_format.h"  #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" -#include "core/hle/service/vi/layer/vi_layer.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/shared_buffer_manager.h"  #include "core/hle/service/vi/vi_results.h"  #include "video_core/gpu.h"  #include "video_core/host1x/host1x.h" -namespace Service::Nvnflinger { +namespace Service::VI {  namespace { @@ -26,7 +26,6 @@ Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_      using Core::Memory::YUZU_PAGESIZE;      // Allocate memory for the system shared buffer. -    // FIXME: This memory belongs to vi's .data section.      auto& kernel = system.Kernel();      // Hold a temporary page group reference while we try to map it. @@ -204,15 +203,15 @@ void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 han  } // namespace -FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger, -                                           std::shared_ptr<Nvidia::Module> nvdrv) -    : m_system(system), m_flinger(flinger), m_nvdrv(std::move(nvdrv)) {} +SharedBufferManager::SharedBufferManager(Core::System& system, Container& container, +                                         std::shared_ptr<Nvidia::Module> nvdrv) +    : m_system(system), m_container(container), m_nvdrv(std::move(nvdrv)) {} -FbShareBufferManager::~FbShareBufferManager() = default; +SharedBufferManager::~SharedBufferManager() = default; -Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, -                                        u64* out_layer_handle, u64 display_id, -                                        LayerBlending blending) { +Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id, +                                          u64* out_layer_handle, u64 display_id, +                                          bool enable_blending) {      std::scoped_lock lk{m_guard};      // Ensure we haven't already created. @@ -237,7 +236,7 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou                                                   owner_process, m_system));      // Create new session. -    auto [it, was_emplaced] = m_sessions.emplace(aruid, FbShareSession{}); +    auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{});      auto& session = it->second;      auto& container = m_nvdrv->GetContainer(); @@ -249,17 +248,18 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou                                    session.nvmap_fd, map_address, SharedBufferSize));      // Create and open a layer for the display. -    session.layer_id = m_flinger.CreateLayer(m_display_id, blending).value(); -    m_flinger.OpenLayer(session.layer_id); +    s32 producer_binder_id; +    R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id), +                                       std::addressof(session.layer_id), display_id)); -    // Get the layer. -    VI::Layer* layer = m_flinger.FindLayer(m_display_id, session.layer_id); -    ASSERT(layer != nullptr); +    // Configure blending. +    R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));      // Get the producer and set preallocated buffers. -    auto& producer = layer->GetBufferQueue(); -    MakeGraphicBuffer(producer, 0, session.buffer_nvmap_handle); -    MakeGraphicBuffer(producer, 1, session.buffer_nvmap_handle); +    std::shared_ptr<android::BufferQueueProducer> producer; +    R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id)); +    MakeGraphicBuffer(*producer, 0, session.buffer_nvmap_handle); +    MakeGraphicBuffer(*producer, 1, session.buffer_nvmap_handle);      // Assign outputs.      *out_buffer_id = m_buffer_id; @@ -269,7 +269,7 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou      R_SUCCEED();  } -void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) { +void SharedBufferManager::DestroySession(Kernel::KProcess* owner_process) {      std::scoped_lock lk{m_guard};      if (m_buffer_id == 0) { @@ -285,7 +285,7 @@ void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {      auto& session = it->second;      // Destroy the layer. -    m_flinger.DestroyLayer(session.layer_id); +    m_container.DestroyStrayLayer(session.layer_id);      // Close nvmap handle.      FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd); @@ -301,11 +301,11 @@ void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {      m_sessions.erase(it);  } -Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, -                                                           s32* out_nvmap_handle, -                                                           SharedMemoryPoolLayout* out_pool_layout, -                                                           u64 buffer_id, -                                                           u64 applet_resource_user_id) { +Result SharedBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, +                                                          s32* out_nvmap_handle, +                                                          SharedMemoryPoolLayout* out_pool_layout, +                                                          u64 buffer_id, +                                                          u64 applet_resource_user_id) {      std::scoped_lock lk{m_guard};      R_UNLESS(m_buffer_id > 0, VI::ResultNotFound); @@ -319,36 +319,18 @@ Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,      R_SUCCEED();  } -Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) { -    // Ensure the layer id is valid. -    R_UNLESS(layer_id > 0, VI::ResultNotFound); - -    // Get the layer. -    VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id); -    R_UNLESS(layer != nullptr, VI::ResultNotFound); - -    // We succeeded. -    *out_layer = layer; -    R_SUCCEED(); -} - -Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, -                                                      std::array<s32, 4>& out_slot_indexes, -                                                      s64* out_target_slot, u64 layer_id) { -    std::scoped_lock lk{m_guard}; - -    // Get the layer. -    VI::Layer* layer; -    R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); - +Result SharedBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, +                                                     std::array<s32, 4>& out_slot_indexes, +                                                     s64* out_target_slot, u64 layer_id) {      // Get the producer. -    auto& producer = layer->GetBufferQueue(); +    std::shared_ptr<android::BufferQueueProducer> producer; +    R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));      // Get the next buffer from the producer.      s32 slot; -    R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0, -                                    SharedBufferWidth, SharedBufferHeight, -                                    SharedBufferBlockLinearFormat, 0) == android::Status::NoError, +    R_UNLESS(producer->DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0, +                                     SharedBufferWidth, SharedBufferHeight, +                                     SharedBufferBlockLinearFormat, 0) == android::Status::NoError,               VI::ResultOperationFailed);      // Assign remaining outputs. @@ -359,27 +341,22 @@ Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,      R_SUCCEED();  } -Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence, -                                                      Common::Rectangle<s32> crop_region, -                                                      u32 transform, s32 swap_interval, -                                                      u64 layer_id, s64 slot) { -    std::scoped_lock lk{m_guard}; - -    // Get the layer. -    VI::Layer* layer; -    R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); - +Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence, +                                                     Common::Rectangle<s32> crop_region, +                                                     u32 transform, s32 swap_interval, u64 layer_id, +                                                     s64 slot) {      // Get the producer. -    auto& producer = layer->GetBufferQueue(); +    std::shared_ptr<android::BufferQueueProducer> producer; +    R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));      // Request to queue the buffer.      std::shared_ptr<android::GraphicBuffer> buffer; -    R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) == +    R_UNLESS(producer->RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) ==                   android::Status::NoError,               VI::ResultOperationFailed);      ON_RESULT_FAILURE { -        producer.CancelBuffer(static_cast<s32>(slot), fence); +        producer->CancelBuffer(static_cast<s32>(slot), fence);      };      // Queue the buffer to the producer. @@ -389,7 +366,7 @@ Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,      input.fence = fence;      input.transform = static_cast<android::NativeWindowTransform>(transform);      input.swap_interval = swap_interval; -    R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) == +    R_UNLESS(producer->QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) ==                   android::Status::NoError,               VI::ResultOperationFailed); @@ -397,25 +374,32 @@ Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,      R_SUCCEED();  } -Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, -                                                                 u64 layer_id) { -    std::scoped_lock lk{m_guard}; +Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { +    // Get the producer. +    std::shared_ptr<android::BufferQueueProducer> producer; +    R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); -    // Get the layer. -    VI::Layer* layer; -    R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); +    // Cancel. +    producer->CancelBuffer(static_cast<s32>(slot), android::Fence::NoFence()); + +    // We succeeded. +    R_SUCCEED(); +} +Result SharedBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, +                                                                u64 layer_id) {      // Get the producer. -    auto& producer = layer->GetBufferQueue(); +    std::shared_ptr<android::BufferQueueProducer> producer; +    R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));      // Set the event. -    *out_event = std::addressof(producer.GetNativeHandle()); +    *out_event = producer->GetNativeHandle({});      // We succeeded.      R_SUCCEED();  } -Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) { +Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {      std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer());      Common::ScratchBuffer<u32> scratch; @@ -444,4 +428,4 @@ Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32      R_SUCCEED();  } -} // namespace Service::Nvnflinger +} // namespace Service::VI diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/vi/shared_buffer_manager.h index b79a7d23a..7c9bb7199 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h +++ b/src/core/hle/service/vi/shared_buffer_manager.h @@ -8,15 +8,27 @@  #include "common/math_util.h"  #include "core/hle/service/nvdrv/core/container.h"  #include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvnflinger/hwc_layer.h"  #include "core/hle/service/nvnflinger/nvnflinger.h"  #include "core/hle/service/nvnflinger/ui/fence.h"  namespace Kernel {  class KPageGroup; +class KReadableEvent; +} // namespace Kernel + +namespace Service::android { +class BufferQueueProducer; +} + +namespace Service::Nvidia { +class Module;  } -namespace Service::Nvnflinger { +union Result; + +namespace Service::VI { + +class Container;  struct SharedMemorySlot {      u64 buffer_offset; @@ -32,17 +44,17 @@ struct SharedMemoryPoolLayout {  };  static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); -struct FbShareSession; +struct SharedBufferSession; -class FbShareBufferManager final { +class SharedBufferManager final {  public: -    explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger, -                                  std::shared_ptr<Nvidia::Module> nvdrv); -    ~FbShareBufferManager(); +    explicit SharedBufferManager(Core::System& system, Container& container, +                                 std::shared_ptr<Nvidia::Module> nvdrv); +    ~SharedBufferManager(); -    Result Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle, -                      u64 display_id, LayerBlending blending); -    void Finalize(Kernel::KProcess* owner_process); +    Result CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle, +                         u64 display_id, bool enable_blending); +    void DestroySession(Kernel::KProcess* owner_process);      Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle,                                           SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, @@ -51,32 +63,30 @@ public:                                      s64* out_target_slot, u64 layer_id);      Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region,                                      u32 transform, s32 swap_interval, u64 layer_id, s64 slot); +    Result CancelSharedFrameBuffer(u64 layer_id, s64 slot);      Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id);      Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index);  private: -    Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id); - -private:      u64 m_next_buffer_id = 1;      u64 m_display_id = 0;      u64 m_buffer_id = 0;      SharedMemoryPoolLayout m_pool_layout = {}; -    std::map<u64, FbShareSession> m_sessions; +    std::map<u64, SharedBufferSession> m_sessions;      std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;      std::mutex m_guard;      Core::System& m_system; -    Nvnflinger& m_flinger; -    std::shared_ptr<Nvidia::Module> m_nvdrv; +    Container& m_container; +    const std::shared_ptr<Nvidia::Module> m_nvdrv;  }; -struct FbShareSession { +struct SharedBufferSession {      Nvidia::DeviceFD nvmap_fd = {};      Nvidia::NvCore::SessionId session_id = {};      u64 layer_id = {};      u32 buffer_nvmap_handle = 0;  }; -} // namespace Service::Nvnflinger +} // namespace Service::VI diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp index 1e1cfc817..c3c50b07b 100644 --- a/src/core/hle/service/vi/system_display_service.cpp +++ b/src/core/hle/service/vi/system_display_service.cpp @@ -3,15 +3,15 @@  #include "common/settings.h"  #include "core/hle/service/cmif_serialization.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" +#include "core/hle/service/vi/container.h"  #include "core/hle/service/vi/system_display_service.h"  #include "core/hle/service/vi/vi_types.h"  namespace Service::VI {  ISystemDisplayService::ISystemDisplayService(Core::System& system_, -                                             Nvnflinger::Nvnflinger& nvnflinger) -    : ServiceFramework{system_, "ISystemDisplayService"}, m_nvnflinger{nvnflinger} { +                                             std::shared_ptr<Container> container) +    : ServiceFramework{system_, "ISystemDisplayService"}, m_container{std::move(container)} {      // clang-format off      static const FunctionInfo functions[] = {          {1200, nullptr, "GetZOrderCountMin"}, @@ -29,7 +29,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_,          {2400, nullptr, "OpenIndirectLayer"},          {2401, nullptr, "CloseIndirectLayer"},          {2402, nullptr, "FlipIndirectLayer"}, -        {3000, nullptr, "ListDisplayModes"}, +        {3000, C<&ISystemDisplayService::ListDisplayModes>, "ListDisplayModes"},          {3001, nullptr, "ListDisplayRgbRanges"},          {3002, nullptr, "ListDisplayContentTypes"},          {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"}, @@ -59,7 +59,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_,          {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"},          {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"},          {8257, nullptr, "FillSharedFrameBufferColor"}, -        {8258, nullptr, "CancelSharedFrameBuffer"}, +        {8258, C<&ISystemDisplayService::CancelSharedFrameBuffer>, "CancelSharedFrameBuffer"},          {9000, nullptr, "GetDp2hdmiController"},      };      // clang-format on @@ -80,31 +80,50 @@ Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) {      R_SUCCEED();  } -Result ISystemDisplayService::GetDisplayMode(Out<u32> out_width, Out<u32> out_height, -                                             Out<f32> out_refresh_rate, Out<u32> out_unknown) { -    LOG_WARNING(Service_VI, "(STUBBED) called"); +Result ISystemDisplayService::ListDisplayModes( +    Out<u64> out_count, u64 display_id, +    OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes) { +    LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id); + +    if (!out_display_modes.empty()) { +        out_display_modes[0] = { +            .width = 1920, +            .height = 1080, +            .refresh_rate = 60.f, +            .unknown = {}, +        }; +        *out_count = 1; +    } else { +        *out_count = 0; +    } + +    R_SUCCEED(); +} + +Result ISystemDisplayService::GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id) { +    LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id);      if (Settings::IsDockedMode()) { -        *out_width = static_cast<u32>(DisplayResolution::DockedWidth); -        *out_height = static_cast<u32>(DisplayResolution::DockedHeight); +        out_display_mode->width = static_cast<u32>(DisplayResolution::DockedWidth); +        out_display_mode->height = static_cast<u32>(DisplayResolution::DockedHeight);      } else { -        *out_width = static_cast<u32>(DisplayResolution::UndockedWidth); -        *out_height = static_cast<u32>(DisplayResolution::UndockedHeight); +        out_display_mode->width = static_cast<u32>(DisplayResolution::UndockedWidth); +        out_display_mode->height = static_cast<u32>(DisplayResolution::UndockedHeight);      } -    *out_refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. -    *out_unknown = 0; +    out_display_mode->refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. +    out_display_mode->unknown = 0;      R_SUCCEED();  }  Result ISystemDisplayService::GetSharedBufferMemoryHandleId(      Out<s32> out_nvmap_handle, Out<u64> out_size, -    OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, -    u64 buffer_id, ClientAppletResourceUserId aruid) { +    OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, u64 buffer_id, +    ClientAppletResourceUserId aruid) {      LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); -    R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( +    R_RETURN(m_container->GetSharedBufferManager()->GetSharedBufferMemoryHandleId(          out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid));  } @@ -122,7 +141,7 @@ Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_f                                                         Out<std::array<s32, 4>> out_slots,                                                         Out<s64> out_target_slot, u64 layer_id) {      LOG_DEBUG(Service_VI, "called"); -    R_RETURN(m_nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( +    R_RETURN(m_container->GetSharedBufferManager()->AcquireSharedFrameBuffer(          out_fence, *out_slots, out_target_slot, layer_id));  } @@ -131,15 +150,20 @@ Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence,                                                         u32 window_transform, s32 swap_interval,                                                         u64 layer_id, s64 surface_id) {      LOG_DEBUG(Service_VI, "called"); -    R_RETURN(m_nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( +    R_RETURN(m_container->GetSharedBufferManager()->PresentSharedFrameBuffer(          fence, crop_region, window_transform, swap_interval, layer_id, surface_id));  }  Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent(      OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) {      LOG_DEBUG(Service_VI, "called"); -    R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(out_event, -                                                                                       layer_id)); +    R_RETURN(m_container->GetSharedBufferManager()->GetSharedFrameBufferAcquirableEvent(out_event, +                                                                                        layer_id)); +} + +Result ISystemDisplayService::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { +    LOG_DEBUG(Service_VI, "called"); +    R_RETURN(m_container->GetSharedBufferManager()->CancelSharedFrameBuffer(layer_id, slot));  }  } // namespace Service::VI diff --git a/src/core/hle/service/vi/system_display_service.h b/src/core/hle/service/vi/system_display_service.h index cfcb196fd..7228d826e 100644 --- a/src/core/hle/service/vi/system_display_service.h +++ b/src/core/hle/service/vi/system_display_service.h @@ -5,27 +5,28 @@  #include "core/hle/service/cmif_types.h"  #include "core/hle/service/nvnflinger/ui/fence.h"  #include "core/hle/service/service.h" - -namespace Service::Nvnflinger { -struct SharedMemoryPoolLayout; -} +#include "core/hle/service/vi/shared_buffer_manager.h"  namespace Service::VI { +struct DisplayMode; + +class Container;  class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {  public: -    explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); +    explicit ISystemDisplayService(Core::System& system_, std::shared_ptr<Container> container);      ~ISystemDisplayService() override;  private:      Result SetLayerZ(u32 z_value, u64 layer_id);      Result SetLayerVisibility(bool visible, u64 layer_id); -    Result GetDisplayMode(Out<u32> out_width, Out<u32> out_height, Out<f32> out_refresh_rate, -                          Out<u32> out_unknown); +    Result ListDisplayModes(Out<u64> out_count, u64 display_id, +                            OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes); +    Result GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id);      Result GetSharedBufferMemoryHandleId(          Out<s32> out_nvmap_handle, Out<u64> out_size, -        OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, +        OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout,          u64 buffer_id, ClientAppletResourceUserId aruid);      Result OpenSharedLayer(u64 layer_id);      Result ConnectSharedLayer(u64 layer_id); @@ -37,9 +38,10 @@ private:      Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region,                                      u32 window_transform, s32 swap_interval, u64 layer_id,                                      s64 surface_id); +    Result CancelSharedFrameBuffer(u64 layer_id, s64 slot);  private: -    Nvnflinger::Nvnflinger& m_nvnflinger; +    const std::shared_ptr<Container> m_container;  };  } // namespace Service::VI diff --git a/src/core/hle/service/vi/system_root_service.cpp b/src/core/hle/service/vi/system_root_service.cpp index 8789b4cfb..3489727d8 100644 --- a/src/core/hle/service/vi/system_root_service.cpp +++ b/src/core/hle/service/vi/system_root_service.cpp @@ -3,6 +3,7 @@  #include "core/hle/service/cmif_serialization.h"  #include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/container.h"  #include "core/hle/service/vi/service_creator.h"  #include "core/hle/service/vi/system_root_service.h"  #include "core/hle/service/vi/vi.h" @@ -10,10 +11,8 @@  namespace Service::VI { -ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, -                                       Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) -    : ServiceFramework{system_, "vi:s"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ -                                                                       hos_binder_driver_server} { +ISystemRootService::ISystemRootService(Core::System& system_, std::shared_ptr<Container> container) +    : ServiceFramework{system_, "vi:s"}, m_container{std::move(container)} {      static const FunctionInfo functions[] = {          {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"},          {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -26,8 +25,8 @@ ISystemRootService::~ISystemRootService() = default;  Result ISystemRootService::GetDisplayService(      Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {      LOG_DEBUG(Service_VI, "called"); -    R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, -                                          m_hos_binder_driver_server, Permission::System, policy)); +    R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, +                                          Permission::System, policy));  }  } // namespace Service::VI diff --git a/src/core/hle/service/vi/system_root_service.h b/src/core/hle/service/vi/system_root_service.h index 2c547faa5..9d5aa53d3 100644 --- a/src/core/hle/service/vi/system_root_service.h +++ b/src/core/hle/service/vi/system_root_service.h @@ -10,20 +10,15 @@ namespace Core {  class System;  } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger -  namespace Service::VI { +class Container;  class IApplicationDisplayService;  enum class Policy : u32;  class ISystemRootService final : public ServiceFramework<ISystemRootService> {  public: -    explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, -                                Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); +    explicit ISystemRootService(Core::System& system_, std::shared_ptr<Container> container);      ~ISystemRootService() override;  private: @@ -31,8 +26,7 @@ private:          Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,          Policy policy); -    Nvnflinger::Nvnflinger& m_nvnflinger; -    Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; +    const std::shared_ptr<Container> m_container;  };  } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 304e589b7..b388efaf6 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -1,25 +1,30 @@  // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/core.h"  #include "core/hle/service/server_manager.h" -#include "core/hle/service/vi/application_display_service.h"  #include "core/hle/service/vi/application_root_service.h" +#include "core/hle/service/vi/container.h"  #include "core/hle/service/vi/manager_root_service.h"  #include "core/hle/service/vi/system_root_service.h"  #include "core/hle/service/vi/vi.h"  namespace Service::VI { -void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, -                 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { +void LoopProcess(Core::System& system, std::stop_token token) { +    const auto container = std::make_shared<Container>(system); +      auto server_manager = std::make_unique<ServerManager>(system); -    server_manager->RegisterNamedService("vi:m", std::make_shared<IManagerRootService>( -                                                     system, nvnflinger, hos_binder_driver_server)); +    server_manager->RegisterNamedService("vi:m", +                                         std::make_shared<IManagerRootService>(system, container)); +    server_manager->RegisterNamedService("vi:s", +                                         std::make_shared<ISystemRootService>(system, container));      server_manager->RegisterNamedService( -        "vi:s", std::make_shared<ISystemRootService>(system, nvnflinger, hos_binder_driver_server)); -    server_manager->RegisterNamedService("vi:u", std::make_shared<IApplicationRootService>( -                                                     system, nvnflinger, hos_binder_driver_server)); +        "vi:u", std::make_shared<IApplicationRootService>(system, container)); + +    std::stop_callback cb(token, [=] { container->OnTerminate(); }); +      ServerManager::RunServer(std::move(server_manager));  } diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 8e681370d..7c1f350d8 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -3,18 +3,14 @@  #pragma once +#include "common/polyfill_thread.h" +  namespace Core {  class System;  } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger -  namespace Service::VI { -void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, -                 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); +void LoopProcess(Core::System& system, std::stop_token token);  } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h index 91e4b380c..95ff66358 100644 --- a/src/core/hle/service/vi/vi_types.h +++ b/src/core/hle/service/vi/vi_types.h @@ -66,9 +66,17 @@ struct DisplayInfo {  };  static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); +struct DisplayMode { +    u32 width; +    u32 height; +    f32 refresh_rate; +    u32 unknown; +}; +static_assert(sizeof(DisplayMode) == 0x10, "DisplayMode has wrong size"); +  class NativeWindow final {  public: -    constexpr explicit NativeWindow(u32 id_) : id{id_} {} +    constexpr explicit NativeWindow(s32 id_) : id{static_cast<u64>(id_)} {}      constexpr explicit NativeWindow(const NativeWindow& other) = default;  private: diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp new file mode 100644 index 000000000..bdc4dfa96 --- /dev/null +++ b/src/core/hle/service/vi/vsync_manager.cpp @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/os/event.h" +#include "core/hle/service/vi/vsync_manager.h" + +namespace Service::VI { + +VsyncManager::VsyncManager() = default; +VsyncManager::~VsyncManager() = default; + +void VsyncManager::SignalVsync() { +    for (auto* event : m_vsync_events) { +        event->Signal(); +    } +} + +void VsyncManager::LinkVsyncEvent(Event* event) { +    m_vsync_events.insert(event); +} + +void VsyncManager::UnlinkVsyncEvent(Event* event) { +    m_vsync_events.erase(event); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/vsync_manager.h b/src/core/hle/service/vi/vsync_manager.h new file mode 100644 index 000000000..5d45bb5ee --- /dev/null +++ b/src/core/hle/service/vi/vsync_manager.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <set> + +namespace Service { +class Event; +} + +namespace Service::VI { + +class DisplayList; + +class VsyncManager { +public: +    explicit VsyncManager(); +    ~VsyncManager(); + +    void SignalVsync(); +    void LinkVsyncEvent(Event* event); +    void UnlinkVsyncEvent(Event* event); + +private: +    std::set<Event*> m_vsync_events; +}; + +} // namespace Service::VI diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp index 2a32b1276..de27ec49e 100644 --- a/src/core/loader/nca.cpp +++ b/src/core/loader/nca.cpp @@ -118,7 +118,9 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function<bool(size_t, size_t)>      mbedtls_sha256_starts_ret(&ctx, 0);      // Ensure we maintain a clean state on exit. -    SCOPE_EXIT({ mbedtls_sha256_free(&ctx); }); +    SCOPE_EXIT { +        mbedtls_sha256_free(&ctx); +    };      // Declare counters.      const size_t total_size = file->GetSize(); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index e10a4601e..8775369a4 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -831,11 +831,11 @@ struct Memory::Impl {          if (core == sys_core) [[unlikely]] {              sys_core_guard.lock();          } -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (core == sys_core) [[unlikely]] {                  sys_core_guard.unlock();              } -        }); +        };          gpu_device_memory->ApplyOpOnPointer(p, scratch_buffers[core], [&](DAddr address) {              auto& current_area = rasterizer_write_areas[core];              PAddr subaddress = address >> YUZU_PAGEBITS; @@ -866,11 +866,11 @@ struct Memory::Impl {          if (core == sys_core) [[unlikely]] {              sys_core_guard.lock();          } -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (core == sys_core) [[unlikely]] {                  sys_core_guard.unlock();              } -        }); +        };          auto& gpu = system.GPU();          gpu_device_memory->ApplyOpOnPointer(              p, scratch_buffers[core], [&](DAddr address) { gpu.InvalidateRegion(address, size); }); diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp index f7097d01d..caceeec4f 100644 --- a/src/core/memory/dmnt_cheat_vm.cpp +++ b/src/core/memory/dmnt_cheat_vm.cpp @@ -224,12 +224,12 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {      // If we've ever seen a decode failure, return false.      bool valid = decode_success;      CheatVmOpcode opcode = {}; -    SCOPE_EXIT({ +    SCOPE_EXIT {          decode_success &= valid;          if (valid) {              out = opcode;          } -    }); +    };      // Helper function for getting instruction dwords.      const auto GetNextDword = [&] { diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index d9d278fa3..5cd26819c 100644 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp @@ -933,8 +933,9 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,      if (index >= controller.stick_values.size()) {          return;      } -    auto trigger_guard = -        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); }); +    auto trigger_guard = SCOPE_GUARD { +        TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); +    };      std::scoped_lock lock{mutex};      const auto stick_value = TransformToStick(callback); @@ -989,8 +990,9 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac      if (index >= controller.trigger_values.size()) {          return;      } -    auto trigger_guard = -        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); }); +    auto trigger_guard = SCOPE_GUARD { +        TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); +    };      std::scoped_lock lock{mutex};      const auto trigger_value = TransformToTrigger(callback); @@ -1036,7 +1038,9 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback      if (index >= controller.motion_values.size()) {          return;      } -    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); }); +    SCOPE_EXIT { +        TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); +    };      std::scoped_lock lock{mutex};      auto& raw_status = controller.motion_values[index].raw_status;      auto& emulated = controller.motion_values[index].emulated; @@ -1070,8 +1074,9 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback      if (index >= controller.color_values.size()) {          return;      } -    auto trigger_guard = -        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); }); +    auto trigger_guard = SCOPE_GUARD { +        TriggerOnChange(ControllerTriggerType::Color, !is_configuring); +    };      std::scoped_lock lock{mutex};      controller.color_values[index] = TransformToColor(callback); @@ -1120,7 +1125,9 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac      if (index >= controller.battery_values.size()) {          return;      } -    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); }); +    SCOPE_EXIT { +        TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); +    };      std::scoped_lock lock{mutex};      controller.battery_values[index] = TransformToBattery(callback); @@ -1183,7 +1190,9 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac  }  void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) { -    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); }); +    SCOPE_EXIT { +        TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); +    };      std::scoped_lock lock{mutex};      controller.camera_values = TransformToCamera(callback); @@ -1198,7 +1207,9 @@ void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback  }  void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) { -    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); }); +    SCOPE_EXIT { +        TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); +    };      std::scoped_lock lock{mutex};      const auto force_value = TransformToStick(callback); @@ -1212,7 +1223,9 @@ void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& call  }  void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { -    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); }); +    SCOPE_EXIT { +        TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); +    };      std::scoped_lock lock{mutex};      controller.nfc_values = TransformToNfc(callback); @@ -1685,8 +1698,9 @@ void EmulatedController::Connect(bool use_temporary_value) {          return;      } -    auto trigger_guard = -        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); }); +    auto trigger_guard = SCOPE_GUARD { +        TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); +    };      std::scoped_lock lock{connect_mutex, mutex};      if (is_configuring) {          tmp_is_connected = true; @@ -1701,8 +1715,9 @@ void EmulatedController::Connect(bool use_temporary_value) {  }  void EmulatedController::Disconnect() { -    auto trigger_guard = -        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); }); +    auto trigger_guard = SCOPE_GUARD { +        TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); +    };      std::scoped_lock lock{connect_mutex, mutex};      if (is_configuring) {          tmp_is_connected = false; @@ -1738,8 +1753,9 @@ NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) c  }  void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { -    auto trigger_guard = -        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); }); +    auto trigger_guard = SCOPE_GUARD { +        TriggerOnChange(ControllerTriggerType::Type, !is_configuring); +    };      std::scoped_lock lock{mutex, npad_mutex};      if (is_configuring) { diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index c9f903213..0dd1c958a 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -268,7 +268,9 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {  }  Common::Input::DriverResult JoyconDriver::SetPollingMode() { -    SCOPE_EXIT({ disable_input_thread = false; }); +    SCOPE_EXIT { +        disable_input_thread = false; +    };      disable_input_thread = true;      rumble_protocol->EnableRumble(vibration_enabled && supported_features.vibration); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 44281e407..945cdb42b 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -60,11 +60,10 @@ public:          Add(spv::ImageOperandsMask::ConstOffsets, offsets);      } -    explicit ImageOperands(EmitContext& ctx, const IR::Value& offset, Id lod, Id ms) { +    explicit ImageOperands(Id lod, Id ms) {          if (Sirit::ValidId(lod)) {              Add(spv::ImageOperandsMask::Lod, lod);          } -        AddOffset(ctx, offset, ImageFetchOffsetAllowed);          if (Sirit::ValidId(ms)) {              Add(spv::ImageOperandsMask::Sample, ms);          } @@ -312,6 +311,43 @@ Id ImageGatherSubpixelOffset(EmitContext& ctx, const IR::TextureInstInfo& info,          return coords;      }  } + +void AddOffsetToCoordinates(EmitContext& ctx, const IR::TextureInstInfo& info, Id& coords, +                            Id offset) { +    if (!Sirit::ValidId(offset)) { +        return; +    } + +    Id result_type{}; +    switch (info.type) { +    case TextureType::Buffer: +    case TextureType::Color1D: { +        result_type = ctx.U32[1]; +        break; +    } +    case TextureType::ColorArray1D: +        offset = ctx.OpCompositeConstruct(ctx.U32[2], offset, ctx.u32_zero_value); +        [[fallthrough]]; +    case TextureType::Color2D: +    case TextureType::Color2DRect: { +        result_type = ctx.U32[2]; +        break; +    } +    case TextureType::ColorArray2D: +        offset = ctx.OpCompositeConstruct(ctx.U32[3], ctx.OpCompositeExtract(ctx.U32[1], coords, 0), +                                          ctx.OpCompositeExtract(ctx.U32[1], coords, 1), +                                          ctx.u32_zero_value); +        [[fallthrough]]; +    case TextureType::Color3D: { +        result_type = ctx.U32[3]; +        break; +    } +    case TextureType::ColorCube: +    case TextureType::ColorArrayCube: +        return; +    } +    coords = ctx.OpIAdd(result_type, coords, offset); +}  } // Anonymous namespace  Id EmitBindlessImageSampleImplicitLod(EmitContext&) { @@ -494,9 +530,10 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,                  operands.Span());  } -Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, -                  const IR::Value& offset, Id lod, Id ms) { +Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, +                  Id lod, Id ms) {      const auto info{inst->Flags<IR::TextureInstInfo>()}; +    AddOffsetToCoordinates(ctx, info, coords, offset);      if (info.type == TextureType::Buffer) {          lod = Id{};      } @@ -504,7 +541,7 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c          // This image is multisampled, lod must be implicit          lod = Id{};      } -    const ImageOperands operands(ctx, offset, lod, ms); +    const ImageOperands operands(lod, ms);      return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],                  TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());  } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 08fcabd58..5c01b1012 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -537,8 +537,8 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id                     const IR::Value& offset, const IR::Value& offset2);  Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,                         const IR::Value& offset, const IR::Value& offset2, Id dref); -Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, -                  const IR::Value& offset, Id lod, Id ms); +Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, +                  Id lod, Id ms);  Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod,                              const IR::Value& skip_mips);  Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 6d3d933c5..ed7a5b27e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -35,7 +35,7 @@ BufferCache<P>::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R      const s64 min_spacing_critical = device_local_memory - 512_MiB;      const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD);      const s64 min_vacancy_expected = (6 * mem_threshold) / 10; -    const s64 min_vacancy_critical = (3 * mem_threshold) / 10; +    const s64 min_vacancy_critical = (2 * mem_threshold) / 10;      minimum_memory = static_cast<u64>(          std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected),                   DEFAULT_EXPECTED_MEMORY)); @@ -1130,7 +1130,7 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {          channel_state->vertex_buffers[index] = NULL_BINDING;          return;      } -    if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) { +    if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end) || size >= 64_MiB) {          size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size));      }      const BufferId buffer_id = FindBuffer(*device_addr, size); diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index a94e1f043..0d47b032c 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -291,7 +291,9 @@ u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) {  }  void Maxwell3D::ConsumeSinkImpl() { -    SCOPE_EXIT({ method_sink.clear(); }); +    SCOPE_EXIT { +        method_sink.clear(); +    };      const auto control = shadow_state.shadow_ram_control;      if (control == Regs::ShadowRamControl::Track ||          control == Regs::ShadowRamControl::TrackWithFilter) { diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index c3eda6893..2135f1f2d 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h @@ -197,7 +197,9 @@ private:          MicroProfileOnThreadCreate(name.c_str());          // Cleanup -        SCOPE_EXIT({ MicroProfileOnThreadExit(); }); +        SCOPE_EXIT { +            MicroProfileOnThreadExit(); +        };          Common::SetCurrentThreadName(name.c_str());          Common::SetCurrentThreadPriority(Common::ThreadPriority::High); diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 58d8110b8..477e11457 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -22,7 +22,9 @@ static void RunThread(std::stop_token stop_token, Core::System& system,                        Tegra::Control::Scheduler& scheduler, SynchState& state) {      std::string name = "GPU";      MicroProfileOnThreadCreate(name.c_str()); -    SCOPE_EXIT({ MicroProfileOnThreadExit(); }); +    SCOPE_EXIT { +        MicroProfileOnThreadExit(); +    };      Common::SetCurrentThreadName(name.c_str());      Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical); diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.cpp b/src/video_core/host1x/ffmpeg/ffmpeg.cpp index 96686da59..1003cd38d 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.cpp +++ b/src/video_core/host1x/ffmpeg/ffmpeg.cpp @@ -273,10 +273,10 @@ DeinterlaceFilter::DeinterlaceFilter(const Frame& frame) {      const AVFilter* buffer_sink = avfilter_get_by_name("buffersink");      AVFilterInOut* inputs = avfilter_inout_alloc();      AVFilterInOut* outputs = avfilter_inout_alloc(); -    SCOPE_EXIT({ +    SCOPE_EXIT {          avfilter_inout_free(&inputs);          avfilter_inout_free(&outputs); -    }); +    };      // Don't know how to get the accurate time_base but it doesn't matter for yadif filter      // so just use 1/1 to make buffer filter happy diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 46e853e04..fb529f88b 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp @@ -92,12 +92,12 @@ public:  private:      void Fallback(const std::vector<u32>& parameters) { -        SCOPE_EXIT({ +        SCOPE_EXIT {              if (extended) {                  maxwell3d.engine_state = Maxwell3D::EngineHint::None;                  maxwell3d.replace_table.clear();              } -        }); +        };          maxwell3d.RefreshParameters();          const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); @@ -281,12 +281,12 @@ public:  private:      void Fallback(const std::vector<u32>& parameters) { -        SCOPE_EXIT({ +        SCOPE_EXIT {              // Clean everything.              maxwell3d.regs.vertex_id_base = 0x0;              maxwell3d.engine_state = Maxwell3D::EngineHint::None;              maxwell3d.replace_table.clear(); -        }); +        };          maxwell3d.RefreshParameters();          const u32 start_indirect = parameters[0];          const u32 end_indirect = parameters[1]; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index b42fb110c..16af8e6bd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -230,7 +230,9 @@ template <typename Func>  void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) {      MICROPROFILE_SCOPE(OpenGL_Drawing); -    SCOPE_EXIT({ gpu.TickWork(); }); +    SCOPE_EXIT { +        gpu.TickWork(); +    };      gpu_memory->FlushCaching();      GraphicsPipeline* const pipeline{shader_cache.CurrentGraphicsPipeline()}; @@ -355,7 +357,9 @@ void RasterizerOpenGL::DrawIndirect() {  void RasterizerOpenGL::DrawTexture() {      MICROPROFILE_SCOPE(OpenGL_Drawing); -    SCOPE_EXIT({ gpu.TickWork(); }); +    SCOPE_EXIT { +        gpu.TickWork(); +    };      texture_cache.SynchronizeGraphicsDescriptors();      texture_cache.UpdateRenderTargets(false); diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index 3847a9a13..4e41afe5b 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -82,7 +82,9 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants,      // Finish any pending renderpass      scheduler.RequestOutsideRenderPassOperationContext();      scheduler.Wait(resource_ticks[image_index]); -    SCOPE_EXIT({ resource_ticks[image_index] = scheduler.CurrentTick(); }); +    SCOPE_EXIT { +        resource_ticks[image_index] = scheduler.CurrentTick(); +    };      if (!use_accelerated) {          UpdateRawImage(framebuffer, image_index); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index d50417116..c553f5b3d 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -144,7 +144,9 @@ void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebu          return;      } -    SCOPE_EXIT({ render_window.OnFrameDisplayed(); }); +    SCOPE_EXIT { +        render_window.OnFrameDisplayed(); +    };      RenderAppletCaptureLayer(framebuffers); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index aa0a027bb..74f9f099e 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -196,7 +196,9 @@ template <typename Func>  void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {      MICROPROFILE_SCOPE(Vulkan_Drawing); -    SCOPE_EXIT({ gpu.TickWork(); }); +    SCOPE_EXIT { +        gpu.TickWork(); +    };      FlushWork();      gpu_memory->FlushCaching(); @@ -288,7 +290,9 @@ void RasterizerVulkan::DrawIndirect() {  void RasterizerVulkan::DrawTexture() {      MICROPROFILE_SCOPE(Vulkan_Drawing); -    SCOPE_EXIT({ gpu.TickWork(); }); +    SCOPE_EXIT { +        gpu.TickWork(); +    };      FlushWork();      query_cache.NotifySegment(true); diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 5b3c7aa5a..9055b1b92 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -3,6 +3,7 @@  #include "common/common_types.h"  #include "common/math_util.h" +#include "common/settings.h"  #include "video_core/surface.h"  namespace VideoCore::Surface { @@ -400,11 +401,20 @@ std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {      return {DefaultBlockWidth(format), DefaultBlockHeight(format)};  } -u64 EstimatedDecompressedSize(u64 base_size, PixelFormat format) { +u64 TranscodedAstcSize(u64 base_size, PixelFormat format) {      constexpr u64 RGBA8_PIXEL_SIZE = 4;      const u64 base_block_size = static_cast<u64>(DefaultBlockWidth(format)) *                                  static_cast<u64>(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE; -    return (base_size * base_block_size) / BytesPerBlock(format); +    const u64 uncompressed_size = (base_size * base_block_size) / BytesPerBlock(format); + +    switch (Settings::values.astc_recompression.GetValue()) { +    case Settings::AstcRecompression::Bc1: +        return uncompressed_size / 8; +    case Settings::AstcRecompression::Bc3: +        return uncompressed_size / 4; +    default: +        return uncompressed_size; +    }  }  } // namespace VideoCore::Surface diff --git a/src/video_core/surface.h b/src/video_core/surface.h index a5e8e2f62..ec9cd2fbf 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h @@ -517,6 +517,6 @@ size_t PixelComponentSizeBitsInteger(PixelFormat format);  std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); -u64 EstimatedDecompressedSize(u64 base_size, PixelFormat format); +u64 TranscodedAstcSize(u64 base_size, PixelFormat format);  } // namespace VideoCore::Surface diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 01c3561c9..53b4876f2 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -55,7 +55,7 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag          const s64 min_spacing_critical = device_local_memory - 512_MiB;          const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD);          const s64 min_vacancy_expected = (6 * mem_threshold) / 10; -        const s64 min_vacancy_critical = (3 * mem_threshold) / 10; +        const s64 min_vacancy_critical = (2 * mem_threshold) / 10;          expected_memory = static_cast<u64>(              std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected),                       DEFAULT_EXPECTED_MEMORY)); @@ -1979,7 +1979,7 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {      if ((IsPixelFormatASTC(image.info.format) &&           True(image.flags & ImageFlagBits::AcceleratedUpload)) ||          True(image.flags & ImageFlagBits::Converted)) { -        tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); +        tentative_size = TranscodedAstcSize(tentative_size, image.info.format);      }      total_used_memory += Common::AlignUp(tentative_size, 1024);      image.lru_index = lru_cache.Insert(image_id, frame_tick); @@ -2149,7 +2149,7 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) {      if ((IsPixelFormatASTC(image.info.format) &&           True(image.flags & ImageFlagBits::AcceleratedUpload)) ||          True(image.flags & ImageFlagBits::Converted)) { -        tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); +        tentative_size = TranscodedAstcSize(tentative_size, image.info.format);      }      total_used_memory -= Common::AlignUp(tentative_size, 1024);      const GPUVAddr gpu_addr = image.gpu_addr; diff --git a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp index 5fa0d9620..f41c3e506 100644 --- a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp +++ b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp @@ -116,7 +116,9 @@ void NsightAftermathTracker::OnGpuCrashDumpCallback(const void* gpu_crash_dump,          LOG_ERROR(Render_Vulkan, "Failed to create decoder");          return;      } -    SCOPE_EXIT({ GFSDK_Aftermath_GpuCrashDump_DestroyDecoder(decoder); }); +    SCOPE_EXIT { +        GFSDK_Aftermath_GpuCrashDump_DestroyDecoder(decoder); +    };      u32 json_size = 0;      if (!GFSDK_Aftermath_SUCCEED(GFSDK_Aftermath_GpuCrashDump_GenerateJSON( diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 0d16bfd65..b2ae3db52 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -646,10 +646,10 @@ void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParamete                                             std::shared_ptr<Service::NFC::NfcDevice> nfp_device) {      cabinet_applet =          new QtAmiiboSettingsDialog(this, parameters, input_subsystem.get(), nfp_device); -    SCOPE_EXIT({ +    SCOPE_EXIT {          cabinet_applet->deleteLater();          cabinet_applet = nullptr; -    }); +    };      cabinet_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |                                     Qt::WindowTitleHint | Qt::WindowSystemMenuHint); @@ -673,10 +673,10 @@ void GMainWindow::ControllerSelectorReconfigureControllers(      const Core::Frontend::ControllerParameters& parameters) {      controller_applet =          new QtControllerSelectorDialog(this, parameters, input_subsystem.get(), *system); -    SCOPE_EXIT({ +    SCOPE_EXIT {          controller_applet->deleteLater();          controller_applet = nullptr; -    }); +    };      controller_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint |                                        Qt::WindowStaysOnTopHint | Qt::WindowTitleHint | @@ -703,10 +703,10 @@ void GMainWindow::ControllerSelectorRequestExit() {  void GMainWindow::ProfileSelectorSelectProfile(      const Core::Frontend::ProfileSelectParameters& parameters) {      profile_select_applet = new QtProfileSelectionDialog(*system, this, parameters); -    SCOPE_EXIT({ +    SCOPE_EXIT {          profile_select_applet->deleteLater();          profile_select_applet = nullptr; -    }); +    };      profile_select_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint |                                            Qt::WindowStaysOnTopHint | Qt::WindowTitleHint | @@ -1604,6 +1604,7 @@ void GMainWindow::ConnectMenuEvents() {      connect_menu(ui->action_Open_yuzu_Folder, &GMainWindow::OnOpenYuzuFolder);      connect_menu(ui->action_Verify_installed_contents, &GMainWindow::OnVerifyInstalledContents);      connect_menu(ui->action_Install_Firmware, &GMainWindow::OnInstallFirmware); +    connect_menu(ui->action_Install_Keys, &GMainWindow::OnInstallDecryptionKeys);      connect_menu(ui->action_About, &GMainWindow::OnAbout);  } @@ -1633,6 +1634,7 @@ void GMainWindow::UpdateMenuState() {      }      ui->action_Install_Firmware->setEnabled(!emulation_running); +    ui->action_Install_Keys->setEnabled(!emulation_running);      for (QAction* action : applet_actions) {          action->setEnabled(is_firmware_available && !emulation_running); @@ -2885,17 +2887,19 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,          LOG_ERROR(Frontend, "CoInitialize failed");          return false;      } -    SCOPE_EXIT({ CoUninitialize(); }); +    SCOPE_EXIT { +        CoUninitialize(); +    };      IShellLinkW* ps1 = nullptr;      IPersistFile* persist_file = nullptr; -    SCOPE_EXIT({ +    SCOPE_EXIT {          if (persist_file != nullptr) {              persist_file->Release();          }          if (ps1 != nullptr) {              ps1->Release();          } -    }); +    };      HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW,                                      reinterpret_cast<void**>(&ps1));      if (FAILED(hres)) { @@ -3520,10 +3524,10 @@ void GMainWindow::OnSaveConfig() {  void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {      error_applet = new OverlayDialog(render_window, *system, error_code, error_text, QString{},                                       tr("OK"), Qt::AlignLeft | Qt::AlignVCenter); -    SCOPE_EXIT({ +    SCOPE_EXIT {          error_applet->deleteLater();          error_applet = nullptr; -    }); +    };      error_applet->exec();      emit ErrorDisplayFinished(); @@ -4167,9 +4171,8 @@ void GMainWindow::OnInstallFirmware() {          return;      } -    QString firmware_source_location = -        QFileDialog::getExistingDirectory(this, tr("Select Dumped Firmware Source Location"), -                                          QString::fromStdString(""), QFileDialog::ShowDirsOnly); +    const QString firmware_source_location = QFileDialog::getExistingDirectory( +        this, tr("Select Dumped Firmware Source Location"), {}, QFileDialog::ShowDirsOnly);      if (firmware_source_location.isEmpty()) {          return;      } @@ -4200,8 +4203,9 @@ void GMainWindow::OnInstallFirmware() {      std::vector<std::filesystem::path> out;      const Common::FS::DirEntryCallable callback =          [&out](const std::filesystem::directory_entry& entry) { -            if (entry.path().has_extension() && entry.path().extension() == ".nca") +            if (entry.path().has_extension() && entry.path().extension() == ".nca") {                  out.emplace_back(entry.path()); +            }              return true;          }; @@ -4233,7 +4237,6 @@ void GMainWindow::OnInstallFirmware() {      auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered");      bool success = true; -    bool cancelled = false;      int i = 0;      for (const auto& firmware_src_path : out) {          i++; @@ -4248,24 +4251,22 @@ void GMainWindow::OnInstallFirmware() {              success = false;          } -        if (QtProgressCallback(100, 20 + (int)(((float)(i) / (float)out.size()) * 70.0))) { -            success = false; -            cancelled = true; -            break; +        if (QtProgressCallback( +                100, 20 + static_cast<int>(((i) / static_cast<float>(out.size())) * 70.0))) { +            progress.close(); +            QMessageBox::warning( +                this, tr("Firmware install failed"), +                tr("Firmware installation cancelled, firmware may be in bad state, " +                   "restart yuzu or re-install firmware.")); +            return;          }      } -    if (!success && !cancelled) { +    if (!success) {          progress.close();          QMessageBox::critical(this, tr("Firmware install failed"),                                tr("One or more firmware files failed to copy into NAND."));          return; -    } else if (cancelled) { -        progress.close(); -        QMessageBox::warning(this, tr("Firmware install failed"), -                             tr("Firmware installation cancelled, firmware may be in bad state, " -                                "restart yuzu or re-install firmware.")); -        return;      }      // Re-scan VFS for the newly placed firmware files. @@ -4293,6 +4294,84 @@ void GMainWindow::OnInstallFirmware() {      OnCheckFirmwareDecryption();  } +void GMainWindow::OnInstallDecryptionKeys() { +    // Don't do this while emulation is running. +    if (emu_thread != nullptr && emu_thread->IsRunning()) { +        return; +    } + +    const QString key_source_location = QFileDialog::getOpenFileName( +        this, tr("Select Dumped Keys Location"), {}, QStringLiteral("prod.keys (prod.keys)"), {}, +        QFileDialog::ReadOnly); +    if (key_source_location.isEmpty()) { +        return; +    } + +    // Verify that it contains prod.keys, title.keys and optionally, key_retail.bin +    LOG_INFO(Frontend, "Installing key files from {}", key_source_location.toStdString()); + +    const std::filesystem::path prod_key_path = key_source_location.toStdString(); +    const std::filesystem::path key_source_path = prod_key_path.parent_path(); +    if (!Common::FS::IsDir(key_source_path)) { +        return; +    } + +    bool prod_keys_found = false; +    std::vector<std::filesystem::path> source_key_files; + +    if (Common::FS::Exists(prod_key_path)) { +        prod_keys_found = true; +        source_key_files.emplace_back(prod_key_path); +    } + +    if (Common::FS::Exists(key_source_path / "title.keys")) { +        source_key_files.emplace_back(key_source_path / "title.keys"); +    } + +    if (Common::FS::Exists(key_source_path / "key_retail.bin")) { +        source_key_files.emplace_back(key_source_path / "key_retail.bin"); +    } + +    // There should be at least prod.keys. +    if (source_key_files.empty() || !prod_keys_found) { +        QMessageBox::warning(this, tr("Decryption Keys install failed"), +                             tr("prod.keys is a required decryption key file.")); +        return; +    } + +    const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); +    for (auto key_file : source_key_files) { +        std::filesystem::path destination_key_file = yuzu_keys_dir / key_file.filename(); +        if (!std::filesystem::copy_file(key_file, destination_key_file, +                                        std::filesystem::copy_options::overwrite_existing)) { +            LOG_ERROR(Frontend, "Failed to copy file {} to {}", key_file.string(), +                      destination_key_file.string()); +            QMessageBox::critical(this, tr("Decryption Keys install failed"), +                                  tr("One or more keys failed to copy.")); +            return; +        } +    } + +    // Reinitialize the key manager, re-read the vfs (for update/dlc files), +    // and re-populate the game list in the UI if the user has already added +    // game folders. +    Core::Crypto::KeyManager::Instance().ReloadKeys(); +    system->GetFileSystemController().CreateFactories(*vfs); +    game_list->PopulateAsync(UISettings::values.game_dirs); + +    if (ContentManager::AreKeysPresent()) { +        QMessageBox::information(this, tr("Decryption Keys install succeeded"), +                                 tr("Decryption Keys were successfully installed")); +    } else { +        QMessageBox::critical( +            this, tr("Decryption Keys install failed"), +            tr("Decryption Keys failed to initialize. Check that your dumping tools are " +               "up to date and re-dump keys.")); +    } + +    OnCheckFirmwareDecryption(); +} +  void GMainWindow::OnAbout() {      AboutDialog aboutDialog(this);      aboutDialog.exec(); @@ -5192,7 +5271,9 @@ int main(int argc, char* argv[]) {      Common::DetachedTasks detached_tasks;      MicroProfileOnThreadCreate("Frontend"); -    SCOPE_EXIT({ MicroProfileShutdown(); }); +    SCOPE_EXIT { +        MicroProfileShutdown(); +    };      Common::ConfigureNvidiaEnvironmentFlags(); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 1f0e35c67..fce643f3f 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -381,6 +381,7 @@ private slots:      void OnOpenYuzuFolder();      void OnVerifyInstalledContents();      void OnInstallFirmware(); +    void OnInstallDecryptionKeys();      void OnAbout();      void OnToggleFilterBar();      void OnToggleStatusBar(); diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 6ff444a22..85dc1f2f6 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -165,8 +165,9 @@       <addaction name="separator"/>       <addaction name="action_Configure_Tas"/>      </widget> -    <addaction name="action_Verify_installed_contents"/> +    <addaction name="action_Install_Keys"/>      <addaction name="action_Install_Firmware"/> +    <addaction name="action_Verify_installed_contents"/>      <addaction name="separator"/>      <addaction name="menu_cabinet_applet"/>      <addaction name="action_Load_Album"/> @@ -469,6 +470,11 @@      <string>Install Firmware</string>     </property>    </action> +  <action name="action_Install_Keys"> +   <property name="text"> +    <string>Install Decryption Keys</string> +   </property> +  </action>   </widget>   <resources>    <include location="yuzu.qrc"/> diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 3b321dad1..8a8cdbc44 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -327,7 +327,9 @@ int main(int argc, char** argv) {  #endif      MicroProfileOnThreadCreate("EmuThread"); -    SCOPE_EXIT({ MicroProfileShutdown(); }); +    SCOPE_EXIT { +        MicroProfileShutdown(); +    };      Common::ConfigureNvidiaEnvironmentFlags();  | 
