diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/caps/caps_a.cpp | 311 |
1 files changed, 97 insertions, 214 deletions
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index e1f836e08..e22f72bf6 100644 --- a/src/core/hle/service/caps/caps_a.cpp +++ b/src/core/hle/service/caps/caps_a.cpp @@ -1,40 +1,18 @@ // 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 "common/logging/log.h" #include "core/hle/service/caps/caps_a.h" +#include "core/hle/service/caps/caps_manager.h" +#include "core/hle/service/caps/caps_result.h" +#include "core/hle/service/caps/caps_types.h" #include "core/hle/service/ipc_helpers.h" namespace Service::Capture { -class IAlbumAccessorSession final : public ServiceFramework<IAlbumAccessorSession> { -public: - explicit IAlbumAccessorSession(Core::System& system_) - : ServiceFramework{system_, "IAlbumAccessorSession"} { - // clang-format off - static const FunctionInfo functions[] = { - {2001, nullptr, "OpenAlbumMovieReadStream"}, - {2002, nullptr, "CloseAlbumMovieReadStream"}, - {2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"}, - {2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"}, - {2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"}, - {2006, nullptr, "GetAlbumMovieReadStreamImageDataSize"}, - {2007, nullptr, "ReadImageDataFromAlbumMovieReadStream"}, - {2008, nullptr, "ReadFileAttributeFromAlbumMovieReadStream"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -IAlbumAccessorService::IAlbumAccessorService(Core::System& system_) - : ServiceFramework{system_, "caps:a"} { +IAlbumAccessorService::IAlbumAccessorService(Core::System& system_, + std::shared_ptr<AlbumManager> album_manager) + : ServiceFramework{system_, "caps:a"}, manager{album_manager} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetAlbumFileCount"}, @@ -91,30 +69,25 @@ void IAlbumAccessorService::DeleteAlbumFile(HLERequestContext& ctx) { 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; - } - } + Result result = manager->DeleteAlbumFile(file_id); + result = TranslateResult(result); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } 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); + LOG_INFO(Service_Capture, "called, storage={}", storage); - if (storage == AlbumStorage::Sd) { - FindScreenshots(); - } + Result result = manager->IsAlbumMounted(storage); + const bool is_mounted = result.IsSuccess(); + result = TranslateResult(result); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); + rb.Push(result); rb.Push<u8>(is_mounted); } @@ -141,38 +114,34 @@ void IAlbumAccessorService::GetAlbumFileListEx0(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto storage{rp.PopEnum<AlbumStorage>()}; const auto flags{rp.Pop<u8>()}; + const auto album_entry_size{ctx.GetWriteBufferNumElements<AlbumEntry>()}; LOG_INFO(Service_Capture, "called, storage={}, flags={}", storage, flags); - std::vector<AlbumEntry> entries{}; + std::vector<AlbumEntry> entries; + Result result = manager->GetAlbumFileList(entries, storage, flags); + result = TranslateResult(result); - 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); - } - } + entries.resize(std::min(album_entry_size, entries.size())); if (!entries.empty()) { ctx.WriteBuffer(entries); } IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); + rb.Push(result); rb.Push(entries.size()); } void IAlbumAccessorService::GetAutoSavingStorage(HLERequestContext& ctx) { - bool is_autosaving{}; + LOG_WARNING(Service_Capture, "(STUBBED) called"); - LOG_WARNING(Service_Capture, "(STUBBED) called, is_autosaving={}", is_autosaving); + bool is_autosaving{}; + Result result = manager->GetAutoSavingStorage(is_autosaving); + result = TranslateResult(result); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); + rb.Push(result); rb.Push<u8>(is_autosaving); } @@ -180,35 +149,28 @@ void IAlbumAccessorService::LoadAlbumScreenShotImageEx1(HLERequestContext& ctx) IPC::RequestParser rp{ctx}; const auto file_id{rp.PopRaw<AlbumFileId>()}; const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()}; + const auto image_buffer_size{ctx.GetWriteBufferSize(1)}; 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); + std::vector<u8> image; + LoadAlbumScreenShotImageOutput image_output; + Result result = + manager->LoadAlbumScreenShotImage(image_output, image, file_id, decoder_options); + result = TranslateResult(result); - 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); + if (image.size() > image_buffer_size) { + result = ResultWorkMemoryError; } - ctx.WriteBuffer(image_output, 0); - ctx.WriteBuffer(image, 1); + if (result.IsSuccess()) { + ctx.WriteBuffer(image_output, 0); + ctx.WriteBuffer(image, 1); + } IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx) { @@ -219,157 +181,78 @@ void IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(HLERequestConte 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); + std::vector<u8> image(ctx.GetWriteBufferSize(1)); + LoadAlbumScreenShotImageOutput image_output; + Result result = + manager->LoadAlbumScreenShotThumbnail(image_output, image, file_id, decoder_options); + result = TranslateResult(result); - 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); + if (result.IsSuccess()) { + ctx.WriteBuffer(image_output, 0); + ctx.WriteBuffer(image, 1); } - ctx.WriteBuffer(image_output, 0); - ctx.WriteBuffer(image, 1); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } -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; +Result IAlbumAccessorService::TranslateResult(Result in_result) { + if (in_result.IsSuccess()) { + return in_result; } - 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; - } + if ((in_result.raw & 0x3801ff) == ResultUnknown1024.raw) { + if (in_result.description - 0x514 < 100) { + return ResultInvalidFileData; + } + if (in_result.description - 0x5dc < 100) { + return ResultInvalidFileData; + } - 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 (in_result.description - 0x578 < 100) { + if (in_result == ResultFileCountLimit) { + return ResultUnknown22; + } + return ResultUnknown25; + } - if (dbi_image == nullptr) { - return ResultUnknown; + if (in_result.raw < ResultUnknown1801.raw) { + if (in_result == ResultUnknown1202) { + return ResultUnknown810; + } + if (in_result == ResultUnknown1203) { + return ResultUnknown810; + } + if (in_result == ResultUnknown1701) { + return ResultUnknown5; + } + } else if (in_result.raw < ResultUnknown1803.raw) { + if (in_result == ResultUnknown1801) { + return ResultUnknown5; + } + if (in_result == ResultUnknown1802) { + return ResultUnknown6; + } + } else { + if (in_result == ResultUnknown1803) { + return ResultUnknown7; + } + if (in_result == ResultUnknown1804) { + return ResultOutOfRange; + } + } + return ResultUnknown1024; } - 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; + if (in_result.module == ErrorModule::FS) { + if ((in_result.description >> 0xc < 0x7d) || (in_result.description - 1000 < 2000) || + (((in_result.description - 3000) >> 3) < 0x271)) { + // TODO: Translate FS error + return in_result; + } } - 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; + return in_result; } } // namespace Service::Capture |