diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp
index e065e592fb..83c184750b 100644
--- a/src/core/file_sys/control_metadata.cpp
+++ b/src/core/file_sys/control_metadata.cpp
@@ -36,18 +36,20 @@ std::string LanguageEntry::GetDeveloperName() const {
                                                        developer_name.size());
 }
 
-NACP::NACP(VirtualFile file) : raw(std::make_unique<RawNACP>()) {
-    file->ReadObject(raw.get());
+NACP::NACP() = default;
+
+NACP::NACP(VirtualFile file) {
+    file->ReadObject(&raw);
 }
 
 NACP::~NACP() = default;
 
 const LanguageEntry& NACP::GetLanguageEntry(Language language) const {
     if (language != Language::Default) {
-        return raw->language_entries.at(static_cast<u8>(language));
+        return raw.language_entries.at(static_cast<u8>(language));
     }
 
-    for (const auto& language_entry : raw->language_entries) {
+    for (const auto& language_entry : raw.language_entries) {
         if (!language_entry.GetApplicationName().empty())
             return language_entry;
     }
@@ -65,21 +67,29 @@ std::string NACP::GetDeveloperName(Language language) const {
 }
 
 u64 NACP::GetTitleId() const {
-    return raw->title_id;
+    return raw.title_id;
 }
 
 u64 NACP::GetDLCBaseTitleId() const {
-    return raw->dlc_base_title_id;
+    return raw.dlc_base_title_id;
 }
 
 std::string NACP::GetVersionString() const {
-    return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(),
-                                                       raw->version_string.size());
+    return Common::StringFromFixedZeroTerminatedBuffer(raw.version_string.data(),
+                                                       raw.version_string.size());
+}
+
+u64 NACP::GetDefaultNormalSaveSize() const {
+    return raw.normal_save_data_size;
+}
+
+u64 NACP::GetDefaultJournalSaveSize() const {
+    return raw.journal_sava_data_size;
 }
 
 std::vector<u8> NACP::GetRawBytes() const {
     std::vector<u8> out(sizeof(RawNACP));
-    std::memcpy(out.data(), raw.get(), sizeof(RawNACP));
+    std::memcpy(out.data(), &raw, sizeof(RawNACP));
     return out;
 }
 } // namespace FileSys
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index bfaad46b41..7b9cdc9105 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -28,17 +28,30 @@ static_assert(sizeof(LanguageEntry) == 0x300, "LanguageEntry has incorrect size.
 // The raw file format of a NACP file.
 struct RawNACP {
     std::array<LanguageEntry, 16> language_entries;
-    INSERT_PADDING_BYTES(0x38);
+    std::array<u8, 0x25> isbn;
+    u8 startup_user_account;
+    INSERT_PADDING_BYTES(2);
+    u32_le application_attribute;
+    u32_le supported_languages;
+    u32_le parental_control;
+    bool screenshot_enabled;
+    u8 video_capture_mode;
+    bool data_loss_confirmation;
+    INSERT_PADDING_BYTES(1);
     u64_le title_id;
-    INSERT_PADDING_BYTES(0x20);
+    std::array<u8, 0x20> rating_age;
     std::array<char, 0x10> version_string;
     u64_le dlc_base_title_id;
     u64_le title_id_2;
-    INSERT_PADDING_BYTES(0x28);
+    u64_le normal_save_data_size;
+    u64_le journal_sava_data_size;
+    INSERT_PADDING_BYTES(0x18);
     u64_le product_code;
-    u64_le title_id_3;
-    std::array<u64_le, 0x7> title_id_array;
-    INSERT_PADDING_BYTES(0x8);
+    std::array<u64_le, 0x8> local_communication;
+    u8 logo_type;
+    u8 logo_handling;
+    bool runtime_add_on_content_install;
+    INSERT_PADDING_BYTES(5);
     u64_le title_id_update;
     std::array<u8, 0x40> bcat_passphrase;
     INSERT_PADDING_BYTES(0xEC0);
@@ -72,6 +85,7 @@ extern const std::array<const char*, 15> LANGUAGE_NAMES;
 // These store application name, dev name, title id, and other miscellaneous data.
 class NACP {
 public:
+    explicit NACP();
     explicit NACP(VirtualFile file);
     ~NACP();
 
@@ -81,10 +95,12 @@ public:
     u64 GetTitleId() const;
     u64 GetDLCBaseTitleId() const;
     std::string GetVersionString() const;
+    u64 GetDefaultNormalSaveSize() const;
+    u64 GetDefaultJournalSaveSize() const;
     std::vector<u8> GetRawBytes() const;
 
 private:
-    std::unique_ptr<RawNACP> raw;
+    RawNACP raw{};
 };
 
 } // namespace FileSys
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index d63b7f19b3..1913dc956c 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -13,6 +13,8 @@
 
 namespace FileSys {
 
+constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
+
 std::string SaveDataDescriptor::DebugInfo() const {
     return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}]",
                        static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id);
@@ -132,4 +134,32 @@ std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType typ
     }
 }
 
+SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
+                                               u128 user_id) const {
+    const auto path = GetFullPath(SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
+    const auto dir = GetOrCreateDirectoryRelative(this->dir, path);
+
+    const auto size_file = dir->GetFile(SAVE_DATA_SIZE_FILENAME);
+    if (size_file == nullptr || size_file->GetSize() < sizeof(SaveDataSize))
+        return {0, 0};
+
+    SaveDataSize out;
+    if (size_file->ReadObject(&out) != sizeof(SaveDataSize))
+        return {0, 0};
+    return out;
+}
+
+void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
+                                        SaveDataSize new_value) {
+    const auto path = GetFullPath(SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
+    const auto dir = GetOrCreateDirectoryRelative(this->dir, path);
+
+    const auto size_file = dir->CreateFile(SAVE_DATA_SIZE_FILENAME);
+    if (size_file == nullptr)
+        return;
+
+    size_file->Resize(sizeof(SaveDataSize));
+    size_file->WriteObject(new_value);
+}
+
 } // namespace FileSys
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index bd4919610e..3a1caf2926 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -46,6 +46,11 @@ struct SaveDataDescriptor {
 };
 static_assert(sizeof(SaveDataDescriptor) == 0x40, "SaveDataDescriptor has incorrect size.");
 
+struct SaveDataSize {
+    u64 normal;
+    u64 journal;
+};
+
 /// File system interface to the SaveData archive
 class SaveDataFactory {
 public:
@@ -60,6 +65,9 @@ public:
     static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id,
                                    u128 user_id, u64 save_id);
 
+    SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const;
+    void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, SaveDataSize new_value);
+
 private:
     VirtualDir dir;
 };
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index e5641b2554..9540947729 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -150,7 +150,7 @@ public:
     template <typename T>
     std::size_t WriteArray(const T* data, std::size_t number_elements, std::size_t offset = 0) {
         static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
-        return Write(data, number_elements * sizeof(T), offset);
+        return Write(reinterpret_cast<const u8*>(data), number_elements * sizeof(T), offset);
     }
 
     // Writes size bytes starting at memory location data to offset in file.
@@ -166,7 +166,7 @@ public:
     template <typename T>
     std::size_t WriteObject(const T& data, std::size_t offset = 0) {
         static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
-        return Write(&data, sizeof(T), offset);
+        return Write(reinterpret_cast<const u8*>(&data), sizeof(T), offset);
     }
 
     // Renames the file to name. Returns whether or not the operation was successsful.
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 5fc02a5211..d13ce4dca2 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -8,6 +8,7 @@
 #include <stack>
 #include "audio_core/audio_renderer.h"
 #include "core/core.h"
+#include "core/file_sys/savedata_factory.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
@@ -865,8 +866,8 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
         {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
         {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
         {24, nullptr, "GetLaunchStorageInfoForDebug"},
-        {25, nullptr, "ExtendSaveData"},
-        {26, nullptr, "GetSaveDataSize"},
+        {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
+        {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
         {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
         {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
         {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
@@ -1043,6 +1044,48 @@ void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) {
     rb.Push<u64>(0);
 }
 
+void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto type{rp.PopRaw<FileSys::SaveDataType>()};
+    rp.Skip(1, false);
+    const auto user_id{rp.PopRaw<u128>()};
+    const auto new_normal_size{rp.PopRaw<u64>()};
+    const auto new_journal_size{rp.PopRaw<u64>()};
+
+    LOG_DEBUG(Service_AM,
+              "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
+              "new_journal={:016X}",
+              static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
+
+    FileSystem::WriteSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id,
+                                  {new_normal_size, new_journal_size});
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(RESULT_SUCCESS);
+
+    // The following value is used upon failure to help the system recover.
+    // Since we always succeed, this should be 0.
+    rb.Push<u64>(0);
+}
+
+void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto type{rp.PopRaw<FileSys::SaveDataType>()};
+    rp.Skip(1, false);
+    const auto user_id{rp.PopRaw<u128>()};
+
+    LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", static_cast<u8>(type),
+              user_id[1], user_id[0]);
+
+    const auto size =
+        FileSystem::ReadSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id);
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push(size.normal);
+    rb.Push(size.journal);
+}
+
 void InstallInterfaces(SM::ServiceManager& service_manager,
                        std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
     auto message_queue = std::make_shared<AppletMessageQueue>();
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 34c45fadf0..b6113cfdd1 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -206,6 +206,8 @@ private:
     void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx);
     void NotifyRunning(Kernel::HLERequestContext& ctx);
     void GetPseudoDeviceId(Kernel::HLERequestContext& ctx);
+    void ExtendSaveData(Kernel::HLERequestContext& ctx);
+    void GetSaveDataSize(Kernel::HLERequestContext& ctx);
     void BeginBlockingHomeButtonShortAndLongPressed(Kernel::HLERequestContext& ctx);
     void EndBlockingHomeButtonShortAndLongPressed(Kernel::HLERequestContext& ctx);
     void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index b1490e6fac..c6da2df43c 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -8,18 +8,23 @@
 #include "common/file_util.h"
 #include "core/core.h"
 #include "core/file_sys/bis_factory.h"
+#include "core/file_sys/control_metadata.h"
 #include "core/file_sys/errors.h"
 #include "core/file_sys/mode.h"
+#include "core/file_sys/partition_filesystem.h"
+#include "core/file_sys/patch_manager.h"
 #include "core/file_sys/registered_cache.h"
 #include "core/file_sys/romfs_factory.h"
 #include "core/file_sys/savedata_factory.h"
 #include "core/file_sys/sdmc_factory.h"
 #include "core/file_sys/vfs.h"
 #include "core/file_sys/vfs_offset.h"
+#include "core/hle/kernel/process.h"
 #include "core/hle/service/filesystem/filesystem.h"
 #include "core/hle/service/filesystem/fsp_ldr.h"
 #include "core/hle/service/filesystem/fsp_pr.h"
 #include "core/hle/service/filesystem/fsp_srv.h"
+#include "core/loader/loader.h"
 
 namespace Service::FileSystem {
 
@@ -28,6 +33,10 @@ namespace Service::FileSystem {
 // TODO(DarkLordZach): Eventually make this configurable in settings.
 constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
 
+// A default size for normal/journal save data size if application control metadata cannot be found.
+// This should be large enough to satisfy even the most extreme requirements (~4.2GB)
+constexpr u64 SUFFICIENT_SAVE_DATA_SIZE = 0xF0000000;
+
 static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
                                                        std::string_view dir_name_) {
     std::string dir_name(FileUtil::SanitizePath(dir_name_));
@@ -341,6 +350,44 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
     return sdmc_factory->Open();
 }
 
+FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id) {
+    if (save_data_factory == nullptr) {
+        return {0, 0};
+    }
+
+    const auto value = save_data_factory->ReadSaveDataSize(type, title_id, user_id);
+
+    if (value.normal == 0 && value.journal == 0) {
+        FileSys::SaveDataSize new_size{SUFFICIENT_SAVE_DATA_SIZE, SUFFICIENT_SAVE_DATA_SIZE};
+
+        FileSys::NACP nacp;
+        const auto res = Core::System::GetInstance().GetAppLoader().ReadControlData(nacp);
+
+        if (res != Loader::ResultStatus::Success) {
+            FileSys::PatchManager pm{Core::CurrentProcess()->GetTitleID()};
+            auto [nacp_unique, discard] = pm.GetControlMetadata();
+
+            if (nacp_unique != nullptr) {
+                new_size = {nacp_unique->GetDefaultNormalSaveSize(),
+                            nacp_unique->GetDefaultJournalSaveSize()};
+            }
+        } else {
+            new_size = {nacp.GetDefaultNormalSaveSize(), nacp.GetDefaultJournalSaveSize()};
+        }
+
+        WriteSaveDataSize(type, title_id, user_id, new_size);
+        return new_size;
+    }
+
+    return value;
+}
+
+void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
+                       FileSys::SaveDataSize new_value) {
+    if (save_data_factory != nullptr)
+        save_data_factory->WriteSaveDataSize(type, title_id, user_id, new_value);
+}
+
 FileSys::RegisteredCacheUnion GetUnionContents() {
     return FileSys::RegisteredCacheUnion{
         {GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}};
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 965414be02..6fd5e7b230 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -21,9 +21,11 @@ class SDMCFactory;
 enum class ContentRecordType : u8;
 enum class Mode : u32;
 enum class SaveDataSpaceId : u8;
+enum class SaveDataType : u8;
 enum class StorageId : u8;
 
 struct SaveDataDescriptor;
+struct SaveDataSize;
 } // namespace FileSys
 
 namespace Service {
@@ -48,6 +50,10 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
 ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space);
 ResultVal<FileSys::VirtualDir> OpenSDMC();
 
+FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id);
+void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
+                       FileSys::SaveDataSize new_value);
+
 FileSys::RegisteredCacheUnion GetUnionContents();
 
 FileSys::RegisteredCache* GetSystemNANDContents();
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 0838e303b3..cfd67adc0f 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -15,6 +15,10 @@
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/vfs.h"
 
+namespace FileSys {
+class NACP;
+} // namespace FileSys
+
 namespace Kernel {
 struct AddressMapping;
 class Process;
@@ -245,11 +249,11 @@ public:
     }
 
     /**
-     * Get the developer of the application
-     * @param developer Reference to store the application developer into
+     * Get the control data (CNMT) of the application
+     * @param control Reference to store the application control data into
      * @return ResultStatus result of function
      */
-    virtual ResultStatus ReadDeveloper(std::string& developer) {
+    virtual ResultStatus ReadControlData(FileSys::NACP& control) {
         return ResultStatus::ErrorNotImplemented;
     }
 
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index b4ab88ae8a..4d4b44571d 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -152,10 +152,10 @@ ResultStatus AppLoader_NSP::ReadTitle(std::string& title) {
     return ResultStatus::Success;
 }
 
-ResultStatus AppLoader_NSP::ReadDeveloper(std::string& developer) {
+ResultStatus AppLoader_NSP::ReadControlData(FileSys::NACP& nacp) {
     if (nacp_file == nullptr)
         return ResultStatus::ErrorNoControl;
-    developer = nacp_file->GetDeveloperName();
+    nacp = *nacp_file;
     return ResultStatus::Success;
 }
 } // namespace Loader
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
index 2b1e0719bb..32eb0193d2 100644
--- a/src/core/loader/nsp.h
+++ b/src/core/loader/nsp.h
@@ -43,7 +43,7 @@ public:
     ResultStatus ReadProgramId(u64& out_program_id) override;
     ResultStatus ReadIcon(std::vector<u8>& buffer) override;
     ResultStatus ReadTitle(std::string& title) override;
-    ResultStatus ReadDeveloper(std::string& developer) override;
+    ResultStatus ReadControlData(FileSys::NACP& nacp) override;
 
 private:
     std::unique_ptr<FileSys::NSP> nsp;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index bd5a83b49f..e67e43c69d 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -121,10 +121,11 @@ ResultStatus AppLoader_XCI::ReadTitle(std::string& title) {
     return ResultStatus::Success;
 }
 
-ResultStatus AppLoader_XCI::ReadDeveloper(std::string& developer) {
+ResultStatus AppLoader_XCI::ReadControlData(FileSys::NACP& control) {
     if (nacp_file == nullptr)
         return ResultStatus::ErrorNoControl;
-    developer = nacp_file->GetDeveloperName();
+    control = *nacp_file;
     return ResultStatus::Success;
 }
+
 } // namespace Loader
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 15d1b1a235..9d3923f62b 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -43,7 +43,7 @@ public:
     ResultStatus ReadProgramId(u64& out_program_id) override;
     ResultStatus ReadIcon(std::vector<u8>& buffer) override;
     ResultStatus ReadTitle(std::string& title) override;
-    ResultStatus ReadDeveloper(std::string& developer) override;
+    ResultStatus ReadControlData(FileSys::NACP& control) override;
 
 private:
     std::unique_ptr<FileSys::XCI> xci;
diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_general.cpp
index 5ca493b6df..dffaba5ed2 100644
--- a/src/yuzu/configuration/configure_per_general.cpp
+++ b/src/yuzu/configuration/configure_per_general.cpp
@@ -108,9 +108,9 @@ void ConfigurePerGameGeneral::loadConfiguration() {
         if (loader->ReadTitle(title) == Loader::ResultStatus::Success)
             ui->display_name->setText(QString::fromStdString(title));
 
-        std::string developer;
-        if (loader->ReadDeveloper(developer) == Loader::ResultStatus::Success)
-            ui->display_developer->setText(QString::fromStdString(developer));
+        FileSys::NACP nacp;
+        if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success)
+            ui->display_developer->setText(QString::fromStdString(nacp.GetDeveloperName()));
 
         ui->display_version->setText(QStringLiteral("1.0.0"));
     }