From 8347e5cdb9377eb10dfd3b17aeb45290625687a1 Mon Sep 17 00:00:00 2001
From: Narr the Reg <juangerman-13@hotmail.com>
Date: Tue, 3 Oct 2023 20:05:02 -0600
Subject: [PATCH] service: caps: Implement album manager and reorganize service

---
 src/core/CMakeLists.txt                    |   8 +-
 src/core/hle/service/am/am.cpp             |   2 +-
 src/core/hle/service/caps/caps.cpp         |  21 +-
 src/core/hle/service/caps/caps.h           |  81 -----
 src/core/hle/service/caps/caps_a.cpp       | 313 ++++++-------------
 src/core/hle/service/caps/caps_a.h         | 107 +------
 src/core/hle/service/caps/caps_c.cpp       |  50 +--
 src/core/hle/service/caps/caps_c.h         |  10 +-
 src/core/hle/service/caps/caps_manager.cpp | 342 +++++++++++++++++++++
 src/core/hle/service/caps/caps_manager.h   |  72 +++++
 src/core/hle/service/caps/caps_result.h    |  35 +++
 src/core/hle/service/caps/caps_sc.cpp      |   5 +-
 src/core/hle/service/caps/caps_sc.h        |   6 +-
 src/core/hle/service/caps/caps_ss.cpp      |   5 +-
 src/core/hle/service/caps/caps_ss.h        |   6 +-
 src/core/hle/service/caps/caps_su.cpp      |   9 +-
 src/core/hle/service/caps/caps_su.h        |   6 +-
 src/core/hle/service/caps/caps_types.h     | 184 +++++++++++
 src/core/hle/service/caps/caps_u.cpp       | 104 ++++---
 src/core/hle/service/caps/caps_u.h         |  12 +-
 20 files changed, 856 insertions(+), 522 deletions(-)
 create mode 100644 src/core/hle/service/caps/caps_manager.cpp
 create mode 100644 src/core/hle/service/caps/caps_manager.h
 create mode 100644 src/core/hle/service/caps/caps_result.h
 create mode 100644 src/core/hle/service/caps/caps_types.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index e02ededfcb..e4f499135a 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -466,14 +466,18 @@ add_library(core STATIC
     hle/service/caps/caps_a.h
     hle/service/caps/caps_c.cpp
     hle/service/caps/caps_c.h
-    hle/service/caps/caps_u.cpp
-    hle/service/caps/caps_u.h
+    hle/service/caps/caps_manager.cpp
+    hle/service/caps/caps_manager.h
+    hle/service/caps/caps_result.h
     hle/service/caps/caps_sc.cpp
     hle/service/caps/caps_sc.h
     hle/service/caps/caps_ss.cpp
     hle/service/caps/caps_ss.h
     hle/service/caps/caps_su.cpp
     hle/service/caps/caps_su.h
+    hle/service/caps/caps_types.h
+    hle/service/caps/caps_u.cpp
+    hle/service/caps/caps_u.h
     hle/service/erpt/erpt.cpp
     hle/service/erpt/erpt.h
     hle/service/es/es.cpp
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 3bb080883e..ac376b55a6 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -31,7 +31,7 @@
 #include "core/hle/service/apm/apm_controller.h"
 #include "core/hle/service/apm/apm_interface.h"
 #include "core/hle/service/bcat/backend/backend.h"
-#include "core/hle/service/caps/caps.h"
+#include "core/hle/service/caps/caps_types.h"
 #include "core/hle/service/filesystem/filesystem.h"
 #include "core/hle/service/ipc_helpers.h"
 #include "core/hle/service/ns/ns.h"
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp
index 0dbf048627..286f9fd107 100644
--- a/src/core/hle/service/caps/caps.cpp
+++ b/src/core/hle/service/caps/caps.cpp
@@ -4,6 +4,7 @@
 #include "core/hle/service/caps/caps.h"
 #include "core/hle/service/caps/caps_a.h"
 #include "core/hle/service/caps/caps_c.h"
+#include "core/hle/service/caps/caps_manager.h"
 #include "core/hle/service/caps/caps_sc.h"
 #include "core/hle/service/caps/caps_ss.h"
 #include "core/hle/service/caps/caps_su.h"
@@ -15,13 +16,21 @@ namespace Service::Capture {
 
 void LoopProcess(Core::System& system) {
     auto server_manager = std::make_unique<ServerManager>(system);
+    auto album_manager = std::make_shared<AlbumManager>();
+
+    server_manager->RegisterNamedService(
+        "caps:a", std::make_shared<IAlbumAccessorService>(system, album_manager));
+    server_manager->RegisterNamedService(
+        "caps:c", std::make_shared<IAlbumControlService>(system, album_manager));
+    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:sc",
+                                         std::make_shared<IScreenShotControlService>(system));
+    server_manager->RegisterNamedService("caps:su",
+                                         std::make_shared<IScreenShotApplicationService>(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));
-    server_manager->RegisterNamedService("caps:ss", std::make_shared<CAPS_SS>(system));
-    server_manager->RegisterNamedService("caps:su", std::make_shared<CAPS_SU>(system));
     ServerManager::RunServer(std::move(server_manager));
 }
 
diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h
index 15f0ecfaad..58e9725b85 100644
--- a/src/core/hle/service/caps/caps.h
+++ b/src/core/hle/service/caps/caps.h
@@ -3,93 +3,12 @@
 
 #pragma once
 
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-
 namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::Capture {
 
-enum class AlbumImageOrientation {
-    Orientation0 = 0,
-    Orientation1 = 1,
-    Orientation2 = 2,
-    Orientation3 = 3,
-};
-
-enum class AlbumReportOption : s32 {
-    Disable = 0,
-    Enable = 1,
-};
-
-enum class ContentType : u8 {
-    Screenshot = 0,
-    Movie = 1,
-    ExtraMovie = 3,
-};
-
-enum class AlbumStorage : u8 {
-    NAND = 0,
-    SD = 1,
-};
-
-struct AlbumFileDateTime {
-    s16 year{};
-    s8 month{};
-    s8 day{};
-    s8 hour{};
-    s8 minute{};
-    s8 second{};
-    s8 uid{};
-};
-static_assert(sizeof(AlbumFileDateTime) == 0x8, "AlbumFileDateTime has incorrect size.");
-
-struct AlbumEntry {
-    u64 size{};
-    u64 application_id{};
-    AlbumFileDateTime datetime{};
-    AlbumStorage storage{};
-    ContentType content{};
-    INSERT_PADDING_BYTES(6);
-};
-static_assert(sizeof(AlbumEntry) == 0x20, "AlbumEntry has incorrect size.");
-
-struct AlbumFileEntry {
-    u64 size{}; // Size of the entry
-    u64 hash{}; // AES256 with hardcoded key over AlbumEntry
-    AlbumFileDateTime datetime{};
-    AlbumStorage storage{};
-    ContentType content{};
-    INSERT_PADDING_BYTES(5);
-    u8 unknown{1}; // Set to 1 on official SW
-};
-static_assert(sizeof(AlbumFileEntry) == 0x20, "AlbumFileEntry has incorrect size.");
-
-struct ApplicationAlbumEntry {
-    u64 size{}; // Size of the entry
-    u64 hash{}; // AES256 with hardcoded key over AlbumEntry
-    AlbumFileDateTime datetime{};
-    AlbumStorage storage{};
-    ContentType content{};
-    INSERT_PADDING_BYTES(5);
-    u8 unknown{1}; // Set to 1 on official SW
-};
-static_assert(sizeof(ApplicationAlbumEntry) == 0x20, "ApplicationAlbumEntry has incorrect size.");
-
-struct ApplicationAlbumFileEntry {
-    ApplicationAlbumEntry entry{};
-    AlbumFileDateTime datetime{};
-    u64 unknown{};
-};
-static_assert(sizeof(ApplicationAlbumFileEntry) == 0x30,
-              "ApplicationAlbumFileEntry has incorrect size.");
-
 void LoopProcess(Core::System& system);
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp
index e1f836e083..e22f72bf63 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;
+    LoadAlbumScreenShotImageOutput image_output;
+    Result result =
+        manager->LoadAlbumScreenShotImage(image_output, image, file_id, decoder_options);
+    result = TranslateResult(result);
 
-    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);
+    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(ctx.GetWriteBufferSize(1));
+    LoadAlbumScreenShotImageOutput image_output;
+    Result result =
+        manager->LoadAlbumScreenShotThumbnail(image_output, image, file_id, decoder_options);
+    result = TranslateResult(result);
 
-    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);
+    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();
+Result IAlbumAccessorService::TranslateResult(Result in_result) {
+    if (in_result.IsSuccess()) {
+        return in_result;
+    }
 
-    // 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 ((in_result.raw & 0x3801ff) == ResultUnknown1024.raw) {
+        if (in_result.description - 0x514 < 100) {
+            return ResultInvalidFileData;
+        }
+        if (in_result.description - 0x5dc < 100) {
+            return ResultInvalidFileData;
+        }
+
+        if (in_result.description - 0x578 < 100) {
+            if (in_result == ResultFileCountLimit) {
+                return ResultUnknown22;
             }
-            if (GetAlbumEntry(entry, full_path).IsSuccess()) {
-                sd_image_paths.push_back(full_path);
+            return ResultUnknown25;
+        }
+
+        if (in_result.raw < ResultUnknown1801.raw) {
+            if (in_result == ResultUnknown1202) {
+                return ResultUnknown810;
             }
-            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;
+            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;
     }
 
-    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;
+    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;
+        }
     }
 
-    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;
+    return in_result;
 }
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h
index 975c0ebdb6..c90cff71e5 100644
--- a/src/core/hle/service/caps/caps_a.h
+++ b/src/core/hle/service/caps/caps_a.h
@@ -3,7 +3,6 @@
 
 #pragma once
 
-#include "common/fs/fs.h"
 #include "core/hle/service/service.h"
 
 namespace Core {
@@ -11,106 +10,15 @@ class System;
 }
 
 namespace Service::Capture {
+class AlbumManager;
 
 class IAlbumAccessorService final : public ServiceFramework<IAlbumAccessorService> {
 public:
-    explicit IAlbumAccessorService(Core::System& system_);
+    explicit IAlbumAccessorService(Core::System& system_,
+                                   std::shared_ptr<AlbumManager> album_manager);
     ~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);
@@ -119,14 +27,9 @@ private:
     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);
+    Result TranslateResult(Result in_result);
 
-    bool is_mounted{};
-    std::vector<std::filesystem::path> sd_image_paths{};
+    std::shared_ptr<AlbumManager> manager = nullptr;
 };
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_c.cpp b/src/core/hle/service/caps/caps_c.cpp
index fc77e35cdc..1e7fe64744 100644
--- a/src/core/hle/service/caps/caps_c.cpp
+++ b/src/core/hle/service/caps/caps_c.cpp
@@ -3,53 +3,21 @@
 
 #include "common/logging/log.h"
 #include "core/hle/service/caps/caps_c.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 IAlbumControlSession final : public ServiceFramework<IAlbumControlSession> {
-public:
-    explicit IAlbumControlSession(Core::System& system_)
-        : ServiceFramework{system_, "IAlbumControlSession"} {
-        // 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"},
-            {2401, nullptr, "OpenAlbumMovieWriteStream"},
-            {2402, nullptr, "FinishAlbumMovieWriteStream"},
-            {2403, nullptr, "CommitAlbumMovieWriteStream"},
-            {2404, nullptr, "DiscardAlbumMovieWriteStream"},
-            {2405, nullptr, "DiscardAlbumMovieWriteStreamNoDelete"},
-            {2406, nullptr, "CommitAlbumMovieWriteStreamEx"},
-            {2411, nullptr, "StartAlbumMovieWriteStreamDataSection"},
-            {2412, nullptr, "EndAlbumMovieWriteStreamDataSection"},
-            {2413, nullptr, "StartAlbumMovieWriteStreamMetaSection"},
-            {2414, nullptr, "EndAlbumMovieWriteStreamMetaSection"},
-            {2421, nullptr, "ReadDataFromAlbumMovieWriteStream"},
-            {2422, nullptr, "WriteDataToAlbumMovieWriteStream"},
-            {2424, nullptr, "WriteMetaToAlbumMovieWriteStream"},
-            {2431, nullptr, "GetAlbumMovieWriteStreamBrokenReason"},
-            {2433, nullptr, "GetAlbumMovieWriteStreamDataSize"},
-            {2434, nullptr, "SetAlbumMovieWriteStreamDataSize"},
-        };
-        // clang-format on
-
-        RegisterHandlers(functions);
-    }
-};
-
-CAPS_C::CAPS_C(Core::System& system_) : ServiceFramework{system_, "caps:c"} {
+IAlbumControlService::IAlbumControlService(Core::System& system_,
+                                           std::shared_ptr<AlbumManager> album_manager)
+    : ServiceFramework{system_, "caps:c"}, manager{album_manager} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {1, nullptr, "CaptureRawImage"},
         {2, nullptr, "CaptureRawImageWithTimeout"},
-        {33, &CAPS_C::SetShimLibraryVersion, "SetShimLibraryVersion"},
+        {33, &IAlbumControlService::SetShimLibraryVersion, "SetShimLibraryVersion"},
         {1001, nullptr, "RequestTakingScreenShot"},
         {1002, nullptr, "RequestTakingScreenShotWithTimeout"},
         {1011, nullptr, "NotifyTakingScreenShotRefused"},
@@ -72,9 +40,9 @@ CAPS_C::CAPS_C(Core::System& system_) : ServiceFramework{system_, "caps:c"} {
     RegisterHandlers(functions);
 }
 
-CAPS_C::~CAPS_C() = default;
+IAlbumControlService::~IAlbumControlService() = default;
 
-void CAPS_C::SetShimLibraryVersion(HLERequestContext& ctx) {
+void IAlbumControlService::SetShimLibraryVersion(HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto library_version{rp.Pop<u64>()};
     const auto applet_resource_user_id{rp.Pop<u64>()};
diff --git a/src/core/hle/service/caps/caps_c.h b/src/core/hle/service/caps/caps_c.h
index 537b3a2e39..92ba242db7 100644
--- a/src/core/hle/service/caps/caps_c.h
+++ b/src/core/hle/service/caps/caps_c.h
@@ -10,14 +10,18 @@ class System;
 }
 
 namespace Service::Capture {
+class AlbumManager;
 
-class CAPS_C final : public ServiceFramework<CAPS_C> {
+class IAlbumControlService final : public ServiceFramework<IAlbumControlService> {
 public:
-    explicit CAPS_C(Core::System& system_);
-    ~CAPS_C() override;
+    explicit IAlbumControlService(Core::System& system_,
+                                  std::shared_ptr<AlbumManager> album_manager);
+    ~IAlbumControlService() override;
 
 private:
     void SetShimLibraryVersion(HLERequestContext& ctx);
+
+    std::shared_ptr<AlbumManager> manager = nullptr;
 };
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp
new file mode 100644
index 0000000000..2df6a930ad
--- /dev/null
+++ b/src/core/hle/service/caps/caps_manager.cpp
@@ -0,0 +1,342 @@
+// SPDX-FileCopyrightText: Copyright 2023 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_manager.h"
+#include "core/hle/service/caps/caps_result.h"
+
+namespace Service::Capture {
+
+AlbumManager::AlbumManager() {}
+
+AlbumManager::~AlbumManager() = default;
+
+Result AlbumManager::DeleteAlbumFile(const AlbumFileId& file_id) {
+    if (file_id.storage > AlbumStorage::Sd) {
+        return ResultInvalidStorage;
+    }
+
+    if (!is_mounted) {
+        return ResultIsNotMounted;
+    }
+
+    std::filesystem::path path;
+    const auto result = GetFile(path, file_id);
+
+    if (result.IsError()) {
+        return result;
+    }
+
+    if (!Common::FS::RemoveFile(path)) {
+        return ResultFileNotFound;
+    }
+
+    return ResultSuccess;
+}
+
+Result AlbumManager::IsAlbumMounted(AlbumStorage storage) {
+    if (storage > AlbumStorage::Sd) {
+        return ResultInvalidStorage;
+    }
+
+    is_mounted = true;
+
+    if (storage == AlbumStorage::Sd) {
+        FindScreenshots();
+    }
+
+    return is_mounted ? ResultSuccess : ResultIsNotMounted;
+}
+
+Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage,
+                                      u8 flags) const {
+    if (storage > AlbumStorage::Sd) {
+        return ResultInvalidStorage;
+    }
+
+    if (!is_mounted) {
+        return ResultIsNotMounted;
+    }
+
+    for (auto& [file_id, path] : album_files) {
+        if (file_id.storage != storage) {
+            continue;
+        }
+        if (out_entries.size() >= SdAlbumFileLimit) {
+            break;
+        }
+
+        const auto entry_size = Common::FS::GetSize(path);
+        out_entries.push_back({
+            .entry_size = entry_size,
+            .file_id = file_id,
+        });
+    }
+
+    return ResultSuccess;
+}
+
+Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
+                                      ContentType contex_type, AlbumFileDateTime start_date,
+                                      AlbumFileDateTime end_date, u64 aruid) const {
+    if (!is_mounted) {
+        return ResultIsNotMounted;
+    }
+
+    for (auto& [file_id, path] : album_files) {
+        if (file_id.type != contex_type) {
+            continue;
+        }
+
+        if (file_id.date > start_date) {
+            continue;
+        }
+
+        if (file_id.date < end_date) {
+            continue;
+        }
+
+        if (out_entries.size() >= SdAlbumFileLimit) {
+            break;
+        }
+
+        const auto entry_size = Common::FS::GetSize(path);
+        ApplicationAlbumFileEntry entry{.entry =
+                                            {
+                                                .size = entry_size,
+                                                .hash{},
+                                                .datetime = file_id.date,
+                                                .storage = file_id.storage,
+                                                .content = contex_type,
+                                                .unknown = 1,
+                                            },
+                                        .datetime = file_id.date,
+                                        .unknown = {}};
+        out_entries.push_back(entry);
+    }
+
+    return ResultSuccess;
+}
+
+Result AlbumManager::GetAutoSavingStorage(bool& out_is_autosaving) const {
+    out_is_autosaving = false;
+    return ResultSuccess;
+}
+
+Result AlbumManager::LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output,
+                                              std::vector<u8>& out_image,
+                                              const AlbumFileId& file_id,
+                                              const ScreenShotDecodeOption& decoder_options) const {
+    if (file_id.storage > AlbumStorage::Sd) {
+        return ResultInvalidStorage;
+    }
+
+    if (!is_mounted) {
+        return ResultIsNotMounted;
+    }
+
+    out_image_output = {
+        .width = 1280,
+        .height = 720,
+        .attribute =
+            {
+                .unknown_0{},
+                .orientation = AlbumImageOrientation::None,
+                .unknown_1{},
+                .unknown_2{},
+            },
+    };
+
+    std::filesystem::path path;
+    const auto result = GetFile(path, file_id);
+
+    if (result.IsError()) {
+        return result;
+    }
+
+    out_image.resize(out_image_output.height * out_image_output.width * STBI_rgb_alpha);
+
+    return LoadImage(out_image, path, static_cast<int>(out_image_output.width),
+                     +static_cast<int>(out_image_output.height), decoder_options.flags);
+}
+
+Result AlbumManager::LoadAlbumScreenShotThumbnail(
+    LoadAlbumScreenShotImageOutput& out_image_output, std::vector<u8>& out_image,
+    const AlbumFileId& file_id, const ScreenShotDecodeOption& decoder_options) const {
+    if (file_id.storage > AlbumStorage::Sd) {
+        return ResultInvalidStorage;
+    }
+
+    if (!is_mounted) {
+        return ResultIsNotMounted;
+    }
+
+    out_image_output = {
+        .width = 320,
+        .height = 180,
+        .attribute =
+            {
+                .unknown_0{},
+                .orientation = AlbumImageOrientation::None,
+                .unknown_1{},
+                .unknown_2{},
+            },
+    };
+
+    std::filesystem::path path;
+    const auto result = GetFile(path, file_id);
+
+    if (result.IsError()) {
+        return result;
+    }
+
+    out_image.resize(out_image_output.height * out_image_output.width * STBI_rgb_alpha);
+
+    return LoadImage(out_image, path, static_cast<int>(out_image_output.width),
+                     +static_cast<int>(out_image_output.height), decoder_options.flags);
+}
+
+Result AlbumManager::GetFile(std::filesystem::path& out_path, const AlbumFileId& file_id) const {
+    const auto file = album_files.find(file_id);
+
+    if (file == album_files.end()) {
+        return ResultFileNotFound;
+    }
+
+    out_path = file->second;
+    return ResultSuccess;
+}
+
+void AlbumManager::FindScreenshots() {
+    is_mounted = false;
+    album_files.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;
+            if (GetAlbumEntry(entry, full_path).IsError()) {
+                return true;
+            }
+            while (album_files.contains(entry.file_id)) {
+                if (++entry.file_id.date.unique_id == 0) {
+                    break;
+                }
+            }
+            album_files[entry.file_id] = full_path;
+            return true;
+        },
+        Common::FS::DirEntryFilter::File);
+
+    is_mounted = true;
+}
+
+Result AlbumManager::GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem::path& path) const {
+    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 AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::path& path,
+                               int width, int height, ScreenShotDecoderFlag flag) const {
+    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
diff --git a/src/core/hle/service/caps/caps_manager.h b/src/core/hle/service/caps/caps_manager.h
new file mode 100644
index 0000000000..8337c655c2
--- /dev/null
+++ b/src/core/hle/service/caps/caps_manager.h
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <unordered_map>
+
+#include "common/fs/fs.h"
+#include "core/hle/result.h"
+#include "core/hle/service/caps/caps_types.h"
+
+namespace Core {
+class System;
+}
+
+namespace std {
+// Hash used to create lists from AlbumFileId data
+template <>
+struct hash<Service::Capture::AlbumFileId> {
+    size_t operator()(const Service::Capture::AlbumFileId& pad_id) const noexcept {
+        u64 hash_value = (static_cast<u64>(pad_id.date.year) << 8);
+        hash_value ^= (static_cast<u64>(pad_id.date.month) << 7);
+        hash_value ^= (static_cast<u64>(pad_id.date.day) << 6);
+        hash_value ^= (static_cast<u64>(pad_id.date.hour) << 5);
+        hash_value ^= (static_cast<u64>(pad_id.date.minute) << 4);
+        hash_value ^= (static_cast<u64>(pad_id.date.second) << 3);
+        hash_value ^= (static_cast<u64>(pad_id.date.unique_id) << 2);
+        hash_value ^= (static_cast<u64>(pad_id.storage) << 1);
+        hash_value ^= static_cast<u64>(pad_id.type);
+        return static_cast<size_t>(hash_value);
+    }
+};
+
+} // namespace std
+
+namespace Service::Capture {
+
+class AlbumManager {
+public:
+    explicit AlbumManager();
+    ~AlbumManager();
+
+    Result DeleteAlbumFile(const AlbumFileId& file_id);
+    Result IsAlbumMounted(AlbumStorage storage);
+    Result GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage,
+                            u8 flags) const;
+    Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
+                            ContentType contex_type, AlbumFileDateTime start_date,
+                            AlbumFileDateTime end_date, u64 aruid) const;
+    Result GetAutoSavingStorage(bool& out_is_autosaving) const;
+    Result LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output,
+                                    std::vector<u8>& out_image, const AlbumFileId& file_id,
+                                    const ScreenShotDecodeOption& decoder_options) const;
+    Result LoadAlbumScreenShotThumbnail(LoadAlbumScreenShotImageOutput& out_image_output,
+                                        std::vector<u8>& out_image, const AlbumFileId& file_id,
+                                        const ScreenShotDecodeOption& decoder_options) const;
+
+private:
+    static constexpr std::size_t NandAlbumFileLimit = 1000;
+    static constexpr std::size_t SdAlbumFileLimit = 10000;
+
+    void FindScreenshots();
+    Result GetFile(std::filesystem::path& out_path, const AlbumFileId& file_id) const;
+    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;
+
+    bool is_mounted{};
+    std::unordered_map<AlbumFileId, std::filesystem::path> album_files;
+};
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_result.h b/src/core/hle/service/caps/caps_result.h
new file mode 100644
index 0000000000..c65e5fb9af
--- /dev/null
+++ b/src/core/hle/service/caps/caps_result.h
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/result.h"
+
+namespace Service::Capture {
+
+constexpr Result ResultWorkMemoryError(ErrorModule::Capture, 3);
+constexpr Result ResultUnknown5(ErrorModule::Capture, 5);
+constexpr Result ResultUnknown6(ErrorModule::Capture, 6);
+constexpr Result ResultUnknown7(ErrorModule::Capture, 7);
+constexpr Result ResultOutOfRange(ErrorModule::Capture, 8);
+constexpr Result ResulInvalidTimestamp(ErrorModule::Capture, 12);
+constexpr Result ResultInvalidStorage(ErrorModule::Capture, 13);
+constexpr Result ResultInvalidFileContents(ErrorModule::Capture, 14);
+constexpr Result ResultIsNotMounted(ErrorModule::Capture, 21);
+constexpr Result ResultUnknown22(ErrorModule::Capture, 22);
+constexpr Result ResultFileNotFound(ErrorModule::Capture, 23);
+constexpr Result ResultInvalidFileData(ErrorModule::Capture, 24);
+constexpr Result ResultUnknown25(ErrorModule::Capture, 25);
+constexpr Result ResultReadBufferShortage(ErrorModule::Capture, 30);
+constexpr Result ResultUnknown810(ErrorModule::Capture, 810);
+constexpr Result ResultUnknown1024(ErrorModule::Capture, 1024);
+constexpr Result ResultUnknown1202(ErrorModule::Capture, 1202);
+constexpr Result ResultUnknown1203(ErrorModule::Capture, 1203);
+constexpr Result ResultFileCountLimit(ErrorModule::Capture, 1401);
+constexpr Result ResultUnknown1701(ErrorModule::Capture, 1701);
+constexpr Result ResultUnknown1801(ErrorModule::Capture, 1801);
+constexpr Result ResultUnknown1802(ErrorModule::Capture, 1802);
+constexpr Result ResultUnknown1803(ErrorModule::Capture, 1803);
+constexpr Result ResultUnknown1804(ErrorModule::Capture, 1804);
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_sc.cpp b/src/core/hle/service/caps/caps_sc.cpp
index 395b13da7f..6117cb7c6c 100644
--- a/src/core/hle/service/caps/caps_sc.cpp
+++ b/src/core/hle/service/caps/caps_sc.cpp
@@ -5,7 +5,8 @@
 
 namespace Service::Capture {
 
-CAPS_SC::CAPS_SC(Core::System& system_) : ServiceFramework{system_, "caps:sc"} {
+IScreenShotControlService::IScreenShotControlService(Core::System& system_)
+    : ServiceFramework{system_, "caps:sc"} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {1, nullptr, "CaptureRawImage"},
@@ -34,6 +35,6 @@ CAPS_SC::CAPS_SC(Core::System& system_) : ServiceFramework{system_, "caps:sc"} {
     RegisterHandlers(functions);
 }
 
-CAPS_SC::~CAPS_SC() = default;
+IScreenShotControlService::~IScreenShotControlService() = default;
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_sc.h b/src/core/hle/service/caps/caps_sc.h
index e5600f6d78..d555f49792 100644
--- a/src/core/hle/service/caps/caps_sc.h
+++ b/src/core/hle/service/caps/caps_sc.h
@@ -11,10 +11,10 @@ class System;
 
 namespace Service::Capture {
 
-class CAPS_SC final : public ServiceFramework<CAPS_SC> {
+class IScreenShotControlService final : public ServiceFramework<IScreenShotControlService> {
 public:
-    explicit CAPS_SC(Core::System& system_);
-    ~CAPS_SC() override;
+    explicit IScreenShotControlService(Core::System& system_);
+    ~IScreenShotControlService() override;
 };
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp
index 62b9edd413..d0d1b5425b 100644
--- a/src/core/hle/service/caps/caps_ss.cpp
+++ b/src/core/hle/service/caps/caps_ss.cpp
@@ -5,7 +5,8 @@
 
 namespace Service::Capture {
 
-CAPS_SS::CAPS_SS(Core::System& system_) : ServiceFramework{system_, "caps:ss"} {
+IScreenShotService::IScreenShotService(Core::System& system_)
+    : ServiceFramework{system_, "caps:ss"} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {201, nullptr, "SaveScreenShot"},
@@ -21,6 +22,6 @@ CAPS_SS::CAPS_SS(Core::System& system_) : ServiceFramework{system_, "caps:ss"} {
     RegisterHandlers(functions);
 }
 
-CAPS_SS::~CAPS_SS() = default;
+IScreenShotService::~IScreenShotService() = default;
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_ss.h b/src/core/hle/service/caps/caps_ss.h
index 718ade4853..381e44fd4b 100644
--- a/src/core/hle/service/caps/caps_ss.h
+++ b/src/core/hle/service/caps/caps_ss.h
@@ -11,10 +11,10 @@ class System;
 
 namespace Service::Capture {
 
-class CAPS_SS final : public ServiceFramework<CAPS_SS> {
+class IScreenShotService final : public ServiceFramework<IScreenShotService> {
 public:
-    explicit CAPS_SS(Core::System& system_);
-    ~CAPS_SS() override;
+    explicit IScreenShotService(Core::System& system_);
+    ~IScreenShotService() override;
 };
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp
index 3b11cc95c5..cad173dc75 100644
--- a/src/core/hle/service/caps/caps_su.cpp
+++ b/src/core/hle/service/caps/caps_su.cpp
@@ -7,10 +7,11 @@
 
 namespace Service::Capture {
 
-CAPS_SU::CAPS_SU(Core::System& system_) : ServiceFramework{system_, "caps:su"} {
+IScreenShotApplicationService::IScreenShotApplicationService(Core::System& system_)
+    : ServiceFramework{system_, "caps:su"} {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {32, &CAPS_SU::SetShimLibraryVersion, "SetShimLibraryVersion"},
+        {32, &IScreenShotApplicationService::SetShimLibraryVersion, "SetShimLibraryVersion"},
         {201, nullptr, "SaveScreenShot"},
         {203, nullptr, "SaveScreenShotEx0"},
         {205, nullptr, "SaveScreenShotEx1"},
@@ -21,9 +22,9 @@ CAPS_SU::CAPS_SU(Core::System& system_) : ServiceFramework{system_, "caps:su"} {
     RegisterHandlers(functions);
 }
 
-CAPS_SU::~CAPS_SU() = default;
+IScreenShotApplicationService::~IScreenShotApplicationService() = default;
 
-void CAPS_SU::SetShimLibraryVersion(HLERequestContext& ctx) {
+void IScreenShotApplicationService::SetShimLibraryVersion(HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto library_version{rp.Pop<u64>()};
     const auto applet_resource_user_id{rp.Pop<u64>()};
diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h
index c6398858d1..647e3059de 100644
--- a/src/core/hle/service/caps/caps_su.h
+++ b/src/core/hle/service/caps/caps_su.h
@@ -11,10 +11,10 @@ class System;
 
 namespace Service::Capture {
 
-class CAPS_SU final : public ServiceFramework<CAPS_SU> {
+class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> {
 public:
-    explicit CAPS_SU(Core::System& system_);
-    ~CAPS_SU() override;
+    explicit IScreenShotApplicationService(Core::System& system_);
+    ~IScreenShotApplicationService() override;
 
 private:
     void SetShimLibraryVersion(HLERequestContext& ctx);
diff --git a/src/core/hle/service/caps/caps_types.h b/src/core/hle/service/caps/caps_types.h
new file mode 100644
index 0000000000..bf60612737
--- /dev/null
+++ b/src/core/hle/service/caps/caps_types.h
@@ -0,0 +1,184 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+
+namespace Service::Capture {
+
+// This is nn::album::ImageOrientation
+enum class AlbumImageOrientation {
+    None,
+    Rotate90,
+    Rotate180,
+    Rotate270,
+};
+
+// This is nn::album::AlbumReportOption
+enum class AlbumReportOption : s32 {
+    Disable,
+    Enable,
+};
+
+enum class ContentType : u8 {
+    Screenshot = 0,
+    Movie = 1,
+    ExtraMovie = 3,
+};
+
+enum class AlbumStorage : u8 {
+    Nand,
+    Sd,
+};
+
+enum class ScreenShotDecoderFlag : u64 {
+    None = 0,
+    EnableFancyUpsampling = 1 << 0,
+    EnableBlockSmoothing = 1 << 1,
+};
+
+// This is nn::capsrv::AlbumFileDateTime
+struct AlbumFileDateTime {
+    u16 year{};
+    u8 month{};
+    u8 day{};
+    u8 hour{};
+    u8 minute{};
+    u8 second{};
+    u8 unique_id{};
+
+    friend constexpr bool operator==(const AlbumFileDateTime&, const AlbumFileDateTime&) = default;
+    friend constexpr bool operator>(const AlbumFileDateTime& a, const AlbumFileDateTime& b) {
+        if (a.year > b.year) {
+            return true;
+        }
+        if (a.month > b.month) {
+            return true;
+        }
+        if (a.day > b.day) {
+            return true;
+        }
+        if (a.hour > b.hour) {
+            return true;
+        }
+        if (a.minute > b.minute) {
+            return true;
+        }
+        return a.second > b.second;
+    };
+    friend constexpr bool operator<(const AlbumFileDateTime& a, const AlbumFileDateTime& b) {
+        if (a.year < b.year) {
+            return true;
+        }
+        if (a.month < b.month) {
+            return true;
+        }
+        if (a.day < b.day) {
+            return true;
+        }
+        if (a.hour < b.hour) {
+            return true;
+        }
+        if (a.minute < b.minute) {
+            return true;
+        }
+        return a.second < b.second;
+    };
+};
+static_assert(sizeof(AlbumFileDateTime) == 0x8, "AlbumFileDateTime has incorrect size.");
+
+// This is nn::album::AlbumEntry
+struct AlbumFileEntry {
+    u64 size{}; // Size of the entry
+    u64 hash{}; // AES256 with hardcoded key over AlbumEntry
+    AlbumFileDateTime datetime{};
+    AlbumStorage storage{};
+    ContentType content{};
+    INSERT_PADDING_BYTES(5);
+    u8 unknown{}; // Set to 1 on official SW
+};
+static_assert(sizeof(AlbumFileEntry) == 0x20, "AlbumFileEntry has incorrect size.");
+
+struct AlbumFileId {
+    u64 application_id{};
+    AlbumFileDateTime date{};
+    AlbumStorage storage{};
+    ContentType type{};
+    INSERT_PADDING_BYTES(0x5);
+    u8 unknown{};
+
+    friend constexpr bool operator==(const AlbumFileId&, const AlbumFileId&) = default;
+};
+static_assert(sizeof(AlbumFileId) == 0x18, "AlbumFileId is an invalid size");
+
+// This is nn::capsrv::AlbumEntry
+struct AlbumEntry {
+    u64 entry_size{};
+    AlbumFileId file_id{};
+};
+static_assert(sizeof(AlbumEntry) == 0x20, "AlbumEntry has incorrect size.");
+
+// This is nn::capsrv::ApplicationAlbumEntry
+struct ApplicationAlbumEntry {
+    u64 size{}; // Size of the entry
+    u64 hash{}; // AES256 with hardcoded key over AlbumEntry
+    AlbumFileDateTime datetime{};
+    AlbumStorage storage{};
+    ContentType content{};
+    INSERT_PADDING_BYTES(5);
+    u8 unknown{1}; // Set to 1 on official SW
+};
+static_assert(sizeof(ApplicationAlbumEntry) == 0x20, "ApplicationAlbumEntry has incorrect size.");
+
+// This is nn::capsrv::ApplicationAlbumFileEntry
+struct ApplicationAlbumFileEntry {
+    ApplicationAlbumEntry entry{};
+    AlbumFileDateTime datetime{};
+    u64 unknown{};
+};
+static_assert(sizeof(ApplicationAlbumFileEntry) == 0x30,
+              "ApplicationAlbumFileEntry has incorrect size.");
+
+struct ApplicationData {
+    std::array<u8, 0x400> data{};
+    u32 data_size{};
+};
+static_assert(sizeof(ApplicationData) == 0x404, "ApplicationData is an invalid size");
+
+struct ScreenShotAttribute {
+    u32 unknown_0{};
+    AlbumImageOrientation 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 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");
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp
index bffe0f8d07..260f254900 100644
--- a/src/core/hle/service/caps/caps_u.cpp
+++ b/src/core/hle/service/caps/caps_u.cpp
@@ -2,45 +2,29 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "common/logging/log.h"
-#include "core/hle/service/caps/caps.h"
+#include "core/hle/service/caps/caps_manager.h"
+#include "core/hle/service/caps/caps_types.h"
 #include "core/hle/service/caps/caps_u.h"
 #include "core/hle/service/ipc_helpers.h"
 
 namespace Service::Capture {
 
-class IAlbumAccessorApplicationSession final
-    : public ServiceFramework<IAlbumAccessorApplicationSession> {
-public:
-    explicit IAlbumAccessorApplicationSession(Core::System& system_)
-        : ServiceFramework{system_, "IAlbumAccessorApplicationSession"} {
-        // clang-format off
-        static const FunctionInfo functions[] = {
-            {2001, nullptr, "OpenAlbumMovieReadStream"},
-            {2002, nullptr, "CloseAlbumMovieReadStream"},
-            {2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"},
-            {2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"},
-            {2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"},
-        };
-        // clang-format on
-
-        RegisterHandlers(functions);
-    }
-};
-
-CAPS_U::CAPS_U(Core::System& system_) : ServiceFramework{system_, "caps:u"} {
+IAlbumApplicationService::IAlbumApplicationService(Core::System& system_,
+                                                   std::shared_ptr<AlbumManager> album_manager)
+    : ServiceFramework{system_, "caps:u"}, manager{album_manager} {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {32, &CAPS_U::SetShimLibraryVersion, "SetShimLibraryVersion"},
-        {102, &CAPS_U::GetAlbumContentsFileListForApplication, "GetAlbumContentsFileListForApplication"},
-        {103, nullptr, "DeleteAlbumContentsFileForApplication"},
-        {104, nullptr, "GetAlbumContentsFileSizeForApplication"},
+        {32, &IAlbumApplicationService::SetShimLibraryVersion, "SetShimLibraryVersion"},
+        {102, &IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated, "GetAlbumFileList0AafeAruidDeprecated"},
+        {103, nullptr, "DeleteAlbumFileByAruid"},
+        {104, nullptr, "GetAlbumFileSizeByAruid"},
         {105, nullptr, "DeleteAlbumFileByAruidForDebug"},
-        {110, nullptr, "LoadAlbumContentsFileScreenShotImageForApplication"},
-        {120, nullptr, "LoadAlbumContentsFileThumbnailImageForApplication"},
-        {130, nullptr, "PrecheckToCreateContentsForApplication"},
+        {110, nullptr, "LoadAlbumScreenShotImageByAruid"},
+        {120, nullptr, "LoadAlbumScreenShotThumbnailImageByAruid"},
+        {130, nullptr, "PrecheckToCreateContentsByAruid"},
         {140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"},
         {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
-        {142, &CAPS_U::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"},
+        {142, &IAlbumApplicationService::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"},
         {143, nullptr, "GetAlbumFileList4AaeUidAruid"},
         {144, nullptr, "GetAllAlbumFileList3AaeAruid"},
         {60002, nullptr, "OpenAccessorSessionForApplication"},
@@ -50,9 +34,9 @@ CAPS_U::CAPS_U(Core::System& system_) : ServiceFramework{system_, "caps:u"} {
     RegisterHandlers(functions);
 }
 
-CAPS_U::~CAPS_U() = default;
+IAlbumApplicationService::~IAlbumApplicationService() = default;
 
-void CAPS_U::SetShimLibraryVersion(HLERequestContext& ctx) {
+void IAlbumApplicationService::SetShimLibraryVersion(HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto library_version{rp.Pop<u64>()};
     const auto applet_resource_user_id{rp.Pop<u64>()};
@@ -64,10 +48,7 @@ void CAPS_U::SetShimLibraryVersion(HLERequestContext& ctx) {
     rb.Push(ResultSuccess);
 }
 
-void CAPS_U::GetAlbumContentsFileListForApplication(HLERequestContext& ctx) {
-    // Takes a type-0x6 output buffer containing an array of ApplicationAlbumFileEntry, a PID, an
-    // u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total
-    // output entries (which is copied to a s32 by official SW).
+void IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated(HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto pid{rp.Pop<s32>()};
     const auto content_type{rp.PopEnum<ContentType>()};
@@ -75,26 +56,49 @@ void CAPS_U::GetAlbumContentsFileListForApplication(HLERequestContext& ctx) {
     const auto end_posix_time{rp.Pop<s64>()};
     const auto applet_resource_user_id{rp.Pop<u64>()};
 
-    // TODO: Update this when we implement the album.
-    // Currently we do not have a method of accessing album entries, set this to 0 for now.
-    constexpr u32 total_entries_1{};
-    constexpr u32 total_entries_2{};
+    LOG_WARNING(Service_Capture,
+                "(STUBBED) called. pid={}, content_type={}, start_posix_time={}, "
+                "end_posix_time={}, applet_resource_user_id={}",
+                pid, content_type, start_posix_time, end_posix_time, applet_resource_user_id);
 
-    LOG_WARNING(
-        Service_Capture,
-        "(STUBBED) called. pid={}, content_type={}, start_posix_time={}, "
-        "end_posix_time={}, applet_resource_user_id={}, total_entries_1={}, total_entries_2={}",
-        pid, content_type, start_posix_time, end_posix_time, applet_resource_user_id,
-        total_entries_1, total_entries_2);
+    // TODO: Translate posix to DateTime
+
+    std::vector<ApplicationAlbumFileEntry> entries;
+    const Result result =
+        manager->GetAlbumFileList(entries, content_type, {}, {}, applet_resource_user_id);
+
+    if (!entries.empty()) {
+        ctx.WriteBuffer(entries);
+    }
 
     IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push(total_entries_1);
-    rb.Push(total_entries_2);
+    rb.Push(result);
+    rb.Push<u64>(entries.size());
 }
 
-void CAPS_U::GetAlbumFileList3AaeAruid(HLERequestContext& ctx) {
-    GetAlbumContentsFileListForApplication(ctx);
+void IAlbumApplicationService::GetAlbumFileList3AaeAruid(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto pid{rp.Pop<s32>()};
+    const auto content_type{rp.PopEnum<ContentType>()};
+    const auto start_date_time{rp.PopRaw<AlbumFileDateTime>()};
+    const auto end_date_time{rp.PopRaw<AlbumFileDateTime>()};
+    const auto applet_resource_user_id{rp.Pop<u64>()};
+
+    LOG_WARNING(Service_Capture,
+                "(STUBBED) called. pid={}, content_type={}, applet_resource_user_id={}", pid,
+                content_type, applet_resource_user_id);
+
+    std::vector<ApplicationAlbumFileEntry> entries;
+    const Result result = manager->GetAlbumFileList(entries, content_type, start_date_time,
+                                                    end_date_time, applet_resource_user_id);
+
+    if (!entries.empty()) {
+        ctx.WriteBuffer(entries);
+    }
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push<u64>(entries.size());
 }
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_u.h b/src/core/hle/service/caps/caps_u.h
index e8dd037d7b..9458c128ef 100644
--- a/src/core/hle/service/caps/caps_u.h
+++ b/src/core/hle/service/caps/caps_u.h
@@ -10,16 +10,20 @@ class System;
 }
 
 namespace Service::Capture {
+class AlbumManager;
 
-class CAPS_U final : public ServiceFramework<CAPS_U> {
+class IAlbumApplicationService final : public ServiceFramework<IAlbumApplicationService> {
 public:
-    explicit CAPS_U(Core::System& system_);
-    ~CAPS_U() override;
+    explicit IAlbumApplicationService(Core::System& system_,
+                                      std::shared_ptr<AlbumManager> album_manager);
+    ~IAlbumApplicationService() override;
 
 private:
     void SetShimLibraryVersion(HLERequestContext& ctx);
-    void GetAlbumContentsFileListForApplication(HLERequestContext& ctx);
+    void GetAlbumFileList0AafeAruidDeprecated(HLERequestContext& ctx);
     void GetAlbumFileList3AaeAruid(HLERequestContext& ctx);
+
+    std::shared_ptr<AlbumManager> manager = nullptr;
 };
 
 } // namespace Service::Capture