summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/core.cpp11
-rw-r--r--src/core/core.h5
-rw-r--r--src/core/file_sys/control_metadata.cpp28
-rw-r--r--src/core/file_sys/control_metadata.h30
-rw-r--r--src/core/file_sys/savedata_factory.cpp30
-rw-r--r--src/core/file_sys/savedata_factory.h8
-rw-r--r--src/core/file_sys/vfs.h4
-rw-r--r--src/core/frontend/applets/profile_select.cpp19
-rw-r--r--src/core/frontend/applets/profile_select.h27
-rw-r--r--src/core/frontend/framebuffer_layout.cpp15
-rw-r--r--src/core/frontend/framebuffer_layout.h7
-rw-r--r--src/core/hle/kernel/errors.h2
-rw-r--r--src/core/hle/kernel/svc.cpp38
-rw-r--r--src/core/hle/kernel/thread.cpp24
-rw-r--r--src/core/hle/kernel/thread.h14
-rw-r--r--src/core/hle/kernel/vm_manager.cpp1
-rw-r--r--src/core/hle/service/am/am.cpp51
-rw-r--r--src/core/hle/service/am/am.h2
-rw-r--r--src/core/hle/service/am/applets/profile_select.cpp77
-rw-r--r--src/core/hle/service/am/applets/profile_select.h50
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp47
-rw-r--r--src/core/hle/service/filesystem/filesystem.h6
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp46
-rw-r--r--src/core/hle/service/hid/hid.cpp207
-rw-r--r--src/core/loader/loader.h10
-rw-r--r--src/core/loader/nsp.cpp4
-rw-r--r--src/core/loader/nsp.h2
-rw-r--r--src/core/loader/xci.cpp5
-rw-r--r--src/core/loader/xci.h2
30 files changed, 651 insertions, 125 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 882c9ab59..93f5ba3fe 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -83,6 +83,8 @@ add_library(core STATIC
file_sys/vfs_vector.h
file_sys/xts_archive.cpp
file_sys/xts_archive.h
+ frontend/applets/profile_select.cpp
+ frontend/applets/profile_select.h
frontend/applets/software_keyboard.cpp
frontend/applets/software_keyboard.h
frontend/emu_window.cpp
@@ -162,6 +164,8 @@ add_library(core STATIC
hle/service/am/applet_oe.h
hle/service/am/applets/applets.cpp
hle/service/am/applets/applets.h
+ hle/service/am/applets/profile_select.cpp
+ hle/service/am/applets/profile_select.h
hle/service/am/applets/software_keyboard.cpp
hle/service/am/applets/software_keyboard.h
hle/service/am/applets/stub_applet.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index ce7851538..fd10199ec 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -99,6 +99,8 @@ struct System::Impl {
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
/// Create default implementations of applets if one is not provided.
+ if (profile_selector == nullptr)
+ profile_selector = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
if (software_keyboard == nullptr)
software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
@@ -229,6 +231,7 @@ struct System::Impl {
bool is_powered_on = false;
/// Frontend applets
+ std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_selector;
std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
/// Service manager
@@ -424,6 +427,14 @@ std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
return impl->virtual_filesystem;
}
+void System::SetProfileSelector(std::unique_ptr<Core::Frontend::ProfileSelectApplet> applet) {
+ impl->profile_selector = std::move(applet);
+}
+
+const Core::Frontend::ProfileSelectApplet& System::GetProfileSelector() const {
+ return *impl->profile_selector;
+}
+
void System::SetSoftwareKeyboard(std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> applet) {
impl->software_keyboard = std::move(applet);
}
diff --git a/src/core/core.h b/src/core/core.h
index 71031dfcf..869921493 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -11,6 +11,7 @@
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/hle/kernel/object.h"
+#include "frontend/applets/profile_select.h"
namespace Core::Frontend {
class EmuWindow;
@@ -241,6 +242,10 @@ public:
std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
+ void SetProfileSelector(std::unique_ptr<Core::Frontend::ProfileSelectApplet> applet);
+
+ const Core::Frontend::ProfileSelectApplet& GetProfileSelector() const;
+
void SetSoftwareKeyboard(std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> applet);
const Core::Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const;
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp
index e065e592f..83c184750 100644
--- a/src/core/file_sys/control_metadata.cpp
+++ b/src/core/file_sys/control_metadata.cpp
@@ -36,18 +36,20 @@ std::string LanguageEntry::GetDeveloperName() const {
developer_name.size());
}
-NACP::NACP(VirtualFile file) : raw(std::make_unique<RawNACP>()) {
- file->ReadObject(raw.get());
+NACP::NACP() = default;
+
+NACP::NACP(VirtualFile file) {
+ file->ReadObject(&raw);
}
NACP::~NACP() = default;
const LanguageEntry& NACP::GetLanguageEntry(Language language) const {
if (language != Language::Default) {
- return raw->language_entries.at(static_cast<u8>(language));
+ return raw.language_entries.at(static_cast<u8>(language));
}
- for (const auto& language_entry : raw->language_entries) {
+ for (const auto& language_entry : raw.language_entries) {
if (!language_entry.GetApplicationName().empty())
return language_entry;
}
@@ -65,21 +67,29 @@ std::string NACP::GetDeveloperName(Language language) const {
}
u64 NACP::GetTitleId() const {
- return raw->title_id;
+ return raw.title_id;
}
u64 NACP::GetDLCBaseTitleId() const {
- return raw->dlc_base_title_id;
+ return raw.dlc_base_title_id;
}
std::string NACP::GetVersionString() const {
- return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(),
- raw->version_string.size());
+ return Common::StringFromFixedZeroTerminatedBuffer(raw.version_string.data(),
+ raw.version_string.size());
+}
+
+u64 NACP::GetDefaultNormalSaveSize() const {
+ return raw.normal_save_data_size;
+}
+
+u64 NACP::GetDefaultJournalSaveSize() const {
+ return raw.journal_sava_data_size;
}
std::vector<u8> NACP::GetRawBytes() const {
std::vector<u8> out(sizeof(RawNACP));
- std::memcpy(out.data(), raw.get(), sizeof(RawNACP));
+ std::memcpy(out.data(), &raw, sizeof(RawNACP));
return out;
}
} // namespace FileSys
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index bfaad46b4..7b9cdc910 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -28,17 +28,30 @@ static_assert(sizeof(LanguageEntry) == 0x300, "LanguageEntry has incorrect size.
// The raw file format of a NACP file.
struct RawNACP {
std::array<LanguageEntry, 16> language_entries;
- INSERT_PADDING_BYTES(0x38);
+ std::array<u8, 0x25> isbn;
+ u8 startup_user_account;
+ INSERT_PADDING_BYTES(2);
+ u32_le application_attribute;
+ u32_le supported_languages;
+ u32_le parental_control;
+ bool screenshot_enabled;
+ u8 video_capture_mode;
+ bool data_loss_confirmation;
+ INSERT_PADDING_BYTES(1);
u64_le title_id;
- INSERT_PADDING_BYTES(0x20);
+ std::array<u8, 0x20> rating_age;
std::array<char, 0x10> version_string;
u64_le dlc_base_title_id;
u64_le title_id_2;
- INSERT_PADDING_BYTES(0x28);
+ u64_le normal_save_data_size;
+ u64_le journal_sava_data_size;
+ INSERT_PADDING_BYTES(0x18);
u64_le product_code;
- u64_le title_id_3;
- std::array<u64_le, 0x7> title_id_array;
- INSERT_PADDING_BYTES(0x8);
+ std::array<u64_le, 0x8> local_communication;
+ u8 logo_type;
+ u8 logo_handling;
+ bool runtime_add_on_content_install;
+ INSERT_PADDING_BYTES(5);
u64_le title_id_update;
std::array<u8, 0x40> bcat_passphrase;
INSERT_PADDING_BYTES(0xEC0);
@@ -72,6 +85,7 @@ extern const std::array<const char*, 15> LANGUAGE_NAMES;
// These store application name, dev name, title id, and other miscellaneous data.
class NACP {
public:
+ explicit NACP();
explicit NACP(VirtualFile file);
~NACP();
@@ -81,10 +95,12 @@ public:
u64 GetTitleId() const;
u64 GetDLCBaseTitleId() const;
std::string GetVersionString() const;
+ u64 GetDefaultNormalSaveSize() const;
+ u64 GetDefaultJournalSaveSize() const;
std::vector<u8> GetRawBytes() const;
private:
- std::unique_ptr<RawNACP> raw;
+ RawNACP raw{};
};
} // namespace FileSys
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index d63b7f19b..1913dc956 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -13,6 +13,8 @@
namespace FileSys {
+constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
+
std::string SaveDataDescriptor::DebugInfo() const {
return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}]",
static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id);
@@ -132,4 +134,32 @@ std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType typ
}
}
+SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
+ u128 user_id) const {
+ const auto path = GetFullPath(SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
+ const auto dir = GetOrCreateDirectoryRelative(this->dir, path);
+
+ const auto size_file = dir->GetFile(SAVE_DATA_SIZE_FILENAME);
+ if (size_file == nullptr || size_file->GetSize() < sizeof(SaveDataSize))
+ return {0, 0};
+
+ SaveDataSize out;
+ if (size_file->ReadObject(&out) != sizeof(SaveDataSize))
+ return {0, 0};
+ return out;
+}
+
+void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
+ SaveDataSize new_value) {
+ const auto path = GetFullPath(SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
+ const auto dir = GetOrCreateDirectoryRelative(this->dir, path);
+
+ const auto size_file = dir->CreateFile(SAVE_DATA_SIZE_FILENAME);
+ if (size_file == nullptr)
+ return;
+
+ size_file->Resize(sizeof(SaveDataSize));
+ size_file->WriteObject(new_value);
+}
+
} // namespace FileSys
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index bd4919610..3a1caf292 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -46,6 +46,11 @@ struct SaveDataDescriptor {
};
static_assert(sizeof(SaveDataDescriptor) == 0x40, "SaveDataDescriptor has incorrect size.");
+struct SaveDataSize {
+ u64 normal;
+ u64 journal;
+};
+
/// File system interface to the SaveData archive
class SaveDataFactory {
public:
@@ -60,6 +65,9 @@ public:
static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id,
u128 user_id, u64 save_id);
+ SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const;
+ void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, SaveDataSize new_value);
+
private:
VirtualDir dir;
};
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index e5641b255..954094772 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -150,7 +150,7 @@ public:
template <typename T>
std::size_t WriteArray(const T* data, std::size_t number_elements, std::size_t offset = 0) {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
- return Write(data, number_elements * sizeof(T), offset);
+ return Write(reinterpret_cast<const u8*>(data), number_elements * sizeof(T), offset);
}
// Writes size bytes starting at memory location data to offset in file.
@@ -166,7 +166,7 @@ public:
template <typename T>
std::size_t WriteObject(const T& data, std::size_t offset = 0) {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
- return Write(&data, sizeof(T), offset);
+ return Write(reinterpret_cast<const u8*>(&data), sizeof(T), offset);
}
// Renames the file to name. Returns whether or not the operation was successsful.
diff --git a/src/core/frontend/applets/profile_select.cpp b/src/core/frontend/applets/profile_select.cpp
new file mode 100644
index 000000000..fbf5f2a9e
--- /dev/null
+++ b/src/core/frontend/applets/profile_select.cpp
@@ -0,0 +1,19 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/frontend/applets/profile_select.h"
+#include "core/settings.h"
+
+namespace Core::Frontend {
+
+ProfileSelectApplet::~ProfileSelectApplet() = default;
+
+void DefaultProfileSelectApplet::SelectProfile(
+ std::function<void(std::optional<Service::Account::UUID>)> callback) const {
+ Service::Account::ProfileManager manager;
+ callback(manager.GetUser(Settings::values.current_user).value_or(Service::Account::UUID{}));
+ LOG_INFO(Service_ACC, "called, selecting current user instead of prompting...");
+}
+
+} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/profile_select.h b/src/core/frontend/applets/profile_select.h
new file mode 100644
index 000000000..fc8f7ae94
--- /dev/null
+++ b/src/core/frontend/applets/profile_select.h
@@ -0,0 +1,27 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <functional>
+#include <optional>
+#include "core/hle/service/acc/profile_manager.h"
+
+namespace Core::Frontend {
+
+class ProfileSelectApplet {
+public:
+ virtual ~ProfileSelectApplet();
+
+ virtual void SelectProfile(
+ std::function<void(std::optional<Service::Account::UUID>)> callback) const = 0;
+};
+
+class DefaultProfileSelectApplet final : public ProfileSelectApplet {
+public:
+ void SelectProfile(
+ std::function<void(std::optional<Service::Account::UUID>)> callback) const override;
+};
+
+} // namespace Core::Frontend
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp
index 8f07aedc9..f8662d193 100644
--- a/src/core/frontend/framebuffer_layout.cpp
+++ b/src/core/frontend/framebuffer_layout.cpp
@@ -6,6 +6,7 @@
#include "common/assert.h"
#include "core/frontend/framebuffer_layout.h"
+#include "core/settings.h"
namespace Layout {
@@ -42,4 +43,18 @@ FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height) {
return res;
}
+FramebufferLayout FrameLayoutFromResolutionScale(u16 res_scale) {
+ int width, height;
+
+ if (Settings::values.use_docked_mode) {
+ width = ScreenDocked::WidthDocked * res_scale;
+ height = ScreenDocked::HeightDocked * res_scale;
+ } else {
+ width = ScreenUndocked::Width * res_scale;
+ height = ScreenUndocked::Height * res_scale;
+ }
+
+ return DefaultFrameLayout(width, height);
+}
+
} // namespace Layout
diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h
index f3fddfa94..e06647794 100644
--- a/src/core/frontend/framebuffer_layout.h
+++ b/src/core/frontend/framebuffer_layout.h
@@ -9,6 +9,7 @@
namespace Layout {
enum ScreenUndocked : unsigned { Width = 1280, Height = 720 };
+enum ScreenDocked : unsigned { WidthDocked = 1920, HeightDocked = 1080 };
/// Describes the layout of the window framebuffer
struct FramebufferLayout {
@@ -34,4 +35,10 @@ struct FramebufferLayout {
*/
FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height);
+/**
+ * Convenience method to get frame layout by resolution scale
+ * @param res_scale resolution scale factor
+ */
+FramebufferLayout FrameLayoutFromResolutionScale(u16 res_scale);
+
} // namespace Layout
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index 8b58d701d..d8240ec6d 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -27,7 +27,7 @@ constexpr ResultCode ERR_SYNCHRONIZATION_CANCELED{ErrorModule::Kernel, 118};
constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119};
constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120};
constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121};
-constexpr ResultCode ERR_ALREADY_REGISTERED{ErrorModule::Kernel, 122};
+constexpr ResultCode ERR_BUSY{ErrorModule::Kernel, 122};
constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123};
constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125};
constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132};
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 28268e112..2e80b48c2 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -932,8 +932,35 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
}
/// Sets the thread activity
-static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
- LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, unknown=0x{:08X}", handle, unknown);
+static ResultCode SetThreadActivity(Handle handle, u32 activity) {
+ LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity);
+ if (activity > static_cast<u32>(ThreadActivity::Paused)) {
+ return ERR_INVALID_ENUM_VALUE;
+ }
+
+ const auto* current_process = Core::CurrentProcess();
+ const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
+ return ERR_INVALID_HANDLE;
+ }
+
+ if (thread->GetOwnerProcess() != current_process) {
+ LOG_ERROR(Kernel_SVC,
+ "The current process does not own the current thread, thread_handle={:08X} "
+ "thread_pid={}, "
+ "current_process_pid={}",
+ handle, thread->GetOwnerProcess()->GetProcessID(),
+ current_process->GetProcessID());
+ return ERR_INVALID_HANDLE;
+ }
+
+ if (thread == GetCurrentThread()) {
+ LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
+ return ERR_BUSY;
+ }
+
+ thread->SetActivity(static_cast<ThreadActivity>(activity));
return RESULT_SUCCESS;
}
@@ -960,7 +987,7 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
if (thread == GetCurrentThread()) {
LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
- return ERR_ALREADY_REGISTERED;
+ return ERR_BUSY;
}
Core::ARM_Interface::ThreadContext ctx = thread->GetContext();
@@ -1245,7 +1272,10 @@ static ResultCode StartThread(Handle thread_handle) {
ASSERT(thread->GetStatus() == ThreadStatus::Dormant);
thread->ResumeFromWait();
- Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
+
+ if (thread->GetStatus() == ThreadStatus::Ready) {
+ Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
+ }
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 63f8923fd..434655638 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -50,7 +50,7 @@ void Thread::Stop() {
// Clean up thread from ready queue
// This is only needed when the thread is terminated forcefully (SVC TerminateProcess)
- if (status == ThreadStatus::Ready) {
+ if (status == ThreadStatus::Ready || status == ThreadStatus::Paused) {
scheduler->UnscheduleThread(this, current_priority);
}
@@ -140,6 +140,11 @@ void Thread::ResumeFromWait() {
wakeup_callback = nullptr;
+ if (activity == ThreadActivity::Paused) {
+ status = ThreadStatus::Paused;
+ return;
+ }
+
status = ThreadStatus::Ready;
ChangeScheduler();
@@ -391,6 +396,23 @@ bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> t
return wakeup_callback(reason, std::move(thread), std::move(object), index);
}
+void Thread::SetActivity(ThreadActivity value) {
+ activity = value;
+
+ if (value == ThreadActivity::Paused) {
+ // Set status if not waiting
+ if (status == ThreadStatus::Ready) {
+ status = ThreadStatus::Paused;
+ } else if (status == ThreadStatus::Running) {
+ status = ThreadStatus::Paused;
+ Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
+ }
+ } else if (status == ThreadStatus::Paused) {
+ // Ready to reschedule
+ ResumeFromWait();
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index d6e7981d3..fe5398d56 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -45,6 +45,7 @@ enum ThreadProcessorId : s32 {
enum class ThreadStatus {
Running, ///< Currently running
Ready, ///< Ready to run
+ Paused, ///< Paused by SetThreadActivity or debug
WaitHLEEvent, ///< Waiting for hle event to finish
WaitSleep, ///< Waiting due to a SleepThread SVC
WaitIPC, ///< Waiting for the reply from an IPC request
@@ -61,6 +62,11 @@ enum class ThreadWakeupReason {
Timeout // The thread was woken up due to a wait timeout.
};
+enum class ThreadActivity : u32 {
+ Normal = 0,
+ Paused = 1,
+};
+
class Thread final : public WaitObject {
public:
using TLSMemory = std::vector<u8>;
@@ -371,6 +377,12 @@ public:
return affinity_mask;
}
+ ThreadActivity GetActivity() const {
+ return activity;
+ }
+
+ void SetActivity(ThreadActivity value);
+
private:
explicit Thread(KernelCore& kernel);
~Thread() override;
@@ -439,6 +451,8 @@ private:
TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>();
std::string name;
+
+ ThreadActivity activity = ThreadActivity::Normal;
};
/**
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index f39e096ca..10ad94aa6 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -190,6 +190,7 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) {
vma.type = VMAType::Free;
vma.permissions = VMAPermission::None;
vma.state = MemoryState::Unmapped;
+ vma.attribute = MemoryAttribute::None;
vma.backing_block = nullptr;
vma.offset = 0;
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 27c31aad2..d13ce4dca 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -8,6 +8,7 @@
#include <stack>
#include "audio_core/audio_renderer.h"
#include "core/core.h"
+#include "core/file_sys/savedata_factory.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
@@ -19,6 +20,7 @@
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/am/applets/profile_select.h"
#include "core/hle/service/am/applets/software_keyboard.h"
#include "core/hle/service/am/applets/stub_applet.h"
#include "core/hle/service/am/idle.h"
@@ -39,6 +41,7 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2};
constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
enum class AppletId : u32 {
+ ProfileSelect = 0x10,
SoftwareKeyboard = 0x11,
};
@@ -775,6 +778,8 @@ ILibraryAppletCreator::~ILibraryAppletCreator() = default;
static std::shared_ptr<Applets::Applet> GetAppletFromId(AppletId id) {
switch (id) {
+ case AppletId::ProfileSelect:
+ return std::make_shared<Applets::ProfileSelect>();
case AppletId::SoftwareKeyboard:
return std::make_shared<Applets::SoftwareKeyboard>();
default:
@@ -861,8 +866,8 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
{23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
{24, nullptr, "GetLaunchStorageInfoForDebug"},
- {25, nullptr, "ExtendSaveData"},
- {26, nullptr, "GetSaveDataSize"},
+ {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
+ {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
{30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
{31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
{32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
@@ -1039,6 +1044,48 @@ void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) {
rb.Push<u64>(0);
}
+void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto type{rp.PopRaw<FileSys::SaveDataType>()};
+ rp.Skip(1, false);
+ const auto user_id{rp.PopRaw<u128>()};
+ const auto new_normal_size{rp.PopRaw<u64>()};
+ const auto new_journal_size{rp.PopRaw<u64>()};
+
+ LOG_DEBUG(Service_AM,
+ "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
+ "new_journal={:016X}",
+ static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
+
+ FileSystem::WriteSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id,
+ {new_normal_size, new_journal_size});
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+
+ // The following value is used upon failure to help the system recover.
+ // Since we always succeed, this should be 0.
+ rb.Push<u64>(0);
+}
+
+void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto type{rp.PopRaw<FileSys::SaveDataType>()};
+ rp.Skip(1, false);
+ const auto user_id{rp.PopRaw<u128>()};
+
+ LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", static_cast<u8>(type),
+ user_id[1], user_id[0]);
+
+ const auto size =
+ FileSystem::ReadSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id);
+
+ IPC::ResponseBuilder rb{ctx, 6};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(size.normal);
+ rb.Push(size.journal);
+}
+
void InstallInterfaces(SM::ServiceManager& service_manager,
std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
auto message_queue = std::make_shared<AppletMessageQueue>();
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 34c45fadf..b6113cfdd 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -206,6 +206,8 @@ private:
void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx);
void NotifyRunning(Kernel::HLERequestContext& ctx);
void GetPseudoDeviceId(Kernel::HLERequestContext& ctx);
+ void ExtendSaveData(Kernel::HLERequestContext& ctx);
+ void GetSaveDataSize(Kernel::HLERequestContext& ctx);
void BeginBlockingHomeButtonShortAndLongPressed(Kernel::HLERequestContext& ctx);
void EndBlockingHomeButtonShortAndLongPressed(Kernel::HLERequestContext& ctx);
void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
new file mode 100644
index 000000000..4c7b45454
--- /dev/null
+++ b/src/core/hle/service/am/applets/profile_select.cpp
@@ -0,0 +1,77 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <cstring>
+
+#include "common/assert.h"
+#include "common/string_util.h"
+#include "core/core.h"
+#include "core/frontend/applets/software_keyboard.h"
+#include "core/hle/service/am/am.h"
+#include "core/hle/service/am/applets/profile_select.h"
+
+namespace Service::AM::Applets {
+
+constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
+
+ProfileSelect::ProfileSelect() = default;
+ProfileSelect::~ProfileSelect() = default;
+
+void ProfileSelect::Initialize() {
+ complete = false;
+ status = RESULT_SUCCESS;
+ final_data.clear();
+
+ Applet::Initialize();
+
+ const auto user_config_storage = broker.PopNormalDataToApplet();
+ ASSERT(user_config_storage != nullptr);
+ const auto& user_config = user_config_storage->GetData();
+
+ ASSERT(user_config.size() >= sizeof(UserSelectionConfig));
+ std::memcpy(&config, user_config.data(), sizeof(UserSelectionConfig));
+}
+
+bool ProfileSelect::TransactionComplete() const {
+ return complete;
+}
+
+ResultCode ProfileSelect::GetStatus() const {
+ return status;
+}
+
+void ProfileSelect::ExecuteInteractive() {
+ UNREACHABLE_MSG("Attempted to call interactive execution on non-interactive applet.");
+}
+
+void ProfileSelect::Execute() {
+ if (complete) {
+ broker.PushNormalDataFromApplet(IStorage{final_data});
+ return;
+ }
+
+ const auto& frontend{Core::System::GetInstance().GetProfileSelector()};
+
+ frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); });
+}
+
+void ProfileSelect::SelectionComplete(std::optional<Account::UUID> uuid) {
+ UserSelectionOutput output{};
+
+ if (uuid.has_value() && uuid->uuid != Account::INVALID_UUID) {
+ output.result = 0;
+ output.uuid_selected = uuid->uuid;
+ } else {
+ status = ERR_USER_CANCELLED_SELECTION;
+ output.result = ERR_USER_CANCELLED_SELECTION.raw;
+ output.uuid_selected = Account::INVALID_UUID;
+ }
+
+ final_data = std::vector<u8>(sizeof(UserSelectionOutput));
+ std::memcpy(final_data.data(), &output, final_data.size());
+ broker.PushNormalDataFromApplet(IStorage{final_data});
+ broker.SignalStateChanged();
+}
+
+} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h
new file mode 100644
index 000000000..787485f22
--- /dev/null
+++ b/src/core/hle/service/am/applets/profile_select.h
@@ -0,0 +1,50 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+
+#include "common/common_funcs.h"
+#include "core/hle/service/acc/profile_manager.h"
+#include "core/hle/service/am/applets/applets.h"
+
+namespace Service::AM::Applets {
+
+struct UserSelectionConfig {
+ // TODO(DarkLordZach): RE this structure
+ // It seems to be flags and the like that determine the UI of the applet on the switch... from
+ // my research this is safe to ignore for now.
+ INSERT_PADDING_BYTES(0xA0);
+};
+static_assert(sizeof(UserSelectionConfig) == 0xA0, "UserSelectionConfig has incorrect size.");
+
+struct UserSelectionOutput {
+ u64 result;
+ u128 uuid_selected;
+};
+static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has incorrect size.");
+
+class ProfileSelect final : public Applet {
+public:
+ ProfileSelect();
+ ~ProfileSelect() override;
+
+ void Initialize() override;
+
+ bool TransactionComplete() const override;
+ ResultCode GetStatus() const override;
+ void ExecuteInteractive() override;
+ void Execute() override;
+
+ void SelectionComplete(std::optional<Account::UUID> uuid);
+
+private:
+ UserSelectionConfig config;
+ bool complete = false;
+ ResultCode status = RESULT_SUCCESS;
+ std::vector<u8> final_data;
+};
+
+} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index b1490e6fa..c6da2df43 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -8,18 +8,23 @@
#include "common/file_util.h"
#include "core/core.h"
#include "core/file_sys/bis_factory.h"
+#include "core/file_sys/control_metadata.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/mode.h"
+#include "core/file_sys/partition_filesystem.h"
+#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
#include "core/file_sys/sdmc_factory.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_offset.h"
+#include "core/hle/kernel/process.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_ldr.h"
#include "core/hle/service/filesystem/fsp_pr.h"
#include "core/hle/service/filesystem/fsp_srv.h"
+#include "core/loader/loader.h"
namespace Service::FileSystem {
@@ -28,6 +33,10 @@ namespace Service::FileSystem {
// TODO(DarkLordZach): Eventually make this configurable in settings.
constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
+// A default size for normal/journal save data size if application control metadata cannot be found.
+// This should be large enough to satisfy even the most extreme requirements (~4.2GB)
+constexpr u64 SUFFICIENT_SAVE_DATA_SIZE = 0xF0000000;
+
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
std::string_view dir_name_) {
std::string dir_name(FileUtil::SanitizePath(dir_name_));
@@ -341,6 +350,44 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
return sdmc_factory->Open();
}
+FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id) {
+ if (save_data_factory == nullptr) {
+ return {0, 0};
+ }
+
+ const auto value = save_data_factory->ReadSaveDataSize(type, title_id, user_id);
+
+ if (value.normal == 0 && value.journal == 0) {
+ FileSys::SaveDataSize new_size{SUFFICIENT_SAVE_DATA_SIZE, SUFFICIENT_SAVE_DATA_SIZE};
+
+ FileSys::NACP nacp;
+ const auto res = Core::System::GetInstance().GetAppLoader().ReadControlData(nacp);
+
+ if (res != Loader::ResultStatus::Success) {
+ FileSys::PatchManager pm{Core::CurrentProcess()->GetTitleID()};
+ auto [nacp_unique, discard] = pm.GetControlMetadata();
+
+ if (nacp_unique != nullptr) {
+ new_size = {nacp_unique->GetDefaultNormalSaveSize(),
+ nacp_unique->GetDefaultJournalSaveSize()};
+ }
+ } else {
+ new_size = {nacp.GetDefaultNormalSaveSize(), nacp.GetDefaultJournalSaveSize()};
+ }
+
+ WriteSaveDataSize(type, title_id, user_id, new_size);
+ return new_size;
+ }
+
+ return value;
+}
+
+void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
+ FileSys::SaveDataSize new_value) {
+ if (save_data_factory != nullptr)
+ save_data_factory->WriteSaveDataSize(type, title_id, user_id, new_value);
+}
+
FileSys::RegisteredCacheUnion GetUnionContents() {
return FileSys::RegisteredCacheUnion{
{GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}};
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 965414be0..6fd5e7b23 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -21,9 +21,11 @@ class SDMCFactory;
enum class ContentRecordType : u8;
enum class Mode : u32;
enum class SaveDataSpaceId : u8;
+enum class SaveDataType : u8;
enum class StorageId : u8;
struct SaveDataDescriptor;
+struct SaveDataSize;
} // namespace FileSys
namespace Service {
@@ -48,6 +50,10 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space);
ResultVal<FileSys::VirtualDir> OpenSDMC();
+FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id);
+void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
+ FileSys::SaveDataSize new_value);
+
FileSys::RegisteredCacheUnion GetUnionContents();
FileSys::RegisteredCache* GetSystemNANDContents();
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index d6829d0b8..75fdb861a 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -339,52 +339,6 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
- if (hold_type == NpadHoldType::Horizontal) {
- ControllerPadState state{};
- AnalogPosition temp_lstick_entry{};
- AnalogPosition temp_rstick_entry{};
- if (controller_type == NPadControllerType::JoyLeft) {
- state.d_down.Assign(pad_state.pad_states.d_left.Value());
- state.d_left.Assign(pad_state.pad_states.d_up.Value());
- state.d_right.Assign(pad_state.pad_states.d_down.Value());
- state.d_up.Assign(pad_state.pad_states.d_right.Value());
- state.l.Assign(pad_state.pad_states.l.Value() |
- pad_state.pad_states.left_sl.Value());
- state.r.Assign(pad_state.pad_states.r.Value() |
- pad_state.pad_states.left_sr.Value());
-
- state.zl.Assign(pad_state.pad_states.zl.Value());
- state.plus.Assign(pad_state.pad_states.minus.Value());
-
- temp_lstick_entry = pad_state.l_stick;
- temp_rstick_entry = pad_state.r_stick;
- std::swap(temp_lstick_entry.x, temp_lstick_entry.y);
- std::swap(temp_rstick_entry.x, temp_rstick_entry.y);
- temp_lstick_entry.y *= -1;
- } else if (controller_type == NPadControllerType::JoyRight) {
- state.x.Assign(pad_state.pad_states.a.Value());
- state.a.Assign(pad_state.pad_states.b.Value());
- state.b.Assign(pad_state.pad_states.y.Value());
- state.y.Assign(pad_state.pad_states.b.Value());
-
- state.l.Assign(pad_state.pad_states.l.Value() |
- pad_state.pad_states.right_sl.Value());
- state.r.Assign(pad_state.pad_states.r.Value() |
- pad_state.pad_states.right_sr.Value());
- state.zr.Assign(pad_state.pad_states.zr.Value());
- state.plus.Assign(pad_state.pad_states.plus.Value());
-
- temp_lstick_entry = pad_state.l_stick;
- temp_rstick_entry = pad_state.r_stick;
- std::swap(temp_lstick_entry.x, temp_lstick_entry.y);
- std::swap(temp_rstick_entry.x, temp_rstick_entry.y);
- temp_rstick_entry.x *= -1;
- }
- pad_state.pad_states.raw = state.raw;
- pad_state.l_stick = temp_lstick_entry;
- pad_state.r_stick = temp_rstick_entry;
- }
-
libnx_entry.connection_status.raw = 0;
switch (controller_type) {
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 2ec38c726..268409257 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -306,7 +306,10 @@ private:
std::shared_ptr<IAppletResource> applet_resource;
void CreateAppletResource(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
if (applet_resource == nullptr) {
applet_resource = std::make_shared<IAppletResource>();
@@ -318,7 +321,12 @@ private:
}
void ActivateXpad(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto basic_xpad_id{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}",
+ basic_xpad_id, applet_resource_user_id);
applet_resource->ActivateController(HidController::XPad);
IPC::ResponseBuilder rb{ctx, 2};
@@ -326,7 +334,10 @@ private:
}
void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
applet_resource->ActivateController(HidController::DebugPad);
IPC::ResponseBuilder rb{ctx, 2};
@@ -334,7 +345,10 @@ private:
}
void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
applet_resource->ActivateController(HidController::Touchscreen);
IPC::ResponseBuilder rb{ctx, 2};
@@ -342,7 +356,10 @@ private:
}
void ActivateMouse(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
applet_resource->ActivateController(HidController::Mouse);
IPC::ResponseBuilder rb{ctx, 2};
@@ -350,7 +367,10 @@ private:
}
void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
applet_resource->ActivateController(HidController::Keyboard);
IPC::ResponseBuilder rb{ctx, 2};
@@ -358,7 +378,12 @@ private:
}
void ActivateGesture(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto unknown{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown,
+ applet_resource_user_id);
applet_resource->ActivateController(HidController::Gesture);
IPC::ResponseBuilder rb{ctx, 2};
@@ -367,7 +392,12 @@ private:
void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
// Should have no effect with how our npad sets up the data
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto unknown{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown,
+ applet_resource_user_id);
applet_resource->ActivateController(HidController::NPad);
IPC::ResponseBuilder rb{ctx, 2};
@@ -376,22 +406,37 @@ private:
void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto handle = rp.PopRaw<u32>();
- LOG_WARNING(Service_HID, "(STUBBED) called with handle={}", handle);
+ const auto handle{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle,
+ applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto handle{rp.Pop<u32>()};
+ const auto drift_mode{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, handle={}, drift_mode={}, applet_resource_user_id={}",
+ handle, drift_mode, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto handle{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle,
+ applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
@@ -401,8 +446,9 @@ private:
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto supported_styleset = rp.PopRaw<u32>();
- LOG_DEBUG(Service_HID, "called with supported_styleset={}", supported_styleset);
+ const auto supported_styleset{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset);
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSupportedStyleSet({supported_styleset});
@@ -412,7 +458,10 @@ private:
}
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
@@ -422,7 +471,10 @@ private:
}
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSupportedNPadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize());
@@ -431,7 +483,10 @@ private:
}
void ActivateNpad(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -440,8 +495,12 @@ private:
void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto npad_id = rp.PopRaw<u32>();
- LOG_DEBUG(Service_HID, "called with npad_id={}", npad_id);
+ const auto npad_id{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto unknown{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}",
+ npad_id, applet_resource_user_id, unknown);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
@@ -451,8 +510,11 @@ private:
void DisconnectNpad(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto npad_id = rp.PopRaw<u32>();
- LOG_DEBUG(Service_HID, "called with npad_id={}", npad_id);
+ const auto npad_id{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id,
+ applet_resource_user_id);
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.DisconnectNPad(npad_id);
@@ -462,8 +524,9 @@ private:
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto npad_id = rp.PopRaw<u32>();
- LOG_DEBUG(Service_HID, "called with npad_id={}", npad_id);
+ const auto npad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -474,8 +537,11 @@ private:
void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto hold_type = rp.PopRaw<u64>();
- LOG_DEBUG(Service_HID, "called with hold_type={}", hold_type);
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto hold_type{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}",
+ applet_resource_user_id, hold_type);
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type});
@@ -485,7 +551,10 @@ private:
}
void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
const auto& controller =
applet_resource->GetController<Controller_NPad>(HidController::NPad);
@@ -496,15 +565,21 @@ private:
void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto npad_id = rp.PopRaw<u32>();
- LOG_WARNING(Service_HID, "(STUBBED) called with npad_id={}", npad_id);
+ const auto npad_id{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
+ npad_id, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetVibrationEnabled(true);
@@ -523,9 +598,12 @@ private:
void SendVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto controller_id = rp.PopRaw<u32>();
- const auto vibration_values = rp.PopRaw<Controller_NPad::Vibration>();
- LOG_DEBUG(Service_HID, "called with controller_id={}", controller_id);
+ const auto controller_id{rp.Pop<u32>()};
+ const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}",
+ controller_id, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -535,7 +613,10 @@ private:
}
void SendVibrationValues(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
const auto controllers = ctx.ReadBuffer(0);
const auto vibrations = ctx.ReadBuffer(1);
@@ -557,7 +638,12 @@ private:
}
void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ IPC::RequestParser rp{ctx};
+ const auto controller_id{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}",
+ controller_id, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
@@ -568,8 +654,11 @@ private:
void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto npad_id = rp.PopRaw<u32>();
- LOG_DEBUG(Service_HID, "called with npad_id={}", npad_id);
+ const auto npad_id{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id,
+ applet_resource_user_id);
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual);
@@ -579,7 +668,14 @@ private:
}
void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto unknown_1{rp.Pop<u32>()};
+ const auto unknown_2{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
+ unknown_1, unknown_2, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -587,8 +683,11 @@ private:
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto mode = rp.PopRaw<u32>();
- LOG_WARNING(Service_HID, "(STUBBED) called with mode={}", mode);
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto mode{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
+ applet_resource_user_id, mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -612,35 +711,55 @@ private:
}
void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
+ applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto handle{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle,
+ applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto handle{rp.Pop<u32>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, handle={}", handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto unknown{rp.Pop<u32>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, unknown={}",
+ applet_resource_user_id, unknown);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto unknown{rp.Pop<u32>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}", unknown);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 0838e303b..cfd67adc0 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -15,6 +15,10 @@
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/vfs.h"
+namespace FileSys {
+class NACP;
+} // namespace FileSys
+
namespace Kernel {
struct AddressMapping;
class Process;
@@ -245,11 +249,11 @@ public:
}
/**
- * Get the developer of the application
- * @param developer Reference to store the application developer into
+ * Get the control data (CNMT) of the application
+ * @param control Reference to store the application control data into
* @return ResultStatus result of function
*/
- virtual ResultStatus ReadDeveloper(std::string& developer) {
+ virtual ResultStatus ReadControlData(FileSys::NACP& control) {
return ResultStatus::ErrorNotImplemented;
}
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index b4ab88ae8..4d4b44571 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -152,10 +152,10 @@ ResultStatus AppLoader_NSP::ReadTitle(std::string& title) {
return ResultStatus::Success;
}
-ResultStatus AppLoader_NSP::ReadDeveloper(std::string& developer) {
+ResultStatus AppLoader_NSP::ReadControlData(FileSys::NACP& nacp) {
if (nacp_file == nullptr)
return ResultStatus::ErrorNoControl;
- developer = nacp_file->GetDeveloperName();
+ nacp = *nacp_file;
return ResultStatus::Success;
}
} // namespace Loader
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
index 2b1e0719b..32eb0193d 100644
--- a/src/core/loader/nsp.h
+++ b/src/core/loader/nsp.h
@@ -43,7 +43,7 @@ public:
ResultStatus ReadProgramId(u64& out_program_id) override;
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
ResultStatus ReadTitle(std::string& title) override;
- ResultStatus ReadDeveloper(std::string& developer) override;
+ ResultStatus ReadControlData(FileSys::NACP& nacp) override;
private:
std::unique_ptr<FileSys::NSP> nsp;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index bd5a83b49..e67e43c69 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -121,10 +121,11 @@ ResultStatus AppLoader_XCI::ReadTitle(std::string& title) {
return ResultStatus::Success;
}
-ResultStatus AppLoader_XCI::ReadDeveloper(std::string& developer) {
+ResultStatus AppLoader_XCI::ReadControlData(FileSys::NACP& control) {
if (nacp_file == nullptr)
return ResultStatus::ErrorNoControl;
- developer = nacp_file->GetDeveloperName();
+ control = *nacp_file;
return ResultStatus::Success;
}
+
} // namespace Loader
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 15d1b1a23..9d3923f62 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -43,7 +43,7 @@ public:
ResultStatus ReadProgramId(u64& out_program_id) override;
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
ResultStatus ReadTitle(std::string& title) override;
- ResultStatus ReadDeveloper(std::string& developer) override;
+ ResultStatus ReadControlData(FileSys::NACP& control) override;
private:
std::unique_ptr<FileSys::XCI> xci;