[FS] Formatting archives v1

This commit is contained in:
wheremyfoodat 2023-05-16 23:37:52 +03:00
parent 2f5bb45d58
commit 4dc04be350
6 changed files with 67 additions and 4 deletions

View file

@ -224,6 +224,10 @@ public:
return Err(FSResult::FileNotFound);
}
virtual void format(const FSPath& path, const FormatInfo& info) {
Helpers::panic("Unimplemented Format for %s archive", name().c_str());
}
// 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<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) = 0;

View file

@ -17,6 +17,10 @@ public:
FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
// Takes in a binary ExtSaveData path, outputs a combination of the backing folder with the low and high save entries of the path
// Used for identifying the archive format info files
std::string getExtSaveDataPathFromBinary(const FSPath& path);
bool isShared = false;
std::string backingFolder; // Backing folder for the archive. Can be NAND, Gamecard or SD depending on the archive path.
};

View file

@ -11,13 +11,19 @@ public:
FSResult createDirectory(const FSPath& path) override;
FSResult createFile(const FSPath& path, u64 size) override;
FSResult deleteFile(const FSPath& path) override;
FormatInfo getFormatInfo(const FSPath& path) override;
Rust::Result<ArchiveBase*, FSResult> 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;
void format(const FSPath& path, const FormatInfo& info) override;
FormatInfo getFormatInfo(const FSPath& path) override;
std::filesystem::path getFormatInfoPath() {
return IOFile::getAppData() / "FormatInfo" / "SaveData.format";
}
// Returns whether the cart has save data or not
bool cartHasSaveData() {
auto cxi = mem.getCXI();

View file

@ -70,11 +70,28 @@ FileDescriptor ExtSaveDataArchive::openFile(const FSPath& path, const FilePerms&
return FileError;
}
std::string ExtSaveDataArchive::getExtSaveDataPathFromBinary(const FSPath& path) {
// TODO: Remove punning here
const u32 mediaType = *(u32*)&path.binary[0];
const u32 saveLow = *(u32*)&path.binary[4];
const u32 saveHigh = *(u32*)&path.binary[8];
// TODO: Should the media type be used here
return backingFolder + std::to_string(saveLow) + std::to_string(saveHigh);
}
Rust::Result<ArchiveBase*, FSResult> ExtSaveDataArchive::openArchive(const FSPath& path) {
if (path.type != PathType::Binary || path.binary.size() != 12) {
Helpers::panic("ExtSaveData accessed with an invalid path in OpenArchive");
}
// Create a format info path in the style of AppData/FormatInfo/Cartridge10390390194.format
fs::path formatInfopath = IOFile::getAppData() / "FormatInfo" / (getExtSaveDataPathFromBinary(path) + ".format");
// Format info not found so the archive is not formatted
if (!fs::is_regular_file(formatInfopath)) {
return isShared ? Err(FSResult::NotFormatted) : Err(FSResult::NotFoundInvalid);
}
return Ok((ArchiveBase*)this);
}

View file

@ -94,8 +94,20 @@ Rust::Result<DirectorySession, FSResult> SaveDataArchive::openDirectory(const FS
}
ArchiveBase::FormatInfo SaveDataArchive::getFormatInfo(const FSPath& path) {
//Helpers::panic("Unimplemented SaveData::GetFormatInfo");
return FormatInfo{ .size = 0, .numOfDirectories = 255, .numOfFiles = 255, .duplicateData = false };
Helpers::panic("Unimplemented SaveData::GetFormatInfo");
}
void SaveDataArchive::format(const FSPath& path, const ArchiveBase::FormatInfo& info) {
const fs::path saveDataPath = IOFile::getAppData() / "SaveData";
const fs::path formatInfoPath = getFormatInfoPath();
// Delete all contents by deleting the directory then recreating it
fs::remove_all(saveDataPath);
fs::create_directories(saveDataPath);
// Write format info on disk
IOFile file(formatInfoPath, "wb");
file.writeBytes(&info, sizeof(info));
}
Rust::Result<ArchiveBase*, FSResult> SaveDataArchive::openArchive(const FSPath& path) {
@ -104,6 +116,12 @@ Rust::Result<ArchiveBase*, FSResult> SaveDataArchive::openArchive(const FSPath&
return Err(FSResult::NotFoundInvalid);
}
const fs::path formatInfoPath = getFormatInfoPath();
// Format info not found so the archive is not formatted
if (!fs::is_regular_file(formatInfoPath)) {
return Err(FSResult::NotFormatted);
}
return Ok((ArchiveBase*)this);
}

View file

@ -48,6 +48,7 @@ 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
const auto formatPath = IOFile::getAppData() / "FormatInfo"; // Create folder for storing archive formatting info
namespace fs = std::filesystem;
// TODO: SDMC, etc
@ -62,6 +63,10 @@ void FSService::initializeFilesystem() {
if (!fs::is_directory(savePath)) {
fs::create_directories(savePath);
}
if (!fs::is_directory(formatPath)) {
fs::create_directories(formatPath);
}
}
ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {
@ -440,9 +445,18 @@ void FSService::formatSaveData(u32 messagePointer) {
const u32 fileNum = mem.read32(messagePointer + 24); // Max number of files
const u32 directoryBucketNum = mem.read32(messagePointer + 28); // Not sure what a directory bucket is...?
const u32 fileBucketNum = mem.read32(messagePointer + 32); // Same here
const bool duplicateData = mem.read8(messagePointer + 36) != 0;
const bool duplicateData = mem.read8(messagePointer + 36) != 0;
ArchiveBase::FormatInfo info {
.size = blockSize * 0x200,
.numOfDirectories = directoryNum,
.numOfFiles = fileNum,
.duplicateData = duplicateData
};
printf("Stubbed FS::FormatSaveData. File num: %d, directory num: %d\n", fileNum, directoryNum);
saveData.format(path, info);
mem.write32(messagePointer, IPC::responseHeader(0x84C, 1, 0));
mem.write32(messagePointer + 4, ResultCode::Success);
}