mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Merge pull request #255 from Subv/sd_card
FS: Implemented access to the SD card
This commit is contained in:
		@@ -6,6 +6,7 @@
 | 
			
		||||
#include "common/file_util.h"
 | 
			
		||||
#include "core/file_sys/filesystem.h"
 | 
			
		||||
#include "core/file_sys/savedata_factory.h"
 | 
			
		||||
#include "core/file_sys/sdmc_factory.h"
 | 
			
		||||
#include "core/hle/service/filesystem/filesystem.h"
 | 
			
		||||
#include "core/hle/service/filesystem/fsp_srv.h"
 | 
			
		||||
 | 
			
		||||
@@ -60,9 +61,13 @@ void RegisterFileSystems() {
 | 
			
		||||
    filesystem_map.clear();
 | 
			
		||||
 | 
			
		||||
    std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
 | 
			
		||||
    std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX);
 | 
			
		||||
 | 
			
		||||
    auto savedata = std::make_unique<FileSys::SaveData_Factory>(std::move(nand_directory));
 | 
			
		||||
    RegisterFileSystem(std::move(savedata), Type::SaveData);
 | 
			
		||||
 | 
			
		||||
    auto sdcard = std::make_unique<FileSys::SDMC_Factory>(std::move(sd_directory));
 | 
			
		||||
    RegisterFileSystem(std::move(sdcard), Type::SDMC);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ namespace FileSystem {
 | 
			
		||||
enum class Type {
 | 
			
		||||
    RomFS = 1,
 | 
			
		||||
    SaveData = 2,
 | 
			
		||||
    SDMC = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
#include <cinttypes>
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/file_sys/directory.h"
 | 
			
		||||
#include "core/file_sys/filesystem.h"
 | 
			
		||||
#include "core/file_sys/storage.h"
 | 
			
		||||
#include "core/hle/ipc_helpers.h"
 | 
			
		||||
@@ -151,14 +152,66 @@ private:
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class IDirectory final : public ServiceFramework<IDirectory> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit IDirectory(std::unique_ptr<FileSys::DirectoryBackend>&& backend)
 | 
			
		||||
        : ServiceFramework("IDirectory"), backend(std::move(backend)) {
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &IDirectory::Read, "Read"},
 | 
			
		||||
            {1, &IDirectory::GetEntryCount, "GetEntryCount"},
 | 
			
		||||
        };
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::unique_ptr<FileSys::DirectoryBackend> backend;
 | 
			
		||||
 | 
			
		||||
    void Read(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
        const u64 unk = rp.Pop<u64>();
 | 
			
		||||
 | 
			
		||||
        LOG_DEBUG(Service_FS, "called, unk=0x%llx", unk);
 | 
			
		||||
 | 
			
		||||
        // Calculate how many entries we can fit in the output buffer
 | 
			
		||||
        u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry);
 | 
			
		||||
 | 
			
		||||
        // Read the data from the Directory backend
 | 
			
		||||
        std::vector<FileSys::Entry> entries(count_entries);
 | 
			
		||||
        u64 read_entries = backend->Read(count_entries, entries.data());
 | 
			
		||||
 | 
			
		||||
        // Convert the data into a byte array
 | 
			
		||||
        std::vector<u8> output(entries.size() * sizeof(FileSys::Entry));
 | 
			
		||||
        std::memcpy(output.data(), entries.data(), output.size());
 | 
			
		||||
 | 
			
		||||
        // Write the data to memory
 | 
			
		||||
        ctx.WriteBuffer(output);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 4};
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
        rb.Push(read_entries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetEntryCount(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        LOG_DEBUG(Service_FS, "called");
 | 
			
		||||
 | 
			
		||||
        u64 count = backend->GetEntryCount();
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 4};
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
        rb.Push(count);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class IFileSystem final : public ServiceFramework<IFileSystem> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit IFileSystem(std::unique_ptr<FileSys::FileSystemBackend>&& backend)
 | 
			
		||||
        : ServiceFramework("IFileSystem"), backend(std::move(backend)) {
 | 
			
		||||
        static const FunctionInfo functions[] = {
 | 
			
		||||
            {0, &IFileSystem::CreateFile, "CreateFile"},
 | 
			
		||||
            {2, &IFileSystem::CreateDirectory, "CreateDirectory"},
 | 
			
		||||
            {7, &IFileSystem::GetEntryType, "GetEntryType"},
 | 
			
		||||
            {8, &IFileSystem::OpenFile, "OpenFile"},
 | 
			
		||||
            {9, &IFileSystem::OpenDirectory, "OpenDirectory"},
 | 
			
		||||
            {10, &IFileSystem::Commit, "Commit"},
 | 
			
		||||
        };
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
@@ -182,6 +235,20 @@ public:
 | 
			
		||||
        rb.Push(backend->CreateFile(name, size));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateDirectory(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
 | 
			
		||||
        auto file_buffer = ctx.ReadBuffer();
 | 
			
		||||
        auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
 | 
			
		||||
 | 
			
		||||
        std::string name(file_buffer.begin(), end);
 | 
			
		||||
 | 
			
		||||
        LOG_DEBUG(Service_FS, "called directory %s", name.c_str());
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(backend->CreateDirectory(name));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void OpenFile(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
 | 
			
		||||
@@ -208,6 +275,33 @@ public:
 | 
			
		||||
        rb.PushIpcInterface<IFile>(std::move(file));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void OpenDirectory(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
 | 
			
		||||
        auto file_buffer = ctx.ReadBuffer();
 | 
			
		||||
        auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
 | 
			
		||||
 | 
			
		||||
        std::string name(file_buffer.begin(), end);
 | 
			
		||||
 | 
			
		||||
        // TODO(Subv): Implement this filter.
 | 
			
		||||
        u32 filter_flags = rp.Pop<u32>();
 | 
			
		||||
 | 
			
		||||
        LOG_DEBUG(Service_FS, "called directory %s filter %u", name.c_str(), filter_flags);
 | 
			
		||||
 | 
			
		||||
        auto result = backend->OpenDirectory(name);
 | 
			
		||||
        if (result.Failed()) {
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
            rb.Push(result.Code());
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto directory = std::move(result.Unwrap());
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
        rb.PushIpcInterface<IDirectory>(std::move(directory));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GetEntryType(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        IPC::RequestParser rp{ctx};
 | 
			
		||||
 | 
			
		||||
@@ -274,10 +368,14 @@ void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_WARNING(Service_FS, "(STUBBED) called");
 | 
			
		||||
    LOG_DEBUG(Service_FS, "called");
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    FileSys::Path unused;
 | 
			
		||||
    auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap();
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user