fs: Implement missing filesystem functions and interfaces

- Add IDeviceOperator interface with 49 functions for SD card, MMC, and game card operations
- Add IEventNotifier interface for filesystem event notifications
- Add ISaveDataTransferManager and related transfer interfaces (exporter/importer)
- Add IWiper interface for BIS partition wiping
- Enhance FSP_SRV with OpenDeviceOperator, OpenSdCardDetectionEventNotifier, OpenSaveDataTransferManager, and other missing functions
- Enhance FSP_LDR with OpenCodeFileSystem, IsArchivedProgram, and SetCurrentProcess implementations
- Enhance FSP_PR with RegisterProgram, UnregisterProgram, and verification functions
- Fix ServiceContext usage for proper event creation and management
- Fix function parameter alignment issues for CMIF serialization
- Update build system to include new source files
- Update copyright headers to 2025 citron

All functions are implemented with appropriate logging and parameter validation based on Nintendo Switch filesystem services documentation.

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-06-30 19:24:23 +10:00
parent 7f5661440a
commit 90f265837d
19 changed files with 1011 additions and 17 deletions

View File

@@ -631,18 +631,30 @@ add_library(core STATIC
hle/service/fgm/fgm.h
hle/service/filesystem/filesystem.cpp
hle/service/filesystem/filesystem.h
hle/service/filesystem/fsp/fs_i_device_operator.cpp
hle/service/filesystem/fsp/fs_i_device_operator.h
hle/service/filesystem/fsp/fs_i_directory.cpp
hle/service/filesystem/fsp/fs_i_directory.h
hle/service/filesystem/fsp/fs_i_event_notifier.cpp
hle/service/filesystem/fsp/fs_i_event_notifier.h
hle/service/filesystem/fsp/fs_i_file.cpp
hle/service/filesystem/fsp/fs_i_file.h
hle/service/filesystem/fsp/fs_i_filesystem.cpp
hle/service/filesystem/fsp/fs_i_filesystem.h
hle/service/filesystem/fsp/fs_i_multi_commit_manager.cpp
hle/service/filesystem/fsp/fs_i_multi_commit_manager.h
hle/service/filesystem/fsp/fs_i_save_data_exporter.cpp
hle/service/filesystem/fsp/fs_i_save_data_exporter.h
hle/service/filesystem/fsp/fs_i_save_data_importer.cpp
hle/service/filesystem/fsp/fs_i_save_data_importer.h
hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp
hle/service/filesystem/fsp/fs_i_save_data_info_reader.h
hle/service/filesystem/fsp/fs_i_save_data_transfer_manager.cpp
hle/service/filesystem/fsp/fs_i_save_data_transfer_manager.h
hle/service/filesystem/fsp/fs_i_storage.cpp
hle/service/filesystem/fsp/fs_i_storage.h
hle/service/filesystem/fsp/fs_i_wiper.cpp
hle/service/filesystem/fsp/fs_i_wiper.h
hle/service/filesystem/fsp/fsp_ldr.cpp
hle/service/filesystem/fsp/fsp_ldr.h
hle/service/filesystem/fsp/fsp_pr.cpp

View File

@@ -0,0 +1,385 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_device_operator.h"
namespace Service::FileSystem {
IDeviceOperator::IDeviceOperator(Core::System& system_)
: ServiceFramework{system_, "IDeviceOperator"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IDeviceOperator::IsSdCardInserted>, "IsSdCardInserted"},
{1, D<&IDeviceOperator::GetSdCardSpeedMode>, "GetSdCardSpeedMode"},
{2, D<&IDeviceOperator::GetSdCardCid>, "GetSdCardCid"},
{3, D<&IDeviceOperator::GetSdCardUserAreaSize>, "GetSdCardUserAreaSize"},
{4, D<&IDeviceOperator::GetSdCardProtectedAreaSize>, "GetSdCardProtectedAreaSize"},
{5, D<&IDeviceOperator::GetAndClearSdCardErrorInfo>, "GetAndClearSdCardErrorInfo"},
{100, D<&IDeviceOperator::GetSdCardHostControllerStatus>, "GetSdCardHostControllerStatus"},
{110, D<&IDeviceOperator::GetMmcCid>, "GetMmcCid"},
{111, D<&IDeviceOperator::GetMmcSpeedMode>, "GetMmcSpeedMode"},
{112, D<&IDeviceOperator::EraseMmc>, "EraseMmc"},
{113, D<&IDeviceOperator::GetMmcPartitionSize>, "GetMmcPartitionSize"},
{114, D<&IDeviceOperator::GetMmcPatrolCount>, "GetMmcPatrolCount"},
{115, D<&IDeviceOperator::GetAndClearMmcErrorInfo>, "GetAndClearMmcErrorInfo"},
{116, D<&IDeviceOperator::GetMmcExtendedCsd>, "GetMmcExtendedCsd"},
{117, D<&IDeviceOperator::SuspendMmcPatrol>, "SuspendMmcPatrol"},
{118, D<&IDeviceOperator::ResumeMmcPatrol>, "ResumeMmcPatrol"},
{119, D<&IDeviceOperator::EraseMmcWithRange>, "EraseMmcWithRange"},
{200, D<&IDeviceOperator::IsGameCardInserted>, "IsGameCardInserted"},
{201, D<&IDeviceOperator::EraseGameCard>, "EraseGameCard"},
{202, D<&IDeviceOperator::GetGameCardHandle>, "GetGameCardHandle"},
{203, D<&IDeviceOperator::GetGameCardUpdatePartitionInfo>, "GetGameCardUpdatePartitionInfo"},
{204, D<&IDeviceOperator::FinalizeGameCardDriver>, "FinalizeGameCardDriver"},
{205, D<&IDeviceOperator::GetGameCardAttribute>, "GetGameCardAttribute"},
{206, D<&IDeviceOperator::GetGameCardDeviceCertificate>, "GetGameCardDeviceCertificate"},
{207, D<&IDeviceOperator::GetGameCardAsicInfo>, "GetGameCardAsicInfo"},
{208, D<&IDeviceOperator::GetGameCardIdSet>, "GetGameCardIdSet"},
{209, D<&IDeviceOperator::WriteToGameCardDirectly>, "WriteToGameCardDirectly"},
{210, D<&IDeviceOperator::SetVerifyWriteEnalbleFlag>, "SetVerifyWriteEnalbleFlag"},
{211, D<&IDeviceOperator::GetGameCardImageHash>, "GetGameCardImageHash"},
{212, D<&IDeviceOperator::GetGameCardDeviceIdForProdCard>, "GetGameCardDeviceIdForProdCard"},
{213, D<&IDeviceOperator::EraseAndWriteParamDirectly>, "EraseAndWriteParamDirectly"},
{214, D<&IDeviceOperator::ReadParamDirectly>, "ReadParamDirectly"},
{215, D<&IDeviceOperator::ForceEraseGameCard>, "ForceEraseGameCard"},
{216, D<&IDeviceOperator::GetGameCardErrorInfo>, "GetGameCardErrorInfo"},
{217, D<&IDeviceOperator::GetGameCardErrorReportInfo>, "GetGameCardErrorReportInfo"},
{218, D<&IDeviceOperator::GetGameCardDeviceId>, "GetGameCardDeviceId"},
{219, D<&IDeviceOperator::ChallengeCardExistence>, "ChallengeCardExistence"},
{220, D<&IDeviceOperator::GetGameCardCompatibilityType>, "GetGameCardCompatibilityType"},
{221, D<&IDeviceOperator::GetGameCardAsicCertificate>, "GetGameCardAsicCertificate"},
{222, D<&IDeviceOperator::GetGameCardCardHeader>, "GetGameCardCardHeader"},
{223, D<&IDeviceOperator::SetGameCardSessionCreationDelay>, "SetGameCardSessionCreationDelay"},
{224, D<&IDeviceOperator::GetGameCardApplicationIdList>, "GetGameCardApplicationIdList"},
{300, D<&IDeviceOperator::SetSpeedEmulationMode>, "SetSpeedEmulationMode"},
{301, D<&IDeviceOperator::GetSpeedEmulationMode>, "GetSpeedEmulationMode"},
{302, D<&IDeviceOperator::SetApplicationStorageSpeed>, "SetApplicationStorageSpeed"},
{400, D<&IDeviceOperator::SuspendSdmmcControl>, "SuspendSdmmcControl"},
{401, D<&IDeviceOperator::ResumeSdmmcControl>, "ResumeSdmmcControl"},
{402, D<&IDeviceOperator::GetSdmmcConnectionStatus>, "GetSdmmcConnectionStatus"},
{500, D<&IDeviceOperator::SetDeviceSimulationEvent>, "SetDeviceSimulationEvent"},
{501, D<&IDeviceOperator::ClearDeviceSimulationEvent>, "ClearDeviceSimulationEvent"},
};
// clang-format on
RegisterHandlers(functions);
}
IDeviceOperator::~IDeviceOperator() = default;
Result IDeviceOperator::IsSdCardInserted(Out<bool> out_is_inserted) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_is_inserted = true;
R_SUCCEED();
}
Result IDeviceOperator::GetSdCardSpeedMode(Out<s64> out_speed_mode) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_speed_mode = 1; // Default speed mode
R_SUCCEED();
}
Result IDeviceOperator::GetSdCardCid(OutBuffer<BufferAttr_HipcMapAlias> out_cid) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
if (out_cid.size() > 0) {
std::memset(out_cid.data(), 0, out_cid.size());
}
R_SUCCEED();
}
Result IDeviceOperator::GetSdCardUserAreaSize(Out<s64> out_size) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_size = 0x10000000; // 256MB default
R_SUCCEED();
}
Result IDeviceOperator::GetSdCardProtectedAreaSize(Out<s64> out_size) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_size = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetAndClearSdCardErrorInfo(Out<s32> out_num_error_info, Out<s64> out_log_size,
OutBuffer<BufferAttr_HipcMapAlias> out_error_info) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_log_size = 0;
*out_num_error_info = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetSdCardHostControllerStatus(Out<s64> out_status) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_status = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetMmcCid(OutBuffer<BufferAttr_HipcMapAlias> out_cid) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
if (out_cid.size() > 0) {
std::memset(out_cid.data(), 0, out_cid.size());
}
R_SUCCEED();
}
Result IDeviceOperator::GetMmcSpeedMode(Out<s64> out_speed_mode) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_speed_mode = 1;
R_SUCCEED();
}
Result IDeviceOperator::EraseMmc(u32 partition_id) {
LOG_DEBUG(Service_FS, "(STUBBED) called, partition_id={}", partition_id);
R_SUCCEED();
}
Result IDeviceOperator::GetMmcPartitionSize(u32 partition_id, Out<s64> out_size) {
LOG_DEBUG(Service_FS, "(STUBBED) called, partition_id={}", partition_id);
*out_size = 0x1000000; // 16MB default
R_SUCCEED();
}
Result IDeviceOperator::GetMmcPatrolCount(Out<u32> out_patrol_count) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_patrol_count = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetAndClearMmcErrorInfo(Out<s32> out_num_error_info, Out<s64> out_log_size,
OutBuffer<BufferAttr_HipcMapAlias> out_error_info) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_log_size = 0;
*out_num_error_info = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetMmcExtendedCsd(OutBuffer<BufferAttr_HipcMapAlias> out_csd) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
if (out_csd.size() > 0) {
std::memset(out_csd.data(), 0, out_csd.size());
}
R_SUCCEED();
}
Result IDeviceOperator::SuspendMmcPatrol() {
LOG_DEBUG(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result IDeviceOperator::ResumeMmcPatrol() {
LOG_DEBUG(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result IDeviceOperator::EraseMmcWithRange(u32 partition_id, u32 offset, u32 size) {
LOG_DEBUG(Service_FS, "(STUBBED) called, partition_id={}, offset={}, size={}", partition_id, offset, size);
R_SUCCEED();
}
Result IDeviceOperator::IsGameCardInserted(Out<bool> out_is_inserted) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_is_inserted = false;
R_SUCCEED();
}
Result IDeviceOperator::EraseGameCard(u32 partition_id, u64 offset, u64 size) {
LOG_DEBUG(Service_FS, "(STUBBED) called, partition_id={}, offset={}, size={}", partition_id, offset, size);
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardHandle(Out<u32> out_handle) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_handle = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardUpdatePartitionInfo(u32 handle, Out<u32> out_title_version,
Out<u64> out_title_id) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
*out_title_version = 0;
*out_title_id = 0;
R_SUCCEED();
}
Result IDeviceOperator::FinalizeGameCardDriver() {
LOG_DEBUG(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardAttribute(u32 handle, Out<u8> out_attribute) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
*out_attribute = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardDeviceCertificate(u32 handle, Out<u64> out_size,
OutBuffer<BufferAttr_HipcMapAlias> out_certificate) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
*out_size = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardAsicInfo(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_asic_info) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
if (out_asic_info.size() > 0) {
std::memset(out_asic_info.data(), 0, out_asic_info.size());
}
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardIdSet(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_id_set) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
if (out_id_set.size() > 0) {
std::memset(out_id_set.data(), 0, out_id_set.size());
}
R_SUCCEED();
}
Result IDeviceOperator::WriteToGameCardDirectly(u32 handle, u64 offset,
InBuffer<BufferAttr_HipcMapAlias> buffer) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}, offset={}", handle, offset);
R_SUCCEED();
}
Result IDeviceOperator::SetVerifyWriteEnalbleFlag(bool is_enabled) {
LOG_DEBUG(Service_FS, "(STUBBED) called, is_enabled={}", is_enabled);
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardImageHash(u32 handle, Out<u64> out_size,
OutBuffer<BufferAttr_HipcMapAlias> out_image_hash) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
*out_size = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardDeviceIdForProdCard(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_device_id) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
if (out_device_id.size() > 0) {
std::memset(out_device_id.data(), 0, out_device_id.size());
}
R_SUCCEED();
}
Result IDeviceOperator::EraseAndWriteParamDirectly(u32 handle, InBuffer<BufferAttr_HipcMapAlias> buffer) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
R_SUCCEED();
}
Result IDeviceOperator::ReadParamDirectly(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_buffer) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
if (out_buffer.size() > 0) {
std::memset(out_buffer.data(), 0, out_buffer.size());
}
R_SUCCEED();
}
Result IDeviceOperator::ForceEraseGameCard() {
LOG_DEBUG(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardErrorInfo(Out<u64> out_error_info) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_error_info = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardErrorReportInfo(Out<u64> out_error_report_info) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_error_report_info = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardDeviceId(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_device_id) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
if (out_device_id.size() > 0) {
std::memset(out_device_id.data(), 0, out_device_id.size());
}
R_SUCCEED();
}
Result IDeviceOperator::ChallengeCardExistence(u32 handle, InBuffer<BufferAttr_HipcMapAlias> challenge_data,
OutBuffer<BufferAttr_HipcMapAlias> out_response_data) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
if (out_response_data.size() > 0) {
std::memset(out_response_data.data(), 0, out_response_data.size());
}
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardCompatibilityType(u32 handle, Out<u8> out_compatibility_type) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
*out_compatibility_type = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardAsicCertificate(u32 handle, Out<u64> out_buffer_size,
OutBuffer<BufferAttr_HipcMapAlias> out_certificate) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
*out_buffer_size = 0;
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardCardHeader(u32 handle, Out<u64> out_buffer_size,
OutBuffer<BufferAttr_HipcMapAlias> out_header) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
*out_buffer_size = 0;
R_SUCCEED();
}
Result IDeviceOperator::SetGameCardSessionCreationDelay(u64 delay_us) {
LOG_DEBUG(Service_FS, "(STUBBED) called, delay_us={}", delay_us);
R_SUCCEED();
}
Result IDeviceOperator::GetGameCardApplicationIdList(u32 handle, Out<u32> out_application_count,
OutBuffer<BufferAttr_HipcMapAlias> out_application_ids) {
LOG_DEBUG(Service_FS, "(STUBBED) called, handle={}", handle);
*out_application_count = 0;
R_SUCCEED();
}
Result IDeviceOperator::SetSpeedEmulationMode(u32 mode) {
LOG_DEBUG(Service_FS, "(STUBBED) called, mode={}", mode);
R_SUCCEED();
}
Result IDeviceOperator::GetSpeedEmulationMode(Out<u32> out_mode) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_mode = 0;
R_SUCCEED();
}
Result IDeviceOperator::SetApplicationStorageSpeed(u32 speed) {
LOG_DEBUG(Service_FS, "(STUBBED) called, speed={}", speed);
R_SUCCEED();
}
Result IDeviceOperator::SuspendSdmmcControl() {
LOG_DEBUG(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result IDeviceOperator::ResumeSdmmcControl() {
LOG_DEBUG(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result IDeviceOperator::GetSdmmcConnectionStatus(Out<u32> out_status) {
LOG_DEBUG(Service_FS, "(STUBBED) called");
*out_status = 0;
R_SUCCEED();
}
Result IDeviceOperator::SetDeviceSimulationEvent(u32 event_type) {
LOG_DEBUG(Service_FS, "(STUBBED) called, event_type={}", event_type);
R_SUCCEED();
}
Result IDeviceOperator::ClearDeviceSimulationEvent(u32 event_type) {
LOG_DEBUG(Service_FS, "(STUBBED) called, event_type={}", event_type);
R_SUCCEED();
}
} // namespace Service::FileSystem

View File

@@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::FileSystem {
class IDeviceOperator final : public ServiceFramework<IDeviceOperator> {
public:
explicit IDeviceOperator(Core::System& system_);
~IDeviceOperator() override;
private:
Result IsSdCardInserted(Out<bool> out_is_inserted);
Result GetSdCardSpeedMode(Out<s64> out_speed_mode);
Result GetSdCardCid(OutBuffer<BufferAttr_HipcMapAlias> out_cid);
Result GetSdCardUserAreaSize(Out<s64> out_size);
Result GetSdCardProtectedAreaSize(Out<s64> out_size);
Result GetAndClearSdCardErrorInfo(Out<s32> out_num_error_info, Out<s64> out_log_size,
OutBuffer<BufferAttr_HipcMapAlias> out_error_info);
Result GetSdCardHostControllerStatus(Out<s64> out_status);
Result GetMmcCid(OutBuffer<BufferAttr_HipcMapAlias> out_cid);
Result GetMmcSpeedMode(Out<s64> out_speed_mode);
Result EraseMmc(u32 partition_id);
Result GetMmcPartitionSize(u32 partition_id, Out<s64> out_size);
Result GetMmcPatrolCount(Out<u32> out_patrol_count);
Result GetAndClearMmcErrorInfo(Out<s32> out_num_error_info, Out<s64> out_log_size,
OutBuffer<BufferAttr_HipcMapAlias> out_error_info);
Result GetMmcExtendedCsd(OutBuffer<BufferAttr_HipcMapAlias> out_csd);
Result SuspendMmcPatrol();
Result ResumeMmcPatrol();
Result EraseMmcWithRange(u32 partition_id, u32 offset, u32 size);
Result IsGameCardInserted(Out<bool> out_is_inserted);
Result EraseGameCard(u32 partition_id, u64 offset, u64 size);
Result GetGameCardHandle(Out<u32> out_handle);
Result GetGameCardUpdatePartitionInfo(u32 handle, Out<u32> out_title_version,
Out<u64> out_title_id);
Result FinalizeGameCardDriver();
Result GetGameCardAttribute(u32 handle, Out<u8> out_attribute);
Result GetGameCardDeviceCertificate(u32 handle, Out<u64> out_size,
OutBuffer<BufferAttr_HipcMapAlias> out_certificate);
Result GetGameCardAsicInfo(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_asic_info);
Result GetGameCardIdSet(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_id_set);
Result WriteToGameCardDirectly(u32 handle, u64 offset,
InBuffer<BufferAttr_HipcMapAlias> buffer);
Result SetVerifyWriteEnalbleFlag(bool is_enabled);
Result GetGameCardImageHash(u32 handle, Out<u64> out_size,
OutBuffer<BufferAttr_HipcMapAlias> out_image_hash);
Result GetGameCardDeviceIdForProdCard(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_device_id);
Result EraseAndWriteParamDirectly(u32 handle, InBuffer<BufferAttr_HipcMapAlias> buffer);
Result ReadParamDirectly(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_buffer);
Result ForceEraseGameCard();
Result GetGameCardErrorInfo(Out<u64> out_error_info);
Result GetGameCardErrorReportInfo(Out<u64> out_error_report_info);
Result GetGameCardDeviceId(u32 handle, OutBuffer<BufferAttr_HipcMapAlias> out_device_id);
Result ChallengeCardExistence(u32 handle, InBuffer<BufferAttr_HipcMapAlias> challenge_data,
OutBuffer<BufferAttr_HipcMapAlias> out_response_data);
Result GetGameCardCompatibilityType(u32 handle, Out<u8> out_compatibility_type);
Result GetGameCardAsicCertificate(u32 handle, Out<u64> out_buffer_size,
OutBuffer<BufferAttr_HipcMapAlias> out_certificate);
Result GetGameCardCardHeader(u32 handle, Out<u64> out_buffer_size,
OutBuffer<BufferAttr_HipcMapAlias> out_header);
Result SetGameCardSessionCreationDelay(u64 delay_us);
Result GetGameCardApplicationIdList(u32 handle, Out<u32> out_application_count,
OutBuffer<BufferAttr_HipcMapAlias> out_application_ids);
Result SetSpeedEmulationMode(u32 mode);
Result GetSpeedEmulationMode(Out<u32> out_mode);
Result SetApplicationStorageSpeed(u32 speed);
Result SuspendSdmmcControl();
Result ResumeSdmmcControl();
Result GetSdmmcConnectionStatus(Out<u32> out_status);
Result SetDeviceSimulationEvent(u32 event_type);
Result ClearDeviceSimulationEvent(u32 event_type);
};
} // namespace Service::FileSystem

View File

@@ -0,0 +1,39 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_event_notifier.h"
#include "core/hle/service/kernel_helpers.h"
// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
#undef CreateEvent
namespace Service::FileSystem {
IEventNotifier::IEventNotifier(Core::System& system_)
: ServiceFramework{system_, "IEventNotifier"}, service_context{system_, "IEventNotifier"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IEventNotifier::GetEventHandle>, "GetEventHandle"},
};
// clang-format on
RegisterHandlers(functions);
// Create a new event for this notifier
event = service_context.CreateEvent("IEventNotifier");
}
IEventNotifier::~IEventNotifier() {
service_context.CloseEvent(event);
}
Result IEventNotifier::GetEventHandle(OutCopyHandle<Kernel::KEvent> out_event) {
LOG_DEBUG(Service_FS, "called");
*out_event = event;
R_SUCCEED();
}
} // namespace Service::FileSystem

View File

@@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Kernel {
class KEvent;
}
namespace Service::FileSystem {
class IEventNotifier final : public ServiceFramework<IEventNotifier> {
public:
explicit IEventNotifier(Core::System& system_);
~IEventNotifier() override;
private:
Result GetEventHandle(OutCopyHandle<Kernel::KEvent> out_event);
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event{};
};
} // namespace Service::FileSystem

View File

@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_exporter.h"
namespace Service::FileSystem {
ISaveDataExporter::ISaveDataExporter(Core::System& system_)
: ServiceFramework{system_, "ISaveDataExporter"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ISaveDataExporter::GetSaveDataInfo>, "GetSaveDataInfo"},
{16, D<&ISaveDataExporter::GetRestSize>, "GetRestSize"},
{17, D<&ISaveDataExporter::Pull>, "Pull"},
{18, D<&ISaveDataExporter::PullInitialData>, "PullInitialData"},
};
// clang-format on
RegisterHandlers(functions);
}
ISaveDataExporter::~ISaveDataExporter() = default;
Result ISaveDataExporter::GetSaveDataInfo(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_info) {
LOG_WARNING(Service_FS, "(STUBBED) called");
*out_size = 0;
if (out_info.size() > 0) {
std::memset(out_info.data(), 0, out_info.size());
}
R_SUCCEED();
}
Result ISaveDataExporter::GetRestSize(Out<u64> out_size) {
LOG_WARNING(Service_FS, "(STUBBED) called");
*out_size = 0;
R_SUCCEED();
}
Result ISaveDataExporter::Pull(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_buffer) {
LOG_WARNING(Service_FS, "(STUBBED) called");
*out_size = 0;
R_SUCCEED();
}
Result ISaveDataExporter::PullInitialData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer) {
LOG_WARNING(Service_FS, "(STUBBED) called");
if (out_buffer.size() > 0) {
std::memset(out_buffer.data(), 0, out_buffer.size());
}
R_SUCCEED();
}
} // namespace Service::FileSystem

View File

@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::FileSystem {
class ISaveDataExporter final : public ServiceFramework<ISaveDataExporter> {
public:
explicit ISaveDataExporter(Core::System& system_);
~ISaveDataExporter() override;
private:
Result GetSaveDataInfo(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_info);
Result GetRestSize(Out<u64> out_size);
Result Pull(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_buffer);
Result PullInitialData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer);
};
} // namespace Service::FileSystem

View File

@@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_importer.h"
namespace Service::FileSystem {
ISaveDataImporter::ISaveDataImporter(Core::System& system_)
: ServiceFramework{system_, "ISaveDataImporter"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ISaveDataImporter::GetSaveDataInfo>, "GetSaveDataInfo"},
{16, D<&ISaveDataImporter::GetRestSize>, "GetRestSize"},
{17, D<&ISaveDataImporter::Push>, "Push"},
{18, D<&ISaveDataImporter::Finalize>, "Finalize"},
};
// clang-format on
RegisterHandlers(functions);
}
ISaveDataImporter::~ISaveDataImporter() = default;
Result ISaveDataImporter::GetSaveDataInfo(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_info) {
LOG_WARNING(Service_FS, "(STUBBED) called");
*out_size = 0;
if (out_info.size() > 0) {
std::memset(out_info.data(), 0, out_info.size());
}
R_SUCCEED();
}
Result ISaveDataImporter::GetRestSize(Out<u64> out_size) {
LOG_WARNING(Service_FS, "(STUBBED) called");
*out_size = 0;
R_SUCCEED();
}
Result ISaveDataImporter::Push(InBuffer<BufferAttr_HipcMapAlias> buffer) {
LOG_WARNING(Service_FS, "(STUBBED) called, buffer_size={}", buffer.size());
R_SUCCEED();
}
Result ISaveDataImporter::Finalize() {
LOG_WARNING(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
} // namespace Service::FileSystem

View File

@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::FileSystem {
class ISaveDataImporter final : public ServiceFramework<ISaveDataImporter> {
public:
explicit ISaveDataImporter(Core::System& system_);
~ISaveDataImporter() override;
private:
Result GetSaveDataInfo(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_info);
Result GetRestSize(Out<u64> out_size);
Result Push(InBuffer<BufferAttr_HipcMapAlias> buffer);
Result Finalize();
};
} // namespace Service::FileSystem

View File

@@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_exporter.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_importer.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_transfer_manager.h"
namespace Service::FileSystem {
ISaveDataTransferManager::ISaveDataTransferManager(Core::System& system_)
: ServiceFramework{system_, "ISaveDataTransferManager"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ISaveDataTransferManager::GetChallenge>, "GetChallenge"},
{16, D<&ISaveDataTransferManager::SetToken>, "SetToken"},
{32, D<&ISaveDataTransferManager::OpenSaveDataExporter>, "OpenSaveDataExporter"},
{64, D<&ISaveDataTransferManager::OpenSaveDataImporter>, "OpenSaveDataImporter"},
};
// clang-format on
RegisterHandlers(functions);
}
ISaveDataTransferManager::~ISaveDataTransferManager() = default;
Result ISaveDataTransferManager::GetChallenge(OutBuffer<BufferAttr_HipcMapAlias> out_challenge) {
LOG_WARNING(Service_FS, "(STUBBED) called");
if (out_challenge.size() > 0) {
std::memset(out_challenge.data(), 0, out_challenge.size());
}
R_SUCCEED();
}
Result ISaveDataTransferManager::SetToken(InBuffer<BufferAttr_HipcMapAlias> token) {
LOG_WARNING(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result ISaveDataTransferManager::OpenSaveDataExporter(OutInterface<ISaveDataExporter> out_exporter,
u8 save_data_type, u64 save_data_id) {
LOG_WARNING(Service_FS, "(STUBBED) called, save_data_type={}, save_data_id={:016X}",
save_data_type, save_data_id);
*out_exporter = std::make_shared<ISaveDataExporter>(system);
R_SUCCEED();
}
Result ISaveDataTransferManager::OpenSaveDataImporter(OutInterface<ISaveDataImporter> out_importer,
u8 save_data_type,
InBuffer<BufferAttr_HipcMapAlias> initial_data_buffer) {
LOG_WARNING(Service_FS, "(STUBBED) called, save_data_type={}", save_data_type);
*out_importer = std::make_shared<ISaveDataImporter>(system);
R_SUCCEED();
}
} // namespace Service::FileSystem

View File

@@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::FileSystem {
class ISaveDataExporter;
class ISaveDataImporter;
class ISaveDataTransferManager final : public ServiceFramework<ISaveDataTransferManager> {
public:
explicit ISaveDataTransferManager(Core::System& system_);
~ISaveDataTransferManager() override;
private:
Result GetChallenge(OutBuffer<BufferAttr_HipcMapAlias> out_challenge);
Result SetToken(InBuffer<BufferAttr_HipcMapAlias> token);
Result OpenSaveDataExporter(OutInterface<ISaveDataExporter> out_exporter, u8 save_data_type,
u64 save_data_id);
Result OpenSaveDataImporter(OutInterface<ISaveDataImporter> out_importer, u8 save_data_type,
InBuffer<BufferAttr_HipcMapAlias> initial_data_buffer);
};
} // namespace Service::FileSystem

View File

@@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_wiper.h"
namespace Service::FileSystem {
IWiper::IWiper(Core::System& system_) : ServiceFramework{system_, "IWiper"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IWiper::Startup>, "Startup"},
{16, D<&IWiper::Process>, "Process"},
};
// clang-format on
RegisterHandlers(functions);
}
IWiper::~IWiper() = default;
Result IWiper::Startup() {
LOG_DEBUG(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result IWiper::Process() {
LOG_DEBUG(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
} // namespace Service::FileSystem

View File

@@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::FileSystem {
class IWiper final : public ServiceFramework<IWiper> {
public:
explicit IWiper(Core::System& system_);
~IWiper() override;
private:
Result Startup();
Result Process();
};
} // namespace Service::FileSystem

View File

@@ -1,6 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/file_sys/errors.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_filesystem.h"
#include "core/hle/service/filesystem/fsp/fsp_ldr.h"
namespace Service::FileSystem {
@@ -8,9 +12,9 @@ namespace Service::FileSystem {
FSP_LDR::FSP_LDR(Core::System& system_) : ServiceFramework{system_, "fsp:ldr"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "OpenCodeFileSystem"},
{1, nullptr, "IsArchivedProgram"},
{2, nullptr, "SetCurrentProcess"},
{0, D<&FSP_LDR::OpenCodeFileSystem>, "OpenCodeFileSystem"},
{1, D<&FSP_LDR::IsArchivedProgram>, "IsArchivedProgram"},
{2, D<&FSP_LDR::SetCurrentProcess>, "SetCurrentProcess"},
};
// clang-format on
@@ -19,4 +23,24 @@ FSP_LDR::FSP_LDR(Core::System& system_) : ServiceFramework{system_, "fsp:ldr"} {
FSP_LDR::~FSP_LDR() = default;
Result FSP_LDR::OpenCodeFileSystem(OutInterface<IFileSystem> out_interface, u64 program_id,
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path) {
LOG_WARNING(Service_FS, "(STUBBED) called, program_id={:016X}", program_id);
// This would need to open the code filesystem for the specified program
// For now, just return an error as this is not implemented
R_THROW(FileSys::ResultTargetNotFound);
}
Result FSP_LDR::IsArchivedProgram(u64 program_id, Out<bool> out_is_archived) {
LOG_WARNING(Service_FS, "(STUBBED) called, program_id={:016X}", program_id);
*out_is_archived = false;
R_SUCCEED();
}
Result FSP_LDR::SetCurrentProcess(ClientProcessId process_id) {
LOG_DEBUG(Service_FS, "called, process_id={}", *process_id);
R_SUCCEED();
}
} // namespace Service::FileSystem

View File

@@ -1,8 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/file_sys/fssrv/fssrv_sf_path.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -11,10 +14,18 @@ class System;
namespace Service::FileSystem {
class IFileSystem;
class FSP_LDR final : public ServiceFramework<FSP_LDR> {
public:
explicit FSP_LDR(Core::System& system_);
~FSP_LDR() override;
private:
Result OpenCodeFileSystem(OutInterface<IFileSystem> out_interface, u64 program_id,
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path);
Result IsArchivedProgram(u64 program_id, Out<bool> out_is_archived);
Result SetCurrentProcess(ClientProcessId process_id);
};
} // namespace Service::FileSystem

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fsp_pr.h"
namespace Service::FileSystem {
@@ -8,10 +10,10 @@ namespace Service::FileSystem {
FSP_PR::FSP_PR(Core::System& system_) : ServiceFramework{system_, "fsp:pr"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RegisterProgram"},
{1, nullptr, "UnregisterProgram"},
{2, nullptr, "SetCurrentProcess"},
{256, nullptr, "SetEnabledProgramVerification"},
{0, D<&FSP_PR::RegisterProgram>, "RegisterProgram"},
{1, D<&FSP_PR::UnregisterProgram>, "UnregisterProgram"},
{2, D<&FSP_PR::SetCurrentProcess>, "SetCurrentProcess"},
{256, D<&FSP_PR::SetEnabledProgramVerification>, "SetEnabledProgramVerification"},
};
// clang-format on
@@ -20,4 +22,26 @@ FSP_PR::FSP_PR(Core::System& system_) : ServiceFramework{system_, "fsp:pr"} {
FSP_PR::~FSP_PR() = default;
Result FSP_PR::RegisterProgram(u64 program_id, u64 storage_id, InBuffer<BufferAttr_HipcMapAlias> data,
InBuffer<BufferAttr_HipcMapAlias> meta) {
LOG_WARNING(Service_FS, "(STUBBED) called, program_id={:016X}, storage_id={:016X}",
program_id, storage_id);
R_SUCCEED();
}
Result FSP_PR::UnregisterProgram(u64 program_id) {
LOG_WARNING(Service_FS, "(STUBBED) called, program_id={:016X}", program_id);
R_SUCCEED();
}
Result FSP_PR::SetCurrentProcess(ClientProcessId process_id) {
LOG_DEBUG(Service_FS, "called, process_id={}", *process_id);
R_SUCCEED();
}
Result FSP_PR::SetEnabledProgramVerification(bool enabled) {
LOG_WARNING(Service_FS, "(STUBBED) called, enabled={}", enabled);
R_SUCCEED();
}
} // namespace Service::FileSystem

View File

@@ -1,8 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -15,6 +17,13 @@ class FSP_PR final : public ServiceFramework<FSP_PR> {
public:
explicit FSP_PR(Core::System& system_);
~FSP_PR() override;
private:
Result RegisterProgram(u64 program_id, u64 storage_id, InBuffer<BufferAttr_HipcMapAlias> data,
InBuffer<BufferAttr_HipcMapAlias> meta);
Result UnregisterProgram(u64 program_id);
Result SetCurrentProcess(ClientProcessId process_id);
Result SetEnabledProgramVerification(bool enabled);
};
} // namespace Service::FileSystem

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cinttypes>
@@ -29,10 +30,14 @@
#include "core/hle/result.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp/fs_i_device_operator.h"
#include "core/hle/service/filesystem/fsp/fs_i_event_notifier.h"
#include "core/hle/service/filesystem/fsp/fs_i_filesystem.h"
#include "core/hle/service/filesystem/fsp/fs_i_multi_commit_manager.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_transfer_manager.h"
#include "core/hle/service/filesystem/fsp/fs_i_storage.h"
#include "core/hle/service/filesystem/fsp/fs_i_wiper.h"
#include "core/hle/service/filesystem/fsp/fsp_srv.h"
#include "core/hle/service/filesystem/fsp/save_data_transfer_prohibiter.h"
#include "core/hle/service/filesystem/romfs_controller.h"
@@ -56,12 +61,12 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{8, nullptr, "OpenFileSystemWithId"},
{9, nullptr, "OpenDataFileSystemByApplicationId"},
{11, nullptr, "OpenBisFileSystem"},
{12, nullptr, "OpenBisStorage"},
{12, D<&FSP_SRV::OpenBisStorage>, "OpenBisStorage"},
{13, nullptr, "InvalidateBisCache"},
{17, nullptr, "OpenHostFileSystem"},
{18, D<&FSP_SRV::OpenSdCardFileSystem>, "OpenSdCardFileSystem"},
{19, nullptr, "FormatSdCardFileSystem"},
{21, nullptr, "DeleteSaveDataFileSystem"},
{21, D<&FSP_SRV::DeleteSaveDataFileSystem>, "DeleteSaveDataFileSystem"},
{22, D<&FSP_SRV::CreateSaveDataFileSystem>, "CreateSaveDataFileSystem"},
{23, D<&FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId>, "CreateSaveDataFileSystemBySystemSaveDataId"},
{24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
@@ -69,8 +74,8 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{26, nullptr, "FormatSdCardDryRun"},
{27, nullptr, "IsExFatSupported"},
{28, nullptr, "DeleteSaveDataFileSystemBySaveDataAttribute"},
{30, nullptr, "OpenGameCardStorage"},
{31, nullptr, "OpenGameCardFileSystem"},
{30, D<&FSP_SRV::OpenGameCardStorage>, "OpenGameCardStorage"},
{31, D<&FSP_SRV::OpenGameCardFileSystem>, "OpenGameCardFileSystem"},
{32, D<&FSP_SRV::ExtendSaveDataFileSystem>, "ExtendSaveDataFileSystem"},
{33, nullptr, "DeleteCacheStorage"},
{34, D<&FSP_SRV::GetCacheStorageSize>, "GetCacheStorageSize"},
@@ -94,8 +99,8 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{70, D<&FSP_SRV::WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute>, "WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"},
{71, D<&FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute>, "ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"},
{80, nullptr, "OpenSaveDataMetaFile"},
{81, nullptr, "OpenSaveDataTransferManager"},
{82, nullptr, "OpenSaveDataTransferManagerVersion2"},
{81, D<&FSP_SRV::OpenSaveDataTransferManager>, "OpenSaveDataTransferManager"},
{82, D<&FSP_SRV::OpenSaveDataTransferManagerVersion2>, "OpenSaveDataTransferManagerVersion2"},
{83, D<&FSP_SRV::OpenSaveDataTransferProhibiter>, "OpenSaveDataTransferProhibiter"},
{84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"},
{85, nullptr, "OpenSaveDataTransferManagerForSaveDataRepair"},
@@ -114,9 +119,9 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{204, nullptr, "OpenDataFileSystemByProgramIndex"},
{205, D<&FSP_SRV::OpenDataStorageWithProgramIndex>, "OpenDataStorageWithProgramIndex"},
{206, nullptr, "OpenDataStorageByPath"},
{400, nullptr, "OpenDeviceOperator"},
{500, nullptr, "OpenSdCardDetectionEventNotifier"},
{501, nullptr, "OpenGameCardDetectionEventNotifier"},
{400, D<&FSP_SRV::OpenDeviceOperator>, "OpenDeviceOperator"},
{500, D<&FSP_SRV::OpenSdCardDetectionEventNotifier>, "OpenSdCardDetectionEventNotifier"},
{501, D<&FSP_SRV::OpenGameCardDetectionEventNotifier>, "OpenGameCardDetectionEventNotifier"},
{510, nullptr, "OpenSystemDataUpdateEventNotifier"},
{511, nullptr, "NotifySystemDataUpdateEvent"},
{520, nullptr, "SimulateGameCardDetectionEvent"},
@@ -171,7 +176,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
{1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"},
{1200, D<&FSP_SRV::OpenMultiCommitManager>, "OpenMultiCommitManager"},
{1300, nullptr, "OpenBisWiper"},
{1300, D<&FSP_SRV::OpenBisWiper>, "OpenBisWiper"},
};
// clang-format on
RegisterHandlers(functions);
@@ -549,4 +554,80 @@ Result FSP_SRV::OpenMultiCommitManager(OutInterface<IMultiCommitManager> out_int
R_SUCCEED();
}
Result FSP_SRV::OpenDeviceOperator(OutInterface<IDeviceOperator> out_interface) {
LOG_DEBUG(Service_FS, "called");
*out_interface = std::make_shared<IDeviceOperator>(system);
R_SUCCEED();
}
Result FSP_SRV::OpenSdCardDetectionEventNotifier(OutInterface<IEventNotifier> out_interface) {
LOG_DEBUG(Service_FS, "called");
*out_interface = std::make_shared<IEventNotifier>(system);
R_SUCCEED();
}
Result FSP_SRV::OpenGameCardDetectionEventNotifier(OutInterface<IEventNotifier> out_interface) {
LOG_DEBUG(Service_FS, "called");
*out_interface = std::make_shared<IEventNotifier>(system);
R_SUCCEED();
}
Result FSP_SRV::OpenSaveDataTransferManager(OutInterface<ISaveDataTransferManager> out_interface) {
LOG_DEBUG(Service_FS, "called");
*out_interface = std::make_shared<ISaveDataTransferManager>(system);
R_SUCCEED();
}
Result FSP_SRV::OpenSaveDataTransferManagerVersion2(OutInterface<ISaveDataTransferManager> out_interface) {
LOG_DEBUG(Service_FS, "called");
*out_interface = std::make_shared<ISaveDataTransferManager>(system);
R_SUCCEED();
}
Result FSP_SRV::OpenBisWiper(OutInterface<IWiper> out_interface) {
LOG_DEBUG(Service_FS, "called");
*out_interface = std::make_shared<IWiper>(system);
R_SUCCEED();
}
Result FSP_SRV::OpenBisStorage(OutInterface<IStorage> out_interface, u32 partition_id) {
LOG_WARNING(Service_FS, "(STUBBED) called, partition_id={}", partition_id);
// Would need to open the BIS storage for the specified partition
R_THROW(FileSys::ResultTargetNotFound);
}
Result FSP_SRV::DeleteSaveDataFileSystem(u64 save_data_id) {
LOG_WARNING(Service_FS, "(STUBBED) called, save_data_id={:016X}", save_data_id);
// Would need to delete the save data with the given ID
R_SUCCEED();
}
Result FSP_SRV::OpenGameCardStorage(OutInterface<IStorage> out_interface, u32 handle, u32 partition_id) {
LOG_WARNING(Service_FS, "(STUBBED) called, handle={}, partition_id={}", handle, partition_id);
// Would need to open game card storage for the specified handle and partition
R_THROW(FileSys::ResultTargetNotFound);
}
Result FSP_SRV::OpenGameCardFileSystem(OutInterface<IFileSystem> out_interface, u32 handle, u32 partition_id) {
LOG_WARNING(Service_FS, "(STUBBED) called, handle={}, partition_id={}", handle, partition_id);
// Would need to open game card filesystem for the specified handle and partition
R_THROW(FileSys::ResultTargetNotFound);
}
} // namespace Service::FileSystem

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -23,11 +24,15 @@ namespace Service::FileSystem {
class RomFsController;
class SaveDataController;
class IDeviceOperator;
class IEventNotifier;
class IFileSystem;
class ISaveDataInfoReader;
class ISaveDataTransferManager;
class ISaveDataTransferProhibiter;
class IStorage;
class IMultiCommitManager;
class IWiper;
enum class AccessLogVersion : u32 {
V7_0_0 = 2,
@@ -106,6 +111,16 @@ private:
Result ExtendSaveDataFileSystem(FileSys::SaveDataSpaceId space_id, u64 save_data_id,
s64 available_size, s64 journal_size);
Result GetCacheStorageSize(s32 index, Out<s64> out_data_size, Out<s64> out_journal_size);
Result OpenDeviceOperator(OutInterface<IDeviceOperator> out_interface);
Result OpenSdCardDetectionEventNotifier(OutInterface<IEventNotifier> out_interface);
Result OpenGameCardDetectionEventNotifier(OutInterface<IEventNotifier> out_interface);
Result OpenSaveDataTransferManager(OutInterface<ISaveDataTransferManager> out_interface);
Result OpenSaveDataTransferManagerVersion2(OutInterface<ISaveDataTransferManager> out_interface);
Result OpenBisWiper(OutInterface<IWiper> out_interface);
Result OpenBisStorage(OutInterface<IStorage> out_interface, u32 partition_id);
Result DeleteSaveDataFileSystem(u64 save_data_id);
Result OpenGameCardStorage(OutInterface<IStorage> out_interface, u32 handle, u32 partition_id);
Result OpenGameCardFileSystem(OutInterface<IFileSystem> out_interface, u32 handle, u32 partition_id);
FileSystemController& fsc;
const FileSys::ContentProvider& content_provider;