summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/hle/service/aoc/addon_content_manager.cpp223
-rw-r--r--src/core/hle/service/aoc/addon_content_manager.h51
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp340
-rw-r--r--src/core/hle/service/aoc/aoc_u.h45
-rw-r--r--src/core/hle/service/aoc/purchase_event_manager.cpp67
-rw-r--r--src/core/hle/service/aoc/purchase_event_manager.h30
-rw-r--r--src/core/hle/service/glue/time/manager.cpp7
-rw-r--r--src/core/hle/service/glue/time/worker.cpp7
-rw-r--r--src/core/hle/service/services.cpp2
-rw-r--r--src/core/hle/service/set/system_settings_server.cpp14
-rw-r--r--src/core/hle/service/set/system_settings_server.h21
12 files changed, 401 insertions, 412 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 75beacf70..1eb43d816 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -486,8 +486,10 @@ add_library(core STATIC
486 hle/service/am/service/system_applet_proxy.h 486 hle/service/am/service/system_applet_proxy.h
487 hle/service/am/service/window_controller.cpp 487 hle/service/am/service/window_controller.cpp
488 hle/service/am/service/window_controller.h 488 hle/service/am/service/window_controller.h
489 hle/service/aoc/aoc_u.cpp 489 hle/service/aoc/addon_content_manager.cpp
490 hle/service/aoc/aoc_u.h 490 hle/service/aoc/addon_content_manager.h
491 hle/service/aoc/purchase_event_manager.cpp
492 hle/service/aoc/purchase_event_manager.h
491 hle/service/apm/apm.cpp 493 hle/service/apm/apm.cpp
492 hle/service/apm/apm.h 494 hle/service/apm/apm.h
493 hle/service/apm/apm_controller.cpp 495 hle/service/apm/apm_controller.cpp
diff --git a/src/core/hle/service/aoc/addon_content_manager.cpp b/src/core/hle/service/aoc/addon_content_manager.cpp
new file mode 100644
index 000000000..d47f57d64
--- /dev/null
+++ b/src/core/hle/service/aoc/addon_content_manager.cpp
@@ -0,0 +1,223 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <algorithm>
5#include <numeric>
6#include <vector>
7
8#include "common/logging/log.h"
9#include "common/settings.h"
10#include "core/core.h"
11#include "core/file_sys/common_funcs.h"
12#include "core/file_sys/content_archive.h"
13#include "core/file_sys/control_metadata.h"
14#include "core/file_sys/nca_metadata.h"
15#include "core/file_sys/patch_manager.h"
16#include "core/file_sys/registered_cache.h"
17#include "core/hle/kernel/k_event.h"
18#include "core/hle/service/aoc/addon_content_manager.h"
19#include "core/hle/service/aoc/purchase_event_manager.h"
20#include "core/hle/service/cmif_serialization.h"
21#include "core/hle/service/ipc_helpers.h"
22#include "core/hle/service/server_manager.h"
23#include "core/loader/loader.h"
24
25namespace Service::AOC {
26
27static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) {
28 return FileSys::GetBaseTitleID(title_id) == base;
29}
30
31static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) {
32 std::vector<u64> add_on_content;
33 const auto& rcu = system.GetContentProvider();
34 const auto list =
35 rcu.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
36 std::transform(list.begin(), list.end(), std::back_inserter(add_on_content),
37 [](const FileSys::ContentProviderEntry& rce) { return rce.title_id; });
38 add_on_content.erase(
39 std::remove_if(
40 add_on_content.begin(), add_on_content.end(),
41 [&rcu](u64 tid) {
42 return rcu.GetEntry(tid, FileSys::ContentRecordType::Data)->GetStatus() !=
43 Loader::ResultStatus::Success;
44 }),
45 add_on_content.end());
46 return add_on_content;
47}
48
49IAddOnContentManager::IAddOnContentManager(Core::System& system_)
50 : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)},
51 service_context{system_, "aoc:u"} {
52 // clang-format off
53 static const FunctionInfo functions[] = {
54 {0, nullptr, "CountAddOnContentByApplicationId"},
55 {1, nullptr, "ListAddOnContentByApplicationId"},
56 {2, D<&IAddOnContentManager::CountAddOnContent>, "CountAddOnContent"},
57 {3, D<&IAddOnContentManager::ListAddOnContent>, "ListAddOnContent"},
58 {4, nullptr, "GetAddOnContentBaseIdByApplicationId"},
59 {5, D<&IAddOnContentManager::GetAddOnContentBaseId>, "GetAddOnContentBaseId"},
60 {6, nullptr, "PrepareAddOnContentByApplicationId"},
61 {7, D<&IAddOnContentManager::PrepareAddOnContent>, "PrepareAddOnContent"},
62 {8, D<&IAddOnContentManager::GetAddOnContentListChangedEvent>, "GetAddOnContentListChangedEvent"},
63 {9, nullptr, "GetAddOnContentLostErrorCode"},
64 {10, D<&IAddOnContentManager::GetAddOnContentListChangedEventWithProcessId>, "GetAddOnContentListChangedEventWithProcessId"},
65 {11, D<&IAddOnContentManager::NotifyMountAddOnContent>, "NotifyMountAddOnContent"},
66 {12, D<&IAddOnContentManager::NotifyUnmountAddOnContent>, "NotifyUnmountAddOnContent"},
67 {13, nullptr, "IsAddOnContentMountedForDebug"},
68 {50, D<&IAddOnContentManager::CheckAddOnContentMountStatus>, "CheckAddOnContentMountStatus"},
69 {100, D<&IAddOnContentManager::CreateEcPurchasedEventManager>, "CreateEcPurchasedEventManager"},
70 {101, D<&IAddOnContentManager::CreatePermanentEcPurchasedEventManager>, "CreatePermanentEcPurchasedEventManager"},
71 {110, nullptr, "CreateContentsServiceManager"},
72 {200, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"},
73 {300, nullptr, "SetupHostAddOnContent"},
74 {301, nullptr, "GetRegisteredAddOnContentPath"},
75 {302, nullptr, "UpdateCachedList"},
76 };
77 // clang-format on
78
79 RegisterHandlers(functions);
80
81 aoc_change_event = service_context.CreateEvent("GetAddOnContentListChanged:Event");
82}
83
84IAddOnContentManager::~IAddOnContentManager() {
85 service_context.CloseEvent(aoc_change_event);
86}
87
88Result IAddOnContentManager::CountAddOnContent(Out<u32> out_count, ClientProcessId process_id) {
89 LOG_DEBUG(Service_AOC, "called. process_id={}", process_id.pid);
90
91 const auto current = system.GetApplicationProcessProgramID();
92
93 const auto& disabled = Settings::values.disabled_addons[current];
94 if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) {
95 *out_count = 0;
96 R_SUCCEED();
97 }
98
99 *out_count = static_cast<u32>(
100 std::count_if(add_on_content.begin(), add_on_content.end(),
101 [current](u64 tid) { return CheckAOCTitleIDMatchesBase(tid, current); }));
102
103 R_SUCCEED();
104}
105
106Result IAddOnContentManager::ListAddOnContent(Out<u32> out_count,
107 OutBuffer<BufferAttr_HipcMapAlias> out_addons,
108 u32 offset, u32 count, ClientProcessId process_id) {
109 LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count,
110 process_id.pid);
111
112 const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID());
113
114 std::vector<u32> out;
115 const auto& disabled = Settings::values.disabled_addons[current];
116 if (std::find(disabled.begin(), disabled.end(), "DLC") == disabled.end()) {
117 for (u64 content_id : add_on_content) {
118 if (FileSys::GetBaseTitleID(content_id) != current) {
119 continue;
120 }
121
122 out.push_back(static_cast<u32>(FileSys::GetAOCID(content_id)));
123 }
124 }
125
126 // TODO(DarkLordZach): Find the correct error code.
127 R_UNLESS(out.size() >= offset, ResultUnknown);
128
129 *out_count = static_cast<u32>(std::min<size_t>(out.size() - offset, count));
130 std::rotate(out.begin(), out.begin() + offset, out.end());
131
132 std::memcpy(out_addons.data(), out.data(), *out_count * sizeof(u32));
133
134 R_SUCCEED();
135}
136
137Result IAddOnContentManager::GetAddOnContentBaseId(Out<u64> out_title_id,
138 ClientProcessId process_id) {
139 LOG_DEBUG(Service_AOC, "called. process_id={}", process_id.pid);
140
141 const auto title_id = system.GetApplicationProcessProgramID();
142 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
143 system.GetContentProvider()};
144
145 const auto res = pm.GetControlMetadata();
146 if (res.first == nullptr) {
147 *out_title_id = FileSys::GetAOCBaseTitleID(title_id);
148 R_SUCCEED();
149 }
150
151 *out_title_id = res.first->GetDLCBaseTitleId();
152
153 R_SUCCEED();
154}
155
156Result IAddOnContentManager::PrepareAddOnContent(s32 addon_index, ClientProcessId process_id) {
157 LOG_WARNING(Service_AOC, "(STUBBED) called with addon_index={}, process_id={}", addon_index,
158 process_id.pid);
159
160 R_SUCCEED();
161}
162
163Result IAddOnContentManager::GetAddOnContentListChangedEvent(
164 OutCopyHandle<Kernel::KReadableEvent> out_event) {
165 LOG_WARNING(Service_AOC, "(STUBBED) called");
166
167 *out_event = &aoc_change_event->GetReadableEvent();
168
169 R_SUCCEED();
170}
171
172Result IAddOnContentManager::GetAddOnContentListChangedEventWithProcessId(
173 OutCopyHandle<Kernel::KReadableEvent> out_event, ClientProcessId process_id) {
174 LOG_WARNING(Service_AOC, "(STUBBED) called");
175
176 *out_event = &aoc_change_event->GetReadableEvent();
177
178 R_SUCCEED();
179}
180
181Result IAddOnContentManager::NotifyMountAddOnContent() {
182 LOG_WARNING(Service_AOC, "(STUBBED) called");
183
184 R_SUCCEED();
185}
186
187Result IAddOnContentManager::NotifyUnmountAddOnContent() {
188 LOG_WARNING(Service_AOC, "(STUBBED) called");
189
190 R_SUCCEED();
191}
192
193Result IAddOnContentManager::CheckAddOnContentMountStatus() {
194 LOG_WARNING(Service_AOC, "(STUBBED) called");
195
196 R_SUCCEED();
197}
198
199Result IAddOnContentManager::CreateEcPurchasedEventManager(
200 OutInterface<IPurchaseEventManager> out_interface) {
201 LOG_WARNING(Service_AOC, "(STUBBED) called");
202
203 *out_interface = std::make_shared<IPurchaseEventManager>(system);
204
205 R_SUCCEED();
206}
207
208Result IAddOnContentManager::CreatePermanentEcPurchasedEventManager(
209 OutInterface<IPurchaseEventManager> out_interface) {
210 LOG_WARNING(Service_AOC, "(STUBBED) called");
211
212 *out_interface = std::make_shared<IPurchaseEventManager>(system);
213
214 R_SUCCEED();
215}
216
217void LoopProcess(Core::System& system) {
218 auto server_manager = std::make_unique<ServerManager>(system);
219 server_manager->RegisterNamedService("aoc:u", std::make_shared<IAddOnContentManager>(system));
220 ServerManager::RunServer(std::move(server_manager));
221}
222
223} // namespace Service::AOC
diff --git a/src/core/hle/service/aoc/addon_content_manager.h b/src/core/hle/service/aoc/addon_content_manager.h
new file mode 100644
index 000000000..91857df4c
--- /dev/null
+++ b/src/core/hle/service/aoc/addon_content_manager.h
@@ -0,0 +1,51 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/service.h"
9
10namespace Core {
11class System;
12}
13
14namespace Kernel {
15class KEvent;
16}
17
18namespace Service::AOC {
19
20class IPurchaseEventManager;
21
22class IAddOnContentManager final : public ServiceFramework<IAddOnContentManager> {
23public:
24 explicit IAddOnContentManager(Core::System& system);
25 ~IAddOnContentManager() override;
26
27 Result CountAddOnContent(Out<u32> out_count, ClientProcessId process_id);
28 Result ListAddOnContent(Out<u32> out_count, OutBuffer<BufferAttr_HipcMapAlias> out_addons,
29 u32 offset, u32 count, ClientProcessId process_id);
30 Result GetAddOnContentBaseId(Out<u64> out_title_id, ClientProcessId process_id);
31 Result PrepareAddOnContent(s32 addon_index, ClientProcessId process_id);
32 Result GetAddOnContentListChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
33 Result GetAddOnContentListChangedEventWithProcessId(
34 OutCopyHandle<Kernel::KReadableEvent> out_event, ClientProcessId process_id);
35 Result NotifyMountAddOnContent();
36 Result NotifyUnmountAddOnContent();
37 Result CheckAddOnContentMountStatus();
38 Result CreateEcPurchasedEventManager(OutInterface<IPurchaseEventManager> out_interface);
39 Result CreatePermanentEcPurchasedEventManager(
40 OutInterface<IPurchaseEventManager> out_interface);
41
42private:
43 std::vector<u64> add_on_content;
44 KernelHelpers::ServiceContext service_context;
45
46 Kernel::KEvent* aoc_change_event;
47};
48
49void LoopProcess(Core::System& system);
50
51} // namespace Service::AOC
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
deleted file mode 100644
index 486719cc0..000000000
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <algorithm>
5#include <numeric>
6#include <vector>
7
8#include "common/logging/log.h"
9#include "common/settings.h"
10#include "core/core.h"
11#include "core/file_sys/common_funcs.h"
12#include "core/file_sys/content_archive.h"
13#include "core/file_sys/control_metadata.h"
14#include "core/file_sys/nca_metadata.h"
15#include "core/file_sys/patch_manager.h"
16#include "core/file_sys/registered_cache.h"
17#include "core/hle/kernel/k_event.h"
18#include "core/hle/service/aoc/aoc_u.h"
19#include "core/hle/service/ipc_helpers.h"
20#include "core/hle/service/server_manager.h"
21#include "core/loader/loader.h"
22
23namespace Service::AOC {
24
25constexpr Result ResultNoPurchasedProductInfoAvailable{ErrorModule::NIMShop, 400};
26
27static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) {
28 return FileSys::GetBaseTitleID(title_id) == base;
29}
30
31static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) {
32 std::vector<u64> add_on_content;
33 const auto& rcu = system.GetContentProvider();
34 const auto list =
35 rcu.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
36 std::transform(list.begin(), list.end(), std::back_inserter(add_on_content),
37 [](const FileSys::ContentProviderEntry& rce) { return rce.title_id; });
38 add_on_content.erase(
39 std::remove_if(
40 add_on_content.begin(), add_on_content.end(),
41 [&rcu](u64 tid) {
42 return rcu.GetEntry(tid, FileSys::ContentRecordType::Data)->GetStatus() !=
43 Loader::ResultStatus::Success;
44 }),
45 add_on_content.end());
46 return add_on_content;
47}
48
49class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> {
50public:
51 explicit IPurchaseEventManager(Core::System& system_)
52 : ServiceFramework{system_, "IPurchaseEventManager"}, service_context{
53 system, "IPurchaseEventManager"} {
54 // clang-format off
55 static const FunctionInfo functions[] = {
56 {0, &IPurchaseEventManager::SetDefaultDeliveryTarget, "SetDefaultDeliveryTarget"},
57 {1, &IPurchaseEventManager::SetDeliveryTarget, "SetDeliveryTarget"},
58 {2, &IPurchaseEventManager::GetPurchasedEventReadableHandle, "GetPurchasedEventReadableHandle"},
59 {3, &IPurchaseEventManager::PopPurchasedProductInfo, "PopPurchasedProductInfo"},
60 {4, &IPurchaseEventManager::PopPurchasedProductInfoWithUid, "PopPurchasedProductInfoWithUid"},
61 };
62 // clang-format on
63
64 RegisterHandlers(functions);
65
66 purchased_event = service_context.CreateEvent("IPurchaseEventManager:PurchasedEvent");
67 }
68
69 ~IPurchaseEventManager() override {
70 service_context.CloseEvent(purchased_event);
71 }
72
73private:
74 void SetDefaultDeliveryTarget(HLERequestContext& ctx) {
75 IPC::RequestParser rp{ctx};
76
77 const auto unknown_1 = rp.Pop<u64>();
78 [[maybe_unused]] const auto unknown_2 = ctx.ReadBuffer();
79
80 LOG_WARNING(Service_AOC, "(STUBBED) called, unknown_1={}", unknown_1);
81
82 IPC::ResponseBuilder rb{ctx, 2};
83 rb.Push(ResultSuccess);
84 }
85
86 void SetDeliveryTarget(HLERequestContext& ctx) {
87 IPC::RequestParser rp{ctx};
88
89 const auto unknown_1 = rp.Pop<u64>();
90 [[maybe_unused]] const auto unknown_2 = ctx.ReadBuffer();
91
92 LOG_WARNING(Service_AOC, "(STUBBED) called, unknown_1={}", unknown_1);
93
94 IPC::ResponseBuilder rb{ctx, 2};
95 rb.Push(ResultSuccess);
96 }
97
98 void GetPurchasedEventReadableHandle(HLERequestContext& ctx) {
99 LOG_WARNING(Service_AOC, "called");
100
101 IPC::ResponseBuilder rb{ctx, 2, 1};
102 rb.Push(ResultSuccess);
103 rb.PushCopyObjects(purchased_event->GetReadableEvent());
104 }
105
106 void PopPurchasedProductInfo(HLERequestContext& ctx) {
107 LOG_DEBUG(Service_AOC, "(STUBBED) called");
108
109 IPC::ResponseBuilder rb{ctx, 2};
110 rb.Push(ResultNoPurchasedProductInfoAvailable);
111 }
112
113 void PopPurchasedProductInfoWithUid(HLERequestContext& ctx) {
114 LOG_DEBUG(Service_AOC, "(STUBBED) called");
115
116 IPC::ResponseBuilder rb{ctx, 2};
117 rb.Push(ResultNoPurchasedProductInfoAvailable);
118 }
119
120 KernelHelpers::ServiceContext service_context;
121
122 Kernel::KEvent* purchased_event;
123};
124
125AOC_U::AOC_U(Core::System& system_)
126 : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)},
127 service_context{system_, "aoc:u"} {
128 // clang-format off
129 static const FunctionInfo functions[] = {
130 {0, nullptr, "CountAddOnContentByApplicationId"},
131 {1, nullptr, "ListAddOnContentByApplicationId"},
132 {2, &AOC_U::CountAddOnContent, "CountAddOnContent"},
133 {3, &AOC_U::ListAddOnContent, "ListAddOnContent"},
134 {4, nullptr, "GetAddOnContentBaseIdByApplicationId"},
135 {5, &AOC_U::GetAddOnContentBaseId, "GetAddOnContentBaseId"},
136 {6, nullptr, "PrepareAddOnContentByApplicationId"},
137 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"},
138 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"},
139 {9, nullptr, "GetAddOnContentLostErrorCode"},
140 {10, &AOC_U::GetAddOnContentListChangedEventWithProcessId, "GetAddOnContentListChangedEventWithProcessId"},
141 {11, &AOC_U::NotifyMountAddOnContent, "NotifyMountAddOnContent"},
142 {12, &AOC_U::NotifyUnmountAddOnContent, "NotifyUnmountAddOnContent"},
143 {13, nullptr, "IsAddOnContentMountedForDebug"},
144 {50, &AOC_U::CheckAddOnContentMountStatus, "CheckAddOnContentMountStatus"},
145 {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"},
146 {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"},
147 {110, nullptr, "CreateContentsServiceManager"},
148 {200, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"},
149 {300, nullptr, "SetupHostAddOnContent"},
150 {301, nullptr, "GetRegisteredAddOnContentPath"},
151 {302, nullptr, "UpdateCachedList"},
152 };
153 // clang-format on
154
155 RegisterHandlers(functions);
156
157 aoc_change_event = service_context.CreateEvent("GetAddOnContentListChanged:Event");
158}
159
160AOC_U::~AOC_U() {
161 service_context.CloseEvent(aoc_change_event);
162}
163
164void AOC_U::CountAddOnContent(HLERequestContext& ctx) {
165 struct Parameters {
166 u64 process_id;
167 };
168 static_assert(sizeof(Parameters) == 8);
169
170 IPC::RequestParser rp{ctx};
171 const auto params = rp.PopRaw<Parameters>();
172
173 LOG_DEBUG(Service_AOC, "called. process_id={}", params.process_id);
174
175 IPC::ResponseBuilder rb{ctx, 3};
176 rb.Push(ResultSuccess);
177
178 const auto current = system.GetApplicationProcessProgramID();
179
180 const auto& disabled = Settings::values.disabled_addons[current];
181 if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) {
182 rb.Push<u32>(0);
183 return;
184 }
185
186 rb.Push<u32>(static_cast<u32>(
187 std::count_if(add_on_content.begin(), add_on_content.end(),
188 [current](u64 tid) { return CheckAOCTitleIDMatchesBase(tid, current); })));
189}
190
191void AOC_U::ListAddOnContent(HLERequestContext& ctx) {
192 struct Parameters {
193 u32 offset;
194 u32 count;
195 u64 process_id;
196 };
197 static_assert(sizeof(Parameters) == 16);
198
199 IPC::RequestParser rp{ctx};
200 const auto [offset, count, process_id] = rp.PopRaw<Parameters>();
201
202 LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count,
203 process_id);
204
205 const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID());
206
207 std::vector<u32> out;
208 const auto& disabled = Settings::values.disabled_addons[current];
209 if (std::find(disabled.begin(), disabled.end(), "DLC") == disabled.end()) {
210 for (u64 content_id : add_on_content) {
211 if (FileSys::GetBaseTitleID(content_id) != current) {
212 continue;
213 }
214
215 out.push_back(static_cast<u32>(FileSys::GetAOCID(content_id)));
216 }
217 }
218
219 if (out.size() < offset) {
220 IPC::ResponseBuilder rb{ctx, 2};
221 // TODO(DarkLordZach): Find the correct error code.
222 rb.Push(ResultUnknown);
223 return;
224 }
225
226 const auto out_count = static_cast<u32>(std::min<size_t>(out.size() - offset, count));
227 std::rotate(out.begin(), out.begin() + offset, out.end());
228 out.resize(out_count);
229
230 ctx.WriteBuffer(out);
231
232 IPC::ResponseBuilder rb{ctx, 3};
233 rb.Push(ResultSuccess);
234 rb.Push(out_count);
235}
236
237void AOC_U::GetAddOnContentBaseId(HLERequestContext& ctx) {
238 struct Parameters {
239 u64 process_id;
240 };
241 static_assert(sizeof(Parameters) == 8);
242
243 IPC::RequestParser rp{ctx};
244 const auto params = rp.PopRaw<Parameters>();
245
246 LOG_DEBUG(Service_AOC, "called. process_id={}", params.process_id);
247
248 IPC::ResponseBuilder rb{ctx, 4};
249 rb.Push(ResultSuccess);
250
251 const auto title_id = system.GetApplicationProcessProgramID();
252 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
253 system.GetContentProvider()};
254
255 const auto res = pm.GetControlMetadata();
256 if (res.first == nullptr) {
257 rb.Push(FileSys::GetAOCBaseTitleID(title_id));
258 return;
259 }
260
261 rb.Push(res.first->GetDLCBaseTitleId());
262}
263
264void AOC_U::PrepareAddOnContent(HLERequestContext& ctx) {
265 struct Parameters {
266 s32 addon_index;
267 u64 process_id;
268 };
269 static_assert(sizeof(Parameters) == 16);
270
271 IPC::RequestParser rp{ctx};
272 const auto [addon_index, process_id] = rp.PopRaw<Parameters>();
273
274 LOG_WARNING(Service_AOC, "(STUBBED) called with addon_index={}, process_id={}", addon_index,
275 process_id);
276
277 IPC::ResponseBuilder rb{ctx, 2};
278 rb.Push(ResultSuccess);
279}
280
281void AOC_U::GetAddOnContentListChangedEvent(HLERequestContext& ctx) {
282 LOG_WARNING(Service_AOC, "(STUBBED) called");
283
284 IPC::ResponseBuilder rb{ctx, 2, 1};
285 rb.Push(ResultSuccess);
286 rb.PushCopyObjects(aoc_change_event->GetReadableEvent());
287}
288
289void AOC_U::GetAddOnContentListChangedEventWithProcessId(HLERequestContext& ctx) {
290 LOG_WARNING(Service_AOC, "(STUBBED) called");
291
292 IPC::ResponseBuilder rb{ctx, 2, 1};
293 rb.Push(ResultSuccess);
294 rb.PushCopyObjects(aoc_change_event->GetReadableEvent());
295}
296
297void AOC_U::NotifyMountAddOnContent(HLERequestContext& ctx) {
298 LOG_WARNING(Service_AOC, "(STUBBED) called");
299
300 IPC::ResponseBuilder rb{ctx, 2};
301 rb.Push(ResultSuccess);
302}
303
304void AOC_U::NotifyUnmountAddOnContent(HLERequestContext& ctx) {
305 LOG_WARNING(Service_AOC, "(STUBBED) called");
306
307 IPC::ResponseBuilder rb{ctx, 2};
308 rb.Push(ResultSuccess);
309}
310
311void AOC_U::CheckAddOnContentMountStatus(HLERequestContext& ctx) {
312 LOG_WARNING(Service_AOC, "(STUBBED) called");
313
314 IPC::ResponseBuilder rb{ctx, 2};
315 rb.Push(ResultSuccess);
316}
317
318void AOC_U::CreateEcPurchasedEventManager(HLERequestContext& ctx) {
319 LOG_WARNING(Service_AOC, "(STUBBED) called");
320
321 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
322 rb.Push(ResultSuccess);
323 rb.PushIpcInterface<IPurchaseEventManager>(system);
324}
325
326void AOC_U::CreatePermanentEcPurchasedEventManager(HLERequestContext& ctx) {
327 LOG_WARNING(Service_AOC, "(STUBBED) called");
328
329 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
330 rb.Push(ResultSuccess);
331 rb.PushIpcInterface<IPurchaseEventManager>(system);
332}
333
334void LoopProcess(Core::System& system) {
335 auto server_manager = std::make_unique<ServerManager>(system);
336 server_manager->RegisterNamedService("aoc:u", std::make_shared<AOC_U>(system));
337 ServerManager::RunServer(std::move(server_manager));
338}
339
340} // namespace Service::AOC
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
deleted file mode 100644
index 12ccfeb6a..000000000
--- a/src/core/hle/service/aoc/aoc_u.h
+++ /dev/null
@@ -1,45 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h"
8
9namespace Core {
10class System;
11}
12
13namespace Kernel {
14class KEvent;
15}
16
17namespace Service::AOC {
18
19class AOC_U final : public ServiceFramework<AOC_U> {
20public:
21 explicit AOC_U(Core::System& system);
22 ~AOC_U() override;
23
24private:
25 void CountAddOnContent(HLERequestContext& ctx);
26 void ListAddOnContent(HLERequestContext& ctx);
27 void GetAddOnContentBaseId(HLERequestContext& ctx);
28 void PrepareAddOnContent(HLERequestContext& ctx);
29 void GetAddOnContentListChangedEvent(HLERequestContext& ctx);
30 void GetAddOnContentListChangedEventWithProcessId(HLERequestContext& ctx);
31 void NotifyMountAddOnContent(HLERequestContext& ctx);
32 void NotifyUnmountAddOnContent(HLERequestContext& ctx);
33 void CheckAddOnContentMountStatus(HLERequestContext& ctx);
34 void CreateEcPurchasedEventManager(HLERequestContext& ctx);
35 void CreatePermanentEcPurchasedEventManager(HLERequestContext& ctx);
36
37 std::vector<u64> add_on_content;
38 KernelHelpers::ServiceContext service_context;
39
40 Kernel::KEvent* aoc_change_event;
41};
42
43void LoopProcess(Core::System& system);
44
45} // namespace Service::AOC
diff --git a/src/core/hle/service/aoc/purchase_event_manager.cpp b/src/core/hle/service/aoc/purchase_event_manager.cpp
new file mode 100644
index 000000000..9e718510b
--- /dev/null
+++ b/src/core/hle/service/aoc/purchase_event_manager.cpp
@@ -0,0 +1,67 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/aoc/purchase_event_manager.h"
5#include "core/hle/service/cmif_serialization.h"
6
7namespace Service::AOC {
8
9constexpr Result ResultNoPurchasedProductInfoAvailable{ErrorModule::NIMShop, 400};
10
11IPurchaseEventManager::IPurchaseEventManager(Core::System& system_)
12 : ServiceFramework{system_, "IPurchaseEventManager"}, service_context{system,
13 "IPurchaseEventManager"} {
14 // clang-format off
15 static const FunctionInfo functions[] = {
16 {0, D<&IPurchaseEventManager::SetDefaultDeliveryTarget>, "SetDefaultDeliveryTarget"},
17 {1, D<&IPurchaseEventManager::SetDeliveryTarget>, "SetDeliveryTarget"},
18 {2, D<&IPurchaseEventManager::GetPurchasedEvent>, "GetPurchasedEvent"},
19 {3, D<&IPurchaseEventManager::PopPurchasedProductInfo>, "PopPurchasedProductInfo"},
20 {4, D<&IPurchaseEventManager::PopPurchasedProductInfoWithUid>, "PopPurchasedProductInfoWithUid"},
21 };
22 // clang-format on
23
24 RegisterHandlers(functions);
25
26 purchased_event = service_context.CreateEvent("IPurchaseEventManager:PurchasedEvent");
27}
28
29IPurchaseEventManager::~IPurchaseEventManager() {
30 service_context.CloseEvent(purchased_event);
31}
32
33Result IPurchaseEventManager::SetDefaultDeliveryTarget(
34 ClientProcessId process_id, InBuffer<BufferAttr_HipcMapAlias> in_buffer) {
35 LOG_WARNING(Service_AOC, "(STUBBED) called, process_id={}", process_id.pid);
36
37 R_SUCCEED();
38}
39
40Result IPurchaseEventManager::SetDeliveryTarget(u64 unknown,
41 InBuffer<BufferAttr_HipcMapAlias> in_buffer) {
42 LOG_WARNING(Service_AOC, "(STUBBED) called, unknown={}", unknown);
43
44 R_SUCCEED();
45}
46
47Result IPurchaseEventManager::GetPurchasedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
48 LOG_WARNING(Service_AOC, "called");
49
50 *out_event = &purchased_event->GetReadableEvent();
51
52 R_SUCCEED();
53}
54
55Result IPurchaseEventManager::PopPurchasedProductInfo() {
56 LOG_DEBUG(Service_AOC, "(STUBBED) called");
57
58 R_RETURN(ResultNoPurchasedProductInfoAvailable);
59}
60
61Result IPurchaseEventManager::PopPurchasedProductInfoWithUid() {
62 LOG_DEBUG(Service_AOC, "(STUBBED) called");
63
64 R_RETURN(ResultNoPurchasedProductInfoAvailable);
65}
66
67} // namespace Service::AOC
diff --git a/src/core/hle/service/aoc/purchase_event_manager.h b/src/core/hle/service/aoc/purchase_event_manager.h
new file mode 100644
index 000000000..ea3836bc9
--- /dev/null
+++ b/src/core/hle/service/aoc/purchase_event_manager.h
@@ -0,0 +1,30 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/os/event.h"
9#include "core/hle/service/service.h"
10
11namespace Service::AOC {
12
13class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> {
14public:
15 explicit IPurchaseEventManager(Core::System& system_);
16 ~IPurchaseEventManager() override;
17
18 Result SetDefaultDeliveryTarget(ClientProcessId process_id,
19 InBuffer<BufferAttr_HipcMapAlias> in_buffer);
20 Result SetDeliveryTarget(u64 unknown, InBuffer<BufferAttr_HipcMapAlias> in_buffer);
21 Result GetPurchasedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
22 Result PopPurchasedProductInfo();
23 Result PopPurchasedProductInfoWithUid();
24
25private:
26 KernelHelpers::ServiceContext service_context;
27 Kernel::KEvent* purchased_event;
28};
29
30} // namespace Service::AOC
diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp
index 059ac3fc9..cb88486dd 100644
--- a/src/core/hle/service/glue/time/manager.cpp
+++ b/src/core/hle/service/glue/time/manager.cpp
@@ -51,16 +51,17 @@ s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
51} 51}
52 52
53s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) { 53s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) {
54 s32 year{2000};
55 set_sys->GetSettingsItemValueImpl(year, "time", "standard_user_clock_initial_year");
56
54 Service::PSC::Time::CalendarTime calendar{ 57 Service::PSC::Time::CalendarTime calendar{
55 .year = 2000, 58 .year = static_cast<s16>(year),
56 .month = 1, 59 .month = 1,
57 .day = 1, 60 .day = 1,
58 .hour = 0, 61 .hour = 0,
59 .minute = 0, 62 .minute = 0,
60 .second = 0, 63 .second = 0,
61 }; 64 };
62 set_sys->GetSettingsItemValueImpl<s16>(calendar.year, "time",
63 "standard_user_clock_initial_year");
64 return CalendarTimeToEpoch(calendar); 65 return CalendarTimeToEpoch(calendar);
65} 66}
66 67
diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp
index b28569b68..b6bbd7965 100644
--- a/src/core/hle/service/glue/time/worker.cpp
+++ b/src/core/hle/service/glue/time/worker.cpp
@@ -26,12 +26,9 @@ Service::PSC::Time::SystemClockContext g_report_ephemeral_clock_context{};
26template <typename T> 26template <typename T>
27T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys, 27T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys,
28 const char* category, const char* name) { 28 const char* category, const char* name) {
29 std::vector<u8> interval_buf;
30 auto res = set_sys->GetSettingsItemValueImpl(interval_buf, category, name);
31 ASSERT(res == ResultSuccess);
32
33 T v{}; 29 T v{};
34 std::memcpy(&v, interval_buf.data(), sizeof(T)); 30 auto res = set_sys->GetSettingsItemValueImpl(v, category, name);
31 ASSERT(res == ResultSuccess);
35 return v; 32 return v;
36} 33}
37 34
diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp
index 1aa85ea54..3defa4b31 100644
--- a/src/core/hle/service/services.cpp
+++ b/src/core/hle/service/services.cpp
@@ -5,7 +5,7 @@
5 5
6#include "core/hle/service/acc/acc.h" 6#include "core/hle/service/acc/acc.h"
7#include "core/hle/service/am/am.h" 7#include "core/hle/service/am/am.h"
8#include "core/hle/service/aoc/aoc_u.h" 8#include "core/hle/service/aoc/addon_content_manager.h"
9#include "core/hle/service/apm/apm.h" 9#include "core/hle/service/apm/apm.h"
10#include "core/hle/service/audio/audio.h" 10#include "core/hle/service/audio/audio.h"
11#include "core/hle/service/bcat/bcat.h" 11#include "core/hle/service/bcat/bcat.h"
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp
index f514519bb..900d5408f 100644
--- a/src/core/hle/service/set/system_settings_server.cpp
+++ b/src/core/hle/service/set/system_settings_server.cpp
@@ -307,6 +307,9 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
307 307
308 SetupSettings(); 308 SetupSettings();
309 309
310 m_system_settings.region_code =
311 static_cast<SystemRegionCode>(::Settings::values.region_index.GetValue());
312
310 // TODO: Remove this when starter applet is fully functional 313 // TODO: Remove this when starter applet is fully functional
311 EulaVersion eula_version{ 314 EulaVersion eula_version{
312 .version = 0x10000, 315 .version = 0x10000,
@@ -712,7 +715,7 @@ Result ISystemSettingsServer::GetSettingsItemValueSize(
712} 715}
713 716
714Result ISystemSettingsServer::GetSettingsItemValue( 717Result ISystemSettingsServer::GetSettingsItemValue(
715 OutBuffer<BufferAttr_HipcMapAlias> out_data, 718 Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_data,
716 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, 719 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
717 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) { 720 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) {
718 const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)}; 721 const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)};
@@ -720,7 +723,7 @@ Result ISystemSettingsServer::GetSettingsItemValue(
720 723
721 LOG_INFO(Service_SET, "called, category={}, name={}", setting_category, setting_name); 724 LOG_INFO(Service_SET, "called, category={}, name={}", setting_category, setting_name);
722 725
723 R_RETURN(GetSettingsItemValueImpl(out_data, setting_category, setting_name)); 726 R_RETURN(GetSettingsItemValueImpl(out_data, *out_size, setting_category, setting_name));
724} 727}
725 728
726Result ISystemSettingsServer::GetTvSettings(Out<TvSettings> out_tv_settings) { 729Result ISystemSettingsServer::GetTvSettings(Out<TvSettings> out_tv_settings) {
@@ -1360,13 +1363,16 @@ void ISystemSettingsServer::SetSaveNeeded() {
1360 m_save_needed = true; 1363 m_save_needed = true;
1361} 1364}
1362 1365
1363Result ISystemSettingsServer::GetSettingsItemValueImpl(std::vector<u8>& out_value, 1366Result ISystemSettingsServer::GetSettingsItemValueImpl(std::span<u8> out_value, u64& out_size,
1364 const std::string& category, 1367 const std::string& category,
1365 const std::string& name) { 1368 const std::string& name) {
1366 auto settings{GetSettings()}; 1369 auto settings{GetSettings()};
1367 R_UNLESS(settings.contains(category) && settings[category].contains(name), ResultUnknown); 1370 R_UNLESS(settings.contains(category) && settings[category].contains(name), ResultUnknown);
1368 1371
1369 out_value = settings[category][name]; 1372 ASSERT_MSG(out_value.size() >= settings[category][name].size(),
1373 "Stored type is bigger than requested type");
1374 out_size = std::min<u64>(settings[category][name].size(), out_value.size());
1375 std::memcpy(out_value.data(), settings[category][name].data(), out_size);
1370 R_SUCCEED(); 1376 R_SUCCEED();
1371} 1377}
1372 1378
diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h
index 46e06c8ea..9a1154ad6 100644
--- a/src/core/hle/service/set/system_settings_server.h
+++ b/src/core/hle/service/set/system_settings_server.h
@@ -34,20 +34,17 @@ public:
34 explicit ISystemSettingsServer(Core::System& system_); 34 explicit ISystemSettingsServer(Core::System& system_);
35 ~ISystemSettingsServer() override; 35 ~ISystemSettingsServer() override;
36 36
37 Result GetSettingsItemValueImpl(std::vector<u8>& out_value, const std::string& category, 37 Result GetSettingsItemValueImpl(std::span<u8> out_value, u64& out_size,
38 const std::string& name); 38 const std::string& category, const std::string& name);
39 39
40 template <typename T> 40 template <typename T>
41 Result GetSettingsItemValueImpl(T& value, const std::string& category, 41 Result GetSettingsItemValueImpl(T& out_value, const std::string& category,
42 const std::string& name) { 42 const std::string& name) {
43 std::vector<u8> data; 43 u64 data_size{};
44 const auto result = GetSettingsItemValueImpl(data, category, name); 44 std::vector<u8> data(sizeof(T));
45 if (result.IsError()) { 45 R_TRY(GetSettingsItemValueImpl(data, data_size, category, name));
46 return result; 46 std::memcpy(&out_value, data.data(), data_size);
47 } 47 R_SUCCEED();
48 ASSERT(data.size() >= sizeof(T));
49 std::memcpy(&value, data.data(), sizeof(T));
50 return result;
51 } 48 }
52 49
53public: 50public:
@@ -84,7 +81,7 @@ public:
84 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, 81 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
85 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buf); 82 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buf);
86 Result GetSettingsItemValue( 83 Result GetSettingsItemValue(
87 OutBuffer<BufferAttr_HipcMapAlias> out_data, 84 Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_data,
88 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, 85 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
89 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer); 86 InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer);
90 Result GetTvSettings(Out<TvSettings> out_tv_settings); 87 Result GetTvSettings(Out<TvSettings> out_tv_settings);