diff options
Diffstat (limited to 'src/core')
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; |