summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/caps/caps.cpp7
-rw-r--r--src/core/hle/service/caps/caps_manager.cpp83
-rw-r--r--src/core/hle/service/caps/caps_manager.h11
-rw-r--r--src/core/hle/service/caps/caps_ss.cpp75
-rw-r--r--src/core/hle/service/caps/caps_ss.h8
-rw-r--r--src/core/hle/service/caps/caps_su.cpp69
-rw-r--r--src/core/hle/service/caps/caps_su.h8
-rw-r--r--src/core/hle/service/caps/caps_types.h2
8 files changed, 250 insertions, 13 deletions
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp
index 31dd98140..cd1dfe993 100644
--- a/src/core/hle/service/caps/caps.cpp
+++ b/src/core/hle/service/caps/caps.cpp
@@ -25,11 +25,12 @@ void LoopProcess(Core::System& system) {
25 server_manager->RegisterNamedService( 25 server_manager->RegisterNamedService(
26 "caps:u", std::make_shared<IAlbumApplicationService>(system, album_manager)); 26 "caps:u", std::make_shared<IAlbumApplicationService>(system, album_manager));
27 27
28 server_manager->RegisterNamedService("caps:ss", std::make_shared<IScreenShotService>(system)); 28 server_manager->RegisterNamedService(
29 "caps:ss", std::make_shared<IScreenShotService>(system, album_manager));
29 server_manager->RegisterNamedService("caps:sc", 30 server_manager->RegisterNamedService("caps:sc",
30 std::make_shared<IScreenShotControlService>(system)); 31 std::make_shared<IScreenShotControlService>(system));
31 server_manager->RegisterNamedService("caps:su", 32 server_manager->RegisterNamedService(
32 std::make_shared<IScreenShotApplicationService>(system)); 33 "caps:su", std::make_shared<IScreenShotApplicationService>(system, album_manager));
33 34
34 ServerManager::RunServer(std::move(server_manager)); 35 ServerManager::RunServer(std::move(server_manager));
35} 36}
diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp
index 2b4e3f076..9c9454b99 100644
--- a/src/core/hle/service/caps/caps_manager.cpp
+++ b/src/core/hle/service/caps/caps_manager.cpp
@@ -4,6 +4,7 @@
4#include <sstream> 4#include <sstream>
5#include <stb_image.h> 5#include <stb_image.h>
6#include <stb_image_resize.h> 6#include <stb_image_resize.h>
7#include <stb_image_write.h>
7 8
8#include "common/fs/file.h" 9#include "common/fs/file.h"
9#include "common/fs/path_util.h" 10#include "common/fs/path_util.h"
@@ -227,6 +228,49 @@ Result AlbumManager::LoadAlbumScreenShotThumbnail(
227 +static_cast<int>(out_image_output.height), decoder_options.flags); 228 +static_cast<int>(out_image_output.height), decoder_options.flags);
228} 229}
229 230
231Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
232 const ScreenShotAttribute& attribute,
233 std::span<const u8> image_data, u64 aruid) {
234 return SaveScreenShot(out_entry, attribute, {}, image_data, aruid);
235}
236
237Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
238 const ScreenShotAttribute& attribute,
239 const ApplicationData& app_data, std::span<const u8> image_data,
240 u64 aruid) {
241 const u64 title_id = system.GetApplicationProcessProgramID();
242 const auto& user_clock = system.GetTimeManager().GetStandardUserSystemClockCore();
243
244 s64 posix_time{};
245 Result result = user_clock.GetCurrentTime(system, posix_time);
246
247 if (result.IsError()) {
248 return result;
249 }
250
251 const auto date = ConvertToAlbumDateTime(posix_time);
252
253 return SaveImage(out_entry, image_data, title_id, date);
254}
255
256Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
257 const ScreenShotAttribute& attribute,
258 const AlbumFileId& file_id,
259 std::span<const u8> image_data) {
260 const auto& user_clock = system.GetTimeManager().GetStandardUserSystemClockCore();
261
262 s64 posix_time{};
263 Result result = user_clock.GetCurrentTime(system, posix_time);
264
265 if (result.IsError()) {
266 return result;
267 }
268
269 const auto date = ConvertToAlbumDateTime(posix_time);
270
271 return SaveImage(out_entry, image_data, file_id.application_id, date);
272}
273
230Result AlbumManager::GetFile(std::filesystem::path& out_path, const AlbumFileId& file_id) const { 274Result AlbumManager::GetFile(std::filesystem::path& out_path, const AlbumFileId& file_id) const {
231 const auto file = album_files.find(file_id); 275 const auto file = album_files.find(file_id);
232 276
@@ -365,6 +409,45 @@ Result AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::p
365 return ResultSuccess; 409 return ResultSuccess;
366} 410}
367 411
412Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image,
413 u64 title_id, const AlbumFileDateTime& date) const {
414 const auto screenshot_path =
415 Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ScreenshotsDir);
416 const std::string formatted_date =
417 fmt::format("{:04}-{:02}-{:02}_{:02}-{:02}-{:02}-{:03}", date.year, date.month, date.day,
418 date.hour, date.minute, date.second, 0);
419 const std::string file_path =
420 fmt::format("{}/{:016x}_{}.png", screenshot_path, title_id, formatted_date);
421
422 const Common::FS::IOFile db_file{file_path, Common::FS::FileAccessMode::Write,
423 Common::FS::FileType::BinaryFile};
424
425 s32 len;
426 const u8* png = stbi_write_png_to_mem(image.data(), 0, 1280, 720, STBI_rgb_alpha, &len);
427
428 if (!png) {
429 return ResultFileCountLimit;
430 }
431
432 std::vector<u8> png_image(len);
433 std::memcpy(png_image.data(), png, len);
434
435 if (db_file.Write(png_image) != png_image.size()) {
436 return ResultFileCountLimit;
437 }
438
439 out_entry = {
440 .size = png_image.size(),
441 .hash = {},
442 .datetime = date,
443 .storage = AlbumStorage::Sd,
444 .content = ContentType::Screenshot,
445 .unknown = 1,
446 };
447
448 return ResultSuccess;
449}
450
368AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const { 451AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const {
369 Time::TimeZone::CalendarInfo calendar_date{}; 452 Time::TimeZone::CalendarInfo calendar_date{};
370 const auto& time_zone_manager = 453 const auto& time_zone_manager =
diff --git a/src/core/hle/service/caps/caps_manager.h b/src/core/hle/service/caps/caps_manager.h
index f65eb12c1..44d85117f 100644
--- a/src/core/hle/service/caps/caps_manager.h
+++ b/src/core/hle/service/caps/caps_manager.h
@@ -58,6 +58,15 @@ public:
58 std::vector<u8>& out_image, const AlbumFileId& file_id, 58 std::vector<u8>& out_image, const AlbumFileId& file_id,
59 const ScreenShotDecodeOption& decoder_options) const; 59 const ScreenShotDecodeOption& decoder_options) const;
60 60
61 Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
62 std::span<const u8> image_data, u64 aruid);
63 Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
64 const ApplicationData& app_data, std::span<const u8> image_data,
65 u64 aruid);
66 Result SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
67 const ScreenShotAttribute& attribute, const AlbumFileId& file_id,
68 std::span<const u8> image_data);
69
61private: 70private:
62 static constexpr std::size_t NandAlbumFileLimit = 1000; 71 static constexpr std::size_t NandAlbumFileLimit = 1000;
63 static constexpr std::size_t SdAlbumFileLimit = 10000; 72 static constexpr std::size_t SdAlbumFileLimit = 10000;
@@ -67,6 +76,8 @@ private:
67 Result GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem::path& path) const; 76 Result GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem::path& path) const;
68 Result LoadImage(std::span<u8> out_image, const std::filesystem::path& path, int width, 77 Result LoadImage(std::span<u8> out_image, const std::filesystem::path& path, int width,
69 int height, ScreenShotDecoderFlag flag) const; 78 int height, ScreenShotDecoderFlag flag) const;
79 Result SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image, u64 title_id,
80 const AlbumFileDateTime& date) const;
70 81
71 AlbumFileDateTime ConvertToAlbumDateTime(u64 posix_time) const; 82 AlbumFileDateTime ConvertToAlbumDateTime(u64 posix_time) const;
72 83
diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp
index d0d1b5425..1ba2b7972 100644
--- a/src/core/hle/service/caps/caps_ss.cpp
+++ b/src/core/hle/service/caps/caps_ss.cpp
@@ -1,19 +1,25 @@
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 "common/logging/log.h"
5#include "core/hle/service/caps/caps_manager.h"
6#include "core/hle/service/caps/caps_types.h"
7#include "core/hle/service/ipc_helpers.h"
8
4#include "core/hle/service/caps/caps_ss.h" 9#include "core/hle/service/caps/caps_ss.h"
5 10
6namespace Service::Capture { 11namespace Service::Capture {
7 12
8IScreenShotService::IScreenShotService(Core::System& system_) 13IScreenShotService::IScreenShotService(Core::System& system_,
9 : ServiceFramework{system_, "caps:ss"} { 14 std::shared_ptr<AlbumManager> album_manager)
15 : ServiceFramework{system_, "caps:ss"}, manager{album_manager} {
10 // clang-format off 16 // clang-format off
11 static const FunctionInfo functions[] = { 17 static const FunctionInfo functions[] = {
12 {201, nullptr, "SaveScreenShot"}, 18 {201, nullptr, "SaveScreenShot"},
13 {202, nullptr, "SaveEditedScreenShot"}, 19 {202, nullptr, "SaveEditedScreenShot"},
14 {203, nullptr, "SaveScreenShotEx0"}, 20 {203, &IScreenShotService::SaveScreenShotEx0, "SaveScreenShotEx0"},
15 {204, nullptr, "SaveEditedScreenShotEx0"}, 21 {204, nullptr, "SaveEditedScreenShotEx0"},
16 {206, nullptr, "Unknown206"}, 22 {206, &IScreenShotService::SaveEditedScreenShotEx1, "SaveEditedScreenShotEx1"},
17 {208, nullptr, "SaveScreenShotOfMovieEx1"}, 23 {208, nullptr, "SaveScreenShotOfMovieEx1"},
18 {1000, nullptr, "Unknown1000"}, 24 {1000, nullptr, "Unknown1000"},
19 }; 25 };
@@ -24,4 +30,65 @@ IScreenShotService::IScreenShotService(Core::System& system_)
24 30
25IScreenShotService::~IScreenShotService() = default; 31IScreenShotService::~IScreenShotService() = default;
26 32
33void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) {
34 IPC::RequestParser rp{ctx};
35 struct Parameters {
36 ScreenShotAttribute attribute{};
37 u32 report_option{};
38 INSERT_PADDING_BYTES(0x4);
39 u64 applet_resource_user_id{};
40 };
41 static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
42
43 const auto parameters{rp.PopRaw<Parameters>()};
44 const auto image_data_buffer = ctx.ReadBuffer();
45
46 LOG_INFO(Service_Capture,
47 "called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
48 parameters.report_option, image_data_buffer.size(),
49 parameters.applet_resource_user_id);
50
51 ApplicationAlbumEntry entry{};
52 const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer,
53 parameters.applet_resource_user_id);
54
55 IPC::ResponseBuilder rb{ctx, 10};
56 rb.Push(result);
57 rb.PushRaw(entry);
58}
59void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) {
60 IPC::RequestParser rp{ctx};
61 struct Parameters {
62 ScreenShotAttribute attribute;
63 u64 width;
64 u64 height;
65 u64 thumbnail_width;
66 u64 thumbnail_height;
67 AlbumFileId file_id;
68 };
69 static_assert(sizeof(Parameters) == 0x78, "Parameters has incorrect size.");
70
71 const auto parameters{rp.PopRaw<Parameters>()};
72 const auto application_data_buffer = ctx.ReadBuffer(0);
73 const auto image_data_buffer = ctx.ReadBuffer(1);
74 const auto thumbnail_image_data_buffer = ctx.ReadBuffer(2);
75
76 LOG_INFO(Service_Capture,
77 "called, width={}, height={}, thumbnail_width={}, thumbnail_height={}, "
78 "application_id={:016x}, storage={}, type={}, app_data_buffer_size={}, "
79 "image_data_buffer_size={}, thumbnail_image_buffer_size={}",
80 parameters.width, parameters.height, parameters.thumbnail_width,
81 parameters.thumbnail_height, parameters.file_id.application_id,
82 parameters.file_id.storage, parameters.file_id.type, application_data_buffer.size(),
83 image_data_buffer.size(), thumbnail_image_data_buffer.size());
84
85 ApplicationAlbumEntry entry{};
86 const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute,
87 parameters.file_id, image_data_buffer);
88
89 IPC::ResponseBuilder rb{ctx, 10};
90 rb.Push(result);
91 rb.PushRaw(entry);
92}
93
27} // namespace Service::Capture 94} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_ss.h b/src/core/hle/service/caps/caps_ss.h
index 381e44fd4..a7e9972ab 100644
--- a/src/core/hle/service/caps/caps_ss.h
+++ b/src/core/hle/service/caps/caps_ss.h
@@ -13,8 +13,14 @@ namespace Service::Capture {
13 13
14class IScreenShotService final : public ServiceFramework<IScreenShotService> { 14class IScreenShotService final : public ServiceFramework<IScreenShotService> {
15public: 15public:
16 explicit IScreenShotService(Core::System& system_); 16 explicit IScreenShotService(Core::System& system_, std::shared_ptr<AlbumManager> album_manager);
17 ~IScreenShotService() override; 17 ~IScreenShotService() override;
18
19private:
20 void SaveScreenShotEx0(HLERequestContext& ctx);
21 void SaveEditedScreenShotEx1(HLERequestContext& ctx);
22
23 std::shared_ptr<AlbumManager> manager;
18}; 24};
19 25
20} // namespace Service::Capture 26} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp
index cad173dc7..e85625ee4 100644
--- a/src/core/hle/service/caps/caps_su.cpp
+++ b/src/core/hle/service/caps/caps_su.cpp
@@ -2,19 +2,22 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/logging/log.h" 4#include "common/logging/log.h"
5#include "core/hle/service/caps/caps_manager.h"
5#include "core/hle/service/caps/caps_su.h" 6#include "core/hle/service/caps/caps_su.h"
7#include "core/hle/service/caps/caps_types.h"
6#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
7 9
8namespace Service::Capture { 10namespace Service::Capture {
9 11
10IScreenShotApplicationService::IScreenShotApplicationService(Core::System& system_) 12IScreenShotApplicationService::IScreenShotApplicationService(
11 : ServiceFramework{system_, "caps:su"} { 13 Core::System& system_, std::shared_ptr<AlbumManager> album_manager)
14 : ServiceFramework{system_, "caps:su"}, manager{album_manager} {
12 // clang-format off 15 // clang-format off
13 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
14 {32, &IScreenShotApplicationService::SetShimLibraryVersion, "SetShimLibraryVersion"}, 17 {32, &IScreenShotApplicationService::SetShimLibraryVersion, "SetShimLibraryVersion"},
15 {201, nullptr, "SaveScreenShot"}, 18 {201, nullptr, "SaveScreenShot"},
16 {203, nullptr, "SaveScreenShotEx0"}, 19 {203, &IScreenShotApplicationService::SaveScreenShotEx0, "SaveScreenShotEx0"},
17 {205, nullptr, "SaveScreenShotEx1"}, 20 {205, &IScreenShotApplicationService::SaveScreenShotEx1, "SaveScreenShotEx1"},
18 {210, nullptr, "SaveScreenShotEx2"}, 21 {210, nullptr, "SaveScreenShotEx2"},
19 }; 22 };
20 // clang-format on 23 // clang-format on
@@ -36,4 +39,62 @@ void IScreenShotApplicationService::SetShimLibraryVersion(HLERequestContext& ctx
36 rb.Push(ResultSuccess); 39 rb.Push(ResultSuccess);
37} 40}
38 41
42void IScreenShotApplicationService::SaveScreenShotEx0(HLERequestContext& ctx) {
43 IPC::RequestParser rp{ctx};
44 struct Parameters {
45 ScreenShotAttribute attribute{};
46 AlbumReportOption report_option{};
47 INSERT_PADDING_BYTES(0x4);
48 u64 applet_resource_user_id{};
49 };
50 static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
51
52 const auto parameters{rp.PopRaw<Parameters>()};
53 const auto image_data_buffer = ctx.ReadBuffer();
54
55 LOG_INFO(Service_Capture,
56 "called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
57 parameters.report_option, image_data_buffer.size(),
58 parameters.applet_resource_user_id);
59
60 ApplicationAlbumEntry entry{};
61 const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer,
62 parameters.applet_resource_user_id);
63
64 IPC::ResponseBuilder rb{ctx, 10};
65 rb.Push(result);
66 rb.PushRaw(entry);
67}
68
69void IScreenShotApplicationService::SaveScreenShotEx1(HLERequestContext& ctx) {
70 IPC::RequestParser rp{ctx};
71 struct Parameters {
72 ScreenShotAttribute attribute{};
73 AlbumReportOption report_option{};
74 INSERT_PADDING_BYTES(0x4);
75 u64 applet_resource_user_id{};
76 };
77 static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
78
79 const auto parameters{rp.PopRaw<Parameters>()};
80 const auto app_data_buffer = ctx.ReadBuffer(0);
81 const auto image_data_buffer = ctx.ReadBuffer(1);
82
83 LOG_INFO(Service_Capture,
84 "called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
85 parameters.report_option, image_data_buffer.size(),
86 parameters.applet_resource_user_id);
87
88 ApplicationAlbumEntry entry{};
89 ApplicationData app_data{};
90 std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData));
91 const auto result =
92 manager->SaveScreenShot(entry, parameters.attribute, app_data, image_data_buffer,
93 parameters.applet_resource_user_id);
94
95 IPC::ResponseBuilder rb{ctx, 10};
96 rb.Push(result);
97 rb.PushRaw(entry);
98}
99
39} // namespace Service::Capture 100} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h
index 647e3059d..89e71f506 100644
--- a/src/core/hle/service/caps/caps_su.h
+++ b/src/core/hle/service/caps/caps_su.h
@@ -10,14 +10,20 @@ class System;
10} 10}
11 11
12namespace Service::Capture { 12namespace Service::Capture {
13class AlbumManager;
13 14
14class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> { 15class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> {
15public: 16public:
16 explicit IScreenShotApplicationService(Core::System& system_); 17 explicit IScreenShotApplicationService(Core::System& system_,
18 std::shared_ptr<AlbumManager> album_manager);
17 ~IScreenShotApplicationService() override; 19 ~IScreenShotApplicationService() override;
18 20
19private: 21private:
20 void SetShimLibraryVersion(HLERequestContext& ctx); 22 void SetShimLibraryVersion(HLERequestContext& ctx);
23 void SaveScreenShotEx0(HLERequestContext& ctx);
24 void SaveScreenShotEx1(HLERequestContext& ctx);
25
26 std::shared_ptr<AlbumManager> manager;
21}; 27};
22 28
23} // namespace Service::Capture 29} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_types.h b/src/core/hle/service/caps/caps_types.h
index 7fd357954..589ac28d3 100644
--- a/src/core/hle/service/caps/caps_types.h
+++ b/src/core/hle/service/caps/caps_types.h
@@ -20,6 +20,8 @@ enum class AlbumImageOrientation {
20enum class AlbumReportOption : s32 { 20enum class AlbumReportOption : s32 {
21 Disable, 21 Disable,
22 Enable, 22 Enable,
23 Unknown2,
24 Unknown3,
23}; 25};
24 26
25enum class ContentType : u8 { 27enum class ContentType : u8 {