diff options
author | Liam <byteslice@airmail.cc> | 2023-12-31 02:51:23 +0100 |
---|---|---|
committer | Liam <byteslice@airmail.cc> | 2024-01-30 00:43:45 +0100 |
commit | 7de6b410305fcfcd34078e62fbe0ceedb43663f9 (patch) | |
tree | b5f3dc0d7631852a64466f3765e62e0707b8d0c8 /src/core/hle/service/am/library_applet_creator.cpp | |
parent | Merge pull request #12846 from german77/mii_const (diff) | |
download | yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.gz yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.bz2 yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.lz yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.xz yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.tar.zst yuzu-7de6b410305fcfcd34078e62fbe0ceedb43663f9.zip |
Diffstat (limited to 'src/core/hle/service/am/library_applet_creator.cpp')
-rw-r--r-- | src/core/hle/service/am/library_applet_creator.cpp | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp new file mode 100644 index 000000000..c33f50a40 --- /dev/null +++ b/src/core/hle/service/am/library_applet_creator.cpp @@ -0,0 +1,145 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/am/library_applet_accessor.h" +#include "core/hle/service/am/library_applet_creator.h" +#include "core/hle/service/am/storage.h" +#include "core/hle/service/ipc_helpers.h" + +namespace Service::AM { + +ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) + : ServiceFramework{system_, "ILibraryAppletCreator"} { + static const FunctionInfo functions[] = { + {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, + {1, nullptr, "TerminateAllLibraryApplets"}, + {2, nullptr, "AreAnyLibraryAppletsLeft"}, + {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, + {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, + {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"}, + }; + RegisterHandlers(functions); +} + +ILibraryAppletCreator::~ILibraryAppletCreator() = default; + +void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const auto applet_id = rp.PopRaw<Applets::AppletId>(); + const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>(); + + LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, + applet_mode); + + const auto& applet_manager{system.GetAppletManager()}; + const auto applet = applet_manager.GetApplet(applet_id, applet_mode); + + if (applet == nullptr) { + LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + + rb.Push(ResultSuccess); + rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); +} + +void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const s64 size{rp.Pop<s64>()}; + + LOG_DEBUG(Service_AM, "called, size={}", size); + + if (size <= 0) { + LOG_ERROR(Service_AM, "size is less than or equal to 0"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + return; + } + + std::vector<u8> buffer(size); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<IStorage>(system, std::move(buffer)); +} + +void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + struct Parameters { + u8 permissions; + s64 size; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; + const auto handle{ctx.GetCopyHandle(0)}; + + LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions, + parameters.size, handle); + + if (parameters.size <= 0) { + LOG_ERROR(Service_AM, "size is less than or equal to 0"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + return; + } + + auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); + + if (transfer_mem.IsNull()) { + LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + return; + } + + std::vector<u8> memory(transfer_mem->GetSize()); + ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<IStorage>(system, std::move(memory)); +} + +void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const s64 size{rp.Pop<s64>()}; + const auto handle{ctx.GetCopyHandle(0)}; + + LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle); + + if (size <= 0) { + LOG_ERROR(Service_AM, "size is less than or equal to 0"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + return; + } + + auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); + + if (transfer_mem.IsNull()) { + LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultUnknown); + return; + } + + std::vector<u8> memory(transfer_mem->GetSize()); + ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<IStorage>(system, std::move(memory)); +} + +} // namespace Service::AM |