mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
[FS] Rehaul to implement all the different things ExtSaveData can target
This commit is contained in:
parent
0f9d94a7d0
commit
f90a266bb4
4 changed files with 71 additions and 24 deletions
|
@ -3,17 +3,20 @@
|
||||||
|
|
||||||
class ExtSaveDataArchive : public ArchiveBase {
|
class ExtSaveDataArchive : public ArchiveBase {
|
||||||
public:
|
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; }
|
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 createFile(const FSPath& path, u64 size) override;
|
||||||
FSResult deleteFile(const FSPath& path) override;
|
FSResult deleteFile(const FSPath& path) override;
|
||||||
|
|
||||||
ArchiveBase* openArchive(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;
|
FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
|
||||||
std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
|
std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override;
|
||||||
|
|
||||||
bool isShared = false;
|
bool isShared = false;
|
||||||
|
std::string backingFolder; // Backing folder for the archive. Can be NAND, Gamecard or SD depending on the archive path.
|
||||||
};
|
};
|
|
@ -22,12 +22,15 @@ class FSService {
|
||||||
// The different filesystem archives (Save data, SelfNCCH, SDMC, NCCH, ExtData, etc)
|
// The different filesystem archives (Save data, SelfNCCH, SDMC, NCCH, ExtData, etc)
|
||||||
SelfNCCHArchive selfNcch;
|
SelfNCCHArchive selfNcch;
|
||||||
SaveDataArchive saveData;
|
SaveDataArchive saveData;
|
||||||
ExtSaveDataArchive extSaveData;
|
|
||||||
ExtSaveDataArchive sharedExtSaveData;
|
|
||||||
SDMCArchive sdmc;
|
SDMCArchive sdmc;
|
||||||
NCCHArchive ncch;
|
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);
|
std::optional<Handle> openArchiveHandle(u32 archiveID, const FSPath& path);
|
||||||
Rust::Result<Handle, FSResult> openDirectoryHandle(ArchiveBase* archive, 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);
|
std::optional<Handle> openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms);
|
||||||
|
@ -53,11 +56,10 @@ class FSService {
|
||||||
u32 priority;
|
u32 priority;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FSService(Memory& mem, Kernel& kernel) : mem(mem), saveData(mem), extSaveData(mem), sharedExtSaveData(mem), sdmc(mem),
|
FSService(Memory& mem, Kernel& kernel) : mem(mem), saveData(mem), extSaveData_nand(mem, "NAND"),
|
||||||
selfNcch(mem), ncch(mem), kernel(kernel)
|
sharedExtSaveData_nand(mem, "NAND", true), extSaveData_cart(mem, "CartSave"), sharedExtSaveData_cart(mem, "CartSave", true),
|
||||||
{
|
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
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void handleSyncRequest(u32 messagePointer);
|
void handleSyncRequest(u32 messagePointer);
|
||||||
|
|
|
@ -11,7 +11,7 @@ FSResult ExtSaveDataArchive::createFile(const FSPath& path, u64 size) {
|
||||||
if (!isPathSafe<PathType::UTF16>(path))
|
if (!isPathSafe<PathType::UTF16>(path))
|
||||||
Helpers::panic("Unsafe path in ExtSaveData::CreateFile");
|
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();
|
p += fs::path(path.utf16_string).make_preferred();
|
||||||
|
|
||||||
if (fs::exists(p))
|
if (fs::exists(p))
|
||||||
|
@ -35,7 +35,7 @@ FSResult ExtSaveDataArchive::deleteFile(const FSPath& path) {
|
||||||
if (!isPathSafe<PathType::UTF16>(path))
|
if (!isPathSafe<PathType::UTF16>(path))
|
||||||
Helpers::panic("Unsafe path in ExtSaveData::DeleteFile");
|
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();
|
p += fs::path(path.utf16_string).make_preferred();
|
||||||
|
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
@ -55,7 +55,7 @@ FileDescriptor ExtSaveDataArchive::openFile(const FSPath& path, const FilePerms&
|
||||||
if (perms.create())
|
if (perms.create())
|
||||||
Helpers::panic("[ExtSaveData] Can't open file with create flag");
|
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();
|
p += fs::path(path.utf16_string).make_preferred();
|
||||||
|
|
||||||
if (fs::exists(p)) { // Return file descriptor if the file exists
|
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");
|
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;
|
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) {
|
std::optional<u32> ExtSaveDataArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) {
|
||||||
Helpers::panic("ExtSaveDataArchive::ReadFile: Failed");
|
Helpers::panic("ExtSaveDataArchive::ReadFile: Failed");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
|
@ -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.
|
// Creates directories for NAND, ExtSaveData, etc if they don't already exist. Should be executed after loading a new ROM.
|
||||||
void FSService::initializeFilesystem() {
|
void FSService::initializeFilesystem() {
|
||||||
const auto nandPath = IOFile::getAppData() / "NAND"; // Create NAND
|
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 savePath = IOFile::getAppData() / "SaveData"; // Create SaveData
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
// TODO: SDMC, etc
|
// TODO: SDMC, etc
|
||||||
|
@ -49,17 +50,37 @@ void FSService::initializeFilesystem() {
|
||||||
fs::create_directories(nandPath);
|
fs::create_directories(nandPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fs::is_directory(cartPath)) {
|
||||||
|
fs::create_directories(cartPath);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fs::is_directory(savePath)) {
|
if (!fs::is_directory(savePath)) {
|
||||||
fs::create_directories(savePath);
|
fs::create_directories(savePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiveBase* FSService::getArchiveFromID(u32 id) {
|
ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case ArchiveID::SelfNCCH: return &selfNcch;
|
case ArchiveID::SelfNCCH: return &selfNcch;
|
||||||
case ArchiveID::SaveData: return &saveData;
|
case ArchiveID::SaveData: return &saveData;
|
||||||
case ArchiveID::ExtSaveData: return &extSaveData;
|
case ArchiveID::ExtSaveData:
|
||||||
case ArchiveID::SharedExtSaveData: return &sharedExtSaveData;
|
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::SDMC: return &sdmc;
|
||||||
case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI
|
case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI
|
||||||
default:
|
default:
|
||||||
|
@ -96,7 +117,7 @@ Rust::Result<Handle, FSResult> FSService::openDirectoryHandle(ArchiveBase* archi
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Handle> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) {
|
std::optional<Handle> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) {
|
||||||
ArchiveBase* archive = getArchiveFromID(archiveID);
|
ArchiveBase* archive = getArchiveFromID(archiveID, path);
|
||||||
|
|
||||||
if (archive == nullptr) [[unlikely]] {
|
if (archive == nullptr) [[unlikely]] {
|
||||||
Helpers::panic("OpenArchive: Tried to open unknown archive %d.", archiveID);
|
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 attributes = mem.read32(messagePointer + 32);
|
||||||
const u32 archivePathPointer = mem.read32(messagePointer + 40);
|
const u32 archivePathPointer = mem.read32(messagePointer + 40);
|
||||||
const u32 filePathPointer = mem.read32(messagePointer + 48);
|
const u32 filePathPointer = mem.read32(messagePointer + 48);
|
||||||
|
|
||||||
log("FS::OpenFileDirectly\n");
|
log("FS::OpenFileDirectly\n");
|
||||||
|
|
||||||
ArchiveBase* archive = getArchiveFromID(archiveID);
|
auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
|
||||||
|
ArchiveBase* archive = getArchiveFromID(archiveID, archivePath);
|
||||||
|
|
||||||
if (archive == nullptr) [[unlikely]] {
|
if (archive == nullptr) [[unlikely]] {
|
||||||
Helpers::panic("OpenFileDirectly: Tried to open unknown archive %d.", archiveID);
|
Helpers::panic("OpenFileDirectly: Tried to open unknown archive %d.", archiveID);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
|
|
||||||
auto filePath = readPath(filePathType, filePathPointer, filePathSize);
|
auto filePath = readPath(filePathType, filePathPointer, filePathSize);
|
||||||
const FilePerms perms(openFlags);
|
const FilePerms perms(openFlags);
|
||||||
|
|
||||||
|
@ -344,7 +364,7 @@ void FSService::getFormatInfo(u32 messagePointer) {
|
||||||
const auto path = readPath(pathType, pathPointer, pathSize);
|
const auto path = readPath(pathType, pathPointer, pathSize);
|
||||||
log("FS::GetFormatInfo(archive ID = %d, archive path type = %d)\n", archiveID, pathType);
|
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]] {
|
if (archive == nullptr) [[unlikely]] {
|
||||||
Helpers::panic("OpenArchive: Tried to open unknown archive %d.", archiveID);
|
Helpers::panic("OpenArchive: Tried to open unknown archive %d.", archiveID);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue