[FS] Rehaul to implement all the different things ExtSaveData can target

This commit is contained in:
wheremyfoodat 2023-04-03 01:19:52 +03:00
parent 0f9d94a7d0
commit f90a266bb4
4 changed files with 71 additions and 24 deletions

View file

@ -3,17 +3,20 @@
class ExtSaveDataArchive : public ArchiveBase {
public:
ExtSaveDataArchive(Memory& mem) : ArchiveBase(mem) {}
ExtSaveDataArchive(Memory& mem, const std::string& folder, bool isShared = false) : ArchiveBase(mem),
isShared(isShared), backingFolder(folder) {}
u64 getFreeBytes() override { Helpers::panic("ExtSaveData::GetFreeBytes unimplemented"); return 0; }
std::string name() override { return "ExtSaveData"; }
std::string name() override { return "ExtSaveData::" + backingFolder; }
FSResult createFile(const FSPath& path, u64 size) override;
FSResult deleteFile(const FSPath& path) override;
ArchiveBase* openArchive(const FSPath& path) override;
Rust::Result<DirectorySession, FSResult> openDirectory(const FSPath& path) override;
FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
bool isShared = false;
std::string backingFolder; // Backing folder for the archive. Can be NAND, Gamecard or SD depending on the archive path.
};

View file

@ -22,12 +22,15 @@ class FSService {
// The different filesystem archives (Save data, SelfNCCH, SDMC, NCCH, ExtData, etc)
SelfNCCHArchive selfNcch;
SaveDataArchive saveData;
ExtSaveDataArchive extSaveData;
ExtSaveDataArchive sharedExtSaveData;
SDMCArchive sdmc;
NCCHArchive ncch;
ArchiveBase* getArchiveFromID(u32 id);
ExtSaveDataArchive extSaveData_nand;
ExtSaveDataArchive extSaveData_cart;
ExtSaveDataArchive sharedExtSaveData_nand;
ExtSaveDataArchive sharedExtSaveData_cart;
ArchiveBase* getArchiveFromID(u32 id, const FSPath& archivePath);
std::optional<Handle> openArchiveHandle(u32 archiveID, const FSPath& path);
Rust::Result<Handle, FSResult> openDirectoryHandle(ArchiveBase* archive, const FSPath& path);
std::optional<Handle> openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms);
@ -53,11 +56,10 @@ class FSService {
u32 priority;
public:
FSService(Memory& mem, Kernel& kernel) : mem(mem), saveData(mem), extSaveData(mem), sharedExtSaveData(mem), sdmc(mem),
selfNcch(mem), ncch(mem), kernel(kernel)
{
sharedExtSaveData.isShared = true; // Need to do this here because templates and virtual classes do not mix well
}
FSService(Memory& mem, Kernel& kernel) : mem(mem), saveData(mem), extSaveData_nand(mem, "NAND"),
sharedExtSaveData_nand(mem, "NAND", true), extSaveData_cart(mem, "CartSave"), sharedExtSaveData_cart(mem, "CartSave", true),
sdmc(mem), selfNcch(mem), ncch(mem), kernel(kernel)
{}
void reset();
void handleSyncRequest(u32 messagePointer);

View file

@ -11,7 +11,7 @@ FSResult ExtSaveDataArchive::createFile(const FSPath& path, u64 size) {
if (!isPathSafe<PathType::UTF16>(path))
Helpers::panic("Unsafe path in ExtSaveData::CreateFile");
fs::path p = IOFile::getAppData() / "NAND";
fs::path p = IOFile::getAppData() / backingFolder;
p += fs::path(path.utf16_string).make_preferred();
if (fs::exists(p))
@ -35,7 +35,7 @@ FSResult ExtSaveDataArchive::deleteFile(const FSPath& path) {
if (!isPathSafe<PathType::UTF16>(path))
Helpers::panic("Unsafe path in ExtSaveData::DeleteFile");
fs::path p = IOFile::getAppData() / "NAND";
fs::path p = IOFile::getAppData() / backingFolder;
p += fs::path(path.utf16_string).make_preferred();
std::error_code ec;
@ -55,7 +55,7 @@ FileDescriptor ExtSaveDataArchive::openFile(const FSPath& path, const FilePerms&
if (perms.create())
Helpers::panic("[ExtSaveData] Can't open file with create flag");
fs::path p = IOFile::getAppData() / "NAND";
fs::path p = IOFile::getAppData() / backingFolder;
p += fs::path(path.utf16_string).make_preferred();
if (fs::exists(p)) { // Return file descriptor if the file exists
@ -75,11 +75,33 @@ ArchiveBase* ExtSaveDataArchive::openArchive(const FSPath& path) {
Helpers::panic("ExtSaveData accessed with an invalid path in OpenArchive");
}
if (path.binary[0] != 0) Helpers::panic("ExtSaveData: Tried to access something other than NAND. ID: %02X", path.binary[0]);
return this;
}
Rust::Result<DirectorySession, FSResult> ExtSaveDataArchive::openDirectory(const FSPath& path) {
if (path.type == PathType::UTF16) {
if (!isPathSafe<PathType::UTF16>(path))
Helpers::panic("Unsafe path in ExtSaveData::OpenDirectory");
fs::path p = IOFile::getAppData() / backingFolder;
p += fs::path(path.utf16_string).make_preferred();
if (fs::is_regular_file(p)) {
printf("ExtSaveData: OpenArchive used with a file path");
return Err(FSResult::UnexpectedFileOrDir);
}
if (fs::is_directory(p)) {
return Ok(DirectorySession(this, p));
} else {
return Err(FSResult::FileNotFound);
}
}
Helpers::panic("ExtSaveDataArchive::OpenDirectory: Unimplemented path type");
return Err(FSResult::Success);
}
std::optional<u32> ExtSaveDataArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) {
Helpers::panic("ExtSaveDataArchive::ReadFile: Failed");
return std::nullopt;

View file

@ -41,6 +41,7 @@ void FSService::reset() {
// Creates directories for NAND, ExtSaveData, etc if they don't already exist. Should be executed after loading a new ROM.
void FSService::initializeFilesystem() {
const auto nandPath = IOFile::getAppData() / "NAND"; // Create NAND
const auto cartPath = IOFile::getAppData() / "CartSave"; // Create cartridge save folder for use with ExtSaveData
const auto savePath = IOFile::getAppData() / "SaveData"; // Create SaveData
namespace fs = std::filesystem;
// TODO: SDMC, etc
@ -49,17 +50,37 @@ void FSService::initializeFilesystem() {
fs::create_directories(nandPath);
}
if (!fs::is_directory(cartPath)) {
fs::create_directories(cartPath);
}
if (!fs::is_directory(savePath)) {
fs::create_directories(savePath);
}
}
ArchiveBase* FSService::getArchiveFromID(u32 id) {
ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {
switch (id) {
case ArchiveID::SelfNCCH: return &selfNcch;
case ArchiveID::SaveData: return &saveData;
case ArchiveID::ExtSaveData: return &extSaveData;
case ArchiveID::SharedExtSaveData: return &sharedExtSaveData;
case ArchiveID::ExtSaveData:
if (archivePath.type == PathType::Binary) {
switch (archivePath.binary[0]) {
case 0: return &extSaveData_nand;
case 1: return &extSaveData_cart;
}
}
return nullptr;
case ArchiveID::SharedExtSaveData:
if (archivePath.type == PathType::Binary) {
switch (archivePath.binary[0]) {
case 0: return &sharedExtSaveData_nand;
case 1: return &sharedExtSaveData_cart;
}
}
return nullptr;
case ArchiveID::SDMC: return &sdmc;
case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI
default:
@ -96,7 +117,7 @@ Rust::Result<Handle, FSResult> FSService::openDirectoryHandle(ArchiveBase* archi
}
std::optional<Handle> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) {
ArchiveBase* archive = getArchiveFromID(archiveID);
ArchiveBase* archive = getArchiveFromID(archiveID, path);
if (archive == nullptr) [[unlikely]] {
Helpers::panic("OpenArchive: Tried to open unknown archive %d.", archiveID);
@ -264,15 +285,14 @@ void FSService::openFileDirectly(u32 messagePointer) {
const u32 attributes = mem.read32(messagePointer + 32);
const u32 archivePathPointer = mem.read32(messagePointer + 40);
const u32 filePathPointer = mem.read32(messagePointer + 48);
log("FS::OpenFileDirectly\n");
ArchiveBase* archive = getArchiveFromID(archiveID);
auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
ArchiveBase* archive = getArchiveFromID(archiveID, archivePath);
if (archive == nullptr) [[unlikely]] {
Helpers::panic("OpenFileDirectly: Tried to open unknown archive %d.", archiveID);
}
auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
auto filePath = readPath(filePathType, filePathPointer, filePathSize);
const FilePerms perms(openFlags);
@ -344,7 +364,7 @@ void FSService::getFormatInfo(u32 messagePointer) {
const auto path = readPath(pathType, pathPointer, pathSize);
log("FS::GetFormatInfo(archive ID = %d, archive path type = %d)\n", archiveID, pathType);
ArchiveBase* archive = getArchiveFromID(archiveID);
ArchiveBase* archive = getArchiveFromID(archiveID, path);
if (archive == nullptr) [[unlikely]] {
Helpers::panic("OpenArchive: Tried to open unknown archive %d.", archiveID);
}