mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	
						commit
						cd2a31eaf4
					
				
					 27 changed files with 337 additions and 526 deletions
				
			
		|  | @ -1,6 +1,7 @@ | ||||||
| #!/bin/sh | #!/bin/sh | ||||||
| 
 | 
 | ||||||
| set -e | set -e | ||||||
|  | set -x | ||||||
| 
 | 
 | ||||||
| #if OS is linux or is not set | #if OS is linux or is not set | ||||||
| if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then  | if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then  | ||||||
|  |  | ||||||
|  | @ -1,13 +1,14 @@ | ||||||
| #!/bin/sh | #!/bin/sh | ||||||
| 
 | 
 | ||||||
| set -e | set -e | ||||||
|  | set -x | ||||||
| 
 | 
 | ||||||
| #if OS is linux or is not set | #if OS is linux or is not set | ||||||
| if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then | if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then | ||||||
|     sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y |     sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y | ||||||
|     sudo apt-get -qq update |     sudo apt-get -qq update | ||||||
|     sudo apt-get -qq install g++-4.8 xorg-dev libglu1-mesa-dev libxcursor-dev |     sudo apt-get -qq install g++-4.9 xorg-dev libglu1-mesa-dev libxcursor-dev | ||||||
|     sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90 |     sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 90 | ||||||
|     ( |     ( | ||||||
|         git clone https://github.com/glfw/glfw.git --branch 3.0.4 --depth 1 |         git clone https://github.com/glfw/glfw.git --branch 3.0.4 --depth 1 | ||||||
|         mkdir glfw/build && cd glfw/build |         mkdir glfw/build && cd glfw/build | ||||||
|  |  | ||||||
|  | @ -5,7 +5,8 @@ cmake_minimum_required(VERSION 2.8.11) | ||||||
| project(citra) | project(citra) | ||||||
| 
 | 
 | ||||||
| if (NOT MSVC) | if (NOT MSVC) | ||||||
|     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-attributes") |     # -std=c++14 is only supported on very new compilers, so use the old c++1y alias instead. | ||||||
|  |     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -Wno-attributes") | ||||||
| else() | else() | ||||||
|     # Silence deprecation warnings |     # Silence deprecation warnings | ||||||
|     add_definitions(/D_CRT_SECURE_NO_WARNINGS) |     add_definitions(/D_CRT_SECURE_NO_WARNINGS) | ||||||
|  |  | ||||||
|  | @ -157,12 +157,6 @@ void GMainWindow::BootGame(std::string filename) | ||||||
|     LOG_INFO(Frontend, "Citra starting...\n"); |     LOG_INFO(Frontend, "Citra starting...\n"); | ||||||
|     System::Init(render_window); |     System::Init(render_window); | ||||||
| 
 | 
 | ||||||
|     if (Core::Init()) { |  | ||||||
|         LOG_CRITICAL(Frontend, "Core initialization failed, exiting..."); |  | ||||||
|         Core::Stop(); |  | ||||||
|         exit(1); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Load a game or die...
 |     // Load a game or die...
 | ||||||
|     if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) { |     if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) { | ||||||
|         LOG_CRITICAL(Frontend, "Failed to load ROM!"); |         LOG_CRITICAL(Frontend, "Failed to load ROM!"); | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ set(SRCS | ||||||
|             file_sys/directory_romfs.cpp |             file_sys/directory_romfs.cpp | ||||||
|             file_sys/directory_sdmc.cpp |             file_sys/directory_sdmc.cpp | ||||||
|             hle/kernel/address_arbiter.cpp |             hle/kernel/address_arbiter.cpp | ||||||
|             hle/kernel/archive.cpp |  | ||||||
|             hle/kernel/event.cpp |             hle/kernel/event.cpp | ||||||
|             hle/kernel/kernel.cpp |             hle/kernel/kernel.cpp | ||||||
|             hle/kernel/mutex.cpp |             hle/kernel/mutex.cpp | ||||||
|  | @ -42,7 +41,8 @@ set(SRCS | ||||||
|             hle/service/csnd_snd.cpp |             hle/service/csnd_snd.cpp | ||||||
|             hle/service/dsp_dsp.cpp |             hle/service/dsp_dsp.cpp | ||||||
|             hle/service/err_f.cpp |             hle/service/err_f.cpp | ||||||
|             hle/service/fs_user.cpp |             hle/service/fs/archive.cpp | ||||||
|  |             hle/service/fs/fs_user.cpp | ||||||
|             hle/service/frd_u.cpp |             hle/service/frd_u.cpp | ||||||
|             hle/service/gsp_gpu.cpp |             hle/service/gsp_gpu.cpp | ||||||
|             hle/service/hid_user.cpp |             hle/service/hid_user.cpp | ||||||
|  | @ -97,17 +97,16 @@ set(HEADERS | ||||||
|             arm/skyeye_common/vfp/vfp.h |             arm/skyeye_common/vfp/vfp.h | ||||||
|             arm/skyeye_common/vfp/vfp_helper.h |             arm/skyeye_common/vfp/vfp_helper.h | ||||||
|             arm/arm_interface.h |             arm/arm_interface.h | ||||||
|             file_sys/archive.h |             file_sys/archive_backend.h | ||||||
|             file_sys/archive_romfs.h |             file_sys/archive_romfs.h | ||||||
|             file_sys/archive_sdmc.h |             file_sys/archive_sdmc.h | ||||||
|             file_sys/file.h |             file_sys/file_backend.h | ||||||
|             file_sys/file_romfs.h |             file_sys/file_romfs.h | ||||||
|             file_sys/file_sdmc.h |             file_sys/file_sdmc.h | ||||||
|             file_sys/directory.h |             file_sys/directory_backend.h | ||||||
|             file_sys/directory_romfs.h |             file_sys/directory_romfs.h | ||||||
|             file_sys/directory_sdmc.h |             file_sys/directory_sdmc.h | ||||||
|             hle/kernel/address_arbiter.h |             hle/kernel/address_arbiter.h | ||||||
|             hle/kernel/archive.h |  | ||||||
|             hle/kernel/event.h |             hle/kernel/event.h | ||||||
|             hle/kernel/kernel.h |             hle/kernel/kernel.h | ||||||
|             hle/kernel/mutex.h |             hle/kernel/mutex.h | ||||||
|  | @ -126,7 +125,8 @@ set(HEADERS | ||||||
|             hle/service/csnd_snd.h |             hle/service/csnd_snd.h | ||||||
|             hle/service/dsp_dsp.h |             hle/service/dsp_dsp.h | ||||||
|             hle/service/err_f.h |             hle/service/err_f.h | ||||||
|             hle/service/fs_user.h |             hle/service/fs/archive.h | ||||||
|  |             hle/service/fs/fs_user.h | ||||||
|             hle/service/frd_u.h |             hle/service/frd_u.h | ||||||
|             hle/service/gsp_gpu.h |             hle/service/gsp_gpu.h | ||||||
|             hle/service/hid_user.h |             hle/service/hid_user.h | ||||||
|  |  | ||||||
|  | @ -10,8 +10,8 @@ | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/file.h" | #include "core/file_sys/file_backend.h" | ||||||
| #include "core/file_sys/directory.h" | #include "core/file_sys/directory_backend.h" | ||||||
| 
 | 
 | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | @ -160,27 +160,14 @@ private: | ||||||
|     std::u16string u16str; |     std::u16string u16str; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Archive : NonCopyable { | class ArchiveBackend : NonCopyable { | ||||||
| public: | public: | ||||||
|     /// Supported archive types
 |     virtual ~ArchiveBackend() { } | ||||||
|     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.) |      * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) | ||||||
|      * @return IdCode of the archive |  | ||||||
|      */ |      */ | ||||||
|     virtual IdCode GetIdCode() const = 0; |     virtual std::string GetName() const = 0; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Open a file specified by its path, using the specified mode |      * Open a file specified by its path, using the specified mode | ||||||
|  | @ -188,7 +175,7 @@ public: | ||||||
|      * @param mode Mode to open the file with |      * @param mode Mode to open the file with | ||||||
|      * @return Opened file, or nullptr |      * @return Opened file, or nullptr | ||||||
|      */ |      */ | ||||||
|     virtual std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const = 0; |     virtual std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const = 0; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Delete a file specified by its path |      * Delete a file specified by its path | ||||||
|  | @ -232,37 +219,7 @@ public: | ||||||
|      * @param path Path relative to the archive |      * @param path Path relative to the archive | ||||||
|      * @return Opened directory, or nullptr |      * @return Opened directory, or nullptr | ||||||
|      */ |      */ | ||||||
|     virtual std::unique_ptr<Directory> OpenDirectory(const Path& path) const = 0; |     virtual std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const = 0; | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Read data from the archive |  | ||||||
|      * @param offset Offset in bytes to start reading data from |  | ||||||
|      * @param length Length in bytes of data to read 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; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Write data to the archive |  | ||||||
|      * @param offset Offset in bytes to start writing data to |  | ||||||
|      * @param length Length in bytes of data to write to archive |  | ||||||
|      * @param buffer Buffer to write data from |  | ||||||
|      * @param flush  The flush parameters (0 == do not flush) |  | ||||||
|      * @return Number of bytes written |  | ||||||
|      */ |  | ||||||
|     virtual size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) = 0; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Get the size of the archive in bytes |  | ||||||
|      * @return Size of the archive in bytes |  | ||||||
|      */ |  | ||||||
|     virtual size_t GetSize() const = 0; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Set the size of the archive in bytes |  | ||||||
|      */ |  | ||||||
|     virtual void SetSize(const u64 size) = 0; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace FileSys
 | } // namespace FileSys
 | ||||||
|  | @ -2,6 +2,8 @@ | ||||||
| // Licensed under GPLv2
 | // Licensed under GPLv2
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive_romfs.h" | #include "core/file_sys/archive_romfs.h" | ||||||
|  | @ -20,17 +22,14 @@ Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Archive_RomFS::~Archive_RomFS() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * Open a file specified by its path, using the specified mode |  * Open a file specified by its path, using the specified mode | ||||||
|  * @param path Path relative to the archive |  * @param path Path relative to the archive | ||||||
|  * @param mode Mode to open the file with |  * @param mode Mode to open the file with | ||||||
|  * @return Opened file, or nullptr |  * @return Opened file, or nullptr | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<File> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { | std::unique_ptr<FileBackend> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { | ||||||
|     return std::unique_ptr<File>(new File_RomFS); |     return std::make_unique<File_RomFS>(this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -78,49 +77,8 @@ bool Archive_RomFS::RenameDirectory(const FileSys::Path& src_path, const FileSys | ||||||
|  * @param path Path relative to the archive |  * @param path Path relative to the archive | ||||||
|  * @return Opened directory, or nullptr |  * @return Opened directory, or nullptr | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const Path& path) const { | std::unique_ptr<DirectoryBackend> Archive_RomFS::OpenDirectory(const Path& path) const { | ||||||
|     return std::unique_ptr<Directory>(new Directory_RomFS); |     return std::make_unique<Directory_RomFS>(); | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Read data from the archive |  | ||||||
|  * @param offset Offset in bytes to start reading data from |  | ||||||
|  * @param length Length in bytes of data to read 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 { |  | ||||||
|     LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); |  | ||||||
|     memcpy(buffer, &raw_data[(u32)offset], length); |  | ||||||
|     return length; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Write data to the archive |  | ||||||
|  * @param offset Offset in bytes to start writing data to |  | ||||||
|  * @param length Length in bytes of data to write to archive |  | ||||||
|  * @param buffer Buffer to write data from |  | ||||||
|  * @param flush  The flush parameters (0 == do not flush) |  | ||||||
|  * @return Number of bytes written |  | ||||||
|  */ |  | ||||||
| size_t Archive_RomFS::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to write to ROMFS."); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Get the size of the archive in bytes |  | ||||||
|  * @return Size of the archive in bytes |  | ||||||
|  */ |  | ||||||
| size_t Archive_RomFS::GetSize() const { |  | ||||||
|     return sizeof(u8) * raw_data.size(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Set the size of the archive in bytes |  | ||||||
|  */ |  | ||||||
| void Archive_RomFS::SetSize(const u64 size) { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS"); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace FileSys
 | } // namespace FileSys
 | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive.h" | #include "core/file_sys/archive_backend.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | @ -17,16 +17,11 @@ | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| /// File system interface to the RomFS archive
 | /// File system interface to the RomFS archive
 | ||||||
| class Archive_RomFS final : public Archive { | class Archive_RomFS final : public ArchiveBackend { | ||||||
| public: | public: | ||||||
|     Archive_RomFS(const Loader::AppLoader& app_loader); |     Archive_RomFS(const Loader::AppLoader& app_loader); | ||||||
|     ~Archive_RomFS() override; |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     std::string GetName() const override { return "RomFS"; } | ||||||
|      * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) |  | ||||||
|      * @return IdCode of the archive |  | ||||||
|      */ |  | ||||||
|     IdCode GetIdCode() const override { return IdCode::RomFS; } |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Open a file specified by its path, using the specified mode |      * Open a file specified by its path, using the specified mode | ||||||
|  | @ -34,7 +29,7 @@ public: | ||||||
|      * @param mode Mode to open the file with |      * @param mode Mode to open the file with | ||||||
|      * @return Opened file, or nullptr |      * @return Opened file, or nullptr | ||||||
|      */ |      */ | ||||||
|     std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; |     std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Delete a file specified by its path |      * Delete a file specified by its path | ||||||
|  | @ -78,39 +73,11 @@ public: | ||||||
|      * @param path Path relative to the archive |      * @param path Path relative to the archive | ||||||
|      * @return Opened directory, or nullptr |      * @return Opened directory, or nullptr | ||||||
|      */ |      */ | ||||||
|     std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; |     std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Read data from the archive |  | ||||||
|      * @param offset Offset in bytes to start reading data from |  | ||||||
|      * @param length Length in bytes of data to read 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 override; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Write data to the archive |  | ||||||
|      * @param offset Offset in bytes to start writing data to |  | ||||||
|      * @param length Length in bytes of data to write to archive |  | ||||||
|      * @param buffer Buffer to write data from |  | ||||||
|      * @param flush  The flush parameters (0 == do not flush) |  | ||||||
|      * @return Number of bytes written |  | ||||||
|      */ |  | ||||||
|     size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Get the size of the archive in bytes |  | ||||||
|      * @return Size of the archive in bytes |  | ||||||
|      */ |  | ||||||
|     size_t GetSize() const override; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Set the size of the archive in bytes |  | ||||||
|      */ |  | ||||||
|     void SetSize(const u64 size) override; |  | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     friend class File_RomFS; | ||||||
|  | 
 | ||||||
|     std::vector<u8> raw_data; |     std::vector<u8> raw_data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -49,12 +49,12 @@ bool Archive_SDMC::Initialize() { | ||||||
|  * @param mode Mode to open the file with |  * @param mode Mode to open the file with | ||||||
|  * @return Opened file, or nullptr |  * @return Opened file, or nullptr | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { | std::unique_ptr<FileBackend> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { | ||||||
|     LOG_DEBUG(Service_FS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex); |     LOG_DEBUG(Service_FS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex); | ||||||
|     File_SDMC* file = new File_SDMC(this, path, mode); |     File_SDMC* file = new File_SDMC(this, path, mode); | ||||||
|     if (!file->Open()) |     if (!file->Open()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     return std::unique_ptr<File>(file); |     return std::unique_ptr<FileBackend>(file); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -97,53 +97,12 @@ bool Archive_SDMC::RenameDirectory(const FileSys::Path& src_path, const FileSys: | ||||||
|  * @param path Path relative to the archive |  * @param path Path relative to the archive | ||||||
|  * @return Opened directory, or nullptr |  * @return Opened directory, or nullptr | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const { | std::unique_ptr<DirectoryBackend> Archive_SDMC::OpenDirectory(const Path& path) const { | ||||||
|     LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); |     LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); | ||||||
|     Directory_SDMC* directory = new Directory_SDMC(this, path); |     Directory_SDMC* directory = new Directory_SDMC(this, path); | ||||||
|     if (!directory->Open()) |     if (!directory->Open()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     return std::unique_ptr<Directory>(directory); |     return std::unique_ptr<DirectoryBackend>(directory); | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * 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_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { |  | ||||||
|     LOG_ERROR(Service_FS, "(UNIMPLEMENTED)"); |  | ||||||
|     return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Write data to the archive |  | ||||||
|  * @param offset Offset in bytes to start writing data to |  | ||||||
|  * @param length Length in bytes of data to write to archive |  | ||||||
|  * @param buffer Buffer to write data from |  | ||||||
|  * @param flush  The flush parameters (0 == do not flush) |  | ||||||
|  * @return Number of bytes written |  | ||||||
|  */ |  | ||||||
| size_t Archive_SDMC::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { |  | ||||||
|     LOG_ERROR(Service_FS, "(UNIMPLEMENTED)"); |  | ||||||
|     return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Get the size of the archive in bytes |  | ||||||
|  * @return Size of the archive in bytes |  | ||||||
|  */ |  | ||||||
| size_t Archive_SDMC::GetSize() const { |  | ||||||
|     LOG_ERROR(Service_FS, "(UNIMPLEMENTED)"); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Set the size of the archive in bytes |  | ||||||
|  */ |  | ||||||
| void Archive_SDMC::SetSize(const u64 size) { |  | ||||||
|     LOG_ERROR(Service_FS, "(UNIMPLEMENTED)"); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive.h" | #include "core/file_sys/archive_backend.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | @ -15,7 +15,7 @@ | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| /// File system interface to the SDMC archive
 | /// File system interface to the SDMC archive
 | ||||||
| class Archive_SDMC final : public Archive { | class Archive_SDMC final : public ArchiveBackend { | ||||||
| public: | public: | ||||||
|     Archive_SDMC(const std::string& mount_point); |     Archive_SDMC(const std::string& mount_point); | ||||||
|     ~Archive_SDMC() override; |     ~Archive_SDMC() override; | ||||||
|  | @ -26,11 +26,7 @@ public: | ||||||
|      */ |      */ | ||||||
|     bool Initialize(); |     bool Initialize(); | ||||||
| 
 | 
 | ||||||
|     /**
 |     std::string GetName() const override { return "SDMC"; } | ||||||
|      * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) |  | ||||||
|      * @return IdCode of the archive |  | ||||||
|      */ |  | ||||||
|     IdCode GetIdCode() const override { return IdCode::SDMC; } |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Open a file specified by its path, using the specified mode |      * Open a file specified by its path, using the specified mode | ||||||
|  | @ -38,7 +34,7 @@ public: | ||||||
|      * @param mode Mode to open the file with |      * @param mode Mode to open the file with | ||||||
|      * @return Opened file, or nullptr |      * @return Opened file, or nullptr | ||||||
|      */ |      */ | ||||||
|     std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; |     std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Delete a file specified by its path |      * Delete a file specified by its path | ||||||
|  | @ -82,37 +78,7 @@ public: | ||||||
|      * @param path Path relative to the archive |      * @param path Path relative to the archive | ||||||
|      * @return Opened directory, or nullptr |      * @return Opened directory, or nullptr | ||||||
|      */ |      */ | ||||||
|     std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; |     std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * 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 override; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Write data to the archive |  | ||||||
|      * @param offset Offset in bytes to start writing data to |  | ||||||
|      * @param length Length in bytes of data to write to archive |  | ||||||
|      * @param buffer Buffer to write data from |  | ||||||
|      * @param flush  The flush parameters (0 == do not flush) |  | ||||||
|      * @return Number of bytes written |  | ||||||
|      */ |  | ||||||
|     size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Get the size of the archive in bytes |  | ||||||
|      * @return Size of the archive in bytes |  | ||||||
|      */ |  | ||||||
|     size_t GetSize() const override; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Set the size of the archive in bytes |  | ||||||
|      */ |  | ||||||
|     void SetSize(const u64 size) override; |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Getter for the path used for this Archive |      * Getter for the path used for this Archive | ||||||
|  |  | ||||||
|  | @ -36,10 +36,10 @@ static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension i | ||||||
| static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); | static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); | ||||||
| static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); | static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); | ||||||
| 
 | 
 | ||||||
| class Directory : NonCopyable { | class DirectoryBackend : NonCopyable { | ||||||
| public: | public: | ||||||
|     Directory() { } |     DirectoryBackend() { } | ||||||
|     virtual ~Directory() { } |     virtual ~DirectoryBackend() { } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|     * Open the directory |     * Open the directory | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/directory.h" | #include "core/file_sys/directory_backend.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | @ -14,7 +14,7 @@ | ||||||
| 
 | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| class Directory_RomFS final : public Directory { | class Directory_RomFS final : public DirectoryBackend { | ||||||
| public: | public: | ||||||
|     Directory_RomFS(); |     Directory_RomFS(); | ||||||
|     ~Directory_RomFS() override; |     ~Directory_RomFS() override; | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/directory.h" | #include "core/file_sys/directory_backend.h" | ||||||
| #include "core/file_sys/archive_sdmc.h" | #include "core/file_sys/archive_sdmc.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
|  | @ -16,7 +16,7 @@ | ||||||
| 
 | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| class Directory_SDMC final : public Directory { | class Directory_SDMC final : public DirectoryBackend { | ||||||
| public: | public: | ||||||
|     Directory_SDMC(); |     Directory_SDMC(); | ||||||
|     Directory_SDMC(const Archive_SDMC* archive, const Path& path); |     Directory_SDMC(const Archive_SDMC* archive, const Path& path); | ||||||
|  |  | ||||||
|  | @ -13,10 +13,10 @@ | ||||||
| 
 | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| class File : NonCopyable { | class FileBackend : NonCopyable { | ||||||
| public: | public: | ||||||
|     File() { } |     FileBackend() { } | ||||||
|     virtual ~File() { } |     virtual ~FileBackend() { } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Open the file |      * Open the file | ||||||
|  | @ -5,24 +5,19 @@ | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/file_romfs.h" | #include "core/file_sys/file_romfs.h" | ||||||
|  | #include "core/file_sys/archive_romfs.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // FileSys namespace
 | // FileSys namespace
 | ||||||
| 
 | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| File_RomFS::File_RomFS() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| File_RomFS::~File_RomFS() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * Open the file |  * Open the file | ||||||
|  * @return true if the file opened correctly |  * @return true if the file opened correctly | ||||||
|  */ |  */ | ||||||
| bool File_RomFS::Open() { | bool File_RomFS::Open() { | ||||||
|     return false; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -33,7 +28,9 @@ bool File_RomFS::Open() { | ||||||
|  * @return Number of bytes read |  * @return Number of bytes read | ||||||
|  */ |  */ | ||||||
| size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | ||||||
|     return -1; |     LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); | ||||||
|  |     memcpy(buffer, &archive->raw_data[(u32)offset], length); | ||||||
|  |     return length; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -45,7 +42,8 @@ size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | ||||||
|  * @return Number of bytes written |  * @return Number of bytes written | ||||||
|  */ |  */ | ||||||
| size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||||||
|     return -1; |     LOG_WARNING(Service_FS, "Attempted to write to ROMFS."); | ||||||
|  |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -53,7 +51,7 @@ size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, co | ||||||
|  * @return Size of the file in bytes |  * @return Size of the file in bytes | ||||||
|  */ |  */ | ||||||
| size_t File_RomFS::GetSize() const { | size_t File_RomFS::GetSize() const { | ||||||
|     return -1; |     return sizeof(u8) * archive->raw_data.size(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -62,6 +60,7 @@ size_t File_RomFS::GetSize() const { | ||||||
|  * @return true if successful |  * @return true if successful | ||||||
|  */ |  */ | ||||||
| bool File_RomFS::SetSize(const u64 size) const { | bool File_RomFS::SetSize(const u64 size) const { | ||||||
|  |     LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS"); | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/file.h" | #include "core/file_sys/file_backend.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | @ -14,10 +14,11 @@ | ||||||
| 
 | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| class File_RomFS final : public File { | class Archive_RomFS; | ||||||
|  | 
 | ||||||
|  | class File_RomFS final : public FileBackend { | ||||||
| public: | public: | ||||||
|     File_RomFS(); |     File_RomFS(const Archive_RomFS* archive) : archive(archive) {} | ||||||
|     ~File_RomFS() override; |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Open the file |      * Open the file | ||||||
|  | @ -62,6 +63,9 @@ public: | ||||||
|      * @return true if the file closed correctly |      * @return true if the file closed correctly | ||||||
|      */ |      */ | ||||||
|     bool Close() const override; |     bool Close() const override; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     const Archive_RomFS* archive; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace FileSys
 | } // namespace FileSys
 | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/file.h" | #include "core/file_sys/file_backend.h" | ||||||
| #include "core/file_sys/archive_sdmc.h" | #include "core/file_sys/archive_sdmc.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
|  | @ -16,7 +16,7 @@ | ||||||
| 
 | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| class File_SDMC final : public File { | class File_SDMC final : public FileBackend { | ||||||
| public: | public: | ||||||
|     File_SDMC(); |     File_SDMC(); | ||||||
|     File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode); |     File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode); | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
| #include "core/hle/hle.h" | #include "core/hle/hle.h" | ||||||
| #include "core/hle/kernel/thread.h" | #include "core/hle/kernel/thread.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
|  | #include "core/hle/service/fs/archive.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
|  | @ -56,6 +57,7 @@ void RegisterAllModules() { | ||||||
| 
 | 
 | ||||||
| void Init() { | void Init() { | ||||||
|     Service::Init(); |     Service::Init(); | ||||||
|  |     Service::FS::ArchiveInit(); | ||||||
| 
 | 
 | ||||||
|     RegisterAllModules(); |     RegisterAllModules(); | ||||||
| 
 | 
 | ||||||
|  | @ -63,6 +65,7 @@ void Init() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|  |     Service::FS::ArchiveShutdown(); | ||||||
|     Service::Shutdown(); |     Service::Shutdown(); | ||||||
| 
 | 
 | ||||||
|     g_module_db.clear(); |     g_module_db.clear(); | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/thread.h" | #include "core/hle/kernel/thread.h" | ||||||
| #include "core/hle/kernel/archive.h" |  | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| 
 | 
 | ||||||
|  | @ -89,13 +88,11 @@ Object* ObjectPool::CreateByIDType(int type) { | ||||||
| /// Initialize the kernel
 | /// Initialize the kernel
 | ||||||
| void Init() { | void Init() { | ||||||
|     Kernel::ThreadingInit(); |     Kernel::ThreadingInit(); | ||||||
|     Kernel::ArchiveInit(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Shutdown the kernel
 | /// Shutdown the kernel
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     Kernel::ThreadingShutdown(); |     Kernel::ThreadingShutdown(); | ||||||
|     Kernel::ArchiveShutdown(); |  | ||||||
| 
 | 
 | ||||||
|     g_object_pool.Clear(); // Free all kernel objects
 |     g_object_pool.Clear(); // Free all kernel objects
 | ||||||
| } | } | ||||||
|  | @ -106,8 +103,6 @@ void Shutdown() { | ||||||
|  * @return True on success, otherwise false |  * @return True on success, otherwise false | ||||||
|  */ |  */ | ||||||
| bool LoadExec(u32 entry_point) { | bool LoadExec(u32 entry_point) { | ||||||
|     Init(); |  | ||||||
| 
 |  | ||||||
|     Core::g_app_core->SetPC(entry_point); |     Core::g_app_core->SetPC(entry_point); | ||||||
| 
 | 
 | ||||||
|     // 0x30 is the typical main thread priority I've seen used so far
 |     // 0x30 is the typical main thread priority I've seen used so far
 | ||||||
|  |  | ||||||
|  | @ -2,23 +2,37 @@ | ||||||
| // Licensed under GPLv2
 | // Licensed under GPLv2
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <map> | #include <memory> | ||||||
|  | #include <unordered_map> | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/math_util.h" | #include "common/math_util.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive.h" | #include "core/file_sys/archive_backend.h" | ||||||
| #include "core/file_sys/archive_sdmc.h" | #include "core/file_sys/archive_sdmc.h" | ||||||
| #include "core/file_sys/directory.h" | #include "core/file_sys/directory_backend.h" | ||||||
| #include "core/hle/kernel/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/hle/kernel/session.h" | #include "core/hle/kernel/session.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map.
 | ||||||
| // Kernel namespace
 | // Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
 | ||||||
|  | namespace std { | ||||||
|  |     template <> | ||||||
|  |     struct hash<Service::FS::ArchiveIdCode> { | ||||||
|  |         typedef Service::FS::ArchiveIdCode argument_type; | ||||||
|  |         typedef std::size_t result_type; | ||||||
| 
 | 
 | ||||||
| namespace Kernel { |         result_type operator()(const argument_type& id_code) const { | ||||||
|  |             typedef std::underlying_type<argument_type>::type Type; | ||||||
|  |             return std::hash<Type>()(static_cast<Type>(id_code)); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | namespace Service { | ||||||
|  | namespace FS { | ||||||
| 
 | 
 | ||||||
| // Command to access archive file
 | // Command to access archive file
 | ||||||
| enum class FileCommand : u32 { | enum class FileCommand : u32 { | ||||||
|  | @ -43,78 +57,28 @@ enum class DirectoryCommand : u32 { | ||||||
|     Close           = 0x08020000, |     Close           = 0x08020000, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Archive : public Kernel::Session { | class Archive { | ||||||
| public: | public: | ||||||
|     std::string GetName() const override { return "Archive: " + name; } |     Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) | ||||||
| 
 |             : backend(std::move(backend)), id_code(id_code) { | ||||||
|     std::string name;           ///< Name of archive (optional)
 |  | ||||||
|     FileSys::Archive* backend;  ///< Archive backend interface
 |  | ||||||
| 
 |  | ||||||
|     ResultVal<bool> SyncRequest() override { |  | ||||||
|         u32* cmd_buff = Kernel::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]; |  | ||||||
| 
 |  | ||||||
|             // Number of bytes read
 |  | ||||||
|             cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         // Write to archive...
 |  | ||||||
|         case FileCommand::Write: |  | ||||||
|         { |  | ||||||
|             u64 offset  = cmd_buff[1] | ((u64)cmd_buff[2] << 32); |  | ||||||
|             u32 length  = cmd_buff[3]; |  | ||||||
|             u32 flush   = cmd_buff[4]; |  | ||||||
|             u32 address = cmd_buff[6]; |  | ||||||
| 
 |  | ||||||
|             // Number of bytes written
 |  | ||||||
|             cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         case FileCommand::GetSize: |  | ||||||
|         { |  | ||||||
|             u64 filesize = (u64) backend->GetSize(); |  | ||||||
|             cmd_buff[2]  = (u32) filesize;         // Lower word
 |  | ||||||
|             cmd_buff[3]  = (u32) (filesize >> 32); // Upper word
 |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         case FileCommand::SetSize: |  | ||||||
|         { |  | ||||||
|             backend->SetSize(cmd_buff[1] | ((u64)cmd_buff[2] << 32)); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         case FileCommand::Close: |  | ||||||
|         { |  | ||||||
|             LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); |  | ||||||
|             CloseArchive(backend->GetIdCode()); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         // Unknown command...
 |  | ||||||
|         default: |  | ||||||
|         { |  | ||||||
|             LOG_ERROR(Service_FS, "Unknown command=0x%08X", cmd); |  | ||||||
|             cmd_buff[0] = UnimplementedFunction(ErrorModule::FS).raw; |  | ||||||
|             return MakeResult<bool>(false); |  | ||||||
|         } |  | ||||||
|         } |  | ||||||
|         cmd_buff[1] = 0; // No error
 |  | ||||||
|         return MakeResult<bool>(false); |  | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     std::string GetName() const { return "Archive: " + backend->GetName(); } | ||||||
|  | 
 | ||||||
|  |     ArchiveIdCode id_code; ///< Id code of the archive
 | ||||||
|  |     std::unique_ptr<FileSys::ArchiveBackend> backend; ///< Archive backend interface
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class File : public Kernel::Session { | class File : public Kernel::Session { | ||||||
| public: | public: | ||||||
|  |     File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) | ||||||
|  |             : backend(std::move(backend)), path(path) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     std::string GetName() const override { return "Path: " + path.DebugStr(); } |     std::string GetName() const override { return "Path: " + path.DebugStr(); } | ||||||
| 
 | 
 | ||||||
|     FileSys::Path path; ///< Path of the file
 |     FileSys::Path path; ///< Path of the file
 | ||||||
|     std::unique_ptr<FileSys::File> backend; ///< File backend interface
 |     std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
 | ||||||
| 
 | 
 | ||||||
|     ResultVal<bool> SyncRequest() override { |     ResultVal<bool> SyncRequest() override { | ||||||
|         u32* cmd_buff = Kernel::GetCommandBuffer(); |         u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
|  | @ -185,10 +149,14 @@ public: | ||||||
| 
 | 
 | ||||||
| class Directory : public Kernel::Session { | class Directory : public Kernel::Session { | ||||||
| public: | public: | ||||||
|  |     Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) | ||||||
|  |             : backend(std::move(backend)), path(path) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     std::string GetName() const override { return "Directory: " + path.DebugStr(); } |     std::string GetName() const override { return "Directory: " + path.DebugStr(); } | ||||||
| 
 | 
 | ||||||
|     FileSys::Path path; ///< Path of the directory
 |     FileSys::Path path; ///< Path of the directory
 | ||||||
|     std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
 |     std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface
 | ||||||
| 
 | 
 | ||||||
|     ResultVal<bool> SyncRequest() override { |     ResultVal<bool> SyncRequest() override { | ||||||
|         u32* cmd_buff = Kernel::GetCommandBuffer(); |         u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
|  | @ -230,105 +198,95 @@ public: | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode
 | /**
 | ||||||
| 
 |  * Map of registered archives, identified by id code. Once an archive is registered here, it is | ||||||
| ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) { |  * never removed until the FS service is shut down. | ||||||
|     auto itr = g_archive_map.find(id_code); |  */ | ||||||
|     if (itr == g_archive_map.end()) { | static std::unordered_map<ArchiveIdCode, std::unique_ptr<Archive>> id_code_map; | ||||||
|         return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |  | ||||||
|                 ErrorSummary::NotFound, ErrorLevel::Permanent); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return MakeResult<Handle>(itr->second); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ResultCode CloseArchive(FileSys::Archive::IdCode id_code) { |  | ||||||
|     auto itr = g_archive_map.find(id_code); |  | ||||||
|     if (itr == g_archive_map.end()) { |  | ||||||
|         LOG_ERROR(Service_FS, "Cannot close archive %d, does not exist!", (int)id_code); |  | ||||||
|         return InvalidHandle(ErrorModule::FS); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     LOG_TRACE(Service_FS, "Closed archive %d", (int) id_code); |  | ||||||
|     return RESULT_SUCCESS; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Mounts an archive |  * Map of active archive handles. Values are pointers to the archives in `idcode_map`. | ||||||
|  * @param archive Pointer to the archive to mount |  | ||||||
|  */ |  */ | ||||||
| ResultCode MountArchive(Archive* archive) { | static std::unordered_map<ArchiveHandle, Archive*> handle_map; | ||||||
|     FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); | static ArchiveHandle next_handle; | ||||||
|     ResultVal<Handle> archive_handle = OpenArchive(id_code); | 
 | ||||||
|     if (archive_handle.Succeeded()) { | static Archive* GetArchive(ArchiveHandle handle) { | ||||||
|         LOG_ERROR(Service_FS, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); |     auto itr = handle_map.find(handle); | ||||||
|         return archive_handle.Code(); |     return (itr == handle_map.end()) ? nullptr : itr->second; | ||||||
|     } |  | ||||||
|     g_archive_map[id_code] = archive->GetHandle(); |  | ||||||
|     LOG_TRACE(Service_FS, "Mounted archive %s", archive->GetName().c_str()); |  | ||||||
|     return RESULT_SUCCESS; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name) { | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code) { | ||||||
|     Archive* archive = new Archive; |     LOG_TRACE(Service_FS, "Opening archive with id code 0x%08X", id_code); | ||||||
|     Handle handle = Kernel::g_object_pool.Create(archive); |  | ||||||
|     archive->name = name; |  | ||||||
|     archive->backend = backend; |  | ||||||
| 
 | 
 | ||||||
|     ResultCode result = MountArchive(archive); |     auto itr = id_code_map.find(id_code); | ||||||
|     if (result.IsError()) { |     if (itr == id_code_map.end()) { | ||||||
|         return result; |         // TODO: Verify error against hardware
 | ||||||
|     } |  | ||||||
|      |  | ||||||
|     return RESULT_SUCCESS; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { |  | ||||||
|     // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create
 |  | ||||||
|     // the archive file handles at app loading, and then keep them persistent throughout execution.
 |  | ||||||
|     // Archives file handles are just reused and not actually freed until emulation shut down.
 |  | ||||||
|     // Verify if real hardware works this way, or if new handles are created each time
 |  | ||||||
|     if (path.GetType() == FileSys::Binary) |  | ||||||
|         // TODO(bunnei): FixMe - this is a hack to compensate for an incorrect FileSys backend
 |  | ||||||
|         // design. While the functionally of this is OK, our implementation decision to separate
 |  | ||||||
|         // normal files from archive file pointers is very likely wrong.
 |  | ||||||
|         // See https://github.com/citra-emu/citra/issues/205
 |  | ||||||
|         return MakeResult<Handle>(archive_handle); |  | ||||||
| 
 |  | ||||||
|     File* file = new File; |  | ||||||
|     Handle handle = Kernel::g_object_pool.Create(file); |  | ||||||
| 
 |  | ||||||
|     Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); |  | ||||||
|     if (archive == nullptr) { |  | ||||||
|         return InvalidHandle(ErrorModule::FS); |  | ||||||
|     } |  | ||||||
|     file->path = path; |  | ||||||
|     file->backend = archive->backend->OpenFile(path, mode); |  | ||||||
| 
 |  | ||||||
|     if (!file->backend) { |  | ||||||
|         return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |         return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | ||||||
|                 ErrorSummary::NotFound, ErrorLevel::Permanent); |                 ErrorSummary::NotFound, ErrorLevel::Permanent); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // This should never even happen in the first place with 64-bit handles, 
 | ||||||
|  |     while (handle_map.count(next_handle) != 0) { | ||||||
|  |         ++next_handle; | ||||||
|  |     } | ||||||
|  |     handle_map.emplace(next_handle, itr->second.get()); | ||||||
|  |     return MakeResult<ArchiveHandle>(next_handle++); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ResultCode CloseArchive(ArchiveHandle handle) { | ||||||
|  |     if (handle_map.erase(handle) == 0) | ||||||
|  |         return InvalidHandle(ErrorModule::FS); | ||||||
|  |     else | ||||||
|  |         return RESULT_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in
 | ||||||
|  | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22
 | ||||||
|  | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) { | ||||||
|  |     auto result = id_code_map.emplace(id_code, std::make_unique<Archive>(std::move(backend), id_code)); | ||||||
|  | 
 | ||||||
|  |     bool inserted = result.second; | ||||||
|  |     _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); | ||||||
|  | 
 | ||||||
|  |     auto& archive = result.first->second; | ||||||
|  |     LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); | ||||||
|  |     return RESULT_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { | ||||||
|  |     Archive* archive = GetArchive(archive_handle); | ||||||
|  |     if (archive == nullptr) | ||||||
|  |         return InvalidHandle(ErrorModule::FS); | ||||||
|  | 
 | ||||||
|  |     std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); | ||||||
|  |     if (backend == nullptr) { | ||||||
|  |         return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | ||||||
|  |                           ErrorSummary::NotFound, ErrorLevel::Permanent); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     auto file = std::make_unique<File>(std::move(backend), path); | ||||||
|  |     Handle handle = Kernel::g_object_pool.Create(file.release()); | ||||||
|     return MakeResult<Handle>(handle); |     return MakeResult<Handle>(handle); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) { | ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | ||||||
|     Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); |     Archive* archive = GetArchive(archive_handle); | ||||||
|     if (archive == nullptr) |     if (archive == nullptr) | ||||||
|         return InvalidHandle(ErrorModule::FS); |         return InvalidHandle(ErrorModule::FS); | ||||||
|  | 
 | ||||||
|     if (archive->backend->DeleteFile(path)) |     if (archive->backend->DeleteFile(path)) | ||||||
|         return RESULT_SUCCESS; |         return RESULT_SUCCESS; | ||||||
|     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 |     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 | ||||||
|                       ErrorSummary::Canceled, ErrorLevel::Status); |                       ErrorSummary::Canceled, ErrorLevel::Status); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | ||||||
|                                      Handle dest_archive_handle, const FileSys::Path& dest_path) { |                                      ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { | ||||||
|     Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle); |     Archive* src_archive = GetArchive(src_archive_handle); | ||||||
|     Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle); |     Archive* dest_archive = GetArchive(dest_archive_handle); | ||||||
|     if (src_archive == nullptr || dest_archive == nullptr) |     if (src_archive == nullptr || dest_archive == nullptr) | ||||||
|         return InvalidHandle(ErrorModule::FS); |         return InvalidHandle(ErrorModule::FS); | ||||||
|  | 
 | ||||||
|     if (src_archive == dest_archive) { |     if (src_archive == dest_archive) { | ||||||
|         if (src_archive->backend->RenameFile(src_path, dest_path)) |         if (src_archive->backend->RenameFile(src_path, dest_path)) | ||||||
|             return RESULT_SUCCESS; |             return RESULT_SUCCESS; | ||||||
|  | @ -336,36 +294,42 @@ ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::P | ||||||
|         // TODO: Implement renaming across archives
 |         // TODO: Implement renaming across archives
 | ||||||
|         return UnimplementedFunction(ErrorModule::FS); |         return UnimplementedFunction(ErrorModule::FS); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't
 | ||||||
|  |     // exist or similar. Verify.
 | ||||||
|     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 |     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 | ||||||
|                       ErrorSummary::NothingHappened, ErrorLevel::Status); |                       ErrorSummary::NothingHappened, ErrorLevel::Status); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | ||||||
|     Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); |     Archive* archive = GetArchive(archive_handle); | ||||||
|     if (archive == nullptr) |     if (archive == nullptr) | ||||||
|         return InvalidHandle(ErrorModule::FS); |         return InvalidHandle(ErrorModule::FS); | ||||||
|  | 
 | ||||||
|     if (archive->backend->DeleteDirectory(path)) |     if (archive->backend->DeleteDirectory(path)) | ||||||
|         return RESULT_SUCCESS; |         return RESULT_SUCCESS; | ||||||
|     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 |     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 | ||||||
|                       ErrorSummary::Canceled, ErrorLevel::Status); |                       ErrorSummary::Canceled, ErrorLevel::Status); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | ||||||
|     Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); |     Archive* archive = GetArchive(archive_handle); | ||||||
|     if (archive == nullptr) |     if (archive == nullptr) | ||||||
|         return InvalidHandle(ErrorModule::FS); |         return InvalidHandle(ErrorModule::FS); | ||||||
|  | 
 | ||||||
|     if (archive->backend->CreateDirectory(path)) |     if (archive->backend->CreateDirectory(path)) | ||||||
|         return RESULT_SUCCESS; |         return RESULT_SUCCESS; | ||||||
|     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 |     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 | ||||||
|                       ErrorSummary::Canceled, ErrorLevel::Status); |                       ErrorSummary::Canceled, ErrorLevel::Status); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | ||||||
|                                           Handle dest_archive_handle, const FileSys::Path& dest_path) { |                                           ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { | ||||||
|     Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle); |     Archive* src_archive = GetArchive(src_archive_handle); | ||||||
|     Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle); |     Archive* dest_archive = GetArchive(dest_archive_handle); | ||||||
|     if (src_archive == nullptr || dest_archive == nullptr) |     if (src_archive == nullptr || dest_archive == nullptr) | ||||||
|         return InvalidHandle(ErrorModule::FS); |         return InvalidHandle(ErrorModule::FS); | ||||||
|  | 
 | ||||||
|     if (src_archive == dest_archive) { |     if (src_archive == dest_archive) { | ||||||
|         if (src_archive->backend->RenameDirectory(src_path, dest_path)) |         if (src_archive->backend->RenameDirectory(src_path, dest_path)) | ||||||
|             return RESULT_SUCCESS; |             return RESULT_SUCCESS; | ||||||
|  | @ -373,6 +337,9 @@ ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileS | ||||||
|         // TODO: Implement renaming across archives
 |         // TODO: Implement renaming across archives
 | ||||||
|         return UnimplementedFunction(ErrorModule::FS); |         return UnimplementedFunction(ErrorModule::FS); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't
 | ||||||
|  |     // exist or similar. Verify.
 | ||||||
|     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 |     return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
 | ||||||
|                       ErrorSummary::NothingHappened, ErrorLevel::Status); |                       ErrorSummary::NothingHappened, ErrorLevel::Status); | ||||||
| } | } | ||||||
|  | @ -383,44 +350,43 @@ ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileS | ||||||
|  * @param path Path to the Directory inside of the Archive |  * @param path Path to the Directory inside of the Archive | ||||||
|  * @return Opened Directory object |  * @return Opened Directory object | ||||||
|  */ |  */ | ||||||
| ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | ||||||
|     Directory* directory = new Directory; |     Archive* archive = GetArchive(archive_handle); | ||||||
|     Handle handle = Kernel::g_object_pool.Create(directory); |     if (archive == nullptr) | ||||||
| 
 |  | ||||||
|     Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); |  | ||||||
|     if (archive == nullptr) { |  | ||||||
|         return InvalidHandle(ErrorModule::FS); |         return InvalidHandle(ErrorModule::FS); | ||||||
|     } |  | ||||||
|     directory->path = path; |  | ||||||
|     directory->backend = archive->backend->OpenDirectory(path); |  | ||||||
| 
 | 
 | ||||||
|     if (!directory->backend) { |     std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path); | ||||||
|  |     if (backend == nullptr) { | ||||||
|         return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |         return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | ||||||
|                           ErrorSummary::NotFound, ErrorLevel::Permanent); |                           ErrorSummary::NotFound, ErrorLevel::Permanent); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     auto directory = std::make_unique<Directory>(std::move(backend), path); | ||||||
|  |     Handle handle = Kernel::g_object_pool.Create(directory.release()); | ||||||
|     return MakeResult<Handle>(handle); |     return MakeResult<Handle>(handle); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Initialize archives
 | /// Initialize archives
 | ||||||
| void ArchiveInit() { | void ArchiveInit() { | ||||||
|     g_archive_map.clear(); |     next_handle = 1; | ||||||
| 
 | 
 | ||||||
|     // TODO(Link Mauve): Add the other archive types (see here for the known types:
 |     // TODO(Link Mauve): Add the other archive types (see here for the known types:
 | ||||||
|     // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes).  Currently the only half-finished
 |     // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes).  Currently the only half-finished
 | ||||||
|     // archive type is SDMC, so it is the only one getting exposed.
 |     // archive type is SDMC, so it is the only one getting exposed.
 | ||||||
| 
 | 
 | ||||||
|     std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); |     std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); | ||||||
|     auto archive = new FileSys::Archive_SDMC(sdmc_directory); |     auto archive = std::make_unique<FileSys::Archive_SDMC>(sdmc_directory); | ||||||
|     if (archive->Initialize()) |     if (archive->Initialize()) | ||||||
|         CreateArchive(archive, "SDMC"); |         CreateArchive(std::move(archive), ArchiveIdCode::SDMC); | ||||||
|     else |     else | ||||||
|         LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); |         LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Shutdown archives
 | /// Shutdown archives
 | ||||||
| void ArchiveShutdown() { | void ArchiveShutdown() { | ||||||
|     g_archive_map.clear(); |     handle_map.clear(); | ||||||
|  |     id_code_map.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace Kernel
 | } // namespace FS
 | ||||||
|  | } // namespace Service
 | ||||||
|  | @ -6,34 +6,45 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive.h" | #include "core/file_sys/archive_backend.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | namespace Service { | ||||||
| // Kernel namespace
 | namespace FS { | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | /// Supported archive types
 | ||||||
|  | enum class ArchiveIdCode : u32 { | ||||||
|  |     RomFS               = 0x00000003, | ||||||
|  |     SaveData            = 0x00000004, | ||||||
|  |     ExtSaveData         = 0x00000006, | ||||||
|  |     SharedExtSaveData   = 0x00000007, | ||||||
|  |     SystemSaveData      = 0x00000008, | ||||||
|  |     SDMC                = 0x00000009, | ||||||
|  |     SDMCWriteOnly       = 0x0000000A, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef u64 ArchiveHandle; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Opens an archive |  * Opens an archive | ||||||
|  * @param id_code IdCode of the archive to open |  * @param id_code IdCode of the archive to open | ||||||
|  * @return Handle to the opened archive |  * @return Handle to the opened archive | ||||||
|  */ |  */ | ||||||
| ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code); | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Closes an archive |  * Closes an archive | ||||||
|  * @param id_code IdCode of the archive to open |  * @param id_code IdCode of the archive to open | ||||||
|  */ |  */ | ||||||
| ResultCode CloseArchive(FileSys::Archive::IdCode id_code); | ResultCode CloseArchive(ArchiveHandle handle); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Creates an Archive |  * Creates an Archive | ||||||
|  * @param backend File system backend interface to the archive |  * @param backend File system backend interface to the archive | ||||||
|  * @param name Name of Archive |  * @param id_code Id code used to access this type of archive | ||||||
|  */ |  */ | ||||||
| ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name); | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Open a File from an Archive |  * Open a File from an Archive | ||||||
|  | @ -42,7 +53,7 @@ ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name); | ||||||
|  * @param mode Mode under which to open the File |  * @param mode Mode under which to open the File | ||||||
|  * @return Handle to the opened File object |  * @return Handle to the opened File object | ||||||
|  */ |  */ | ||||||
| ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); | ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Delete a File from an Archive |  * Delete a File from an Archive | ||||||
|  | @ -50,7 +61,7 @@ ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path | ||||||
|  * @param path Path to the File inside of the Archive |  * @param path Path to the File inside of the Archive | ||||||
|  * @return Whether deletion succeeded |  * @return Whether deletion succeeded | ||||||
|  */ |  */ | ||||||
| ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path); | ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Rename a File between two Archives |  * Rename a File between two Archives | ||||||
|  | @ -60,8 +71,8 @@ ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& pat | ||||||
|  * @param dest_path Path to the File inside of the destination Archive |  * @param dest_path Path to the File inside of the destination Archive | ||||||
|  * @return Whether rename succeeded |  * @return Whether rename succeeded | ||||||
|  */ |  */ | ||||||
| ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | ||||||
|                                      Handle dest_archive_handle, const FileSys::Path& dest_path); |                                      ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Delete a Directory from an Archive |  * Delete a Directory from an Archive | ||||||
|  | @ -69,7 +80,7 @@ ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::P | ||||||
|  * @param path Path to the Directory inside of the Archive |  * @param path Path to the Directory inside of the Archive | ||||||
|  * @return Whether deletion succeeded |  * @return Whether deletion succeeded | ||||||
|  */ |  */ | ||||||
| ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); | ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Create a Directory from an Archive |  * Create a Directory from an Archive | ||||||
|  | @ -77,7 +88,7 @@ ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path | ||||||
|  * @param path Path to the Directory inside of the Archive |  * @param path Path to the Directory inside of the Archive | ||||||
|  * @return Whether creation of directory succeeded |  * @return Whether creation of directory succeeded | ||||||
|  */ |  */ | ||||||
| ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); | ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Rename a Directory between two Archives |  * Rename a Directory between two Archives | ||||||
|  | @ -87,8 +98,8 @@ ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path | ||||||
|  * @param dest_path Path to the Directory inside of the destination Archive |  * @param dest_path Path to the Directory inside of the destination Archive | ||||||
|  * @return Whether rename succeeded |  * @return Whether rename succeeded | ||||||
|  */ |  */ | ||||||
| ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | ||||||
|                                           Handle dest_archive_handle, const FileSys::Path& dest_path); |                                           ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Open a Directory from an Archive |  * Open a Directory from an Archive | ||||||
|  | @ -96,7 +107,7 @@ ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileS | ||||||
|  * @param path Path to the Directory inside of the Archive |  * @param path Path to the Directory inside of the Archive | ||||||
|  * @return Handle to the opened File object |  * @return Handle to the opened File object | ||||||
|  */ |  */ | ||||||
| ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); | ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); | ||||||
| 
 | 
 | ||||||
| /// Initialize archives
 | /// Initialize archives
 | ||||||
| void ArchiveInit(); | void ArchiveInit(); | ||||||
|  | @ -104,4 +115,5 @@ void ArchiveInit(); | ||||||
| /// Shutdown archives
 | /// Shutdown archives
 | ||||||
| void ArchiveShutdown(); | void ArchiveShutdown(); | ||||||
| 
 | 
 | ||||||
| } // namespace FileSys
 | } // namespace FS
 | ||||||
|  | } // namespace Service
 | ||||||
|  | @ -3,18 +3,23 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
|  | #include "common/scope_exit.h" | ||||||
| 
 | 
 | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/hle/kernel/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/hle/kernel/archive.h" |  | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/hle/service/fs_user.h" | #include "core/hle/service/fs/fs_user.h" | ||||||
| #include "core/settings.h" | #include "core/settings.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // Namespace FS_User
 | // Namespace FS_User
 | ||||||
| 
 | 
 | ||||||
| namespace FS_User { | namespace Service { | ||||||
|  | namespace FS { | ||||||
|  | 
 | ||||||
|  | static ArchiveHandle MakeArchiveHandle(u32 low_word, u32 high_word) { | ||||||
|  |     return (u64)low_word | ((u64)high_word << 32); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| static void Initialize(Service::Interface* self) { | static void Initialize(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
|  | @ -57,11 +62,12 @@ static void OpenFile(Service::Interface* self) { | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); |     LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); | ||||||
| 
 | 
 | ||||||
|     ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode); |     ResultVal<Handle> handle = OpenFileFromArchive(archive_handle, file_path, mode); | ||||||
|     cmd_buff[1] = handle.Code().raw; |     cmd_buff[1] = handle.Code().raw; | ||||||
|     if (handle.Succeeded()) { |     if (handle.Succeeded()) { | ||||||
|         cmd_buff[3] = *handle; |         cmd_buff[3] = *handle; | ||||||
|     } else { |     } else { | ||||||
|  |         cmd_buff[3] = 0; | ||||||
|         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -88,7 +94,7 @@ static void OpenFile(Service::Interface* self) { | ||||||
| static void OpenFileDirectly(Service::Interface* self) { | static void OpenFileDirectly(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|     auto archive_id       = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); |     auto archive_id       = static_cast<FS::ArchiveIdCode>(cmd_buff[2]); | ||||||
|     auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); |     auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); | ||||||
|     u32 archivename_size  = cmd_buff[4]; |     u32 archivename_size  = cmd_buff[4]; | ||||||
|     auto filename_type    = static_cast<FileSys::LowPathType>(cmd_buff[5]); |     auto filename_type    = static_cast<FileSys::LowPathType>(cmd_buff[5]); | ||||||
|  | @ -106,25 +112,25 @@ static void OpenFileDirectly(Service::Interface* self) { | ||||||
|     if (archive_path.GetType() != FileSys::Empty) { |     if (archive_path.GetType() != FileSys::Empty) { | ||||||
|         LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported"); |         LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported"); | ||||||
|         cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; |         cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; | ||||||
|  |         cmd_buff[3] = 0; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO(Link Mauve): Check if we should even get a handle for the archive, and don't leak it
 |     ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id); | ||||||
|     // TODO(yuriks): Why is there all this duplicate (and seemingly useless) code up here?
 |  | ||||||
|     ResultVal<Handle> archive_handle = Kernel::OpenArchive(archive_id); |  | ||||||
|     cmd_buff[1] = archive_handle.Code().raw; |  | ||||||
|     if (archive_handle.Failed()) { |     if (archive_handle.Failed()) { | ||||||
|         LOG_ERROR(Service_FS, "failed to get a handle for archive"); |         LOG_ERROR(Service_FS, "failed to get a handle for archive"); | ||||||
|  |         cmd_buff[1] = archive_handle.Code().raw; | ||||||
|  |         cmd_buff[3] = 0; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     // cmd_buff[2] isn't used according to 3dmoo's implementation.
 |     SCOPE_EXIT({ CloseArchive(*archive_handle); }); | ||||||
|     cmd_buff[3] = *archive_handle; |  | ||||||
| 
 | 
 | ||||||
|     ResultVal<Handle> handle = Kernel::OpenFileFromArchive(*archive_handle, file_path, mode); |     ResultVal<Handle> handle = OpenFileFromArchive(*archive_handle, file_path, mode); | ||||||
|     cmd_buff[1] = handle.Code().raw; |     cmd_buff[1] = handle.Code().raw; | ||||||
|     if (handle.Succeeded()) { |     if (handle.Succeeded()) { | ||||||
|         cmd_buff[3] = *handle; |         cmd_buff[3] = *handle; | ||||||
|     } else { |     } else { | ||||||
|  |         cmd_buff[3] = 0; | ||||||
|         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |         LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -140,12 +146,10 @@ static void OpenFileDirectly(Service::Interface* self) { | ||||||
|  *  Outputs: |  *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |  *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  */ |  */ | ||||||
| void DeleteFile(Service::Interface* self) { | static void DeleteFile(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|     // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
 |     ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | ||||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 |  | ||||||
|     Handle archive_handle = static_cast<Handle>(cmd_buff[3]); |  | ||||||
|     auto filename_type    = static_cast<FileSys::LowPathType>(cmd_buff[4]); |     auto filename_type    = static_cast<FileSys::LowPathType>(cmd_buff[4]); | ||||||
|     u32 filename_size     = cmd_buff[5]; |     u32 filename_size     = cmd_buff[5]; | ||||||
|     u32 filename_ptr      = cmd_buff[7]; |     u32 filename_ptr      = cmd_buff[7]; | ||||||
|  | @ -155,7 +159,7 @@ void DeleteFile(Service::Interface* self) { | ||||||
|     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", |     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", | ||||||
|               filename_type, filename_size, file_path.DebugStr().c_str()); |               filename_type, filename_size, file_path.DebugStr().c_str()); | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path).raw; |     cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -174,15 +178,13 @@ void DeleteFile(Service::Interface* self) { | ||||||
|  *  Outputs: |  *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |  *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  */ |  */ | ||||||
| void RenameFile(Service::Interface* self) { | static void RenameFile(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|     // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
 |     ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | ||||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 |  | ||||||
|     Handle src_archive_handle  = static_cast<Handle>(cmd_buff[3]); |  | ||||||
|     auto src_filename_type     = static_cast<FileSys::LowPathType>(cmd_buff[4]); |     auto src_filename_type     = static_cast<FileSys::LowPathType>(cmd_buff[4]); | ||||||
|     u32 src_filename_size      = cmd_buff[5]; |     u32 src_filename_size      = cmd_buff[5]; | ||||||
|     Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]); |     ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);; | ||||||
|     auto dest_filename_type    = static_cast<FileSys::LowPathType>(cmd_buff[8]); |     auto dest_filename_type    = static_cast<FileSys::LowPathType>(cmd_buff[8]); | ||||||
|     u32 dest_filename_size     = cmd_buff[9]; |     u32 dest_filename_size     = cmd_buff[9]; | ||||||
|     u32 src_filename_ptr       = cmd_buff[11]; |     u32 src_filename_ptr       = cmd_buff[11]; | ||||||
|  | @ -195,7 +197,7 @@ void RenameFile(Service::Interface* self) { | ||||||
|               src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), |               src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), | ||||||
|               dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); |               dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = Kernel::RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; |     cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -209,12 +211,10 @@ void RenameFile(Service::Interface* self) { | ||||||
|  *  Outputs: |  *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |  *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  */ |  */ | ||||||
| void DeleteDirectory(Service::Interface* self) { | static void DeleteDirectory(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|     // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
 |     ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | ||||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 |  | ||||||
|     Handle archive_handle = static_cast<Handle>(cmd_buff[3]); |  | ||||||
|     auto dirname_type     = static_cast<FileSys::LowPathType>(cmd_buff[4]); |     auto dirname_type     = static_cast<FileSys::LowPathType>(cmd_buff[4]); | ||||||
|     u32 dirname_size      = cmd_buff[5]; |     u32 dirname_size      = cmd_buff[5]; | ||||||
|     u32 dirname_ptr       = cmd_buff[7]; |     u32 dirname_ptr       = cmd_buff[7]; | ||||||
|  | @ -224,7 +224,7 @@ void DeleteDirectory(Service::Interface* self) { | ||||||
|     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", |     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", | ||||||
|               dirname_type, dirname_size, dir_path.DebugStr().c_str()); |               dirname_type, dirname_size, dir_path.DebugStr().c_str()); | ||||||
|      |      | ||||||
|     cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path).raw; |     cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -241,9 +241,7 @@ void DeleteDirectory(Service::Interface* self) { | ||||||
| static void CreateDirectory(Service::Interface* self) { | static void CreateDirectory(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|     // TODO: cmd_buff[2], aka archive handle lower word, isn't used according to
 |     ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | ||||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 |  | ||||||
|     Handle archive_handle = static_cast<Handle>(cmd_buff[3]); |  | ||||||
|     auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |     auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | ||||||
|     u32 dirname_size = cmd_buff[5]; |     u32 dirname_size = cmd_buff[5]; | ||||||
|     u32 dirname_ptr = cmd_buff[8]; |     u32 dirname_ptr = cmd_buff[8]; | ||||||
|  | @ -252,7 +250,7 @@ static void CreateDirectory(Service::Interface* self) { | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); |     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path).raw; |     cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -271,15 +269,13 @@ static void CreateDirectory(Service::Interface* self) { | ||||||
|  *  Outputs: |  *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |  *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  */ |  */ | ||||||
| void RenameDirectory(Service::Interface* self) { | static void RenameDirectory(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|     // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to
 |     ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | ||||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 |  | ||||||
|     Handle src_archive_handle  = static_cast<Handle>(cmd_buff[3]); |  | ||||||
|     auto src_dirname_type      = static_cast<FileSys::LowPathType>(cmd_buff[4]); |     auto src_dirname_type      = static_cast<FileSys::LowPathType>(cmd_buff[4]); | ||||||
|     u32 src_dirname_size       = cmd_buff[5]; |     u32 src_dirname_size       = cmd_buff[5]; | ||||||
|     Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]); |     ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]); | ||||||
|     auto dest_dirname_type     = static_cast<FileSys::LowPathType>(cmd_buff[8]); |     auto dest_dirname_type     = static_cast<FileSys::LowPathType>(cmd_buff[8]); | ||||||
|     u32 dest_dirname_size      = cmd_buff[9]; |     u32 dest_dirname_size      = cmd_buff[9]; | ||||||
|     u32 src_dirname_ptr        = cmd_buff[11]; |     u32 src_dirname_ptr        = cmd_buff[11]; | ||||||
|  | @ -292,15 +288,26 @@ void RenameDirectory(Service::Interface* self) { | ||||||
|               src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), |               src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), | ||||||
|               dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); |               dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = Kernel::RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; |     cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * FS_User::OpenDirectory service function | ||||||
|  |  *  Inputs: | ||||||
|  |  *      1 : Archive handle low word | ||||||
|  |  *      2 : Archive handle high word | ||||||
|  |  *      3 : Low path type | ||||||
|  |  *      4 : Low path size | ||||||
|  |  *      7 : (LowPathSize << 14) | 2 | ||||||
|  |  *      8 : Low path data pointer | ||||||
|  |  *  Outputs: | ||||||
|  |  *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  |  *      3 : Directory handle | ||||||
|  |  */ | ||||||
| static void OpenDirectory(Service::Interface* self) { | static void OpenDirectory(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|     // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
 |     ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[1], cmd_buff[2]); | ||||||
|     // 3dmoo's or ctrulib's implementations.  Triple check if it's really the case.
 |  | ||||||
|     Handle archive_handle = static_cast<Handle>(cmd_buff[2]); |  | ||||||
|     auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); |     auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); | ||||||
|     u32 dirname_size = cmd_buff[4]; |     u32 dirname_size = cmd_buff[4]; | ||||||
|     u32 dirname_ptr = cmd_buff[6]; |     u32 dirname_ptr = cmd_buff[6]; | ||||||
|  | @ -309,7 +316,7 @@ static void OpenDirectory(Service::Interface* self) { | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); |     LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); | ||||||
| 
 | 
 | ||||||
|     ResultVal<Handle> handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_path); |     ResultVal<Handle> handle = OpenDirectoryFromArchive(archive_handle, dir_path); | ||||||
|     cmd_buff[1] = handle.Code().raw; |     cmd_buff[1] = handle.Code().raw; | ||||||
|     if (handle.Succeeded()) { |     if (handle.Succeeded()) { | ||||||
|         cmd_buff[3] = *handle; |         cmd_buff[3] = *handle; | ||||||
|  | @ -334,7 +341,7 @@ static void OpenDirectory(Service::Interface* self) { | ||||||
| static void OpenArchive(Service::Interface* self) { | static void OpenArchive(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|     auto archive_id       = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); |     auto archive_id       = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); | ||||||
|     auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); |     auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); | ||||||
|     u32 archivename_size  = cmd_buff[3]; |     u32 archivename_size  = cmd_buff[3]; | ||||||
|     u32 archivename_ptr   = cmd_buff[5]; |     u32 archivename_ptr   = cmd_buff[5]; | ||||||
|  | @ -348,16 +355,34 @@ static void OpenArchive(Service::Interface* self) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ResultVal<Handle> handle = Kernel::OpenArchive(archive_id); |     ResultVal<ArchiveHandle> handle = OpenArchive(archive_id); | ||||||
|     cmd_buff[1] = handle.Code().raw; |     cmd_buff[1] = handle.Code().raw; | ||||||
|     if (handle.Succeeded()) { |     if (handle.Succeeded()) { | ||||||
|         // cmd_buff[2] isn't used according to 3dmoo's implementation.
 |         cmd_buff[2] = *handle & 0xFFFFFFFF; | ||||||
|         cmd_buff[3] = *handle; |         cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF; | ||||||
|     } else { |     } else { | ||||||
|  |         cmd_buff[2] = cmd_buff[3] = 0; | ||||||
|         LOG_ERROR(Service_FS, "failed to get a handle for archive"); |         LOG_ERROR(Service_FS, "failed to get a handle for archive"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * FS_User::CloseArchive service function | ||||||
|  |  *  Inputs: | ||||||
|  |  *      0 : 0x080E0080 | ||||||
|  |  *      1 : Archive handle low word | ||||||
|  |  *      2 : Archive handle high word | ||||||
|  |  *  Outputs: | ||||||
|  |  *      0 : ??? TODO(yuriks): Verify return header | ||||||
|  |  *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  |  */ | ||||||
|  | static void CloseArchive(Service::Interface* self) { | ||||||
|  |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
|  | 
 | ||||||
|  |     ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[1], cmd_buff[2]); | ||||||
|  |     cmd_buff[1] = CloseArchive(archive_handle).raw; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
| * FS_User::IsSdmcDetected service function | * FS_User::IsSdmcDetected service function | ||||||
| *  Outputs: | *  Outputs: | ||||||
|  | @ -373,7 +398,7 @@ static void IsSdmcDetected(Service::Interface* self) { | ||||||
|     LOG_DEBUG(Service_FS, "called"); |     LOG_DEBUG(Service_FS, "called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | const FSUserInterface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x000100C6, nullptr,               "Dummy1"}, |     {0x000100C6, nullptr,               "Dummy1"}, | ||||||
|     {0x040100C4, nullptr,               "Control"}, |     {0x040100C4, nullptr,               "Control"}, | ||||||
|     {0x08010002, Initialize,            "Initialize"}, |     {0x08010002, Initialize,            "Initialize"}, | ||||||
|  | @ -389,7 +414,7 @@ const Interface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x080B0102, OpenDirectory,         "OpenDirectory"}, |     {0x080B0102, OpenDirectory,         "OpenDirectory"}, | ||||||
|     {0x080C00C2, OpenArchive,           "OpenArchive"}, |     {0x080C00C2, OpenArchive,           "OpenArchive"}, | ||||||
|     {0x080D0144, nullptr,               "ControlArchive"}, |     {0x080D0144, nullptr,               "ControlArchive"}, | ||||||
|     {0x080E0080, nullptr,               "CloseArchive"}, |     {0x080E0080, CloseArchive,          "CloseArchive"}, | ||||||
|     {0x080F0180, nullptr,               "FormatThisUserSaveData"}, |     {0x080F0180, nullptr,               "FormatThisUserSaveData"}, | ||||||
|     {0x08100200, nullptr,               "CreateSystemSaveData"}, |     {0x08100200, nullptr,               "CreateSystemSaveData"}, | ||||||
|     {0x08110040, nullptr,               "DeleteSystemSaveData"}, |     {0x08110040, nullptr,               "DeleteSystemSaveData"}, | ||||||
|  | @ -465,11 +490,12 @@ const Interface::FunctionInfo FunctionTable[] = { | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // Interface class
 | // Interface class
 | ||||||
| 
 | 
 | ||||||
| Interface::Interface() { | FSUserInterface::FSUserInterface() { | ||||||
|     Register(FunctionTable, ARRAY_SIZE(FunctionTable)); |     Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Interface::~Interface() { | FSUserInterface::~FSUserInterface() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace FS
 | ||||||
|  | } // namespace Service
 | ||||||
|  | @ -9,15 +9,16 @@ | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // Namespace FS_User
 | // Namespace FS_User
 | ||||||
| 
 | 
 | ||||||
| namespace FS_User { | namespace Service { | ||||||
|  | namespace FS { | ||||||
| 
 | 
 | ||||||
| /// Interface to "fs:USER" service
 | /// Interface to "fs:USER" service
 | ||||||
| class Interface : public Service::Interface { | class FSUserInterface : public Service::Interface { | ||||||
| public: | public: | ||||||
| 
 | 
 | ||||||
|     Interface(); |     FSUserInterface(); | ||||||
| 
 | 
 | ||||||
|     ~Interface(); |     ~FSUserInterface(); | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Gets the string port name used by CTROS for the service |      * Gets the string port name used by CTROS for the service | ||||||
|  | @ -28,4 +29,5 @@ public: | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace FS
 | ||||||
|  | } // namespace Service
 | ||||||
|  | @ -17,7 +17,7 @@ | ||||||
| #include "core/hle/service/csnd_snd.h" | #include "core/hle/service/csnd_snd.h" | ||||||
| #include "core/hle/service/dsp_dsp.h" | #include "core/hle/service/dsp_dsp.h" | ||||||
| #include "core/hle/service/err_f.h" | #include "core/hle/service/err_f.h" | ||||||
| #include "core/hle/service/fs_user.h" | #include "core/hle/service/fs/fs_user.h" | ||||||
| #include "core/hle/service/frd_u.h" | #include "core/hle/service/frd_u.h" | ||||||
| #include "core/hle/service/gsp_gpu.h" | #include "core/hle/service/gsp_gpu.h" | ||||||
| #include "core/hle/service/hid_user.h" | #include "core/hle/service/hid_user.h" | ||||||
|  | @ -99,7 +99,7 @@ void Init() { | ||||||
|     g_manager->AddService(new DSP_DSP::Interface); |     g_manager->AddService(new DSP_DSP::Interface); | ||||||
|     g_manager->AddService(new ERR_F::Interface); |     g_manager->AddService(new ERR_F::Interface); | ||||||
|     g_manager->AddService(new FRD_U::Interface); |     g_manager->AddService(new FRD_U::Interface); | ||||||
|     g_manager->AddService(new FS_User::Interface); |     g_manager->AddService(new FS::FSUserInterface); | ||||||
|     g_manager->AddService(new GSP_GPU::Interface); |     g_manager->AddService(new GSP_GPU::Interface); | ||||||
|     g_manager->AddService(new HID_User::Interface); |     g_manager->AddService(new HID_User::Interface); | ||||||
|     g_manager->AddService(new IR_RST::Interface); |     g_manager->AddService(new IR_RST::Interface); | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
| #include "core/file_sys/archive_romfs.h" | #include "core/file_sys/archive_romfs.h" | ||||||
| #include "core/loader/elf.h" | #include "core/loader/elf.h" | ||||||
| #include "core/loader/ncch.h" | #include "core/loader/ncch.h" | ||||||
| #include "core/hle/kernel/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
| 
 | 
 | ||||||
| #include "3dsx.h" | #include "3dsx.h" | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
| #include "core/loader/3dsx.h" | #include "core/loader/3dsx.h" | ||||||
| #include "core/loader/elf.h" | #include "core/loader/elf.h" | ||||||
| #include "core/loader/ncch.h" | #include "core/loader/ncch.h" | ||||||
| #include "core/hle/kernel/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | @ -74,7 +74,7 @@ ResultStatus LoadFile(const std::string& filename) { | ||||||
| 
 | 
 | ||||||
|         // Load application and RomFS
 |         // Load application and RomFS
 | ||||||
|         if (ResultStatus::Success == app_loader.Load()) { |         if (ResultStatus::Success == app_loader.Load()) { | ||||||
|             Kernel::CreateArchive(new FileSys::Archive_RomFS(app_loader), "RomFS"); |             Service::FS::CreateArchive(std::make_unique<FileSys::Archive_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS); | ||||||
|             return ResultStatus::Success; |             return ResultStatus::Success; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|  | @ -23,10 +23,10 @@ void Init(EmuWindow* emu_window) { | ||||||
|     Core::Init(); |     Core::Init(); | ||||||
|     Memory::Init(); |     Memory::Init(); | ||||||
|     HW::Init(); |     HW::Init(); | ||||||
|  |     Kernel::Init(); | ||||||
|     HLE::Init(); |     HLE::Init(); | ||||||
|     CoreTiming::Init(); |     CoreTiming::Init(); | ||||||
|     VideoCore::Init(emu_window); |     VideoCore::Init(emu_window); | ||||||
|     Kernel::Init(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RunLoopFor(int cycles) { | void RunLoopFor(int cycles) { | ||||||
|  | @ -37,13 +37,13 @@ void RunLoopUntil(u64 global_cycles) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     Core::Shutdown(); |  | ||||||
|     Memory::Shutdown(); |  | ||||||
|     HW::Shutdown(); |  | ||||||
|     HLE::Shutdown(); |  | ||||||
|     CoreTiming::Shutdown(); |  | ||||||
|     VideoCore::Shutdown(); |     VideoCore::Shutdown(); | ||||||
|  |     CoreTiming::Shutdown(); | ||||||
|  |     HLE::Shutdown(); | ||||||
|     Kernel::Shutdown(); |     Kernel::Shutdown(); | ||||||
|  |     HW::Shutdown(); | ||||||
|  |     Memory::Shutdown(); | ||||||
|  |     Core::Shutdown(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue