mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 22:55:40 +12:00
Merge pull request #275 from wheremyfoodat/SystemSaveData
Moar filesystem
This commit is contained in:
commit
fa6a257b43
9 changed files with 136 additions and 9 deletions
|
@ -6,7 +6,7 @@ class SystemSaveDataArchive : public ArchiveBase {
|
||||||
SystemSaveDataArchive(Memory& mem) : ArchiveBase(mem) {}
|
SystemSaveDataArchive(Memory& mem) : ArchiveBase(mem) {}
|
||||||
|
|
||||||
u64 getFreeBytes() override {
|
u64 getFreeBytes() override {
|
||||||
Helpers::panic("Unimplemented GetFreeBytes for SystemSaveData archive");
|
Helpers::warn("Unimplemented GetFreeBytes for SystemSaveData archive");
|
||||||
return 32_MB;
|
return 32_MB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,14 +14,10 @@ class SystemSaveDataArchive : public ArchiveBase {
|
||||||
|
|
||||||
//HorizonResult createDirectory(const FSPath& path) override;
|
//HorizonResult createDirectory(const FSPath& path) override;
|
||||||
HorizonResult createFile(const FSPath& path, u64 size) override;
|
HorizonResult createFile(const FSPath& path, u64 size) override;
|
||||||
|
HorizonResult deleteFile(const FSPath& path) override;
|
||||||
HorizonResult deleteFile(const FSPath& path) override {
|
|
||||||
Helpers::panic("Unimplemented DeleteFile for SystemSaveData archive");
|
|
||||||
return Result::Success;
|
|
||||||
};
|
|
||||||
|
|
||||||
Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
|
Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
|
||||||
//Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
|
Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
|
||||||
|
|
||||||
FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
|
FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ class BOSSService {
|
||||||
void registerStorageEntry(u32 messagePointer);
|
void registerStorageEntry(u32 messagePointer);
|
||||||
void registerTask(u32 messagePointer);
|
void registerTask(u32 messagePointer);
|
||||||
void sendProperty(u32 messagePointer);
|
void sendProperty(u32 messagePointer);
|
||||||
|
void setOptoutFlag(u32 messagePointer);
|
||||||
void startTask(u32 messagePointer);
|
void startTask(u32 messagePointer);
|
||||||
void unregisterStorage(u32 messagePointer);
|
void unregisterStorage(u32 messagePointer);
|
||||||
void unregisterTask(u32 messagePointer);
|
void unregisterTask(u32 messagePointer);
|
||||||
|
|
|
@ -46,11 +46,13 @@ class FSService {
|
||||||
|
|
||||||
// Service commands
|
// Service commands
|
||||||
void abnegateAccessRight(u32 messagePointer);
|
void abnegateAccessRight(u32 messagePointer);
|
||||||
|
void cardSlotIsInserted(u32 messagePointer);
|
||||||
void createDirectory(u32 messagePointer);
|
void createDirectory(u32 messagePointer);
|
||||||
void createExtSaveData(u32 messagePointer);
|
void createExtSaveData(u32 messagePointer);
|
||||||
void createFile(u32 messagePointer);
|
void createFile(u32 messagePointer);
|
||||||
void closeArchive(u32 messagePointer);
|
void closeArchive(u32 messagePointer);
|
||||||
void controlArchive(u32 messagePointer);
|
void controlArchive(u32 messagePointer);
|
||||||
|
void deleteDirectory(u32 messagePointer);
|
||||||
void deleteExtSaveData(u32 messagePointer);
|
void deleteExtSaveData(u32 messagePointer);
|
||||||
void deleteFile(u32 messagePointer);
|
void deleteFile(u32 messagePointer);
|
||||||
void formatSaveData(u32 messagePointer);
|
void formatSaveData(u32 messagePointer);
|
||||||
|
|
|
@ -64,8 +64,9 @@ HorizonResult SaveDataArchive::createDirectory(const FSPath& path) {
|
||||||
|
|
||||||
HorizonResult SaveDataArchive::deleteFile(const FSPath& path) {
|
HorizonResult SaveDataArchive::deleteFile(const FSPath& path) {
|
||||||
if (path.type == PathType::UTF16) {
|
if (path.type == PathType::UTF16) {
|
||||||
if (!isPathSafe<PathType::UTF16>(path))
|
if (!isPathSafe<PathType::UTF16>(path)) {
|
||||||
Helpers::panic("Unsafe path in SaveData::DeleteFile");
|
Helpers::panic("Unsafe path in SaveData::DeleteFile");
|
||||||
|
}
|
||||||
|
|
||||||
fs::path p = IOFile::getAppData() / "SaveData";
|
fs::path p = IOFile::getAppData() / "SaveData";
|
||||||
p += fs::path(path.utf16_string).make_preferred();
|
p += fs::path(path.utf16_string).make_preferred();
|
||||||
|
|
|
@ -4,7 +4,37 @@
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
HorizonResult SDMCArchive::createFile(const FSPath& path, u64 size) {
|
HorizonResult SDMCArchive::createFile(const FSPath& path, u64 size) {
|
||||||
Helpers::panic("[SDMC] CreateFile not yet supported");
|
if (path.type == PathType::UTF16) {
|
||||||
|
if (!isPathSafe<PathType::UTF16>(path)) {
|
||||||
|
Helpers::panic("Unsafe path in SDMC::CreateFile");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path p = IOFile::getAppData() / "SDMC";
|
||||||
|
p += fs::path(path.utf16_string).make_preferred();
|
||||||
|
|
||||||
|
if (fs::exists(p)) {
|
||||||
|
return Result::FS::AlreadyExists;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOFile file(p.string().c_str(), "wb");
|
||||||
|
|
||||||
|
// If the size is 0, leave the file empty and return success
|
||||||
|
if (size == 0) {
|
||||||
|
file.close();
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is not empty, seek to size - 1 and write a 0 to create a file of size "size"
|
||||||
|
else if (file.seek(size - 1, SEEK_SET) && file.writeBytes("", 1).second == 1) {
|
||||||
|
file.close();
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return Result::FS::FileTooLarge;
|
||||||
|
}
|
||||||
|
|
||||||
|
Helpers::panic("SDMC::CreateFile: Failed");
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,4 +82,63 @@ HorizonResult SystemSaveDataArchive::createFile(const FSPath& path, u64 size) {
|
||||||
|
|
||||||
Helpers::panic("SystemSaveData::CreateFile: Failed");
|
Helpers::panic("SystemSaveData::CreateFile: Failed");
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HorizonResult SystemSaveDataArchive::deleteFile(const FSPath& path) {
|
||||||
|
if (path.type == PathType::UTF16) {
|
||||||
|
if (!isPathSafe<PathType::UTF16>(path)) {
|
||||||
|
Helpers::panic("Unsafe path in SystemSaveData::DeleteFile");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path p = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
|
||||||
|
p += fs::path(path.utf16_string).make_preferred();
|
||||||
|
|
||||||
|
if (fs::is_directory(p)) {
|
||||||
|
Helpers::panic("SystemSaveData::DeleteFile: Tried to delete directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs::is_regular_file(p)) {
|
||||||
|
return Result::FS::FileNotFoundAlt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
bool success = fs::remove(p, ec);
|
||||||
|
|
||||||
|
// It might still be possible for fs::remove to fail, if there's eg an open handle to a file being deleted
|
||||||
|
// In this case, print a warning, but still return success for now
|
||||||
|
if (!success) {
|
||||||
|
Helpers::warn("SystemSaveData::DeleteFile: fs::remove failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Helpers::panic("SystemSaveData::DeleteFile: Unknown path type");
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rust::Result<DirectorySession, HorizonResult> SystemSaveDataArchive::openDirectory(const FSPath& path) {
|
||||||
|
if (path.type == PathType::UTF16) {
|
||||||
|
if (!isPathSafe<PathType::UTF16>(path)) {
|
||||||
|
Helpers::panic("Unsafe path in SystemSaveData::OpenDirectory");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path p = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
|
||||||
|
p += fs::path(path.utf16_string).make_preferred();
|
||||||
|
|
||||||
|
if (fs::is_regular_file(p)) {
|
||||||
|
printf("SystemSaveData: OpenDirectory used with a file path");
|
||||||
|
return Err(Result::FS::UnexpectedFileOrDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs::is_directory(p)) {
|
||||||
|
return Ok(DirectorySession(this, p));
|
||||||
|
} else {
|
||||||
|
return Err(Result::FS::FileNotFoundAlt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Helpers::panic("SystemSaveData::OpenDirectory: Unimplemented path type");
|
||||||
|
return Err(Result::Success);
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ namespace BOSSCommands {
|
||||||
UnregisterStorage = 0x00030000,
|
UnregisterStorage = 0x00030000,
|
||||||
GetTaskStorageInfo = 0x00040000,
|
GetTaskStorageInfo = 0x00040000,
|
||||||
RegisterNewArrivalEvent = 0x00080002,
|
RegisterNewArrivalEvent = 0x00080002,
|
||||||
|
SetOptoutFlag = 0x00090040,
|
||||||
GetOptoutFlag = 0x000A0000,
|
GetOptoutFlag = 0x000A0000,
|
||||||
RegisterTask = 0x000B00C2,
|
RegisterTask = 0x000B00C2,
|
||||||
UnregisterTask = 0x000C0082,
|
UnregisterTask = 0x000C0082,
|
||||||
|
@ -53,6 +54,7 @@ void BOSSService::handleSyncRequest(u32 messagePointer) {
|
||||||
case BOSSCommands::RegisterStorageEntry: registerStorageEntry(messagePointer); break;
|
case BOSSCommands::RegisterStorageEntry: registerStorageEntry(messagePointer); break;
|
||||||
case BOSSCommands::RegisterTask: registerTask(messagePointer); break;
|
case BOSSCommands::RegisterTask: registerTask(messagePointer); break;
|
||||||
case BOSSCommands::SendProperty: sendProperty(messagePointer); break;
|
case BOSSCommands::SendProperty: sendProperty(messagePointer); break;
|
||||||
|
case BOSSCommands::SetOptoutFlag: setOptoutFlag(messagePointer); break;
|
||||||
case BOSSCommands::StartTask: startTask(messagePointer); break;
|
case BOSSCommands::StartTask: startTask(messagePointer); break;
|
||||||
case BOSSCommands::UnregisterStorage: unregisterStorage(messagePointer); break;
|
case BOSSCommands::UnregisterStorage: unregisterStorage(messagePointer); break;
|
||||||
case BOSSCommands::UnregisterTask: unregisterTask(messagePointer); break;
|
case BOSSCommands::UnregisterTask: unregisterTask(messagePointer); break;
|
||||||
|
@ -66,6 +68,15 @@ void BOSSService::initializeSession(u32 messagePointer) {
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BOSSService::setOptoutFlag(u32 messagePointer) {
|
||||||
|
const s8 flag = static_cast<s8>(mem.read8(messagePointer + 4));
|
||||||
|
log("BOSS::SetOptoutFlag (flag = %d)\n", flag);
|
||||||
|
optoutFlag = flag;
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x9, 1, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
}
|
||||||
|
|
||||||
void BOSSService::getOptoutFlag(u32 messagePointer) {
|
void BOSSService::getOptoutFlag(u32 messagePointer) {
|
||||||
log("BOSS::GetOptoutFlag\n");
|
log("BOSS::GetOptoutFlag\n");
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0xA, 2, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0xA, 2, 0));
|
||||||
|
|
|
@ -16,6 +16,8 @@ namespace FSCommands {
|
||||||
OpenFile = 0x080201C2,
|
OpenFile = 0x080201C2,
|
||||||
OpenFileDirectly = 0x08030204,
|
OpenFileDirectly = 0x08030204,
|
||||||
DeleteFile = 0x08040142,
|
DeleteFile = 0x08040142,
|
||||||
|
DeleteDirectory = 0x08060142,
|
||||||
|
DeleteDirectoryRecursively = 0x08070142,
|
||||||
CreateFile = 0x08080202,
|
CreateFile = 0x08080202,
|
||||||
CreateDirectory = 0x08090182,
|
CreateDirectory = 0x08090182,
|
||||||
OpenDirectory = 0x080B0102,
|
OpenDirectory = 0x080B0102,
|
||||||
|
@ -26,6 +28,7 @@ namespace FSCommands {
|
||||||
GetFreeBytes = 0x08120080,
|
GetFreeBytes = 0x08120080,
|
||||||
IsSdmcDetected = 0x08170000,
|
IsSdmcDetected = 0x08170000,
|
||||||
IsSdmcWritable = 0x08180000,
|
IsSdmcWritable = 0x08180000,
|
||||||
|
CardSlotIsInserted = 0x08210000,
|
||||||
AbnegateAccessRight = 0x08400040,
|
AbnegateAccessRight = 0x08400040,
|
||||||
GetFormatInfo = 0x084500C2,
|
GetFormatInfo = 0x084500C2,
|
||||||
GetArchiveResource = 0x08490040,
|
GetArchiveResource = 0x08490040,
|
||||||
|
@ -160,11 +163,13 @@ FSPath FSService::readPath(u32 type, u32 pointer, u32 size) {
|
||||||
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) {
|
||||||
|
case FSCommands::CardSlotIsInserted: cardSlotIsInserted(messagePointer); break;
|
||||||
case FSCommands::CreateDirectory: createDirectory(messagePointer); break;
|
case FSCommands::CreateDirectory: createDirectory(messagePointer); break;
|
||||||
case FSCommands::CreateExtSaveData: createExtSaveData(messagePointer); break;
|
case FSCommands::CreateExtSaveData: createExtSaveData(messagePointer); break;
|
||||||
case FSCommands::CreateFile: createFile(messagePointer); break;
|
case FSCommands::CreateFile: createFile(messagePointer); break;
|
||||||
case FSCommands::ControlArchive: controlArchive(messagePointer); break;
|
case FSCommands::ControlArchive: controlArchive(messagePointer); break;
|
||||||
case FSCommands::CloseArchive: closeArchive(messagePointer); break;
|
case FSCommands::CloseArchive: closeArchive(messagePointer); break;
|
||||||
|
case FSCommands::DeleteDirectory: deleteDirectory(messagePointer); break;
|
||||||
case FSCommands::DeleteExtSaveData: deleteExtSaveData(messagePointer); break;
|
case FSCommands::DeleteExtSaveData: deleteExtSaveData(messagePointer); break;
|
||||||
case FSCommands::DeleteFile: deleteFile(messagePointer); break;
|
case FSCommands::DeleteFile: deleteFile(messagePointer); break;
|
||||||
case FSCommands::FormatSaveData: formatSaveData(messagePointer); break;
|
case FSCommands::FormatSaveData: formatSaveData(messagePointer); break;
|
||||||
|
@ -414,6 +419,18 @@ void FSService::deleteFile(u32 messagePointer) {
|
||||||
mem.write32(messagePointer + 4, static_cast<u32>(res));
|
mem.write32(messagePointer + 4, static_cast<u32>(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FSService::deleteDirectory(u32 messagePointer) {
|
||||||
|
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8));
|
||||||
|
const u32 filePathType = mem.read32(messagePointer + 16);
|
||||||
|
const u32 filePathSize = mem.read32(messagePointer + 20);
|
||||||
|
const u32 filePathPointer = mem.read32(messagePointer + 28);
|
||||||
|
log("FS::DeleteDirectory\n");
|
||||||
|
|
||||||
|
Helpers::warn("Stubbed FS::DeleteDirectory call!");
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x806, 1, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
}
|
||||||
|
|
||||||
void FSService::getFormatInfo(u32 messagePointer) {
|
void FSService::getFormatInfo(u32 messagePointer) {
|
||||||
const u32 archiveID = mem.read32(messagePointer + 4);
|
const u32 archiveID = mem.read32(messagePointer + 4);
|
||||||
const u32 pathType = mem.read32(messagePointer + 8);
|
const u32 pathType = mem.read32(messagePointer + 8);
|
||||||
|
@ -690,4 +707,13 @@ void FSService::isSdmcWritable(u32 messagePointer) {
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x818, 2, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x818, 2, 0));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
mem.write8(messagePointer + 8, writeProtected ? 0 : 1);
|
mem.write8(messagePointer + 8, writeProtected ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSService::cardSlotIsInserted(u32 messagePointer) {
|
||||||
|
log("FS::CardSlotIsInserted\n");
|
||||||
|
constexpr bool cardInserted = false;
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x821, 2, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
mem.write8(messagePointer + 8, cardInserted ? 1 : 0);
|
||||||
}
|
}
|
|
@ -95,6 +95,7 @@ void ServiceManager::registerClient(u32 messagePointer) {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static std::map<std::string, Handle> serviceMap = {
|
static std::map<std::string, Handle> serviceMap = {
|
||||||
{ "ac:u", KernelHandles::AC },
|
{ "ac:u", KernelHandles::AC },
|
||||||
|
{ "act:a", KernelHandles::ACT },
|
||||||
{ "act:u", KernelHandles::ACT },
|
{ "act:u", KernelHandles::ACT },
|
||||||
{ "am:app", KernelHandles::AM },
|
{ "am:app", KernelHandles::AM },
|
||||||
{ "APT:S", KernelHandles::APT }, // TODO: APT:A, APT:S and APT:U are slightly different
|
{ "APT:S", KernelHandles::APT }, // TODO: APT:A, APT:S and APT:U are slightly different
|
||||||
|
|
Loading…
Add table
Reference in a new issue