diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/kernel/archive.cpp | 98 | ||||
-rw-r--r-- | src/core/hle/kernel/archive.h | 17 | ||||
-rw-r--r-- | src/core/hle/service/fs.cpp | 33 |
3 files changed, 135 insertions, 13 deletions
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index d7351e702..f31c02ea9 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp @@ -4,6 +4,8 @@ #include "common/common_types.h" +#include "core/file_sys/archive.h" +#include "core/hle/service/service.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/archive.h" @@ -12,6 +14,21 @@ namespace Kernel { +// Command to access archive file +enum class FileCommand : u32 { + Dummy1 = 0x000100C6, + Control = 0x040100C4, + OpenSubFile = 0x08010100, + Read = 0x080200C2, + Write = 0x08030102, + GetSize = 0x08040000, + SetSize = 0x08050080, + GetAttributes = 0x08060000, + SetAttributes = 0x08070040, + Close = 0x08080000, + Flush = 0x08090000, +}; + class Archive : public Object { public: const char* GetTypeName() const { return "Archive"; } @@ -20,7 +37,37 @@ public: static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; } Kernel::HandleType GetHandleType() const { return HandleType::Archive; } - std::string name; ///< Name of archive (optional) + std::string name; ///< Name of archive (optional) + FileSys::Archive* backend; ///< Archive backend interface + + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { + u32* cmd_buff = Service::GetCommandBuffer(); + FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); + switch (cmd) { + + // Read from archive... + case FileCommand::Read: + { + u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; + u32 length = cmd_buff[3]; + u32 address = cmd_buff[5]; + cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); + break; + } + + // Unknown command... + default: + ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); + return -1; + } + cmd_buff[1] = 0; // No error + return 0; + } /** * Wait for kernel object to synchronize @@ -29,32 +76,71 @@ public: */ Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe - ERROR_LOG(OSHLE, "unimplemented function"); + ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); return 0; } }; +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode + +/** + * Opens an archive + * @param id_code IdCode of the archive to open + * @return Handle to archive if it exists, otherwise a null handle (0) + */ +Handle OpenArchive(FileSys::Archive::IdCode id_code) { + auto itr = g_archive_map.find(id_code); + if (itr == g_archive_map.end()) { + return 0; + } + return itr->second; +} + +/** + * Mounts an archive + * @param archive Pointer to the archive to mount + * @return Result of operation, 0 on success, otherwise error code + */ +Result MountArchive(Archive* archive) { + FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); + if (0 != OpenArchive(id_code)) { + ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); + return -1; + } + g_archive_map[id_code] = archive->GetHandle(); + INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName()); + return 0; +} + /** * Creates an Archive - * @param name Optional name of Archive * @param handle Handle to newly created archive object + * @param backend File system backend interface to the archive + * @param name Optional name of Archive * @return Newly created Archive object */ -Archive* CreateArchive(Handle& handle, const std::string& name) { +Archive* CreateArchive(Handle& handle, FileSys::Archive* backend, const std::string& name) { Archive* archive = new Archive; handle = Kernel::g_object_pool.Create(archive); archive->name = name; + archive->backend = backend; + + MountArchive(archive); + return archive; } /** * Creates an Archive + * @param backend File system backend interface to the archive * @param name Optional name of Archive * @return Handle to newly created Archive object */ -Handle CreateArchive(const std::string& name) { +Handle CreateArchive(FileSys::Archive* backend, const std::string& name) { Handle handle; - Archive* archive = CreateArchive(handle, name); + Archive* archive = CreateArchive(handle, backend, name); return handle; } diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h index 98670f06c..07fb37ae7 100644 --- a/src/core/hle/kernel/archive.h +++ b/src/core/hle/kernel/archive.h @@ -7,6 +7,7 @@ #include "common/common_types.h" #include "core/hle/kernel/kernel.h" +#include "core/file_sys/archive.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Kernel namespace @@ -14,10 +15,18 @@ namespace Kernel { /** - * Creates an archive - * @param name Optional name of archive - * @return Handle to newly created archive object + * Opens an archive + * @param id_code IdCode of the archive to open + * @return Handle to archive if it exists, otherwise a null handle (0) */ -Handle CreateArchive(const std::string& name="Unknown"); +Handle OpenArchive(FileSys::Archive::IdCode id_code); + +/** + * Creates an Archive + * @param backend File system backend interface to the archive + * @param name Optional name of Archive + * @return Handle to newly created Archive object + */ +Handle CreateArchive(FileSys::Archive* backend, const std::string& name); } // namespace FileSys diff --git a/src/core/hle/service/fs.cpp b/src/core/hle/service/fs.cpp index 3a5afaa3c..5eabf36ad 100644 --- a/src/core/hle/service/fs.cpp +++ b/src/core/hle/service/fs.cpp @@ -2,11 +2,12 @@ // Licensed under GPLv2 // Refer to the license.txt file included. - #include "common/common.h" +#include "core/loader/loader.h" #include "core/hle/hle.h" #include "core/hle/service/fs.h" +#include "core/hle/kernel/archive.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace FS_User @@ -15,8 +16,34 @@ namespace FS_User { void Initialize(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); - DEBUG_LOG(KERNEL, "called"); cmd_buff[1] = 0; // No error + DEBUG_LOG(KERNEL, "called"); +} + +void OpenFileDirectly(Service::Interface* self) { + u32* cmd_buff = Service::GetCommandBuffer(); + + FileSys::Archive::IdCode arch_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); + + // TODO(bunnei): Properly implement use of these... + //u32 transaction = cmd_buff[1]; + //u32 arch_lowpath_type = cmd_buff[3]; + //u32 arch_lowpath_sz = cmd_buff[4]; + //u32 file_lowpath_type = cmd_buff[5]; + //u32 file_lowpath_sz = cmd_buff[6]; + //u32 flags = cmd_buff[7]; + //u32 attr = cmd_buff[8]; + //u32 arch_lowpath_desc = cmd_buff[9]; + //u32 arch_lowpath_ptr = cmd_buff[10]; + //u32 file_lowpath_desc = cmd_buff[11]; + //u32 file_lowpath_ptr = cmd_buff[12]; + + Handle handle = Kernel::OpenArchive(arch_id); + if (0 != handle) { + cmd_buff[1] = 0; // No error + cmd_buff[3] = handle; + } + DEBUG_LOG(KERNEL, "called"); } const Interface::FunctionInfo FunctionTable[] = { @@ -24,7 +51,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x040100C4, nullptr, "Control"}, {0x08010002, Initialize, "Initialize"}, {0x080201C2, nullptr, "OpenFile"}, - {0x08030204, nullptr, "OpenFileDirectly"}, + {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, {0x08040142, nullptr, "DeleteFile"}, {0x08050244, nullptr, "RenameFile"}, {0x08060142, nullptr, "DeleteDirectory"}, |