Compare commits

..

3 Commits

Author SHA1 Message Date
Caio Oliveira
513b81b965 [DONOTMERGE] add debug knobs for faster testing
* should work?

Signed-off-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
2025-12-16 20:52:03 +01:00
Caio Oliveira
955cc70796 Fix license headers 2025-12-16 20:52:03 +01:00
wildcard
b55c8bb2e7 [Vulkan] speed up bank lookup with LRU cache, batch growth to 32
Adds a tiny 8 entry LRU cache(should be tested for optimal number)
Increase batch growth to 32 (should be tested to determine the difference between 16 and 32)
2025-12-16 20:52:03 +01:00
79 changed files with 800 additions and 1466 deletions

2
.gitignore vendored
View File

@@ -37,8 +37,6 @@ CMakeLists.txt.user*
# *nix related
# Common convention for backup or temporary files
*~
*.core
dtrace-out/
# Visual Studio CMake settings
CMakeSettings.json

View File

@@ -25,9 +25,9 @@ It is written in C++ with portability in mind, and we actively maintain builds f
<img src="https://img.shields.io/discord/1367654015269339267?color=5865F2&label=Eden&logo=discord&logoColor=white"
alt="Discord">
</a>
<a href="https://stt.gg/qKgFEAbH">
<img src="https://img.shields.io/revolt/invite/qKgFEAbH?color=d61f3a&label=Stoat"
alt="Stoat">
<a href="https://rvlt.gg/qKgFEAbH">
<img src="https://img.shields.io/revolt/invite/qKgFEAbH?color=d61f3a&label=Revolt"
alt="Revolt">
</a>
</p>
@@ -52,10 +52,10 @@ Check out our [website](https://eden-emu.dev) for the latest news on exciting fe
## Development
Most of the development happens on our Git server. It is also where [our central repository](https://git.eden-emu.dev/eden-emu/eden) is hosted. For development discussions, please join us on [Discord](https://discord.gg/HstXbPch7X) or [Stoat](https://stt.gg/qKgFEAbH).
Most of the development happens on our Git server. It is also where [our central repository](https://git.eden-emu.dev/eden-emu/eden) is hosted. For development discussions, please join us on [Discord](https://discord.gg/HstXbPch7X) or [Revolt](https://rvlt.gg/qKgFEAbH).
You can also follow us on [X (Twitter)](https://nitter.poast.org/edenemuofficial) for updates and announcements.
If you would like to contribute, we are open to new developers and pull requests. Please ensure that your work is of a high standard and properly documented. You can also contact any of the developers on Discord or Stoat to learn more about the current state of the emulator.
If you would like to contribute, we are open to new developers and pull requests. Please ensure that your work is of a high standard and properly documented. You can also contact any of the developers on Discord or Revolt to learn more about the current state of the emulator.
See the [sign-up instructions](docs/SIGNUP.md) for information on registration.

View File

@@ -137,7 +137,7 @@ If your initial configure failed:
- Evaluate the error and find any related settings
- See the [CPM docs](CPM.md) to see if you may need to forcefully bundle any packages
Otherwise, feel free to ask for help in Stoat or Discord.
Otherwise, feel free to ask for help in Revolt or Discord.
## Caveats

View File

@@ -18,7 +18,6 @@ import android.content.IntentFilter
import android.content.res.Configuration
import android.graphics.Rect
import android.graphics.drawable.Icon
import android.hardware.input.InputManager
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
@@ -64,12 +63,11 @@ import kotlin.math.roundToInt
import org.yuzu.yuzu_emu.utils.ForegroundService
import androidx.core.os.BundleCompat
class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager.InputDeviceListener {
class EmulationActivity : AppCompatActivity(), SensorEventListener {
private lateinit var binding: ActivityEmulationBinding
var isActivityRecreated = false
private lateinit var nfcReader: NfcReader
private lateinit var inputManager: InputManager
private var touchDownTime: Long = 0
private val maxTapDuration = 500L
@@ -142,9 +140,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
nfcReader = NfcReader(this)
nfcReader.initialize()
inputManager = getSystemService(INPUT_SERVICE) as InputManager
inputManager.registerInputDeviceListener(this, null)
foregroundService = Intent(this, ForegroundService::class.java)
startForegroundService(foregroundService)
@@ -211,9 +206,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
override fun onDestroy() {
super.onDestroy()
inputManager.unregisterInputDeviceListener(this)
stopForegroundService(this)
NativeLibrary.playTimeManagerStop()
}
override fun onUserLeaveHint() {
@@ -249,10 +244,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
val isPhysicalKeyboard = event.source and InputDevice.SOURCE_KEYBOARD == InputDevice.SOURCE_KEYBOARD &&
event.device?.isVirtual == false
val isControllerInput = event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK ||
event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
if (!isControllerInput &&
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE &&
!isPhysicalKeyboard
) {
@@ -263,18 +256,12 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
return super.dispatchKeyEvent(event)
}
if (isControllerInput && event.action == KeyEvent.ACTION_DOWN) {
notifyControllerInput()
}
return InputHandler.dispatchKeyEvent(event)
}
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
val isControllerInput = event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK ||
event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
if (!isControllerInput &&
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE
) {
@@ -290,54 +277,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
return true
}
if (isControllerInput) {
notifyControllerInput()
}
return InputHandler.dispatchGenericMotionEvent(event)
}
private fun notifyControllerInput() {
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
val emulationFragment =
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
emulationFragment?.onControllerInputDetected()
}
private fun isGameController(deviceId: Int): Boolean {
val device = InputDevice.getDevice(deviceId) ?: return false
val sources = device.sources
return sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
}
override fun onInputDeviceAdded(deviceId: Int) {
if (isGameController(deviceId)) {
InputHandler.updateControllerData()
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
val emulationFragment =
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
emulationFragment?.onControllerConnected()
}
}
override fun onInputDeviceRemoved(deviceId: Int) {
InputHandler.updateControllerData()
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
val emulationFragment =
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
emulationFragment?.onControllerDisconnected()
}
override fun onInputDeviceChanged(deviceId: Int) {
if (isGameController(deviceId)) {
InputHandler.updateControllerData()
}
}
override fun onSensorChanged(event: SensorEvent) {
val rotation = this.display?.rotation
if (rotation == Surface.ROTATION_90) {
@@ -577,10 +519,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
when (event.action) {
MotionEvent.ACTION_DOWN -> {
touchDownTime = System.currentTimeMillis()
// show overlay immediately on touch and cancel timer when only auto-hide is enabled
if (!emulationViewModel.drawerOpen.value &&
BooleanSetting.ENABLE_INPUT_OVERLAY_AUTO_HIDE.getBoolean() &&
!BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) {
// show overlay immediately on touch and cancel timer
if (!emulationViewModel.drawerOpen.value) {
fragment.handler.removeCallbacksAndMessages(null)
fragment.showOverlay()
}

View File

@@ -52,7 +52,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
SOC_OVERLAY_BACKGROUND("soc_overlay_background"),
ENABLE_INPUT_OVERLAY_AUTO_HIDE("enable_input_overlay_auto_hide"),
HIDE_OVERLAY_ON_CONTROLLER_INPUT("hide_overlay_on_controller_input"),
PERF_OVERLAY_BACKGROUND("perf_overlay_background"),
SHOW_PERFORMANCE_OVERLAY("show_performance_overlay"),

View File

@@ -387,13 +387,6 @@ abstract class SettingsItem(
valueHint = R.string.seconds
)
)
put(
SwitchSetting(
BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT,
titleId = R.string.hide_overlay_on_controller_input,
descriptionId = R.string.hide_overlay_on_controller_input_description
)
)
put(
SwitchSetting(

View File

@@ -274,7 +274,6 @@ class SettingsFragmentPresenter(
sl.apply {
add(BooleanSetting.ENABLE_INPUT_OVERLAY_AUTO_HIDE.key)
add(IntSetting.INPUT_OVERLAY_AUTO_HIDE.key)
add(BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.key)
}
}

View File

@@ -100,7 +100,7 @@ class AboutFragment : Fragment() {
}
binding.buttonDiscord.setOnClickListener { openLink(getString(R.string.discord_link)) }
binding.buttonStoat.setOnClickListener { openLink(getString(R.string.stoat_link)) }
binding.buttonRevolt.setOnClickListener { openLink(getString(R.string.revolt_link)) }
binding.buttonX.setOnClickListener { openLink(getString(R.string.x_link)) }
binding.buttonWebsite.setOnClickListener { openLink(getString(R.string.website_link)) }
binding.buttonGithub.setOnClickListener { openLink(getString(R.string.github_link)) }

View File

@@ -93,6 +93,7 @@ import org.yuzu.yuzu_emu.utils.collect
import org.yuzu.yuzu_emu.utils.CustomSettingsHandler
import java.io.ByteArrayOutputStream
import java.io.File
import kotlin.coroutines.coroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
@@ -105,7 +106,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
val handler = Handler(Looper.getMainLooper())
private var isOverlayVisible = true
private var controllerInputReceived = false
private var _binding: FragmentEmulationBinding? = null
@@ -656,12 +656,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(newState)
updateQuickOverlayMenuEntry(newState)
binding.surfaceInputOverlay.refreshControls()
// Sync view visibility with the setting
if (newState) {
showOverlay()
} else {
hideOverlay()
}
NativeConfig.saveGlobalConfig()
true
}
@@ -1907,7 +1901,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
companion object {
fun fromValue(value: Int): AmiiboState =
entries.firstOrNull { it.value == value } ?: Disabled
values().firstOrNull { it.value == value } ?: Disabled
}
}
@@ -1920,7 +1914,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
companion object {
fun fromValue(value: Int): AmiiboLoadResult =
entries.firstOrNull { it.value == value } ?: Unknown
values().firstOrNull { it.value == value } ?: Unknown
}
}
@@ -1977,8 +1971,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
fun showOverlay() {
if (!isOverlayVisible) {
isOverlayVisible = true
// Reset controller input flag so controller can hide overlay again
controllerInputReceived = false
ViewUtils.showView(binding.surfaceInputOverlay, 500)
}
}
@@ -1986,26 +1978,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private fun hideOverlay() {
if (isOverlayVisible) {
isOverlayVisible = false
ViewUtils.hideView(binding.surfaceInputOverlay)
ViewUtils.hideView(binding.surfaceInputOverlay, 500)
}
}
fun onControllerInputDetected() {
if (!BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) return
if (!BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) return
if (controllerInputReceived) return
controllerInputReceived = true
hideOverlay()
}
fun onControllerConnected() {
controllerInputReceived = false
}
fun onControllerDisconnected() {
if (!BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) return
if (!BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) return
controllerInputReceived = false
showOverlay()
}
}

View File

@@ -92,11 +92,6 @@ namespace AndroidSettings {
Settings::Setting<u32> input_overlay_auto_hide{linkage, 5, "input_overlay_auto_hide",
Settings::Category::Overlay,
Settings::Specialization::Default, true, true, &enable_input_overlay_auto_hide};
Settings::Setting<bool> hide_overlay_on_controller_input{linkage, false,
"hide_overlay_on_controller_input",
Settings::Category::Overlay,
Settings::Specialization::Default, true,
true};
Settings::Setting<bool> perf_overlay_background{linkage, false, "perf_overlay_background",
Settings::Category::Overlay,
Settings::Specialization::Default, true,

View File

@@ -220,12 +220,12 @@
app:iconPadding="0dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_stoat"
android:id="@+id/button_revolt"
style="@style/EdenButton.Secondary"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginEnd="12dp"
app:icon="@drawable/ic_stoat"
app:icon="@drawable/ic_revolt"
app:iconGravity="textStart"
app:iconSize="24dp"
app:iconPadding="0dp" />
@@ -270,4 +270,4 @@
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -215,12 +215,12 @@
<com.google.android.material.button.MaterialButton
style="@style/EdenButton.Secondary"
android:id="@+id/button_stoat"
android:id="@+id/button_revolt"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginEnd="8dp"
app:icon="@drawable/ic_stoat"
app:icon="@drawable/ic_revolt"
app:iconSize="24dp"
app:iconGravity="textStart"
app:iconPadding="0dp" />
@@ -235,7 +235,7 @@
app:icon="@drawable/ic_x"
app:iconSize="24dp"
app:iconGravity="textStart"
app:iconPadding="0dp" />
app:iconPadding="0dp" />
<com.google.android.material.button.MaterialButton
style="@style/EdenButton.Secondary"
@@ -267,4 +267,4 @@
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -26,8 +26,6 @@
<string name="overlay_auto_hide">Overlay Auto Hide</string>
<string name="overlay_auto_hide_description">Automatically hide the touch controls overlay after the specified time of inactivity.</string>
<string name="enable_input_overlay_auto_hide">Enable Overlay Auto Hide</string>
<string name="hide_overlay_on_controller_input">Hide Overlay on Controller Input</string>
<string name="hide_overlay_on_controller_input_description">Automatically hide the touch controls overlay when a physical controller is used. Overlay reappears when controller is disconnected.</string>
<string name="input_overlay_options">Input Overlay</string>
<string name="input_overlay_options_description">Configure on-screen controls</string>
@@ -447,7 +445,7 @@
<string name="user_data_export_cancelled">Export cancelled</string>
<string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string>
<string name="discord_link" translatable="false">https://discord.gg/HstXbPch7X</string>
<string name="stoat_link" translatable="false">https://stt.gg/qKgFEAbH</string>
<string name="revolt_link" translatable="false">https://rvlt.gg/qKgFEAbH</string>
<string name="x_link" translatable="false">https://nitter.poast.org/edenemuofficial</string>
<string name="website_link" translatable="false">https://eden-emu.dev</string>
<string name="github_link" translatable="false">https://git.eden-emu.dev/eden-emu</string>

View File

@@ -17,8 +17,6 @@ add_library(core STATIC
constants.h
core.cpp
core.h
game_settings.cpp
game_settings.h
core_timing.cpp
core_timing.h
cpu_manager.cpp

View File

@@ -6,7 +6,6 @@
#include <memory>
#include <utility>
#include "game_settings.h"
#include "audio_core/audio_core.h"
#include "common/fs/fs.h"
#include "common/logging/log.h"
@@ -293,6 +292,48 @@ struct System::Impl {
return SystemResultStatus::Success;
}
void LoadOverrides(u64 programId) const {
std::string vendor = gpu_core->Renderer().GetDeviceVendor();
LOG_INFO(Core, "GPU Vendor: {}", vendor);
// Reset all per-game flags
Settings::values.use_squashed_iterated_blend = false;
// Insert PC overrides here
#ifdef ANDROID
// Example on how to set a setting based on the program ID and vendor
if (programId == 0x010028600EBDA000 && vendor == "Mali") { // Mario 3d World
// Settings::values.example = true;
}
// Example array of program IDs
const std::array<u64, 10> example_array = {
//0xprogramId
0x0004000000033400, // Game 1
0x0004000000033500 // Game 2
// And so on
};
for (auto id : example_array) {
if (programId == id) {
// Settings::values.example = true;
break;
}
}
#endif
// Ninja Gaiden Ragebound
constexpr u64 ngr = 0x0100781020710000ULL;
if (programId == ngr) {
LOG_INFO(Core, "Enabling game specifc override: use_squashed_iterated_blend");
Settings::values.use_squashed_iterated_blend = true;
}
}
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath,
Service::AM::FrontendAppletParameters& params) {
@@ -378,8 +419,7 @@ struct System::Impl {
LOG_ERROR(Core, "Failed to find program id for ROM");
}
GameSettings::LoadOverrides(program_id, gpu_core->Renderer());
LoadOverrides(program_id);
if (auto room_member = Network::GetRoomMember().lock()) {
Network::GameInfo game_info;
game_info.name = name;

View File

@@ -1,140 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/game_settings.h"
#include <algorithm>
#include <cctype>
#include "common/logging/log.h"
#include "common/settings.h"
#include "video_core/renderer_base.h"
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
namespace Core::GameSettings {
static GPUVendor GetGPU(const std::string& gpu_vendor_string) {
struct Entry { const char* name; GPUVendor vendor; };
static constexpr Entry GpuVendor[] = {
// NVIDIA
{"NVIDIA", GPUVendor::Nvidia},
{"Nouveau", GPUVendor::Nvidia},
{"NVK", GPUVendor::Nvidia},
{"Tegra", GPUVendor::Nvidia},
// AMD
{"AMD", GPUVendor::AMD},
{"RadeonSI", GPUVendor::AMD},
{"RADV", GPUVendor::AMD},
{"AMDVLK", GPUVendor::AMD},
{"R600", GPUVendor::AMD},
// Intel
{"Intel", GPUVendor::Intel},
{"ANV", GPUVendor::Intel},
{"i965", GPUVendor::Intel},
{"i915", GPUVendor::Intel},
{"OpenSWR", GPUVendor::Intel},
// Apple
{"Apple", GPUVendor::Apple},
{"MoltenVK", GPUVendor::Apple},
// Qualcomm / Adreno
{"Qualcomm", GPUVendor::Qualcomm},
{"Turnip", GPUVendor::Qualcomm},
// ARM / Mali
{"Mali", GPUVendor::ARM},
{"PanVK", GPUVendor::ARM},
// Imagination / PowerVR
{"PowerVR", GPUVendor::Imagination},
{"PVR", GPUVendor::Imagination},
// Microsoft / WARP / D3D12 GL
{"D3D12", GPUVendor::Microsoft},
{"Microsoft", GPUVendor::Microsoft},
{"WARP", GPUVendor::Microsoft},
};
for (const auto& entry : GpuVendor) {
if (gpu_vendor_string == entry.name) {
return entry.vendor;
}
}
// legacy (shouldn't be needed anymore, but just in case)
std::string gpu = gpu_vendor_string;
std::transform(gpu.begin(), gpu.end(), gpu.begin(), [](unsigned char c){ return (char)std::tolower(c); });
if (gpu.find("geforce") != std::string::npos) {
return GPUVendor::Nvidia;
}
if (gpu.find("radeon") != std::string::npos || gpu.find("ati") != std::string::npos) {
return GPUVendor::AMD;
}
return GPUVendor::Unknown;
}
static OS DetectOS() {
#if defined(_WIN32)
return OS::Windows;
#elif defined(__FIREOS__)
return OS::FireOS;
#elif defined(__ANDROID__)
return OS::Android;
#elif defined(__OHOS__)
return OS::HarmonyOS;
#elif defined(__HAIKU__)
return OS::HaikuOS;
#elif defined(__DragonFly__)
return OS::DragonFlyBSD;
#elif defined(__NetBSD__)
return OS::NetBSD;
#elif defined(__OpenBSD__)
return OS::OpenBSD;
#elif defined(_AIX)
return OS::AIX;
#elif defined(__managarm__)
return OS::Managarm;
#elif defined(__redox__)
return OS::RedoxOS;
#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
return OS::IOS;
#elif defined(__APPLE__)
return OS::MacOS;
#elif defined(__FreeBSD__)
return OS::FreeBSD;
#elif defined(__sun) && defined(__SVR4)
return OS::Solaris;
#elif defined(__linux__)
return OS::Linux;
#else
return OS::Unknown;
#endif
}
EnvironmentInfo DetectEnvironment(const VideoCore::RendererBase& renderer) {
EnvironmentInfo env{};
env.os = DetectOS();
env.vendor_string = renderer.GetDeviceVendor();
env.vendor = GetGPU(env.vendor_string);
return env;
}
void LoadOverrides(std::uint64_t program_id, const VideoCore::RendererBase& renderer) {
const auto env = DetectEnvironment(renderer);
switch (static_cast<TitleID>(program_id)) {
case TitleID::NinjaGaidenRagebound:
Settings::values.use_squashed_iterated_blend = true;
break;
default:
break;
}
LOG_INFO(Core, "Applied game settings for title ID {:016X} on OS {}, GPU vendor {} ({})",
program_id,
static_cast<int>(env.os),
static_cast<int>(env.vendor),
env.vendor_string);
}
} // namespace Core::GameSettings

View File

@@ -1,60 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
#include <cstdint>
#include <string>
namespace VideoCore { class RendererBase; }
namespace Core::GameSettings {
enum class OS {
Windows,
Linux,
MacOS,
IOS,
Android,
FireOS,
HarmonyOS,
FreeBSD,
DragonFlyBSD,
NetBSD,
OpenBSD,
HaikuOS,
AIX,
Managarm,
RedoxOS,
Solaris,
Unknown,
};
enum class GPUVendor {
Nvidia,
AMD,
Intel,
Apple,
Qualcomm,
ARM,
Imagination,
Microsoft,
Unknown,
};
enum class TitleID : std::uint64_t {
NinjaGaidenRagebound = 0x0100781020710000ULL
};
struct EnvironmentInfo {
OS os{OS::Unknown};
GPUVendor vendor{GPUVendor::Unknown};
std::string vendor_string; // raw string from driver
};
EnvironmentInfo DetectEnvironment(const VideoCore::RendererBase& renderer);
void LoadOverrides(std::uint64_t program_id, const VideoCore::RendererBase& renderer);
} // namespace Core::GameSettings

View File

@@ -12,7 +12,7 @@
#include "common/common_types.h"
#include "common/expected.h"
// All the constants in this file come from <http://switchbrew.org/index.php?title=Error_codes>
// All the constants in this file come from http://switchbrew.org/index.php?title=Error_codes
/**
* Identifies the module which caused the error. Error codes can be propagated through a call
@@ -87,7 +87,6 @@ enum class ErrorModule : u32 {
AM = 128,
PlayReport = 129,
AHID = 130,
APPLET = 131,
Qlaunch = 132,
PCV = 133,
USBPD = 134,
@@ -114,8 +113,8 @@ enum class ErrorModule : u32 {
NPNSHTTPSTREAM = 155,
IDLE = 156,
ARP = 157,
UPDATER = 158,
SWKBD = 159,
SWKBD = 158,
BOOT = 159,
NetDiag = 160,
NFCMifare = 161,
UserlandAssert = 162,
@@ -126,8 +125,7 @@ enum class ErrorModule : u32 {
BGTC = 167,
UserlandCrash = 168,
SASBUS = 169,
PL = 170,
CDMSC = 171,
PI = 170,
AudioCtrl = 172,
LBL = 173,
JIT = 175,
@@ -139,30 +137,23 @@ enum class ErrorModule : u32 {
Dauth = 181,
STDFU = 182,
DBG = 183,
CDACM = 184,
TCAP = 185,
DHCPS = 186,
SPI = 187,
AVM = 188,
PWM = 189,
DNSServer = 190,
RTC = 191,
Regulator = 192,
LED = 193,
HTCTool = 194,
SIO = 195,
PCM = 196,
CLKRST = 197,
POWCTL = 198,
HIDDriver = 199,
DMA = 200,
AudioOld = 201,
HID = 202,
LDN = 203,
CS = 204,
Irsensor = 205,
Capture = 206,
MM = 207,
Manu = 208,
ATK = 209,
WEB = 210,
@@ -175,24 +166,19 @@ enum class ErrorModule : u32 {
MigrationLdcServ = 217,
HIDBUS = 218,
ENS = 219,
ND = 220,
NDD = 221,
ToyCon = 222,
WebSocket = 223,
SocketIO = 224,
DCDMTP = 227,
PGL = 228,
Notification = 229,
INS = 230,
LP2P = 231,
RCD = 232,
ICM40607 = 233,
LCM40607 = 233,
PRC = 235,
BridgeCtrl = 237,
ErrContext = 238,
TMAHTC = 237,
ECTX = 238,
MNPP = 239,
HSHL = 240,
RINGCON = 241,
CAPMTP = 242,
DP2HDMI = 244,
Cradle = 245,
@@ -200,8 +186,6 @@ enum class ErrorModule : u32 {
Icm42607p = 248,
NDRM = 250,
Fst2 = 251,
TS = 253,
SPLAY = 260,
Nex = 306,
NPLN = 321,
TSPM = 499,

View File

@@ -36,6 +36,10 @@ void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* pro
m_buffer_sharing_enabled = false;
m_blending_enabled = mode == LibraryAppletMode::PartialForeground ||
mode == LibraryAppletMode::PartialForegroundIndirectDisplay;
if (m_applet_id != AppletId::Application) {
(void)this->IsSystemBufferSharingEnabled();
}
}
void DisplayLayerManager::Finalize() {
@@ -76,10 +80,11 @@ Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) {
if (m_applet_id != AppletId::Application) {
(void)m_manager_display_service->SetLayerBlending(m_blending_enabled, *out_layer_id);
if (m_applet_id == AppletId::OverlayDisplay) {
(void)m_manager_display_service->SetLayerZIndex(-1, *out_layer_id);
(void)m_display_service->GetContainer()->SetLayerIsOverlay(*out_layer_id, true);
static constexpr s32 kOverlayBackgroundZ = -1;
(void)m_manager_display_service->SetLayerZIndex(kOverlayBackgroundZ, *out_layer_id);
} else {
(void)m_manager_display_service->SetLayerZIndex(1, *out_layer_id);
static constexpr s32 kOverlayZ = 3;
(void)m_manager_display_service->SetLayerZIndex(kOverlayZ, *out_layer_id);
}
}
@@ -126,7 +131,6 @@ Result DisplayLayerManager::IsSystemBufferSharingEnabled() {
s32 initial_z = 1;
if (m_applet_id == AppletId::OverlayDisplay) {
initial_z = -1;
(void)m_display_service->GetContainer()->SetLayerIsOverlay(m_system_shared_layer_id, true);
}
m_manager_display_service->SetLayerZIndex(initial_z, m_system_shared_layer_id);
R_SUCCEED();

View File

@@ -88,13 +88,13 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_
{181, nullptr, "UpgradeLaunchRequiredVersion"},
{190, nullptr, "SendServerMaintenanceOverlayNotification"},
{200, nullptr, "GetLastApplicationExitReason"},
{210, D<&IApplicationFunctions::GetLaunchRequiredVersionUpgrade>, "GetLaunchRequiredVersionUpgrade"}, //20.0.0+
{211, nullptr, "GetLaunchRequiredVersionUpgradeStatus"}, //20.0.0+
{220, nullptr, "Unknown220"}, //20.0.0+
{300, nullptr, "CreateMovieWriter"}, //20.0.0+
{310, nullptr, "Unknown310"}, //20.0.0+
{320, nullptr, "Unknown320"}, //20.0.0+
{330, nullptr, "Unknown330"}, //20.0.0+
{210, D<&IApplicationFunctions::GetLaunchRequiredVersionUpgrade>, "GetLaunchRequiredVersionUpgrade"}, // [20.0.0+]
{211, nullptr, "GetLaunchRequiredVersionUpgradeStatus"}, // [20.0.0+]
{220, nullptr, "Unknown220"}, // [20.0.0+]
{300, nullptr, "Unknown300"}, // [20.0.0+]
{310, nullptr, "Unknown310"}, // [20.0.0+]
{320, nullptr, "Unknown320"}, // [20.0.0+]
{330, nullptr, "Unknown330"}, // [20.0.0+]
{500, nullptr, "StartContinuousRecordingFlushForDebug"},
{1000, nullptr, "CreateMovieMaker"},
{1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"},

View File

@@ -18,7 +18,7 @@ IAudioController::IAudioController(Core::System& system_)
{2, D<&IAudioController::GetLibraryAppletExpectedMasterVolume>, "GetLibraryAppletExpectedMasterVolume"},
{3, D<&IAudioController::ChangeMainAppletMasterVolume>, "ChangeMainAppletMasterVolume"},
{4, D<&IAudioController::SetTransparentVolumeRate>, "SetTransparentVolumeRate"},
{5, nullptr, "Unknown5"}, //20.0.0+
{5, nullptr, "Unknown5"},
};
// clang-format on

View File

@@ -24,7 +24,7 @@ namespace Service::AM {
{20, D<&IOverlayFunctions::SetHandlingHomeButtonShortPressedEnabled>, "SetHandlingHomeButtonShortPressedEnabled"},
{21, nullptr, "SetHandlingTouchScreenInputEnabled"},
{30, nullptr, "SetHealthWarningShowingState"},
{31, D<&IOverlayFunctions::IsHealthWarningRequired>, "IsHealthWarningRequired"},
{31, nullptr, "IsHealthWarningRequired"},
{40, nullptr, "GetApplicationNintendoLogo"},
{41, nullptr, "GetApplicationStartupMovie"},
{50, nullptr, "SetGpuTimeSliceBoostForApplication"},
@@ -69,33 +69,12 @@ namespace Service::AM {
Result IOverlayFunctions::GetApplicationIdForLogo(Out<u64> out_application_id) {
LOG_DEBUG(Service_AM, "called");
std::shared_ptr<Applet> target_applet;
auto* window_system = system.GetAppletManager().GetWindowSystem();
if (window_system) {
target_applet = window_system->GetMainApplet();
if (target_applet) {
std::scoped_lock lk{target_applet->lock};
LOG_DEBUG(Service_AM, "applet_id={}, program_id={:016X}, type={}",
static_cast<u32>(target_applet->applet_id), target_applet->program_id,
static_cast<u32>(target_applet->type));
u64 id = target_applet->screen_shot_identity.application_id;
if (id == 0) {
id = target_applet->program_id;
}
LOG_DEBUG(Service_AM, "application_id={:016X}", id);
*out_application_id = id;
R_SUCCEED();
}
}
// Prefer explicit application_id if available, else fall back to program_id
std::scoped_lock lk{m_applet->lock};
u64 id = m_applet->screen_shot_identity.application_id;
if (id == 0) {
id = m_applet->program_id;
}
LOG_DEBUG(Service_AM, "application_id={:016X} (fallback)", id);
*out_application_id = id;
R_SUCCEED();
}
@@ -107,13 +86,6 @@ namespace Service::AM {
R_SUCCEED();
}
Result IOverlayFunctions::IsHealthWarningRequired(Out<bool> is_required) {
LOG_DEBUG(Service_AM, "called");
std::scoped_lock lk{m_applet->lock};
*is_required = false;
R_SUCCEED();
}
Result IOverlayFunctions::SetHandlingHomeButtonShortPressedEnabled(bool enabled) {
LOG_DEBUG(Service_AM, "called, enabled={}", enabled);
std::scoped_lock lk{m_applet->lock};

View File

@@ -18,7 +18,6 @@ namespace Service::AM {
Result EndToWatchShortHomeButtonMessage();
Result GetApplicationIdForLogo(Out<u64> out_application_id);
Result SetAutoSleepTimeAndDimmingTimeEnabled(bool enabled);
Result IsHealthWarningRequired(Out<bool> is_required);
Result SetHandlingHomeButtonShortPressedEnabled(bool enabled);
Result Unknown70();

View File

@@ -186,6 +186,8 @@ void WindowSystem::OnSystemButtonPress(SystemButtonType type) {
if (m_overlay_display) {
std::scoped_lock lk_overlay{m_overlay_display->lock};
m_overlay_display->overlay_in_foreground = !m_overlay_display->overlay_in_foreground;
// Tie window visibility to foreground state so hidden when not active
m_overlay_display->window_visible = m_overlay_display->overlay_in_foreground;
LOG_INFO(Service_AM, "Overlay long-press toggle: overlay_in_foreground={} window_visible={}", m_overlay_display->overlay_in_foreground, m_overlay_display->window_visible);
}
SendButtonAppletMessageLocked(AppletMessage::DetectLongPressingHomeButton);
@@ -391,7 +393,7 @@ void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, b
s32 z_index = 0;
const bool now_foreground = inherited_foreground;
if (applet->applet_id == AppletId::OverlayDisplay) {
z_index = applet->overlay_in_foreground ? 100000 : -1;
z_index = applet->overlay_in_foreground ? 100000 : -100000;
} else if (now_foreground && !is_obscured) {
z_index = 2;
} else if (now_foreground) {

View File

@@ -30,7 +30,7 @@ IAudioController::IAudioController(Core::System& system_)
{3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
{4, D<&IAudioController::IsTargetMute>, "IsTargetMute"},
{5, D<&IAudioController::SetTargetMute>, "SetTargetMute"},
{6, nullptr, "IsTargetConnected"}, //20.0.0+
{6, nullptr, "IsTargetConnected"},
{7, nullptr, "SetDefaultTarget"},
{8, nullptr, "GetDefaultTarget"},
{9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
@@ -67,8 +67,7 @@ IAudioController::IAudioController(Core::System& system_)
{40, nullptr, "GetSystemInformationForDebug"},
{41, nullptr, "SetVolumeButtonLongPressTime"},
{42, nullptr, "SetNativeVolumeForDebug"},
{43, nullptr, "Unknown43"}, //21.0.0+
{5000, D<&IAudioController::Unknown5000>, "Unknown5000"}, //19.0.0+
{5000, D<&IAudioController::Unknown5000>, "Unknown5000"},
{10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
{10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
{10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
@@ -77,13 +76,13 @@ IAudioController::IAudioController(Core::System& system_)
{10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
{10103, nullptr, "GetAudioOutputTargetForPlayReport"},
{10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, //14.0.0-19.0.1
{10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"}, //14.0.0-19.0.1
{10200, nullptr, "Unknown10200"}, //20.0.0+
{50000, nullptr, "SetAnalogInputBoostGainForPrototyping"}, //15.0.0-18.1.0
{50001, nullptr, "OverrideDefaultTargetForDebug"}, //19.0.0-19.0.1
{50003, nullptr, "SetForceOverrideExternalDeviceNameForDebug"}, //19.0.0+
{50004, nullptr, "ClearForceOverrideExternalDeviceNameForDebug"} //19.0.0+
{10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
{10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
{10200, nullptr, "Unknown10200"}, // [20.0.0+]
{50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
{50001, nullptr, "OverrideDefaultTargetForDebug"},
{50003, nullptr, "SetForceOverrideExternalDeviceNameForDebug"},
{50004, nullptr, "ClearForceOverrideExternalDeviceNameForDebug"}
};
// clang-format on

View File

@@ -32,13 +32,13 @@ IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u
{12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"},
{13, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioOutputDeviceName"},
{14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"},
{15, nullptr, "AcquireAudioInputDeviceNotification"}, //17.0.0+
{16, nullptr, "ReleaseAudioInputDeviceNotification"}, //17.0.0+
{17, nullptr, "AcquireAudioOutputDeviceNotification"}, //17.0.0+
{18, nullptr, "ReleaseAudioOutputDeviceNotification"}, //17.0.0+
{19, nullptr, "SetAudioDeviceOutputVolumeAutoTuneEnabled"}, //18.0.0+
{20, nullptr, "IsAudioDeviceOutputVolumeAutoTuneEnabled"}, //18.0.0+
{21, nullptr, "IsActiveOutputDeviceEstimatedLowLatency"} //21.0.0+
{15, nullptr, "AcquireAudioInputDeviceNotification"}, // 17.0.0+
{16, nullptr, "ReleaseAudioInputDeviceNotification"}, // 17.0.0+
{17, nullptr, "AcquireAudioOutputDeviceNotification"}, // 17.0.0+
{18, nullptr, "ReleaseAudioOutputDeviceNotification"}, // 17.0.0+
{19, nullptr, "SetAudioDeviceOutputVolumeAutoTuneEnabled"}, // 18.0.0+
{20, nullptr, "IsAudioDeviceOutputVolumeAutoTuneEnabled"}, // 18.0.0+
{21, nullptr, "IsActiveOutputDeviceEstimatedLowLatency"} // 21.0.0+
};
RegisterHandlers(functions);

View File

@@ -43,21 +43,21 @@ IBcatService::IBcatService(Core::System& system_, BcatBackend& backend_)
{20401, nullptr, "UnregisterSystemApplicationDeliveryTask"},
{20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"},
{30100, D<&IBcatService::SetPassphrase>, "SetPassphrase"},
{30101, nullptr, "Unknown30101"}, //2.0.0-2.3.0
{30102, nullptr, "Unknown30102"}, //2.0.0-2.3.0
{30101, nullptr, "Unknown30101"},
{30102, nullptr, "Unknown30102"},
{30200, nullptr, "RegisterBackgroundDeliveryTask"},
{30201, nullptr, "UnregisterBackgroundDeliveryTask"},
{30202, nullptr, "BlockDeliveryTask"},
{30203, nullptr, "UnblockDeliveryTask"},
{30210, nullptr, "SetDeliveryTaskTimer"},
{30300, D<&IBcatService::RegisterSystemApplicationDeliveryTasks>, "RegisterSystemApplicationDeliveryTasks"},
{90100, nullptr, "GetDeliveryTaskList"},
{90101, nullptr, "GetDeliveryTaskListForSystem"}, //11.0.0+
{90100, nullptr, "EnumerateBackgroundDeliveryTask"},
{90101, nullptr, "Unknown90101"},
{90200, nullptr, "GetDeliveryList"},
{90201, D<&IBcatService::ClearDeliveryCacheStorage>, "ClearDeliveryCacheStorage"},
{90202, nullptr, "ClearDeliveryTaskSubscriptionStatus"},
{90300, nullptr, "GetPushNotificationLog"},
{90301, nullptr, "GetDeliveryCacheStorageUsage"}, //11.0.0+
{90301, nullptr, "Unknown90301"},
};
// clang-format on
RegisterHandlers(functions);

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -15,19 +12,19 @@ INewsService::INewsService(Core::System& system_) : ServiceFramework{system_, "I
{10100, D<&INewsService::PostLocalNews>, "PostLocalNews"},
{20100, nullptr, "SetPassphrase"},
{30100, D<&INewsService::GetSubscriptionStatus>, "GetSubscriptionStatus"},
{30101, nullptr, "GetTopicList"}, //3.0.0+
{30110, nullptr, "Unknown30110"}, //6.0.0+
{30101, nullptr, "GetTopicList"},
{30110, nullptr, "Unknown30110"},
{30200, D<&INewsService::IsSystemUpdateRequired>, "IsSystemUpdateRequired"},
{30201, nullptr, "Unknown30201"}, //8.0.0+
{30210, nullptr, "Unknown30210"}, //10.0.0+
{30201, nullptr, "Unknown30201"},
{30210, nullptr, "Unknown30210"},
{30300, nullptr, "RequestImmediateReception"},
{30400, nullptr, "DecodeArchiveFile"}, //3.0.0-18.1.0
{30500, nullptr, "Unknown30500"}, //8.0.0+
{30900, nullptr, "Unknown30900"}, //1.0.0
{30901, nullptr, "Unknown30901"}, //1.0.0
{30902, nullptr, "Unknown30902"}, //1.0.0
{30400, nullptr, "DecodeArchiveFile"},
{30500, nullptr, "Unknown30500"},
{30900, nullptr, "Unknown30900"},
{30901, nullptr, "Unknown30901"},
{30902, nullptr, "Unknown30902"},
{40100, nullptr, "SetSubscriptionStatus"},
{40101, D<&INewsService::RequestAutoSubscription>, "RequestAutoSubscription"}, //3.0.0+
{40101, D<&INewsService::RequestAutoSubscription>, "RequestAutoSubscription"},
{40200, nullptr, "ClearStorage"},
{40201, nullptr, "ClearSubscriptionStatusAll"},
{90100, nullptr, "GetNewsDatabaseDump"},

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -80,33 +77,31 @@ public:
{57, nullptr, "RegisterAppletResourceUserId"},
{58, nullptr, "UnregisterAppletResourceUserId"},
{59, nullptr, "SetAppletResourceUserId"},
{60, nullptr, "AcquireBleConnectionParameterUpdateEvent"}, //8.0.0+
{61, nullptr, "SetCeLength"}, //8.0.0+
{62, nullptr, "EnsureSlotExpansion"}, //9.0.0+
{63, nullptr, "IsSlotExpansionEnsured"}, //9.0.0+
{64, nullptr, "CancelConnectionTrigger"}, //10.0.0+
{65, nullptr, "GetConnectionCapacity"}, //13.0.0+
{66, nullptr, "GetWlanMode"}, //13.0.0+
{67, nullptr, "IsSlotSavingEnabled"}, //13.0.0+
{68, nullptr, "IsSlotSavingForPairingEnabled"}, //13.0.0+
{69, nullptr, "AcquireAudioDeviceConnectionEvent"}, //13.0.0+
{70, nullptr, "GetConnectedAudioDevices"}, //13.0.0+
{71, nullptr, "SetAudioSourceVolume"}, //13.0.0+
{72, nullptr, "GetAudioSourceVolume"}, //13.0.0+
{73, nullptr, "RequestAudioDeviceConnectionRejection"}, //13.0.0+
{74, nullptr, "CancelAudioDeviceConnectionRejection"}, //13.0.0+
{75, nullptr, "GetPairedAudioDevices"}, //13.0.0+
{76, nullptr, "SetWlanModeWithOption"}, //13.1.0+
{100, nullptr, "AcquireConnectionDisallowedEvent"}, //13.0.0+
{101, nullptr, "GetUsecaseViolationFactor"}, //13.0.0+
{110, nullptr, "GetShortenedDeviceInfo"}, //13.0.0+
{111, nullptr, "AcquirePairingCountUpdateEvent"},//13.0.0+
{112, nullptr, "Unknown112"}, //14.0.0-14.1.2
{113, nullptr, "Unknown113"}, //14.0.0-14.1.2
{114, nullptr, "IsFirstAudioControlConnection"}, //14.0.0+
{115, nullptr, "GetShortenedDeviceCondition"}, //14.0.0+
{116, nullptr, "SetAudioSinkVolume"}, //15.0.0+
{117, nullptr, "GetAudioSinkVolume"}, //15.0.0+
{60, nullptr, "Unknown60"},
{61, nullptr, "Unknown61"},
{62, nullptr, "Unknown62"},
{63, nullptr, "Unknown63"},
{64, nullptr, "Unknown64"},
{65, nullptr, "Unknown65"},
{66, nullptr, "Unknown66"},
{67, nullptr, "Unknown67"},
{68, nullptr, "Unknown68"},
{69, nullptr, "Unknown69"},
{70, nullptr, "Unknown70"},
{71, nullptr, "Unknown71"},
{72, nullptr, "Unknown72"},
{73, nullptr, "Unknown73"},
{74, nullptr, "Unknown74"},
{75, nullptr, "Unknown75"},
{76, nullptr, "Unknown76"},
{100, nullptr, "Unknown100"},
{101, nullptr, "Unknown101"},
{110, nullptr, "Unknown110"},
{111, nullptr, "Unknown111"},
{112, nullptr, "Unknown112"},
{113, nullptr, "Unknown113"},
{114, nullptr, "Unknown114"},
{115, nullptr, "Unknown115"},
};
// clang-format on

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -20,15 +17,11 @@ IBtmDebug::IBtmDebug(Core::System& system_) : ServiceFramework{system_, "btm:dbg
{6, nullptr, "SetTsiMode"},
{7, nullptr, "GeneralTest"},
{8, nullptr, "HidConnect"},
{9, nullptr, "GeneralGet"}, //5.0.0+
{10, nullptr, "GetGattClientDisconnectionReason"}, //5.0.0+
{11, nullptr, "GetBleConnectionParameter"}, //5.1.0+
{12, nullptr, "GetBleConnectionParameterRequest"}, //5.1.0+
{13, nullptr, "GetDiscoveredDevice"}, //12.0.0+
{14, nullptr, "SleepAwakeLoopTest"}, //15.0.0+
{15, nullptr, "SleepTest"}, //15.0.0+
{16, nullptr, "MinimumAwakeTest"}, //15.0.0+
{17, nullptr, "ForceEnableBtm"}, //15.0.0+
{9, nullptr, "GeneralGet"},
{10, nullptr, "GetGattClientDisconnectionReason"},
{11, nullptr, "GetBleConnectionParameter"},
{12, nullptr, "GetBleConnectionParameterRequest"},
{13, nullptr, "Unknown13"},
};
// clang-format on

View File

@@ -60,16 +60,6 @@ public:
{38, nullptr, "OwnTicket3"},
{39, nullptr, "DeleteAllInactivePersonalizedTicket"},
{40, nullptr, "DeletePrepurchaseRecordByNintendoAccountId"},
{101, nullptr, "Unknown101"}, //18.0.0+
{102, nullptr, "Unknown102"}, //18.0.0+
{103, nullptr, "Unknown103"}, //18.0.0+
{104, nullptr, "Unknown104"}, //18.0.0+
{105, nullptr, "Unknown105"}, //20.0.0+
{201, nullptr, "Unknown201"}, //18.0.0+
{202, nullptr, "Unknown202"}, //18.0.0+
{203, nullptr, "Unknown203"}, //18.0.0+
{204, nullptr, "Unknown204"}, //18.0.0+
{205, nullptr, "Unknown205"}, //18.0.0+
{501, nullptr, "Unknown501"},
{502, nullptr, "Unknown502"},
{503, nullptr, "GetTitleKey"},

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -70,7 +67,7 @@ public:
{20701, &IFriendService::GetPlayHistoryStatistics, "GetPlayHistoryStatistics"},
{20800, &IFriendService::LoadUserSetting, "LoadUserSetting"},
{20801, nullptr, "SyncUserSetting"},
{20900, &IFriendService::RequestListSummaryOverlayNotification, "RequestListSummaryOverlayNotification"},
{20900, nullptr, "RequestListSummaryOverlayNotification"},
{21000, nullptr, "GetExternalApplicationCatalog"},
{22000, nullptr, "GetReceivedFriendInvitationList"},
{22001, nullptr, "GetReceivedFriendInvitationDetailedInfo"},
@@ -320,13 +317,6 @@ private:
rb.Push(ResultSuccess);
}
void RequestListSummaryOverlayNotification(HLERequestContext& ctx) {
LOG_INFO(Service_Friend, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetReceivedFriendInvitationCountCache(HLERequestContext& ctx) {
LOG_DEBUG(Service_Friend, "(STUBBED) called, check in out");

View File

@@ -125,10 +125,13 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
{250, nullptr, "IsVirtual"},
{251, nullptr, "GetAnalogStickModuleParam"},
{253, nullptr, "ClearStorageForShipment"}, //19.0.0+
{261, nullptr, "UpdateDesignInfo12"}, //21.0.0+
{262, nullptr, "GetUniquePadButtonCount"}, //21.0.0+
{267, nullptr, "SetAnalogStickCalibration"}, //21.0.0+
{268, nullptr, "ResetAnalogStickCalibration"}, //21.0.0+
{254, nullptr, "Unknown254"},
{255, nullptr, "Unknown255"},
{256, nullptr, "Unknown256"},
{261, nullptr, "UpdateDesignInfo12"},
{262, nullptr, "GetUniquePadButtonCount"},
{267, nullptr, "Unknown267"},
{268, nullptr, "Unknown268"},
{301, nullptr, "GetAbstractedPadHandles"},
{302, nullptr, "GetAbstractedPadState"},
{303, nullptr, "GetAbstractedPadsState"},
@@ -145,8 +148,6 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
{331, nullptr, "DetachHdlsVirtualDevice"},
{332, nullptr, "SetHdlsState"},
{350, nullptr, "AddRegisteredDevice"},
{351, nullptr, "GetRegisteredDevicesCountDebug"}, //17.0.0-18.1.0
{352, nullptr, "DeleteRegisteredDevicesDebug"}, //17.0.0-18.1.0
{400, nullptr, "DisableExternalMcuOnNxDevice"},
{401, nullptr, "DisableRailDeviceFiltering"},
{402, nullptr, "EnableWiredPairing"},
@@ -158,30 +159,14 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
{551, nullptr, "GetAnalogStickModelData"},
{552, nullptr, "ResetAnalogStickModelData"},
{600, nullptr, "ConvertPadState"},
{601, nullptr, "IsButtonConfigSupported"}, //18.0.0+
{602, nullptr, "IsButtonConfigEmbeddedSupported"}, //18.0.0+
{603, nullptr, "DeleteButtonConfig"}, //18.0.0+
{604, nullptr, "DeleteButtonConfigEmbedded"}, //18.0.0+
{605, nullptr, "SetButtonConfigEnabled"}, //18.0.0+
{606, nullptr, "SetButtonConfigEmbeddedEnabled"}, //18.0.0+
{607, nullptr, "IsButtonConfigEnabled"}, //18.0.0+
{608, nullptr, "IsButtonConfigEmbeddedEnabled"}, //18.0.0+
{609, nullptr, "SetButtonConfigEmbedded"}, //18.0.0+
{610, nullptr, "SetButtonConfigFull"}, //18.0.0+
{611, nullptr, "SetButtonConfigLeft"}, //18.0.0+
{612, nullptr, "SetButtonConfigRight"}, //18.0.0+
{613, nullptr, "GetButtonConfigEmbedded"}, //18.0.0+
{614, nullptr, "GetButtonConfigFull"}, //18.0.0+
{615, nullptr, "GetButtonConfigLeft"}, //18.0.0+
{616, nullptr, "GetButtonConfigRight"}, //18.0.0+
{650, nullptr, "AddButtonPlayData"},
{651, nullptr, "StartButtonPlayData"},
{652, nullptr, "StopButtonPlayData"},
{700, nullptr, "GetRailAttachEventCount"}, //21.0.0+
{700, nullptr, "Unknown700"},
{2000, nullptr, "DeactivateDigitizer"},
{2001, nullptr, "SetDigitizerAutoPilotState"},
{2002, nullptr, "UnsetDigitizerAutoPilotState"},
{3000, nullptr, "ReloadFirmwareDebugSettings"},
{2002, nullptr, "ReloadFirmwareDebugSettings"},
};
// clang-format on

View File

@@ -70,9 +70,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{328, nullptr, "AttachAbstractedPadToNpad"},
{329, nullptr, "DetachAbstractedPadAll"},
{330, nullptr, "CheckAbstractedPadConnection"},
{332, nullptr, "ConvertAppletDetailedUiTypeFromPlayReportType"}, //19.0.0+
{333, nullptr, "SetNpadUserSpgApplet"}, //20.0.0+
{334, nullptr, "AcquireUniquePadButtonStateChangedEventHandle"}, //20.0.0+
{500, nullptr, "SetAppletResourceUserId"},
{501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"},
{502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"},
{503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"},
@@ -101,7 +99,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{547, nullptr, "GetAllowedBluetoothLinksCount"},
{548, &IHidSystemServer::GetRegisteredDevices, "GetRegisteredDevices"},
{549, nullptr, "GetConnectableRegisteredDevices"},
{551, nullptr, "GetRegisteredDevicesForControllerSupport"}, //20.0.0+
{551, nullptr, "GetRegisteredDevicesForControllerSupport"},
{700, nullptr, "ActivateUniquePad"},
{702, &IHidSystemServer::AcquireUniquePadConnectionEventHandle, "AcquireUniquePadConnectionEventHandle"},
{703, &IHidSystemServer::GetUniquePadIds, "GetUniquePadIds"},
@@ -121,7 +119,6 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{810, nullptr, "GetUniquePadControllerNumber"},
{811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
{812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
{813, nullptr, "GetDeviceType"},
{821, nullptr, "StartAnalogStickManualCalibration"},
{822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
{823, nullptr, "CancelAnalogStickManualCalibration"},
@@ -152,7 +149,6 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{1009, nullptr, "AcquireAudioControlEventHandle"},
{1010, nullptr, "GetAudioControlStates"},
{1011, nullptr, "DeactivateAudioControl"},
{1012, nullptr, "GetFirmwareVersionStringForUserSupportPage"},
{1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
{1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
{1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
@@ -173,8 +169,6 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{1155, &IHidSystemServer::SetForceHandheldStyleVibration, "SetForceHandheldStyleVibration"},
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
{1157, nullptr, "CancelConnectionTrigger"},
{1158, nullptr, "SetConnectionLimitForSplay"}, //20.1.0+
{1159, nullptr, "ClearConnectionLimitForSplay"}, //20.1.0+
{1200, nullptr, "IsButtonConfigSupported"},
{1201, nullptr, "IsButtonConfigEmbeddedSupported"},
{1202, nullptr, "DeleteButtonConfig"},
@@ -233,17 +227,16 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{1289, nullptr, "SetButtonConfigStorageFull"},
{1290, nullptr, "DeleteButtonConfigStorageRight"},
{1291, nullptr, "DeleteButtonConfigStorageRight"},
{1308, nullptr, "SetButtonConfigVisible"}, //18.0.0+
{1309, nullptr, "IsButtonConfigVisible"}, //18.0.0+
{1320, nullptr, "WakeTouchScreenUp"}, //17.0.0+
{1321, nullptr, "PutTouchScreenToSleep"}, //17.0.0+
{1322, nullptr, "AcquireTouchScreenAsyncWakeCompletedEvent"}, //20.0.0+
{1323, nullptr, "StartTouchScreenAutoTuneForSystemSettings"}, //21.0.0+
{1324, nullptr, "AcquireTouchScreenAutoTuneCompletedEvent"}, //21.0.0+
{1325, nullptr, "IsTouchScreenAutoTuneRequiredForRepairProviderReplacement"}, //21.0.0+
{1326, nullptr, "SetTouchScreenOffset"}, //21.0.0+
{1420, nullptr, "GetAppletResourceProperty"}, //19.0.0+
{12010, nullptr, "SetButtonConfigLeft"} //11.0.0-17.0.1
{1308, nullptr, "SetButtonConfigVisible"}, // 18.0.0+
{1309, nullptr, "IsButtonConfigVisible"}, // 18.0.0+
{1320, nullptr, "WakeTouchScreenUp"}, // 17.0.0+
{1321, nullptr, "PutTouchScreenToSleep"}, // 17.0.0+
{1322, nullptr, "AcquireTouchScreenAsyncWakeCompletedEvent"}, // 20.0.0+
{1323, nullptr, "StartTouchScreenAutoTuneForSystemSettings"}, // 21.0.0+
{1324, nullptr, "AcquireTouchScreenAutoTuneCompletedEvent"}, // 21.0.0+
{1325, nullptr, "IsTouchScreenAutoTuneRequiredForRepairProviderReplacement"}, // 21.0.0+
{1326, nullptr, "Unknown1326"}, // 21.0.0+
{1420, nullptr, "GetAppletResourceProperty"}, // 19.0.0+
};
// clang-format on

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -17,42 +14,17 @@ public:
explicit MIG_USR(Core::System& system_) : ServiceFramework{system_, "mig:usr"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown0"}, //19.0.0+
{1, nullptr, "Unknown1"}, //20.0.0+
{2, nullptr, "Unknown2"}, //20.0.0+
{10, nullptr, "TryGetLastMigrationInfo"},
{11, nullptr, "Unknown11"}, //20.0.0+
{100, nullptr, "CreateUserMigrationServer"}, //7.0.0+
{101, nullptr, "ResumeUserMigrationServer"}, //7.0.0+
{200, nullptr, "CreateUserMigrationClient"}, //7.0.0+
{201, nullptr, "ResumeUserMigrationClient"}, //7.0.0+
{1001, nullptr, "GetSaveDataMigrationPolicyInfoAsync"}, //8.0.0-20.5.0
{1010, nullptr, "TryGetLastSaveDataMigrationInfo"}, //7.0.0+
{1100, nullptr, "CreateSaveDataMigrationServer"}, //7.0.0-19.0.1
{1101, nullptr, "ResumeSaveDataMigrationServer"}, //7.0.0+
{1110, nullptr, "Unknown1101"}, //17.0.0+
{1200, nullptr, "CreateSaveDataMigrationClient"}, //7.0.0+
{1201, nullptr, "ResumeSaveDataMigrationClient"}, //7.0.0+
{2001, nullptr, "Unknown2001"}, //20.0.0+
{2010, nullptr, "Unknown2010"}, //20.0.0+
{2100, nullptr, "Unknown2100"}, //20.0.0+
{2110, nullptr, "Unknown2110"}, //20.0.0+
{2200, nullptr, "Unknown2200"}, //20.0.0+
{2210, nullptr, "Unknown2210"}, //20.0.0+
{2220, nullptr, "Unknown2220"}, //20.0.0+
{2230, nullptr, "Unknown2230"}, //20.0.0+
{2231, nullptr, "Unknown2231"}, //20.0.0+
{2232, nullptr, "Unknown2232"}, //20.0.0+
{2233, nullptr, "Unknown2233"}, //20.0.0+
{2234, nullptr, "Unknown2234"}, //20.0.0+
{2250, nullptr, "Unknown2250"}, //20.0.0+
{2260, nullptr, "Unknown2260"}, //20.0.0+
{2270, nullptr, "Unknown2270"}, //20.0.0+
{2280, nullptr, "Unknown2280"}, //20.0.0+
{2300, nullptr, "Unknown2300"}, //20.0.0+
{2310, nullptr, "Unknown2310"}, //20.0.0+
{2400, nullptr, "Unknown2400"}, //20.0.0+
{2420, nullptr, "Unknown2420"}, //20.0.0+
{100, nullptr, "CreateServer"},
{101, nullptr, "ResumeServer"},
{200, nullptr, "CreateClient"},
{201, nullptr, "ResumeClient"},
{1001, nullptr, "Unknown1001"},
{1010, nullptr, "Unknown1010"},
{1100, nullptr, "Unknown1100"},
{1101, nullptr, "Unknown1101"},
{1200, nullptr, "Unknown1200"},
{1201, nullptr, "Unknown1201"}
};
// clang-format on

View File

@@ -167,146 +167,57 @@ public:
{81, nullptr, "ListLocalCommunicationSendSystemUpdateTask"},
{82, nullptr, "GetReceivedSystemDataPath"},
{83, nullptr, "CalculateApplyDeltaTaskOccupiedSize"},
{84, nullptr, "ReloadErrorSimulation"},
{84, nullptr, "Unknown84"},
{85, nullptr, "ListNetworkInstallTaskContentMetaFromInstallMeta"},
{86, nullptr, "ListNetworkInstallTaskOccupiedSize"},
{87, nullptr, "RequestQueryAvailableELicenses"},
{88, nullptr, "RequestAssignELicenses"},
{89, nullptr, "RequestExtendELicenses"},
{90, nullptr, "RequestSyncELicenses"},
{91, nullptr, "Unknown91"}, //6.0.0-14.1.2
{92, nullptr, "Unknown92"}, //21.0.0+
{93, nullptr, "RequestReportActiveELicenses"},
{94, nullptr, "RequestReportActiveELicensesPassively"},
{95, nullptr, "RequestRegisterDynamicRightsNotificationToken"},
{96, nullptr, "RequestAssignAllDeviceLinkedELicenses"},
{97, nullptr, "RequestRevokeAllELicenses"},
{98, nullptr, "RequestPrefetchForDynamicRights"},
{99, nullptr, "CreateNetworkInstallTask"},
{100, nullptr, "ListNetworkInstallTaskRightsIds"},
{101, nullptr, "RequestDownloadETickets"},
{102, nullptr, "RequestQueryDownloadableContents"},
{103, nullptr, "DeleteNetworkInstallTaskContentMeta"},
{104, nullptr, "RequestIssueEdgeTokenForDebug"},
{105, nullptr, "RequestQueryAvailableELicenses2"},
{106, nullptr, "RequestAssignELicenses2"},
{107, nullptr, "GetNetworkInstallTaskStateCounter"},
{108, nullptr, "InvalidateDynamicRightsNaIdTokenCacheForDebug"},
{109, nullptr, "ListNetworkInstallTaskPartialInstallContentMeta"},
{110, nullptr, "ListNetworkInstallTaskRightsIdsFromIndex"},
{111, nullptr, "AddNetworkInstallTaskContentMetaForUser"},
{112, nullptr, "RequestAssignELicensesAndDownloadETickets"},
{113, nullptr, "RequestQueryAvailableCommonELicenses"},
{114, nullptr, "SetNetworkInstallTaskExtendedAttribute"},
{115, nullptr, "GetNetworkInstallTaskExtendedAttribute"},
{116, nullptr, "GetAllocatorInfo"},
{117, nullptr, "RequestQueryDownloadableContentsByApplicationId"},
{118, nullptr, "MarkNoDownloadRightsErrorResolved"},
{119, nullptr, "GetApplyDeltaTaskAllAppliedContentMeta"},
{120, nullptr, "PrioritizeNetworkInstallTask"},
{121, nullptr, "RequestQueryAvailableCommonELicenses2"},
{122, nullptr, "RequestAssignCommonELicenses"},
{123, nullptr, "RequestAssignCommonELicenses2"},
{124, nullptr, "IsNetworkInstallTaskFrontOfQueue"},
{125, nullptr, "PrioritizeApplyDeltaTask"},
{126, nullptr, "RerouteDownloadingPatch"},
{127, nullptr, "UnmarkNoDownloadRightsErrorResolved"},
{128, nullptr, "RequestContentsSize"},
{129, nullptr, "RequestContentsAuthorizationToken"},
{130, nullptr, "RequestCdnVendorDiscovery"},
{131, nullptr, "RefreshDebugAvailability"},
{132, nullptr, "ClearResponseSimulationEntry"},
{133, nullptr, "RegisterResponseSimulationEntry"},
{134, nullptr, "GetProcessedCdnVendors"},
{135, nullptr, "RefreshRuntimeBehaviorsForDebug"},
{136, nullptr, "RequestOnlineSubscriptionFreeTrialAvailability"},
{137, nullptr, "GetNetworkInstallTaskContentMetaCount"},
{138, nullptr, "RequestRevokeELicenses"},
{139, nullptr, "EnableNetworkConnectionToUseApplicationCore"},
{140, nullptr, "DisableNetworkConnectionToUseApplicationCore"},
{141, nullptr, "IsNetworkConnectionEnabledToUseApplicationCore"},
{142, nullptr, "RequestCheckSafeSystemVersion"},
{143, nullptr, "RequestApplicationIcon"},
{144, nullptr, "RequestDownloadIdbeIconFile"},
{147, nullptr, "Unknown147"}, //18.0.0+
{148, nullptr, "Unknown148"}, //18.0.0+
{150, nullptr, "Unknown150"}, //19.0.0+
{151, nullptr, "Unknown151"}, //20.0.0+
{152, nullptr, "Unknown152"}, //20.0.0+
{153, nullptr, "Unknown153"}, //20.0.0+
{154, nullptr, "Unknown154"}, //20.0.0+
{155, nullptr, "Unknown155"}, //20.0.0+
{156, nullptr, "Unknown156"}, //20.0.0+
{157, nullptr, "Unknown157"}, //20.0.0+
{158, nullptr, "Unknown158"}, //20.0.0+
{159, nullptr, "Unknown159"}, //20.0.0+
{160, nullptr, "Unknown160"}, //20.0.0+
{161, nullptr, "Unknown161"}, //20.0.0+
{162, nullptr, "Unknown162"}, //20.0.0+
{163, nullptr, "Unknown163"}, //20.0.0+
{164, nullptr, "Unknown164"}, //20.0.0+
{165, nullptr, "Unknown165"}, //20.0.0+
{166, nullptr, "Unknown166"}, //20.0.0+
{167, nullptr, "Unknown167"}, //20.0.0+
{168, nullptr, "Unknown168"}, //20.0.0+
{169, nullptr, "Unknown169"}, //20.0.0+
{170, nullptr, "Unknown170"}, //20.0.0+
{171, nullptr, "Unknown171"}, //20.0.0+
{172, nullptr, "Unknown172"}, //20.0.0+
{173, nullptr, "Unknown173"}, //20.0.0+
{174, nullptr, "Unknown174"}, //20.0.0+
{175, nullptr, "Unknown175"}, //20.0.0+
{176, nullptr, "Unknown176"}, //20.0.0+
{177, nullptr, "Unknown177"}, //20.0.0+
{2000, nullptr, "Unknown2000"}, //20.0.0+
{2001, nullptr, "Unknown2001"}, //20.0.0+
{2002, nullptr, "Unknown2002"}, //20.0.0+
{2003, nullptr, "Unknown2003"}, //20.0.0+
{2004, nullptr, "Unknown2004"}, //20.0.0+
{2007, nullptr, "Unknown2007"}, //20.0.0+
{2011, nullptr, "Unknown2011"}, //20.0.0+
{2012, nullptr, "Unknown2012"}, //20.0.0+
{2013, nullptr, "Unknown2013"}, //20.0.0+
{2014, nullptr, "Unknown2014"}, //20.0.0+
{2015, nullptr, "Unknown2015"}, //20.0.0+
{2016, nullptr, "Unknown2016"}, //20.0.0+
{2017, nullptr, "Unknown2017"}, //20.0.0+
{2018, nullptr, "Unknown2018"}, //20.0.0+
{2019, nullptr, "Unknown2019"}, //20.0.0+
{2020, nullptr, "Unknown2020"}, //20.0.0+
{2021, nullptr, "Unknown2021"}, //20.0.0+
{2022, nullptr, "Unknown2022"}, //20.0.0+
{2023, nullptr, "Unknown2023"}, //20.0.0+
{2024, nullptr, "Unknown2024"}, //20.0.0+
{2025, nullptr, "Unknown2025"}, //20.0.0+
{2026, nullptr, "Unknown2026"}, //20.0.0+
{2027, nullptr, "Unknown2027"}, //20.0.0+
{2028, nullptr, "Unknown2028"}, //20.0.0+
{2029, nullptr, "Unknown2029"}, //20.0.0+
{2030, nullptr, "Unknown2030"}, //20.0.0+
{2031, nullptr, "Unknown2031"}, //20.0.0+
{2032, nullptr, "Unknown2032"}, //20.0.0+
{2033, nullptr, "Unknown2033"}, //20.0.0+
{2034, nullptr, "Unknown2034"}, //20.0.0+
{2035, nullptr, "Unknown2035"}, //20.0.0+
{2036, nullptr, "Unknown2036"}, //20.0.0+
{2037, nullptr, "Unknown2037"}, //20.0.0+
{2038, nullptr, "Unknown2038"}, //20.0.0+
{2039, nullptr, "Unknown2039"}, //20.0.0+
{2040, nullptr, "Unknown2040"}, //20.0.0+
{2041, nullptr, "Unknown2041"}, //20.0.0+
{2042, nullptr, "Unknown2042"}, //20.0.0+
{2043, nullptr, "Unknown2043"}, //20.0.0+
{2044, nullptr, "Unknown2044"}, //20.0.0+
{2045, nullptr, "Unknown2045"}, //20.0.0+
{2046, nullptr, "Unknown2046"}, //20.0.0+
{2047, nullptr, "Unknown2047"}, //20.0.0+
{2048, nullptr, "Unknown2048"}, //20.0.0+
{2049, nullptr, "Unknown2049"}, //20.0.0+
{2050, nullptr, "Unknown2050"}, //20.0.0+
{2051, nullptr, "Unknown2051"}, //20.0.0+
{3000, nullptr, "RequestLatestApplicationIcon"}, //17.0.0+
{3001, nullptr, "RequestDownloadIdbeLatestIconFile"}, //17.0.0+
{87, nullptr, "Unknown87"},
{88, nullptr, "Unknown88"},
{89, nullptr, "Unknown89"},
{90, nullptr, "Unknown90"},
{91, nullptr, "Unknown91"},
{92, nullptr, "Unknown92"},
{93, nullptr, "Unknown93"},
{94, nullptr, "Unknown94"},
{95, nullptr, "Unknown95"},
{96, nullptr, "Unknown96"},
{97, nullptr, "Unknown97"},
{98, nullptr, "Unknown98"},
{99, nullptr, "Unknown99"},
{100, nullptr, "Unknown100"},
{101, nullptr, "Unknown101"},
{102, nullptr, "Unknown102"},
{103, nullptr, "Unknown103"},
{104, nullptr, "Unknown104"},
{105, nullptr, "Unknown105"},
{106, nullptr, "Unknown106"},
{107, nullptr, "Unknown107"},
{108, nullptr, "Unknown108"},
{109, nullptr, "Unknown109"},
{110, nullptr, "Unknown110"},
{111, nullptr, "Unknown111"},
{112, nullptr, "Unknown112"},
{113, nullptr, "Unknown113"},
{114, nullptr, "Unknown114"},
{115, nullptr, "Unknown115"},
{116, nullptr, "Unknown116"},
{117, nullptr, "Unknown117"},
{118, nullptr, "Unknown118"},
{119, nullptr, "Unknown119"},
{120, nullptr, "Unknown120"},
{121, nullptr, "Unknown121"},
{122, nullptr, "Unknown122"},
{123, nullptr, "Unknown123"},
{124, nullptr, "Unknown124"},
{125, nullptr, "Unknown125"},
{126, nullptr, "Unknown126"},
{127, nullptr, "Unknown127"},
{128, nullptr, "Unknown128"},
{129, nullptr, "Unknown129"},
{130, nullptr, "Unknown130"},
{131, nullptr, "Unknown131"},
{132, nullptr, "Unknown132"},
{133, nullptr, "Unknown133"},
{134, nullptr, "Unknown134"},
};
// clang-format on

View File

@@ -10,8 +10,6 @@
#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/file_sys/content_archive.h"
#include "core/hle/service/ns/content_management_interface.h"
#include "core/hle/service/ns/read_only_application_control_data_interface.h"
#include "core/file_sys/patch_manager.h"
@@ -56,7 +54,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{37, nullptr, "ListRequiredVersion"},
{38, D<&IApplicationManagerInterface::CheckApplicationLaunchVersion>, "CheckApplicationLaunchVersion"},
{39, nullptr, "CheckApplicationLaunchRights"},
{40, D<&IApplicationManagerInterface::GetApplicationLogoData>, "GetApplicationLogoData"},
{40, nullptr, "GetApplicationLogoData"},
{41, nullptr, "CalculateApplicationDownloadRequiredSize"},
{42, nullptr, "CleanupSdCard"},
{43, D<&IApplicationManagerInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
@@ -134,26 +132,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{406, nullptr, "GetApplicationControlProperty"},
{407, nullptr, "ListApplicationTitle"},
{408, nullptr, "ListApplicationIcon"},
{411, nullptr, "Unknown411"}, //19.0.0+
{412, nullptr, "Unknown412"}, //19.0.0+
{413, nullptr, "Unknown413"}, //19.0.0+
{414, nullptr, "Unknown414"}, //19.0.0+
{415, nullptr, "Unknown415"}, //19.0.0+
{416, nullptr, "Unknown416"}, //19.0.0+
{417, nullptr, "InvalidateAllApplicationControlCacheOfTheStage"}, //19.0.0+
{418, nullptr, "InvalidateApplicationControlCacheOfTheStage"}, //19.0.0+
{419, D<&IApplicationManagerInterface::RequestDownloadApplicationControlDataInBackground>, "RequestDownloadApplicationControlDataInBackground"},
{420, nullptr, "CloneApplicationControlDataCacheForDebug"},
{421, nullptr, "Unknown421"}, //20.0.0+
{422, nullptr, "Unknown422"}, //20.0.0+
{423, nullptr, "Unknown423"}, //20.0.0+
{424, nullptr, "Unknown424"}, //20.0.0+
{425, nullptr, "Unknown425"}, //20.0.0+
{426, nullptr, "Unknown426"}, //20.0.0+
{427, nullptr, "Unknown427"}, //20.0.0+
{428, nullptr, "Unknown428"}, //21.0.0+
{429, nullptr, "Unknown429"}, //21.0.0+
{430, nullptr, "Unknown430"}, //21.0.0+
{502, nullptr, "RequestCheckGameCardRegistration"},
{503, nullptr, "RequestGameCardRegistrationGoldPoint"},
{504, nullptr, "RequestRegisterGameCard"},
@@ -165,13 +144,6 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{510, nullptr, "GetGameCardPlatformRegion"},
{511, D<&IApplicationManagerInterface::GetGameCardWakenReadyEvent>, "GetGameCardWakenReadyEvent"},
{512, D<&IApplicationManagerInterface::IsGameCardApplicationRunning>, "IsGameCardApplicationRunning"},
{513, nullptr, "Unknown513"}, //20.0.0+
{514, nullptr, "Unknown514"}, //20.0.0+
{515, nullptr, "Unknown515"}, //20.0.0+
{516, nullptr, "Unknown516"}, //21.0.0+
{517, nullptr, "Unknown517"}, //21.0.0+
{518, nullptr, "Unknown518"}, //21.0.0+
{519, nullptr, "Unknown519"}, //21.0.0+
{600, nullptr, "CountApplicationContentMeta"},
{601, nullptr, "ListApplicationContentMetaStatus"},
{602, nullptr, "ListAvailableAddOnContent"},
@@ -209,22 +181,6 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{914, nullptr, "HideApplicationRecord"},
{915, nullptr, "ShowApplicationRecord"},
{916, nullptr, "IsApplicationAutoDeleteDisabled"},
{916, nullptr, "Unknown916"}, //20.0.0+
{917, nullptr, "Unknown917"}, //20.0.0+
{918, nullptr, "Unknown918"}, //20.0.0+
{919, nullptr, "Unknown919"}, //20.0.0+
{920, nullptr, "Unknown920"}, //20.0.0+
{921, nullptr, "Unknown921"}, //20.0.0+
{922, nullptr, "Unknown922"}, //20.0.0+
{923, nullptr, "Unknown923"}, //20.0.0+
{928, nullptr, "Unknown928"}, //20.0.0+
{929, nullptr, "Unknown929"}, //20.0.0+
{930, nullptr, "Unknown930"}, //20.0.0+
{931, nullptr, "Unknown931"}, //20.0.0+
{933, nullptr, "Unknown933"}, //20.0.0+
{934, nullptr, "Unknown934"}, //20.0.0+
{935, nullptr, "Unknown935"}, //20.0.0+
{936, nullptr, "Unknown936"}, //20.0.0+
{1000, nullptr, "RequestVerifyApplicationDeprecated"},
{1001, nullptr, "CorruptApplicationForDebug"},
{1002, nullptr, "RequestVerifyAddOnContentsRights"},
@@ -253,11 +209,6 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{1504, nullptr, "InsertSdCard"},
{1505, nullptr, "RemoveSdCard"},
{1506, nullptr, "GetSdCardStartupStatus"},
{1508, nullptr, "Unknown1508"}, //20.0.0+
{1509, nullptr, "Unknown1509"}, //20.0.0+
{1510, nullptr, "Unknown1510"}, //20.0.0+
{1511, nullptr, "Unknown1511"}, //20.0.0+
{1512, nullptr, "Unknown1512"}, //20.0.0+
{1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
{1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
{1700, nullptr, "ListApplicationDownloadingContentMeta"},
@@ -294,11 +245,8 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{2016, nullptr, "ListNotCommittedContentMeta"},
{2017, nullptr, "CreateDownloadTask"},
{2018, nullptr, "GetApplicationDeliveryInfoHash"},
{2019, nullptr, "Unknown2019"}, //20.0.0+
{2050, D<&IApplicationManagerInterface::GetApplicationRightsOnClient>, "GetApplicationRightsOnClient"},
{2051, nullptr, "InvalidateRightsIdCache"},
{2052, nullptr, "Unknown2052"}, //20.0.0+
{2053, nullptr, "Unknown2053"}, //20.0.0+
{2100, D<&IApplicationManagerInterface::GetApplicationTerminateResult>, "GetApplicationTerminateResult"},
{2101, nullptr, "GetRawApplicationTerminateResult"},
{2150, nullptr, "CreateRightsEnvironment"},
@@ -315,7 +263,6 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
{2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
{2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
{2183, nullptr, "Unknown2183"}, //20.1.0+
{2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
{2199, nullptr, "GetRightsEnvironmentCountForDebug"},
{2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
@@ -332,16 +279,6 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{2357, nullptr, "EnableMultiCoreDownload"},
{2358, nullptr, "DisableMultiCoreDownload"},
{2359, nullptr, "IsMultiCoreDownloadEnabled"},
{2360, nullptr, "GetApplicationDownloadTaskCount"}, //19.0.0+
{2361, nullptr, "GetMaxApplicationDownloadTaskCount"}, //19.0.0+
{2362, nullptr, "Unknown2362"}, //20.0.0+
{2363, nullptr, "Unknown2363"}, //20.0.0+
{2364, nullptr, "Unknown2364"}, //20.0.0+
{2365, nullptr, "Unknown2365"}, //20.0.0+
{2366, nullptr, "Unknown2366"}, //20.0.0+
{2367, nullptr, "Unknown2367"}, //20.0.0+
{2368, nullptr, "Unknown2368"}, //20.0.0+
{2369, nullptr, "Unknown2369"}, //21.0.0+
{2400, nullptr, "GetPromotionInfo"},
{2401, nullptr, "CountPromotionInfo"},
{2402, nullptr, "ListPromotionInfo"},
@@ -360,9 +297,6 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{2520, nullptr, "IsQualificationTransitionSupportedByProcessId"},
{2521, nullptr, "GetRightsUserChangedEvent"},
{2522, nullptr, "IsRomRedirectionAvailable"},
{2523, nullptr, "GetProgramId"}, //17.0.0+
{2524, nullptr, "Unknown2524"}, //19.0.0+
{2525, nullptr, "Unknown2525"}, //20.0.0+
{2800, nullptr, "GetApplicationIdOfPreomia"},
{3000, nullptr, "RegisterDeviceLockKey"},
{3001, nullptr, "UnregisterDeviceLockKey"},
@@ -380,99 +314,11 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{3013, nullptr, "IsGameCardEnabled"},
{3014, nullptr, "IsLocalContentShareEnabled"},
{3050, nullptr, "ListAssignELicenseTaskResult"},
{3104, nullptr, "GetApplicationNintendoLogo"}, //18.0.0+
{3105, nullptr, "GetApplicationStartupMovie"}, //18.0.0+
{4000, nullptr, "Unknown4000"}, //20.0.0+
{4004, nullptr, "Unknown4004"}, //20.0.0+
{4006, nullptr, "Unknown4006"}, //20.0.0+
{4007, nullptr, "Unknown4007"}, //20.0.0+
{4008, nullptr, "Unknown4008"}, //20.0.0+
{4009, nullptr, "Unknown4009"}, //20.0.0+
{4010, nullptr, "Unknown4010"}, //20.0.0+
{4011, nullptr, "Unknown4011"}, //20.0.0+
{4012, nullptr, "Unknown4012"}, //20.0.0+
{4013, nullptr, "Unknown4013"}, //20.0.0+
{4015, nullptr, "Unknown4015"}, //20.0.0+
{4017, nullptr, "Unknown4017"}, //20.0.0+
{4019, nullptr, "Unknown4019"}, //20.0.0+
{4020, nullptr, "Unknown4020"}, //20.0.0+
{4021, nullptr, "Unknown4021"}, //20.0.0+
{4022, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4022"}, //20.0.0+
{4023, D<&IApplicationManagerInterface::Unknown4023>, "Unknown4023"}, //20.0.0+
{4024, nullptr, "Unknown4024"}, //20.0.0+
{4025, nullptr, "Unknown4025"}, //20.0.0+
{4026, nullptr, "Unknown4026"}, //20.0.0+
{4027, nullptr, "Unknown4027"}, //20.0.0+
{4028, nullptr, "Unknown4028"}, //20.0.0+
{4029, nullptr, "Unknown4029"}, //20.0.0+
{4030, nullptr, "Unknown4030"}, //20.0.0+
{4031, nullptr, "Unknown4031"}, //20.0.0+
{4032, nullptr, "Unknown4032"}, //20.0.0+
{4033, nullptr, "Unknown4033"}, //20.0.0+
{4034, nullptr, "Unknown4034"}, //20.0.0+
{4035, nullptr, "Unknown4035"}, //20.0.0+
{4037, nullptr, "Unknown4037"}, //20.0.0+
{4038, nullptr, "Unknown4038"}, //20.0.0+
{4039, nullptr, "Unknown4039"}, //20.0.0+
{4040, nullptr, "Unknown4040"}, //20.0.0+
{4041, nullptr, "Unknown4041"}, //20.0.0+
{4042, nullptr, "Unknown4042"}, //20.0.0+
{4043, nullptr, "Unknown4043"}, //20.0.0+
{4044, nullptr, "Unknown4044"}, //20.0.0+
{4045, nullptr, "Unknown4045"}, //20.0.0+
{4046, nullptr, "Unknown4046"}, //20.0.0+
{4049, nullptr, "Unknown4049"}, //20.0.0+
{4050, nullptr, "Unknown4050"}, //20.0.0+
{4051, nullptr, "Unknown4051"}, //20.0.0+
{4052, nullptr, "Unknown4052"}, //20.0.0+
{4053, D<&IApplicationManagerInterface::Unknown4053>, "Unknown4053"}, //20.0.0+
{4054, nullptr, "Unknown4054"}, //20.0.0+
{4055, nullptr, "Unknown4055"}, //20.0.0+
{4056, nullptr, "Unknown4056"}, //20.0.0+
{4057, nullptr, "Unknown4057"}, //20.0.0+
{4058, nullptr, "Unknown4058"}, //20.0.0+
{4059, nullptr, "Unknown4059"}, //20.0.0+
{4060, nullptr, "Unknown4060"}, //20.0.0+
{4061, nullptr, "Unknown4061"}, //20.0.0+
{4062, nullptr, "Unknown4062"}, //20.0.0+
{4063, nullptr, "Unknown4063"}, //20.0.0+
{4064, nullptr, "Unknown4064"}, //20.0.0+
{4065, nullptr, "Unknown4065"}, //20.0.0+
{4066, nullptr, "Unknown4066"}, //20.0.0+
{4067, nullptr, "Unknown4067"}, //20.0.0+
{4068, nullptr, "Unknown4068"}, //20.0.0+
{4069, nullptr, "Unknown4069"}, //20.0.0+
{4070, nullptr, "Unknown4070"}, //20.0.0+
{4071, nullptr, "Unknown4071"}, //20.0.0+
{4072, nullptr, "Unknown4072"}, //20.0.0+
{4073, nullptr, "Unknown4073"}, //20.0.0+
{4074, nullptr, "Unknown4074"}, //20.0.0+
{4075, nullptr, "Unknown4075"}, //20.0.0+
{4076, nullptr, "Unknown4076"}, //20.0.0+
{4077, nullptr, "Unknown4077"}, //20.0.0+
{4078, nullptr, "Unknown4078"}, //20.0.0+
{4079, nullptr, "Unknown4079"}, //20.0.0+
{4080, nullptr, "Unknown4080"}, //20.0.0+
{4081, nullptr, "Unknown4081"}, //20.0.0+
{4083, nullptr, "Unknown4083"}, //20.0.0+
{4084, nullptr, "Unknown4084"}, //20.0.0+
{4085, nullptr, "Unknown4085"}, //20.0.0+
{4086, nullptr, "Unknown4086"}, //20.0.0+
{4087, nullptr, "Unknown4087"}, //20.0.0+
{4088, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4088"}, //20.0.0+
{4089, nullptr, "Unknown4089"}, //20.0.0+
{4090, nullptr, "Unknown4090"}, //20.0.0+
{4091, nullptr, "Unknown4091"}, //20.0.0+
{4092, nullptr, "Unknown4092"}, //20.0.0+
{4093, nullptr, "Unknown4093"}, //20.0.0+
{4094, nullptr, "Unknown4094"}, //20.0.0+
{4095, nullptr, "Unknown4095"}, //20.0.0+
{4096, nullptr, "Unknown4096"}, //20.0.0+
{4097, nullptr, "Unknown4097"}, //20.0.0+
{4099, nullptr, "Unknown4099"}, //21.0.0+
{5000, nullptr, "Unknown5000"}, //18.0.0+
{5001, nullptr, "Unknown5001"}, //18.0.0+
{9999, nullptr, "GetApplicationCertificate"}, //10.0.0-10.2.0
{4022, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4022"},
{4023, D<&IApplicationManagerInterface::Unknown4023>, "Unknown4023"},
{4088, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4088"},
{4053, D<&IApplicationManagerInterface::Unknown4053>, "Unknown4053"},
{9999, nullptr, "GetApplicationCertificate"},
};
// clang-format on
@@ -485,53 +331,6 @@ Result IApplicationManagerInterface::UnregisterNetworkServiceAccountWithUserSave
LOG_DEBUG(Service_NS, "called, user_id={}", user_id.FormattedString());
R_SUCCEED();
}
Result IApplicationManagerInterface::GetApplicationLogoData(
Out<s64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, u64 application_id,
InBuffer<BufferAttr_HipcMapAlias> logo_path_buffer) {
const std::string path_view{reinterpret_cast<const char*>(logo_path_buffer.data()),
logo_path_buffer.size()};
// Find null terminator and trim the path
auto null_pos = path_view.find('\0');
std::string path = (null_pos != std::string::npos) ? path_view.substr(0, null_pos) : path_view;
LOG_DEBUG(Service_NS, "called, application_id={:016X}, logo_path={}", application_id, path);
auto& content_provider = system.GetContentProviderUnion();
auto program = content_provider.GetEntry(application_id, FileSys::ContentRecordType::Program);
if (!program) {
LOG_WARNING(Service_NS, "Application program not found for id={:016X}", application_id);
R_RETURN(ResultUnknown);
}
const auto logo_dir = program->GetLogoPartition();
if (!logo_dir) {
LOG_WARNING(Service_NS, "Logo partition not found for id={:016X}", application_id);
R_RETURN(ResultUnknown);
}
const auto file = logo_dir->GetFile(path);
if (!file) {
LOG_WARNING(Service_NS, "Logo path not found: {} for id={:016X}", path,
application_id);
R_RETURN(ResultUnknown);
}
const auto data = file->ReadAllBytes();
if (data.size() > out_buffer.size()) {
LOG_WARNING(Service_NS, "Logo buffer too small: have={}, need={}", out_buffer.size(),
data.size());
R_RETURN(ResultUnknown);
}
std::memcpy(out_buffer.data(), data.data(), data.size());
*out_size = static_cast<s64>(data.size());
R_SUCCEED();
}
Result IApplicationManagerInterface::GetApplicationControlData(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
ApplicationControlSource application_control_source, u64 application_id) {

View File

@@ -60,10 +60,6 @@ public:
u64 application_id);
Result CheckApplicationLaunchVersion(u64 application_id);
Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id);
Result GetApplicationLogoData(Out<s64> out_size,
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
u64 application_id,
InBuffer<BufferAttr_HipcMapAlias> logo_path_buffer);
Result Unknown4022(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result Unknown4023(Out<u64> out_result);
Result Unknown4053();

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -25,7 +22,6 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
{601, nullptr, "ListApplicationContentMetaStatus"},
{605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
{607, nullptr, "IsAnyApplicationRunning"},
{608, nullptr, "Unknown608"}, //21.0.0+
};
// clang-format on

View File

@@ -37,11 +37,7 @@ IDynamicRightsInterface::IDynamicRightsInterface(Core::System& system_)
{23, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
{24, nullptr, "NotifyLimitedApplicationLicenseUpgradableEventForDebug"},
{25, nullptr, "RequestProceedDynamicRightsState"},
{26, D<&IDynamicRightsInterface::HasAccountRestrictedRightsInRunningApplications>, "HasAccountRestrictedRightsInRunningApplications"},
{27, nullptr, "Unknown27"}, //20.0.0+
{28, nullptr, "Unknown28"}, //20.0.0+
{29, nullptr, "Unknown29"}, //21.0.0+
{30, nullptr, "Unknown30"}, //21.0.0+
{26, D<&IDynamicRightsInterface::HasAccountRestrictedRightsInRunningApplications>, "HasAccountRestrictedRightsInRunningApplications"}
};
// clang-format on

View File

@@ -179,9 +179,4 @@ struct ApplicationDisplayData {
};
static_assert(sizeof(ApplicationDisplayData) == 0x300, "ApplicationDisplayData has incorrect size.");
struct LogoPath {
std::array<char, 0x300> path;
};
static_assert(std::is_trivially_copyable_v<LogoPath>, "LogoPath must be trivially copyable.");
} // namespace Service::NS

View File

@@ -15,7 +15,7 @@ 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), z_index(0), is_overlay(false) {}
blending(LayerBlending::None), visible(true), z_index(0) {}
~Layer() {
buffer_item_consumer->Abandon();
}
@@ -25,7 +25,6 @@ struct Layer {
LayerBlending blending;
bool visible;
s32 z_index;
bool is_overlay;
};
struct LayerStack {

View File

@@ -78,25 +78,8 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
for (auto& layer : display.stack.layers) {
auto consumer_id = layer->consumer_id;
bool should_try_acquire = true;
if (!layer->is_overlay) {
auto fb_it = m_framebuffers.find(consumer_id);
if (fb_it != m_framebuffers.end() && fb_it->second.is_acquired) {
const u64 frames_since_last_acquire = m_frame_number - fb_it->second.last_acquire_frame;
const s32 expected_interval = NormalizeSwapInterval(nullptr, fb_it->second.item.swap_interval);
if (frames_since_last_acquire < static_cast<u64>(expected_interval)) {
should_try_acquire = false;
}
}
}
// Try to fetch the framebuffer (either new or stale).
const auto result = should_try_acquire
? this->CacheFramebufferLocked(*layer, consumer_id)
: (m_framebuffers.find(consumer_id) != m_framebuffers.end() && m_framebuffers[consumer_id].is_acquired
? CacheStatus::CachedBufferReused
: CacheStatus::NoBufferAvailable);
const auto result = this->CacheFramebufferLocked(*layer, consumer_id);
// If we failed, skip this layer.
if (result == CacheStatus::NoBufferAvailable) {
@@ -128,12 +111,6 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
});
}
// Overlay layers run at their own framerate independently of the game.
// Skip them when calculating the swap interval for the main game.
if (layer->is_overlay) {
continue;
}
// We need to compose again either before this frame is supposed to
// be released, or exactly on the vsync period it should be released.
const s32 item_swap_interval = NormalizeSwapInterval(out_speed_scale, item.swap_interval);
@@ -161,44 +138,33 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
// Batch framebuffer releases, instead of one-into-one.
std::vector<std::pair<Layer*, Framebuffer*>> to_release;
for (auto& [layer_id, framebuffer] : m_framebuffers) {
if (!framebuffer.is_acquired)
if (framebuffer.release_frame_number > m_frame_number || !framebuffer.is_acquired)
continue;
auto layer = display.stack.FindLayer(layer_id);
if (!layer)
continue;
// Overlay layers always release after every compose
// Non-overlay layers release based on their swap interval
if (layer->is_overlay || framebuffer.release_frame_number <= m_frame_number) {
if (auto layer = display.stack.FindLayer(layer_id); layer)
to_release.emplace_back(layer.get(), &framebuffer);
}
}
for (auto& [layer, framebuffer] : to_release) {
layer->buffer_item_consumer->ReleaseBuffer(framebuffer->item, android::Fence::NoFence());
framebuffer->is_acquired = false;
}
// Advance by 1 frame (60 FPS compositing)
m_frame_number += 1;
// Advance by at least one frame.
const u32 frame_advance = swap_interval.value_or(1);
m_frame_number += frame_advance;
// Release any necessary framebuffers (non-overlay layers only, as overlays are already released above).
// Release any necessary framebuffers.
for (auto& [layer_id, framebuffer] : m_framebuffers) {
if (framebuffer.release_frame_number > m_frame_number) {
// Not yet ready to release this framebuffer.
continue;
}
if (!framebuffer.is_acquired) {
// Already released.
continue;
}
if (framebuffer.release_frame_number > m_frame_number) {
continue;
}
if (const auto layer = display.stack.FindLayer(layer_id); layer != nullptr) {
// Skip overlay layers as they were already released above
if (layer->is_overlay) {
continue;
}
// TODO: support release fence
// This is needed to prevent screen tearing
layer->buffer_item_consumer->ReleaseBuffer(framebuffer.item, android::Fence::NoFence());
@@ -206,7 +172,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
}
}
return 1;
return frame_advance;
}
void HardwareComposer::RemoveLayerLocked(Display& display, ConsumerId consumer_id) {
@@ -234,9 +200,8 @@ bool HardwareComposer::TryAcquireFramebufferLocked(Layer& layer, Framebuffer& fr
}
// We succeeded, so set the new release frame info.
const s32 swap_interval = layer.is_overlay ? 1 : NormalizeSwapInterval(nullptr, framebuffer.item.swap_interval);
framebuffer.release_frame_number = m_frame_number + swap_interval;
framebuffer.last_acquire_frame = m_frame_number;
framebuffer.release_frame_number =
NormalizeSwapInterval(nullptr, framebuffer.item.swap_interval);
framebuffer.is_acquired = true;
return true;

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -37,7 +34,6 @@ private:
struct Framebuffer {
android::BufferItem item{};
ReleaseFrameNumber release_frame_number{};
u64 last_acquire_frame{0};
bool is_acquired{false};
};

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -104,13 +101,6 @@ void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blen
}
}
void SurfaceFlinger::SetLayerIsOverlay(s32 consumer_binder_id, bool is_overlay) {
if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) {
layer->is_overlay = is_overlay;
LOG_DEBUG(Service_VI, "Layer {} marked as overlay: {}", consumer_binder_id, is_overlay);
}
}
Display* SurfaceFlinger::FindDisplay(u64 display_id) {
for (auto& display : m_displays) {
if (display.id == display_id) {

View File

@@ -47,7 +47,6 @@ public:
void SetLayerVisibility(s32 consumer_binder_id, bool visible);
void SetLayerBlending(s32 consumer_binder_id, LayerBlending blending);
void SetLayerIsOverlay(s32 consumer_binder_id, bool is_overlay);
std::shared_ptr<Layer> FindLayer(s32 consumer_binder_id);

View File

@@ -16,67 +16,64 @@ IOlscServiceForSystemService::IOlscServiceForSystemService(Core::System& system_
: ServiceFramework{system_, "olsc:s"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IOlscServiceForSystemService::GetTransferTaskListController>, "GetTransferTaskListController"},
{1, D<&IOlscServiceForSystemService::GetRemoteStorageController>, "GetRemoteStorageController"},
{2, D<&IOlscServiceForSystemService::GetDaemonController>, "GetDaemonController"},
{10, nullptr, "PrepareDeleteUserProperty"},
{11, nullptr, "DeleteUserSaveDataProperty"},
{12, nullptr, "InvalidateMountCache"},
{13, nullptr, "DeleteDeviceSaveDataProperty"},
{0, D<&IOlscServiceForSystemService::OpenTransferTaskListController>, "OpenTransferTaskListController"},
{1, D<&IOlscServiceForSystemService::OpenRemoteStorageController>, "OpenRemoteStorageController"},
{2, D<&IOlscServiceForSystemService::OpenDaemonController>, "OpenDaemonController"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{100, nullptr, "ListLastTransferTaskErrorInfo"},
{101, nullptr, "GetLastErrorInfoCount"},
{102, nullptr, "RemoveLastErrorInfoOld"},
{103, nullptr, "GetLastErrorInfo"},
{104, nullptr, "GetLastErrorEventHolder"},
{105, nullptr, "GetLastTransferTaskErrorInfo"},
{200, D<&IOlscServiceForSystemService::GetDataTransferPolicy>, "GetDataTransferPolicy"},
{201, nullptr, "DeleteDataTransferPolicyCache"},
{202, nullptr, "Unknown202"},
{203, nullptr, "RequestUpdateDataTransferPolicyCacheAsync"},
{204, nullptr, "ClearDataTransferPolicyCache"},
{205, nullptr, "RequestGetDataTransferPolicyAsync"},
{206, nullptr, "Unknown206"}, //21.0.0+
{300, nullptr, "GetUserSaveDataProperty"},
{301, nullptr, "SetUserSaveDataProperty"},
{302, nullptr, "Unknown302"}, //21.0.0+
{400, nullptr, "CleanupSaveDataBackupContextForSpecificApplications"},
{900, nullptr, "DeleteAllTransferTask"},
{902, nullptr, "DeleteAllSeriesInfo"},
{903, nullptr, "DeleteAllSdaInfoCache"},
{904, nullptr, "DeleteAllApplicationSetting"},
{905, nullptr, "DeleteAllTransferTaskErrorInfo"},
{906, nullptr, "RegisterTransferTaskErrorInfo"},
{907, nullptr, "AddSaveDataArchiveInfoCache"},
{908, nullptr, "DeleteSeriesInfo"},
{909, nullptr, "GetSeriesInfo"},
{910, nullptr, "RemoveTransferTaskErrorInfo"},
{911, nullptr, "DeleteAllSeriesInfoForSaveDataBackup"},
{912, nullptr, "DeleteSeriesInfoForSaveDataBackup"},
{913, nullptr, "GetSeriesInfoForSaveDataBackup"},
{914, nullptr, "Unknown914"}, //20.2.0+
{200, D<&IOlscServiceForSystemService::GetDataTransferPolicyInfo>, "GetDataTransferPolicyInfo"},
{201, nullptr, "RemoveDataTransferPolicyInfo"},
{202, nullptr, "UpdateDataTransferPolicyOld"},
{203, nullptr, "UpdateDataTransferPolicy"},
{204, nullptr, "CleanupDataTransferPolicyInfo"},
{205, nullptr, "RequestDataTransferPolicy"},
{300, nullptr, "GetAutoTransferSeriesInfo"},
{301, nullptr, "UpdateAutoTransferSeriesInfo"},
{400, nullptr, "CleanupSaveDataArchiveInfoType1"},
{900, nullptr, "CleanupTransferTask"},
{902, nullptr, "CleanupSeriesInfoType0"},
{903, nullptr, "CleanupSaveDataArchiveInfoType0"},
{904, nullptr, "CleanupApplicationAutoTransferSetting"},
{905, nullptr, "CleanupErrorHistory"},
{906, nullptr, "SetLastError"},
{907, nullptr, "AddSaveDataArchiveInfoType0"},
{908, nullptr, "RemoveSeriesInfoType0"},
{909, nullptr, "GetSeriesInfoType0"},
{910, nullptr, "RemoveLastErrorInfo"},
{911, nullptr, "CleanupSeriesInfoType1"},
{912, nullptr, "RemoveSeriesInfoType1"},
{913, nullptr, "GetSeriesInfoType1"},
{1000, nullptr, "UpdateIssueOld"},
{1010, nullptr, "Unknown1010"},
{1011, nullptr, "Unknown1011"},
{1012, nullptr, "Unknown1012"},
{1013, nullptr, "Unkown1013"},
{1014, nullptr, "Unknown1014"},
{1020, nullptr, "Unknown1020"},
{1021, nullptr, "Unknown1021"},
{1022, nullptr, "Unknown1022"},
{1023, nullptr, "Unknown1023"},
{1011, nullptr, "ListIssueInfoOld"},
{1012, nullptr, "GetIssueOld"},
{1013, nullptr, "GetIssue2Old"},
{1014, nullptr, "GetIssue3Old"},
{1020, nullptr, "RepairIssueOld"},
{1021, nullptr, "RepairIssueWithUserIdOld"},
{1022, nullptr, "RepairIssue2Old"},
{1023, nullptr, "RepairIssue3Old"},
{1024, nullptr, "Unknown1024"},
{1100, nullptr, "RepairUpdateIssueInfoCacheAync"},
{1110, nullptr, "RepairGetIssueInfo"},
{1111, nullptr, "RepairListIssueInfo"},
{1112, nullptr, "RepairListOperationPermissionInfo"},
{1113, nullptr, "RepairListDataInfoForRepairedSaveDataDownload"},
{1114, nullptr, "RepairListDataInfoForOriginalSaveDataDownload"},
{1120, nullptr, "RepairUploadSaveDataAsync"},
{1121, nullptr, "RepairUploadSaveDataAsync1"},
{1122, nullptr, "RepairDownloadRepairedSaveDataAsync"},
{1123, nullptr, "RepairDownloadOriginalSaveDataAsync"},
{1124, nullptr, "RepairGetOperationProgressInfo"},
{10000, D<&IOlscServiceForSystemService::GetOlscServiceForSystemService>, "GetOlscServiceForSystemService"},
{1100, nullptr, "UpdateIssue"},
{1110, nullptr, "Unknown1110"},
{1111, nullptr, "ListIssueInfo"},
{1112, nullptr, "GetIssue"},
{1113, nullptr, "GetIssue2"},
{1114, nullptr, "GetIssue3"},
{1120, nullptr, "RepairIssue"},
{1121, nullptr, "RepairIssueWithUserId"},
{1122, nullptr, "RepairIssue2"},
{1123, nullptr, "RepairIssue3"},
{1124, nullptr, "Unknown1124"},
{10000, D<&IOlscServiceForSystemService::CloneService>, "CloneService"},
};
// clang-format on
@@ -85,38 +82,38 @@ IOlscServiceForSystemService::IOlscServiceForSystemService(Core::System& system_
IOlscServiceForSystemService::~IOlscServiceForSystemService() = default;
Result IOlscServiceForSystemService::GetTransferTaskListController(
Result IOlscServiceForSystemService::OpenTransferTaskListController(
Out<SharedPointer<ITransferTaskListController>> out_interface) {
LOG_INFO(Service_OLSC, "called");
*out_interface = std::make_shared<ITransferTaskListController>(system);
R_SUCCEED();
}
Result IOlscServiceForSystemService::GetRemoteStorageController(
Result IOlscServiceForSystemService::OpenRemoteStorageController(
Out<SharedPointer<IRemoteStorageController>> out_interface) {
LOG_INFO(Service_OLSC, "called");
*out_interface = std::make_shared<IRemoteStorageController>(system);
R_SUCCEED();
}
Result IOlscServiceForSystemService::GetDaemonController(
Result IOlscServiceForSystemService::OpenDaemonController(
Out<SharedPointer<IDaemonController>> out_interface) {
LOG_INFO(Service_OLSC, "called");
*out_interface = std::make_shared<IDaemonController>(system);
R_SUCCEED();
}
Result IOlscServiceForSystemService::GetDataTransferPolicy(
Out<DataTransferPolicy> out_policy, u64 application_id) {
Result IOlscServiceForSystemService::GetDataTransferPolicyInfo(
Out<DataTransferPolicy> out_policy_info, u64 application_id) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
DataTransferPolicy policy{};
policy.upload_policy = 0;
policy.download_policy = 0;
*out_policy = policy;
*out_policy_info = policy;
R_SUCCEED();
}
Result IOlscServiceForSystemService::GetOlscServiceForSystemService(
Result IOlscServiceForSystemService::CloneService(
Out<SharedPointer<IOlscServiceForSystemService>> out_interface) {
LOG_INFO(Service_OLSC, "called");
*out_interface = std::static_pointer_cast<IOlscServiceForSystemService>(shared_from_this());

View File

@@ -24,12 +24,12 @@ public:
~IOlscServiceForSystemService() override;
private:
Result GetTransferTaskListController(
Result OpenTransferTaskListController(
Out<SharedPointer<ITransferTaskListController>> out_interface);
Result GetRemoteStorageController(Out<SharedPointer<IRemoteStorageController>> out_interface);
Result GetDaemonController(Out<SharedPointer<IDaemonController>> out_interface);
Result GetDataTransferPolicy(Out<DataTransferPolicy> out_policy, u64 application_id);
Result GetOlscServiceForSystemService(Out<SharedPointer<IOlscServiceForSystemService>> out_interface);
Result OpenRemoteStorageController(Out<SharedPointer<IRemoteStorageController>> out_interface);
Result OpenDaemonController(Out<SharedPointer<IDaemonController>> out_interface);
Result GetDataTransferPolicyInfo(Out<DataTransferPolicy> out_policy_info, u64 application_id);
Result CloneService(Out<SharedPointer<IOlscServiceForSystemService>> out_interface);
};
} // namespace Service::OLSC

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -14,37 +11,32 @@ ITransferTaskListController::ITransferTaskListController(Core::System& system_)
: ServiceFramework{system_, "ITransferTaskListController"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetTransferTaskCountForOcean"},
{1, nullptr, "GetTransferTaskInfoForOcean"},
{2, nullptr, "ListTransferTaskInfoForOcean"},
{3, nullptr, "DeleteTransferTaskForOcean"},
{4, nullptr, "RaiseTransferTaskPriorityForOcean"},
{5, D<&ITransferTaskListController::GetTransferTaskEndEventNativeHandleHolder>, "GetTransferTaskEndEventNativeHandleHolder"},
{6, nullptr, "GetTransferTaskProgressForOcean"},
{7, nullptr, "GetTransferTaskLastResultForOcean"},
{8, nullptr, "StopNextTransferTaskExecution"},
{9, D<&ITransferTaskListController::GetTransferTaskStartEventNativeHandleHolder>, "GetTransferTaskStartEventNativeHandleHolder"},
{10, nullptr, "SuspendTransferTaskForOcean"},
{11, nullptr, "GetCurrentTransferTaskInfoForOcean"},
{12, nullptr, "FindTransferTaskInfoForOcean"},
{13, nullptr, "CancelCurrentRepairTransferTask"},
{14, nullptr, "GetRepairTransferTaskProgress"},
{15, nullptr, "EnsureExecutableForRepairTransferTask"},
{16, nullptr, "GetTransferTaskCount"},
{17, nullptr, "GetTransferTaskInfo"},
{18, nullptr, "ListTransferTaskInfo"},
{19, nullptr, "DeleteTransferTask"},
{20, nullptr, "RaiseTransferTaskPriority"},
{21, nullptr, "GetTransferTaskProgress"},
{22, nullptr, "GetTransferTaskLastResult"},
{23, nullptr, "SuspendTransferTask"},
{24, nullptr, "GetCurrentTransferTaskInfo"},
{25, nullptr, "Unknown25"}, //20.1.0+
{26, nullptr, "Unknown26"}, //20.1.0+
{27, nullptr, "Unknown27"}, //20.1.0+
{28, nullptr, "Unknown28"}, //20.1.0+
{29, nullptr, "Unknown29"}, //20.1.0+
{30, nullptr, "Unknown30"}, //20.1.0+
{0, nullptr, "Unknown0"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, D<&ITransferTaskListController::GetNativeHandleHolder>, "GetNativeHandleHolder"},
{6, nullptr, "Unknown6"},
{7, nullptr, "Unknown7"},
{8, nullptr, "GetRemoteStorageController"},
{9, D<&ITransferTaskListController::GetNativeHandleHolder>, "GetNativeHandleHolder2"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{14, nullptr, "Unknown14"},
{15, nullptr, "Unknown15"},
{16, nullptr, "Unknown16"},
{17, nullptr, "Unknown17"},
{18, nullptr, "Unknown18"},
{19, nullptr, "Unknown19"},
{20, nullptr, "Unknown20"},
{21, nullptr, "Unknown21"},
{22, nullptr, "Unknown22"},
{23, nullptr, "Unknown23"},
{24, nullptr, "Unknown24"},
{25, nullptr, "Unknown25"},
};
// clang-format on
@@ -53,14 +45,7 @@ ITransferTaskListController::ITransferTaskListController(Core::System& system_)
ITransferTaskListController::~ITransferTaskListController() = default;
Result ITransferTaskListController::GetTransferTaskEndEventNativeHandleHolder(
Out<SharedPointer<INativeHandleHolder>> out_holder) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
*out_holder = std::make_shared<INativeHandleHolder>(system);
R_SUCCEED();
}
Result ITransferTaskListController::GetTransferTaskStartEventNativeHandleHolder(
Result ITransferTaskListController::GetNativeHandleHolder(
Out<SharedPointer<INativeHandleHolder>> out_holder) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
*out_holder = std::make_shared<INativeHandleHolder>(system);

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -17,8 +14,7 @@ public:
~ITransferTaskListController() override;
private:
Result GetTransferTaskEndEventNativeHandleHolder(Out<SharedPointer<INativeHandleHolder>> out_holder);
Result GetTransferTaskStartEventNativeHandleHolder(Out<SharedPointer<INativeHandleHolder>> out_holder);
Result GetNativeHandleHolder(Out<SharedPointer<INativeHandleHolder>> out_holder);
};
} // namespace Service::OLSC

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -37,10 +34,10 @@ public:
{17, nullptr, "AcquireIrq"},
{18, nullptr, "ReleaseIrq"},
{19, nullptr, "SetIrqEnable"},
{20, nullptr, "GetIrqEvent"},
{21, nullptr, "SetAspmEnable"},
{22, nullptr, "SetResetUponResumeEnable"},
{23, nullptr, "ResetFunction"},
{20, nullptr, "SetAspmEnable"},
{21, nullptr, "SetResetUponResumeEnable"},
{22, nullptr, "ResetFunction"},
{23, nullptr, "Unknown23"},
};
// clang-format on

View File

@@ -39,9 +39,6 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
{1017, D<&IParentalControlService::EndFreeCommunication>, "EndFreeCommunication"},
{1018, D<&IParentalControlService::IsFreeCommunicationAvailable>, "IsFreeCommunicationAvailable"},
{1019, D<&IParentalControlService::ConfirmLaunchApplicationPermission>, "ConfirmLaunchApplicationPermission"},
{1020, nullptr, "ConfirmLaunchSharedApplicationPermission"}, //20.0.0+
{1021, nullptr, "TryBeginFreeCommunicationForStreamPlay"}, //21.0.0+
{1022, nullptr, "EndFreeCommunicationForStreamPlay"}, //21.0.0+
{1031, D<&IParentalControlService::IsRestrictionEnabled>, "IsRestrictionEnabled"},
{1032, D<&IParentalControlService::GetSafetyLevel>, "GetSafetyLevel"},
{1033, nullptr, "SetSafetyLevel"},
@@ -59,8 +56,6 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
{1047, nullptr, "NotifyApplicationDownloadStarted"},
{1048, nullptr, "NotifyNetworkProfileCreated"},
{1049, nullptr, "ResetFreeCommunicationApplicationList"},
{1050, nullptr, "AddToFreeCommunicationApplicationList"}, //20.0.0+
{1051, nullptr, "NotifyApplicationDownloadStarted"}, //20.0.0+
{1061, D<&IParentalControlService::ConfirmStereoVisionRestrictionConfigurable>, "ConfirmStereoVisionRestrictionConfigurable"},
{1062, D<&IParentalControlService::GetStereoVisionRestriction>, "GetStereoVisionRestriction"},
{1063, D<&IParentalControlService::SetStereoVisionRestriction>, "SetStereoVisionRestriction"},
@@ -131,17 +126,8 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
{2013, nullptr, "SynchronizeParentalControlSettingsAsync"},
{2014, nullptr, "FinishSynchronizeParentalControlSettings"},
{2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
{2016, nullptr, "RequestUpdateExemptionListAsync"}, //5.0.0+
{145601, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"}, // 18.0.0+
{2017, nullptr, "AuthorizePairingAsync"}, //19.0.0+
{2019, nullptr, "RequestUpdateDeviceUsersBackground"}, //19.0.0+
{2021, nullptr, "RequestCopyPairingAsync"}, //20.0.0+
{2022, nullptr, "FinishRequestCopyPairing"}, //20.0.0+
{2023, nullptr, "IsFromPairingActiveDevice"}, //20.0.0+
{2024, nullptr, "RollbackCopyPairing"}, //21.0.0+
{3001, nullptr, "GetErrorContextChangedEvent"}, //20.0.0+
{145601, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"}, // 18.0.0+
{195101, D<&IParentalControlService::SetPlayTimerSettings>, "SetPlayTimerSettingsForDebug"}, //18.0.0+
{2016, nullptr, "RequestUpdateExemptionListAsync"},
{145601, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"} // 18.0.0+
};
// clang-format on
RegisterHandlers(functions);
@@ -407,21 +393,16 @@ Result IParentalControlService::IsRestrictedByPlayTimer(Out<bool> out_is_restric
}
Result IParentalControlService::GetPlayTimerSettingsOld(
Out<PlayTimerSettingsOld> out_play_timer_settings) {
Out<PlayTimerSettings> out_play_timer_settings) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
*out_play_timer_settings = {};
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerSettings(Out<PlayTimerSettings> out_play_timer_settings) {
Result IParentalControlService::GetPlayTimerSettings(
Out<PlayTimerSettings> out_play_timer_settings) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
*out_play_timer_settings = raw_play_timer_settings;
R_SUCCEED();
}
Result IParentalControlService::SetPlayTimerSettings(PlayTimerSettings play_timer_settings) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
raw_play_timer_settings = play_timer_settings;
*out_play_timer_settings = {};
R_SUCCEED();
}

View File

@@ -51,7 +51,7 @@ private:
Result IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled);
Result GetPlayTimerRemainingTime(Out<s32> out_remaining_time);
Result IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer);
Result GetPlayTimerSettingsOld(Out<PlayTimerSettingsOld> out_play_timer_settings);
Result GetPlayTimerSettingsOld(Out<PlayTimerSettings> out_play_timer_settings);
Result GetPlayTimerEventToRequestSuspension(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled);
Result GetPlayTimerRemainingTimeDisplayInfo();
@@ -60,7 +60,6 @@ private:
Result SetStereoVisionRestriction(bool stereo_vision_restriction);
Result ResetConfirmedStereoVisionPermission();
Result GetPlayTimerSettings(Out<PlayTimerSettings> out_play_timer_settings);
Result SetPlayTimerSettings(PlayTimerSettings out_play_timer_settings);
struct States {
u64 current_tid{};
@@ -84,8 +83,6 @@ private:
RestrictionSettings restriction_settings{};
std::array<char, 8> pin_code{};
Capability capability{};
// TODO: this is RAW as fuck
PlayTimerSettings raw_play_timer_settings{};
KernelHelpers::ServiceContext service_context;
Event synchronization_event;

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -37,16 +34,10 @@ struct RestrictionSettings {
};
static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size.");
// This is nn::pctl::PlayTimerSettingsOld
struct PlayTimerSettingsOld {
std::array<u32, 13> settings;
};
static_assert(sizeof(PlayTimerSettingsOld) == 0x34, "PlayTimerSettingsOld has incorrect size.");
// This is nn::pctl::PlayTimerSettings
struct PlayTimerSettings {
std::array<u32, 17> settings; //21.0.0+ now takes 0x44
std::array<u32, 13> settings;
};
static_assert(sizeof(PlayTimerSettings) == 0x44, "PlayTimerSettings has incorrect size.");
static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size.");
} // namespace Service::PCTL

View File

@@ -34,9 +34,9 @@ public:
{10300, &PlayReport::GetTransmissionStatus, "GetTransmissionStatus"},
{10400, &PlayReport::GetSystemSessionId, "GetSystemSessionId"},
{20100, &PlayReport::SaveSystemReportOld, "SaveSystemReport"},
{20101, &PlayReport::SaveSystemReportWithUserOld, "SaveSystemReportWithUser"},
{20102, &PlayReport::SaveSystemReport, "SaveSystemReport"},
{20103, &PlayReport::SaveSystemReportWithUser, "SaveSystemReportWithUser"},
{20101, &PlayReport::SaveSystemReportWithUserOld, "SaveSystemReportWithUser"},
{20102, &PlayReport::SaveSystemReport, "SaveSystemReport"},
{20103, &PlayReport::SaveSystemReportWithUser, "SaveSystemReportWithUser"},
{20200, nullptr, "SetOperationMode"},
{30100, nullptr, "ClearStorage"},
{30200, nullptr, "ClearStatistics"},

View File

@@ -18,43 +18,49 @@
namespace Service {
/// @brief Creates a function string for logging, complete with the name (or header code, depending
/// on what's passed in) the port name, and all the cmd_buff arguments.
[[maybe_unused]] static std::string MakeFunctionString(std::string_view name, std::string_view port_name, const u32* cmd_buff) {
/**
* Creates a function string for logging, complete with the name (or header code, depending
* on what's passed in) the port name, and all the cmd_buff arguments.
*/
[[maybe_unused]] static std::string MakeFunctionString(std::string_view name,
std::string_view port_name,
const u32* cmd_buff) {
// Number of params == bits 0-5 + bits 6-11
int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
std::string function_string = fmt::format("function '{}': port={}", name, port_name);
for (int i = 1; i <= num_params; ++i)
for (int i = 1; i <= num_params; ++i) {
function_string += fmt::format(", cmd_buff[{}]={:#X}", i, cmd_buff[i]);
}
return function_string;
}
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
u32 max_sessions_, InvokerFn* handler_invoker_)
: SessionRequestHandler(system_.Kernel(), service_name_), system{system_},
service_name{service_name_}, handler_invoker{handler_invoker_}, max_sessions{max_sessions_} {}
service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {}
ServiceFrameworkBase::~ServiceFrameworkBase() {
// Wait for other threads to release access before destroying
const auto guard = ServiceFrameworkBase::LockService();
const auto guard = LockService();
}
void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
// Usually this array is sorted by id already, so hint to insert at the end
handlers.reserve(handlers.size() + n);
for (std::size_t i = 0; i < n; ++i)
for (std::size_t i = 0; i < n; ++i) {
// Usually this array is sorted by id already, so hint to insert at the end
handlers.emplace_hint(handlers.cend(), functions[i].expected_header, functions[i]);
}
}
void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n) {
// Usually this array is sorted by id already, so hint to insert at the end
void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions,
std::size_t n) {
handlers_tipc.reserve(handlers_tipc.size() + n);
for (std::size_t i = 0; i < n; ++i)
for (std::size_t i = 0; i < n; ++i) {
// Usually this array is sorted by id already, so hint to insert at the end
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header,
functions[i]);
}
}
void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
@@ -63,12 +69,15 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
std::string function_name = info == nullptr ? "<unknown>" : info->name;
fmt::memory_buffer buf;
fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}", ctx.GetCommand(), function_name, service_name, cmd_buf[0]);
for (int i = 1; i <= 8; ++i)
fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}",
ctx.GetCommand(), function_name, service_name, cmd_buf[0]);
for (int i = 1; i <= 8; ++i) {
fmt::format_to(std::back_inserter(buf), ", [{}]={:#X}", i, cmd_buf[i]);
}
buf.push_back('}');
system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, service_name);
system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name,
service_name);
UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf));
if (Settings::values.use_auto_stub) {
LOG_WARNING(Service, "Using auto stub fallback!");
@@ -78,20 +87,25 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
}
void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) {
auto it = handlers.find(ctx.GetCommand());
FunctionInfoBase const* info = it == handlers.end() ? nullptr : &it->second;
if (info == nullptr || info->handler_callback == nullptr)
auto itr = handlers.find(ctx.GetCommand());
const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second;
if (info == nullptr || info->handler_callback == nullptr) {
return ReportUnimplementedFunction(ctx, info);
}
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
handler_invoker(this, info->handler_callback, ctx);
}
void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) {
auto it = handlers_tipc.find(ctx.GetCommand());
FunctionInfoBase const* info = it == handlers_tipc.end() ? nullptr : &it->second;
if (info == nullptr || info->handler_callback == nullptr)
boost::container::flat_map<u32, FunctionInfoBase>::iterator itr;
itr = handlers_tipc.find(ctx.GetCommand());
const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second;
if (info == nullptr || info->handler_callback == nullptr) {
return ReportUnimplementedFunction(ctx, info);
}
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
handler_invoker(this, info->handler_callback, ctx);

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -50,23 +47,25 @@ static_assert(ServerSessionCountMax == 0x40,
class ServiceFrameworkBase : public SessionRequestHandler {
public:
/// Returns the string identifier used to connect to the service.
[[nodiscard]] std::string_view GetServiceName() const noexcept {
std::string GetServiceName() const {
return service_name;
}
/// @brief Returns the maximum number of sessions that can be connected to this service at the same
/// time.
u32 GetMaxSessions() const noexcept {
/**
* Returns the maximum number of sessions that can be connected to this service at the same
* time.
*/
u32 GetMaxSessions() const {
return max_sessions;
}
/// @brief Invokes a service request routine using the HIPC protocol.
/// Invokes a service request routine using the HIPC protocol.
void InvokeRequest(HLERequestContext& ctx);
/// @brief Invokes a service request routine using the HIPC protocol.
/// Invokes a service request routine using the HIPC protocol.
void InvokeRequestTipc(HLERequestContext& ctx);
/// @brief Handles a synchronization request for the service.
/// Handles a synchronization request for the service.
Result HandleSyncRequest(Kernel::KServerSession& session, HLERequestContext& context) override;
protected:
@@ -75,7 +74,7 @@ protected:
using HandlerFnP = void (Self::*)(HLERequestContext&);
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
[[nodiscard]] virtual std::unique_lock<std::mutex> LockService() noexcept {
[[nodiscard]] virtual std::unique_lock<std::mutex> LockService() {
return std::unique_lock{lock_service};
}
@@ -106,19 +105,20 @@ private:
void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n);
void ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info);
boost::container::flat_map<u32, FunctionInfoBase> handlers;
boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc;
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
std::mutex lock_service;
/// Function used to safely up-cast pointers to the derived class before invoking a handler.
InvokerFn* handler_invoker;
/// Maximum number of concurrent sessions that this service can handle.
u32 max_sessions;
/// Flag to store if a port was already create/installed to detect multiple install attempts,
/// which is not supported.
bool service_registered = false;
/// Function used to safely up-cast pointers to the derived class before invoking a handler.
InvokerFn* handler_invoker;
boost::container::flat_map<u32, FunctionInfoBase> handlers;
boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc;
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
std::mutex lock_service;
};
/**
@@ -142,12 +142,20 @@ protected:
// TODO(yuriks): This function could be constexpr, but clang is the only compiler that
// doesn't emit an ICE or a wrong diagnostic because of the static_cast.
/// @brief Constructs a FunctionInfo for a function.
/// @param expected_header_ request header in the command buffer which will trigger dispatch to this handler
/// @param handler_callback_ member function in this service which will be called to handle the request
/// @param name_ human-friendly name for the request. Used mostly for logging purposes.
constexpr FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_)
: FunctionInfoBase{expected_header_, HandlerFnP<ServiceFrameworkBase>(handler_callback_), name_} {}
/**
* Constructs a FunctionInfo for a function.
*
* @param expected_header_ request header in the command buffer which will trigger dispatch
* to this handler
* @param handler_callback_ member function in this service which will be called to handle
* the request
* @param name_ human-friendly name for the request. Used mostly for logging purposes.
*/
FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_)
: FunctionInfoBase{
expected_header_,
// Type-erase member function pointer by casting it down to the base class.
static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback_), name_} {}
};
using FunctionInfo = FunctionInfoTyped<Self>;

View File

@@ -36,29 +36,6 @@ struct SettingsHeader {
u32 version;
u32 reserved;
};
void SyncGlobalLanguageFromCode(LanguageCode language_code) {
const auto it = std::find_if(available_language_codes.begin(), available_language_codes.end(),
[language_code](LanguageCode code) { return code == language_code; });
if (it == available_language_codes.end()) {
return;
}
const std::size_t index = static_cast<std::size_t>(std::distance(available_language_codes.begin(), it));
if (index >= static_cast<std::size_t>(Settings::values.language_index.GetValue())) {
Settings::values.language_index.SetValue(static_cast<Settings::Language>(index));
}
}
void SyncGlobalRegionFromCode(SystemRegionCode region_code) {
const auto region_index = static_cast<std::size_t>(region_code);
if (region_index > static_cast<std::size_t>(Settings::Region::Taiwan)) {
return;
}
Settings::values.region_index.SetValue(static_cast<Settings::Region>(region_index));
}
} // Anonymous namespace
Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
@@ -480,7 +457,6 @@ Result ISystemSettingsServer::SetLanguageCode(LanguageCode language_code) {
LOG_INFO(Service_SET, "called, language_code={}", language_code);
m_system_settings.language_code = language_code;
SyncGlobalLanguageFromCode(language_code);
SetSaveNeeded();
R_SUCCEED();
}
@@ -913,7 +889,6 @@ Result ISystemSettingsServer::SetRegionCode(SystemRegionCode region_code) {
LOG_INFO(Service_SET, "called, region_code={}", region_code);
m_system_settings.region_code = region_code;
SyncGlobalRegionFromCode(region_code);
SetSaveNeeded();
R_SUCCEED();
}
@@ -1249,7 +1224,6 @@ Result ISystemSettingsServer::SetKeyboardLayout(KeyboardLayout keyboard_layout)
LOG_INFO(Service_SET, "called, keyboard_layout={}", keyboard_layout);
m_system_settings.keyboard_layout = keyboard_layout;
SetSaveNeeded();
R_SUCCEED();
}

View File

@@ -578,7 +578,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
}
std::vector<Network::PollFD> host_pollfds(fds.size());
std::transform(fds.begin(), fds.end(), host_pollfds.begin(), [](PollFD pollfd) {
std::transform(fds.begin(), fds.end(), host_pollfds.begin(), [this](PollFD pollfd) {
Network::PollFD result;
result.socket = file_descriptors[pollfd.fd]->socket.get();
result.events = Translate(pollfd.events);
@@ -657,11 +657,7 @@ Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
const auto result = Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in)));
if (result != Errno::SUCCESS) {
if (result == Errno::INPROGRESS || result == Errno::AGAIN) {
LOG_DEBUG(Service, "Connect fd={} in progress (non-blocking), errno={}", fd, static_cast<int>(result));
} else {
LOG_ERROR(Service, "Connect fd={} failed with errno={}", fd, static_cast<int>(result));
}
LOG_ERROR(Service, "Connect fd={} failed with errno={}", fd, static_cast<int>(result));
} else {
LOG_INFO(Service, "Connect fd={} succeeded", fd);
}
@@ -971,11 +967,7 @@ Expected<s32, Errno> BSD::DuplicateSocketImpl(s32 fd) {
return Unexpected(Errno::MFILE);
}
file_descriptors[new_fd] = FileDescriptor{
.socket = file_descriptors[fd]->socket,
.flags = file_descriptors[fd]->flags,
.is_connection_based = file_descriptors[fd]->is_connection_based,
};
file_descriptors[new_fd] = file_descriptors[fd];
return new_fd;
}
@@ -1082,7 +1074,8 @@ BSD::~BSD() {
}
}
std::unique_lock<std::mutex> BSD::LockService() noexcept {
std::unique_lock<std::mutex> BSD::LockService() {
// Do not lock socket IClient instances.
return {};
}

View File

@@ -179,7 +179,7 @@ private:
void BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept;
static inline std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors{};
std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors;
/// Callback to parse and handle a received wifi packet.
void OnProxyPacketReceived(const Network::ProxyPacket& packet);
@@ -188,7 +188,7 @@ private:
Network::RoomMember::CallbackHandle<Network::ProxyPacket> proxy_packet_received;
protected:
std::unique_lock<std::mutex> LockService() noexcept override;
virtual std::unique_lock<std::mutex> LockService() override;
};
class BSDCFG final : public ServiceFramework<BSDCFG> {

View File

@@ -157,24 +157,22 @@ private:
auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
auto res = bsd->DuplicateSocketImpl(fd);
if (!res.has_value()) {
LOG_ERROR(Service_SSL, "Failed to duplicate socket with fd {}", fd);
return ResultInvalidSocket;
}
const s32 duplicated_fd = *res;
// Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor
if (do_not_close_socket) {
*out_fd = duplicated_fd;
auto res = bsd->DuplicateSocketImpl(fd);
if (!res.has_value()) {
LOG_ERROR(Service_SSL, "Failed to duplicate socket with fd {}", fd);
return ResultInvalidSocket;
}
fd = *res;
fd_to_close = fd;
*out_fd = fd;
} else {
*out_fd = -1;
fd_to_close = duplicated_fd;
}
std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(duplicated_fd);
std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd);
if (!sock.has_value()) {
LOG_ERROR(Service_SSL, "invalid socket fd {} after duplication", duplicated_fd);
LOG_ERROR(Service_SSL, "invalid socket fd {}", fd);
return ResultInvalidSocket;
}
socket = std::move(*sock);
@@ -327,19 +325,7 @@ private:
res = backend->GetServerCerts(&certs);
if (res == ResultSuccess) {
const std::vector<u8> certs_buf = SerializeServerCerts(certs);
if (ctx.CanWriteBuffer()) {
const size_t buffer_size = ctx.GetWriteBufferSize();
if (certs_buf.size() <= buffer_size) {
ctx.WriteBuffer(certs_buf);
} else {
LOG_WARNING(Service_SSL, "Certificate buffer too small: {} bytes needed, {} bytes available",
certs_buf.size(), buffer_size);
ctx.WriteBuffer(std::span<const u8>(certs_buf.data(), buffer_size));
}
} else {
LOG_DEBUG(Service_SSL, "No output buffer provided for certificates ({} bytes)", certs_buf.size());
}
ctx.WriteBuffer(certs_buf);
out.certs_count = static_cast<u32>(certs.size());
out.certs_size = static_cast<u32>(certs_buf.size());
}
@@ -678,119 +664,119 @@ class ISslServiceForSystem final : public ServiceFramework<ISslServiceForSystem>
{103, D<&ISslServiceForSystem::VerifySignature>, "VerifySignature"}
};
// clang-format on
RegisterHandlers(functions);
};
Result CreateContext() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result GetContextCount() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result GetCertificates() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result GetCertificateBufSize() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result DebugIoctl() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result SetInterfaceVersion() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result FlushSessionCache() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result SetDebugOption() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result GetDebugOption() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result ClearTls12FallbackFlag() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result CreateContextForSystem() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result SetThreadCoreMask() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result GetThreadCoreMask() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
Result VerifySignature() {
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
// TODO (jarrodnorwell)
return ResultSuccess;
};
};

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

View File

@@ -166,16 +166,6 @@ Result Container::GetLayerZIndex(u64 layer_id, s32* out_z_index) {
R_RETURN(VI::ResultNotFound);
}
Result Container::SetLayerIsOverlay(u64 layer_id, bool is_overlay) {
std::scoped_lock lk{m_lock};
auto* const layer = m_layers.GetLayerById(layer_id);
R_UNLESS(layer != nullptr, VI::ResultNotFound);
m_surface_flinger->SetLayerIsOverlay(layer->GetConsumerBinderId(), is_overlay);
R_SUCCEED();
}
void Container::LinkVsyncEvent(u64 display_id, Event* event) {
std::scoped_lock lk{m_lock};
m_conductor->LinkVsyncEvent(display_id, event);

View File

@@ -67,7 +67,6 @@ public:
Result SetLayerBlending(u64 layer_id, bool enabled);
Result SetLayerZIndex(u64 layer_id, s32 z_index);
Result GetLayerZIndex(u64 layer_id, s32* out_z_index);
Result SetLayerIsOverlay(u64 layer_id, bool is_overlay);
void LinkVsyncEvent(u64 display_id, Event* event);
void UnlinkVsyncEvent(u64 display_id, Event* event);

View File

@@ -46,8 +46,8 @@ Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_
u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress());
u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize());
for (; start < end; start++) {
*start = 0xFF0000FF;
for (; start < end; ++start) {
*start = 0x00000000; // ARGB/RGBA with alpha=0
}
}
@@ -257,6 +257,7 @@ Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64*
// Configure blending and z-index
R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));
R_ASSERT(m_container.SetLayerZIndex(session.layer_id, 100000));
// Get the producer and set preallocated buffers.
std::shared_ptr<android::BufferQueueProducer> producer;
@@ -373,6 +374,11 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
android::Status::NoError,
VI::ResultOperationFailed);
// Ensure the layer is visible when content is presented.
// Re-assert overlay priority in case clients reset it.
(void)m_container.SetLayerZIndex(layer_id, 100000);
(void)m_container.SetLayerVisibility(layer_id, true);
// We succeeded.
R_SUCCEED();
}
@@ -409,22 +415,51 @@ Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32*
// TODO: this could be optimized
s64 e = -1280 * 768 * 4;
for (auto& block : *m_buffer_page_group) {
u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
u8* const block_start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
u8* ptr = block_start;
u8* const block_end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
for (; start < end; start++) {
*start = 0;
for (; ptr < block_end; ++ptr) {
if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) {
*start = capture_buffer[e];
*ptr = capture_buffer[static_cast<size_t>(e)];
} else {
*ptr = 0;
}
e++;
++e;
}
m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) {
m_system.GPU().InvalidateRegion(addr, end - start);
m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(block_start, scratch, [&](DAddr addr) {
m_system.GPU().InvalidateRegion(addr, block_end - block_start);
});
}
// After writing, present a frame on each active shared layer so it becomes visible.
for (auto& [aruid, session] : m_sessions) {
std::shared_ptr<android::BufferQueueProducer> producer;
if (R_FAILED(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id))) {
continue;
}
s32 slot = -1;
android::Fence fence = android::Fence::NoFence();
if (producer->DequeueBuffer(&slot, &fence, SharedBufferAsync != 0, SharedBufferWidth,
SharedBufferHeight, SharedBufferBlockLinearFormat, 0) !=
android::Status::NoError) {
continue;
}
std::shared_ptr<android::GraphicBuffer> gb;
if (producer->RequestBuffer(slot, &gb) != android::Status::NoError) {
producer->CancelBuffer(slot, android::Fence::NoFence());
continue;
}
android::QueueBufferInput qin{};
android::QueueBufferOutput qout{};
qin.crop = {0, 0, static_cast<s32>(SharedBufferWidth), static_cast<s32>(SharedBufferHeight)};
qin.fence = android::Fence::NoFence();
qin.transform = static_cast<android::NativeWindowTransform>(0);
qin.swap_interval = 1;
(void)producer->QueueBuffer(slot, qin, &qout);
}
*out_was_written = true;
*out_layer_index = 1;
R_SUCCEED();

View File

@@ -57,7 +57,7 @@ class SigHandler {
public:
SigHandler() noexcept {
signal_stack_size = std::max<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
signal_stack_memory = std::malloc(signal_stack_size);
signal_stack_memory = mmap(nullptr, signal_stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
stack_t signal_stack{};
signal_stack.ss_sp = signal_stack_memory;
@@ -89,7 +89,7 @@ public:
}
~SigHandler() noexcept {
std::free(signal_stack_memory);
munmap(signal_stack_memory, signal_stack_size);
}
void AddCodeBlock(u64 offset, CodeBlockInfo cbi) noexcept {

View File

@@ -82,8 +82,7 @@ FP::FPCR A32EmitContext::FPCR(bool fpcr_controlled) const {
A32EmitX64::A32EmitX64(BlockOfCode& code, A32::UserConfig conf, A32::Jit* jit_interface)
: EmitX64(code), conf(std::move(conf)), jit_interface(jit_interface) {
if (conf.fastmem_pointer.has_value())
GenFastmemFallbacks();
GenFastmemFallbacks();
GenTerminalHandlers();
code.PreludeComplete();
ClearFastDispatchTable();
@@ -218,13 +217,13 @@ void A32EmitX64::ClearFastDispatchTable() {
}
void A32EmitX64::GenTerminalHandlers() {
// PC ends up in edi, location_descriptor ends up in rbx
// PC ends up in ebp, location_descriptor ends up in rbx
const auto calculate_location_descriptor = [this] {
// This calculation has to match up with IREmitter::PushRSB
code.mov(ebx, dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)]);
code.shl(rbx, 32);
code.mov(ecx, MJitStateReg(A32::Reg::PC));
code.mov(edi, ecx);
code.mov(ebp, ecx);
code.or_(rbx, rcx);
};
@@ -239,7 +238,7 @@ void A32EmitX64::GenTerminalHandlers() {
code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)], eax);
code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
code.jne(rsb_cache_miss, code.T_NEAR);
code.jne(rsb_cache_miss);
} else {
code.jne(code.GetReturnFromRunCodeAddress());
}
@@ -252,21 +251,20 @@ void A32EmitX64::GenTerminalHandlers() {
terminal_handler_fast_dispatch_hint = code.getCurr<const void*>();
calculate_location_descriptor();
code.L(rsb_cache_miss);
code.mov(r8, reinterpret_cast<u64>(fast_dispatch_table.data()));
//code.mov(r12d, MJitStateReg(A32::Reg::PC));
code.mov(r12, rbx);
code.mov(r12, reinterpret_cast<u64>(fast_dispatch_table.data()));
code.mov(rbp, rbx);
if (code.HasHostFeature(HostFeature::SSE42)) {
code.crc32(r12, r8);
code.crc32(rbp, r12);
}
code.and_(r12d, fast_dispatch_table_mask);
code.lea(r12, ptr[r8 + r12]);
code.cmp(rbx, qword[r12 + offsetof(FastDispatchEntry, location_descriptor)]);
code.jne(fast_dispatch_cache_miss, code.T_NEAR);
code.jmp(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)]);
code.and_(ebp, fast_dispatch_table_mask);
code.lea(rbp, ptr[r12 + rbp]);
code.cmp(rbx, qword[rbp + offsetof(FastDispatchEntry, location_descriptor)]);
code.jne(fast_dispatch_cache_miss);
code.jmp(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)]);
code.L(fast_dispatch_cache_miss);
code.mov(qword[r12 + offsetof(FastDispatchEntry, location_descriptor)], rbx);
code.mov(qword[rbp + offsetof(FastDispatchEntry, location_descriptor)], rbx);
code.LookupBlock();
code.mov(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)], rax);
code.mov(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)], rax);
code.jmp(rax);
PerfMapRegister(terminal_handler_fast_dispatch_hint, code.getCurr(), "a32_terminal_handler_fast_dispatch_hint");

View File

@@ -56,8 +56,7 @@ FP::FPCR A64EmitContext::FPCR(bool fpcr_controlled) const {
A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_interface)
: EmitX64(code), conf(conf), jit_interface{jit_interface} {
GenMemory128Accessors();
if (conf.fastmem_pointer.has_value())
GenFastmemFallbacks();
GenFastmemFallbacks();
GenTerminalHandlers();
code.PreludeComplete();
ClearFastDispatchTable();
@@ -189,14 +188,13 @@ void A64EmitX64::ClearFastDispatchTable() {
}
void A64EmitX64::GenTerminalHandlers() {
// PC ends up in rcx, location_descriptor ends up in rbx
static_assert(std::find(ABI_ALL_CALLEE_SAVE.begin(), ABI_ALL_CALLEE_SAVE.end(), HostLoc::R12) != ABI_ALL_CALLEE_SAVE.end());
// PC ends up in rbp, location_descriptor ends up in rbx
const auto calculate_location_descriptor = [this] {
// This calculation has to match up with A64::LocationDescriptor::UniqueHash
// TODO: Optimization is available here based on known state of fpcr.
code.mov(rdi, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
code.mov(rbp, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
code.mov(rcx, A64::LocationDescriptor::pc_mask);
code.and_(rcx, rdi);
code.and_(rcx, rbp);
code.mov(ebx, dword[code.ABI_JIT_PTR + offsetof(A64JitState, fpcr)]);
code.and_(ebx, A64::LocationDescriptor::fpcr_mask);
code.shl(rbx, A64::LocationDescriptor::fpcr_shift);
@@ -228,21 +226,20 @@ void A64EmitX64::GenTerminalHandlers() {
terminal_handler_fast_dispatch_hint = code.getCurr<const void*>();
calculate_location_descriptor();
code.L(rsb_cache_miss);
code.mov(r8, reinterpret_cast<u64>(fast_dispatch_table.data()));
//code.mov(r12, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
code.mov(r12, rbx);
code.mov(r12, reinterpret_cast<u64>(fast_dispatch_table.data()));
code.mov(rbp, rbx);
if (code.HasHostFeature(HostFeature::SSE42)) {
code.crc32(r12, r8);
code.crc32(rbp, r12);
}
code.and_(r12d, fast_dispatch_table_mask);
code.lea(r12, ptr[r8 + r12]);
code.cmp(rbx, qword[r12 + offsetof(FastDispatchEntry, location_descriptor)]);
code.jne(fast_dispatch_cache_miss, code.T_NEAR);
code.jmp(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)]);
code.and_(ebp, fast_dispatch_table_mask);
code.lea(rbp, ptr[r12 + rbp]);
code.cmp(rbx, qword[rbp + offsetof(FastDispatchEntry, location_descriptor)]);
code.jne(fast_dispatch_cache_miss);
code.jmp(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)]);
code.L(fast_dispatch_cache_miss);
code.mov(qword[r12 + offsetof(FastDispatchEntry, location_descriptor)], rbx);
code.mov(qword[rbp + offsetof(FastDispatchEntry, location_descriptor)], rbx);
code.LookupBlock();
code.mov(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)], rax);
code.mov(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)], rax);
code.jmp(rax);
PerfMapRegister(terminal_handler_fast_dispatch_hint, code.getCurr(), "a64_terminal_handler_fast_dispatch_hint");

View File

@@ -370,7 +370,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
cmp(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], 0);
jne(return_to_caller_mxcsr_already_exited, T_NEAR);
lock(); or_(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], u32(HaltReason::Step));
lock(); or_(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], static_cast<u32>(HaltReason::Step));
SwitchMxcsrOnEntry();
jmp(ABI_PARAM2);

View File

@@ -37,9 +37,6 @@
#include "dynarmic/ir/basic_block.h"
#include "dynarmic/ir/opt_passes.h"
#include "./A32/testenv.h"
#include "./A64/testenv.h"
using namespace Dynarmic;
std::string_view GetNameOfA32Instruction(u32 instruction) {
@@ -68,10 +65,7 @@ void PrintA32Instruction(u32 instruction) {
fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
ArmTestEnv jit_env{};
Dynarmic::A32::UserConfig jit_user_config{};
jit_user_config.callbacks = &jit_env;
Optimization::Optimize(ir_block, jit_user_config, {});
Optimization::Optimize(ir_block, A32::UserConfig{}, {});
fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
}
@@ -86,10 +80,7 @@ void PrintA64Instruction(u32 instruction) {
fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
A64TestEnv jit_env{};
Dynarmic::A64::UserConfig jit_user_config{};
jit_user_config.callbacks = &jit_env;
Optimization::Optimize(ir_block, jit_user_config, {});
Optimization::Optimize(ir_block, A64::UserConfig{}, {});
fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
}
@@ -107,10 +98,7 @@ void PrintThumbInstruction(u32 instruction) {
fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
ThumbTestEnv jit_env{};
Dynarmic::A32::UserConfig jit_user_config{};
jit_user_config.callbacks = &jit_env;
Optimization::Optimize(ir_block, jit_user_config, {});
Optimization::Optimize(ir_block, A32::UserConfig{}, {});
fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
}
@@ -231,7 +219,7 @@ void ExecuteA32Instruction(u32 instruction) {
*(iter->second) = *value;
fmt::print("> {} = 0x{:08x}\n", reg_name, *value);
}
} else if (reg_name.starts_with("m")) {
} else if (reg_name == "mem" || reg_name == "memory") {
fmt::print("address: ");
if (const auto address = get_value()) {
fmt::print("value: ");
@@ -240,7 +228,7 @@ void ExecuteA32Instruction(u32 instruction) {
fmt::print("> mem[0x{:08x}] = 0x{:08x}\n", *address, *value);
}
}
} else if (reg_name == "exit" || reg_name == "end" || reg_name.starts_with("q")) {
} else if (reg_name == "end") {
break;
}
}
@@ -256,7 +244,6 @@ void ExecuteA32Instruction(u32 instruction) {
env.MemoryWrite32(initial_pc + 4, 0xEAFFFFFE); // B +0
cpu.Run();
fmt::print("{}", fmt::join(cpu.Disassemble(), "\n"));
fmt::print("Registers modified:\n");
for (size_t i = 0; i < regs.size(); ++i) {

View File

@@ -20,7 +20,7 @@
namespace Vulkan {
// Prefer small grow rates to avoid saturating the descriptor pool with barely used pipelines
constexpr size_t SETS_GROW_RATE = 16;
//constexpr size_t SETS_GROW_RATE = 32; //test difference between 16 and 32
constexpr s32 SCORE_THRESHOLD = 3;
struct DescriptorBank {
@@ -29,9 +29,12 @@ struct DescriptorBank {
};
bool DescriptorBankInfo::IsSuperset(const DescriptorBankInfo& subset) const noexcept {
return uniform_buffers >= subset.uniform_buffers && storage_buffers >= subset.storage_buffers &&
texture_buffers >= subset.texture_buffers && image_buffers >= subset.image_buffers &&
textures >= subset.textures && images >= subset.images;
return uniform_buffers >= subset.uniform_buffers &&
storage_buffers >= subset.storage_buffers &&
texture_buffers >= subset.texture_buffers &&
image_buffers >= subset.image_buffers &&
textures >= subset.textures &&
images >= subset.images;
}
template <typename Descriptors>
@@ -45,6 +48,19 @@ static u32 Accumulate(const Descriptors& descriptors) {
static DescriptorBankInfo MakeBankInfo(std::span<const Shader::Info> infos) {
DescriptorBankInfo bank;
if (infos.size() == 1) {
const auto& info = infos.front();
const auto acc = [](const auto& ds){ u32 c=0; for (const auto& d: ds) c+=d.count; return c; };
bank.uniform_buffers += acc(info.constant_buffer_descriptors);
bank.storage_buffers += acc(info.storage_buffers_descriptors);
bank.texture_buffers += acc(info.texture_buffer_descriptors);
bank.image_buffers += acc(info.image_buffer_descriptors);
bank.textures += acc(info.texture_descriptors);
bank.images += acc(info.image_descriptors);
bank.score = bank.uniform_buffers + bank.storage_buffers + bank.texture_buffers +
bank.image_buffers + bank.textures + bank.images;
return bank;
}
for (const Shader::Info& info : infos) {
bank.uniform_buffers += Accumulate(info.constant_buffer_descriptors);
bank.storage_buffers += Accumulate(info.storage_buffers_descriptors);
@@ -87,14 +103,35 @@ static void AllocatePool(const Device& device, DescriptorBank& bank) {
}));
}
static size_t GetGrowRate() {
if (Settings::getDebugKnobAt(0))
return 8;
else if (Settings::getDebugKnobAt(1))
return 16;
else if (Settings::getDebugKnobAt(2))
return 24;
else if (Settings::getDebugKnobAt(3))
return 32;
else if (Settings::getDebugKnobAt(4))
return 40;
else if (Settings::getDebugKnobAt(5))
return 48;
else if (Settings::getDebugKnobAt(6))
return 56;
else if (Settings::getDebugKnobAt(7))
return 64;
else
return 16;
}
DescriptorAllocator::DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_,
DescriptorBank& bank_, VkDescriptorSetLayout layout_)
: ResourcePool(master_semaphore_, SETS_GROW_RATE), device{&device_}, bank{&bank_},
layout{layout_} {}
: ResourcePool(master_semaphore_, /*SETS_GROW_RATE*/ GetGrowRate()), device{&device_}, bank{&bank_},
layout{layout_}, grow_rate{GetGrowRate()} {}
VkDescriptorSet DescriptorAllocator::Commit() {
const size_t index = CommitResource();
return sets[index / SETS_GROW_RATE][index % SETS_GROW_RATE];
return sets[index / grow_rate][index % grow_rate];
}
void DescriptorAllocator::Allocate(size_t begin, size_t end) {
@@ -102,13 +139,22 @@ void DescriptorAllocator::Allocate(size_t begin, size_t end) {
}
vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) {
const std::vector<VkDescriptorSetLayout> layouts(count, layout);
std::array<VkDescriptorSetLayout, 64> stack{};
const VkDescriptorSetLayout* p_layouts = nullptr;
std::vector<VkDescriptorSetLayout> heap;
if (count <= stack.size()) {
stack.fill(layout);
p_layouts = stack.data();
} else {
heap.assign(count, layout);
p_layouts = heap.data();
}
VkDescriptorSetAllocateInfo allocate_info{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.pNext = nullptr,
.descriptorPool = *bank->pools.back(),
.descriptorSetCount = static_cast<u32>(count),
.pSetLayouts = layouts.data(),
.pSetLayouts = p_layouts,
};
vk::DescriptorSets new_sets = bank->pools.back().Allocate(allocate_info);
if (!new_sets.IsOutOfPoolMemory()) {
@@ -146,21 +192,58 @@ DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout,
}
DescriptorBank& DescriptorPool::Bank(const DescriptorBankInfo& reqs) {
{
std::scoped_lock lk(cache_mutex);
DescriptorBank* best = nullptr; u64 best_stamp = 0;
for (const auto& e : cache_) {
if (!e.bank) continue;
if (std::abs(e.info.score - reqs.score) < SCORE_THRESHOLD && e.info.IsSuperset(reqs)) {
if (e.stamp >= best_stamp) { best_stamp = e.stamp; best = e.bank; }
}
}
if (best) return *best;
}
std::shared_lock read_lock{banks_mutex};
const auto it = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) {
return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs);
});
if (it != bank_infos.end()) {
return *banks[std::distance(bank_infos.begin(), it)].get();
DescriptorBank& found = *banks[std::distance(bank_infos.begin(), it)].get();
read_lock.unlock();
// update cache
std::scoped_lock lk(cache_mutex);
size_t victim = 0; u64 oldest = UINT64_MAX;
for (size_t i=0;i<cache_.size();++i) if (cache_[i].stamp < oldest) { oldest = cache_[i].stamp; victim = i; }
cache_[victim] = CacheEntry{found.info, &found, ++cache_tick_};
return found;
}
read_lock.unlock();
std::unique_lock write_lock{banks_mutex};
auto it2 = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) {
return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs);
});
if (it2 != bank_infos.end()) {
DescriptorBank& found = *banks[std::distance(bank_infos.begin(), it2)].get();
// update cache
std::scoped_lock lk(cache_mutex);
size_t victim = 0; u64 oldest = UINT64_MAX;
for (size_t i=0;i<cache_.size();++i) if (cache_[i].stamp < oldest) { oldest = cache_[i].stamp; victim = i; }
cache_[victim] = CacheEntry{found.info, &found, ++cache_tick_};
return found;
}
bank_infos.push_back(reqs);
auto& bank = *banks.emplace_back(std::make_unique<DescriptorBank>());
bank.info = reqs;
AllocatePool(device, bank);
// update cache
{
std::scoped_lock lk(cache_mutex);
size_t victim = 0; u64 oldest = UINT64_MAX;
for (size_t i=0;i<cache_.size();++i) if (cache_[i].stamp < oldest) { oldest = cache_[i].stamp; victim = i; }
cache_[victim] = CacheEntry{bank.info, &bank, ++cache_tick_};
}
return bank;
}

View File

@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -6,7 +9,8 @@
#include <shared_mutex>
#include <span>
#include <vector>
#include <array>
#include <mutex>
#include "shader_recompiler/shader_info.h"
#include "video_core/renderer_vulkan/vk_resource_pool.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -58,6 +62,7 @@ private:
VkDescriptorSetLayout layout{};
std::vector<vk::DescriptorSets> sets;
size_t grow_rate = 32;
};
class DescriptorPool {
@@ -75,6 +80,14 @@ public:
private:
DescriptorBank& Bank(const DescriptorBankInfo& reqs);
struct CacheEntry {
DescriptorBankInfo info{};
DescriptorBank* bank{nullptr};
u64 stamp{0};
};
std::mutex cache_mutex{};
std::array<CacheEntry, 8> cache_{}; //test and then adjust
u64 cache_tick_{0};
const Device& device;
MasterSemaphore& master_semaphore;

View File

@@ -146,7 +146,7 @@ PresentManager::PresentManager(const vk::Instance& instance_,
.pNext = nullptr,
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
});
free_queue.push_back(&frame);
free_queue.push(&frame);
}
if (use_present_thread) {
@@ -164,7 +164,7 @@ Frame* PresentManager::GetRenderFrame() {
// Take the frame from the queue
Frame* frame = free_queue.front();
free_queue.pop_front();
free_queue.pop();
// Wait for the presentation to be finished so all frame resources are free
frame->present_done.Wait();
@@ -174,17 +174,18 @@ Frame* PresentManager::GetRenderFrame() {
}
void PresentManager::Present(Frame* frame) {
if (use_present_thread) {
scheduler.Record([this, frame](vk::CommandBuffer) {
std::unique_lock lock{queue_mutex};
present_queue.push_back(frame);
frame_cv.notify_one();
});
} else {
if (!use_present_thread) {
scheduler.WaitWorker();
CopyToSwapchain(frame);
free_queue.push_back(frame);
free_queue.push(frame);
return;
}
scheduler.Record([this, frame](vk::CommandBuffer) {
std::unique_lock lock{queue_mutex};
present_queue.push(frame);
frame_cv.notify_one();
});
}
void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format,
@@ -276,25 +277,29 @@ void PresentManager::PresentThread(std::stop_token token) {
Common::SetCurrentThreadName("VulkanPresent");
while (!token.stop_requested()) {
std::unique_lock lock{queue_mutex};
// Wait for presentation frames
frame_cv.wait(lock, token, [this] { return !present_queue.empty(); });
if (!token.stop_requested()) {
// Take the frame and notify anyone waiting
Frame* frame = present_queue.front();
present_queue.pop_front();
frame_cv.notify_one();
// By exchanging the lock ownership we take the swapchain lock
// before the queue lock goes out of scope. This way the swapchain
// lock in WaitPresent is guaranteed to occur after here.
std::exchange(lock, std::unique_lock{swapchain_mutex});
CopyToSwapchain(frame);
// Free the frame for reuse
std::scoped_lock fl{free_mutex};
free_queue.push_back(frame);
free_cv.notify_one();
if (token.stop_requested()) {
return;
}
// Take the frame and notify anyone waiting
Frame* frame = present_queue.front();
present_queue.pop();
frame_cv.notify_one();
// By exchanging the lock ownership we take the swapchain lock
// before the queue lock goes out of scope. This way the swapchain
// lock in WaitPresent is guaranteed to occur after here.
std::exchange(lock, std::unique_lock{swapchain_mutex});
CopyToSwapchain(frame);
// Free the frame for reuse
std::scoped_lock fl{free_mutex};
free_queue.push(frame);
free_cv.notify_one();
}
}

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,7 +5,7 @@
#include <condition_variable>
#include <mutex>
#include <boost/container/deque.hpp>
#include <queue>
#include "common/common_types.h"
#include "common/polyfill_thread.h"
@@ -91,8 +88,8 @@ private:
#endif
vk::CommandPool cmdpool;
std::vector<Frame> frames;
boost::container::deque<Frame*> present_queue;
boost::container::deque<Frame*> free_queue;
std::queue<Frame*> present_queue;
std::queue<Frame*> free_queue;
std::condition_variable_any frame_cv;
std::condition_variable free_cv;
std::mutex swapchain_mutex;

View File

@@ -20,12 +20,18 @@
namespace Vulkan {
namespace {
[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld, std::vector<VkExtensionProperties> const& properties, std::span<const char* const> extensions) {
[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld,
std::span<const char* const> extensions) {
const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld);
if (!properties) {
LOG_ERROR(Render_Vulkan, "Failed to query extension properties");
return false;
}
for (const char* extension : extensions) {
const auto it = std::ranges::find_if(properties, [extension](const auto& prop) {
const auto it = std::ranges::find_if(*properties, [extension](const auto& prop) {
return std::strcmp(extension, prop.extensionName) == 0;
});
if (it == properties.end()) {
if (it == properties->end()) {
LOG_ERROR(Render_Vulkan, "Required instance extension {} is not available", extension);
return false;
}
@@ -72,16 +78,14 @@ namespace {
if (window_type != Core::Frontend::WindowSystemType::Headless) {
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
}
if (auto const properties = vk::EnumerateInstanceExtensionProperties(dld); properties) {
#ifdef __APPLE__
if (AreExtensionsSupported(dld, *properties, std::array{VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME}))
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
if (AreExtensionsSupported(dld, std::array{VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME})) {
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
}
#endif
if (enable_validation && AreExtensionsSupported(dld, *properties, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME}))
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
// VK_EXT_surface_maintenance1 is required for VK_EXT_swapchain_maintenance1
if (window_type != Core::Frontend::WindowSystemType::Headless && AreExtensionsSupported(dld, *properties, std::array{VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME}))
extensions.push_back(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
if (enable_validation &&
AreExtensionsSupported(dld, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME})) {
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
return extensions;
}
@@ -129,10 +133,11 @@ vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceD
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers");
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
std::vector<const char*> const extensions = RequiredExtensions(dld, window_type, enable_validation);
auto const properties = vk::EnumerateInstanceExtensionProperties(dld);
if (!properties || !AreExtensionsSupported(dld, *properties, extensions))
const std::vector<const char*> extensions =
RequiredExtensions(dld, window_type, enable_validation);
if (!AreExtensionsSupported(dld, extensions)) {
throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT);
}
std::vector<const char*> layers = Layers(enable_validation);
RemoveUnavailableLayers(dld, layers);

View File

@@ -128,7 +128,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<item>
<widget class="QLabel" name="labelLinks">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://eden-emulator.github.io/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Website&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://git.eden-emu.dev&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Source Code&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://git.eden-emu.dev/eden-emu/eden/activity/contributors&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Contributors&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://discord.gg/HstXbPch7X&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Discord&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://stt.gg/qKgFEAbH&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Stoat&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://nitter.poast.org/edenemuofficial&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Twitter&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;License&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://eden-emulator.github.io/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Website&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://git.eden-emu.dev&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Source Code&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://git.eden-emu.dev/eden-emu/eden/activity/contributors&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Contributors&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://discord.gg/HstXbPch7X&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Discord&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://rvlt.gg/qKgFEAbH&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Revolt&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://nitter.poast.org/edenemuofficial&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Twitter&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;License&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>

View File

@@ -1900,7 +1900,7 @@ bool MainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPar
tr("Error while loading ROM! %1", "%1 signifies a numeric error code.")
.arg(QString::fromStdString(error_code));
const auto description =
tr("%1<br>Please redump your files or ask on Discord/Stoat for help.",
tr("%1<br>Please redump your files or ask on Discord/Revolt for help.",
"%1 signifies an error string.")
.arg(QString::fromStdString(
GetResultStatusString(static_cast<Loader::ResultStatus>(error_id))));

59
tools/dtrace-tool.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/local/bin/bash -ex
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# Basic script to run dtrace sampling over the program (requires Flamegraph)
# Usage is either running as: ./dtrace-tool.sh pid (then input the pid of the process)
# Or just run directly with: ./dtrace-tool.sh <command>
FLAMEGRAPH_DIR=".."
fail() {
printf '%s\n' "$1" >&2
exit "${2-1}"
}
[ -f $FLAMEGRAPH_DIR/FlameGraph/stackcollapse.pl ] || fail 'Where is flamegraph?'
#[ which dtrace ] || fail 'Needs DTrace installed'
read -r "Sampling Hz [800]: " TRACE_CFG_HZ
if [ -z "${TRACE_CFG_HZ}" ]; then
TRACE_CFG_HZ=800
fi
read -r "Sampling time [5] sec: " TRACE_CFG_TIME
if [ -z "${TRACE_CFG_TIME}" ]; then
TRACE_CFG_TIME=5
fi
TRACE_FILE=dtrace-out.user_stacks
TRACE_FOLD=dtrace-out.fold
TRACE_SVG=dtrace-out.svg
ps
if [ "$1" = 'pid' ]; then
read -r "PID: " TRACE_CFG_PID
sudo echo 'Sudo!'
else
if [ -f "$1" ] && [ "$1" ]; then
fail 'Usage: ./tools/dtrace-profile.sh <path to program>'
fi
printf "Executing: "
echo "$@"
sudo echo 'Sudo!'
"$@" &
TRACE_CFG_PID=$!
fi
TRACE_PROBE="profile-${TRACE_CFG_HZ} /pid == ${TRACE_CFG_PID} && arg1/ { @[ustack()] = count(); } tick-${TRACE_CFG_TIME}s { exit(0); }"
rm -- $TRACE_SVG || echo 'Skip'
sudo dtrace -x ustackframes=100 -Z -n "$TRACE_PROBE" -o $TRACE_FILE 2>/dev/null || exit
perl $FLAMEGRAPH_DIR/FlameGraph/stackcollapse.pl $TRACE_FILE > $TRACE_FOLD || exit
perl $FLAMEGRAPH_DIR/FlameGraph/flamegraph.pl $TRACE_FOLD > $TRACE_SVG || exit
sudo chmod 0666 $TRACE_FILE
rm -- $TRACE_FILE $TRACE_FOLD