Compare commits
22 Commits
android-23
...
android-23
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50135e480a | ||
|
|
8495adfed5 | ||
|
|
0b624b8bfa | ||
|
|
98d0ccc78c | ||
|
|
bfc714e16c | ||
|
|
18fa807cd3 | ||
|
|
d5a7230036 | ||
|
|
afb77e967f | ||
|
|
71e59bdcd8 | ||
|
|
0a1283f94f | ||
|
|
f049453dd6 | ||
|
|
cac37a6f6e | ||
|
|
263dfa95e4 | ||
|
|
bc9711cb1e | ||
|
|
b4d88a7bb4 | ||
|
|
ae833aa9c0 | ||
|
|
fa47ac1c9f | ||
|
|
f296a9ce9a | ||
|
|
0d5a3abeae | ||
|
|
accccc0cbf | ||
|
|
01ba6cf610 | ||
|
|
4841dc0b74 |
@@ -1,13 +1,12 @@
|
||||
| Pull Request | Commit | Title | Author | Merged? |
|
||||
|----|----|----|----|----|
|
||||
| [12461](https://github.com/yuzu-emu/yuzu//pull/12461) | [`4c08a0e6d`](https://github.com/yuzu-emu/yuzu//pull/12461/files) | Rework Nvdec and VIC to fix out-of-order videos, and speed up decoding. | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
||||
| [12461](https://github.com/yuzu-emu/yuzu//pull/12461) | [`54eb8dcc9`](https://github.com/yuzu-emu/yuzu//pull/12461/files) | Rework Nvdec and VIC to fix out-of-order videos, and speed up decoding. | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
||||
| [12749](https://github.com/yuzu-emu/yuzu//pull/12749) | [`aad4b0d6f`](https://github.com/yuzu-emu/yuzu//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12756](https://github.com/yuzu-emu/yuzu//pull/12756) | [`cd3de0848`](https://github.com/yuzu-emu/yuzu//pull/12756/files) | general: applet multiprocess | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12903](https://github.com/yuzu-emu/yuzu//pull/12903) | [`f296a9ce9`](https://github.com/yuzu-emu/yuzu//pull/12903/files) | shader_recompiler: use only ConstOffset for OpImageFetch | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12914](https://github.com/yuzu-emu/yuzu//pull/12914) | [`fa47ac1c9`](https://github.com/yuzu-emu/yuzu//pull/12914/files) | VideoCore Refactor Part 1. | [FernandoS27](https://github.com/FernandoS27/) | Yes |
|
||||
| [12920](https://github.com/yuzu-emu/yuzu//pull/12920) | [`62fc6d5c3`](https://github.com/yuzu-emu/yuzu//pull/12920/files) | android: Move JNI setup and helpers to common | [t895](https://github.com/t895/) | Yes |
|
||||
| [12920](https://github.com/yuzu-emu/yuzu//pull/12920) | [`2600ac65c`](https://github.com/yuzu-emu/yuzu//pull/12920/files) | android: Move JNI setup and helpers to common | [t895](https://github.com/t895/) | Yes |
|
||||
| [12951](https://github.com/yuzu-emu/yuzu//pull/12951) | [`fee263c59`](https://github.com/yuzu-emu/yuzu//pull/12951/files) | ipc: additional fixes | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12953](https://github.com/yuzu-emu/yuzu//pull/12953) | [`ae833aa9c`](https://github.com/yuzu-emu/yuzu//pull/12953/files) | SMMU: Ensure the backing address range matches the current | [FernandoS27](https://github.com/FernandoS27/) | Yes |
|
||||
| [12955](https://github.com/yuzu-emu/yuzu//pull/12955) | [`8d2ad3d8f`](https://github.com/yuzu-emu/yuzu//pull/12955/files) | dmnt: cheat: Avoid invalidating cache on 32bit | [german77](https://github.com/german77/) | Yes |
|
||||
| [12964](https://github.com/yuzu-emu/yuzu//pull/12964) | [`d93459db6`](https://github.com/yuzu-emu/yuzu//pull/12964/files) | android: Remove foreground service | [t895](https://github.com/t895/) | Yes |
|
||||
|
||||
|
||||
End of merge log. You can find the original README.md below the break.
|
||||
|
||||
@@ -259,13 +259,20 @@ fun runGitCommand(command: List<String>): String {
|
||||
}
|
||||
|
||||
fun getGitVersion(): String {
|
||||
val gitVersion = runGitCommand(listOf("git", "describe", "--always", "--long"))
|
||||
val gitVersion = runGitCommand(
|
||||
listOf(
|
||||
"git",
|
||||
"describe",
|
||||
"--always",
|
||||
"--long"
|
||||
)
|
||||
).replace(Regex("(-0)?-[^-]+$"), "")
|
||||
val versionName = if (System.getenv("GITHUB_ACTIONS") != null) {
|
||||
System.getenv("GIT_TAG_NAME") ?: gitVersion
|
||||
} else {
|
||||
gitVersion
|
||||
}
|
||||
return versionName.replace(Regex("(-0)?-[^-]+$"), "").ifEmpty { "0.0" }
|
||||
return versionName.ifEmpty { "0.0" }
|
||||
}
|
||||
|
||||
fun getGitHash(): String =
|
||||
|
||||
@@ -12,8 +12,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<uses-feature android:name="android.hardware.vulkan.version" android:version="0x401000" android:required="true" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
@@ -80,10 +78,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
android:resource="@xml/nfc_tech_filter" />
|
||||
</activity>
|
||||
|
||||
<service android:name="org.yuzu.yuzu_emu.utils.ForegroundService" android:foregroundServiceType="specialUse">
|
||||
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="Keep emulation running in background"/>
|
||||
</service>
|
||||
|
||||
<provider
|
||||
android:name=".features.DocumentProvider"
|
||||
android:authorities="${applicationId}.user"
|
||||
|
||||
@@ -17,17 +17,6 @@ fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
|
||||
|
||||
class YuzuApplication : Application() {
|
||||
private fun createNotificationChannels() {
|
||||
val emulationChannel = NotificationChannel(
|
||||
getString(R.string.emulation_notification_channel_id),
|
||||
getString(R.string.emulation_notification_channel_name),
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
emulationChannel.description = getString(
|
||||
R.string.emulation_notification_channel_description
|
||||
)
|
||||
emulationChannel.setSound(null, null)
|
||||
emulationChannel.vibrationPattern = null
|
||||
|
||||
val noticeChannel = NotificationChannel(
|
||||
getString(R.string.notice_notification_channel_id),
|
||||
getString(R.string.notice_notification_channel_name),
|
||||
@@ -39,7 +28,6 @@ class YuzuApplication : Application() {
|
||||
// Register the channel with the system; you can't change the importance
|
||||
// or other notification behaviors after this
|
||||
val notificationManager = getSystemService(NotificationManager::class.java)
|
||||
notificationManager.createNotificationChannel(emulationChannel)
|
||||
notificationManager.createNotificationChannel(noticeChannel)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
package org.yuzu.yuzu_emu.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.PendingIntent
|
||||
import android.app.PictureInPictureParams
|
||||
import android.app.RemoteAction
|
||||
@@ -45,7 +44,6 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.model.EmulationViewModel
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.utils.ForegroundService
|
||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import org.yuzu.yuzu_emu.utils.MemoryUtil
|
||||
@@ -74,11 +72,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
|
||||
private val emulationViewModel: EmulationViewModel by viewModels()
|
||||
|
||||
override fun onDestroy() {
|
||||
stopForegroundService(this)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Log.gameLaunched = true
|
||||
ThemeHelper.setTheme(this)
|
||||
@@ -125,10 +118,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
|
||||
// Start a foreground service to prevent the app from getting killed in the background
|
||||
val startIntent = Intent(this, ForegroundService::class.java)
|
||||
startForegroundService(startIntent)
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||
@@ -481,12 +470,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
activity.startActivity(launcher)
|
||||
}
|
||||
|
||||
fun stopForegroundService(activity: Activity) {
|
||||
val startIntent = Intent(activity, ForegroundService::class.java)
|
||||
startIntent.action = ForegroundService.ACTION_STOP
|
||||
activity.startForegroundService(startIntent)
|
||||
}
|
||||
|
||||
private fun areCoordinatesOutside(view: View?, x: Float, y: Float): Boolean {
|
||||
if (view == null) {
|
||||
return true
|
||||
|
||||
@@ -34,7 +34,6 @@ import kotlinx.coroutines.launch
|
||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||
import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment
|
||||
@@ -177,9 +176,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
}
|
||||
}
|
||||
|
||||
// Dismiss previous notifications (should not happen unless a crash occurred)
|
||||
EmulationActivity.stopForegroundService(this)
|
||||
|
||||
setInsets()
|
||||
}
|
||||
|
||||
@@ -298,11 +294,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
EmulationActivity.stopForegroundService(this)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||
|
||||
/**
|
||||
* A service that shows a permanent notification in the background to avoid the app getting
|
||||
* cleared from memory by the system.
|
||||
*/
|
||||
class ForegroundService : Service() {
|
||||
companion object {
|
||||
const val EMULATION_RUNNING_NOTIFICATION = 0x1000
|
||||
|
||||
const val ACTION_STOP = "stop"
|
||||
}
|
||||
|
||||
private fun showRunningNotification() {
|
||||
// Intent is used to resume emulation if the notification is clicked
|
||||
val contentIntent = PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
Intent(this, EmulationActivity::class.java),
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
val builder =
|
||||
NotificationCompat.Builder(this, getString(R.string.emulation_notification_channel_id))
|
||||
.setSmallIcon(R.drawable.ic_stat_notification_logo)
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setContentText(getString(R.string.emulation_notification_running))
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setOngoing(true)
|
||||
.setVibrate(null)
|
||||
.setSound(null)
|
||||
.setContentIntent(contentIntent)
|
||||
startForeground(EMULATION_RUNNING_NOTIFICATION, builder.build())
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
showRunningNotification()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
if (intent == null) {
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
if (intent.action == ACTION_STOP) {
|
||||
NotificationManagerCompat.from(this).cancel(EMULATION_RUNNING_NOTIFICATION)
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
stopSelfResult(startId)
|
||||
}
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
NotificationManagerCompat.from(this).cancel(EMULATION_RUNNING_NOTIFICATION)
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,6 @@
|
||||
<!-- General application strings -->
|
||||
<string name="app_name" translatable="false">yuzu</string>
|
||||
<string name="app_disclaimer">This software will run games for the Nintendo Switch game console. No game titles or keys are included.<br /><br />Before you begin, please locate your <![CDATA[<b> prod.keys </b>]]> file on your device storage.<br /><br /><![CDATA[<a href="https://yuzu-emu.org/help/quickstart">Learn more</a>]]></string>
|
||||
<string name="emulation_notification_channel_name">Emulation is Active</string>
|
||||
<string name="emulation_notification_channel_id" translatable="false">emulationIsActive</string>
|
||||
<string name="emulation_notification_channel_description">Shows a persistent notification when emulation is running.</string>
|
||||
<string name="emulation_notification_running">yuzu is running</string>
|
||||
<string name="notice_notification_channel_name">Notices and errors</string>
|
||||
<string name="notice_notification_channel_id" translatable="false">noticesAndErrors</string>
|
||||
<string name="notice_notification_channel_description">Shows notifications when something goes wrong.</string>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "common/android/id_cache.h"
|
||||
#include "common/string_util.h"
|
||||
#include "id_cache.h"
|
||||
|
||||
namespace Common::Android {
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "applets/software_keyboard.h"
|
||||
#include "common/android/id_cache.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/fs/fs_android.h"
|
||||
#include "id_cache.h"
|
||||
#include "video_core/rasterizer_interface.h"
|
||||
|
||||
static JavaVM* s_java_vm;
|
||||
|
||||
@@ -44,7 +44,7 @@ bool IsContentUri(const std::string& path) {
|
||||
return path.find(prefix) == 0;
|
||||
}
|
||||
|
||||
int OpenContentUri(const std::string& filepath, OpenMode openmode) {
|
||||
s32 OpenContentUri(const std::string& filepath, OpenMode openmode) {
|
||||
if (s_open_content_uri == nullptr)
|
||||
return -1;
|
||||
|
||||
@@ -63,7 +63,7 @@ int OpenContentUri(const std::string& filepath, OpenMode openmode) {
|
||||
return env->CallStaticIntMethod(native_library, s_open_content_uri, j_filepath, j_mode);
|
||||
}
|
||||
|
||||
std::uint64_t GetSize(const std::string& filepath) {
|
||||
u64 GetSize(const std::string& filepath) {
|
||||
if (s_get_size == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ void LoopProcess(Core::System& system) {
|
||||
server_manager->RegisterNamedService(
|
||||
"hid:sys", std::make_shared<IHidSystemServer>(system, resource_manager, firmware_settings));
|
||||
|
||||
server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system));
|
||||
server_manager->RegisterNamedService("hidbus", std::make_shared<Hidbus>(system));
|
||||
|
||||
server_manager->RegisterNamedService("irs", std::make_shared<IRS::IRS>(system));
|
||||
server_manager->RegisterNamedService("irs:sys", std::make_shared<IRS::IRS_SYS>(system));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/hid/hidbus.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
@@ -22,25 +23,25 @@ namespace Service::HID {
|
||||
// (15ms, 66Hz)
|
||||
constexpr auto hidbus_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000};
|
||||
|
||||
HidBus::HidBus(Core::System& system_)
|
||||
Hidbus::Hidbus(Core::System& system_)
|
||||
: ServiceFramework{system_, "hidbus"}, service_context{system_, service_name} {
|
||||
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, &HidBus::GetBusHandle, "GetBusHandle"},
|
||||
{2, &HidBus::IsExternalDeviceConnected, "IsExternalDeviceConnected"},
|
||||
{3, &HidBus::Initialize, "Initialize"},
|
||||
{4, &HidBus::Finalize, "Finalize"},
|
||||
{5, &HidBus::EnableExternalDevice, "EnableExternalDevice"},
|
||||
{6, &HidBus::GetExternalDeviceId, "GetExternalDeviceId"},
|
||||
{7, &HidBus::SendCommandAsync, "SendCommandAsync"},
|
||||
{8, &HidBus::GetSendCommandAsynceResult, "GetSendCommandAsynceResult"},
|
||||
{9, &HidBus::SetEventForSendCommandAsycResult, "SetEventForSendCommandAsycResult"},
|
||||
{10, &HidBus::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
|
||||
{11, &HidBus::EnableJoyPollingReceiveMode, "EnableJoyPollingReceiveMode"},
|
||||
{12, &HidBus::DisableJoyPollingReceiveMode, "DisableJoyPollingReceiveMode"},
|
||||
{1, C<&Hidbus::GetBusHandle>, "GetBusHandle"},
|
||||
{2, C<&Hidbus::IsExternalDeviceConnected>, "IsExternalDeviceConnected"},
|
||||
{3, C<&Hidbus::Initialize>, "Initialize"},
|
||||
{4, C<&Hidbus::Finalize>, "Finalize"},
|
||||
{5, C<&Hidbus::EnableExternalDevice>, "EnableExternalDevice"},
|
||||
{6, C<&Hidbus::GetExternalDeviceId>, "GetExternalDeviceId"},
|
||||
{7, C<&Hidbus::SendCommandAsync>, "SendCommandAsync"},
|
||||
{8, C<&Hidbus::GetSendCommandAsynceResult>, "GetSendCommandAsynceResult"},
|
||||
{9, C<&Hidbus::SetEventForSendCommandAsycResult>, "SetEventForSendCommandAsycResult"},
|
||||
{10, C<&Hidbus::GetSharedMemoryHandle>, "GetSharedMemoryHandle"},
|
||||
{11, C<&Hidbus::EnableJoyPollingReceiveMode>, "EnableJoyPollingReceiveMode"},
|
||||
{12, C<&Hidbus::DisableJoyPollingReceiveMode>, "DisableJoyPollingReceiveMode"},
|
||||
{13, nullptr, "GetPollingData"},
|
||||
{14, &HidBus::SetStatusManagerType, "SetStatusManagerType"},
|
||||
{14, C<&Hidbus::SetStatusManagerType>, "SetStatusManagerType"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@@ -60,11 +61,11 @@ HidBus::HidBus(Core::System& system_)
|
||||
hidbus_update_event);
|
||||
}
|
||||
|
||||
HidBus::~HidBus() {
|
||||
Hidbus::~Hidbus() {
|
||||
system.CoreTiming().UnscheduleEvent(hidbus_update_event);
|
||||
}
|
||||
|
||||
void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
|
||||
void Hidbus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
|
||||
if (is_hidbus_enabled) {
|
||||
for (std::size_t i = 0; i < devices.size(); ++i) {
|
||||
if (!devices[i].is_device_initialized) {
|
||||
@@ -84,7 +85,7 @@ void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) const {
|
||||
std::optional<std::size_t> Hidbus::GetDeviceIndexFromHandle(BusHandle handle) const {
|
||||
for (std::size_t i = 0; i < devices.size(); ++i) {
|
||||
const auto& device_handle = devices[i].handle;
|
||||
if (handle.abstracted_pad_id == device_handle.abstracted_pad_id &&
|
||||
@@ -98,20 +99,11 @@ std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) co
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
Core::HID::NpadIdType npad_id;
|
||||
INSERT_PADDING_WORDS_NOINIT(1);
|
||||
BusType bus_type;
|
||||
u64 applet_resource_user_id;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}",
|
||||
parameters.npad_id, parameters.bus_type, parameters.applet_resource_user_id);
|
||||
Result Hidbus::GetBusHandle(Out<bool> out_is_valid, Out<BusHandle> out_bus_handle,
|
||||
Core::HID::NpadIdType npad_id, BusType bus_type,
|
||||
AppletResourceUserId aruid) {
|
||||
LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", npad_id,
|
||||
bus_type, aruid.pid);
|
||||
|
||||
bool is_handle_found = 0;
|
||||
std::size_t handle_index = 0;
|
||||
@@ -121,8 +113,8 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
||||
if (!handle.is_valid) {
|
||||
continue;
|
||||
}
|
||||
if (static_cast<Core::HID::NpadIdType>(handle.player_number) == parameters.npad_id &&
|
||||
handle.bus_type_id == static_cast<u8>(parameters.bus_type)) {
|
||||
if (handle.player_number.As<Core::HID::NpadIdType>() == npad_id &&
|
||||
handle.bus_type_id == static_cast<u8>(bus_type)) {
|
||||
is_handle_found = true;
|
||||
handle_index = i;
|
||||
break;
|
||||
@@ -135,388 +127,231 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) {
|
||||
if (devices[i].handle.is_valid) {
|
||||
continue;
|
||||
}
|
||||
devices[i].handle = {
|
||||
.abstracted_pad_id = static_cast<u8>(i),
|
||||
.internal_index = static_cast<u8>(i),
|
||||
.player_number = static_cast<u8>(parameters.npad_id),
|
||||
.bus_type_id = static_cast<u8>(parameters.bus_type),
|
||||
.is_valid = true,
|
||||
};
|
||||
devices[i].handle.raw = 0;
|
||||
devices[i].handle.abstracted_pad_id.Assign(i);
|
||||
devices[i].handle.internal_index.Assign(i);
|
||||
devices[i].handle.player_number.Assign(static_cast<u8>(npad_id));
|
||||
devices[i].handle.bus_type_id.Assign(static_cast<u8>(bus_type));
|
||||
devices[i].handle.is_valid.Assign(true);
|
||||
handle_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct OutData {
|
||||
bool is_valid;
|
||||
INSERT_PADDING_BYTES(7);
|
||||
BusHandle handle;
|
||||
};
|
||||
static_assert(sizeof(OutData) == 0x10, "OutData has incorrect size.");
|
||||
|
||||
const OutData out_data{
|
||||
.is_valid = true,
|
||||
.handle = devices[handle_index].handle,
|
||||
};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(out_data);
|
||||
*out_is_valid = true;
|
||||
*out_bus_handle = devices[handle_index].handle;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
|
||||
Result Hidbus::IsExternalDeviceConnected(Out<bool> out_is_connected, BusHandle bus_handle) {
|
||||
LOG_INFO(Service_HID,
|
||||
"Called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
||||
"player_number={}, is_valid={}",
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
||||
bus_handle.player_number, bus_handle.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
const auto& device = devices[device_index.value()].device;
|
||||
const bool is_attached = device->IsDeviceActivated();
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(is_attached);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
*out_is_connected = devices[device_index.value()].device->IsDeviceActivated();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void HidBus::Initialize(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
Result Hidbus::Initialize(BusHandle bus_handle, AppletResourceUserId aruid) {
|
||||
LOG_INFO(Service_HID,
|
||||
"called, abstracted_pad_id={} bus_type={} internal_index={} "
|
||||
"player_number={} is_valid={}, applet_resource_user_id={}",
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id);
|
||||
bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
||||
bus_handle.player_number, bus_handle.is_valid, aruid.pid);
|
||||
|
||||
is_hidbus_enabled = true;
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
const auto entry_index = devices[device_index.value()].handle.internal_index;
|
||||
auto& cur_entry = hidbus_status.entries[entry_index];
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
if (bus_handle_.internal_index == 0 && Settings::values.enable_ring_controller) {
|
||||
MakeDevice<RingController>(bus_handle_);
|
||||
devices[device_index.value()].is_device_initialized = true;
|
||||
devices[device_index.value()].device->ActivateDevice();
|
||||
cur_entry.is_in_focus = true;
|
||||
cur_entry.is_connected = true;
|
||||
cur_entry.is_connected_result = ResultSuccess;
|
||||
cur_entry.is_enabled = false;
|
||||
cur_entry.is_polling_mode = false;
|
||||
} else {
|
||||
MakeDevice<HidbusStubbed>(bus_handle_);
|
||||
devices[device_index.value()].is_device_initialized = true;
|
||||
cur_entry.is_in_focus = true;
|
||||
cur_entry.is_connected = false;
|
||||
cur_entry.is_connected_result = ResultSuccess;
|
||||
cur_entry.is_enabled = false;
|
||||
cur_entry.is_polling_mode = false;
|
||||
}
|
||||
|
||||
std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
||||
sizeof(hidbus_status));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
}
|
||||
|
||||
void HidBus::Finalize(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_INFO(Service_HID,
|
||||
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
||||
"player_number={}, is_valid={}, applet_resource_user_id={}",
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
|
||||
if (device_index) {
|
||||
const auto entry_index = devices[device_index.value()].handle.internal_index;
|
||||
auto& cur_entry = hidbus_status.entries[entry_index];
|
||||
auto& device = devices[device_index.value()].device;
|
||||
devices[device_index.value()].is_device_initialized = false;
|
||||
device->DeactivateDevice();
|
||||
const auto entry_index = devices[device_index.value()].handle.internal_index;
|
||||
auto& cur_entry = hidbus_status.entries[entry_index];
|
||||
|
||||
if (bus_handle.internal_index == 0 && Settings::values.enable_ring_controller) {
|
||||
MakeDevice<RingController>(bus_handle);
|
||||
devices[device_index.value()].is_device_initialized = true;
|
||||
devices[device_index.value()].device->ActivateDevice();
|
||||
cur_entry.is_in_focus = true;
|
||||
cur_entry.is_connected = true;
|
||||
cur_entry.is_connected_result = ResultSuccess;
|
||||
cur_entry.is_enabled = false;
|
||||
cur_entry.is_polling_mode = false;
|
||||
} else {
|
||||
MakeDevice<HidbusStubbed>(bus_handle);
|
||||
devices[device_index.value()].is_device_initialized = true;
|
||||
cur_entry.is_in_focus = true;
|
||||
cur_entry.is_connected = false;
|
||||
cur_entry.is_connected_result = ResultSuccess;
|
||||
cur_entry.is_enabled = false;
|
||||
cur_entry.is_polling_mode = false;
|
||||
std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
||||
sizeof(hidbus_status));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
||||
sizeof(hidbus_status));
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void HidBus::EnableExternalDevice(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
bool enable;
|
||||
INSERT_PADDING_BYTES_NOINIT(7);
|
||||
BusHandle bus_handle;
|
||||
u64 inval;
|
||||
u64 applet_resource_user_id;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
|
||||
Result Hidbus::Finalize(BusHandle bus_handle, AppletResourceUserId aruid) {
|
||||
LOG_INFO(Service_HID,
|
||||
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
||||
"player_number={}, is_valid={}, applet_resource_user_id={}",
|
||||
bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
||||
bus_handle.player_number, bus_handle.is_valid, aruid.pid);
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
const auto entry_index = devices[device_index.value()].handle.internal_index;
|
||||
auto& cur_entry = hidbus_status.entries[entry_index];
|
||||
auto& device = devices[device_index.value()].device;
|
||||
devices[device_index.value()].is_device_initialized = false;
|
||||
device->DeactivateDevice();
|
||||
|
||||
cur_entry.is_in_focus = true;
|
||||
cur_entry.is_connected = false;
|
||||
cur_entry.is_connected_result = ResultSuccess;
|
||||
cur_entry.is_enabled = false;
|
||||
cur_entry.is_polling_mode = false;
|
||||
std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
|
||||
sizeof(hidbus_status));
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result Hidbus::EnableExternalDevice(bool is_enabled, BusHandle bus_handle, u64 inval,
|
||||
AppletResourceUserId aruid) {
|
||||
LOG_DEBUG(Service_HID,
|
||||
"called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
||||
"player_number={}, is_valid={}, inval={}, applet_resource_user_id{}",
|
||||
parameters.enable, parameters.bus_handle.abstracted_pad_id,
|
||||
parameters.bus_handle.bus_type_id, parameters.bus_handle.internal_index,
|
||||
parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval,
|
||||
parameters.applet_resource_user_id);
|
||||
is_enabled, bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
|
||||
bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid, inval,
|
||||
aruid.pid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(parameters.bus_handle);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->Enable(parameters.enable);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
devices[device_index.value()].device->Enable(is_enabled);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void HidBus::GetExternalDeviceId(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
|
||||
Result Hidbus::GetExternalDeviceId(Out<u32> out_device_id, BusHandle bus_handle) {
|
||||
LOG_DEBUG(Service_HID,
|
||||
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
||||
"is_valid={}",
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
||||
bus_handle.player_number, bus_handle.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
const auto& device = devices[device_index.value()].device;
|
||||
u32 device_id = device->GetDeviceId();
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(device_id);
|
||||
return;
|
||||
}
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
*out_device_id = devices[device_index.value()].device->GetDeviceId();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void HidBus::SendCommandAsync(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto data = ctx.ReadBuffer();
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
|
||||
Result Hidbus::SendCommandAsync(BusHandle bus_handle,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> buffer_data) {
|
||||
LOG_DEBUG(Service_HID,
|
||||
"called, data_size={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
|
||||
"player_number={}, is_valid={}",
|
||||
data.size(), bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id,
|
||||
bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid);
|
||||
buffer_data.size(), bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
|
||||
bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->SetCommand(data);
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
devices[device_index.value()].device->SetCommand(buffer_data);
|
||||
R_SUCCEED();
|
||||
};
|
||||
|
||||
void HidBus::GetSendCommandAsynceResult(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
|
||||
Result Hidbus::GetSendCommandAsynceResult(Out<u64> out_data_size, BusHandle bus_handle,
|
||||
OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_data) {
|
||||
LOG_DEBUG(Service_HID,
|
||||
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
||||
"is_valid={}",
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
||||
bus_handle.player_number, bus_handle.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
const auto& device = devices[device_index.value()].device;
|
||||
const std::vector<u8> data = device->GetReply();
|
||||
const u64 data_size = ctx.WriteBuffer(data);
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u64>(data_size);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
*out_data_size = devices[device_index.value()].device->GetReply(out_buffer_data);
|
||||
R_SUCCEED();
|
||||
};
|
||||
|
||||
void HidBus::SetEventForSendCommandAsycResult(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
|
||||
Result Hidbus::SetEventForSendCommandAsycResult(OutCopyHandle<Kernel::KReadableEvent> out_event,
|
||||
BusHandle bus_handle) {
|
||||
LOG_INFO(Service_HID,
|
||||
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
||||
"is_valid={}",
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
||||
bus_handle.player_number, bus_handle.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
const auto& device = devices[device_index.value()].device;
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(device->GetSendCommandAsycEvent());
|
||||
return;
|
||||
}
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
*out_event = &devices[device_index.value()].device->GetSendCommandAsycEvent();
|
||||
R_SUCCEED();
|
||||
};
|
||||
|
||||
void HidBus::GetSharedMemoryHandle(HLERequestContext& ctx) {
|
||||
Result Hidbus::GetSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
|
||||
LOG_DEBUG(Service_HID, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(&system.Kernel().GetHidBusSharedMem());
|
||||
*out_shared_memory = &system.Kernel().GetHidBusSharedMem();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void HidBus::EnableJoyPollingReceiveMode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto t_mem_size{rp.Pop<u32>()};
|
||||
const auto t_mem_handle{ctx.GetCopyHandle(0)};
|
||||
const auto polling_mode_{rp.PopEnum<JoyPollingMode>()};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
|
||||
Result Hidbus::EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode polling_mode,
|
||||
BusHandle bus_handle,
|
||||
InCopyHandle<Kernel::KTransferMemory> t_mem) {
|
||||
ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes");
|
||||
|
||||
auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle);
|
||||
|
||||
if (t_mem.IsNull()) {
|
||||
LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_MSG(t_mem->GetSize() == 0x1000, "t_mem has incorrect size");
|
||||
ASSERT_MSG(t_mem->GetSize() == t_mem_size, "t_mem has incorrect size");
|
||||
|
||||
LOG_INFO(Service_HID,
|
||||
"called, t_mem_handle=0x{:08X}, polling_mode={}, abstracted_pad_id={}, bus_type={}, "
|
||||
"called, polling_mode={}, abstracted_pad_id={}, bus_type={}, "
|
||||
"internal_index={}, player_number={}, is_valid={}",
|
||||
t_mem_handle, polling_mode_, bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id,
|
||||
bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid);
|
||||
polling_mode, bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
|
||||
bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->SetPollingMode(polling_mode_);
|
||||
device->SetTransferMemoryAddress(t_mem->GetSourceAddress());
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->SetPollingMode(polling_mode);
|
||||
device->SetTransferMemoryAddress(t_mem->GetSourceAddress());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void HidBus::DisableJoyPollingReceiveMode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto bus_handle_{rp.PopRaw<BusHandle>()};
|
||||
|
||||
Result Hidbus::DisableJoyPollingReceiveMode(BusHandle bus_handle) {
|
||||
LOG_INFO(Service_HID,
|
||||
"called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
|
||||
"is_valid={}",
|
||||
bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index,
|
||||
bus_handle_.player_number, bus_handle_.is_valid);
|
||||
bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
|
||||
bus_handle.player_number, bus_handle.is_valid);
|
||||
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
|
||||
const auto device_index = GetDeviceIndexFromHandle(bus_handle);
|
||||
|
||||
if (device_index) {
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->DisablePollingMode();
|
||||
R_UNLESS(device_index.has_value(), ResultUnknown);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Invalid handle");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
auto& device = devices[device_index.value()].device;
|
||||
device->DisablePollingMode();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void HidBus::SetStatusManagerType(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto manager_type{rp.PopEnum<StatusManagerType>()};
|
||||
|
||||
Result Hidbus::SetStatusManagerType(StatusManagerType manager_type) {
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, manager_type={}", manager_type);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
R_SUCCEED();
|
||||
};
|
||||
|
||||
} // namespace Service::HID
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "hid_core/hid_types.h"
|
||||
#include "hid_core/hidbus/hidbus_base.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
@@ -19,10 +21,10 @@ class System;
|
||||
|
||||
namespace Service::HID {
|
||||
|
||||
class HidBus final : public ServiceFramework<HidBus> {
|
||||
class Hidbus final : public ServiceFramework<Hidbus> {
|
||||
public:
|
||||
explicit HidBus(Core::System& system_);
|
||||
~HidBus() override;
|
||||
explicit Hidbus(Core::System& system_);
|
||||
~Hidbus() override;
|
||||
|
||||
private:
|
||||
static const std::size_t max_number_of_handles = 0x13;
|
||||
@@ -41,7 +43,7 @@ private:
|
||||
};
|
||||
|
||||
// This is nn::hidbus::BusType
|
||||
enum class BusType : u32 {
|
||||
enum class BusType : u64 {
|
||||
LeftJoyRail,
|
||||
RightJoyRail,
|
||||
InternalBus, // Lark microphone
|
||||
@@ -51,11 +53,15 @@ private:
|
||||
|
||||
// This is nn::hidbus::BusHandle
|
||||
struct BusHandle {
|
||||
u32 abstracted_pad_id;
|
||||
u8 internal_index;
|
||||
u8 player_number;
|
||||
u8 bus_type_id;
|
||||
bool is_valid;
|
||||
union {
|
||||
u64 raw{};
|
||||
|
||||
BitField<0, 32, u64> abstracted_pad_id;
|
||||
BitField<32, 8, u64> internal_index;
|
||||
BitField<40, 8, u64> player_number;
|
||||
BitField<48, 8, u64> bus_type_id;
|
||||
BitField<56, 1, u64> is_valid;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(BusHandle) == 0x8, "BusHandle is an invalid size");
|
||||
|
||||
@@ -94,19 +100,38 @@ private:
|
||||
std::unique_ptr<HidbusBase> device{nullptr};
|
||||
};
|
||||
|
||||
void GetBusHandle(HLERequestContext& ctx);
|
||||
void IsExternalDeviceConnected(HLERequestContext& ctx);
|
||||
void Initialize(HLERequestContext& ctx);
|
||||
void Finalize(HLERequestContext& ctx);
|
||||
void EnableExternalDevice(HLERequestContext& ctx);
|
||||
void GetExternalDeviceId(HLERequestContext& ctx);
|
||||
void SendCommandAsync(HLERequestContext& ctx);
|
||||
void GetSendCommandAsynceResult(HLERequestContext& ctx);
|
||||
void SetEventForSendCommandAsycResult(HLERequestContext& ctx);
|
||||
void GetSharedMemoryHandle(HLERequestContext& ctx);
|
||||
void EnableJoyPollingReceiveMode(HLERequestContext& ctx);
|
||||
void DisableJoyPollingReceiveMode(HLERequestContext& ctx);
|
||||
void SetStatusManagerType(HLERequestContext& ctx);
|
||||
Result GetBusHandle(Out<bool> out_is_valid, Out<BusHandle> out_bus_handle,
|
||||
Core::HID::NpadIdType npad_id, BusType bus_type,
|
||||
AppletResourceUserId aruid);
|
||||
|
||||
Result IsExternalDeviceConnected(Out<bool> out_is_connected, BusHandle bus_handle);
|
||||
|
||||
Result Initialize(BusHandle bus_handle, AppletResourceUserId aruid);
|
||||
|
||||
Result Finalize(BusHandle bus_handle, AppletResourceUserId aruid);
|
||||
|
||||
Result EnableExternalDevice(bool is_enabled, BusHandle bus_handle, u64 inval,
|
||||
AppletResourceUserId aruid);
|
||||
|
||||
Result GetExternalDeviceId(Out<u32> out_device_id, BusHandle bus_handle);
|
||||
|
||||
Result SendCommandAsync(BusHandle bus_handle, InBuffer<BufferAttr_HipcAutoSelect> buffer_data);
|
||||
|
||||
Result GetSendCommandAsynceResult(Out<u64> out_data_size, BusHandle bus_handle,
|
||||
OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_data);
|
||||
|
||||
Result SetEventForSendCommandAsycResult(OutCopyHandle<Kernel::KReadableEvent> out_event,
|
||||
BusHandle bus_handle);
|
||||
|
||||
Result GetSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory);
|
||||
|
||||
Result EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode polling_mode,
|
||||
BusHandle bus_handle,
|
||||
InCopyHandle<Kernel::KTransferMemory> t_mem);
|
||||
|
||||
Result DisableJoyPollingReceiveMode(BusHandle bus_handle);
|
||||
|
||||
Result SetStatusManagerType(StatusManagerType manager_type);
|
||||
|
||||
void UpdateHidbus(std::chrono::nanoseconds ns_late);
|
||||
std::optional<std::size_t> GetDeviceIndexFromHandle(BusHandle handle) const;
|
||||
|
||||
@@ -64,7 +64,8 @@ void StandardVmCallbacks::MemoryWriteUnsafe(VAddr address, const void* data, u64
|
||||
return;
|
||||
}
|
||||
|
||||
if (system.ApplicationMemory().WriteBlock(address, data, size)) {
|
||||
if (system.ApplicationMemory().WriteBlock(address, data, size) &&
|
||||
system.ApplicationProcess()->Is64Bit()) {
|
||||
Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), address, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
}
|
||||
|
||||
// Returns a reply from a command
|
||||
virtual std::vector<u8> GetReply() const {
|
||||
virtual u64 GetReply(std::span<u8> out_data) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -90,32 +90,32 @@ u8 RingController::GetDeviceId() const {
|
||||
return device_id;
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetReply() const {
|
||||
u64 RingController::GetReply(std::span<u8> out_data) const {
|
||||
const RingConCommands current_command = command;
|
||||
|
||||
switch (current_command) {
|
||||
case RingConCommands::GetFirmwareVersion:
|
||||
return GetFirmwareVersionReply();
|
||||
return GetFirmwareVersionReply(out_data);
|
||||
case RingConCommands::ReadId:
|
||||
return GetReadIdReply();
|
||||
return GetReadIdReply(out_data);
|
||||
case RingConCommands::c20105:
|
||||
return GetC020105Reply();
|
||||
return GetC020105Reply(out_data);
|
||||
case RingConCommands::ReadUnkCal:
|
||||
return GetReadUnkCalReply();
|
||||
return GetReadUnkCalReply(out_data);
|
||||
case RingConCommands::ReadFactoryCal:
|
||||
return GetReadFactoryCalReply();
|
||||
return GetReadFactoryCalReply(out_data);
|
||||
case RingConCommands::ReadUserCal:
|
||||
return GetReadUserCalReply();
|
||||
return GetReadUserCalReply(out_data);
|
||||
case RingConCommands::ReadRepCount:
|
||||
return GetReadRepCountReply();
|
||||
return GetReadRepCountReply(out_data);
|
||||
case RingConCommands::ReadTotalPushCount:
|
||||
return GetReadTotalPushCountReply();
|
||||
return GetReadTotalPushCountReply(out_data);
|
||||
case RingConCommands::ResetRepCount:
|
||||
return GetResetRepCountReply();
|
||||
return GetResetRepCountReply(out_data);
|
||||
case RingConCommands::SaveCalData:
|
||||
return GetSaveDataReply();
|
||||
return GetSaveDataReply(out_data);
|
||||
default:
|
||||
return GetErrorReply();
|
||||
return GetErrorReply(out_data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,16 +163,16 @@ bool RingController::SetCommand(std::span<const u8> data) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetFirmwareVersionReply() const {
|
||||
u64 RingController::GetFirmwareVersionReply(std::span<u8> out_data) const {
|
||||
const FirmwareVersionReply reply{
|
||||
.status = DataValid::Valid,
|
||||
.firmware = version,
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetReadIdReply() const {
|
||||
u64 RingController::GetReadIdReply(std::span<u8> out_data) const {
|
||||
// The values are hardcoded from a real joycon
|
||||
const ReadIdReply reply{
|
||||
.status = DataValid::Valid,
|
||||
@@ -184,83 +184,83 @@ std::vector<u8> RingController::GetReadIdReply() const {
|
||||
.id_h_x4 = 8245,
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetC020105Reply() const {
|
||||
u64 RingController::GetC020105Reply(std::span<u8> out_data) const {
|
||||
const Cmd020105Reply reply{
|
||||
.status = DataValid::Valid,
|
||||
.data = 1,
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetReadUnkCalReply() const {
|
||||
u64 RingController::GetReadUnkCalReply(std::span<u8> out_data) const {
|
||||
const ReadUnkCalReply reply{
|
||||
.status = DataValid::Valid,
|
||||
.data = 0,
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetReadFactoryCalReply() const {
|
||||
u64 RingController::GetReadFactoryCalReply(std::span<u8> out_data) const {
|
||||
const ReadFactoryCalReply reply{
|
||||
.status = DataValid::Valid,
|
||||
.calibration = factory_calibration,
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetReadUserCalReply() const {
|
||||
u64 RingController::GetReadUserCalReply(std::span<u8> out_data) const {
|
||||
const ReadUserCalReply reply{
|
||||
.status = DataValid::Valid,
|
||||
.calibration = user_calibration,
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetReadRepCountReply() const {
|
||||
u64 RingController::GetReadRepCountReply(std::span<u8> out_data) const {
|
||||
const GetThreeByteReply reply{
|
||||
.status = DataValid::Valid,
|
||||
.data = {total_rep_count, 0, 0},
|
||||
.crc = GetCrcValue({total_rep_count, 0, 0, 0}),
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetReadTotalPushCountReply() const {
|
||||
u64 RingController::GetReadTotalPushCountReply(std::span<u8> out_data) const {
|
||||
const GetThreeByteReply reply{
|
||||
.status = DataValid::Valid,
|
||||
.data = {total_push_count, 0, 0},
|
||||
.crc = GetCrcValue({total_push_count, 0, 0, 0}),
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetResetRepCountReply() const {
|
||||
return GetReadRepCountReply();
|
||||
u64 RingController::GetResetRepCountReply(std::span<u8> out_data) const {
|
||||
return GetReadRepCountReply(out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetSaveDataReply() const {
|
||||
u64 RingController::GetSaveDataReply(std::span<u8> out_data) const {
|
||||
const StatusReply reply{
|
||||
.status = DataValid::Valid,
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
std::vector<u8> RingController::GetErrorReply() const {
|
||||
u64 RingController::GetErrorReply(std::span<u8> out_data) const {
|
||||
const ErrorReply reply{
|
||||
.status = DataValid::BadCRC,
|
||||
};
|
||||
|
||||
return GetDataVector(reply);
|
||||
return GetData(reply, out_data);
|
||||
}
|
||||
|
||||
u8 RingController::GetCrcValue(const std::vector<u8>& data) const {
|
||||
@@ -281,12 +281,11 @@ u8 RingController::GetCrcValue(const std::vector<u8>& data) const {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<u8> RingController::GetDataVector(const T& reply) const {
|
||||
u64 RingController::GetData(const T& reply, std::span<u8> out_data) const {
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
std::vector<u8> data;
|
||||
data.resize(sizeof(reply));
|
||||
std::memcpy(data.data(), &reply, sizeof(reply));
|
||||
return data;
|
||||
const auto data_size = static_cast<u64>(std::min(sizeof(reply), out_data.size()));
|
||||
std::memcpy(out_data.data(), &reply, data_size);
|
||||
return data_size;
|
||||
}
|
||||
|
||||
} // namespace Service::HID
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
bool SetCommand(std::span<const u8> data) override;
|
||||
|
||||
// Returns a reply from a command
|
||||
std::vector<u8> GetReply() const override;
|
||||
u64 GetReply(std::span<u8> data) const override;
|
||||
|
||||
private:
|
||||
// These values are obtained from a real ring controller
|
||||
@@ -184,44 +184,44 @@ private:
|
||||
RingConData GetSensorValue() const;
|
||||
|
||||
// Returns 8 byte reply with firmware version
|
||||
std::vector<u8> GetFirmwareVersionReply() const;
|
||||
u64 GetFirmwareVersionReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 16 byte reply with ID values
|
||||
std::vector<u8> GetReadIdReply() const;
|
||||
u64 GetReadIdReply(std::span<u8> out_data) const;
|
||||
|
||||
// (STUBBED) Returns 8 byte reply
|
||||
std::vector<u8> GetC020105Reply() const;
|
||||
u64 GetC020105Reply(std::span<u8> out_data) const;
|
||||
|
||||
// (STUBBED) Returns 8 byte empty reply
|
||||
std::vector<u8> GetReadUnkCalReply() const;
|
||||
u64 GetReadUnkCalReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 20 byte reply with factory calibration values
|
||||
std::vector<u8> GetReadFactoryCalReply() const;
|
||||
u64 GetReadFactoryCalReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 20 byte reply with user calibration values
|
||||
std::vector<u8> GetReadUserCalReply() const;
|
||||
u64 GetReadUserCalReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 8 byte reply
|
||||
std::vector<u8> GetReadRepCountReply() const;
|
||||
u64 GetReadRepCountReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 8 byte reply
|
||||
std::vector<u8> GetReadTotalPushCountReply() const;
|
||||
u64 GetReadTotalPushCountReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 8 byte reply
|
||||
std::vector<u8> GetResetRepCountReply() const;
|
||||
u64 GetResetRepCountReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 4 byte save data reply
|
||||
std::vector<u8> GetSaveDataReply() const;
|
||||
u64 GetSaveDataReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 8 byte error reply
|
||||
std::vector<u8> GetErrorReply() const;
|
||||
u64 GetErrorReply(std::span<u8> out_data) const;
|
||||
|
||||
// Returns 8 bit redundancy check from provided data
|
||||
u8 GetCrcValue(const std::vector<u8>& data) const;
|
||||
|
||||
// Converts structs to an u8 vector equivalent
|
||||
template <typename T>
|
||||
std::vector<u8> GetDataVector(const T& reply) const;
|
||||
u64 GetData(const T& reply, std::span<u8> out_data) const;
|
||||
|
||||
RingConCommands command{RingConCommands::Error};
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ u8 Starlink::GetDeviceId() const {
|
||||
return DEVICE_ID;
|
||||
}
|
||||
|
||||
std::vector<u8> Starlink::GetReply() const {
|
||||
u64 Starlink::GetReply(std::span<u8> out_data) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
bool SetCommand(std::span<const u8> data) override;
|
||||
|
||||
// Returns a reply from a command
|
||||
std::vector<u8> GetReply() const override;
|
||||
u64 GetReply(std::span<u8> out_data) const override;
|
||||
};
|
||||
|
||||
} // namespace Service::HID
|
||||
|
||||
@@ -38,7 +38,7 @@ u8 HidbusStubbed::GetDeviceId() const {
|
||||
return DEVICE_ID;
|
||||
}
|
||||
|
||||
std::vector<u8> HidbusStubbed::GetReply() const {
|
||||
u64 HidbusStubbed::GetReply(std::span<u8> out_data) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
bool SetCommand(std::span<const u8> data) override;
|
||||
|
||||
// Returns a reply from a command
|
||||
std::vector<u8> GetReply() const override;
|
||||
u64 GetReply(std::span<u8> out_data) const override;
|
||||
};
|
||||
|
||||
} // namespace Service::HID
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/assert.h"
|
||||
@@ -40,7 +40,8 @@ void Decoder::Decode() {
|
||||
auto frame_copy = frame;
|
||||
|
||||
if (!frame.get()) {
|
||||
LOG_ERROR(HW_GPU, "Failed to decode interlaced frame for top 0x{:X} bottom 0x{:X}",
|
||||
LOG_ERROR(HW_GPU,
|
||||
"Nvdec {} dailed to decode interlaced frame for top 0x{:X} bottom 0x{:X}", id,
|
||||
luma_top, luma_bottom);
|
||||
}
|
||||
|
||||
@@ -55,7 +56,8 @@ void Decoder::Decode() {
|
||||
auto [luma_offset, chroma_offset] = GetProgressiveOffsets();
|
||||
|
||||
if (!frame.get()) {
|
||||
LOG_ERROR(HW_GPU, "Failed to decode progressive frame for luma 0x{:X}", luma_offset);
|
||||
LOG_ERROR(HW_GPU, "Nvdec {} failed to decode progressive frame for luma 0x{:X}", id,
|
||||
luma_offset);
|
||||
}
|
||||
|
||||
if (UsingDecodeOrder()) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Ryujinx Team and Contributors
|
||||
// SPDX-License-Identifier: MIT
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Ryujinx Team and Contributors
|
||||
// SPDX-License-Identifier: MIT
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -66,12 +66,18 @@ public:
|
||||
void PushPresentOrder(s32 fd, u64 offset, std::shared_ptr<FFmpeg::Frame>&& frame) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
auto map = m_presentation_order.find(fd);
|
||||
if (map == m_presentation_order.end()) {
|
||||
return;
|
||||
}
|
||||
map->second.emplace_back(offset, std::move(frame));
|
||||
}
|
||||
|
||||
void PushDecodeOrder(s32 fd, u64 offset, std::shared_ptr<FFmpeg::Frame>&& frame) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
auto map = m_decode_order.find(fd);
|
||||
if (map == m_decode_order.end()) {
|
||||
return;
|
||||
}
|
||||
map->second.insert_or_assign(offset, std::move(frame));
|
||||
}
|
||||
|
||||
@@ -82,12 +88,12 @@ public:
|
||||
|
||||
std::scoped_lock l{m_mutex};
|
||||
auto present_map = m_presentation_order.find(fd);
|
||||
if (present_map->second.size() > 0) {
|
||||
if (present_map != m_presentation_order.end() && present_map->second.size() > 0) {
|
||||
return GetPresentOrderLocked(fd);
|
||||
}
|
||||
|
||||
auto decode_map = m_decode_order.find(fd);
|
||||
if (decode_map->second.size() > 0) {
|
||||
if (decode_map != m_decode_order.end() && decode_map->second.size() > 0) {
|
||||
return GetDecodeOrderLocked(fd, offset);
|
||||
}
|
||||
|
||||
@@ -97,7 +103,7 @@ public:
|
||||
private:
|
||||
std::shared_ptr<FFmpeg::Frame> GetPresentOrderLocked(s32 fd) {
|
||||
auto map = m_presentation_order.find(fd);
|
||||
if (map->second.size() == 0) {
|
||||
if (map == m_presentation_order.end() || map->second.size() == 0) {
|
||||
return {};
|
||||
}
|
||||
auto frame = std::move(map->second.front().second);
|
||||
@@ -107,6 +113,9 @@ private:
|
||||
|
||||
std::shared_ptr<FFmpeg::Frame> GetDecodeOrderLocked(s32 fd, u64 offset) {
|
||||
auto map = m_decode_order.find(fd);
|
||||
if (map == m_decode_order.end() || map->second.size() == 0) {
|
||||
return {};
|
||||
}
|
||||
auto it = map->second.find(offset);
|
||||
if (it == map->second.end()) {
|
||||
return {};
|
||||
|
||||
@@ -24,7 +24,6 @@ Nvdec::Nvdec(Host1x& host1x_, s32 id_, u32 syncpt, FrameQueue& frame_queue_)
|
||||
|
||||
Nvdec::~Nvdec() {
|
||||
LOG_INFO(HW_GPU, "Destroying nvdec {}", id);
|
||||
frame_queue.Close(id);
|
||||
}
|
||||
|
||||
void Nvdec::ProcessMethod(u32 method, u32 argument) {
|
||||
|
||||
@@ -100,10 +100,11 @@ Vic::Vic(Host1x& host1x_, s32 id_, u32 syncpt, FrameQueue& frame_queue_)
|
||||
|
||||
Vic::~Vic() {
|
||||
LOG_INFO(HW_GPU, "Destroying vic {}", id);
|
||||
frame_queue.Close(id);
|
||||
}
|
||||
|
||||
void Vic::ProcessMethod(u32 method, u32 arg) {
|
||||
LOG_TRACE(HW_GPU, "Vic method 0x{:X}", static_cast<u32>(method));
|
||||
LOG_TRACE(HW_GPU, "Vic {} method 0x{:X}", id, static_cast<u32>(method));
|
||||
regs.reg_array[method] = arg;
|
||||
|
||||
switch (static_cast<Method>(method * sizeof(u32))) {
|
||||
@@ -140,7 +141,7 @@ void Vic::Execute() {
|
||||
|
||||
auto frame = frame_queue.GetFrame(nvdec_id, luma_offset);
|
||||
if (!frame.get()) {
|
||||
LOG_ERROR(HW_GPU, "Vic failed to get frame with offset 0x{:X}", luma_offset);
|
||||
LOG_ERROR(HW_GPU, "Vic {} failed to get frame with offset 0x{:X}", id, luma_offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user