diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp
index 610fe99401b7e7d6cfaf2804f12b86a1500a4073..0dbf04862778025b5be43c038c272662086a8546 100644
--- a/src/core/hle/service/caps/caps.cpp
+++ b/src/core/hle/service/caps/caps.cpp
@@ -16,7 +16,7 @@ namespace Service::Capture {
 void LoopProcess(Core::System& system) {
     auto server_manager = std::make_unique<ServerManager>(system);
 
-    server_manager->RegisterNamedService("caps:a", std::make_shared<CAPS_A>(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));
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp
index 44267b284e79396dc151654b921fbfbe6a7e4d78..e1f836e08392c2392da80c7147142347130e6c12 100644
--- a/src/core/hle/service/caps/caps_a.cpp
+++ b/src/core/hle/service/caps/caps_a.cpp
@@ -1,7 +1,14 @@
 // 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 "core/hle/service/caps/caps_a.h"
+#include "core/hle/service/ipc_helpers.h"
 
 namespace Service::Capture {
 
@@ -26,15 +33,16 @@ public:
     }
 };
 
-CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} {
+IAlbumAccessorService::IAlbumAccessorService(Core::System& system_)
+    : ServiceFramework{system_, "caps:a"} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, nullptr, "GetAlbumFileCount"},
         {1, nullptr, "GetAlbumFileList"},
         {2, nullptr, "LoadAlbumFile"},
-        {3, nullptr, "DeleteAlbumFile"},
+        {3, &IAlbumAccessorService::DeleteAlbumFile, "DeleteAlbumFile"},
         {4, nullptr, "StorageCopyAlbumFile"},
-        {5, nullptr, "IsAlbumMounted"},
+        {5, &IAlbumAccessorService::IsAlbumMounted, "IsAlbumMounted"},
         {6, nullptr, "GetAlbumUsage"},
         {7, nullptr, "GetAlbumFileSize"},
         {8, nullptr, "LoadAlbumFileThumbnail"},
@@ -47,18 +55,18 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} {
         {15, nullptr, "GetAlbumUsage3"},
         {16, nullptr, "GetAlbumMountResult"},
         {17, nullptr, "GetAlbumUsage16"},
-        {18, nullptr, "Unknown18"},
+        {18, &IAlbumAccessorService::Unknown18, "Unknown18"},
         {19, nullptr, "Unknown19"},
         {100, nullptr, "GetAlbumFileCountEx0"},
-        {101, nullptr, "GetAlbumFileListEx0"},
+        {101, &IAlbumAccessorService::GetAlbumFileListEx0, "GetAlbumFileListEx0"},
         {202, nullptr, "SaveEditedScreenShot"},
         {301, nullptr, "GetLastThumbnail"},
         {302, nullptr, "GetLastOverlayMovieThumbnail"},
-        {401, nullptr, "GetAutoSavingStorage"},
+        {401,  &IAlbumAccessorService::GetAutoSavingStorage, "GetAutoSavingStorage"},
         {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
         {1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"},
-        {1002, nullptr, "LoadAlbumScreenShotImageEx1"},
-        {1003, nullptr, "LoadAlbumScreenShotThumbnailImageEx1"},
+        {1002, &IAlbumAccessorService::LoadAlbumScreenShotImageEx1, "LoadAlbumScreenShotImageEx1"},
+        {1003, &IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1, "LoadAlbumScreenShotThumbnailImageEx1"},
         {8001, nullptr, "ForceAlbumUnmounted"},
         {8002, nullptr, "ResetAlbumMountStatus"},
         {8011, nullptr, "RefreshAlbumCache"},
@@ -74,6 +82,294 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} {
     RegisterHandlers(functions);
 }
 
-CAPS_A::~CAPS_A() = default;
+IAlbumAccessorService::~IAlbumAccessorService() = default;
+
+void IAlbumAccessorService::DeleteAlbumFile(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto file_id{rp.PopRaw<AlbumFileId>()};
+
+    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;
+        }
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+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);
+
+    if (storage == AlbumStorage::Sd) {
+        FindScreenshots();
+    }
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(is_mounted);
+}
+
+void IAlbumAccessorService::Unknown18(HLERequestContext& ctx) {
+    struct UnknownBuffer {
+        INSERT_PADDING_BYTES(0x10);
+    };
+    static_assert(sizeof(UnknownBuffer) == 0x10, "UnknownBuffer is an invalid size");
+
+    LOG_WARNING(Service_Capture, "(STUBBED) called");
+
+    std::vector<UnknownBuffer> buffer{};
+
+    if (!buffer.empty()) {
+        ctx.WriteBuffer(buffer);
+    }
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(static_cast<u32>(buffer.size()));
+}
+
+void IAlbumAccessorService::GetAlbumFileListEx0(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto storage{rp.PopEnum<AlbumStorage>()};
+    const auto flags{rp.Pop<u8>()};
+
+    LOG_INFO(Service_Capture, "called, storage={}, flags={}", storage, flags);
+
+    std::vector<AlbumEntry> entries{};
+
+    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);
+        }
+    }
+
+    if (!entries.empty()) {
+        ctx.WriteBuffer(entries);
+    }
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(entries.size());
+}
+
+void IAlbumAccessorService::GetAutoSavingStorage(HLERequestContext& ctx) {
+    bool is_autosaving{};
+
+    LOG_WARNING(Service_Capture, "(STUBBED) called, is_autosaving={}", is_autosaving);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(is_autosaving);
+}
+
+void IAlbumAccessorService::LoadAlbumScreenShotImageEx1(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto file_id{rp.PopRaw<AlbumFileId>()};
+    const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()};
+
+    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);
+
+    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);
+    }
+
+    ctx.WriteBuffer(image_output, 0);
+    ctx.WriteBuffer(image, 1);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto file_id{rp.PopRaw<AlbumFileId>()};
+    const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()};
+
+    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);
+
+    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);
+    }
+
+    ctx.WriteBuffer(image_output, 0);
+    ctx.WriteBuffer(image, 1);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+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;
+    }
+
+    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_a.h b/src/core/hle/service/caps/caps_a.h
index 98a21a5adb5f7b3b68c8ea2b01b9155464d17035..975c0ebdb6323b3abc35df76105bcee0d41d2b3d 100644
--- a/src/core/hle/service/caps/caps_a.h
+++ b/src/core/hle/service/caps/caps_a.h
@@ -3,6 +3,7 @@
 
 #pragma once
 
+#include "common/fs/fs.h"
 #include "core/hle/service/service.h"
 
 namespace Core {
@@ -11,10 +12,121 @@ class System;
 
 namespace Service::Capture {
 
-class CAPS_A final : public ServiceFramework<CAPS_A> {
+class IAlbumAccessorService final : public ServiceFramework<IAlbumAccessorService> {
 public:
-    explicit CAPS_A(Core::System& system_);
-    ~CAPS_A() override;
+    explicit IAlbumAccessorService(Core::System& system_);
+    ~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);
+    void GetAlbumFileListEx0(HLERequestContext& ctx);
+    void GetAutoSavingStorage(HLERequestContext& ctx);
+    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);
+
+    bool is_mounted{};
+    std::vector<std::filesystem::path> sd_image_paths{};
 };
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 6e0baf0bee1105395d5f40ea53ec0094b2875dfc..f9e0e272df5ea6c22913b2f6b163840c7ff110fe 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -7,6 +7,7 @@
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/patch_manager.h"
 #include "core/file_sys/vfs.h"
+#include "core/hle/service/filesystem/filesystem.h"
 #include "core/hle/service/glue/glue_manager.h"
 #include "core/hle/service/ipc_helpers.h"
 #include "core/hle/service/ns/errors.h"
@@ -502,8 +503,8 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
     static const FunctionInfo functions[] = {
         {11, nullptr, "CalculateApplicationOccupiedSize"},
         {43, nullptr, "CheckSdCardMountStatus"},
-        {47, nullptr, "GetTotalSpaceSize"},
-        {48, nullptr, "GetFreeSpaceSize"},
+        {47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"},
+        {48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"},
         {600, nullptr, "CountApplicationContentMeta"},
         {601, nullptr, "ListApplicationContentMetaStatus"},
         {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
@@ -516,6 +517,28 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
 
 IContentManagementInterface::~IContentManagementInterface() = default;
 
+void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto storage{rp.PopEnum<FileSys::StorageId>()};
+
+    LOG_INFO(Service_Capture, "called, storage={}", storage);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage));
+}
+
+void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto storage{rp.PopEnum<FileSys::StorageId>()};
+
+    LOG_INFO(Service_Capture, "called, storage={}", storage);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage));
+}
+
 IDocumentInterface::IDocumentInterface(Core::System& system_)
     : ServiceFramework{system_, "IDocumentInterface"} {
     // clang-format off
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h
index 175dad780e819c3ff68d7c23238c9bd67beace35..34d2a45dcbe826879bcee1887d7cf502d701a606 100644
--- a/src/core/hle/service/ns/ns.h
+++ b/src/core/hle/service/ns/ns.h
@@ -48,6 +48,10 @@ class IContentManagementInterface final : public ServiceFramework<IContentManage
 public:
     explicit IContentManagementInterface(Core::System& system_);
     ~IContentManagementInterface() override;
+
+private:
+    void GetTotalSpaceSize(HLERequestContext& ctx);
+    void GetFreeSpaceSize(HLERequestContext& ctx);
 };
 
 class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {