From deaf7d518cfecdac83dc323a2b3e552bd944d013 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Sat, 14 Jan 2023 01:46:48 +0200 Subject: [PATCH] [FS] More concrete path impl --- include/fs/archive_base.hpp | 39 ++++++++++++++++++++------- include/services/fs.hpp | 1 + src/core/fs/archive_ext_save_data.cpp | 6 ++--- src/core/fs/archive_ncch.cpp | 8 +++--- src/core/fs/archive_save_data.cpp | 4 +-- src/core/services/fs.cpp | 18 ++++++++++--- 6 files changed, 55 insertions(+), 21 deletions(-) diff --git a/include/fs/archive_base.hpp b/include/fs/archive_base.hpp index 4bd267fe..5fcc37f9 100644 --- a/include/fs/archive_base.hpp +++ b/include/fs/archive_base.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "helpers.hpp" #include "memory.hpp" @@ -40,9 +41,33 @@ namespace ArchiveID { } struct FSPath { - u32 type; - u32 size; - u32 pointer; // Pointer to the actual path data + 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, 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; + } +; } + } }; class ArchiveBase; @@ -52,9 +77,7 @@ struct FileSession { FSPath path; bool isOpen; - FileSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), isOpen(isOpen) { - path = filePath; - } + FileSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), path(path), isOpen(isOpen) {} }; struct ArchiveSession { @@ -62,9 +85,7 @@ struct ArchiveSession { FSPath path; bool isOpen; - ArchiveSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), isOpen(isOpen) { - path = filePath; - } + ArchiveSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), path(path), isOpen(isOpen) {} }; class ArchiveBase { diff --git a/include/services/fs.hpp b/include/services/fs.hpp index 8dcfc854..fbfc141a 100644 --- a/include/services/fs.hpp +++ b/include/services/fs.hpp @@ -27,6 +27,7 @@ class FSService { ArchiveBase* getArchiveFromID(u32 id); std::optional openArchiveHandle(u32 archiveID, const FSPath& path); std::optional openFileHandle(ArchiveBase* archive, const FSPath& path); + FSPath readPath(u32 type, u32 pointer, u32 size); // Service commands void closeArchive(u32 messagePointer); diff --git a/src/core/fs/archive_ext_save_data.cpp b/src/core/fs/archive_ext_save_data.cpp index ea7adf61..ad68ef38 100644 --- a/src/core/fs/archive_ext_save_data.cpp +++ b/src/core/fs/archive_ext_save_data.cpp @@ -11,12 +11,12 @@ bool ExtSaveDataArchive::openFile(const FSPath& path) { } ArchiveBase* ExtSaveDataArchive::openArchive(const FSPath& path) { - if (path.type != PathType::Binary || path.size != 12) { + if (path.type != PathType::Binary || path.binary.size() != 12) { Helpers::panic("ExtSaveData accessed with an invalid path in OpenArchive"); } - u32 mediaType = mem.read32(path.pointer); - u64 saveID = mem.read64(path.pointer + 4); + u32 mediaType = *(u32*)&path.binary[0]; + u64 saveID = *(u64*)&path.binary[4]; // TODO: Get rid of UB here. Helpers::panic("ExtSaveData: media type = %d\n", mediaType); diff --git a/src/core/fs/archive_ncch.cpp b/src/core/fs/archive_ncch.cpp index e91333ae..9514de94 100644 --- a/src/core/fs/archive_ncch.cpp +++ b/src/core/fs/archive_ncch.cpp @@ -7,13 +7,15 @@ bool SelfNCCHArchive::openFile(const FSPath& path) { return false; } - if (path.type != PathType::Binary) { + if (path.type != PathType::Binary || path.binary.size() != 12) { printf("Invalid SelfNCCH path type\n"); return false; } - // We currently only know how to read from an NCCH's RomFS - if (mem.read32(path.pointer) != 0) { + // Where to read the file from. (https://www.3dbrew.org/wiki/Filesystem_services#SelfNCCH_File_Path_Data_Format) + // We currently only know how to read from an NCCH's RomFS, ie type = 0 + const u32 type = *(u32*)&path.binary[0]; // TODO: Get rid of UB here + if (type != 0) { Helpers::panic("Read from NCCH's non-RomFS section!"); } diff --git a/src/core/fs/archive_save_data.cpp b/src/core/fs/archive_save_data.cpp index 451d7972..071d5264 100644 --- a/src/core/fs/archive_save_data.cpp +++ b/src/core/fs/archive_save_data.cpp @@ -8,8 +8,8 @@ bool SaveDataArchive::openFile(const FSPath& path) { return false; } - if (path.type == PathType::UTF16 && mem.readString(path.pointer, path.size) == "/") { - printf("Reading root save data dir\n"); + if (path.type == PathType::UTF16 /* && path.utf16_string == u"/game_header" */) { + printf("Opened file from the SaveData archive \n"); return true; } diff --git a/src/core/services/fs.cpp b/src/core/services/fs.cpp index 361aa64b..2a0df4e5 100644 --- a/src/core/services/fs.cpp +++ b/src/core/services/fs.cpp @@ -72,6 +72,16 @@ std::optional FSService::openArchiveHandle(u32 archiveID, const FSPath& } } +FSPath FSService::readPath(u32 type, u32 pointer, u32 size) { + std::vector data; + data.resize(size); + + for (u32 i = 0; i < size; i++) + data[i] = mem.read8(pointer + i); + + return FSPath(type, data); +} + void FSService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { @@ -120,8 +130,8 @@ void FSService::openArchive(u32 messagePointer) { const u32 archivePathType = mem.read32(messagePointer + 8); const u32 archivePathSize = mem.read32(messagePointer + 12); const u32 archivePathPointer = mem.read32(messagePointer + 20); - FSPath archivePath{ .type = archivePathType, .size = archivePathSize, .pointer = archivePathPointer }; + auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize); log("FS::OpenArchive(archive ID = %d, archive path type = %d)\n", archiveID, archivePathType); std::optional handle = openArchiveHandle(archiveID, archivePath); @@ -152,7 +162,7 @@ void FSService::openFile(u32 messagePointer) { } ArchiveBase* archive = archiveObject->getData()->archive; - FSPath filePath{ .type = filePathType, .size = filePathSize, .pointer = filePathPointer }; + auto filePath = readPath(filePathType, filePathPointer, filePathSize); std::optional handle = openFileHandle(archive, filePath); if (!handle.has_value()) { @@ -183,8 +193,8 @@ void FSService::openFileDirectly(u32 messagePointer) { Helpers::panic("OpenFileDirectly: Tried to open unknown archive %d.", archiveID); } - FSPath archivePath { .type = archivePathType, .size = archivePathSize, .pointer = archivePathPointer }; - FSPath filePath { .type = filePathType, .size = filePathSize, .pointer = filePathPointer }; + auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize); + auto filePath = readPath(filePathType, filePathPointer, filePathSize); archive = archive->openArchive(archivePath); if (archive == nullptr) [[unlikely]] {