From 7ada8da8a84c0607603c91d5b57dcd8a647a440f Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 20 Aug 2023 13:22:48 +0300 Subject: [PATCH] Start adding SD card support --- include/fs/archive_sdmc.hpp | 2 +- include/services/fs.hpp | 10 ++++--- src/core/fs/archive_save_data.cpp | 6 ++-- src/core/fs/archive_sdmc.cpp | 43 +++++++++++++++++++++++++-- src/core/services/fs.cpp | 19 ++++++------ src/core/services/service_manager.cpp | 2 +- 6 files changed, 62 insertions(+), 20 deletions(-) diff --git a/include/fs/archive_sdmc.hpp b/include/fs/archive_sdmc.hpp index a8d9e259..23cbe600 100644 --- a/include/fs/archive_sdmc.hpp +++ b/include/fs/archive_sdmc.hpp @@ -8,7 +8,7 @@ class SDMCArchive : public ArchiveBase { public: SDMCArchive(Memory& mem) : ArchiveBase(mem) {} - u64 getFreeBytes() override { Helpers::panic("SDMC::GetFreeBytes unimplemented"); return 0; } + u64 getFreeBytes() override { return 1_GB; } std::string name() override { return "SDMC"; } HorizonResult createFile(const FSPath& path, u64 size) override; diff --git a/include/services/fs.hpp b/include/services/fs.hpp index fb098c7d..e65be798 100644 --- a/include/services/fs.hpp +++ b/include/services/fs.hpp @@ -1,4 +1,5 @@ #pragma once +#include "config.hpp" #include "fs/archive_ext_save_data.hpp" #include "fs/archive_ncch.hpp" #include "fs/archive_save_data.hpp" @@ -8,7 +9,6 @@ #include "kernel_types.hpp" #include "logger.hpp" #include "memory.hpp" -#include "result/result.hpp" // Yay, more circular dependencies class Kernel; @@ -35,6 +35,8 @@ class FSService { std::optional openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms); FSPath readPath(u32 type, u32 pointer, u32 size); + const EmulatorConfig& config; + // Service commands void createDirectory(u32 messagePointer); void createExtSaveData(u32 messagePointer); @@ -62,9 +64,9 @@ class FSService { u32 priority; public: - FSService(Memory& mem, Kernel& kernel) : mem(mem), saveData(mem), - sharedExtSaveData_nand(mem, "../SharedFiles/NAND", true), extSaveData_sdmc(mem, "SDMC"), - sdmc(mem), selfNcch(mem), ncch(mem), kernel(kernel) + FSService(Memory& mem, Kernel& kernel, const EmulatorConfig& config) : mem(mem), saveData(mem), + sharedExtSaveData_nand(mem, "../SharedFiles/NAND", true), extSaveData_sdmc(mem, "SDMC"), sdmc(mem), selfNcch(mem), + ncch(mem), kernel(kernel), config(config) {} void reset(); diff --git a/src/core/fs/archive_save_data.cpp b/src/core/fs/archive_save_data.cpp index 107aefde..97ae3229 100644 --- a/src/core/fs/archive_save_data.cpp +++ b/src/core/fs/archive_save_data.cpp @@ -92,11 +92,13 @@ HorizonResult SaveDataArchive::deleteFile(const FSPath& path) { FileDescriptor SaveDataArchive::openFile(const FSPath& path, const FilePerms& perms) { if (path.type == PathType::UTF16) { - if (!isPathSafe(path)) + if (!isPathSafe(path)) { Helpers::panic("Unsafe path in SaveData::OpenFile"); + } - if (perms.raw == 0 || (perms.create() && !perms.write())) + if (perms.raw == 0 || (perms.create() && !perms.write())) { Helpers::panic("[SaveData] Unsupported flags for OpenFile"); + } fs::path p = IOFile::getAppData() / "SaveData"; p += fs::path(path.utf16_string).make_preferred(); diff --git a/src/core/fs/archive_sdmc.cpp b/src/core/fs/archive_sdmc.cpp index 5049df14..428354d1 100644 --- a/src/core/fs/archive_sdmc.cpp +++ b/src/core/fs/archive_sdmc.cpp @@ -1,6 +1,8 @@ #include "fs/archive_sdmc.hpp" #include +namespace fs = std::filesystem; + HorizonResult SDMCArchive::createFile(const FSPath& path, u64 size) { Helpers::panic("[SDMC] CreateFile not yet supported"); return Result::Success; @@ -12,13 +14,48 @@ HorizonResult SDMCArchive::deleteFile(const FSPath& path) { } FileDescriptor SDMCArchive::openFile(const FSPath& path, const FilePerms& perms) { - printf("SDMCArchive::OpenFile: Failed"); + if (path.type == PathType::ASCII) { + if (!isPathSafe(path)) { + Helpers::panic("Unsafe path in SaveData::OpenFile"); + } + + if (perms.raw == 0 || (perms.create() && !perms.write())) { + Helpers::panic("[SaveData] Unsupported flags for OpenFile"); + } + + fs::path p = IOFile::getAppData() / "SDMC"; + p += fs::path(path.string).make_preferred(); + + const char* permString = perms.write() ? "r+b" : "rb"; + + if (fs::exists(p)) { // Return file descriptor if the file exists + IOFile file(p.string().c_str(), permString); + return file.isOpen() ? file.getHandle() : FileError; + } else { + // If the file is not found, create it if the create flag is on + if (perms.create()) { + IOFile file(p.string().c_str(), "wb"); // Create file + file.close(); // Close it + + file.open(p.string().c_str(), permString); // Reopen with proper perms + return file.isOpen() ? file.getHandle() : FileError; + } else { + return FileError; + } + } + } + + Helpers::panic("SDMCArchive::OpenFile: Failed"); return FileError; } Rust::Result SDMCArchive::openArchive(const FSPath& path) { - printf("SDMCArchive::OpenArchive: Failed\n"); - return Err(Result::FS::NotFormatted); + // TODO: Fail here if the SD is disabled in the connfig. + if (path.type != PathType::Empty) { + Helpers::panic("Unimplemented path type for SDMC::OpenArchive"); + } + + return Ok((ArchiveBase*)this); } std::optional SDMCArchive::readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) { diff --git a/src/core/services/fs.cpp b/src/core/services/fs.cpp index 38a526e3..cc3c3a76 100644 --- a/src/core/services/fs.cpp +++ b/src/core/services/fs.cpp @@ -2,6 +2,7 @@ #include "kernel/kernel.hpp" #include "io_file.hpp" #include "ipc.hpp" +#include "result/result.hpp" #ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does. #undef CreateDirectory @@ -338,7 +339,8 @@ void FSService::openFileDirectly(u32 messagePointer) { std::optional handle = openFileHandle(archive, filePath, archivePath, perms); mem.write32(messagePointer, IPC::responseHeader(0x803, 1, 2)); if (!handle.has_value()) { - Helpers::panic("OpenFileDirectly: Failed to open file with given path"); + printf("OpenFileDirectly failed\n"); + mem.write32(messagePointer + 4, Result::FS::FileNotFound); } else { mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 12, handle.value()); @@ -582,22 +584,21 @@ void FSService::setPriority(u32 messagePointer) { priority = value; } - -// Shows whether an SD card is inserted. At the moment stubbed to no -constexpr bool sdInserted = false; - void FSService::isSdmcDetected(u32 messagePointer) { log("FS::IsSdmcDetected\n"); + mem.write32(messagePointer, IPC::responseHeader(0x817, 2, 0)); mem.write32(messagePointer + 4, Result::Success); - mem.write8(messagePointer + 8, sdInserted ? 1 : 0); + mem.write8(messagePointer + 8, config.sdCardInserted ? 1 : 0); } -// We consider our SD card to always be writable if oen is inserted for now -// So isSdmcWritable returns 1 if an SD card is inserted (because it's always writable) and 0 if not. +// We consider our SD card to always be writable if one is inserted for now +// However we do make sure to respect the configs and properly return the correct value here void FSService::isSdmcWritable(u32 messagePointer) { log("FS::isSdmcWritable\n"); + const bool writeProtected = (!config.sdCardInserted) || (config.sdCardInserted && config.sdWriteProtected); + mem.write32(messagePointer, IPC::responseHeader(0x818, 2, 0)); mem.write32(messagePointer + 4, Result::Success); - mem.write8(messagePointer + 8, sdInserted ? 1 : 0); + mem.write8(messagePointer + 8, writeProtected ? 0 : 1); } \ No newline at end of file diff --git a/src/core/services/service_manager.cpp b/src/core/services/service_manager.cpp index 591d424a..15fcb401 100644 --- a/src/core/services/service_manager.cpp +++ b/src/core/services/service_manager.cpp @@ -7,7 +7,7 @@ ServiceManager::ServiceManager(std::span regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel, const EmulatorConfig& config) : regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem, kernel), cecd(mem, kernel), cfg(mem), - dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel), + dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel, config), gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mcu_hwc(mem, config), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}