diff options
Diffstat (limited to 'src/core/hle')
23 files changed, 556 insertions, 100 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index a38ee117b..757e5f21f 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -181,7 +181,12 @@ void KernelCore::AppendNewProcess(SharedPtr<Process> process) { void KernelCore::MakeCurrentProcess(Process* process) { impl->current_process = process; - Memory::SetCurrentPageTable(&process->VMManager().page_table); + + if (process == nullptr) { + return; + } + + Memory::SetCurrentPageTable(*process); } Process* KernelCore::CurrentProcess() { diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 0ace3d21c..20d01fc88 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -28,21 +28,20 @@ namespace { * * @param owner_process The parent process for the main thread * @param kernel The kernel instance to create the main thread under. - * @param entry_point The address at which the thread should start execution * @param priority The priority to give the main thread */ -void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) { - // Initialize new "main" thread - const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress(); +void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) { + const auto& vm_manager = owner_process.VMManager(); + const VAddr entry_point = vm_manager.GetCodeRegionBaseAddress(); + const VAddr stack_top = vm_manager.GetTLSIORegionEndAddress(); auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, owner_process.GetIdealCore(), stack_top, owner_process); SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); // Register 1 must be a handle to the main thread - const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); - thread->SetGuestHandle(guest_handle); - thread->GetContext().cpu_registers[1] = guest_handle; + const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); + thread->GetContext().cpu_registers[1] = thread_handle; // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires thread->ResumeFromWait(); @@ -106,8 +105,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { is_64bit_process = metadata.Is64BitProgram(); vm_manager.Reset(metadata.GetAddressSpaceType()); - // Ensure that the potentially resized page table is seen by CPU backends. - Memory::SetCurrentPageTable(&vm_manager.page_table); const auto& caps = metadata.GetKernelCapabilities(); const auto capability_init_result = @@ -119,7 +116,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { return handle_table.SetSize(capabilities.GetHandleTableSize()); } -void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) { +void Process::Run(s32 main_thread_priority, u64 stack_size) { // The kernel always ensures that the given stack size is page aligned. main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE); @@ -135,7 +132,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) { vm_manager.LogLayout(); ChangeStatus(ProcessStatus::Running); - SetupMainThread(*this, kernel, entry_point, main_thread_priority); + SetupMainThread(*this, kernel, main_thread_priority); } void Process::PrepareForTermination() { @@ -241,9 +238,6 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) { MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData); code_memory_size += module_.memory.size(); - - // Clear instruction cache in CPU JIT - system.InvalidateCpuInstructionCaches(); } Process::Process(Core::System& system) diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index dda52f4c0..bf3b7eef3 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -225,9 +225,12 @@ public: ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata); /** - * Applies address space changes and launches the process main thread. + * Starts the main application thread for this process. + * + * @param main_thread_priority The priority for the main thread. + * @param stack_size The stack size for the main thread in bytes. */ - void Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size); + void Run(s32 main_thread_priority, u64 stack_size); /** * Prepares a process for termination by stopping all of its threads diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index ea3fdc315..2dcf174c5 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1378,20 +1378,22 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e return ERR_INVALID_THREAD_PRIORITY; } - const std::string name = fmt::format("thread-{:X}", entry_point); auto& kernel = system.Kernel(); CASCADE_RESULT(SharedPtr<Thread> thread, - Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top, + Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top, *current_process)); - const auto new_guest_handle = current_process->GetHandleTable().Create(thread); - if (new_guest_handle.Failed()) { + const auto new_thread_handle = current_process->GetHandleTable().Create(thread); + if (new_thread_handle.Failed()) { LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}", - new_guest_handle.Code().raw); - return new_guest_handle.Code(); + new_thread_handle.Code().raw); + return new_thread_handle.Code(); } - thread->SetGuestHandle(*new_guest_handle); - *out_handle = *new_guest_handle; + *out_handle = *new_thread_handle; + + // Set the thread name for debugging purposes. + thread->SetName( + fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle)); system.CpuCore(thread->GetProcessorID()).PrepareReschedule(); @@ -2286,7 +2288,7 @@ static const FunctionDef SVC_Table[] = { {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"}, {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"}, - {0x36, nullptr, "Unknown"}, + {0x36, nullptr, "SynchronizePreemptionState"}, {0x37, nullptr, "Unknown"}, {0x38, nullptr, "Unknown"}, {0x39, nullptr, "Unknown"}, diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 62ce7bfda..f07332f02 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -101,6 +101,11 @@ public: std::string GetName() const override { return name; } + + void SetName(std::string new_name) { + name = std::move(new_name); + } + std::string GetTypeName() const override { return "Thread"; } @@ -343,10 +348,6 @@ public: arb_wait_address = address; } - void SetGuestHandle(Handle handle) { - guest_handle = handle; - } - bool HasWakeupCallback() const { return wakeup_callback != nullptr; } @@ -440,9 +441,6 @@ private: /// If waiting for an AddressArbiter, this is the address being waited on. VAddr arb_wait_address{0}; - /// Handle used by guest emulated application to access this thread - Handle guest_handle = 0; - /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. Handle callback_handle = 0; diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index 38d8a6e0c..0e96ba872 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -30,7 +30,7 @@ void WaitObject::RemoveWaitingThread(Thread* thread) { waiting_threads.erase(itr); } -SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { +SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() const { Thread* candidate = nullptr; u32 candidate_priority = THREADPRIO_LOWEST + 1; diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h index 04464a51a..3271a30a7 100644 --- a/src/core/hle/kernel/wait_object.h +++ b/src/core/hle/kernel/wait_object.h @@ -54,7 +54,7 @@ public: void WakeupWaitingThread(SharedPtr<Thread> thread); /// Obtains the highest priority thread that is ready to run from this object's waiting list. - SharedPtr<Thread> GetHighestPriorityReadyThread(); + SharedPtr<Thread> GetHighestPriorityReadyThread() const; /// Get a const reference to the waiting threads list for debug use const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 1aa4ce1ac..26a665bfd 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -22,7 +22,6 @@ #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/applets/web_browser.h" #include "core/hle/service/am/idle.h" #include "core/hle/service/am/omm.h" @@ -42,12 +41,6 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2}; constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3}; constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7}; -enum class AppletId : u32 { - ProfileSelect = 0x10, - SoftwareKeyboard = 0x11, - LibAppletOff = 0x17, -}; - constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA; struct LaunchParameters { @@ -886,30 +879,16 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple 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>(); - case AppletId::LibAppletOff: - return std::make_shared<Applets::WebBrowser>(); - default: - LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!", - static_cast<u32>(id)); - return std::make_shared<Applets::StubApplet>(); - } -} - void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_id = rp.PopRaw<AppletId>(); + const auto applet_id = rp.PopRaw<Applets::AppletId>(); const auto applet_mode = rp.PopRaw<u32>(); LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", static_cast<u32>(applet_id), applet_mode); - const auto applet = GetAppletFromId(applet_id); + const auto& applet_manager{Core::System::GetInstance().GetAppletManager()}; + const auto applet = applet_manager.GetApplet(applet_id); if (applet == nullptr) { LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id)); diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index a6064c63f..7f70b10df 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -5,11 +5,21 @@ #include <cstring> #include "common/assert.h" #include "core/core.h" +#include "core/frontend/applets/error.h" +#include "core/frontend/applets/general_frontend.h" +#include "core/frontend/applets/profile_select.h" +#include "core/frontend/applets/software_keyboard.h" +#include "core/frontend/applets/web_browser.h" #include "core/hle/kernel/readable_event.h" #include "core/hle/kernel/server_session.h" #include "core/hle/kernel/writable_event.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/am/applets/error.h" +#include "core/hle/service/am/applets/general_backend.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/web_browser.h" namespace Service::AM::Applets { @@ -111,4 +121,76 @@ void Applet::Initialize() { initialized = true; } +AppletManager::AppletManager() = default; + +AppletManager::~AppletManager() = default; + +void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { + if (set.error != nullptr) + frontend.error = std::move(set.error); + if (set.photo_viewer != nullptr) + frontend.photo_viewer = std::move(set.photo_viewer); + if (set.profile_select != nullptr) + frontend.profile_select = std::move(set.profile_select); + if (set.software_keyboard != nullptr) + frontend.software_keyboard = std::move(set.software_keyboard); + if (set.web_browser != nullptr) + frontend.web_browser = std::move(set.web_browser); +} + +void AppletManager::SetDefaultAppletFrontendSet() { + frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); + frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>(); + frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>(); + frontend.software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>(); + frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); +} + +void AppletManager::SetDefaultAppletsIfMissing() { + if (frontend.error == nullptr) { + frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); + } + + if (frontend.photo_viewer == nullptr) { + frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>(); + } + + if (frontend.profile_select == nullptr) { + frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>(); + } + + if (frontend.software_keyboard == nullptr) { + frontend.software_keyboard = + std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>(); + } + + if (frontend.web_browser == nullptr) { + frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); + } +} + +void AppletManager::ClearAll() { + frontend = {}; +} + +std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const { + switch (id) { + case AppletId::Error: + return std::make_shared<Error>(*frontend.error); + case AppletId::ProfileSelect: + return std::make_shared<ProfileSelect>(*frontend.profile_select); + case AppletId::SoftwareKeyboard: + return std::make_shared<SoftwareKeyboard>(*frontend.software_keyboard); + case AppletId::PhotoViewer: + return std::make_shared<PhotoViewer>(*frontend.photo_viewer); + case AppletId::LibAppletOff: + return std::make_shared<WebBrowser>(*frontend.web_browser); + default: + UNIMPLEMENTED_MSG( + "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", + static_cast<u8>(id)); + return std::make_shared<StubApplet>(); + } +} + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 37424c379..7f932672c 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -12,12 +12,43 @@ union ResultCode; +namespace Core::Frontend { +class ErrorApplet; +class PhotoViewerApplet; +class ProfileSelectApplet; +class SoftwareKeyboardApplet; +class WebBrowserApplet; +} // namespace Core::Frontend + namespace Service::AM { class IStorage; namespace Applets { +enum class AppletId : u32 { + OverlayDisplay = 0x02, + QLaunch = 0x03, + Starter = 0x04, + Auth = 0x0A, + Cabinet = 0x0B, + Controller = 0x0C, + DataErase = 0x0D, + Error = 0x0E, + NetConnect = 0x0F, + ProfileSelect = 0x10, + SoftwareKeyboard = 0x11, + MiiEdit = 0x12, + LibAppletWeb = 0x13, + LibAppletShop = 0x14, + PhotoViewer = 0x15, + Settings = 0x16, + LibAppletOff = 0x17, + LibAppletWhitelisted = 0x18, + LibAppletAuth = 0x19, + MyPage = 0x1A, +}; + class AppletDataBroker final { public: AppletDataBroker(); @@ -105,5 +136,29 @@ protected: bool initialized = false; }; +struct AppletFrontendSet { + std::unique_ptr<Core::Frontend::ErrorApplet> error; + std::unique_ptr<Core::Frontend::PhotoViewerApplet> photo_viewer; + std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_select; + std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard; + std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser; +}; + +class AppletManager { +public: + AppletManager(); + ~AppletManager(); + + void SetAppletFrontendSet(AppletFrontendSet set); + void SetDefaultAppletFrontendSet(); + void SetDefaultAppletsIfMissing(); + void ClearAll(); + + std::shared_ptr<Applet> GetApplet(AppletId id) const; + +private: + AppletFrontendSet frontend; +}; + } // namespace Applets } // namespace Service::AM diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp new file mode 100644 index 000000000..04774bedc --- /dev/null +++ b/src/core/hle/service/am/applets/error.cpp @@ -0,0 +1,182 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <array> +#include <cstring> +#include "common/assert.h" +#include "common/logging/log.h" +#include "common/string_util.h" +#include "core/core.h" +#include "core/frontend/applets/error.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applets/error.h" + +namespace Service::AM::Applets { + +#pragma pack(push, 4) +struct ShowError { + u8 mode; + bool jump; + INSERT_PADDING_BYTES(4); + bool use_64bit_error_code; + INSERT_PADDING_BYTES(1); + u64 error_code_64; + u32 error_code_32; +}; +static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size."); +#pragma pack(pop) + +struct ShowErrorRecord { + u8 mode; + bool jump; + INSERT_PADDING_BYTES(6); + u64 error_code_64; + u64 posix_time; +}; +static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect size."); + +struct SystemErrorArg { + u8 mode; + bool jump; + INSERT_PADDING_BYTES(6); + u64 error_code_64; + std::array<char, 8> language_code; + std::array<char, 0x800> main_text; + std::array<char, 0x800> detail_text; +}; +static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect size."); + +struct ApplicationErrorArg { + u8 mode; + bool jump; + INSERT_PADDING_BYTES(6); + u32 error_code; + std::array<char, 8> language_code; + std::array<char, 0x800> main_text; + std::array<char, 0x800> detail_text; +}; +static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size."); + +union Error::ErrorArguments { + ShowError error; + ShowErrorRecord error_record; + SystemErrorArg system_error; + ApplicationErrorArg application_error; +}; + +namespace { +template <typename T> +void CopyArgumentData(const std::vector<u8>& data, T& variable) { + ASSERT(data.size() >= sizeof(T)); + std::memcpy(&variable, data.data(), sizeof(T)); +} + +ResultCode Decode64BitError(u64 error) { + const auto description = (error >> 32) & 0x1FFF; + auto module = error & 0x3FF; + if (module >= 2000) + module -= 2000; + module &= 0x1FF; + return {static_cast<ErrorModule>(module), static_cast<u32>(description)}; +} + +} // Anonymous namespace + +Error::Error(const Core::Frontend::ErrorApplet& frontend) : frontend(frontend) {} + +Error::~Error() = default; + +void Error::Initialize() { + Applet::Initialize(); + args = std::make_unique<ErrorArguments>(); + complete = false; + + const auto storage = broker.PopNormalDataToApplet(); + ASSERT(storage != nullptr); + const auto data = storage->GetData(); + + ASSERT(!data.empty()); + std::memcpy(&mode, data.data(), sizeof(ErrorAppletMode)); + + switch (mode) { + case ErrorAppletMode::ShowError: + CopyArgumentData(data, args->error); + if (args->error.use_64bit_error_code) { + error_code = Decode64BitError(args->error.error_code_64); + } else { + error_code = ResultCode(args->error.error_code_32); + } + break; + case ErrorAppletMode::ShowSystemError: + CopyArgumentData(data, args->system_error); + error_code = ResultCode(Decode64BitError(args->system_error.error_code_64)); + break; + case ErrorAppletMode::ShowApplicationError: + CopyArgumentData(data, args->application_error); + error_code = ResultCode(args->application_error.error_code); + break; + case ErrorAppletMode::ShowErrorRecord: + CopyArgumentData(data, args->error_record); + error_code = Decode64BitError(args->error_record.error_code_64); + break; + default: + UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode)); + } +} + +bool Error::TransactionComplete() const { + return complete; +} + +ResultCode Error::GetStatus() const { + return RESULT_SUCCESS; +} + +void Error::ExecuteInteractive() { + UNREACHABLE_MSG("Unexpected interactive applet data!"); +} + +void Error::Execute() { + if (complete) { + return; + } + + const auto callback = [this] { DisplayCompleted(); }; + + switch (mode) { + case ErrorAppletMode::ShowError: + frontend.ShowError(error_code, callback); + break; + case ErrorAppletMode::ShowSystemError: + case ErrorAppletMode::ShowApplicationError: { + const auto system = mode == ErrorAppletMode::ShowSystemError; + const auto& main_text = + system ? args->system_error.main_text : args->application_error.main_text; + const auto& detail_text = + system ? args->system_error.detail_text : args->application_error.detail_text; + + frontend.ShowCustomErrorText( + error_code, + Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()), + Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()), + callback); + break; + } + case ErrorAppletMode::ShowErrorRecord: + frontend.ShowErrorWithTimestamp( + error_code, std::chrono::seconds{args->error_record.posix_time}, callback); + break; + default: + UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode)); + DisplayCompleted(); + } +} + +void Error::DisplayCompleted() { + complete = true; + broker.PushNormalDataFromApplet(IStorage{{}}); + broker.SignalStateChanged(); +} + +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h new file mode 100644 index 000000000..a3590d181 --- /dev/null +++ b/src/core/hle/service/am/applets/error.h @@ -0,0 +1,47 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/result.h" +#include "core/hle/service/am/applets/applets.h" + +namespace Service::AM::Applets { + +enum class ErrorAppletMode : u8 { + ShowError = 0, + ShowSystemError = 1, + ShowApplicationError = 2, + ShowEula = 3, + ShowErrorPctl = 4, + ShowErrorRecord = 5, + ShowUpdateEula = 8, +}; + +class Error final : public Applet { +public: + explicit Error(const Core::Frontend::ErrorApplet& frontend); + ~Error() override; + + void Initialize() override; + + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; + + void DisplayCompleted(); + +private: + union ErrorArguments; + + const Core::Frontend::ErrorApplet& frontend; + ResultCode error_code = RESULT_SUCCESS; + ErrorAppletMode mode = ErrorAppletMode::ShowError; + std::unique_ptr<ErrorArguments> args; + + bool complete = false; +}; + +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/stub_applet.cpp b/src/core/hle/service/am/applets/general_backend.cpp index ed166b87d..c591b9ac2 100644 --- a/src/core/hle/service/am/applets/stub_applet.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp @@ -4,11 +4,15 @@ #include <string> +#include "common/assert.h" #include "common/hex_util.h" #include "common/logging/log.h" +#include "core/core.h" +#include "core/frontend/applets/general_frontend.h" +#include "core/hle/kernel/process.h" #include "core/hle/result.h" #include "core/hle/service/am/am.h" -#include "core/hle/service/am/applets/stub_applet.h" +#include "core/hle/service/am/applets/general_backend.h" namespace Service::AM::Applets { @@ -30,6 +34,55 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) { } } +PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {} + +PhotoViewer::~PhotoViewer() = default; + +void PhotoViewer::Initialize() { + Applet::Initialize(); + complete = false; + + const auto storage = broker.PopNormalDataToApplet(); + ASSERT(storage != nullptr); + const auto data = storage->GetData(); + ASSERT(!data.empty()); + mode = static_cast<PhotoViewerAppletMode>(data[0]); +} + +bool PhotoViewer::TransactionComplete() const { + return complete; +} + +ResultCode PhotoViewer::GetStatus() const { + return RESULT_SUCCESS; +} + +void PhotoViewer::ExecuteInteractive() { + UNREACHABLE_MSG("Unexpected interactive applet data."); +} + +void PhotoViewer::Execute() { + if (complete) + return; + + const auto callback = [this] { ViewFinished(); }; + switch (mode) { + case PhotoViewerAppletMode::CurrentApp: + frontend.ShowPhotosForApplication(Core::CurrentProcess()->GetTitleID(), callback); + break; + case PhotoViewerAppletMode::AllApps: + frontend.ShowAllPhotos(callback); + break; + default: + UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", static_cast<u8>(mode)); + } +} + +void PhotoViewer::ViewFinished() { + broker.PushNormalDataFromApplet(IStorage{{}}); + broker.SignalStateChanged(); +} + StubApplet::StubApplet() = default; StubApplet::~StubApplet() = default; @@ -67,4 +120,5 @@ void StubApplet::Execute() { broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)}); broker.SignalStateChanged(); } + } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h new file mode 100644 index 000000000..2dd255d7c --- /dev/null +++ b/src/core/hle/service/am/applets/general_backend.h @@ -0,0 +1,48 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/am/applets/applets.h" + +namespace Service::AM::Applets { + +enum class PhotoViewerAppletMode : u8 { + CurrentApp = 0, + AllApps = 1, +}; + +class PhotoViewer final : public Applet { +public: + explicit PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend); + ~PhotoViewer() override; + + void Initialize() override; + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; + + void ViewFinished(); + +private: + const Core::Frontend::PhotoViewerApplet& frontend; + bool complete = false; + PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; +}; + +class StubApplet final : public Applet { +public: + StubApplet(); + ~StubApplet() override; + + void Initialize() override; + + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; +}; + +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp index 14e2a1fee..d113bd2eb 100644 --- a/src/core/hle/service/am/applets/profile_select.cpp +++ b/src/core/hle/service/am/applets/profile_select.cpp @@ -15,7 +15,9 @@ namespace Service::AM::Applets { constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; -ProfileSelect::ProfileSelect() = default; +ProfileSelect::ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend) + : frontend(frontend) {} + ProfileSelect::~ProfileSelect() = default; void ProfileSelect::Initialize() { @@ -51,8 +53,6 @@ void ProfileSelect::Execute() { return; } - const auto& frontend{Core::System::GetInstance().GetProfileSelector()}; - frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); }); } diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h index 787485f22..a2ac6cf50 100644 --- a/src/core/hle/service/am/applets/profile_select.h +++ b/src/core/hle/service/am/applets/profile_select.h @@ -28,7 +28,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco class ProfileSelect final : public Applet { public: - ProfileSelect(); + explicit ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend); ~ProfileSelect() override; void Initialize() override; @@ -41,6 +41,8 @@ public: void SelectionComplete(std::optional<Account::UUID> uuid); private: + const Core::Frontend::ProfileSelectApplet& frontend; + UserSelectionConfig config; bool complete = false; ResultCode status = RESULT_SUCCESS; diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 8c5bd6059..e197990f7 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -39,7 +39,8 @@ static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( return params; } -SoftwareKeyboard::SoftwareKeyboard() = default; +SoftwareKeyboard::SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend) + : frontend(frontend) {} SoftwareKeyboard::~SoftwareKeyboard() = default; @@ -90,8 +91,6 @@ void SoftwareKeyboard::ExecuteInteractive() { if (status == INTERACTIVE_STATUS_OK) { complete = true; } else { - const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; - std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string; std::memcpy(string.data(), data.data() + 4, string.size() * 2); frontend.SendTextCheckDialog( @@ -106,8 +105,6 @@ void SoftwareKeyboard::Execute() { return; } - const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; - const auto parameters = ConvertToFrontendParameters(config, initial_text); frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); }, diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index b93a30d28..0fbc43e51 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h @@ -55,7 +55,7 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz class SoftwareKeyboard final : public Applet { public: - SoftwareKeyboard(); + explicit SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend); ~SoftwareKeyboard() override; void Initialize() override; @@ -68,6 +68,8 @@ public: void WriteText(std::optional<std::u16string> text); private: + const Core::Frontend::SoftwareKeyboardApplet& frontend; + KeyboardConfig config; std::u16string initial_text; bool complete = false; diff --git a/src/core/hle/service/am/applets/stub_applet.h b/src/core/hle/service/am/applets/stub_applet.h deleted file mode 100644 index 7d8dc968d..000000000 --- a/src/core/hle/service/am/applets/stub_applet.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/am/applets/applets.h" - -namespace Service::AM::Applets { - -class StubApplet final : public Applet { -public: - StubApplet(); - ~StubApplet() override; - - void Initialize() override; - - bool TransactionComplete() const override; - ResultCode GetStatus() const override; - void ExecuteInteractive() override; - void Execute() override; -}; - -} // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index 7e17df98a..7878f5136 100644 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp @@ -95,7 +95,7 @@ static FileSys::VirtualFile GetManualRomFS() { return nullptr; } -WebBrowser::WebBrowser() = default; +WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {} WebBrowser::~WebBrowser() = default; @@ -152,8 +152,6 @@ void WebBrowser::Execute() { return; } - auto& frontend{Core::System::GetInstance().GetWebBrowser()}; - frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); } diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h index b9e228fac..7e0f34c7d 100644 --- a/src/core/hle/service/am/applets/web_browser.h +++ b/src/core/hle/service/am/applets/web_browser.h @@ -12,7 +12,7 @@ namespace Service::AM::Applets { class WebBrowser final : public Applet { public: - WebBrowser(); + WebBrowser(Core::Frontend::WebBrowserApplet& frontend); ~WebBrowser() override; void Initialize() override; @@ -32,6 +32,8 @@ public: void Finalize(); private: + Core::Frontend::WebBrowserApplet& frontend; + bool complete = false; bool unpacked = false; ResultCode status = RESULT_SUCCESS; diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp index b6b71f966..f43e512e9 100644 --- a/src/core/hle/service/audio/audctl.cpp +++ b/src/core/hle/service/audio/audctl.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" #include "core/hle/service/audio/audctl.h" namespace Service::Audio { @@ -11,8 +13,8 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} { static const FunctionInfo functions[] = { {0, nullptr, "GetTargetVolume"}, {1, nullptr, "SetTargetVolume"}, - {2, nullptr, "GetTargetVolumeMin"}, - {3, nullptr, "GetTargetVolumeMax"}, + {2, &AudCtl::GetTargetVolumeMin, "GetTargetVolumeMin"}, + {3, &AudCtl::GetTargetVolumeMax, "GetTargetVolumeMax"}, {4, nullptr, "IsTargetMute"}, {5, nullptr, "SetTargetMute"}, {6, nullptr, "IsTargetConnected"}, @@ -44,4 +46,28 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} { AudCtl::~AudCtl() = default; +void AudCtl::GetTargetVolumeMin(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Audio, "called."); + + // This service function is currently hardcoded on the + // actual console to this value (as of 6.0.0). + constexpr s32 target_min_volume = 0; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(target_min_volume); +} + +void AudCtl::GetTargetVolumeMax(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Audio, "called."); + + // This service function is currently hardcoded on the + // actual console to this value (as of 6.0.0). + constexpr s32 target_max_volume = 15; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(target_max_volume); +} + } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h index 9d2d9e83b..c7fafc02e 100644 --- a/src/core/hle/service/audio/audctl.h +++ b/src/core/hle/service/audio/audctl.h @@ -12,6 +12,10 @@ class AudCtl final : public ServiceFramework<AudCtl> { public: explicit AudCtl(); ~AudCtl() override; + +private: + void GetTargetVolumeMin(Kernel::HLERequestContext& ctx); + void GetTargetVolumeMax(Kernel::HLERequestContext& ctx); }; } // namespace Service::Audio |