From 0cc3e85685496f1dd5b742c42d0b2903b9f0c735 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 25 Jun 2014 17:32:09 -0400 Subject: Core: Removed unused directory_file_system and meta_file_system modules. Core: Updated CMakeLists.txt to remove directory_file_system and meta_file_system modules. --- src/core/core.vcxproj | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/core/core.vcxproj') diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index e2216760a..d92825a0e 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -162,8 +162,6 @@ - - @@ -211,9 +209,7 @@ - - -- cgit v1.2.3 From 8b8c8f4c13c8959853aadf931161f2b867158068 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 25 Jun 2014 18:15:35 -0400 Subject: Kernel: Added stubbed code to support creation of kernel Archive objects. --- src/core/CMakeLists.txt | 2 ++ src/core/core.vcxproj | 2 ++ src/core/core.vcxproj.filters | 6 ++++ src/core/hle/kernel/archive.cpp | 61 +++++++++++++++++++++++++++++++++++++++++ src/core/hle/kernel/archive.h | 23 ++++++++++++++++ src/core/hle/kernel/kernel.h | 1 + 6 files changed, 95 insertions(+) create mode 100644 src/core/hle/kernel/archive.cpp create mode 100644 src/core/hle/kernel/archive.h (limited to 'src/core/core.vcxproj') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e534f07c4..204c5d45a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -33,6 +33,7 @@ set(SRCS core.cpp hle/config_mem.cpp hle/coprocessor.cpp hle/svc.cpp + hle/kernel/archive.cpp hle/kernel/event.cpp hle/kernel/kernel.cpp hle/kernel/mutex.cpp @@ -78,6 +79,7 @@ set(HEADERS core.h hle/coprocessor.h hle/hle.h hle/svc.h + hle/kernel/archive.h hle/kernel/kernel.h hle/kernel/mutex.h hle/kernel/thread.h diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index d92825a0e..85ac50818 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -165,6 +165,7 @@ + @@ -214,6 +215,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 8f1751c5d..37c550d56 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -170,6 +170,9 @@ loader + + hle\kernel + @@ -302,6 +305,9 @@ loader + + hle\kernel + diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp new file mode 100644 index 000000000..d7351e702 --- /dev/null +++ b/src/core/hle/kernel/archive.cpp @@ -0,0 +1,61 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/archive.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Kernel namespace + +namespace Kernel { + +class Archive : public Object { +public: + const char* GetTypeName() const { return "Archive"; } + const char* GetName() const { return name.c_str(); } + + static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; } + Kernel::HandleType GetHandleType() const { return HandleType::Archive; } + + std::string name; ///< Name of archive (optional) + + /** + * Wait for kernel object to synchronize + * @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 WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe + ERROR_LOG(OSHLE, "unimplemented function"); + return 0; + } +}; + +/** + * Creates an Archive + * @param name Optional name of Archive + * @param handle Handle to newly created archive object + * @return Newly created Archive object + */ +Archive* CreateArchive(Handle& handle, const std::string& name) { + Archive* archive = new Archive; + handle = Kernel::g_object_pool.Create(archive); + archive->name = name; + return archive; +} + +/** + * Creates an Archive + * @param name Optional name of Archive + * @return Handle to newly created Archive object + */ +Handle CreateArchive(const std::string& name) { + Handle handle; + Archive* archive = CreateArchive(handle, name); + return handle; +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h new file mode 100644 index 000000000..98670f06c --- /dev/null +++ b/src/core/hle/kernel/archive.h @@ -0,0 +1,23 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Kernel namespace + +namespace Kernel { + +/** + * Creates an archive + * @param name Optional name of archive + * @return Handle to newly created archive object + */ +Handle CreateArchive(const std::string& name="Unknown"); + +} // namespace FileSys diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3f15da0ac..69f4ddd37 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -29,6 +29,7 @@ enum class HandleType : u32 { Arbiter = 9, File = 10, Semaphore = 11, + Archive = 12, }; enum { -- cgit v1.2.3 From 48e39fc9928f3dabc1954c1acb650d2f57f6a491 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 26 Jun 2014 17:58:44 -0400 Subject: FS: Added stubbed code to intercept and decode file system service functions. FS: Added to CMakeLists.txt --- src/core/CMakeLists.txt | 2 + src/core/core.vcxproj | 2 + src/core/core.vcxproj.filters | 6 ++ src/core/hle/service/fs.cpp | 121 +++++++++++++++++++++++++++++++++++++++ src/core/hle/service/fs.h | 31 ++++++++++ src/core/hle/service/service.cpp | 2 + 6 files changed, 164 insertions(+) create mode 100644 src/core/hle/service/fs.cpp create mode 100644 src/core/hle/service/fs.h (limited to 'src/core/core.vcxproj') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 204c5d45a..978e956dc 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRCS core.cpp hle/kernel/mutex.cpp hle/kernel/thread.cpp hle/service/apt.cpp + hle/service/fs.cpp hle/service/gsp.cpp hle/service/hid.cpp hle/service/ndm.cpp @@ -85,6 +86,7 @@ set(HEADERS core.h hle/kernel/thread.h hle/function_wrappers.h hle/service/apt.h + hle/service/fs.h hle/service/gsp.h hle/service/hid.h hle/service/service.h diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 85ac50818..63efe7c4d 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -171,6 +171,7 @@ + @@ -221,6 +222,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 37c550d56..39a3cdc4b 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -173,6 +173,9 @@ hle\kernel + + hle\service + @@ -308,6 +311,9 @@ hle\kernel + + hle\service + diff --git a/src/core/hle/service/fs.cpp b/src/core/hle/service/fs.cpp new file mode 100644 index 000000000..3a5afaa3c --- /dev/null +++ b/src/core/hle/service/fs.cpp @@ -0,0 +1,121 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + + +#include "common/common.h" + +#include "core/hle/hle.h" +#include "core/hle/service/fs.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace FS_User + +namespace FS_User { + +void Initialize(Service::Interface* self) { + u32* cmd_buff = Service::GetCommandBuffer(); + DEBUG_LOG(KERNEL, "called"); + cmd_buff[1] = 0; // No error +} + +const Interface::FunctionInfo FunctionTable[] = { + {0x000100C6, nullptr, "Dummy1"}, + {0x040100C4, nullptr, "Control"}, + {0x08010002, Initialize, "Initialize"}, + {0x080201C2, nullptr, "OpenFile"}, + {0x08030204, nullptr, "OpenFileDirectly"}, + {0x08040142, nullptr, "DeleteFile"}, + {0x08050244, nullptr, "RenameFile"}, + {0x08060142, nullptr, "DeleteDirectory"}, + {0x08070142, nullptr, "DeleteDirectoryRecursively"}, + {0x08080202, nullptr, "CreateFile"}, + {0x08090182, nullptr, "CreateDirectory"}, + {0x080A0244, nullptr, "RenameDirectory"}, + {0x080B0102, nullptr, "OpenDirectory"}, + {0x080C00C2, nullptr, "OpenArchive"}, + {0x080D0144, nullptr, "ControlArchive"}, + {0x080E0080, nullptr, "CloseArchive"}, + {0x080F0180, nullptr, "FormatThisUserSaveData"}, + {0x08100200, nullptr, "CreateSystemSaveData"}, + {0x08110040, nullptr, "DeleteSystemSaveData"}, + {0x08120080, nullptr, "GetFreeBytes"}, + {0x08130000, nullptr, "GetCardType"}, + {0x08140000, nullptr, "GetSdmcArchiveResource"}, + {0x08150000, nullptr, "GetNandArchiveResource"}, + {0x08160000, nullptr, "GetSdmcFatfsErro"}, + {0x08170000, nullptr, "IsSdmcDetected"}, + {0x08180000, nullptr, "IsSdmcWritable"}, + {0x08190042, nullptr, "GetSdmcCid"}, + {0x081A0042, nullptr, "GetNandCid"}, + {0x081B0000, nullptr, "GetSdmcSpeedInfo"}, + {0x081C0000, nullptr, "GetNandSpeedInfo"}, + {0x081D0042, nullptr, "GetSdmcLog"}, + {0x081E0042, nullptr, "GetNandLog"}, + {0x081F0000, nullptr, "ClearSdmcLog"}, + {0x08200000, nullptr, "ClearNandLog"}, + {0x08210000, nullptr, "CardSlotIsInserted"}, + {0x08220000, nullptr, "CardSlotPowerOn"}, + {0x08230000, nullptr, "CardSlotPowerOff"}, + {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"}, + {0x08250040, nullptr, "CardNorDirectCommand"}, + {0x08260080, nullptr, "CardNorDirectCommandWithAddress"}, + {0x08270082, nullptr, "CardNorDirectRead"}, + {0x082800C2, nullptr, "CardNorDirectReadWithAddress"}, + {0x08290082, nullptr, "CardNorDirectWrite"}, + {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"}, + {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"}, + {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"}, + {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"}, + {0x082E0040, nullptr, "GetProductInfo"}, + {0x082F0040, nullptr, "GetProgramLaunchInfo"}, + {0x08300182, nullptr, "CreateExtSaveData"}, + {0x08310180, nullptr, "CreateSharedExtSaveData"}, + {0x08320102, nullptr, "ReadExtSaveDataIcon"}, + {0x08330082, nullptr, "EnumerateExtSaveData"}, + {0x08340082, nullptr, "EnumerateSharedExtSaveData"}, + {0x08350080, nullptr, "DeleteExtSaveData"}, + {0x08360080, nullptr, "DeleteSharedExtSaveData"}, + {0x08370040, nullptr, "SetCardSpiBaudRate"}, + {0x08380040, nullptr, "SetCardSpiBusMode"}, + {0x08390000, nullptr, "SendInitializeInfoTo9"}, + {0x083A0100, nullptr, "GetSpecialContentIndex"}, + {0x083B00C2, nullptr, "GetLegacyRomHeader"}, + {0x083C00C2, nullptr, "GetLegacyBannerData"}, + {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"}, + {0x083E00C2, nullptr, "QueryTotalQuotaSize"}, + {0x083F00C0, nullptr, "GetExtDataBlockSize"}, + {0x08400040, nullptr, "AbnegateAccessRight"}, + {0x08410000, nullptr, "DeleteSdmcRoot"}, + {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"}, + {0x08430000, nullptr, "InitializeCtrFileSystem"}, + {0x08440000, nullptr, "CreateSeed"}, + {0x084500C2, nullptr, "GetFormatInfo"}, + {0x08460102, nullptr, "GetLegacyRomHeader2"}, + {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, + {0x08480042, nullptr, "GetSdmcCtrRootPath"}, + {0x08490040, nullptr, "GetArchiveResource"}, + {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, + {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, + {0x084C0242, nullptr, "FormatSaveData"}, + {0x084D0102, nullptr, "GetLegacySubBannerData"}, + {0x084E0342, nullptr, "UpdateSha256Context"}, + {0x084F0102, nullptr, "ReadSpecialFile"}, + {0x08500040, nullptr, "GetSpecialFileSize"}, + {0x08580000, nullptr, "GetMovableSedHashedKeyYRandomData"}, + {0x08610042, nullptr, "InitializeWithSdkVersion"}, + {0x08620040, nullptr, "SetPriority"}, + {0x08630000, nullptr, "GetPriority"}, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Interface class + +Interface::Interface() { + Register(FunctionTable, ARRAY_SIZE(FunctionTable)); +} + +Interface::~Interface() { +} + +} // namespace diff --git a/src/core/hle/service/fs.h b/src/core/hle/service/fs.h new file mode 100644 index 000000000..34b0610ad --- /dev/null +++ b/src/core/hle/service/fs.h @@ -0,0 +1,31 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace FS_User + +namespace FS_User { + +/// Interface to "fs:USER" service +class Interface : public Service::Interface { +public: + + Interface(); + + ~Interface(); + + /** + * Gets the string port name used by CTROS for the service + * @return Port name of service + */ + const char *GetPortName() const { + return "Ufs:"; + } +}; + +} // namespace diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 4a1ac857e..d3af2768a 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -10,6 +10,7 @@ #include "core/hle/service/service.h" #include "core/hle/service/apt.h" +#include "core/hle/service/fs.h" #include "core/hle/service/gsp.h" #include "core/hle/service/hid.h" #include "core/hle/service/ndm.h" @@ -71,6 +72,7 @@ void Init() { g_manager->AddService(new SRV::Interface); g_manager->AddService(new APT_U::Interface); + g_manager->AddService(new FS_User::Interface); g_manager->AddService(new GSP_GPU::Interface); g_manager->AddService(new HID_User::Interface); g_manager->AddService(new NDM_U::Interface); -- cgit v1.2.3 From 17a6148f9df406a6ca4bdca98777e0aaf21f582a Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 27 Jun 2014 16:18:56 -0400 Subject: FileSys: Added preliminary support for applications reading the RomFS archive. Archive: Fixed brace ugliness for neobrain :) FS: Commented out unused local variables to prevent warnings. ...But keeping them here for future use. archive_romfs: Removed unused #include. --- src/core/CMakeLists.txt | 4 +- src/core/core.vcxproj | 4 +- src/core/core.vcxproj.filters | 12 +++- src/core/file_sys/archive.h | 54 ++++++++++++++ src/core/file_sys/archive_romfs.cpp | 46 ++++++++++++ src/core/file_sys/archive_romfs.h | 50 +++++++++++++ src/core/file_sys/file_sys.h | 138 ------------------------------------ src/core/hle/kernel/archive.cpp | 98 +++++++++++++++++++++++-- src/core/hle/kernel/archive.h | 17 +++-- src/core/hle/service/fs.cpp | 33 ++++++++- src/core/loader/loader.cpp | 15 ++-- 11 files changed, 311 insertions(+), 160 deletions(-) create mode 100644 src/core/file_sys/archive.h create mode 100644 src/core/file_sys/archive_romfs.cpp create mode 100644 src/core/file_sys/archive_romfs.h delete mode 100644 src/core/file_sys/file_sys.h (limited to 'src/core/core.vcxproj') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 978e956dc..9ee803fda 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -8,6 +8,7 @@ set(SRCS core.cpp system.cpp arm/disassembler/arm_disasm.cpp arm/disassembler/load_symbol_map.cpp + file_sys/archive_romfs.cpp arm/interpreter/arm_interpreter.cpp arm/interpreter/armcopro.cpp arm/interpreter/armemu.cpp @@ -75,7 +76,8 @@ set(HEADERS core.h arm/interpreter/vfp/asm_vfp.h arm/interpreter/vfp/vfp.h arm/interpreter/vfp/vfp_helper.h - file_sys/file_sys.h + file_sys/archive.h + file_sys/archive_romfs.h hle/config_mem.h hle/coprocessor.h hle/hle.h diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 63efe7c4d..4e521903c 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -162,6 +162,7 @@ + @@ -211,7 +212,8 @@ - + + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 39a3cdc4b..17829b8b1 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -176,6 +176,9 @@ hle\service + + file_sys + @@ -205,9 +208,6 @@ arm\interpreter - - file_sys - hw @@ -314,6 +314,12 @@ hle\service + + file_sys + + + file_sys + diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h new file mode 100644 index 000000000..ed2d83640 --- /dev/null +++ b/src/core/file_sys/archive.h @@ -0,0 +1,54 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FileSys namespace + +namespace FileSys { + +class Archive : NonCopyable { +public: + /// Supported archive types + enum class IdCode : u32 { + RomFS = 0x00000003, + SaveData = 0x00000004, + ExtSaveData = 0x00000006, + SharedExtSaveData = 0x00000007, + SystemSaveData = 0x00000008, + SDMC = 0x00000009, + SDMCWriteOnly = 0x0000000A, + }; + + Archive() { } + virtual ~Archive() { } + + /** + * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) + * @return IdCode of the archive + */ + virtual IdCode GetIdCode() const = 0; + + /** + * Read data from the archive + * @param offset Offset in bytes to start reading archive from + * @param length Length in bytes to read data from archive + * @param buffer Buffer to read data into + * @return Number of bytes read + */ + virtual size_t Read(const u64 offset, const u32 length, u8* buffer) const = 0; + + /** + * Get the size of the archive in bytes + * @return Size of the archive in bytes + */ + virtual size_t GetSize() const = 0; +}; + +} // namespace FileSys diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp new file mode 100644 index 000000000..6fdb768d6 --- /dev/null +++ b/src/core/file_sys/archive_romfs.cpp @@ -0,0 +1,46 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "common/common_types.h" + +#include "core/file_sys/archive_romfs.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FileSys namespace + +namespace FileSys { + +Archive_RomFS::Archive_RomFS(Loader::AppLoader& app_loader) { + // Load the RomFS from the app + if (Loader::ResultStatus::Success != app_loader.ReadRomFS(raw_data)) { + WARN_LOG(FILESYS, "Unable to read RomFS!"); + } +} + +Archive_RomFS::~Archive_RomFS() { +} + +/** + * Read data from the archive + * @param offset Offset in bytes to start reading archive from + * @param length Length in bytes to read data from archive + * @param buffer Buffer to read data into + * @return Number of bytes read + */ +size_t Archive_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { + DEBUG_LOG(FILESYS, "called offset=%d, length=%d", offset, length); + memcpy(buffer, &raw_data[(u32)offset], length); + return length; +} + +/** + * Get the size of the archive in bytes + * @return Size of the archive in bytes + */ +size_t Archive_RomFS::GetSize() const { + ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); + return 0; +} + +} // namespace FileSys diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h new file mode 100644 index 000000000..60af8ff0d --- /dev/null +++ b/src/core/file_sys/archive_romfs.h @@ -0,0 +1,50 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/common_types.h" + +#include "core/file_sys/archive.h" +#include "core/loader/loader.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FileSys namespace + +namespace FileSys { + +/// File system interface to the RomFS archive +class Archive_RomFS : public Archive { +public: + Archive_RomFS(Loader::AppLoader& app_loader); + ~Archive_RomFS(); + + /** + * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) + * @return IdCode of the archive + */ + IdCode GetIdCode() const { return IdCode::RomFS; }; + + /** + * Read data from the archive + * @param offset Offset in bytes to start reading archive from + * @param length Length in bytes to read data from archive + * @param buffer Buffer to read data into + * @return Number of bytes read + */ + size_t Read(const u64 offset, const u32 length, u8* buffer) const; + + /** + * Get the size of the archive in bytes + * @return Size of the archive in bytes + */ + size_t GetSize() const; + +private: + std::vector raw_data; +}; + +} // namespace FileSys diff --git a/src/core/file_sys/file_sys.h b/src/core/file_sys/file_sys.h deleted file mode 100644 index bb8503e62..000000000 --- a/src/core/file_sys/file_sys.h +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) 2012- PPSSPP Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "common/common.h" -#include "common/chunk_file.h" - -enum FileAccess { - FILEACCESS_NONE=0, - FILEACCESS_READ=1, - FILEACCESS_WRITE=2, - FILEACCESS_APPEND=4, - FILEACCESS_CREATE=8 -}; - -enum FileMove { - FILEMOVE_BEGIN=0, - FILEMOVE_CURRENT=1, - FILEMOVE_END=2 -}; - -enum FileType { - FILETYPE_NORMAL=1, - FILETYPE_DIRECTORY=2 -}; - - -class IHandleAllocator { -public: - virtual ~IHandleAllocator() {} - virtual u32 GetNewHandle() = 0; - virtual void FreeHandle(u32 handle) = 0; -}; - -class SequentialHandleAllocator : public IHandleAllocator { -public: - SequentialHandleAllocator() : handle_(1) {} - virtual u32 GetNewHandle() { return handle_++; } - virtual void FreeHandle(u32 handle) {} -private: - int handle_; -}; - -struct FileInfo { - FileInfo() - : size(0), access(0), exists(false), type(FILETYPE_NORMAL), isOnSectorSystem(false), startSector(0), numSectors(0) {} - - void DoState(PointerWrap &p) { - auto s = p.Section("FileInfo", 1); - if (!s) - return; - - p.Do(name); - p.Do(size); - p.Do(access); - p.Do(exists); - p.Do(type); - p.Do(atime); - p.Do(ctime); - p.Do(mtime); - p.Do(isOnSectorSystem); - p.Do(startSector); - p.Do(numSectors); - p.Do(sectorSize); - } - - std::string name; - s64 size; - u32 access; //unix 777 - bool exists; - FileType type; - - tm atime; - tm ctime; - tm mtime; - - bool isOnSectorSystem; - u32 startSector; - u32 numSectors; - u32 sectorSize; -}; - - -class IFileSystem { -public: - virtual ~IFileSystem() {} - - virtual void DoState(PointerWrap &p) = 0; - virtual std::vector GetDirListing(std::string path) = 0; - virtual u32 OpenFile(std::string filename, FileAccess access, const char *devicename=NULL) = 0; - virtual void CloseFile(u32 handle) = 0; - virtual size_t ReadFile(u32 handle, u8 *pointer, s64 size) = 0; - virtual size_t WriteFile(u32 handle, const u8 *pointer, s64 size) = 0; - virtual size_t SeekFile(u32 handle, s32 position, FileMove type) = 0; - virtual FileInfo GetFileInfo(std::string filename) = 0; - virtual bool OwnsHandle(u32 handle) = 0; - virtual bool MkDir(const std::string &dirname) = 0; - virtual bool RmDir(const std::string &dirname) = 0; - virtual int RenameFile(const std::string &from, const std::string &to) = 0; - virtual bool RemoveFile(const std::string &filename) = 0; - virtual bool GetHostPath(const std::string &inpath, std::string &outpath) = 0; -}; - - -class EmptyFileSystem : public IFileSystem { -public: - virtual void DoState(PointerWrap &p) {} - std::vector GetDirListing(std::string path) {std::vector vec; return vec;} - u32 OpenFile(std::string filename, FileAccess access, const char *devicename=NULL) {return 0;} - void CloseFile(u32 handle) {} - size_t ReadFile(u32 handle, u8 *pointer, s64 size) {return 0;} - size_t WriteFile(u32 handle, const u8 *pointer, s64 size) {return 0;} - size_t SeekFile(u32 handle, s32 position, FileMove type) {return 0;} - FileInfo GetFileInfo(std::string filename) {FileInfo f; return f;} - bool OwnsHandle(u32 handle) {return false;} - virtual bool MkDir(const std::string &dirname) {return false;} - virtual bool RmDir(const std::string &dirname) {return false;} - virtual int RenameFile(const std::string &from, const std::string &to) {return -1;} - virtual bool RemoveFile(const std::string &filename) {return false;} - virtual bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;} -}; - - 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(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 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(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"}, diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 96cb81de0..2b42e3c64 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -4,9 +4,11 @@ #include +#include "core/file_sys/archive_romfs.h" #include "core/loader/loader.h" #include "core/loader/elf.h" #include "core/loader/ncch.h" +#include "core/hle/kernel/archive.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -51,14 +53,20 @@ ResultStatus LoadFile(const std::string& filename) { switch (IdentifyFile(filename)) { // Standard ELF file format... - case FileType::ELF: { + case FileType::ELF: return AppLoader_ELF(filename).Load(); - } // NCCH/NCSD container formats... case FileType::CXI: case FileType::CCI: { - return AppLoader_NCCH(filename).Load(); + AppLoader_NCCH app_loader(filename); + + // Load application and RomFS + if (ResultStatus::Success == app_loader.Load()) { + Kernel::CreateArchive(new FileSys::Archive_RomFS(app_loader), "RomFS"); + return ResultStatus::Success; + } + break; } // Error occurred durring IdentifyFile... @@ -70,7 +78,6 @@ ResultStatus LoadFile(const std::string& filename) { default: return ResultStatus::ErrorInvalidFormat; } - return ResultStatus::Error; } -- cgit v1.2.3