mikage-dev/source/processes/fs.hpp

225 lines
12 KiB
C++
Raw Normal View History

2024-03-07 22:05:16 +01:00
#pragma once
#include "fake_process.hpp"
#include "../platform/fs.hpp"
#include <memory>
#include <string>
namespace HLE {
using Platform::FS::ArchiveHandle;
class FakeFS;
using OS::FakeProcess;
using OS::FakeThread;
using OS::RESULT_OK;
using Result = OS::OS::Result;
using OS::HandleTable;
using OS::Handle;
using OS::Event;
using OS::ProcessId;
struct FileContext {
spdlog::logger& logger;
};
/**
* Interface for an internal buffer used as the data source/target for file
* read/write operations.
*
* Usually, files operate on emulated memory, but it's beneficial for code
* reuse in frontend code to enable file implementations to work with
* host memory, too. This class enables this by abstracting away the notion
* of emulated memory.
*/
class FileBuffer {
public:
/// Read the specified number of bytes from the internal buffer to dest
// virtual void Read(char* dest, uint32_t num_bytes) = 0;
/// Write the specified number of bytes from the source to the internal buffer
virtual void Write(char* source, uint32_t num_bytes) = 0;
};
class File {
friend class SubFile;
void Fail();
// True if this file is the reference file of a SubFile. While a sub file
// is open, no operations may be requested on the parent file.
bool has_subfile = false;
public:
virtual ~File() = default;
// Returns result code and number of bytes read (0 on error)
virtual OS::OS::ResultAnd<uint32_t> Read(FileContext&, FakeFS&, uint64_t offset, uint32_t num_bytes, FileBuffer& target)/* = 0*/;
// Returns result code and number of bytes written (0 on error)
virtual OS::OS::ResultAnd<uint32_t> Write(FakeThread& thread, FakeFS&, uint64_t offset, uint32_t num_bytes, uint32_t options, uint32_t buffer_addr)/* = 0*/;
// Returns result code and file size in bytes (0 on error)
virtual OS::OS::ResultAnd<uint64_t> GetSize(FakeThread& thread, FakeFS&)/* = 0*/ { Fail(); return std::make_tuple(RESULT_OK, 0);}
virtual OS::OS::ResultAnd<> SetSize(FakeThread& thread, FakeFS&, uint64_t size) { Fail(); return std::make_tuple(RESULT_OK);}
virtual const char* GetFileName() {
static std::string buffer;
buffer = std::string("(unknown ") + typeid(*this).name() + ")";
return buffer.c_str();
}
bool HasOpenSubFile() const noexcept;
};
class Directory;
class Archive {
public:
virtual ~Archive() = default;
virtual Platform::FS::ArchiveFormatInfo GetFormatInfo(FakeThread&, FakeFS&);
virtual std::pair<Result,std::unique_ptr<File>> OpenFile(FakeThread&, FakeFS&, uint32_t transaction, uint32_t open_flags, uint32_t attributes, uint32_t path_type, IPC::StaticBuffer path) = 0;
virtual Result CreateDirectory(FakeThread&, FakeFS&, uint32_t path_type, IPC::StaticBuffer path) = 0;
virtual std::pair<Result,std::unique_ptr<Directory>> OpenDirectory(FakeThread&, FakeFS&, uint32_t path_type, IPC::StaticBuffer path) = 0;
virtual Result CreateFile(FakeThread&, FakeFS&, uint32_t transaction, uint32_t attributes, uint64_t size, uint32_t path_type, IPC::StaticBuffer path);
virtual Result DeleteFile(FakeThread&, FakeFS&, uint32_t transaction, uint32_t path_type, IPC::StaticBuffer path) = 0;
virtual Result RenameFile(FakeThread&, FakeFS&, uint32_t transaction, uint32_t source_path_type, IPC::StaticBuffer source_path, uint32_t target_path_type, IPC::StaticBuffer target_path) = 0;
virtual Result DeleteDirectory(FakeThread&, FakeFS&, uint32_t transaction, bool recursive, uint32_t path_type, IPC::StaticBuffer path) = 0;
};
struct FSServiceHelper : HLE::OS::ServiceHelper {
// nullptr for ports; uint32_t (port handle index) for fs:USER/LDR sessions; others are self-explanatory
using HandleData = std::variant<decltype(nullptr), uint32_t, std::shared_ptr<File>, std::shared_ptr<Directory>>;
template<typename T>
uint32_t Append(HandleTable::Entry<T> entry, FSServiceHelper::HandleData data = nullptr);
void Erase(int32_t index) override;
void OnNewSession(int32_t port_index, HandleTable::Entry<OS::ServerSession> session) override;
/// Replaces the File object in the indexed HandleData with a new one. The previous object will be destroyed.
void ReplaceFileServer(int32_t index, std::unique_ptr<File> new_file);
std::vector<HandleData> handle_data;
};
class FakeFS {
struct ProcessInfo {
Platform::FS::ProgramInfo program;
Platform::FS::StorageInfo storage;
};
public: // TODO: Un-public-ize
FSServiceHelper service;
// Map from session handles to the ProcessId assigned via FSUser::Initialize
std::unordered_map<Handle,ProcessId> fsuser_process_ids;
std::unordered_map<ProcessId, ProcessInfo> process_infos;
std::unordered_map<ArchiveHandle, std::unique_ptr<Archive>> archives;
uint64_t next_archive_handle = 0;
// TODO: Clarify what thread these belong to, and make sure they are *NOT* shared between threads!
uint32_t static_buffer_size = 0x1000;
uint32_t static_buffer_addr[3];
Handle pxifs_session;
// handle table indices
uint32_t fsuser_handle_index;
uint32_t fsldr_handle_index;
void FSRegThread(FakeThread& thread);
void FSUserThread(FakeThread& thread);
decltype(HLE::OS::ServiceHelper::SendReply) RegCommandHandler(FakeThread& thread, IPC::CommandHeader header);
decltype(HLE::OS::ServiceHelper::SendReply) UserCommandHandler(FakeThread& thread, Handle sender, const IPC::CommandHeader& header);
OS::OS::ResultAnd<> OnReg_Register(FakeThread& thread, ProcessId pid, Platform::PXI::PM::ProgramHandle program_handle, Platform::PXI::PM::ProgramInfo program_info, Platform::FS::StorageInfo);
OS::OS::ResultAnd<> OnReg_Unregister(FakeThread& thread, ProcessId pid);
OS::OS::ResultAnd<> OnReg_CheckHostLoadId(FakeThread& thread, Platform::PXI::PM::ProgramHandle program_handle);
std::tuple<OS::Result> HandleInitialize(FakeThread& thread, Handle session_handle, ProcessId id);
std::tuple<OS::Result> HandleInitializeWithSdkVersion(FakeThread& thread, Handle session_handle, uint32_t version, ProcessId id);
std::tuple<OS::Result, Handle> HandleOpenFile(FakeThread& thread, ProcessId session_id, uint32_t transaction, uint64_t archive_handle, uint32_t path_type, uint32_t path_size, uint32_t open_flags, uint32_t attributes, IPC::StaticBuffer path);
std::tuple<OS::Result, Handle> HandleOpenFileDirectly(FakeThread& thread, ProcessId session_id, uint32_t transaction, uint32_t archive_id, uint32_t archive_path_type, uint32_t archive_path_size, uint32_t file_path_type, uint32_t file_path_size, uint32_t open_flags, uint32_t attributes, const IPC::StaticBuffer& archive_path, const IPC::StaticBuffer& file_path);
std::tuple<OS::Result> HandleDeleteFile(FakeThread& thread, ProcessId session_id, uint32_t transaction, uint64_t archive_handle,
uint32_t file_path_type, uint32_t file_path_size, IPC::StaticBuffer file_path);
std::tuple<OS::Result> HandleRenameFile(FakeThread& thread, uint32_t transaction,
uint64_t source_archive_handle, uint32_t source_file_path_type, uint32_t source_file_path_size,
uint64_t target_archive_handle, uint32_t target_file_path_type, uint32_t target_file_path_size,
IPC::StaticBuffer source_file_path, IPC::StaticBuffer target_file_path);
std::tuple<OS::Result> HandleDeleteDirectory(FakeThread& thread, ProcessId session_id, bool recursive,
uint32_t transaction, ArchiveHandle archive_handle,
uint32_t dir_path_type, uint32_t dir_path_size,
IPC::StaticBuffer dir_path);
std::tuple<OS::Result> HandleCreateFile(FakeThread& thread, ProcessId session_id, uint32_t transaction,
uint64_t archive_handle, uint32_t file_path_type, uint32_t file_path_size,
uint32_t attributes, uint64_t initial_file_size,
IPC::StaticBuffer file_path);
std::tuple<OS::Result> HandleCreateDirectory(FakeThread& thread, ProcessId session_id, uint32_t transaction,
uint64_t archive_handle, uint32_t dir_path_type, uint32_t dir_path_size,
uint32_t attributes, IPC::StaticBuffer dir_path);
std::tuple<OS::Result, Handle> HandleOpenDirectory(FakeThread& thread, ProcessId session_id, uint64_t archive_handle, uint32_t path_type, uint32_t path_size, IPC::StaticBuffer path);
std::tuple<OS::Result, uint64_t> HandleOpenArchive(FakeThread& thread, ProcessId session_id, uint32_t archive_id, uint32_t path_type, uint32_t path_size, IPC::StaticBuffer path);
std::tuple<OS::Result, IPC::MappedBuffer, IPC::MappedBuffer> HandleControlArchive(FakeThread& thread, ProcessId session_id, uint64_t archive_handle, uint32_t action, uint32_t input_size, uint32_t output_size, IPC::MappedBuffer input, IPC::MappedBuffer output);
std::tuple<OS::Result> HandleCloseArchive(FakeThread& thread, ProcessId session_id, uint64_t archive_handle);
std::tuple<OS::Result> HandleFormatOwnSaveData(FakeThread& thread, ProcessId session_id, uint32_t block_size,
uint32_t num_dirs, uint32_t num_files, uint32_t num_dir_buckets,
uint32_t num_file_buckets, uint32_t unknown);
std::tuple<OS::Result, uint32_t> HandleIsSdmcDetected(FakeThread& thread);
std::tuple<OS::Result, uint32_t> HandleGetPriority(FakeThread& thread);
std::tuple<OS::Result, Platform::PXI::PM::ProgramInfo> HandleGetProgramLaunchInfo(FakeThread& thread, ProcessId id);
std::tuple<OS::Result, Platform::FS::ArchiveFormatInfo>
HandleGetFormatInfo(FakeThread& thread, ProcessId session_id, Platform::FS::ArchiveId archive_id,
uint32_t archive_path_type, uint32_t archive_path_size, IPC::StaticBuffer archive_path);
std::tuple<OS::Result> HandleFormatSaveData(FakeThread& thread, ProcessId session_id, Platform::FS::ArchiveId archive_id,
uint32_t path_type, uint32_t path_size, uint32_t num_blocks,
uint32_t num_dirs, uint32_t num_files, uint32_t num_dir_buckets,
uint32_t num_file_buckets, uint32_t unknown, IPC::StaticBuffer archive_path);
std::tuple<OS::Result, IPC::MappedBuffer> HandleCreateExtSaveData(FakeThread& thread, ProcessId session_id, const Platform::FS::ExtSaveDataInfo& info,
uint32_t num_directories, uint32_t num_files, uint64_t size_limit,
uint32_t smdh_size, IPC::MappedBuffer smdh);
std::tuple<OS::Result, IPC::MappedBuffer> HandleCreateExtSaveDataLegacy(FakeThread& thread, ProcessId session_id, uint32_t media_type,
uint64_t save_id, uint32_t smdh_size, uint32_t num_directories, uint32_t num_files,
IPC::MappedBuffer smdh);
std::tuple<OS::Result> HandleDeleteExtSaveData(FakeThread& thread, ProcessId session_id, const Platform::FS::ExtSaveDataInfo& info);
std::tuple<OS::Result> HandleCreateSystemSaveData(FakeThread& thread, ProcessId session_id, uint32_t media_type, uint32_t save_id,
uint32_t total_size, uint32_t block_size, uint32_t num_directories,
uint32_t num_files, uint32_t unk1, uint32_t unk2, uint32_t unk3);
std::tuple<OS::Result, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, IPC::MappedBuffer>
HandleUpdateSha256Context( FakeThread& thread, ProcessId session_id, uint32_t, uint32_t, uint32_t, uint32_t,
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
uint32_t, IPC::MappedBuffer);
FakeProcess& process;
spdlog::logger& logger;
FileContext file_context { logger };
2024-03-24 10:53:38 +01:00
Settings::Settings& settings;
2024-03-07 22:05:16 +01:00
public:
FakeFS(FakeThread& thread);
~FakeFS();
};
} // namespace HLE