caps_a.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/logging/log.h"
  4. #include "core/hle/service/caps/caps_a.h"
  5. #include "core/hle/service/caps/caps_manager.h"
  6. #include "core/hle/service/caps/caps_result.h"
  7. #include "core/hle/service/caps/caps_types.h"
  8. #include "core/hle/service/ipc_helpers.h"
  9. namespace Service::Capture {
  10. IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
  11. std::shared_ptr<AlbumManager> album_manager)
  12. : ServiceFramework{system_, "caps:a"}, manager{album_manager} {
  13. // clang-format off
  14. static const FunctionInfo functions[] = {
  15. {0, nullptr, "GetAlbumFileCount"},
  16. {1, nullptr, "GetAlbumFileList"},
  17. {2, nullptr, "LoadAlbumFile"},
  18. {3, &IAlbumAccessorService::DeleteAlbumFile, "DeleteAlbumFile"},
  19. {4, nullptr, "StorageCopyAlbumFile"},
  20. {5, &IAlbumAccessorService::IsAlbumMounted, "IsAlbumMounted"},
  21. {6, nullptr, "GetAlbumUsage"},
  22. {7, nullptr, "GetAlbumFileSize"},
  23. {8, nullptr, "LoadAlbumFileThumbnail"},
  24. {9, nullptr, "LoadAlbumScreenShotImage"},
  25. {10, nullptr, "LoadAlbumScreenShotThumbnailImage"},
  26. {11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"},
  27. {12, nullptr, "LoadAlbumScreenShotImageEx"},
  28. {13, nullptr, "LoadAlbumScreenShotThumbnailImageEx"},
  29. {14, nullptr, "LoadAlbumScreenShotImageEx0"},
  30. {15, nullptr, "GetAlbumUsage3"},
  31. {16, nullptr, "GetAlbumMountResult"},
  32. {17, nullptr, "GetAlbumUsage16"},
  33. {18, &IAlbumAccessorService::Unknown18, "Unknown18"},
  34. {19, nullptr, "Unknown19"},
  35. {100, nullptr, "GetAlbumFileCountEx0"},
  36. {101, &IAlbumAccessorService::GetAlbumFileListEx0, "GetAlbumFileListEx0"},
  37. {202, nullptr, "SaveEditedScreenShot"},
  38. {301, nullptr, "GetLastThumbnail"},
  39. {302, nullptr, "GetLastOverlayMovieThumbnail"},
  40. {401, &IAlbumAccessorService::GetAutoSavingStorage, "GetAutoSavingStorage"},
  41. {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
  42. {1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"},
  43. {1002, &IAlbumAccessorService::LoadAlbumScreenShotImageEx1, "LoadAlbumScreenShotImageEx1"},
  44. {1003, &IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1, "LoadAlbumScreenShotThumbnailImageEx1"},
  45. {8001, nullptr, "ForceAlbumUnmounted"},
  46. {8002, nullptr, "ResetAlbumMountStatus"},
  47. {8011, nullptr, "RefreshAlbumCache"},
  48. {8012, nullptr, "GetAlbumCache"},
  49. {8013, nullptr, "GetAlbumCacheEx"},
  50. {8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"},
  51. {10011, nullptr, "SetInternalErrorConversionEnabled"},
  52. {50000, nullptr, "LoadMakerNoteInfoForDebug"},
  53. {60002, nullptr, "OpenAccessorSession"},
  54. };
  55. // clang-format on
  56. RegisterHandlers(functions);
  57. }
  58. IAlbumAccessorService::~IAlbumAccessorService() = default;
  59. void IAlbumAccessorService::DeleteAlbumFile(HLERequestContext& ctx) {
  60. IPC::RequestParser rp{ctx};
  61. const auto file_id{rp.PopRaw<AlbumFileId>()};
  62. LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}",
  63. file_id.application_id, file_id.storage, file_id.type);
  64. Result result = manager->DeleteAlbumFile(file_id);
  65. result = TranslateResult(result);
  66. IPC::ResponseBuilder rb{ctx, 2};
  67. rb.Push(result);
  68. }
  69. void IAlbumAccessorService::IsAlbumMounted(HLERequestContext& ctx) {
  70. IPC::RequestParser rp{ctx};
  71. const auto storage{rp.PopEnum<AlbumStorage>()};
  72. LOG_INFO(Service_Capture, "called, storage={}", storage);
  73. Result result = manager->IsAlbumMounted(storage);
  74. const bool is_mounted = result.IsSuccess();
  75. result = TranslateResult(result);
  76. IPC::ResponseBuilder rb{ctx, 3};
  77. rb.Push(result);
  78. rb.Push<u8>(is_mounted);
  79. }
  80. void IAlbumAccessorService::Unknown18(HLERequestContext& ctx) {
  81. struct UnknownBuffer {
  82. INSERT_PADDING_BYTES(0x10);
  83. };
  84. static_assert(sizeof(UnknownBuffer) == 0x10, "UnknownBuffer is an invalid size");
  85. LOG_WARNING(Service_Capture, "(STUBBED) called");
  86. std::vector<UnknownBuffer> buffer{};
  87. if (!buffer.empty()) {
  88. ctx.WriteBuffer(buffer);
  89. }
  90. IPC::ResponseBuilder rb{ctx, 3};
  91. rb.Push(ResultSuccess);
  92. rb.Push(static_cast<u32>(buffer.size()));
  93. }
  94. void IAlbumAccessorService::GetAlbumFileListEx0(HLERequestContext& ctx) {
  95. IPC::RequestParser rp{ctx};
  96. const auto storage{rp.PopEnum<AlbumStorage>()};
  97. const auto flags{rp.Pop<u8>()};
  98. const auto album_entry_size{ctx.GetWriteBufferNumElements<AlbumEntry>()};
  99. LOG_INFO(Service_Capture, "called, storage={}, flags={}", storage, flags);
  100. std::vector<AlbumEntry> entries;
  101. Result result = manager->GetAlbumFileList(entries, storage, flags);
  102. result = TranslateResult(result);
  103. entries.resize(std::min(album_entry_size, entries.size()));
  104. if (!entries.empty()) {
  105. ctx.WriteBuffer(entries);
  106. }
  107. IPC::ResponseBuilder rb{ctx, 3};
  108. rb.Push(result);
  109. rb.Push(entries.size());
  110. }
  111. void IAlbumAccessorService::GetAutoSavingStorage(HLERequestContext& ctx) {
  112. LOG_WARNING(Service_Capture, "(STUBBED) called");
  113. bool is_autosaving{};
  114. Result result = manager->GetAutoSavingStorage(is_autosaving);
  115. result = TranslateResult(result);
  116. IPC::ResponseBuilder rb{ctx, 3};
  117. rb.Push(result);
  118. rb.Push<u8>(is_autosaving);
  119. }
  120. void IAlbumAccessorService::LoadAlbumScreenShotImageEx1(HLERequestContext& ctx) {
  121. IPC::RequestParser rp{ctx};
  122. const auto file_id{rp.PopRaw<AlbumFileId>()};
  123. const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()};
  124. const auto image_buffer_size{ctx.GetWriteBufferSize(1)};
  125. LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}",
  126. file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
  127. std::vector<u8> image;
  128. LoadAlbumScreenShotImageOutput image_output;
  129. Result result =
  130. manager->LoadAlbumScreenShotImage(image_output, image, file_id, decoder_options);
  131. result = TranslateResult(result);
  132. if (image.size() > image_buffer_size) {
  133. result = ResultWorkMemoryError;
  134. }
  135. if (result.IsSuccess()) {
  136. ctx.WriteBuffer(image_output, 0);
  137. ctx.WriteBuffer(image, 1);
  138. }
  139. IPC::ResponseBuilder rb{ctx, 2};
  140. rb.Push(result);
  141. }
  142. void IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx) {
  143. IPC::RequestParser rp{ctx};
  144. const auto file_id{rp.PopRaw<AlbumFileId>()};
  145. const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()};
  146. LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}",
  147. file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
  148. std::vector<u8> image(ctx.GetWriteBufferSize(1));
  149. LoadAlbumScreenShotImageOutput image_output;
  150. Result result =
  151. manager->LoadAlbumScreenShotThumbnail(image_output, image, file_id, decoder_options);
  152. result = TranslateResult(result);
  153. if (result.IsSuccess()) {
  154. ctx.WriteBuffer(image_output, 0);
  155. ctx.WriteBuffer(image, 1);
  156. }
  157. IPC::ResponseBuilder rb{ctx, 2};
  158. rb.Push(result);
  159. }
  160. Result IAlbumAccessorService::TranslateResult(Result in_result) {
  161. if (in_result.IsSuccess()) {
  162. return in_result;
  163. }
  164. if ((in_result.raw & 0x3801ff) == ResultUnknown1024.raw) {
  165. if (in_result.description - 0x514 < 100) {
  166. return ResultInvalidFileData;
  167. }
  168. if (in_result.description - 0x5dc < 100) {
  169. return ResultInvalidFileData;
  170. }
  171. if (in_result.description - 0x578 < 100) {
  172. if (in_result == ResultFileCountLimit) {
  173. return ResultUnknown22;
  174. }
  175. return ResultUnknown25;
  176. }
  177. if (in_result.raw < ResultUnknown1801.raw) {
  178. if (in_result == ResultUnknown1202) {
  179. return ResultUnknown810;
  180. }
  181. if (in_result == ResultUnknown1203) {
  182. return ResultUnknown810;
  183. }
  184. if (in_result == ResultUnknown1701) {
  185. return ResultUnknown5;
  186. }
  187. } else if (in_result.raw < ResultUnknown1803.raw) {
  188. if (in_result == ResultUnknown1801) {
  189. return ResultUnknown5;
  190. }
  191. if (in_result == ResultUnknown1802) {
  192. return ResultUnknown6;
  193. }
  194. } else {
  195. if (in_result == ResultUnknown1803) {
  196. return ResultUnknown7;
  197. }
  198. if (in_result == ResultUnknown1804) {
  199. return ResultOutOfRange;
  200. }
  201. }
  202. return ResultUnknown1024;
  203. }
  204. if (in_result.module == ErrorModule::FS) {
  205. if ((in_result.description >> 0xc < 0x7d) || (in_result.description - 1000 < 2000) ||
  206. (((in_result.description - 3000) >> 3) < 0x271)) {
  207. // TODO: Translate FS error
  208. return in_result;
  209. }
  210. }
  211. return in_result;
  212. }
  213. } // namespace Service::Capture