mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 10:44:49 +01:00 
			
		
		
		
	service: caps: Partially implement IAlbumAccessorService
This commit is contained in:
		
							parent
							
								
									2fa53ec1d9
								
							
						
					
					
						commit
						c334959440
					
				| @ -16,7 +16,7 @@ namespace Service::Capture { | ||||
| void LoopProcess(Core::System& system) { | ||||
|     auto server_manager = std::make_unique<ServerManager>(system); | ||||
| 
 | ||||
|     server_manager->RegisterNamedService("caps:a", std::make_shared<CAPS_A>(system)); | ||||
|     server_manager->RegisterNamedService("caps:a", std::make_shared<IAlbumAccessorService>(system)); | ||||
|     server_manager->RegisterNamedService("caps:c", std::make_shared<CAPS_C>(system)); | ||||
|     server_manager->RegisterNamedService("caps:u", std::make_shared<CAPS_U>(system)); | ||||
|     server_manager->RegisterNamedService("caps:sc", std::make_shared<CAPS_SC>(system)); | ||||
|  | ||||
| @ -1,7 +1,14 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include <sstream> | ||||
| #include <stb_image.h> | ||||
| #include <stb_image_resize.h> | ||||
| 
 | ||||
| #include "common/fs/file.h" | ||||
| #include "common/fs/path_util.h" | ||||
| #include "core/hle/service/caps/caps_a.h" | ||||
| #include "core/hle/service/ipc_helpers.h" | ||||
| 
 | ||||
| namespace Service::Capture { | ||||
| 
 | ||||
| @ -26,15 +33,16 @@ public: | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} { | ||||
| IAlbumAccessorService::IAlbumAccessorService(Core::System& system_) | ||||
|     : ServiceFramework{system_, "caps:a"} { | ||||
|     // clang-format off
 | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, nullptr, "GetAlbumFileCount"}, | ||||
|         {1, nullptr, "GetAlbumFileList"}, | ||||
|         {2, nullptr, "LoadAlbumFile"}, | ||||
|         {3, nullptr, "DeleteAlbumFile"}, | ||||
|         {3, &IAlbumAccessorService::DeleteAlbumFile, "DeleteAlbumFile"}, | ||||
|         {4, nullptr, "StorageCopyAlbumFile"}, | ||||
|         {5, nullptr, "IsAlbumMounted"}, | ||||
|         {5, &IAlbumAccessorService::IsAlbumMounted, "IsAlbumMounted"}, | ||||
|         {6, nullptr, "GetAlbumUsage"}, | ||||
|         {7, nullptr, "GetAlbumFileSize"}, | ||||
|         {8, nullptr, "LoadAlbumFileThumbnail"}, | ||||
| @ -47,18 +55,18 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} { | ||||
|         {15, nullptr, "GetAlbumUsage3"}, | ||||
|         {16, nullptr, "GetAlbumMountResult"}, | ||||
|         {17, nullptr, "GetAlbumUsage16"}, | ||||
|         {18, nullptr, "Unknown18"}, | ||||
|         {18, &IAlbumAccessorService::Unknown18, "Unknown18"}, | ||||
|         {19, nullptr, "Unknown19"}, | ||||
|         {100, nullptr, "GetAlbumFileCountEx0"}, | ||||
|         {101, nullptr, "GetAlbumFileListEx0"}, | ||||
|         {101, &IAlbumAccessorService::GetAlbumFileListEx0, "GetAlbumFileListEx0"}, | ||||
|         {202, nullptr, "SaveEditedScreenShot"}, | ||||
|         {301, nullptr, "GetLastThumbnail"}, | ||||
|         {302, nullptr, "GetLastOverlayMovieThumbnail"}, | ||||
|         {401, nullptr, "GetAutoSavingStorage"}, | ||||
|         {401,  &IAlbumAccessorService::GetAutoSavingStorage, "GetAutoSavingStorage"}, | ||||
|         {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"}, | ||||
|         {1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"}, | ||||
|         {1002, nullptr, "LoadAlbumScreenShotImageEx1"}, | ||||
|         {1003, nullptr, "LoadAlbumScreenShotThumbnailImageEx1"}, | ||||
|         {1002, &IAlbumAccessorService::LoadAlbumScreenShotImageEx1, "LoadAlbumScreenShotImageEx1"}, | ||||
|         {1003, &IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1, "LoadAlbumScreenShotThumbnailImageEx1"}, | ||||
|         {8001, nullptr, "ForceAlbumUnmounted"}, | ||||
|         {8002, nullptr, "ResetAlbumMountStatus"}, | ||||
|         {8011, nullptr, "RefreshAlbumCache"}, | ||||
| @ -74,6 +82,294 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} { | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| CAPS_A::~CAPS_A() = default; | ||||
| IAlbumAccessorService::~IAlbumAccessorService() = default; | ||||
| 
 | ||||
| void IAlbumAccessorService::DeleteAlbumFile(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto file_id{rp.PopRaw<AlbumFileId>()}; | ||||
| 
 | ||||
|     LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}", | ||||
|              file_id.application_id, file_id.storage, file_id.type); | ||||
| 
 | ||||
|     if (file_id.storage == AlbumStorage::Sd) { | ||||
|         if (!Common::FS::RemoveFile(sd_image_paths[file_id.date.unique_id])) { | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultUnknown); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IAlbumAccessorService::IsAlbumMounted(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto storage{rp.PopEnum<AlbumStorage>()}; | ||||
| 
 | ||||
|     LOG_INFO(Service_Capture, "called, storage={}, is_mounted={}", storage, is_mounted); | ||||
| 
 | ||||
|     if (storage == AlbumStorage::Sd) { | ||||
|         FindScreenshots(); | ||||
|     } | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push<u8>(is_mounted); | ||||
| } | ||||
| 
 | ||||
| void IAlbumAccessorService::Unknown18(HLERequestContext& ctx) { | ||||
|     struct UnknownBuffer { | ||||
|         INSERT_PADDING_BYTES(0x10); | ||||
|     }; | ||||
|     static_assert(sizeof(UnknownBuffer) == 0x10, "UnknownBuffer is an invalid size"); | ||||
| 
 | ||||
|     LOG_WARNING(Service_Capture, "(STUBBED) called"); | ||||
| 
 | ||||
|     std::vector<UnknownBuffer> buffer{}; | ||||
| 
 | ||||
|     if (!buffer.empty()) { | ||||
|         ctx.WriteBuffer(buffer); | ||||
|     } | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(static_cast<u32>(buffer.size())); | ||||
| } | ||||
| 
 | ||||
| void IAlbumAccessorService::GetAlbumFileListEx0(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto storage{rp.PopEnum<AlbumStorage>()}; | ||||
|     const auto flags{rp.Pop<u8>()}; | ||||
| 
 | ||||
|     LOG_INFO(Service_Capture, "called, storage={}, flags={}", storage, flags); | ||||
| 
 | ||||
|     std::vector<AlbumEntry> entries{}; | ||||
| 
 | ||||
|     if (storage == AlbumStorage::Sd) { | ||||
|         AlbumEntry entry; | ||||
|         for (u8 i = 0; i < static_cast<u8>(sd_image_paths.size()); i++) { | ||||
|             if (GetAlbumEntry(entry, sd_image_paths[i]).IsError()) { | ||||
|                 continue; | ||||
|             } | ||||
|             entry.file_id.date.unique_id = i; | ||||
|             entries.push_back(entry); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (!entries.empty()) { | ||||
|         ctx.WriteBuffer(entries); | ||||
|     } | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(entries.size()); | ||||
| } | ||||
| 
 | ||||
| void IAlbumAccessorService::GetAutoSavingStorage(HLERequestContext& ctx) { | ||||
|     bool is_autosaving{}; | ||||
| 
 | ||||
|     LOG_WARNING(Service_Capture, "(STUBBED) called, is_autosaving={}", is_autosaving); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push<u8>(is_autosaving); | ||||
| } | ||||
| 
 | ||||
| void IAlbumAccessorService::LoadAlbumScreenShotImageEx1(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto file_id{rp.PopRaw<AlbumFileId>()}; | ||||
|     const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()}; | ||||
| 
 | ||||
|     LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}", | ||||
|              file_id.application_id, file_id.storage, file_id.type, decoder_options.flags); | ||||
| 
 | ||||
|     const LoadAlbumScreenShotImageOutput image_output{ | ||||
|         .width = 1280, | ||||
|         .height = 720, | ||||
|         .attribute = | ||||
|             { | ||||
|                 .unknown_0{}, | ||||
|                 .orientation = ScreenShotOrientation::None, | ||||
|                 .unknown_1{}, | ||||
|                 .unknown_2{}, | ||||
|             }, | ||||
|     }; | ||||
| 
 | ||||
|     std::vector<u8> image(image_output.height * image_output.width * STBI_rgb_alpha); | ||||
| 
 | ||||
|     if (file_id.storage == AlbumStorage::Sd) { | ||||
|         LoadImage(image, sd_image_paths[file_id.date.unique_id], | ||||
|                   static_cast<int>(image_output.width), static_cast<int>(image_output.height), | ||||
|                   decoder_options.flags); | ||||
|     } | ||||
| 
 | ||||
|     ctx.WriteBuffer(image_output, 0); | ||||
|     ctx.WriteBuffer(image, 1); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto file_id{rp.PopRaw<AlbumFileId>()}; | ||||
|     const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()}; | ||||
| 
 | ||||
|     LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}", | ||||
|              file_id.application_id, file_id.storage, file_id.type, decoder_options.flags); | ||||
| 
 | ||||
|     const LoadAlbumScreenShotImageOutput image_output{ | ||||
|         .width = 320, | ||||
|         .height = 180, | ||||
|         .attribute = | ||||
|             { | ||||
|                 .unknown_0{}, | ||||
|                 .orientation = ScreenShotOrientation::None, | ||||
|                 .unknown_1{}, | ||||
|                 .unknown_2{}, | ||||
|             }, | ||||
|     }; | ||||
| 
 | ||||
|     std::vector<u8> image(image_output.height * image_output.width * STBI_rgb_alpha); | ||||
| 
 | ||||
|     if (file_id.storage == AlbumStorage::Sd) { | ||||
|         LoadImage(image, sd_image_paths[file_id.date.unique_id], | ||||
|                   static_cast<int>(image_output.width), static_cast<int>(image_output.height), | ||||
|                   decoder_options.flags); | ||||
|     } | ||||
| 
 | ||||
|     ctx.WriteBuffer(image_output, 0); | ||||
|     ctx.WriteBuffer(image, 1); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IAlbumAccessorService::FindScreenshots() { | ||||
|     is_mounted = false; | ||||
|     sd_image_paths.clear(); | ||||
| 
 | ||||
|     // TODO: Swap this with a blocking operation.
 | ||||
|     const auto screenshots_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ScreenshotsDir); | ||||
|     Common::FS::IterateDirEntries( | ||||
|         screenshots_dir, | ||||
|         [this](const std::filesystem::path& full_path) { | ||||
|             AlbumEntry entry; | ||||
|             // TODO: Implement proper indexing to allow more images
 | ||||
|             if (sd_image_paths.size() > 0xFF) { | ||||
|                 return true; | ||||
|             } | ||||
|             if (GetAlbumEntry(entry, full_path).IsSuccess()) { | ||||
|                 sd_image_paths.push_back(full_path); | ||||
|             } | ||||
|             return true; | ||||
|         }, | ||||
|         Common::FS::DirEntryFilter::File); | ||||
| 
 | ||||
|     is_mounted = true; | ||||
| } | ||||
| 
 | ||||
| Result IAlbumAccessorService::GetAlbumEntry(AlbumEntry& out_entry, | ||||
|                                             const std::filesystem::path& path) { | ||||
|     std::istringstream line_stream(path.filename().string()); | ||||
|     std::string date; | ||||
|     std::string application; | ||||
|     std::string time; | ||||
| 
 | ||||
|     // Parse filename to obtain entry properties
 | ||||
|     std::getline(line_stream, application, '_'); | ||||
|     std::getline(line_stream, date, '_'); | ||||
|     std::getline(line_stream, time, '_'); | ||||
| 
 | ||||
|     std::istringstream date_stream(date); | ||||
|     std::istringstream time_stream(time); | ||||
|     std::string year; | ||||
|     std::string month; | ||||
|     std::string day; | ||||
|     std::string hour; | ||||
|     std::string minute; | ||||
|     std::string second; | ||||
| 
 | ||||
|     std::getline(date_stream, year, '-'); | ||||
|     std::getline(date_stream, month, '-'); | ||||
|     std::getline(date_stream, day, '-'); | ||||
| 
 | ||||
|     std::getline(time_stream, hour, '-'); | ||||
|     std::getline(time_stream, minute, '-'); | ||||
|     std::getline(time_stream, second, '-'); | ||||
| 
 | ||||
|     try { | ||||
|         out_entry = { | ||||
|             .entry_size = 1, | ||||
|             .file_id{ | ||||
|                 .application_id = static_cast<u64>(std::stoll(application, 0, 16)), | ||||
|                 .date = | ||||
|                     { | ||||
|                         .year = static_cast<u16>(std::stoi(year)), | ||||
|                         .month = static_cast<u8>(std::stoi(month)), | ||||
|                         .day = static_cast<u8>(std::stoi(day)), | ||||
|                         .hour = static_cast<u8>(std::stoi(hour)), | ||||
|                         .minute = static_cast<u8>(std::stoi(minute)), | ||||
|                         .second = static_cast<u8>(std::stoi(second)), | ||||
|                         .unique_id = 0, | ||||
|                     }, | ||||
|                 .storage = AlbumStorage::Sd, | ||||
|                 .type = ContentType::Screenshot, | ||||
|                 .unknown = 1, | ||||
|             }, | ||||
|         }; | ||||
|     } catch (const std::invalid_argument&) { | ||||
|         return ResultUnknown; | ||||
|     } catch (const std::out_of_range&) { | ||||
|         return ResultUnknown; | ||||
|     } catch (const std::exception&) { | ||||
|         return ResultUnknown; | ||||
|     } | ||||
| 
 | ||||
|     return ResultSuccess; | ||||
| } | ||||
| 
 | ||||
| Result IAlbumAccessorService::LoadImage(std::span<u8> out_image, const std::filesystem::path& path, | ||||
|                                         int width, int height, ScreenShotDecoderFlag flag) { | ||||
|     if (out_image.size() != static_cast<std::size_t>(width * height * STBI_rgb_alpha)) { | ||||
|         return ResultUnknown; | ||||
|     } | ||||
| 
 | ||||
|     const Common::FS::IOFile db_file{path, Common::FS::FileAccessMode::Read, | ||||
|                                      Common::FS::FileType::BinaryFile}; | ||||
| 
 | ||||
|     std::vector<u8> raw_file(db_file.GetSize()); | ||||
|     if (db_file.Read(raw_file) != raw_file.size()) { | ||||
|         return ResultUnknown; | ||||
|     } | ||||
| 
 | ||||
|     int filter_flag = STBIR_FILTER_DEFAULT; | ||||
|     int original_width, original_height, color_channels; | ||||
|     const auto dbi_image = | ||||
|         stbi_load_from_memory(raw_file.data(), static_cast<int>(raw_file.size()), &original_width, | ||||
|                               &original_height, &color_channels, STBI_rgb_alpha); | ||||
| 
 | ||||
|     if (dbi_image == nullptr) { | ||||
|         return ResultUnknown; | ||||
|     } | ||||
| 
 | ||||
|     switch (flag) { | ||||
|     case ScreenShotDecoderFlag::EnableFancyUpsampling: | ||||
|         filter_flag = STBIR_FILTER_TRIANGLE; | ||||
|         break; | ||||
|     case ScreenShotDecoderFlag::EnableBlockSmoothing: | ||||
|         filter_flag = STBIR_FILTER_BOX; | ||||
|         break; | ||||
|     default: | ||||
|         filter_flag = STBIR_FILTER_DEFAULT; | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     stbir_resize_uint8_srgb(dbi_image, original_width, original_height, 0, out_image.data(), width, | ||||
|                             height, 0, STBI_rgb_alpha, 3, filter_flag); | ||||
| 
 | ||||
|     return ResultSuccess; | ||||
| } | ||||
| 
 | ||||
| } // namespace Service::Capture
 | ||||
|  | ||||
| @ -3,6 +3,7 @@ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/fs/fs.h" | ||||
| #include "core/hle/service/service.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| @ -11,10 +12,121 @@ class System; | ||||
| 
 | ||||
| namespace Service::Capture { | ||||
| 
 | ||||
| class CAPS_A final : public ServiceFramework<CAPS_A> { | ||||
| class IAlbumAccessorService final : public ServiceFramework<IAlbumAccessorService> { | ||||
| public: | ||||
|     explicit CAPS_A(Core::System& system_); | ||||
|     ~CAPS_A() override; | ||||
|     explicit IAlbumAccessorService(Core::System& system_); | ||||
|     ~IAlbumAccessorService() override; | ||||
| 
 | ||||
| private: | ||||
|     enum class ContentType : u8 { | ||||
|         Screenshot, | ||||
|         Movie, | ||||
|         ExtraMovie, | ||||
|     }; | ||||
| 
 | ||||
|     enum class AlbumStorage : u8 { | ||||
|         Nand, | ||||
|         Sd, | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
|     enum class ScreenShotDecoderFlag : u64 { | ||||
|         None = 0, | ||||
|         EnableFancyUpsampling = 1 << 0, | ||||
|         EnableBlockSmoothing = 1 << 1, | ||||
|     }; | ||||
| 
 | ||||
|     enum class ScreenShotOrientation : u32 { | ||||
|         None, | ||||
|         Rotate90, | ||||
|         Rotate180, | ||||
|         Rotate270, | ||||
|     }; | ||||
| 
 | ||||
|     struct ScreenShotAttribute { | ||||
|         u32 unknown_0; | ||||
|         ScreenShotOrientation orientation; | ||||
|         u32 unknown_1; | ||||
|         u32 unknown_2; | ||||
|         INSERT_PADDING_BYTES(0x30); | ||||
|     }; | ||||
|     static_assert(sizeof(ScreenShotAttribute) == 0x40, "ScreenShotAttribute is an invalid size"); | ||||
| 
 | ||||
|     struct ScreenShotDecodeOption { | ||||
|         ScreenShotDecoderFlag flags; | ||||
|         INSERT_PADDING_BYTES(0x18); | ||||
|     }; | ||||
|     static_assert(sizeof(ScreenShotDecodeOption) == 0x20, | ||||
|                   "ScreenShotDecodeOption is an invalid size"); | ||||
| 
 | ||||
|     struct AlbumFileDateTime { | ||||
|         u16 year; | ||||
|         u8 month; | ||||
|         u8 day; | ||||
|         u8 hour; | ||||
|         u8 minute; | ||||
|         u8 second; | ||||
|         u8 unique_id; | ||||
|     }; | ||||
|     static_assert(sizeof(AlbumFileDateTime) == 0x8, "AlbumFileDateTime is an invalid size"); | ||||
| 
 | ||||
|     struct AlbumFileId { | ||||
|         u64 application_id; | ||||
|         AlbumFileDateTime date; | ||||
|         AlbumStorage storage; | ||||
|         ContentType type; | ||||
|         INSERT_PADDING_BYTES(0x5); | ||||
|         u8 unknown; | ||||
|     }; | ||||
|     static_assert(sizeof(AlbumFileId) == 0x18, "AlbumFileId is an invalid size"); | ||||
| 
 | ||||
|     struct AlbumEntry { | ||||
|         u64 entry_size; | ||||
|         AlbumFileId file_id; | ||||
|     }; | ||||
|     static_assert(sizeof(AlbumEntry) == 0x20, "AlbumEntry is an invalid size"); | ||||
| 
 | ||||
|     struct ApplicationData { | ||||
|         std::array<u8, 0x400> data; | ||||
|         u32 data_size; | ||||
|     }; | ||||
|     static_assert(sizeof(ApplicationData) == 0x404, "ApplicationData is an invalid size"); | ||||
| 
 | ||||
|     struct LoadAlbumScreenShotImageOutput { | ||||
|         s64 width; | ||||
|         s64 height; | ||||
|         ScreenShotAttribute attribute; | ||||
|         INSERT_PADDING_BYTES(0x400); | ||||
|     }; | ||||
|     static_assert(sizeof(LoadAlbumScreenShotImageOutput) == 0x450, | ||||
|                   "LoadAlbumScreenShotImageOutput is an invalid size"); | ||||
| 
 | ||||
|     struct LoadAlbumScreenShotImageOutputForApplication { | ||||
|         s64 width; | ||||
|         s64 height; | ||||
|         ScreenShotAttribute attribute; | ||||
|         ApplicationData data; | ||||
|         INSERT_PADDING_BYTES(0xAC); | ||||
|     }; | ||||
|     static_assert(sizeof(LoadAlbumScreenShotImageOutputForApplication) == 0x500, | ||||
|                   "LoadAlbumScreenShotImageOutput is an invalid size"); | ||||
| 
 | ||||
|     void DeleteAlbumFile(HLERequestContext& ctx); | ||||
|     void IsAlbumMounted(HLERequestContext& ctx); | ||||
|     void Unknown18(HLERequestContext& ctx); | ||||
|     void GetAlbumFileListEx0(HLERequestContext& ctx); | ||||
|     void GetAutoSavingStorage(HLERequestContext& ctx); | ||||
|     void LoadAlbumScreenShotImageEx1(HLERequestContext& ctx); | ||||
|     void LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx); | ||||
| 
 | ||||
| private: | ||||
|     void FindScreenshots(); | ||||
|     Result GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem::path& path); | ||||
|     Result LoadImage(std::span<u8> out_image, const std::filesystem::path& path, int width, | ||||
|                      int height, ScreenShotDecoderFlag flag); | ||||
| 
 | ||||
|     bool is_mounted{}; | ||||
|     std::vector<std::filesystem::path> sd_image_paths{}; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Service::Capture
 | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| #include "core/file_sys/control_metadata.h" | ||||
| #include "core/file_sys/patch_manager.h" | ||||
| #include "core/file_sys/vfs.h" | ||||
| #include "core/hle/service/filesystem/filesystem.h" | ||||
| #include "core/hle/service/glue/glue_manager.h" | ||||
| #include "core/hle/service/ipc_helpers.h" | ||||
| #include "core/hle/service/ns/errors.h" | ||||
| @ -502,8 +503,8 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_) | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {11, nullptr, "CalculateApplicationOccupiedSize"}, | ||||
|         {43, nullptr, "CheckSdCardMountStatus"}, | ||||
|         {47, nullptr, "GetTotalSpaceSize"}, | ||||
|         {48, nullptr, "GetFreeSpaceSize"}, | ||||
|         {47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"}, | ||||
|         {48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"}, | ||||
|         {600, nullptr, "CountApplicationContentMeta"}, | ||||
|         {601, nullptr, "ListApplicationContentMetaStatus"}, | ||||
|         {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, | ||||
| @ -516,6 +517,28 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_) | ||||
| 
 | ||||
| IContentManagementInterface::~IContentManagementInterface() = default; | ||||
| 
 | ||||
| void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto storage{rp.PopEnum<FileSys::StorageId>()}; | ||||
| 
 | ||||
|     LOG_INFO(Service_Capture, "called, storage={}", storage); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 4}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage)); | ||||
| } | ||||
| 
 | ||||
| void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto storage{rp.PopEnum<FileSys::StorageId>()}; | ||||
| 
 | ||||
|     LOG_INFO(Service_Capture, "called, storage={}", storage); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 4}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage)); | ||||
| } | ||||
| 
 | ||||
| IDocumentInterface::IDocumentInterface(Core::System& system_) | ||||
|     : ServiceFramework{system_, "IDocumentInterface"} { | ||||
|     // clang-format off
 | ||||
|  | ||||
| @ -48,6 +48,10 @@ class IContentManagementInterface final : public ServiceFramework<IContentManage | ||||
| public: | ||||
|     explicit IContentManagementInterface(Core::System& system_); | ||||
|     ~IContentManagementInterface() override; | ||||
| 
 | ||||
| private: | ||||
|     void GetTotalSpaceSize(HLERequestContext& ctx); | ||||
|     void GetFreeSpaceSize(HLERequestContext& ctx); | ||||
| }; | ||||
| 
 | ||||
| class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user