summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Narr the Reg2023-10-01 12:49:11 -0600
committerGravatar Narr the Reg2023-10-02 12:38:03 -0600
commitc3349594403bd7d39a38fef0c2b73c449e651f49 (patch)
treec98d325ac60fc7288b4427a8a00499b3ae066e79
parentyuzu: Allow to launch album applet from firmware (diff)
downloadyuzu-c3349594403bd7d39a38fef0c2b73c449e651f49.tar.gz
yuzu-c3349594403bd7d39a38fef0c2b73c449e651f49.tar.xz
yuzu-c3349594403bd7d39a38fef0c2b73c449e651f49.zip
service: caps: Partially implement IAlbumAccessorService
-rw-r--r--src/core/hle/service/caps/caps.cpp2
-rw-r--r--src/core/hle/service/caps/caps_a.cpp314
-rw-r--r--src/core/hle/service/caps/caps_a.h118
-rw-r--r--src/core/hle/service/ns/ns.cpp27
-rw-r--r--src/core/hle/service/ns/ns.h4
5 files changed, 450 insertions, 15 deletions
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp
index 610fe9940..0dbf04862 100644
--- a/src/core/hle/service/caps/caps.cpp
+++ b/src/core/hle/service/caps/caps.cpp
@@ -16,7 +16,7 @@ namespace Service::Capture {
16void LoopProcess(Core::System& system) { 16void LoopProcess(Core::System& system) {
17 auto server_manager = std::make_unique<ServerManager>(system); 17 auto server_manager = std::make_unique<ServerManager>(system);
18 18
19 server_manager->RegisterNamedService("caps:a", std::make_shared<CAPS_A>(system)); 19 server_manager->RegisterNamedService("caps:a", std::make_shared<IAlbumAccessorService>(system));
20 server_manager->RegisterNamedService("caps:c", std::make_shared<CAPS_C>(system)); 20 server_manager->RegisterNamedService("caps:c", std::make_shared<CAPS_C>(system));
21 server_manager->RegisterNamedService("caps:u", std::make_shared<CAPS_U>(system)); 21 server_manager->RegisterNamedService("caps:u", std::make_shared<CAPS_U>(system));
22 server_manager->RegisterNamedService("caps:sc", std::make_shared<CAPS_SC>(system)); 22 server_manager->RegisterNamedService("caps:sc", std::make_shared<CAPS_SC>(system));
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp
index 44267b284..e1f836e08 100644
--- a/src/core/hle/service/caps/caps_a.cpp
+++ b/src/core/hle/service/caps/caps_a.cpp
@@ -1,7 +1,14 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <sstream>
5#include <stb_image.h>
6#include <stb_image_resize.h>
7
8#include "common/fs/file.h"
9#include "common/fs/path_util.h"
4#include "core/hle/service/caps/caps_a.h" 10#include "core/hle/service/caps/caps_a.h"
11#include "core/hle/service/ipc_helpers.h"
5 12
6namespace Service::Capture { 13namespace Service::Capture {
7 14
@@ -26,15 +33,16 @@ public:
26 } 33 }
27}; 34};
28 35
29CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} { 36IAlbumAccessorService::IAlbumAccessorService(Core::System& system_)
37 : ServiceFramework{system_, "caps:a"} {
30 // clang-format off 38 // clang-format off
31 static const FunctionInfo functions[] = { 39 static const FunctionInfo functions[] = {
32 {0, nullptr, "GetAlbumFileCount"}, 40 {0, nullptr, "GetAlbumFileCount"},
33 {1, nullptr, "GetAlbumFileList"}, 41 {1, nullptr, "GetAlbumFileList"},
34 {2, nullptr, "LoadAlbumFile"}, 42 {2, nullptr, "LoadAlbumFile"},
35 {3, nullptr, "DeleteAlbumFile"}, 43 {3, &IAlbumAccessorService::DeleteAlbumFile, "DeleteAlbumFile"},
36 {4, nullptr, "StorageCopyAlbumFile"}, 44 {4, nullptr, "StorageCopyAlbumFile"},
37 {5, nullptr, "IsAlbumMounted"}, 45 {5, &IAlbumAccessorService::IsAlbumMounted, "IsAlbumMounted"},
38 {6, nullptr, "GetAlbumUsage"}, 46 {6, nullptr, "GetAlbumUsage"},
39 {7, nullptr, "GetAlbumFileSize"}, 47 {7, nullptr, "GetAlbumFileSize"},
40 {8, nullptr, "LoadAlbumFileThumbnail"}, 48 {8, nullptr, "LoadAlbumFileThumbnail"},
@@ -47,18 +55,18 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} {
47 {15, nullptr, "GetAlbumUsage3"}, 55 {15, nullptr, "GetAlbumUsage3"},
48 {16, nullptr, "GetAlbumMountResult"}, 56 {16, nullptr, "GetAlbumMountResult"},
49 {17, nullptr, "GetAlbumUsage16"}, 57 {17, nullptr, "GetAlbumUsage16"},
50 {18, nullptr, "Unknown18"}, 58 {18, &IAlbumAccessorService::Unknown18, "Unknown18"},
51 {19, nullptr, "Unknown19"}, 59 {19, nullptr, "Unknown19"},
52 {100, nullptr, "GetAlbumFileCountEx0"}, 60 {100, nullptr, "GetAlbumFileCountEx0"},
53 {101, nullptr, "GetAlbumFileListEx0"}, 61 {101, &IAlbumAccessorService::GetAlbumFileListEx0, "GetAlbumFileListEx0"},
54 {202, nullptr, "SaveEditedScreenShot"}, 62 {202, nullptr, "SaveEditedScreenShot"},
55 {301, nullptr, "GetLastThumbnail"}, 63 {301, nullptr, "GetLastThumbnail"},
56 {302, nullptr, "GetLastOverlayMovieThumbnail"}, 64 {302, nullptr, "GetLastOverlayMovieThumbnail"},
57 {401, nullptr, "GetAutoSavingStorage"}, 65 {401, &IAlbumAccessorService::GetAutoSavingStorage, "GetAutoSavingStorage"},
58 {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"}, 66 {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
59 {1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"}, 67 {1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"},
60 {1002, nullptr, "LoadAlbumScreenShotImageEx1"}, 68 {1002, &IAlbumAccessorService::LoadAlbumScreenShotImageEx1, "LoadAlbumScreenShotImageEx1"},
61 {1003, nullptr, "LoadAlbumScreenShotThumbnailImageEx1"}, 69 {1003, &IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1, "LoadAlbumScreenShotThumbnailImageEx1"},
62 {8001, nullptr, "ForceAlbumUnmounted"}, 70 {8001, nullptr, "ForceAlbumUnmounted"},
63 {8002, nullptr, "ResetAlbumMountStatus"}, 71 {8002, nullptr, "ResetAlbumMountStatus"},
64 {8011, nullptr, "RefreshAlbumCache"}, 72 {8011, nullptr, "RefreshAlbumCache"},
@@ -74,6 +82,294 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} {
74 RegisterHandlers(functions); 82 RegisterHandlers(functions);
75} 83}
76 84
77CAPS_A::~CAPS_A() = default; 85IAlbumAccessorService::~IAlbumAccessorService() = default;
86
87void IAlbumAccessorService::DeleteAlbumFile(HLERequestContext& ctx) {
88 IPC::RequestParser rp{ctx};
89 const auto file_id{rp.PopRaw<AlbumFileId>()};
90
91 LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}",
92 file_id.application_id, file_id.storage, file_id.type);
93
94 if (file_id.storage == AlbumStorage::Sd) {
95 if (!Common::FS::RemoveFile(sd_image_paths[file_id.date.unique_id])) {
96 IPC::ResponseBuilder rb{ctx, 2};
97 rb.Push(ResultUnknown);
98 return;
99 }
100 }
101
102 IPC::ResponseBuilder rb{ctx, 2};
103 rb.Push(ResultSuccess);
104}
105
106void IAlbumAccessorService::IsAlbumMounted(HLERequestContext& ctx) {
107 IPC::RequestParser rp{ctx};
108 const auto storage{rp.PopEnum<AlbumStorage>()};
109
110 LOG_INFO(Service_Capture, "called, storage={}, is_mounted={}", storage, is_mounted);
111
112 if (storage == AlbumStorage::Sd) {
113 FindScreenshots();
114 }
115
116 IPC::ResponseBuilder rb{ctx, 3};
117 rb.Push(ResultSuccess);
118 rb.Push<u8>(is_mounted);
119}
120
121void IAlbumAccessorService::Unknown18(HLERequestContext& ctx) {
122 struct UnknownBuffer {
123 INSERT_PADDING_BYTES(0x10);
124 };
125 static_assert(sizeof(UnknownBuffer) == 0x10, "UnknownBuffer is an invalid size");
126
127 LOG_WARNING(Service_Capture, "(STUBBED) called");
128
129 std::vector<UnknownBuffer> buffer{};
130
131 if (!buffer.empty()) {
132 ctx.WriteBuffer(buffer);
133 }
134
135 IPC::ResponseBuilder rb{ctx, 3};
136 rb.Push(ResultSuccess);
137 rb.Push(static_cast<u32>(buffer.size()));
138}
139
140void IAlbumAccessorService::GetAlbumFileListEx0(HLERequestContext& ctx) {
141 IPC::RequestParser rp{ctx};
142 const auto storage{rp.PopEnum<AlbumStorage>()};
143 const auto flags{rp.Pop<u8>()};
144
145 LOG_INFO(Service_Capture, "called, storage={}, flags={}", storage, flags);
146
147 std::vector<AlbumEntry> entries{};
148
149 if (storage == AlbumStorage::Sd) {
150 AlbumEntry entry;
151 for (u8 i = 0; i < static_cast<u8>(sd_image_paths.size()); i++) {
152 if (GetAlbumEntry(entry, sd_image_paths[i]).IsError()) {
153 continue;
154 }
155 entry.file_id.date.unique_id = i;
156 entries.push_back(entry);
157 }
158 }
159
160 if (!entries.empty()) {
161 ctx.WriteBuffer(entries);
162 }
163
164 IPC::ResponseBuilder rb{ctx, 3};
165 rb.Push(ResultSuccess);
166 rb.Push(entries.size());
167}
168
169void IAlbumAccessorService::GetAutoSavingStorage(HLERequestContext& ctx) {
170 bool is_autosaving{};
171
172 LOG_WARNING(Service_Capture, "(STUBBED) called, is_autosaving={}", is_autosaving);
173
174 IPC::ResponseBuilder rb{ctx, 3};
175 rb.Push(ResultSuccess);
176 rb.Push<u8>(is_autosaving);
177}
178
179void IAlbumAccessorService::LoadAlbumScreenShotImageEx1(HLERequestContext& ctx) {
180 IPC::RequestParser rp{ctx};
181 const auto file_id{rp.PopRaw<AlbumFileId>()};
182 const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()};
183
184 LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}",
185 file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
186
187 const LoadAlbumScreenShotImageOutput image_output{
188 .width = 1280,
189 .height = 720,
190 .attribute =
191 {
192 .unknown_0{},
193 .orientation = ScreenShotOrientation::None,
194 .unknown_1{},
195 .unknown_2{},
196 },
197 };
198
199 std::vector<u8> image(image_output.height * image_output.width * STBI_rgb_alpha);
200
201 if (file_id.storage == AlbumStorage::Sd) {
202 LoadImage(image, sd_image_paths[file_id.date.unique_id],
203 static_cast<int>(image_output.width), static_cast<int>(image_output.height),
204 decoder_options.flags);
205 }
206
207 ctx.WriteBuffer(image_output, 0);
208 ctx.WriteBuffer(image, 1);
209
210 IPC::ResponseBuilder rb{ctx, 2};
211 rb.Push(ResultSuccess);
212}
213
214void IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx) {
215 IPC::RequestParser rp{ctx};
216 const auto file_id{rp.PopRaw<AlbumFileId>()};
217 const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()};
218
219 LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}",
220 file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
221
222 const LoadAlbumScreenShotImageOutput image_output{
223 .width = 320,
224 .height = 180,
225 .attribute =
226 {
227 .unknown_0{},
228 .orientation = ScreenShotOrientation::None,
229 .unknown_1{},
230 .unknown_2{},
231 },
232 };
233
234 std::vector<u8> image(image_output.height * image_output.width * STBI_rgb_alpha);
235
236 if (file_id.storage == AlbumStorage::Sd) {
237 LoadImage(image, sd_image_paths[file_id.date.unique_id],
238 static_cast<int>(image_output.width), static_cast<int>(image_output.height),
239 decoder_options.flags);
240 }
241
242 ctx.WriteBuffer(image_output, 0);
243 ctx.WriteBuffer(image, 1);
244
245 IPC::ResponseBuilder rb{ctx, 2};
246 rb.Push(ResultSuccess);
247}
248
249void IAlbumAccessorService::FindScreenshots() {
250 is_mounted = false;
251 sd_image_paths.clear();
252
253 // TODO: Swap this with a blocking operation.
254 const auto screenshots_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ScreenshotsDir);
255 Common::FS::IterateDirEntries(
256 screenshots_dir,
257 [this](const std::filesystem::path& full_path) {
258 AlbumEntry entry;
259 // TODO: Implement proper indexing to allow more images
260 if (sd_image_paths.size() > 0xFF) {
261 return true;
262 }
263 if (GetAlbumEntry(entry, full_path).IsSuccess()) {
264 sd_image_paths.push_back(full_path);
265 }
266 return true;
267 },
268 Common::FS::DirEntryFilter::File);
269
270 is_mounted = true;
271}
272
273Result IAlbumAccessorService::GetAlbumEntry(AlbumEntry& out_entry,
274 const std::filesystem::path& path) {
275 std::istringstream line_stream(path.filename().string());
276 std::string date;
277 std::string application;
278 std::string time;
279
280 // Parse filename to obtain entry properties
281 std::getline(line_stream, application, '_');
282 std::getline(line_stream, date, '_');
283 std::getline(line_stream, time, '_');
284
285 std::istringstream date_stream(date);
286 std::istringstream time_stream(time);
287 std::string year;
288 std::string month;
289 std::string day;
290 std::string hour;
291 std::string minute;
292 std::string second;
293
294 std::getline(date_stream, year, '-');
295 std::getline(date_stream, month, '-');
296 std::getline(date_stream, day, '-');
297
298 std::getline(time_stream, hour, '-');
299 std::getline(time_stream, minute, '-');
300 std::getline(time_stream, second, '-');
301
302 try {
303 out_entry = {
304 .entry_size = 1,
305 .file_id{
306 .application_id = static_cast<u64>(std::stoll(application, 0, 16)),
307 .date =
308 {
309 .year = static_cast<u16>(std::stoi(year)),
310 .month = static_cast<u8>(std::stoi(month)),
311 .day = static_cast<u8>(std::stoi(day)),
312 .hour = static_cast<u8>(std::stoi(hour)),
313 .minute = static_cast<u8>(std::stoi(minute)),
314 .second = static_cast<u8>(std::stoi(second)),
315 .unique_id = 0,
316 },
317 .storage = AlbumStorage::Sd,
318 .type = ContentType::Screenshot,
319 .unknown = 1,
320 },
321 };
322 } catch (const std::invalid_argument&) {
323 return ResultUnknown;
324 } catch (const std::out_of_range&) {
325 return ResultUnknown;
326 } catch (const std::exception&) {
327 return ResultUnknown;
328 }
329
330 return ResultSuccess;
331}
332
333Result IAlbumAccessorService::LoadImage(std::span<u8> out_image, const std::filesystem::path& path,
334 int width, int height, ScreenShotDecoderFlag flag) {
335 if (out_image.size() != static_cast<std::size_t>(width * height * STBI_rgb_alpha)) {
336 return ResultUnknown;
337 }
338
339 const Common::FS::IOFile db_file{path, Common::FS::FileAccessMode::Read,
340 Common::FS::FileType::BinaryFile};
341
342 std::vector<u8> raw_file(db_file.GetSize());
343 if (db_file.Read(raw_file) != raw_file.size()) {
344 return ResultUnknown;
345 }
346
347 int filter_flag = STBIR_FILTER_DEFAULT;
348 int original_width, original_height, color_channels;
349 const auto dbi_image =
350 stbi_load_from_memory(raw_file.data(), static_cast<int>(raw_file.size()), &original_width,
351 &original_height, &color_channels, STBI_rgb_alpha);
352
353 if (dbi_image == nullptr) {
354 return ResultUnknown;
355 }
356
357 switch (flag) {
358 case ScreenShotDecoderFlag::EnableFancyUpsampling:
359 filter_flag = STBIR_FILTER_TRIANGLE;
360 break;
361 case ScreenShotDecoderFlag::EnableBlockSmoothing:
362 filter_flag = STBIR_FILTER_BOX;
363 break;
364 default:
365 filter_flag = STBIR_FILTER_DEFAULT;
366 break;
367 }
368
369 stbir_resize_uint8_srgb(dbi_image, original_width, original_height, 0, out_image.data(), width,
370 height, 0, STBI_rgb_alpha, 3, filter_flag);
371
372 return ResultSuccess;
373}
78 374
79} // namespace Service::Capture 375} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h
index 98a21a5ad..975c0ebdb 100644
--- a/src/core/hle/service/caps/caps_a.h
+++ b/src/core/hle/service/caps/caps_a.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/fs/fs.h"
6#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
7 8
8namespace Core { 9namespace Core {
@@ -11,10 +12,121 @@ class System;
11 12
12namespace Service::Capture { 13namespace Service::Capture {
13 14
14class CAPS_A final : public ServiceFramework<CAPS_A> { 15class IAlbumAccessorService final : public ServiceFramework<IAlbumAccessorService> {
15public: 16public:
16 explicit CAPS_A(Core::System& system_); 17 explicit IAlbumAccessorService(Core::System& system_);
17 ~CAPS_A() override; 18 ~IAlbumAccessorService() override;
19
20private:
21 enum class ContentType : u8 {
22 Screenshot,
23 Movie,
24 ExtraMovie,
25 };
26
27 enum class AlbumStorage : u8 {
28 Nand,
29 Sd,
30
31 };
32
33 enum class ScreenShotDecoderFlag : u64 {
34 None = 0,
35 EnableFancyUpsampling = 1 << 0,
36 EnableBlockSmoothing = 1 << 1,
37 };
38
39 enum class ScreenShotOrientation : u32 {
40 None,
41 Rotate90,
42 Rotate180,
43 Rotate270,
44 };
45
46 struct ScreenShotAttribute {
47 u32 unknown_0;
48 ScreenShotOrientation orientation;
49 u32 unknown_1;
50 u32 unknown_2;
51 INSERT_PADDING_BYTES(0x30);
52 };
53 static_assert(sizeof(ScreenShotAttribute) == 0x40, "ScreenShotAttribute is an invalid size");
54
55 struct ScreenShotDecodeOption {
56 ScreenShotDecoderFlag flags;
57 INSERT_PADDING_BYTES(0x18);
58 };
59 static_assert(sizeof(ScreenShotDecodeOption) == 0x20,
60 "ScreenShotDecodeOption is an invalid size");
61
62 struct AlbumFileDateTime {
63 u16 year;
64 u8 month;
65 u8 day;
66 u8 hour;
67 u8 minute;
68 u8 second;
69 u8 unique_id;
70 };
71 static_assert(sizeof(AlbumFileDateTime) == 0x8, "AlbumFileDateTime is an invalid size");
72
73 struct AlbumFileId {
74 u64 application_id;
75 AlbumFileDateTime date;
76 AlbumStorage storage;
77 ContentType type;
78 INSERT_PADDING_BYTES(0x5);
79 u8 unknown;
80 };
81 static_assert(sizeof(AlbumFileId) == 0x18, "AlbumFileId is an invalid size");
82
83 struct AlbumEntry {
84 u64 entry_size;
85 AlbumFileId file_id;
86 };
87 static_assert(sizeof(AlbumEntry) == 0x20, "AlbumEntry is an invalid size");
88
89 struct ApplicationData {
90 std::array<u8, 0x400> data;
91 u32 data_size;
92 };
93 static_assert(sizeof(ApplicationData) == 0x404, "ApplicationData is an invalid size");
94
95 struct LoadAlbumScreenShotImageOutput {
96 s64 width;
97 s64 height;
98 ScreenShotAttribute attribute;
99 INSERT_PADDING_BYTES(0x400);
100 };
101 static_assert(sizeof(LoadAlbumScreenShotImageOutput) == 0x450,
102 "LoadAlbumScreenShotImageOutput is an invalid size");
103
104 struct LoadAlbumScreenShotImageOutputForApplication {
105 s64 width;
106 s64 height;
107 ScreenShotAttribute attribute;
108 ApplicationData data;
109 INSERT_PADDING_BYTES(0xAC);
110 };
111 static_assert(sizeof(LoadAlbumScreenShotImageOutputForApplication) == 0x500,
112 "LoadAlbumScreenShotImageOutput is an invalid size");
113
114 void DeleteAlbumFile(HLERequestContext& ctx);
115 void IsAlbumMounted(HLERequestContext& ctx);
116 void Unknown18(HLERequestContext& ctx);
117 void GetAlbumFileListEx0(HLERequestContext& ctx);
118 void GetAutoSavingStorage(HLERequestContext& ctx);
119 void LoadAlbumScreenShotImageEx1(HLERequestContext& ctx);
120 void LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx);
121
122private:
123 void FindScreenshots();
124 Result GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem::path& path);
125 Result LoadImage(std::span<u8> out_image, const std::filesystem::path& path, int width,
126 int height, ScreenShotDecoderFlag flag);
127
128 bool is_mounted{};
129 std::vector<std::filesystem::path> sd_image_paths{};
18}; 130};
19 131
20} // namespace Service::Capture 132} // namespace Service::Capture
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 6e0baf0be..f9e0e272d 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -7,6 +7,7 @@
7#include "core/file_sys/control_metadata.h" 7#include "core/file_sys/control_metadata.h"
8#include "core/file_sys/patch_manager.h" 8#include "core/file_sys/patch_manager.h"
9#include "core/file_sys/vfs.h" 9#include "core/file_sys/vfs.h"
10#include "core/hle/service/filesystem/filesystem.h"
10#include "core/hle/service/glue/glue_manager.h" 11#include "core/hle/service/glue/glue_manager.h"
11#include "core/hle/service/ipc_helpers.h" 12#include "core/hle/service/ipc_helpers.h"
12#include "core/hle/service/ns/errors.h" 13#include "core/hle/service/ns/errors.h"
@@ -502,8 +503,8 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
502 static const FunctionInfo functions[] = { 503 static const FunctionInfo functions[] = {
503 {11, nullptr, "CalculateApplicationOccupiedSize"}, 504 {11, nullptr, "CalculateApplicationOccupiedSize"},
504 {43, nullptr, "CheckSdCardMountStatus"}, 505 {43, nullptr, "CheckSdCardMountStatus"},
505 {47, nullptr, "GetTotalSpaceSize"}, 506 {47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"},
506 {48, nullptr, "GetFreeSpaceSize"}, 507 {48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"},
507 {600, nullptr, "CountApplicationContentMeta"}, 508 {600, nullptr, "CountApplicationContentMeta"},
508 {601, nullptr, "ListApplicationContentMetaStatus"}, 509 {601, nullptr, "ListApplicationContentMetaStatus"},
509 {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, 510 {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
@@ -516,6 +517,28 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
516 517
517IContentManagementInterface::~IContentManagementInterface() = default; 518IContentManagementInterface::~IContentManagementInterface() = default;
518 519
520void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) {
521 IPC::RequestParser rp{ctx};
522 const auto storage{rp.PopEnum<FileSys::StorageId>()};
523
524 LOG_INFO(Service_Capture, "called, storage={}", storage);
525
526 IPC::ResponseBuilder rb{ctx, 4};
527 rb.Push(ResultSuccess);
528 rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage));
529}
530
531void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) {
532 IPC::RequestParser rp{ctx};
533 const auto storage{rp.PopEnum<FileSys::StorageId>()};
534
535 LOG_INFO(Service_Capture, "called, storage={}", storage);
536
537 IPC::ResponseBuilder rb{ctx, 4};
538 rb.Push(ResultSuccess);
539 rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage));
540}
541
519IDocumentInterface::IDocumentInterface(Core::System& system_) 542IDocumentInterface::IDocumentInterface(Core::System& system_)
520 : ServiceFramework{system_, "IDocumentInterface"} { 543 : ServiceFramework{system_, "IDocumentInterface"} {
521 // clang-format off 544 // clang-format off
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h
index 175dad780..34d2a45dc 100644
--- a/src/core/hle/service/ns/ns.h
+++ b/src/core/hle/service/ns/ns.h
@@ -48,6 +48,10 @@ class IContentManagementInterface final : public ServiceFramework<IContentManage
48public: 48public:
49 explicit IContentManagementInterface(Core::System& system_); 49 explicit IContentManagementInterface(Core::System& system_);
50 ~IContentManagementInterface() override; 50 ~IContentManagementInterface() override;
51
52private:
53 void GetTotalSpaceSize(HLERequestContext& ctx);
54 void GetFreeSpaceSize(HLERequestContext& ctx);
51}; 55};
52 56
53class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { 57class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {