summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp50
-rw-r--r--src/core/hle/kernel/svc.cpp8
-rw-r--r--src/core/hle/kernel/transfer_memory.cpp66
-rw-r--r--src/core/hle/kernel/transfer_memory.h19
-rw-r--r--src/core/hle/kernel/vm_manager.cpp3
-rw-r--r--src/core/hle/kernel/vm_manager.h60
-rw-r--r--src/core/hle/kernel/wait_object.cpp13
-rw-r--r--src/core/hle/service/am/am.cpp84
-rw-r--r--src/core/hle/service/am/am.h30
-rw-r--r--src/core/hle/service/am/applets/applets.cpp2
-rw-r--r--src/core/hle/service/am/applets/error.cpp2
-rw-r--r--src/core/hle/service/am/applets/general_backend.cpp4
-rw-r--r--src/core/hle/service/am/applets/profile_select.cpp4
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp13
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp2
-rw-r--r--src/core/hle/service/prepo/prepo.cpp30
16 files changed, 265 insertions, 125 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 2db28dcf0..ab05788d7 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -284,13 +284,18 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
284 284
285std::vector<u8> HLERequestContext::ReadBuffer(int buffer_index) const { 285std::vector<u8> HLERequestContext::ReadBuffer(int buffer_index) const {
286 std::vector<u8> buffer; 286 std::vector<u8> buffer;
287 const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[buffer_index].Size()}; 287 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
288 BufferDescriptorA()[buffer_index].Size()};
288 auto& memory = Core::System::GetInstance().Memory(); 289 auto& memory = Core::System::GetInstance().Memory();
289 290
290 if (is_buffer_a) { 291 if (is_buffer_a) {
292 ASSERT_MSG(BufferDescriptorA().size() > buffer_index,
293 "BufferDescriptorA invalid buffer_index {}", buffer_index);
291 buffer.resize(BufferDescriptorA()[buffer_index].Size()); 294 buffer.resize(BufferDescriptorA()[buffer_index].Size());
292 memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); 295 memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size());
293 } else { 296 } else {
297 ASSERT_MSG(BufferDescriptorX().size() > buffer_index,
298 "BufferDescriptorX invalid buffer_index {}", buffer_index);
294 buffer.resize(BufferDescriptorX()[buffer_index].Size()); 299 buffer.resize(BufferDescriptorX()[buffer_index].Size());
295 memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); 300 memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size());
296 } 301 }
@@ -305,7 +310,8 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
305 return 0; 310 return 0;
306 } 311 }
307 312
308 const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[buffer_index].Size()}; 313 const bool is_buffer_b{BufferDescriptorB().size() > buffer_index &&
314 BufferDescriptorB()[buffer_index].Size()};
309 const std::size_t buffer_size{GetWriteBufferSize(buffer_index)}; 315 const std::size_t buffer_size{GetWriteBufferSize(buffer_index)};
310 if (size > buffer_size) { 316 if (size > buffer_size) {
311 LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, 317 LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size,
@@ -315,8 +321,16 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
315 321
316 auto& memory = Core::System::GetInstance().Memory(); 322 auto& memory = Core::System::GetInstance().Memory();
317 if (is_buffer_b) { 323 if (is_buffer_b) {
324 ASSERT_MSG(BufferDescriptorB().size() > buffer_index,
325 "BufferDescriptorB invalid buffer_index {}", buffer_index);
326 ASSERT_MSG(BufferDescriptorB()[buffer_index].Size() >= size,
327 "BufferDescriptorB buffer_index {} is not large enough", buffer_index);
318 memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); 328 memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size);
319 } else { 329 } else {
330 ASSERT_MSG(BufferDescriptorC().size() > buffer_index,
331 "BufferDescriptorC invalid buffer_index {}", buffer_index);
332 ASSERT_MSG(BufferDescriptorC()[buffer_index].Size() >= size,
333 "BufferDescriptorC buffer_index {} is not large enough", buffer_index);
320 memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); 334 memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size);
321 } 335 }
322 336
@@ -324,15 +338,35 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
324} 338}
325 339
326std::size_t HLERequestContext::GetReadBufferSize(int buffer_index) const { 340std::size_t HLERequestContext::GetReadBufferSize(int buffer_index) const {
327 const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[buffer_index].Size()}; 341 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
328 return is_buffer_a ? BufferDescriptorA()[buffer_index].Size() 342 BufferDescriptorA()[buffer_index].Size()};
329 : BufferDescriptorX()[buffer_index].Size(); 343 if (is_buffer_a) {
344 ASSERT_MSG(BufferDescriptorA().size() > buffer_index,
345 "BufferDescriptorA invalid buffer_index {}", buffer_index);
346 ASSERT_MSG(BufferDescriptorA()[buffer_index].Size() > 0,
347 "BufferDescriptorA buffer_index {} is empty", buffer_index);
348 return BufferDescriptorA()[buffer_index].Size();
349 } else {
350 ASSERT_MSG(BufferDescriptorX().size() > buffer_index,
351 "BufferDescriptorX invalid buffer_index {}", buffer_index);
352 ASSERT_MSG(BufferDescriptorX()[buffer_index].Size() > 0,
353 "BufferDescriptorX buffer_index {} is empty", buffer_index);
354 return BufferDescriptorX()[buffer_index].Size();
355 }
330} 356}
331 357
332std::size_t HLERequestContext::GetWriteBufferSize(int buffer_index) const { 358std::size_t HLERequestContext::GetWriteBufferSize(int buffer_index) const {
333 const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[buffer_index].Size()}; 359 const bool is_buffer_b{BufferDescriptorB().size() > buffer_index &&
334 return is_buffer_b ? BufferDescriptorB()[buffer_index].Size() 360 BufferDescriptorB()[buffer_index].Size()};
335 : BufferDescriptorC()[buffer_index].Size(); 361 if (is_buffer_b) {
362 ASSERT_MSG(BufferDescriptorB().size() > buffer_index,
363 "BufferDescriptorB invalid buffer_index {}", buffer_index);
364 return BufferDescriptorB()[buffer_index].Size();
365 } else {
366 ASSERT_MSG(BufferDescriptorC().size() > buffer_index,
367 "BufferDescriptorC invalid buffer_index {}", buffer_index);
368 return BufferDescriptorC()[buffer_index].Size();
369 }
336} 370}
337 371
338std::string HLERequestContext::Description() const { 372std::string HLERequestContext::Description() const {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 1d99bf7a2..9cae5c73d 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1863,10 +1863,14 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
1863 } 1863 }
1864 1864
1865 auto& kernel = system.Kernel(); 1865 auto& kernel = system.Kernel();
1866 auto transfer_mem_handle = TransferMemory::Create(kernel, addr, size, perms); 1866 auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms);
1867
1868 if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) {
1869 return reserve_result;
1870 }
1867 1871
1868 auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); 1872 auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
1869 const auto result = handle_table.Create(std::move(transfer_mem_handle)); 1873 const auto result{handle_table.Create(std::move(transfer_mem_handle))};
1870 if (result.Failed()) { 1874 if (result.Failed()) {
1871 return result.Code(); 1875 return result.Code();
1872 } 1876 }
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp
index f0e73f57b..f2d3f8b49 100644
--- a/src/core/hle/kernel/transfer_memory.cpp
+++ b/src/core/hle/kernel/transfer_memory.cpp
@@ -8,15 +8,23 @@
8#include "core/hle/kernel/shared_memory.h" 8#include "core/hle/kernel/shared_memory.h"
9#include "core/hle/kernel/transfer_memory.h" 9#include "core/hle/kernel/transfer_memory.h"
10#include "core/hle/result.h" 10#include "core/hle/result.h"
11#include "core/memory.h"
11 12
12namespace Kernel { 13namespace Kernel {
13 14
14TransferMemory::TransferMemory(KernelCore& kernel) : Object{kernel} {} 15TransferMemory::TransferMemory(KernelCore& kernel, Memory::Memory& memory)
15TransferMemory::~TransferMemory() = default; 16 : Object{kernel}, memory{memory} {}
16 17
17std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address, 18TransferMemory::~TransferMemory() {
18 u64 size, MemoryPermission permissions) { 19 // Release memory region when transfer memory is destroyed
19 std::shared_ptr<TransferMemory> transfer_memory{std::make_shared<TransferMemory>(kernel)}; 20 Reset();
21}
22
23std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, Memory::Memory& memory,
24 VAddr base_address, u64 size,
25 MemoryPermission permissions) {
26 std::shared_ptr<TransferMemory> transfer_memory{
27 std::make_shared<TransferMemory>(kernel, memory)};
20 28
21 transfer_memory->base_address = base_address; 29 transfer_memory->base_address = base_address;
22 transfer_memory->memory_size = size; 30 transfer_memory->memory_size = size;
@@ -27,7 +35,7 @@ std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr
27} 35}
28 36
29const u8* TransferMemory::GetPointer() const { 37const u8* TransferMemory::GetPointer() const {
30 return backing_block.get()->data(); 38 return memory.GetPointer(base_address);
31} 39}
32 40
33u64 TransferMemory::GetSize() const { 41u64 TransferMemory::GetSize() const {
@@ -62,6 +70,52 @@ ResultCode TransferMemory::MapMemory(VAddr address, u64 size, MemoryPermission p
62 return RESULT_SUCCESS; 70 return RESULT_SUCCESS;
63} 71}
64 72
73ResultCode TransferMemory::Reserve() {
74 auto& vm_manager{owner_process->VMManager()};
75 const auto check_range_result{vm_manager.CheckRangeState(
76 base_address, memory_size, MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated,
77 MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated, VMAPermission::All,
78 VMAPermission::ReadWrite, MemoryAttribute::Mask, MemoryAttribute::None,
79 MemoryAttribute::IpcAndDeviceMapped)};
80
81 if (check_range_result.Failed()) {
82 return check_range_result.Code();
83 }
84
85 auto [state_, permissions_, attribute] = *check_range_result;
86
87 if (const auto result{vm_manager.ReprotectRange(
88 base_address, memory_size, SharedMemory::ConvertPermissions(owner_permissions))};
89 result.IsError()) {
90 return result;
91 }
92
93 return vm_manager.SetMemoryAttribute(base_address, memory_size, MemoryAttribute::Mask,
94 attribute | MemoryAttribute::Locked);
95}
96
97ResultCode TransferMemory::Reset() {
98 auto& vm_manager{owner_process->VMManager()};
99 if (const auto result{vm_manager.CheckRangeState(
100 base_address, memory_size,
101 MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated,
102 MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated, VMAPermission::None,
103 VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::Locked,
104 MemoryAttribute::IpcAndDeviceMapped)};
105 result.Failed()) {
106 return result.Code();
107 }
108
109 if (const auto result{
110 vm_manager.ReprotectRange(base_address, memory_size, VMAPermission::ReadWrite)};
111 result.IsError()) {
112 return result;
113 }
114
115 return vm_manager.SetMemoryAttribute(base_address, memory_size, MemoryAttribute::Mask,
116 MemoryAttribute::None);
117}
118
65ResultCode TransferMemory::UnmapMemory(VAddr address, u64 size) { 119ResultCode TransferMemory::UnmapMemory(VAddr address, u64 size) {
66 if (memory_size != size) { 120 if (memory_size != size) {
67 return ERR_INVALID_SIZE; 121 return ERR_INVALID_SIZE;
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h
index 0a6e15d18..6e388536a 100644
--- a/src/core/hle/kernel/transfer_memory.h
+++ b/src/core/hle/kernel/transfer_memory.h
@@ -11,6 +11,10 @@
11 11
12union ResultCode; 12union ResultCode;
13 13
14namespace Memory {
15class Memory;
16}
17
14namespace Kernel { 18namespace Kernel {
15 19
16class KernelCore; 20class KernelCore;
@@ -26,12 +30,13 @@ enum class MemoryPermission : u32;
26/// 30///
27class TransferMemory final : public Object { 31class TransferMemory final : public Object {
28public: 32public:
29 explicit TransferMemory(KernelCore& kernel); 33 explicit TransferMemory(KernelCore& kernel, Memory::Memory& memory);
30 ~TransferMemory() override; 34 ~TransferMemory() override;
31 35
32 static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; 36 static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
33 37
34 static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, u64 size, 38 static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Memory::Memory& memory,
39 VAddr base_address, u64 size,
35 MemoryPermission permissions); 40 MemoryPermission permissions);
36 41
37 TransferMemory(const TransferMemory&) = delete; 42 TransferMemory(const TransferMemory&) = delete;
@@ -80,6 +85,14 @@ public:
80 /// 85 ///
81 ResultCode UnmapMemory(VAddr address, u64 size); 86 ResultCode UnmapMemory(VAddr address, u64 size);
82 87
88 /// Reserves the region to be used for the transfer memory, called after the transfer memory is
89 /// created.
90 ResultCode Reserve();
91
92 /// Resets the region previously used for the transfer memory, called after the transfer memory
93 /// is closed.
94 ResultCode Reset();
95
83private: 96private:
84 /// Memory block backing this instance. 97 /// Memory block backing this instance.
85 std::shared_ptr<PhysicalMemory> backing_block; 98 std::shared_ptr<PhysicalMemory> backing_block;
@@ -98,6 +111,8 @@ private:
98 111
99 /// Whether or not this transfer memory instance has mapped memory. 112 /// Whether or not this transfer memory instance has mapped memory.
100 bool is_mapped = false; 113 bool is_mapped = false;
114
115 Memory::Memory& memory;
101}; 116};
102 117
103} // namespace Kernel 118} // namespace Kernel
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 0b3500fce..024c22901 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -544,7 +544,8 @@ MemoryInfo VMManager::QueryMemory(VAddr address) const {
544 544
545ResultCode VMManager::SetMemoryAttribute(VAddr address, u64 size, MemoryAttribute mask, 545ResultCode VMManager::SetMemoryAttribute(VAddr address, u64 size, MemoryAttribute mask,
546 MemoryAttribute attribute) { 546 MemoryAttribute attribute) {
547 constexpr auto ignore_mask = MemoryAttribute::Uncached | MemoryAttribute::DeviceMapped; 547 constexpr auto ignore_mask =
548 MemoryAttribute::Uncached | MemoryAttribute::DeviceMapped | MemoryAttribute::Locked;
548 constexpr auto attribute_mask = ~ignore_mask; 549 constexpr auto attribute_mask = ~ignore_mask;
549 550
550 const auto result = CheckRangeState( 551 const auto result = CheckRangeState(
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 850a7ebc3..90b4b006a 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -98,6 +98,8 @@ enum class MemoryAttribute : u32 {
98 DeviceMapped = 4, 98 DeviceMapped = 4,
99 /// Uncached memory 99 /// Uncached memory
100 Uncached = 8, 100 Uncached = 8,
101
102 IpcAndDeviceMapped = LockedForIPC | DeviceMapped,
101}; 103};
102 104
103constexpr MemoryAttribute operator|(MemoryAttribute lhs, MemoryAttribute rhs) { 105constexpr MemoryAttribute operator|(MemoryAttribute lhs, MemoryAttribute rhs) {
@@ -654,6 +656,35 @@ public:
654 /// is scheduled. 656 /// is scheduled.
655 Common::PageTable page_table{Memory::PAGE_BITS}; 657 Common::PageTable page_table{Memory::PAGE_BITS};
656 658
659 using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>;
660
661 /// Checks if an address range adheres to the specified states provided.
662 ///
663 /// @param address The starting address of the address range.
664 /// @param size The size of the address range.
665 /// @param state_mask The memory state mask.
666 /// @param state The state to compare the individual VMA states against,
667 /// which is done in the form of: (vma.state & state_mask) != state.
668 /// @param permission_mask The memory permissions mask.
669 /// @param permissions The permission to compare the individual VMA permissions against,
670 /// which is done in the form of:
671 /// (vma.permission & permission_mask) != permission.
672 /// @param attribute_mask The memory attribute mask.
673 /// @param attribute The memory attributes to compare the individual VMA attributes
674 /// against, which is done in the form of:
675 /// (vma.attributes & attribute_mask) != attribute.
676 /// @param ignore_mask The memory attributes to ignore during the check.
677 ///
678 /// @returns If successful, returns a tuple containing the memory attributes
679 /// (with ignored bits specified by ignore_mask unset), memory permissions, and
680 /// memory state across the memory range.
681 /// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE.
682 ///
683 CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state,
684 VMAPermission permission_mask, VMAPermission permissions,
685 MemoryAttribute attribute_mask, MemoryAttribute attribute,
686 MemoryAttribute ignore_mask) const;
687
657private: 688private:
658 using VMAIter = VMAMap::iterator; 689 using VMAIter = VMAMap::iterator;
659 690
@@ -707,35 +738,6 @@ private:
707 /// Clears out the page table 738 /// Clears out the page table
708 void ClearPageTable(); 739 void ClearPageTable();
709 740
710 using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>;
711
712 /// Checks if an address range adheres to the specified states provided.
713 ///
714 /// @param address The starting address of the address range.
715 /// @param size The size of the address range.
716 /// @param state_mask The memory state mask.
717 /// @param state The state to compare the individual VMA states against,
718 /// which is done in the form of: (vma.state & state_mask) != state.
719 /// @param permission_mask The memory permissions mask.
720 /// @param permissions The permission to compare the individual VMA permissions against,
721 /// which is done in the form of:
722 /// (vma.permission & permission_mask) != permission.
723 /// @param attribute_mask The memory attribute mask.
724 /// @param attribute The memory attributes to compare the individual VMA attributes
725 /// against, which is done in the form of:
726 /// (vma.attributes & attribute_mask) != attribute.
727 /// @param ignore_mask The memory attributes to ignore during the check.
728 ///
729 /// @returns If successful, returns a tuple containing the memory attributes
730 /// (with ignored bits specified by ignore_mask unset), memory permissions, and
731 /// memory state across the memory range.
732 /// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE.
733 ///
734 CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state,
735 VMAPermission permission_mask, VMAPermission permissions,
736 MemoryAttribute attribute_mask, MemoryAttribute attribute,
737 MemoryAttribute ignore_mask) const;
738
739 /// Gets the amount of memory currently mapped (state != Unmapped) in a range. 741 /// Gets the amount of memory currently mapped (state != Unmapped) in a range.
740 ResultVal<std::size_t> SizeOfAllocatedVMAsInRange(VAddr address, std::size_t size) const; 742 ResultVal<std::size_t> SizeOfAllocatedVMAsInRange(VAddr address, std::size_t size) const;
741 743
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index a0c806e8f..1838260fd 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -50,17 +50,8 @@ std::shared_ptr<Thread> WaitObject::GetHighestPriorityReadyThread() const {
50 if (ShouldWait(thread.get())) 50 if (ShouldWait(thread.get()))
51 continue; 51 continue;
52 52
53 // A thread is ready to run if it's either in ThreadStatus::WaitSynch 53 candidate = thread.get();
54 // and the rest of the objects it is waiting on are ready. 54 candidate_priority = thread->GetPriority();
55 bool ready_to_run = true;
56 if (thread_status == ThreadStatus::WaitSynch) {
57 ready_to_run = thread->AllWaitObjectsReady();
58 }
59
60 if (ready_to_run) {
61 candidate = thread.get();
62 candidate_priority = thread->GetPriority();
63 }
64 } 55 }
65 56
66 return SharedFrom(candidate); 57 return SharedFrom(candidate);
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 95aa5d23d..c1550013a 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -709,8 +709,34 @@ void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) {
709 apm_sys->SetCpuBoostMode(ctx); 709 apm_sys->SetCpuBoostMode(ctx);
710} 710}
711 711
712IStorage::IStorage(std::vector<u8> buffer) 712IStorageImpl::~IStorageImpl() = default;
713 : ServiceFramework("IStorage"), buffer(std::move(buffer)) { 713
714class StorageDataImpl final : public IStorageImpl {
715public:
716 explicit StorageDataImpl(std::vector<u8>&& buffer) : buffer{std::move(buffer)} {}
717
718 std::vector<u8>& GetData() override {
719 return buffer;
720 }
721
722 const std::vector<u8>& GetData() const override {
723 return buffer;
724 }
725
726 std::size_t GetSize() const override {
727 return buffer.size();
728 }
729
730private:
731 std::vector<u8> buffer;
732};
733
734IStorage::IStorage(std::vector<u8>&& buffer)
735 : ServiceFramework("IStorage"), impl{std::make_shared<StorageDataImpl>(std::move(buffer))} {
736 Register();
737}
738
739void IStorage::Register() {
714 // clang-format off 740 // clang-format off
715 static const FunctionInfo functions[] = { 741 static const FunctionInfo functions[] = {
716 {0, &IStorage::Open, "Open"}, 742 {0, &IStorage::Open, "Open"},
@@ -723,8 +749,13 @@ IStorage::IStorage(std::vector<u8> buffer)
723 749
724IStorage::~IStorage() = default; 750IStorage::~IStorage() = default;
725 751
726const std::vector<u8>& IStorage::GetData() const { 752void IStorage::Open(Kernel::HLERequestContext& ctx) {
727 return buffer; 753 LOG_DEBUG(Service_AM, "called");
754
755 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
756
757 rb.Push(RESULT_SUCCESS);
758 rb.PushIpcInterface<IStorageAccessor>(*this);
728} 759}
729 760
730void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { 761void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
@@ -825,17 +856,16 @@ private:
825 void PopOutData(Kernel::HLERequestContext& ctx) { 856 void PopOutData(Kernel::HLERequestContext& ctx) {
826 LOG_DEBUG(Service_AM, "called"); 857 LOG_DEBUG(Service_AM, "called");
827 858
828 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
829
830 const auto storage = applet->GetBroker().PopNormalDataToGame(); 859 const auto storage = applet->GetBroker().PopNormalDataToGame();
831 if (storage == nullptr) { 860 if (storage == nullptr) {
832 LOG_ERROR(Service_AM, 861 LOG_ERROR(Service_AM,
833 "storage is a nullptr. There is no data in the current normal channel"); 862 "storage is a nullptr. There is no data in the current normal channel");
834 863 IPC::ResponseBuilder rb{ctx, 2};
835 rb.Push(ERR_NO_DATA_IN_CHANNEL); 864 rb.Push(ERR_NO_DATA_IN_CHANNEL);
836 return; 865 return;
837 } 866 }
838 867
868 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
839 rb.Push(RESULT_SUCCESS); 869 rb.Push(RESULT_SUCCESS);
840 rb.PushIpcInterface<IStorage>(std::move(*storage)); 870 rb.PushIpcInterface<IStorage>(std::move(*storage));
841 } 871 }
@@ -857,17 +887,16 @@ private:
857 void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { 887 void PopInteractiveOutData(Kernel::HLERequestContext& ctx) {
858 LOG_DEBUG(Service_AM, "called"); 888 LOG_DEBUG(Service_AM, "called");
859 889
860 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
861
862 const auto storage = applet->GetBroker().PopInteractiveDataToGame(); 890 const auto storage = applet->GetBroker().PopInteractiveDataToGame();
863 if (storage == nullptr) { 891 if (storage == nullptr) {
864 LOG_ERROR(Service_AM, 892 LOG_ERROR(Service_AM,
865 "storage is a nullptr. There is no data in the current interactive channel"); 893 "storage is a nullptr. There is no data in the current interactive channel");
866 894 IPC::ResponseBuilder rb{ctx, 2};
867 rb.Push(ERR_NO_DATA_IN_CHANNEL); 895 rb.Push(ERR_NO_DATA_IN_CHANNEL);
868 return; 896 return;
869 } 897 }
870 898
899 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
871 rb.Push(RESULT_SUCCESS); 900 rb.Push(RESULT_SUCCESS);
872 rb.PushIpcInterface<IStorage>(std::move(*storage)); 901 rb.PushIpcInterface<IStorage>(std::move(*storage));
873 } 902 }
@@ -891,15 +920,6 @@ private:
891 std::shared_ptr<Applets::Applet> applet; 920 std::shared_ptr<Applets::Applet> applet;
892}; 921};
893 922
894void IStorage::Open(Kernel::HLERequestContext& ctx) {
895 LOG_DEBUG(Service_AM, "called");
896
897 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
898
899 rb.Push(RESULT_SUCCESS);
900 rb.PushIpcInterface<IStorageAccessor>(*this);
901}
902
903IStorageAccessor::IStorageAccessor(IStorage& storage) 923IStorageAccessor::IStorageAccessor(IStorage& storage)
904 : ServiceFramework("IStorageAccessor"), backing(storage) { 924 : ServiceFramework("IStorageAccessor"), backing(storage) {
905 // clang-format off 925 // clang-format off
@@ -921,7 +941,7 @@ void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) {
921 IPC::ResponseBuilder rb{ctx, 4}; 941 IPC::ResponseBuilder rb{ctx, 4};
922 942
923 rb.Push(RESULT_SUCCESS); 943 rb.Push(RESULT_SUCCESS);
924 rb.Push(static_cast<u64>(backing.buffer.size())); 944 rb.Push(static_cast<u64>(backing.GetSize()));
925} 945}
926 946
927void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { 947void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
@@ -932,17 +952,17 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
932 952
933 LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size()); 953 LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size());
934 954
935 if (data.size() > backing.buffer.size() - offset) { 955 if (data.size() > backing.GetSize() - offset) {
936 LOG_ERROR(Service_AM, 956 LOG_ERROR(Service_AM,
937 "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}", 957 "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
938 backing.buffer.size(), data.size(), offset); 958 backing.GetSize(), data.size(), offset);
939 959
940 IPC::ResponseBuilder rb{ctx, 2}; 960 IPC::ResponseBuilder rb{ctx, 2};
941 rb.Push(ERR_SIZE_OUT_OF_BOUNDS); 961 rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
942 return; 962 return;
943 } 963 }
944 964
945 std::memcpy(backing.buffer.data() + offset, data.data(), data.size()); 965 std::memcpy(backing.GetData().data() + offset, data.data(), data.size());
946 966
947 IPC::ResponseBuilder rb{ctx, 2}; 967 IPC::ResponseBuilder rb{ctx, 2};
948 rb.Push(RESULT_SUCCESS); 968 rb.Push(RESULT_SUCCESS);
@@ -956,16 +976,16 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
956 976
957 LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); 977 LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
958 978
959 if (size > backing.buffer.size() - offset) { 979 if (size > backing.GetSize() - offset) {
960 LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}", 980 LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
961 backing.buffer.size(), size, offset); 981 backing.GetSize(), size, offset);
962 982
963 IPC::ResponseBuilder rb{ctx, 2}; 983 IPC::ResponseBuilder rb{ctx, 2};
964 rb.Push(ERR_SIZE_OUT_OF_BOUNDS); 984 rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
965 return; 985 return;
966 } 986 }
967 987
968 ctx.WriteBuffer(backing.buffer.data() + offset, size); 988 ctx.WriteBuffer(backing.GetData().data() + offset, size);
969 989
970 IPC::ResponseBuilder rb{ctx, 2}; 990 IPC::ResponseBuilder rb{ctx, 2};
971 rb.Push(RESULT_SUCCESS); 991 rb.Push(RESULT_SUCCESS);
@@ -1031,7 +1051,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
1031 rp.SetCurrentOffset(3); 1051 rp.SetCurrentOffset(3);
1032 const auto handle{rp.Pop<Kernel::Handle>()}; 1052 const auto handle{rp.Pop<Kernel::Handle>()};
1033 1053
1034 const auto transfer_mem = 1054 auto transfer_mem =
1035 system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); 1055 system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
1036 1056
1037 if (transfer_mem == nullptr) { 1057 if (transfer_mem == nullptr) {
@@ -1047,7 +1067,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
1047 1067
1048 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 1068 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1049 rb.Push(RESULT_SUCCESS); 1069 rb.Push(RESULT_SUCCESS);
1050 rb.PushIpcInterface(std::make_shared<IStorage>(std::move(memory))); 1070 rb.PushIpcInterface<IStorage>(std::move(memory));
1051} 1071}
1052 1072
1053IApplicationFunctions::IApplicationFunctions(Core::System& system_) 1073IApplicationFunctions::IApplicationFunctions(Core::System& system_)
@@ -1189,13 +1209,11 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
1189 u64 build_id{}; 1209 u64 build_id{};
1190 std::memcpy(&build_id, build_id_full.data(), sizeof(u64)); 1210 std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
1191 1211
1192 const auto data = 1212 auto data = backend->GetLaunchParameter({system.CurrentProcess()->GetTitleID(), build_id});
1193 backend->GetLaunchParameter({system.CurrentProcess()->GetTitleID(), build_id});
1194
1195 if (data.has_value()) { 1213 if (data.has_value()) {
1196 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 1214 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1197 rb.Push(RESULT_SUCCESS); 1215 rb.Push(RESULT_SUCCESS);
1198 rb.PushIpcInterface<AM::IStorage>(*data); 1216 rb.PushIpcInterface<IStorage>(std::move(*data));
1199 launch_popped_application_specific = true; 1217 launch_popped_application_specific = true;
1200 return; 1218 return;
1201 } 1219 }
@@ -1218,7 +1236,7 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
1218 std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); 1236 std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
1219 std::memcpy(buffer.data(), &params, buffer.size()); 1237 std::memcpy(buffer.data(), &params, buffer.size());
1220 1238
1221 rb.PushIpcInterface<AM::IStorage>(buffer); 1239 rb.PushIpcInterface<IStorage>(std::move(buffer));
1222 launch_popped_account_preselect = true; 1240 launch_popped_account_preselect = true;
1223 return; 1241 return;
1224 } 1242 }
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 448817be9..0b9a4332d 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -12,7 +12,8 @@
12 12
13namespace Kernel { 13namespace Kernel {
14class KernelCore; 14class KernelCore;
15} 15class TransferMemory;
16} // namespace Kernel
16 17
17namespace Service::NVFlinger { 18namespace Service::NVFlinger {
18class NVFlinger; 19class NVFlinger;
@@ -188,19 +189,36 @@ private:
188 std::shared_ptr<AppletMessageQueue> msg_queue; 189 std::shared_ptr<AppletMessageQueue> msg_queue;
189}; 190};
190 191
192class IStorageImpl {
193public:
194 virtual ~IStorageImpl();
195 virtual std::vector<u8>& GetData() = 0;
196 virtual const std::vector<u8>& GetData() const = 0;
197 virtual std::size_t GetSize() const = 0;
198};
199
191class IStorage final : public ServiceFramework<IStorage> { 200class IStorage final : public ServiceFramework<IStorage> {
192public: 201public:
193 explicit IStorage(std::vector<u8> buffer); 202 explicit IStorage(std::vector<u8>&& buffer);
194 ~IStorage() override; 203 ~IStorage() override;
195 204
196 const std::vector<u8>& GetData() const; 205 std::vector<u8>& GetData() {
206 return impl->GetData();
207 }
208
209 const std::vector<u8>& GetData() const {
210 return impl->GetData();
211 }
212
213 std::size_t GetSize() const {
214 return impl->GetSize();
215 }
197 216
198private: 217private:
218 void Register();
199 void Open(Kernel::HLERequestContext& ctx); 219 void Open(Kernel::HLERequestContext& ctx);
200 220
201 std::vector<u8> buffer; 221 std::shared_ptr<IStorageImpl> impl;
202
203 friend class IStorageAccessor;
204}; 222};
205 223
206class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { 224class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 92f995f8f..3e97ba218 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -56,6 +56,7 @@ std::unique_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
56 56
57 auto out = std::move(out_channel.front()); 57 auto out = std::move(out_channel.front());
58 out_channel.pop_front(); 58 out_channel.pop_front();
59 pop_out_data_event.writable->Clear();
59 return out; 60 return out;
60} 61}
61 62
@@ -74,6 +75,7 @@ std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
74 75
75 auto out = std::move(out_interactive_channel.front()); 76 auto out = std::move(out_interactive_channel.front());
76 out_interactive_channel.pop_front(); 77 out_interactive_channel.pop_front();
78 pop_interactive_out_data_event.writable->Clear();
77 return out; 79 return out;
78} 80}
79 81
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
index eab0d42c9..e6c4e8b87 100644
--- a/src/core/hle/service/am/applets/error.cpp
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -186,7 +186,7 @@ void Error::Execute() {
186 186
187void Error::DisplayCompleted() { 187void Error::DisplayCompleted() {
188 complete = true; 188 complete = true;
189 broker.PushNormalDataFromApplet(IStorage{{}}); 189 broker.PushNormalDataFromApplet(IStorage{std::vector<u8>{}});
190 broker.SignalStateChanged(); 190 broker.SignalStateChanged();
191} 191}
192 192
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index 328438a1d..fe8400a15 100644
--- a/src/core/hle/service/am/applets/general_backend.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -148,7 +148,7 @@ void Auth::AuthFinished(bool successful) {
148 std::vector<u8> out(sizeof(Return)); 148 std::vector<u8> out(sizeof(Return));
149 std::memcpy(out.data(), &return_, sizeof(Return)); 149 std::memcpy(out.data(), &return_, sizeof(Return));
150 150
151 broker.PushNormalDataFromApplet(IStorage{out}); 151 broker.PushNormalDataFromApplet(IStorage{std::move(out)});
152 broker.SignalStateChanged(); 152 broker.SignalStateChanged();
153} 153}
154 154
@@ -198,7 +198,7 @@ void PhotoViewer::Execute() {
198} 198}
199 199
200void PhotoViewer::ViewFinished() { 200void PhotoViewer::ViewFinished() {
201 broker.PushNormalDataFromApplet(IStorage{{}}); 201 broker.PushNormalDataFromApplet(IStorage{std::vector<u8>{}});
202 broker.SignalStateChanged(); 202 broker.SignalStateChanged();
203} 203}
204 204
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index 3eba696ca..91d00f72a 100644
--- a/src/core/hle/service/am/applets/profile_select.cpp
+++ b/src/core/hle/service/am/applets/profile_select.cpp
@@ -50,7 +50,7 @@ void ProfileSelect::ExecuteInteractive() {
50 50
51void ProfileSelect::Execute() { 51void ProfileSelect::Execute() {
52 if (complete) { 52 if (complete) {
53 broker.PushNormalDataFromApplet(IStorage{final_data}); 53 broker.PushNormalDataFromApplet(IStorage{std::move(final_data)});
54 return; 54 return;
55 } 55 }
56 56
@@ -71,7 +71,7 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
71 71
72 final_data = std::vector<u8>(sizeof(UserSelectionOutput)); 72 final_data = std::vector<u8>(sizeof(UserSelectionOutput));
73 std::memcpy(final_data.data(), &output, final_data.size()); 73 std::memcpy(final_data.data(), &output, final_data.size());
74 broker.PushNormalDataFromApplet(IStorage{final_data}); 74 broker.PushNormalDataFromApplet(IStorage{std::move(final_data)});
75 broker.SignalStateChanged(); 75 broker.SignalStateChanged();
76} 76}
77 77
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 748559cd0..964c67202 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -102,7 +102,8 @@ void SoftwareKeyboard::ExecuteInteractive() {
102 102
103void SoftwareKeyboard::Execute() { 103void SoftwareKeyboard::Execute() {
104 if (complete) { 104 if (complete) {
105 broker.PushNormalDataFromApplet(IStorage{final_data}); 105 broker.PushNormalDataFromApplet(IStorage{std::move(final_data)});
106 broker.SignalStateChanged();
106 return; 107 return;
107 } 108 }
108 109
@@ -119,7 +120,7 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
119 std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE); 120 std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE);
120 121
121 if (config.utf_8) { 122 if (config.utf_8) {
122 const u64 size = text->size() + 8; 123 const u64 size = text->size() + sizeof(u64);
123 const auto new_text = Common::UTF16ToUTF8(*text); 124 const auto new_text = Common::UTF16ToUTF8(*text);
124 125
125 std::memcpy(output_sub.data(), &size, sizeof(u64)); 126 std::memcpy(output_sub.data(), &size, sizeof(u64));
@@ -130,7 +131,7 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
130 std::memcpy(output_main.data() + 4, new_text.data(), 131 std::memcpy(output_main.data() + 4, new_text.data(),
131 std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4)); 132 std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4));
132 } else { 133 } else {
133 const u64 size = text->size() * 2 + 8; 134 const u64 size = text->size() * 2 + sizeof(u64);
134 std::memcpy(output_sub.data(), &size, sizeof(u64)); 135 std::memcpy(output_sub.data(), &size, sizeof(u64));
135 std::memcpy(output_sub.data() + 8, text->data(), 136 std::memcpy(output_sub.data() + 8, text->data(),
136 std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8)); 137 std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8));
@@ -144,15 +145,15 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
144 final_data = output_main; 145 final_data = output_main;
145 146
146 if (complete) { 147 if (complete) {
147 broker.PushNormalDataFromApplet(IStorage{output_main}); 148 broker.PushNormalDataFromApplet(IStorage{std::move(output_main)});
148 broker.SignalStateChanged(); 149 broker.SignalStateChanged();
149 } else { 150 } else {
150 broker.PushInteractiveDataFromApplet(IStorage{output_sub}); 151 broker.PushInteractiveDataFromApplet(IStorage{std::move(output_sub)});
151 } 152 }
152 } else { 153 } else {
153 output_main[0] = 1; 154 output_main[0] = 1;
154 complete = true; 155 complete = true;
155 broker.PushNormalDataFromApplet(IStorage{output_main}); 156 broker.PushNormalDataFromApplet(IStorage{std::move(output_main)});
156 broker.SignalStateChanged(); 157 broker.SignalStateChanged();
157 } 158 }
158} 159}
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 5546ef6e8..05d6b3a19 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -284,7 +284,7 @@ void WebBrowser::Finalize() {
284 std::vector<u8> data(sizeof(WebCommonReturnValue)); 284 std::vector<u8> data(sizeof(WebCommonReturnValue));
285 std::memcpy(data.data(), &out, sizeof(WebCommonReturnValue)); 285 std::memcpy(data.data(), &out, sizeof(WebCommonReturnValue));
286 286
287 broker.PushNormalDataFromApplet(IStorage{data}); 287 broker.PushNormalDataFromApplet(IStorage{std::move(data)});
288 broker.SignalStateChanged(); 288 broker.SignalStateChanged();
289 289
290 if (!temporary_dir.empty() && FileUtil::IsDirectory(temporary_dir)) { 290 if (!temporary_dir.empty() && FileUtil::IsDirectory(temporary_dir)) {
diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp
index 5eb26caf8..8f1be0e48 100644
--- a/src/core/hle/service/prepo/prepo.cpp
+++ b/src/core/hle/service/prepo/prepo.cpp
@@ -50,16 +50,16 @@ private:
50 IPC::RequestParser rp{ctx}; 50 IPC::RequestParser rp{ctx};
51 const auto process_id = rp.PopRaw<u64>(); 51 const auto process_id = rp.PopRaw<u64>();
52 52
53 const auto data1 = ctx.ReadBuffer(0); 53 std::vector<std::vector<u8>> data{ctx.ReadBuffer(0)};
54 const auto data2 = ctx.ReadBuffer(1); 54 if (Type == Core::Reporter::PlayReportType::New) {
55 data.emplace_back(ctx.ReadBuffer(1));
56 }
55 57
56 LOG_DEBUG(Service_PREPO, 58 LOG_DEBUG(Service_PREPO, "called, type={:02X}, process_id={:016X}, data1_size={:016X}",
57 "called, type={:02X}, process_id={:016X}, data1_size={:016X}, data2_size={:016X}", 59 static_cast<u8>(Type), process_id, data[0].size());
58 static_cast<u8>(Type), process_id, data1.size(), data2.size());
59 60
60 const auto& reporter{system.GetReporter()}; 61 const auto& reporter{system.GetReporter()};
61 reporter.SavePlayReport(Type, system.CurrentProcess()->GetTitleID(), {data1, data2}, 62 reporter.SavePlayReport(Type, system.CurrentProcess()->GetTitleID(), data, process_id);
62 process_id);
63 63
64 IPC::ResponseBuilder rb{ctx, 2}; 64 IPC::ResponseBuilder rb{ctx, 2};
65 rb.Push(RESULT_SUCCESS); 65 rb.Push(RESULT_SUCCESS);
@@ -70,19 +70,19 @@ private:
70 IPC::RequestParser rp{ctx}; 70 IPC::RequestParser rp{ctx};
71 const auto user_id = rp.PopRaw<u128>(); 71 const auto user_id = rp.PopRaw<u128>();
72 const auto process_id = rp.PopRaw<u64>(); 72 const auto process_id = rp.PopRaw<u64>();
73 73 std::vector<std::vector<u8>> data{ctx.ReadBuffer(0)};
74 const auto data1 = ctx.ReadBuffer(0); 74 if (Type == Core::Reporter::PlayReportType::New) {
75 const auto data2 = ctx.ReadBuffer(1); 75 data.emplace_back(ctx.ReadBuffer(1));
76 }
76 77
77 LOG_DEBUG( 78 LOG_DEBUG(
78 Service_PREPO, 79 Service_PREPO,
79 "called, type={:02X}, user_id={:016X}{:016X}, process_id={:016X}, data1_size={:016X}, " 80 "called, type={:02X}, user_id={:016X}{:016X}, process_id={:016X}, data1_size={:016X}",
80 "data2_size={:016X}", 81 static_cast<u8>(Type), user_id[1], user_id[0], process_id, data[0].size());
81 static_cast<u8>(Type), user_id[1], user_id[0], process_id, data1.size(), data2.size());
82 82
83 const auto& reporter{system.GetReporter()}; 83 const auto& reporter{system.GetReporter()};
84 reporter.SavePlayReport(Type, system.CurrentProcess()->GetTitleID(), {data1, data2}, 84 reporter.SavePlayReport(Type, system.CurrentProcess()->GetTitleID(), data, process_id,
85 process_id, user_id); 85 user_id);
86 86
87 IPC::ResponseBuilder rb{ctx, 2}; 87 IPC::ResponseBuilder rb{ctx, 2};
88 rb.Push(RESULT_SUCCESS); 88 rb.Push(RESULT_SUCCESS);