From b436fdca6468c92c0096582fd1f627b5904650f5 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 8 Dec 2024 22:33:14 +0200 Subject: [PATCH 1/2] FS: Stub TWL_PHOTO --- CMakeLists.txt | 3 +- include/fs/archive_base.hpp | 332 +++++++++++------------ include/fs/archive_twl_photo.hpp | 30 ++ include/services/fs.hpp | 5 +- src/core/fs/archive_system_save_data.cpp | 2 +- src/core/fs/archive_twl_photo.cpp | 40 +++ src/core/services/fs.cpp | 3 + 7 files changed, 246 insertions(+), 169 deletions(-) create mode 100644 include/fs/archive_twl_photo.hpp create mode 100644 src/core/fs/archive_twl_photo.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b21353af0..010e991d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -338,6 +338,7 @@ set(LOADER_SOURCE_FILES src/core/loader/elf.cpp src/core/loader/ncsd.cpp src/cor set(FS_SOURCE_FILES src/core/fs/archive_self_ncch.cpp src/core/fs/archive_save_data.cpp src/core/fs/archive_sdmc.cpp src/core/fs/archive_ext_save_data.cpp src/core/fs/archive_ncch.cpp src/core/fs/romfs.cpp src/core/fs/ivfc.cpp src/core/fs/archive_user_save_data.cpp src/core/fs/archive_system_save_data.cpp + src/core/fs/archive_twl_photo.cpp ) set(APPLET_SOURCE_FILES src/core/applets/applet.cpp src/core/applets/mii_selector.cpp src/core/applets/software_keyboard.cpp src/core/applets/applet_manager.cpp @@ -387,7 +388,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp include/PICA/pica_vert_config.hpp include/sdl_sensors.hpp include/PICA/draw_acceleration.hpp include/renderdoc.hpp include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp include/audio/audio_interpolation.hpp include/audio/hle_mixer.hpp include/audio/dsp_simd.hpp - include/services/dsp_firmware_db.hpp include/frontend_settings.hpp + include/services/dsp_firmware_db.hpp include/frontend_settings.hpp include/fs/archive_twl_photo.hpp ) cmrc_add_resource_library( diff --git a/include/fs/archive_base.hpp b/include/fs/archive_base.hpp index 2843be687..2eef4d802 100644 --- a/include/fs/archive_base.hpp +++ b/include/fs/archive_base.hpp @@ -7,6 +7,7 @@ #include #include #include + #include "helpers.hpp" #include "memory.hpp" #include "result.hpp" @@ -15,13 +16,13 @@ using Result::HorizonResult; namespace PathType { - enum : u32 { - Invalid = 0, - Empty = 1, - Binary = 2, - ASCII = 3, - UTF16 = 4, - }; + enum : u32 { + Invalid = 0, + Empty = 1, + Binary = 2, + ASCII = 3, + UTF16 = 4, + }; } namespace ArchiveID { @@ -40,85 +41,86 @@ namespace ArchiveID { UserSaveData1 = 0x567890B2, // 3DBrew: Similar to 0x567890B2 but can only access Accessible Save specified in exheader? UserSaveData2 = 0x567890B4, + + TwlPhoto = 0x567890AC }; - static std::string toString(u32 id) { - switch (id) { - case SelfNCCH: return "SelfNCCH"; - case SaveData: return "SaveData"; - case ExtSaveData: return "ExtSaveData"; - case SharedExtSaveData: return "SharedExtSaveData"; - case SystemSaveData: return "SystemSaveData"; - case SDMC: return "SDMC"; - case SDMCWriteOnly: return "SDMC (Write-only)"; - case SavedataAndNcch: return "Savedata & NCCH (archive 0x2345678A)"; - default: return "Unknown archive"; - } - } -} + static std::string toString(u32 id) { + switch (id) { + case SelfNCCH: return "SelfNCCH"; + case SaveData: return "SaveData"; + case ExtSaveData: return "ExtSaveData"; + case SharedExtSaveData: return "SharedExtSaveData"; + case SystemSaveData: return "SystemSaveData"; + case SDMC: return "SDMC"; + case SDMCWriteOnly: return "SDMC (Write-only)"; + case SavedataAndNcch: return "Savedata & NCCH (archive 0x2345678A)"; + case TwlPhoto: return "TWL_PHOTO"; + default: return "Unknown archive"; + } + } +} // namespace ArchiveID struct FSPath { - u32 type = PathType::Invalid; - - std::vector binary; // Path data for binary paths - std::string string; // Path data for ASCII paths - std::u16string utf16_string; - - FSPath() {} - - FSPath(u32 type, const std::vector& vec) : type(type) { - switch (type) { - case PathType::Binary: - binary = std::move(vec); - break; - - case PathType::ASCII: - string.resize(vec.size() - 1); // -1 because of the null terminator - std::memcpy(string.data(), vec.data(), vec.size() - 1); // Copy string data - break; - - case PathType::UTF16: { - const size_t size = vec.size() / sizeof(u16) - 1; // Character count. -1 because null terminator here too - utf16_string.resize(size); - std::memcpy(utf16_string.data(), vec.data(), size * sizeof(u16)); - break; - } -; } - } + u32 type = PathType::Invalid; + + std::vector binary; // Path data for binary paths + std::string string; // Path data for ASCII paths + std::u16string utf16_string; + + FSPath() {} + + FSPath(u32 type, const std::vector& vec) : type(type) { + switch (type) { + case PathType::Binary: binary = std::move(vec); break; + + case PathType::ASCII: + string.resize(vec.size() - 1); // -1 because of the null terminator + std::memcpy(string.data(), vec.data(), vec.size() - 1); // Copy string data + break; + + case PathType::UTF16: { + const size_t size = vec.size() / sizeof(u16) - 1; // Character count. -1 because null terminator here too + utf16_string.resize(size); + std::memcpy(utf16_string.data(), vec.data(), size * sizeof(u16)); + break; + }; + } + } }; struct FilePerms { - u32 raw; + u32 raw; - FilePerms(u32 val) : raw(val) {} - bool read() const { return (raw & 1) != 0; } - bool write() const { return (raw & 2) != 0; } - bool create() const { return (raw & 4) != 0; } + FilePerms(u32 val) : raw(val) {} + bool read() const { return (raw & 1) != 0; } + bool write() const { return (raw & 2) != 0; } + bool create() const { return (raw & 4) != 0; } }; class ArchiveBase; struct FileSession { - ArchiveBase* archive = nullptr; - FILE* fd = nullptr; // File descriptor for file sessions that require them. - FSPath path; - FSPath archivePath; - u32 priority = 0; // TODO: What does this even do - bool isOpen; - - FileSession(ArchiveBase* archive, const FSPath& filePath, const FSPath& archivePath, FILE* fd, bool isOpen = true) : - archive(archive), path(filePath), archivePath(archivePath), fd(fd), isOpen(isOpen), priority(0) {} - - // For cloning a file session - FileSession(const FileSession& other) : archive(other.archive), path(other.path), - archivePath(other.archivePath), fd(other.fd), isOpen(other.isOpen), priority(other.priority) {} + ArchiveBase* archive = nullptr; + FILE* fd = nullptr; // File descriptor for file sessions that require them. + FSPath path; + FSPath archivePath; + u32 priority = 0; // TODO: What does this even do + bool isOpen; + + FileSession(ArchiveBase* archive, const FSPath& filePath, const FSPath& archivePath, FILE* fd, bool isOpen = true) + : archive(archive), path(filePath), archivePath(archivePath), fd(fd), isOpen(isOpen), priority(0) {} + + // For cloning a file session + FileSession(const FileSession& other) + : archive(other.archive), path(other.path), archivePath(other.archivePath), fd(other.fd), isOpen(other.isOpen), priority(other.priority) {} }; struct ArchiveSession { - ArchiveBase* archive = nullptr; - FSPath path; - bool isOpen; + ArchiveBase* archive = nullptr; + FSPath path; + bool isOpen; - ArchiveSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), path(filePath), isOpen(isOpen) {} + ArchiveSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), path(filePath), isOpen(isOpen) {} }; struct DirectoryEntry { @@ -156,106 +158,104 @@ struct DirectorySession { using FileDescriptor = std::optional; class ArchiveBase { -public: - struct FormatInfo { - u32 size; // Archive size - u32 numOfDirectories; // Number of directories - u32 numOfFiles; // Number of files - bool duplicateData; // Whether to duplicate data or not - }; - -protected: - using Handle = u32; - - static constexpr FileDescriptor NoFile = nullptr; - static constexpr FileDescriptor FileError = std::nullopt; - Memory& mem; - - // Returns if a specified 3DS path in UTF16 or ASCII format is safe or not - // A 3DS path is considered safe if its first character is '/' which means we're not trying to access anything outside the root of the fs - // And if it doesn't contain enough instances of ".." (Indicating "climb up a folder" in filesystems) to let the software climb up the directory tree - // And access files outside of the emulator's app data folder - template - bool isPathSafe(const FSPath& path) { - static_assert(format == PathType::ASCII || format == PathType::UTF16); - using String = typename std::conditional::type; // String type for the path - using Char = typename String::value_type; // Char type for the path - - String pathString, dots; - if constexpr (std::is_same()) { - pathString = path.utf16_string; - dots = u".."; - } else { - pathString = path.string; - dots = ".."; - } - - // If the path string doesn't begin with / then that means it's accessing outside the FS root, which is invalid & unsafe - if (pathString[0] != Char('/')) return false; - - // Counts how many folders sans the root our file is nested under. - // If it's < 0 at any point of parsing, then the path is unsafe and tries to crawl outside our file sandbox. - // If it's 0 then this is the FS root. - // If it's > 0 then we're in a subdirectory of the root. - int level = 0; - - // Split the string on / characters and see how many of the substrings are ".." - size_t pos = 0; - while ((pos = pathString.find(Char('/'))) != String::npos) { - String token = pathString.substr(0, pos); - pathString.erase(0, pos + 1); - - if (token == dots) { - level--; - if (level < 0) return false; - } else { - level++; - } - } - - return true; - } - -public: - virtual std::string name() = 0; - virtual u64 getFreeBytes() = 0; - virtual HorizonResult createFile(const FSPath& path, u64 size) = 0; - virtual HorizonResult deleteFile(const FSPath& path) = 0; - - virtual Rust::Result getFormatInfo(const FSPath& path) { - Helpers::panic("Unimplemented GetFormatInfo for %s archive", name().c_str()); - // Return a dummy struct just to avoid the UB of not returning anything, even if we panic - return Ok(FormatInfo{ .size = 0, .numOfDirectories = 0, .numOfFiles = 0, .duplicateData = false }); - } - - virtual HorizonResult createDirectory(const FSPath& path) { - Helpers::panic("Unimplemented CreateDirectory for %s archive", name().c_str()); - return Result::FS::AlreadyExists; - } - - // Returns nullopt if opening the file failed, otherwise returns a file descriptor to it (nullptr if none is needed) - virtual FileDescriptor openFile(const FSPath& path, const FilePerms& perms) = 0; - virtual Rust::Result openArchive(const FSPath& path) = 0; - - virtual Rust::Result openDirectory(const FSPath& path) { - Helpers::panic("Unimplemented OpenDirectory for %s archive", name().c_str()); - return Err(Result::FS::FileNotFoundAlt); - } - - virtual void format(const FSPath& path, const FormatInfo& info) { - Helpers::panic("Unimplemented Format for %s archive", name().c_str()); - } - - virtual HorizonResult renameFile(const FSPath& oldPath, const FSPath& newPath) { + public: + struct FormatInfo { + u32 size; // Archive size + u32 numOfDirectories; // Number of directories + u32 numOfFiles; // Number of files + bool duplicateData; // Whether to duplicate data or not + }; + + protected: + using Handle = u32; + + static constexpr FileDescriptor NoFile = nullptr; + static constexpr FileDescriptor FileError = std::nullopt; + Memory& mem; + + // Returns if a specified 3DS path in UTF16 or ASCII format is safe or not + // A 3DS path is considered safe if its first character is '/' which means we're not trying to access anything outside the root of the fs + // And if it doesn't contain enough instances of ".." (Indicating "climb up a folder" in filesystems) to let the software climb up the directory + // tree And access files outside of the emulator's app data folder + template + bool isPathSafe(const FSPath& path) { + static_assert(format == PathType::ASCII || format == PathType::UTF16); + using String = typename std::conditional::type; // String type for the path + using Char = typename String::value_type; // Char type for the path + + String pathString, dots; + if constexpr (std::is_same()) { + pathString = path.utf16_string; + dots = u".."; + } else { + pathString = path.string; + dots = ".."; + } + + // If the path string doesn't begin with / then that means it's accessing outside the FS root, which is invalid & unsafe + if (pathString[0] != Char('/')) return false; + + // Counts how many folders sans the root our file is nested under. + // If it's < 0 at any point of parsing, then the path is unsafe and tries to crawl outside our file sandbox. + // If it's 0 then this is the FS root. + // If it's > 0 then we're in a subdirectory of the root. + int level = 0; + + // Split the string on / characters and see how many of the substrings are ".." + size_t pos = 0; + while ((pos = pathString.find(Char('/'))) != String::npos) { + String token = pathString.substr(0, pos); + pathString.erase(0, pos + 1); + + if (token == dots) { + level--; + if (level < 0) return false; + } else { + level++; + } + } + + return true; + } + + public: + virtual std::string name() = 0; + virtual u64 getFreeBytes() = 0; + virtual HorizonResult createFile(const FSPath& path, u64 size) = 0; + virtual HorizonResult deleteFile(const FSPath& path) = 0; + + virtual Rust::Result getFormatInfo(const FSPath& path) { + Helpers::panic("Unimplemented GetFormatInfo for %s archive", name().c_str()); + // Return a dummy struct just to avoid the UB of not returning anything, even if we panic + return Ok(FormatInfo{.size = 0, .numOfDirectories = 0, .numOfFiles = 0, .duplicateData = false}); + } + + virtual HorizonResult createDirectory(const FSPath& path) { + Helpers::panic("Unimplemented CreateDirectory for %s archive", name().c_str()); + return Result::FS::AlreadyExists; + } + + // Returns nullopt if opening the file failed, otherwise returns a file descriptor to it (nullptr if none is needed) + virtual FileDescriptor openFile(const FSPath& path, const FilePerms& perms) = 0; + virtual Rust::Result openArchive(const FSPath& path) = 0; + + virtual Rust::Result openDirectory(const FSPath& path) { + Helpers::panic("Unimplemented OpenDirectory for %s archive", name().c_str()); + return Err(Result::FS::FileNotFoundAlt); + } + + virtual void format(const FSPath& path, const FormatInfo& info) { Helpers::panic("Unimplemented Format for %s archive", name().c_str()); } + + virtual HorizonResult renameFile(const FSPath& oldPath, const FSPath& newPath) { Helpers::panic("Unimplemented RenameFile for %s archive", name().c_str()); return Result::Success; - } + } - // Read size bytes from a file starting at offset "offset" into a certain buffer in memory - // Returns the number of bytes read, or nullopt if the read failed - virtual std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) = 0; + // Read size bytes from a file starting at offset "offset" into a certain buffer in memory + // Returns the number of bytes read, or nullopt if the read failed + virtual std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) = 0; - ArchiveBase(Memory& mem) : mem(mem) {} + ArchiveBase(Memory& mem) : mem(mem) {} }; struct ArchiveResource { diff --git a/include/fs/archive_twl_photo.hpp b/include/fs/archive_twl_photo.hpp new file mode 100644 index 000000000..23111e2b2 --- /dev/null +++ b/include/fs/archive_twl_photo.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "archive_base.hpp" +#include "result/result.hpp" + +using Result::HorizonResult; + +class TWLPhotoArchive : public ArchiveBase { + public: + TWLPhotoArchive(Memory& mem) : ArchiveBase(mem) {} + std::string name() override { return "TWL_PHOTO"; } + + u64 getFreeBytes() override { + Helpers::warn("Unimplemented GetFreeBytes for TWLPhoto archive"); + return 32_MB; + } + + HorizonResult createDirectory(const FSPath& path) override; + HorizonResult createFile(const FSPath& path, u64 size) override; + HorizonResult deleteFile(const FSPath& path) override; + + Rust::Result openArchive(const FSPath& path) override; + Rust::Result openDirectory(const FSPath& path) override; + + FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override; + + std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override { + Helpers::panic("Unimplemented ReadFile for TWL_PHOTO archive"); + return {}; + }; +}; \ No newline at end of file diff --git a/include/services/fs.hpp b/include/services/fs.hpp index 3b3b3d44b..a2b64554b 100644 --- a/include/services/fs.hpp +++ b/include/services/fs.hpp @@ -6,6 +6,7 @@ #include "fs/archive_sdmc.hpp" #include "fs/archive_self_ncch.hpp" #include "fs/archive_system_save_data.hpp" +#include "fs/archive_twl_photo.hpp" #include "fs/archive_user_save_data.hpp" #include "helpers.hpp" #include "kernel_types.hpp" @@ -39,6 +40,8 @@ class FSService { ExtSaveDataArchive sharedExtSaveData_nand; SystemSaveDataArchive systemSaveData; + TWLPhotoArchive twlPhoto; + ArchiveBase* getArchiveFromID(u32 id, const FSPath& archivePath); Rust::Result openArchiveHandle(u32 archiveID, const FSPath& path); Rust::Result openDirectoryHandle(ArchiveBase* archive, const FSPath& path); @@ -87,7 +90,7 @@ class FSService { FSService(Memory& mem, Kernel& kernel, const EmulatorConfig& config) : mem(mem), saveData(mem), sharedExtSaveData_nand(mem, "../SharedFiles/NAND", true), extSaveData_sdmc(mem, "SDMC"), sdmc(mem), sdmcWriteOnly(mem, true), selfNcch(mem), ncch(mem), userSaveData1(mem, ArchiveID::UserSaveData1), - userSaveData2(mem, ArchiveID::UserSaveData2), kernel(kernel), config(config), systemSaveData(mem) {} + userSaveData2(mem, ArchiveID::UserSaveData2), systemSaveData(mem), twlPhoto(mem), kernel(kernel), config(config) {} void reset(); void handleSyncRequest(u32 messagePointer); diff --git a/src/core/fs/archive_system_save_data.cpp b/src/core/fs/archive_system_save_data.cpp index 37afb431f..7cb454a25 100644 --- a/src/core/fs/archive_system_save_data.cpp +++ b/src/core/fs/archive_system_save_data.cpp @@ -87,7 +87,7 @@ HorizonResult SystemSaveDataArchive::createFile(const FSPath& path, u64 size) { HorizonResult SystemSaveDataArchive::createDirectory(const FSPath& path) { if (path.type == PathType::UTF16) { if (!isPathSafe(path)) { - Helpers::panic("Unsafe path in SystemSaveData::OpenFile"); + Helpers::panic("Unsafe path in SystemSaveData::CreateDirectory"); } fs::path p = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData"; diff --git a/src/core/fs/archive_twl_photo.cpp b/src/core/fs/archive_twl_photo.cpp new file mode 100644 index 000000000..a1833c5cf --- /dev/null +++ b/src/core/fs/archive_twl_photo.cpp @@ -0,0 +1,40 @@ +#include +#include + +#include "fs/archive_twl_photo.hpp" + +namespace fs = std::filesystem; + +HorizonResult TWLPhotoArchive::createFile(const FSPath& path, u64 size) { + Helpers::panic("[TWL_PHOTO] CreateFile not yet supported"); + return Result::Success; +} + +HorizonResult TWLPhotoArchive::deleteFile(const FSPath& path) { + Helpers::panic("[TWL_PHOTO] Unimplemented DeleteFile"); + return Result::Success; +} + +HorizonResult TWLPhotoArchive::createDirectory(const FSPath& path) { + Helpers::panic("[TWL_PHOTO] CreateDirectory not yet supported"); + return Result::Success; +} + +FileDescriptor TWLPhotoArchive::openFile(const FSPath& path, const FilePerms& perms) { + Helpers::panic("[TWL_PHOTO] OpenFile not yet supported"); + return FileError; +} + +Rust::Result TWLPhotoArchive::openArchive(const FSPath& path) { + if (path.type != PathType::Empty) { + Helpers::panic("Unimplemented path type for TWLPhotoArchive::OpenArchive"); + } + + Helpers::warn("Unimplemented: TWL_PHOTO archive"); + return Err(Result::FailurePlaceholder); +} + +Rust::Result TWLPhotoArchive::openDirectory(const FSPath& path) { + Helpers::panic("[TWL_PHOTO] OpenDirectory not yet supported"); + return Err(Result::FailurePlaceholder); +} diff --git a/src/core/services/fs.cpp b/src/core/services/fs.cpp index e81db6cd3..483884f4d 100644 --- a/src/core/services/fs.cpp +++ b/src/core/services/fs.cpp @@ -99,6 +99,9 @@ ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) { case ArchiveID::SDMC: return &sdmc; case ArchiveID::SDMCWriteOnly: return &sdmcWriteOnly; case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI + + case ArchiveID::TwlPhoto: return &twlPhoto; + default: Helpers::panic("Unknown archive. ID: %d\n", id); return nullptr; From 055dbc7fb69528476cd83fd234550b95ed8bb509 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 8 Dec 2024 22:49:46 +0200 Subject: [PATCH 2/2] FS: Stub TWL_SOUND --- CMakeLists.txt | 3 ++- include/fs/archive_base.hpp | 4 +++- include/fs/archive_twl_sound.hpp | 30 +++++++++++++++++++++++ include/services/fs.hpp | 4 +++- src/core/fs/archive_twl_sound.cpp | 40 +++++++++++++++++++++++++++++++ src/core/services/fs.cpp | 1 + 6 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 include/fs/archive_twl_sound.hpp create mode 100644 src/core/fs/archive_twl_sound.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 010e991d7..c5ac456e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -338,7 +338,7 @@ set(LOADER_SOURCE_FILES src/core/loader/elf.cpp src/core/loader/ncsd.cpp src/cor set(FS_SOURCE_FILES src/core/fs/archive_self_ncch.cpp src/core/fs/archive_save_data.cpp src/core/fs/archive_sdmc.cpp src/core/fs/archive_ext_save_data.cpp src/core/fs/archive_ncch.cpp src/core/fs/romfs.cpp src/core/fs/ivfc.cpp src/core/fs/archive_user_save_data.cpp src/core/fs/archive_system_save_data.cpp - src/core/fs/archive_twl_photo.cpp + src/core/fs/archive_twl_photo.cpp src/core/fs/archive_twl_sound.cpp ) set(APPLET_SOURCE_FILES src/core/applets/applet.cpp src/core/applets/mii_selector.cpp src/core/applets/software_keyboard.cpp src/core/applets/applet_manager.cpp @@ -389,6 +389,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp include/audio/audio_interpolation.hpp include/audio/hle_mixer.hpp include/audio/dsp_simd.hpp include/services/dsp_firmware_db.hpp include/frontend_settings.hpp include/fs/archive_twl_photo.hpp + include/fs/archive_twl_sound.hpp ) cmrc_add_resource_library( diff --git a/include/fs/archive_base.hpp b/include/fs/archive_base.hpp index 2eef4d802..4c42ca021 100644 --- a/include/fs/archive_base.hpp +++ b/include/fs/archive_base.hpp @@ -42,7 +42,8 @@ namespace ArchiveID { // 3DBrew: Similar to 0x567890B2 but can only access Accessible Save specified in exheader? UserSaveData2 = 0x567890B4, - TwlPhoto = 0x567890AC + TwlPhoto = 0x567890AC, + TwlSound = 0x567890AD, }; static std::string toString(u32 id) { @@ -56,6 +57,7 @@ namespace ArchiveID { case SDMCWriteOnly: return "SDMC (Write-only)"; case SavedataAndNcch: return "Savedata & NCCH (archive 0x2345678A)"; case TwlPhoto: return "TWL_PHOTO"; + case TwlSound: return "TWL_SOUND"; default: return "Unknown archive"; } } diff --git a/include/fs/archive_twl_sound.hpp b/include/fs/archive_twl_sound.hpp new file mode 100644 index 000000000..cc8fc866c --- /dev/null +++ b/include/fs/archive_twl_sound.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "archive_base.hpp" +#include "result/result.hpp" + +using Result::HorizonResult; + +class TWLSoundArchive : public ArchiveBase { + public: + TWLSoundArchive(Memory& mem) : ArchiveBase(mem) {} + std::string name() override { return "TWL_SOUND"; } + + u64 getFreeBytes() override { + Helpers::warn("Unimplemented GetFreeBytes for TWLSound archive"); + return 32_MB; + } + + HorizonResult createDirectory(const FSPath& path) override; + HorizonResult createFile(const FSPath& path, u64 size) override; + HorizonResult deleteFile(const FSPath& path) override; + + Rust::Result openArchive(const FSPath& path) override; + Rust::Result openDirectory(const FSPath& path) override; + + FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override; + + std::optional readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override { + Helpers::panic("Unimplemented ReadFile for TWL_SOUND archive"); + return {}; + }; +}; \ No newline at end of file diff --git a/include/services/fs.hpp b/include/services/fs.hpp index a2b64554b..dd115cc41 100644 --- a/include/services/fs.hpp +++ b/include/services/fs.hpp @@ -7,6 +7,7 @@ #include "fs/archive_self_ncch.hpp" #include "fs/archive_system_save_data.hpp" #include "fs/archive_twl_photo.hpp" +#include "fs/archive_twl_sound.hpp" #include "fs/archive_user_save_data.hpp" #include "helpers.hpp" #include "kernel_types.hpp" @@ -41,6 +42,7 @@ class FSService { SystemSaveDataArchive systemSaveData; TWLPhotoArchive twlPhoto; + TWLSoundArchive twlSound; ArchiveBase* getArchiveFromID(u32 id, const FSPath& archivePath); Rust::Result openArchiveHandle(u32 archiveID, const FSPath& path); @@ -90,7 +92,7 @@ class FSService { FSService(Memory& mem, Kernel& kernel, const EmulatorConfig& config) : mem(mem), saveData(mem), sharedExtSaveData_nand(mem, "../SharedFiles/NAND", true), extSaveData_sdmc(mem, "SDMC"), sdmc(mem), sdmcWriteOnly(mem, true), selfNcch(mem), ncch(mem), userSaveData1(mem, ArchiveID::UserSaveData1), - userSaveData2(mem, ArchiveID::UserSaveData2), systemSaveData(mem), twlPhoto(mem), kernel(kernel), config(config) {} + userSaveData2(mem, ArchiveID::UserSaveData2), systemSaveData(mem), twlPhoto(mem), twlSound(mem), kernel(kernel), config(config) {} void reset(); void handleSyncRequest(u32 messagePointer); diff --git a/src/core/fs/archive_twl_sound.cpp b/src/core/fs/archive_twl_sound.cpp new file mode 100644 index 000000000..fbe98caf5 --- /dev/null +++ b/src/core/fs/archive_twl_sound.cpp @@ -0,0 +1,40 @@ +#include +#include + +#include "fs/archive_twl_sound.hpp" + +namespace fs = std::filesystem; + +HorizonResult TWLSoundArchive::createFile(const FSPath& path, u64 size) { + Helpers::panic("[TWL_SOUND] CreateFile not yet supported"); + return Result::Success; +} + +HorizonResult TWLSoundArchive::deleteFile(const FSPath& path) { + Helpers::panic("[TWL_SOUND] Unimplemented DeleteFile"); + return Result::Success; +} + +HorizonResult TWLSoundArchive::createDirectory(const FSPath& path) { + Helpers::panic("[TWL_SOUND] CreateDirectory not yet supported"); + return Result::Success; +} + +FileDescriptor TWLSoundArchive::openFile(const FSPath& path, const FilePerms& perms) { + Helpers::panic("[TWL_SOUND] OpenFile not yet supported"); + return FileError; +} + +Rust::Result TWLSoundArchive::openArchive(const FSPath& path) { + if (path.type != PathType::Empty) { + Helpers::panic("Unimplemented path type for TWLSoundArchive::OpenArchive"); + } + + Helpers::warn("Unimplemented: TWL_SOUND archive"); + return Err(Result::FailurePlaceholder); +} + +Rust::Result TWLSoundArchive::openDirectory(const FSPath& path) { + Helpers::panic("[TWL_SOUND] OpenDirectory not yet supported"); + return Err(Result::FailurePlaceholder); +} diff --git a/src/core/services/fs.cpp b/src/core/services/fs.cpp index 483884f4d..c6c84ae5f 100644 --- a/src/core/services/fs.cpp +++ b/src/core/services/fs.cpp @@ -101,6 +101,7 @@ ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) { case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI case ArchiveID::TwlPhoto: return &twlPhoto; + case ArchiveID::TwlSound: return &twlSound; default: Helpers::panic("Unknown archive. ID: %d\n", id);