[FS] More concrete path impl

This commit is contained in:
wheremyfoodat 2023-01-14 01:46:48 +02:00
parent 1730ab9734
commit deaf7d518c
6 changed files with 55 additions and 21 deletions

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <optional> #include <optional>
#include <string> #include <string>
#include <vector>
#include "helpers.hpp" #include "helpers.hpp"
#include "memory.hpp" #include "memory.hpp"
@ -40,9 +41,33 @@ namespace ArchiveID {
} }
struct FSPath { struct FSPath {
u32 type; u32 type = PathType::Invalid;
u32 size;
u32 pointer; // Pointer to the actual path data std::vector<u8> binary; // Path data for binary paths
std::string string; // Path data for ASCII paths
std::u16string utf16_string;
FSPath() {}
FSPath(u32 type, std::vector<u8> 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; class ArchiveBase;
@ -52,9 +77,7 @@ struct FileSession {
FSPath path; FSPath path;
bool isOpen; bool isOpen;
FileSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), isOpen(isOpen) { FileSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), path(path), isOpen(isOpen) {}
path = filePath;
}
}; };
struct ArchiveSession { struct ArchiveSession {
@ -62,9 +85,7 @@ struct ArchiveSession {
FSPath path; FSPath path;
bool isOpen; bool isOpen;
ArchiveSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), isOpen(isOpen) { ArchiveSession(ArchiveBase* archive, const FSPath& filePath, bool isOpen = true) : archive(archive), path(path), isOpen(isOpen) {}
path = filePath;
}
}; };
class ArchiveBase { class ArchiveBase {

View file

@ -27,6 +27,7 @@ class FSService {
ArchiveBase* getArchiveFromID(u32 id); ArchiveBase* getArchiveFromID(u32 id);
std::optional<Handle> openArchiveHandle(u32 archiveID, const FSPath& path); std::optional<Handle> openArchiveHandle(u32 archiveID, const FSPath& path);
std::optional<Handle> openFileHandle(ArchiveBase* archive, const FSPath& path); std::optional<Handle> openFileHandle(ArchiveBase* archive, const FSPath& path);
FSPath readPath(u32 type, u32 pointer, u32 size);
// Service commands // Service commands
void closeArchive(u32 messagePointer); void closeArchive(u32 messagePointer);

View file

@ -11,12 +11,12 @@ bool ExtSaveDataArchive::openFile(const FSPath& path) {
} }
ArchiveBase* ExtSaveDataArchive::openArchive(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"); Helpers::panic("ExtSaveData accessed with an invalid path in OpenArchive");
} }
u32 mediaType = mem.read32(path.pointer); u32 mediaType = *(u32*)&path.binary[0];
u64 saveID = mem.read64(path.pointer + 4); u64 saveID = *(u64*)&path.binary[4]; // TODO: Get rid of UB here.
Helpers::panic("ExtSaveData: media type = %d\n", mediaType); Helpers::panic("ExtSaveData: media type = %d\n", mediaType);

View file

@ -7,13 +7,15 @@ bool SelfNCCHArchive::openFile(const FSPath& path) {
return false; return false;
} }
if (path.type != PathType::Binary) { if (path.type != PathType::Binary || path.binary.size() != 12) {
printf("Invalid SelfNCCH path type\n"); printf("Invalid SelfNCCH path type\n");
return false; return false;
} }
// We currently only know how to read from an NCCH's RomFS // Where to read the file from. (https://www.3dbrew.org/wiki/Filesystem_services#SelfNCCH_File_Path_Data_Format)
if (mem.read32(path.pointer) != 0) { // 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!"); Helpers::panic("Read from NCCH's non-RomFS section!");
} }

View file

@ -8,8 +8,8 @@ bool SaveDataArchive::openFile(const FSPath& path) {
return false; return false;
} }
if (path.type == PathType::UTF16 && mem.readString(path.pointer, path.size) == "/") { if (path.type == PathType::UTF16 /* && path.utf16_string == u"/game_header" */) {
printf("Reading root save data dir\n"); printf("Opened file from the SaveData archive \n");
return true; return true;
} }

View file

@ -72,6 +72,16 @@ std::optional<Handle> FSService::openArchiveHandle(u32 archiveID, const FSPath&
} }
} }
FSPath FSService::readPath(u32 type, u32 pointer, u32 size) {
std::vector<u8> 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) { void FSService::handleSyncRequest(u32 messagePointer) {
const u32 command = mem.read32(messagePointer); const u32 command = mem.read32(messagePointer);
switch (command) { switch (command) {
@ -120,8 +130,8 @@ void FSService::openArchive(u32 messagePointer) {
const u32 archivePathType = mem.read32(messagePointer + 8); const u32 archivePathType = mem.read32(messagePointer + 8);
const u32 archivePathSize = mem.read32(messagePointer + 12); const u32 archivePathSize = mem.read32(messagePointer + 12);
const u32 archivePathPointer = mem.read32(messagePointer + 20); 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); log("FS::OpenArchive(archive ID = %d, archive path type = %d)\n", archiveID, archivePathType);
std::optional<Handle> handle = openArchiveHandle(archiveID, archivePath); std::optional<Handle> handle = openArchiveHandle(archiveID, archivePath);
@ -152,7 +162,7 @@ void FSService::openFile(u32 messagePointer) {
} }
ArchiveBase* archive = archiveObject->getData<ArchiveSession>()->archive; ArchiveBase* archive = archiveObject->getData<ArchiveSession>()->archive;
FSPath filePath{ .type = filePathType, .size = filePathSize, .pointer = filePathPointer }; auto filePath = readPath(filePathType, filePathPointer, filePathSize);
std::optional<Handle> handle = openFileHandle(archive, filePath); std::optional<Handle> handle = openFileHandle(archive, filePath);
if (!handle.has_value()) { if (!handle.has_value()) {
@ -183,8 +193,8 @@ void FSService::openFileDirectly(u32 messagePointer) {
Helpers::panic("OpenFileDirectly: Tried to open unknown archive %d.", archiveID); Helpers::panic("OpenFileDirectly: Tried to open unknown archive %d.", archiveID);
} }
FSPath archivePath { .type = archivePathType, .size = archivePathSize, .pointer = archivePathPointer }; auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
FSPath filePath { .type = filePathType, .size = filePathSize, .pointer = filePathPointer }; auto filePath = readPath(filePathType, filePathPointer, filePathSize);
archive = archive->openArchive(archivePath); archive = archive->openArchive(archivePath);
if (archive == nullptr) [[unlikely]] { if (archive == nullptr) [[unlikely]] {