diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/caps/caps.cpp | 7 | ||||
| -rw-r--r-- | src/core/hle/service/caps/caps_manager.cpp | 83 | ||||
| -rw-r--r-- | src/core/hle/service/caps/caps_manager.h | 11 | ||||
| -rw-r--r-- | src/core/hle/service/caps/caps_ss.cpp | 75 | ||||
| -rw-r--r-- | src/core/hle/service/caps/caps_ss.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/caps/caps_su.cpp | 69 | ||||
| -rw-r--r-- | src/core/hle/service/caps/caps_su.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/caps/caps_types.h | 2 | 
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) {      server_manager->RegisterNamedService(          "caps:u", std::make_shared<IAlbumApplicationService>(system, album_manager)); -    server_manager->RegisterNamedService("caps:ss", std::make_shared<IScreenShotService>(system)); +    server_manager->RegisterNamedService( +        "caps:ss", std::make_shared<IScreenShotService>(system, album_manager));      server_manager->RegisterNamedService("caps:sc",                                           std::make_shared<IScreenShotControlService>(system)); -    server_manager->RegisterNamedService("caps:su", -                                         std::make_shared<IScreenShotApplicationService>(system)); +    server_manager->RegisterNamedService( +        "caps:su", std::make_shared<IScreenShotApplicationService>(system, album_manager));      ServerManager::RunServer(std::move(server_manager));  } 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 @@  #include <sstream>  #include <stb_image.h>  #include <stb_image_resize.h> +#include <stb_image_write.h>  #include "common/fs/file.h"  #include "common/fs/path_util.h" @@ -227,6 +228,49 @@ Result AlbumManager::LoadAlbumScreenShotThumbnail(                       +static_cast<int>(out_image_output.height), decoder_options.flags);  } +Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, +                                    const ScreenShotAttribute& attribute, +                                    std::span<const u8> image_data, u64 aruid) { +    return SaveScreenShot(out_entry, attribute, {}, image_data, aruid); +} + +Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, +                                    const ScreenShotAttribute& attribute, +                                    const ApplicationData& app_data, std::span<const u8> image_data, +                                    u64 aruid) { +    const u64 title_id = system.GetApplicationProcessProgramID(); +    const auto& user_clock = system.GetTimeManager().GetStandardUserSystemClockCore(); + +    s64 posix_time{}; +    Result result = user_clock.GetCurrentTime(system, posix_time); + +    if (result.IsError()) { +        return result; +    } + +    const auto date = ConvertToAlbumDateTime(posix_time); + +    return SaveImage(out_entry, image_data, title_id, date); +} + +Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry, +                                          const ScreenShotAttribute& attribute, +                                          const AlbumFileId& file_id, +                                          std::span<const u8> image_data) { +    const auto& user_clock = system.GetTimeManager().GetStandardUserSystemClockCore(); + +    s64 posix_time{}; +    Result result = user_clock.GetCurrentTime(system, posix_time); + +    if (result.IsError()) { +        return result; +    } + +    const auto date = ConvertToAlbumDateTime(posix_time); + +    return SaveImage(out_entry, image_data, file_id.application_id, date); +} +  Result AlbumManager::GetFile(std::filesystem::path& out_path, const AlbumFileId& file_id) const {      const auto file = album_files.find(file_id); @@ -365,6 +409,45 @@ Result AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::p      return ResultSuccess;  } +Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image, +                               u64 title_id, const AlbumFileDateTime& date) const { +    const auto screenshot_path = +        Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ScreenshotsDir); +    const std::string formatted_date = +        fmt::format("{:04}-{:02}-{:02}_{:02}-{:02}-{:02}-{:03}", date.year, date.month, date.day, +                    date.hour, date.minute, date.second, 0); +    const std::string file_path = +        fmt::format("{}/{:016x}_{}.png", screenshot_path, title_id, formatted_date); + +    const Common::FS::IOFile db_file{file_path, Common::FS::FileAccessMode::Write, +                                     Common::FS::FileType::BinaryFile}; + +    s32 len; +    const u8* png = stbi_write_png_to_mem(image.data(), 0, 1280, 720, STBI_rgb_alpha, &len); + +    if (!png) { +        return ResultFileCountLimit; +    } + +    std::vector<u8> png_image(len); +    std::memcpy(png_image.data(), png, len); + +    if (db_file.Write(png_image) != png_image.size()) { +        return ResultFileCountLimit; +    } + +    out_entry = { +        .size = png_image.size(), +        .hash = {}, +        .datetime = date, +        .storage = AlbumStorage::Sd, +        .content = ContentType::Screenshot, +        .unknown = 1, +    }; + +    return ResultSuccess; +} +  AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const {      Time::TimeZone::CalendarInfo calendar_date{};      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:                                          std::vector<u8>& out_image, const AlbumFileId& file_id,                                          const ScreenShotDecodeOption& decoder_options) const; +    Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute, +                          std::span<const u8> image_data, u64 aruid); +    Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute, +                          const ApplicationData& app_data, std::span<const u8> image_data, +                          u64 aruid); +    Result SaveEditedScreenShot(ApplicationAlbumEntry& out_entry, +                                const ScreenShotAttribute& attribute, const AlbumFileId& file_id, +                                std::span<const u8> image_data); +  private:      static constexpr std::size_t NandAlbumFileLimit = 1000;      static constexpr std::size_t SdAlbumFileLimit = 10000; @@ -67,6 +76,8 @@ private:      Result GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem::path& path) const;      Result LoadImage(std::span<u8> out_image, const std::filesystem::path& path, int width,                       int height, ScreenShotDecoderFlag flag) const; +    Result SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image, u64 title_id, +                     const AlbumFileDateTime& date) const;      AlbumFileDateTime ConvertToAlbumDateTime(u64 posix_time) const; 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 @@  // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/logging/log.h" +#include "core/hle/service/caps/caps_manager.h" +#include "core/hle/service/caps/caps_types.h" +#include "core/hle/service/ipc_helpers.h" +  #include "core/hle/service/caps/caps_ss.h"  namespace Service::Capture { -IScreenShotService::IScreenShotService(Core::System& system_) -    : ServiceFramework{system_, "caps:ss"} { +IScreenShotService::IScreenShotService(Core::System& system_, +                                       std::shared_ptr<AlbumManager> album_manager) +    : ServiceFramework{system_, "caps:ss"}, manager{album_manager} {      // clang-format off      static const FunctionInfo functions[] = {          {201, nullptr, "SaveScreenShot"},          {202, nullptr, "SaveEditedScreenShot"}, -        {203, nullptr, "SaveScreenShotEx0"}, +        {203, &IScreenShotService::SaveScreenShotEx0, "SaveScreenShotEx0"},          {204, nullptr, "SaveEditedScreenShotEx0"}, -        {206, nullptr, "Unknown206"}, +        {206, &IScreenShotService::SaveEditedScreenShotEx1, "SaveEditedScreenShotEx1"},          {208, nullptr, "SaveScreenShotOfMovieEx1"},          {1000, nullptr, "Unknown1000"},      }; @@ -24,4 +30,65 @@ IScreenShotService::IScreenShotService(Core::System& system_)  IScreenShotService::~IScreenShotService() = default; +void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    struct Parameters { +        ScreenShotAttribute attribute{}; +        u32 report_option{}; +        INSERT_PADDING_BYTES(0x4); +        u64 applet_resource_user_id{}; +    }; +    static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size."); + +    const auto parameters{rp.PopRaw<Parameters>()}; +    const auto image_data_buffer = ctx.ReadBuffer(); + +    LOG_INFO(Service_Capture, +             "called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}", +             parameters.report_option, image_data_buffer.size(), +             parameters.applet_resource_user_id); + +    ApplicationAlbumEntry entry{}; +    const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer, +                                                parameters.applet_resource_user_id); + +    IPC::ResponseBuilder rb{ctx, 10}; +    rb.Push(result); +    rb.PushRaw(entry); +} +void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    struct Parameters { +        ScreenShotAttribute attribute; +        u64 width; +        u64 height; +        u64 thumbnail_width; +        u64 thumbnail_height; +        AlbumFileId file_id; +    }; +    static_assert(sizeof(Parameters) == 0x78, "Parameters has incorrect size."); + +    const auto parameters{rp.PopRaw<Parameters>()}; +    const auto application_data_buffer = ctx.ReadBuffer(0); +    const auto image_data_buffer = ctx.ReadBuffer(1); +    const auto thumbnail_image_data_buffer = ctx.ReadBuffer(2); + +    LOG_INFO(Service_Capture, +             "called, width={}, height={}, thumbnail_width={}, thumbnail_height={}, " +             "application_id={:016x},  storage={},  type={}, app_data_buffer_size={}, " +             "image_data_buffer_size={}, thumbnail_image_buffer_size={}", +             parameters.width, parameters.height, parameters.thumbnail_width, +             parameters.thumbnail_height, parameters.file_id.application_id, +             parameters.file_id.storage, parameters.file_id.type, application_data_buffer.size(), +             image_data_buffer.size(), thumbnail_image_data_buffer.size()); + +    ApplicationAlbumEntry entry{}; +    const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute, +                                                      parameters.file_id, image_data_buffer); + +    IPC::ResponseBuilder rb{ctx, 10}; +    rb.Push(result); +    rb.PushRaw(entry); +} +  } // 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 {  class IScreenShotService final : public ServiceFramework<IScreenShotService> {  public: -    explicit IScreenShotService(Core::System& system_); +    explicit IScreenShotService(Core::System& system_, std::shared_ptr<AlbumManager> album_manager);      ~IScreenShotService() override; + +private: +    void SaveScreenShotEx0(HLERequestContext& ctx); +    void SaveEditedScreenShotEx1(HLERequestContext& ctx); + +    std::shared_ptr<AlbumManager> manager;  };  } // 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 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "common/logging/log.h" +#include "core/hle/service/caps/caps_manager.h"  #include "core/hle/service/caps/caps_su.h" +#include "core/hle/service/caps/caps_types.h"  #include "core/hle/service/ipc_helpers.h"  namespace Service::Capture { -IScreenShotApplicationService::IScreenShotApplicationService(Core::System& system_) -    : ServiceFramework{system_, "caps:su"} { +IScreenShotApplicationService::IScreenShotApplicationService( +    Core::System& system_, std::shared_ptr<AlbumManager> album_manager) +    : ServiceFramework{system_, "caps:su"}, manager{album_manager} {      // clang-format off      static const FunctionInfo functions[] = {          {32, &IScreenShotApplicationService::SetShimLibraryVersion, "SetShimLibraryVersion"},          {201, nullptr, "SaveScreenShot"}, -        {203, nullptr, "SaveScreenShotEx0"}, -        {205, nullptr, "SaveScreenShotEx1"}, +        {203, &IScreenShotApplicationService::SaveScreenShotEx0, "SaveScreenShotEx0"}, +        {205, &IScreenShotApplicationService::SaveScreenShotEx1, "SaveScreenShotEx1"},          {210, nullptr, "SaveScreenShotEx2"},      };      // clang-format on @@ -36,4 +39,62 @@ void IScreenShotApplicationService::SetShimLibraryVersion(HLERequestContext& ctx      rb.Push(ResultSuccess);  } +void IScreenShotApplicationService::SaveScreenShotEx0(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    struct Parameters { +        ScreenShotAttribute attribute{}; +        AlbumReportOption report_option{}; +        INSERT_PADDING_BYTES(0x4); +        u64 applet_resource_user_id{}; +    }; +    static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size."); + +    const auto parameters{rp.PopRaw<Parameters>()}; +    const auto image_data_buffer = ctx.ReadBuffer(); + +    LOG_INFO(Service_Capture, +             "called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}", +             parameters.report_option, image_data_buffer.size(), +             parameters.applet_resource_user_id); + +    ApplicationAlbumEntry entry{}; +    const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer, +                                                parameters.applet_resource_user_id); + +    IPC::ResponseBuilder rb{ctx, 10}; +    rb.Push(result); +    rb.PushRaw(entry); +} + +void IScreenShotApplicationService::SaveScreenShotEx1(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    struct Parameters { +        ScreenShotAttribute attribute{}; +        AlbumReportOption report_option{}; +        INSERT_PADDING_BYTES(0x4); +        u64 applet_resource_user_id{}; +    }; +    static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size."); + +    const auto parameters{rp.PopRaw<Parameters>()}; +    const auto app_data_buffer = ctx.ReadBuffer(0); +    const auto image_data_buffer = ctx.ReadBuffer(1); + +    LOG_INFO(Service_Capture, +             "called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}", +             parameters.report_option, image_data_buffer.size(), +             parameters.applet_resource_user_id); + +    ApplicationAlbumEntry entry{}; +    ApplicationData app_data{}; +    std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData)); +    const auto result = +        manager->SaveScreenShot(entry, parameters.attribute, app_data, image_data_buffer, +                                parameters.applet_resource_user_id); + +    IPC::ResponseBuilder rb{ctx, 10}; +    rb.Push(result); +    rb.PushRaw(entry); +} +  } // 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;  }  namespace Service::Capture { +class AlbumManager;  class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> {  public: -    explicit IScreenShotApplicationService(Core::System& system_); +    explicit IScreenShotApplicationService(Core::System& system_, +                                           std::shared_ptr<AlbumManager> album_manager);      ~IScreenShotApplicationService() override;  private:      void SetShimLibraryVersion(HLERequestContext& ctx); +    void SaveScreenShotEx0(HLERequestContext& ctx); +    void SaveScreenShotEx1(HLERequestContext& ctx); + +    std::shared_ptr<AlbumManager> manager;  };  } // 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 {  enum class AlbumReportOption : s32 {      Disable,      Enable, +    Unknown2, +    Unknown3,  };  enum class ContentType : u8 {  | 
