diff options
38 files changed, 607 insertions, 533 deletions
diff --git a/.travis-build.sh b/.travis-build.sh index 78e7583a8..b869b8b8f 100644 --- a/.travis-build.sh +++ b/.travis-build.sh | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | 2 | ||
| 3 | set -e | 3 | set -e |
| 4 | set -x | ||
| 4 | 5 | ||
| 5 | #if OS is linux or is not set | 6 | #if OS is linux or is not set |
| 6 | if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then | 7 | if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then |
diff --git a/.travis-deps.sh b/.travis-deps.sh index b8e8417b2..8e22a6358 100644 --- a/.travis-deps.sh +++ b/.travis-deps.sh | |||
| @@ -1,13 +1,14 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | 2 | ||
| 3 | set -e | 3 | set -e |
| 4 | set -x | ||
| 4 | 5 | ||
| 5 | #if OS is linux or is not set | 6 | #if OS is linux or is not set |
| 6 | if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then | 7 | if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then |
| 7 | sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y | 8 | sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y |
| 8 | sudo apt-get -qq update | 9 | sudo apt-get -qq update |
| 9 | sudo apt-get -qq install g++-4.8 xorg-dev libglu1-mesa-dev libxcursor-dev | 10 | sudo apt-get -qq install g++-4.9 xorg-dev libglu1-mesa-dev libxcursor-dev |
| 10 | sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90 | 11 | sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 90 |
| 11 | ( | 12 | ( |
| 12 | git clone https://github.com/glfw/glfw.git --branch 3.0.4 --depth 1 | 13 | git clone https://github.com/glfw/glfw.git --branch 3.0.4 --depth 1 |
| 13 | mkdir glfw/build && cd glfw/build | 14 | mkdir glfw/build && cd glfw/build |
diff --git a/CMakeLists.txt b/CMakeLists.txt index 61d5d524a..63738b5ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -5,7 +5,8 @@ cmake_minimum_required(VERSION 2.8.11) | |||
| 5 | project(citra) | 5 | project(citra) |
| 6 | 6 | ||
| 7 | if (NOT MSVC) | 7 | if (NOT MSVC) |
| 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-attributes") | 8 | # -std=c++14 is only supported on very new compilers, so use the old c++1y alias instead. |
| 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -Wno-attributes") | ||
| 9 | else() | 10 | else() |
| 10 | # Silence deprecation warnings | 11 | # Silence deprecation warnings |
| 11 | add_definitions(/D_CRT_SECURE_NO_WARNINGS) | 12 | add_definitions(/D_CRT_SECURE_NO_WARNINGS) |
| @@ -1,10 +1,12 @@ | |||
| 1 | citra emulator | 1 | Citra Emulator |
| 2 | ============== | 2 | ============== |
| 3 | [](https://travis-ci.org/citra-emu/citra) | 3 | [](https://travis-ci.org/citra-emu/citra) |
| 4 | 4 | ||
| 5 | An experimental open-source Nintendo 3DS emulator/debugger written in C++. Citra is written with portability in mind, with builds actively maintained for Windows, Linux and OS X. At this time, it only emulates a subset of 3DS hardware, and therefore is generally only useful for booting/debugging very simple homebrew demos. Citra is licensed under the GPLv2. Refer to the license.txt file included. Please read the [FAQ](https://github.com/citra-emu/citra/wiki/FAQ) before getting started with the project. | 5 | Citra is an experimental open-source Nintendo 3DS emulator/debugger written in C++. It is written with portability in mind, with builds actively maintained for Windows, Linux and OS X. At this time, it only emulates a subset of 3DS hardware, and therefore is generally only useful for booting/debugging very simple homebrew demos. However, this is changing as more and more progress is being made on running commercial titles, too. |
| 6 | 6 | ||
| 7 | For development discussion, please join us @ #citra on [freenode](http://webchat.freenode.net/). | 7 | Citra is licensed under the GPLv2. Refer to the license.txt file included. Please read the [FAQ](https://github.com/citra-emu/citra/wiki/FAQ) before getting started with the project. |
| 8 | |||
| 9 | For development discussion, please join us @ #citra on [freenode](http://webchat.freenode.net/?channels=citra). | ||
| 8 | 10 | ||
| 9 | ### Development | 11 | ### Development |
| 10 | 12 | ||
| @@ -15,3 +17,15 @@ If you want to contribute please take a took at the [Contributor's Guide](CONTRI | |||
| 15 | * __Windows__: [Windows Build](https://github.com/citra-emu/citra/wiki/Windows-Build) | 17 | * __Windows__: [Windows Build](https://github.com/citra-emu/citra/wiki/Windows-Build) |
| 16 | * __Linux__: [Linux Build](https://github.com/citra-emu/citra/wiki/Linux-Build) | 18 | * __Linux__: [Linux Build](https://github.com/citra-emu/citra/wiki/Linux-Build) |
| 17 | * __OSX__: [OS X Build](https://github.com/citra-emu/citra/wiki/OS-X-Build) | 19 | * __OSX__: [OS X Build](https://github.com/citra-emu/citra/wiki/OS-X-Build) |
| 20 | |||
| 21 | |||
| 22 | ### Support | ||
| 23 | If you like, you can [donate by PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=K899FANUJ2ZXW) - any donation received will go towards things like: | ||
| 24 | * 3DS consoles for developers to explore the hardware | ||
| 25 | * 3DS games for testing | ||
| 26 | * Any equipment required for homebrew | ||
| 27 | * Infrastructure setup | ||
| 28 | * Eventually 3D displays to get proper 3D output working | ||
| 29 | * ... etc ... | ||
| 30 | |||
| 31 | We also more than gladly accept used 3DS consoles, preferrably ones with firmware 4.5 or lower! If you would like to give yours away, don't hesitate to join our IRC channel #citra on [Freenode](http://webchat.freenode.net/?channels=citra) and talk to neobrain or bunnei. Mind you, IRC is slow-paced, so it might be a while until people reply. If you're in a hurry you can just leave contact details in the channel or via private message and we'll get back to you. | ||
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 1299338ac..23d4925b8 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp | |||
| @@ -157,12 +157,6 @@ void GMainWindow::BootGame(std::string filename) | |||
| 157 | LOG_INFO(Frontend, "Citra starting...\n"); | 157 | LOG_INFO(Frontend, "Citra starting...\n"); |
| 158 | System::Init(render_window); | 158 | System::Init(render_window); |
| 159 | 159 | ||
| 160 | if (Core::Init()) { | ||
| 161 | LOG_CRITICAL(Frontend, "Core initialization failed, exiting..."); | ||
| 162 | Core::Stop(); | ||
| 163 | exit(1); | ||
| 164 | } | ||
| 165 | |||
| 166 | // Load a game or die... | 160 | // Load a game or die... |
| 167 | if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) { | 161 | if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) { |
| 168 | LOG_CRITICAL(Frontend, "Failed to load ROM!"); | 162 | LOG_CRITICAL(Frontend, "Failed to load ROM!"); |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ab63f54de..198e4afd3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -24,7 +24,6 @@ set(SRCS | |||
| 24 | file_sys/directory_romfs.cpp | 24 | file_sys/directory_romfs.cpp |
| 25 | file_sys/directory_sdmc.cpp | 25 | file_sys/directory_sdmc.cpp |
| 26 | hle/kernel/address_arbiter.cpp | 26 | hle/kernel/address_arbiter.cpp |
| 27 | hle/kernel/archive.cpp | ||
| 28 | hle/kernel/event.cpp | 27 | hle/kernel/event.cpp |
| 29 | hle/kernel/kernel.cpp | 28 | hle/kernel/kernel.cpp |
| 30 | hle/kernel/mutex.cpp | 29 | hle/kernel/mutex.cpp |
| @@ -32,21 +31,26 @@ set(SRCS | |||
| 32 | hle/kernel/shared_memory.cpp | 31 | hle/kernel/shared_memory.cpp |
| 33 | hle/kernel/thread.cpp | 32 | hle/kernel/thread.cpp |
| 34 | hle/service/ac_u.cpp | 33 | hle/service/ac_u.cpp |
| 34 | hle/service/am_app.cpp | ||
| 35 | hle/service/am_net.cpp | 35 | hle/service/am_net.cpp |
| 36 | hle/service/apt_u.cpp | 36 | hle/service/apt_u.cpp |
| 37 | hle/service/boss_u.cpp | 37 | hle/service/boss_u.cpp |
| 38 | hle/service/cecd_u.cpp | ||
| 38 | hle/service/cfg_i.cpp | 39 | hle/service/cfg_i.cpp |
| 39 | hle/service/cfg_u.cpp | 40 | hle/service/cfg_u.cpp |
| 40 | hle/service/csnd_snd.cpp | 41 | hle/service/csnd_snd.cpp |
| 41 | hle/service/dsp_dsp.cpp | 42 | hle/service/dsp_dsp.cpp |
| 42 | hle/service/err_f.cpp | 43 | hle/service/err_f.cpp |
| 43 | hle/service/fs_user.cpp | 44 | hle/service/fs/archive.cpp |
| 45 | hle/service/fs/fs_user.cpp | ||
| 44 | hle/service/frd_u.cpp | 46 | hle/service/frd_u.cpp |
| 45 | hle/service/gsp_gpu.cpp | 47 | hle/service/gsp_gpu.cpp |
| 46 | hle/service/hid_user.cpp | 48 | hle/service/hid_user.cpp |
| 47 | hle/service/ir_rst.cpp | 49 | hle/service/ir_rst.cpp |
| 48 | hle/service/ir_u.cpp | 50 | hle/service/ir_u.cpp |
| 51 | hle/service/ldr_ro.cpp | ||
| 49 | hle/service/mic_u.cpp | 52 | hle/service/mic_u.cpp |
| 53 | hle/service/nim_aoc.cpp | ||
| 50 | hle/service/ndm_u.cpp | 54 | hle/service/ndm_u.cpp |
| 51 | hle/service/nwm_uds.cpp | 55 | hle/service/nwm_uds.cpp |
| 52 | hle/service/pm_app.cpp | 56 | hle/service/pm_app.cpp |
| @@ -93,17 +97,16 @@ set(HEADERS | |||
| 93 | arm/skyeye_common/vfp/vfp.h | 97 | arm/skyeye_common/vfp/vfp.h |
| 94 | arm/skyeye_common/vfp/vfp_helper.h | 98 | arm/skyeye_common/vfp/vfp_helper.h |
| 95 | arm/arm_interface.h | 99 | arm/arm_interface.h |
| 96 | file_sys/archive.h | 100 | file_sys/archive_backend.h |
| 97 | file_sys/archive_romfs.h | 101 | file_sys/archive_romfs.h |
| 98 | file_sys/archive_sdmc.h | 102 | file_sys/archive_sdmc.h |
| 99 | file_sys/file.h | 103 | file_sys/file_backend.h |
| 100 | file_sys/file_romfs.h | 104 | file_sys/file_romfs.h |
| 101 | file_sys/file_sdmc.h | 105 | file_sys/file_sdmc.h |
| 102 | file_sys/directory.h | 106 | file_sys/directory_backend.h |
| 103 | file_sys/directory_romfs.h | 107 | file_sys/directory_romfs.h |
| 104 | file_sys/directory_sdmc.h | 108 | file_sys/directory_sdmc.h |
| 105 | hle/kernel/address_arbiter.h | 109 | hle/kernel/address_arbiter.h |
| 106 | hle/kernel/archive.h | ||
| 107 | hle/kernel/event.h | 110 | hle/kernel/event.h |
| 108 | hle/kernel/kernel.h | 111 | hle/kernel/kernel.h |
| 109 | hle/kernel/mutex.h | 112 | hle/kernel/mutex.h |
| @@ -112,21 +115,26 @@ set(HEADERS | |||
| 112 | hle/kernel/shared_memory.h | 115 | hle/kernel/shared_memory.h |
| 113 | hle/kernel/thread.h | 116 | hle/kernel/thread.h |
| 114 | hle/service/ac_u.h | 117 | hle/service/ac_u.h |
| 118 | hle/service/am_app.h | ||
| 115 | hle/service/am_net.h | 119 | hle/service/am_net.h |
| 116 | hle/service/apt_u.h | 120 | hle/service/apt_u.h |
| 117 | hle/service/boss_u.h | 121 | hle/service/boss_u.h |
| 122 | hle/service/cecd_u.h | ||
| 118 | hle/service/cfg_i.h | 123 | hle/service/cfg_i.h |
| 119 | hle/service/cfg_u.h | 124 | hle/service/cfg_u.h |
| 120 | hle/service/csnd_snd.h | 125 | hle/service/csnd_snd.h |
| 121 | hle/service/dsp_dsp.h | 126 | hle/service/dsp_dsp.h |
| 122 | hle/service/err_f.h | 127 | hle/service/err_f.h |
| 123 | hle/service/fs_user.h | 128 | hle/service/fs/archive.h |
| 129 | hle/service/fs/fs_user.h | ||
| 124 | hle/service/frd_u.h | 130 | hle/service/frd_u.h |
| 125 | hle/service/gsp_gpu.h | 131 | hle/service/gsp_gpu.h |
| 126 | hle/service/hid_user.h | 132 | hle/service/hid_user.h |
| 127 | hle/service/ir_rst.h | 133 | hle/service/ir_rst.h |
| 128 | hle/service/ir_u.h | 134 | hle/service/ir_u.h |
| 135 | hle/service/ldr_ro.h | ||
| 129 | hle/service/mic_u.h | 136 | hle/service/mic_u.h |
| 137 | hle/service/nim_aoc.h | ||
| 130 | hle/service/ndm_u.h | 138 | hle/service/ndm_u.h |
| 131 | hle/service/nwm_uds.h | 139 | hle/service/nwm_uds.h |
| 132 | hle/service/pm_app.h | 140 | hle/service/pm_app.h |
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index e4159ceb0..5752d116f 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp | |||
| @@ -6101,17 +6101,32 @@ L_stm_s_takeabort: | |||
| 6101 | 6101 | ||
| 6102 | return 1; | 6102 | return 1; |
| 6103 | } | 6103 | } |
| 6104 | case 0x6c: | 6104 | case 0x6c: // UXTB16 and UXTAB16 |
| 6105 | if ((instr & 0xf03f0) == 0xf0070) { //uxtb16 | 6105 | { |
| 6106 | u8 rm_idx = BITS(0, 3); | 6106 | const u8 rm_idx = BITS(0, 3); |
| 6107 | u8 rd_idx = BITS(12, 15); | 6107 | const u8 rn_idx = BITS(16, 19); |
| 6108 | u32 rm_val = state->Reg[rm_idx]; | 6108 | const u8 rd_idx = BITS(12, 15); |
| 6109 | u32 rotation = BITS(10, 11) * 8; | 6109 | const u32 rm_val = state->Reg[rm_idx]; |
| 6110 | u32 in = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); | 6110 | const u32 rn_val = state->Reg[rn_idx]; |
| 6111 | state->Reg[rd_idx] = in & 0x00FF00FF; | 6111 | const u32 rotation = BITS(10, 11) * 8; |
| 6112 | const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); | ||
| 6113 | |||
| 6114 | // UXTB16 | ||
| 6115 | if ((instr & 0xf03f0) == 0xf0070) { | ||
| 6116 | state->Reg[rd_idx] = rotated_rm & 0x00FF00FF; | ||
| 6117 | } | ||
| 6118 | else { // UXTAB16 | ||
| 6119 | const u8 lo_rotated = (rotated_rm & 0xFF); | ||
| 6120 | const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated; | ||
| 6121 | |||
| 6122 | const u8 hi_rotated = (rotated_rm >> 16) & 0xFF; | ||
| 6123 | const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated; | ||
| 6124 | |||
| 6125 | state->Reg[rd_idx] = ((hi_result << 16) | (lo_result & 0xFFFF)); | ||
| 6126 | } | ||
| 6127 | |||
| 6112 | return 1; | 6128 | return 1; |
| 6113 | } else | 6129 | } |
| 6114 | printf ("Unhandled v6 insn: uxtab16\n"); | ||
| 6115 | break; | 6130 | break; |
| 6116 | case 0x6e: { | 6131 | case 0x6e: { |
| 6117 | ARMword Rm; | 6132 | ARMword Rm; |
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index 871900497..6c33d8b78 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp | |||
| @@ -614,7 +614,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 614 | exceptions |= FPSCR_IDC; | 614 | exceptions |= FPSCR_IDC; |
| 615 | 615 | ||
| 616 | if (tm & VFP_NAN) | 616 | if (tm & VFP_NAN) |
| 617 | vsm.sign = 0; | 617 | vsm.sign = 1; |
| 618 | 618 | ||
| 619 | if (vsm.exponent >= 127 + 32) { | 619 | if (vsm.exponent >= 127 + 32) { |
| 620 | d = vsm.sign ? 0 : 0xffffffff; | 620 | d = vsm.sign ? 0 : 0xffffffff; |
| @@ -1148,7 +1148,10 @@ static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | |||
| 1148 | /* | 1148 | /* |
| 1149 | * Subtraction is addition with one sign inverted. | 1149 | * Subtraction is addition with one sign inverted. |
| 1150 | */ | 1150 | */ |
| 1151 | return vfp_single_fadd(state, sd, sn, vfp_single_packed_negate(m), fpscr); | 1151 | if (m != 0x7FC00000) // Only negate if m isn't NaN. |
| 1152 | m = vfp_single_packed_negate(m); | ||
| 1153 | |||
| 1154 | return vfp_single_fadd(state, sd, sn, m, fpscr); | ||
| 1152 | } | 1155 | } |
| 1153 | 1156 | ||
| 1154 | /* | 1157 | /* |
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive_backend.h index 27ed23cd0..18c314884 100644 --- a/src/core/file_sys/archive.h +++ b/src/core/file_sys/archive_backend.h | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | #include "common/string_util.h" | 10 | #include "common/string_util.h" |
| 11 | #include "common/bit_field.h" | 11 | #include "common/bit_field.h" |
| 12 | 12 | ||
| 13 | #include "core/file_sys/file.h" | 13 | #include "core/file_sys/file_backend.h" |
| 14 | #include "core/file_sys/directory.h" | 14 | #include "core/file_sys/directory_backend.h" |
| 15 | 15 | ||
| 16 | #include "core/mem_map.h" | 16 | #include "core/mem_map.h" |
| 17 | #include "core/hle/kernel/kernel.h" | 17 | #include "core/hle/kernel/kernel.h" |
| @@ -160,27 +160,14 @@ private: | |||
| 160 | std::u16string u16str; | 160 | std::u16string u16str; |
| 161 | }; | 161 | }; |
| 162 | 162 | ||
| 163 | class Archive : NonCopyable { | 163 | class ArchiveBackend : NonCopyable { |
| 164 | public: | 164 | public: |
| 165 | /// Supported archive types | 165 | virtual ~ArchiveBackend() { } |
| 166 | enum class IdCode : u32 { | ||
| 167 | RomFS = 0x00000003, | ||
| 168 | SaveData = 0x00000004, | ||
| 169 | ExtSaveData = 0x00000006, | ||
| 170 | SharedExtSaveData = 0x00000007, | ||
| 171 | SystemSaveData = 0x00000008, | ||
| 172 | SDMC = 0x00000009, | ||
| 173 | SDMCWriteOnly = 0x0000000A, | ||
| 174 | }; | ||
| 175 | |||
| 176 | Archive() { } | ||
| 177 | virtual ~Archive() { } | ||
| 178 | 166 | ||
| 179 | /** | 167 | /** |
| 180 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | 168 | * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) |
| 181 | * @return IdCode of the archive | ||
| 182 | */ | 169 | */ |
| 183 | virtual IdCode GetIdCode() const = 0; | 170 | virtual std::string GetName() const = 0; |
| 184 | 171 | ||
| 185 | /** | 172 | /** |
| 186 | * Open a file specified by its path, using the specified mode | 173 | * Open a file specified by its path, using the specified mode |
| @@ -188,7 +175,7 @@ public: | |||
| 188 | * @param mode Mode to open the file with | 175 | * @param mode Mode to open the file with |
| 189 | * @return Opened file, or nullptr | 176 | * @return Opened file, or nullptr |
| 190 | */ | 177 | */ |
| 191 | virtual std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const = 0; | 178 | virtual std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const = 0; |
| 192 | 179 | ||
| 193 | /** | 180 | /** |
| 194 | * Delete a file specified by its path | 181 | * Delete a file specified by its path |
| @@ -232,37 +219,7 @@ public: | |||
| 232 | * @param path Path relative to the archive | 219 | * @param path Path relative to the archive |
| 233 | * @return Opened directory, or nullptr | 220 | * @return Opened directory, or nullptr |
| 234 | */ | 221 | */ |
| 235 | virtual std::unique_ptr<Directory> OpenDirectory(const Path& path) const = 0; | 222 | virtual std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const = 0; |
| 236 | |||
| 237 | /** | ||
| 238 | * Read data from the archive | ||
| 239 | * @param offset Offset in bytes to start reading data from | ||
| 240 | * @param length Length in bytes of data to read from archive | ||
| 241 | * @param buffer Buffer to read data into | ||
| 242 | * @return Number of bytes read | ||
| 243 | */ | ||
| 244 | virtual size_t Read(const u64 offset, const u32 length, u8* buffer) const = 0; | ||
| 245 | |||
| 246 | /** | ||
| 247 | * Write data to the archive | ||
| 248 | * @param offset Offset in bytes to start writing data to | ||
| 249 | * @param length Length in bytes of data to write to archive | ||
| 250 | * @param buffer Buffer to write data from | ||
| 251 | * @param flush The flush parameters (0 == do not flush) | ||
| 252 | * @return Number of bytes written | ||
| 253 | */ | ||
| 254 | virtual size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) = 0; | ||
| 255 | |||
| 256 | /** | ||
| 257 | * Get the size of the archive in bytes | ||
| 258 | * @return Size of the archive in bytes | ||
| 259 | */ | ||
| 260 | virtual size_t GetSize() const = 0; | ||
| 261 | |||
| 262 | /** | ||
| 263 | * Set the size of the archive in bytes | ||
| 264 | */ | ||
| 265 | virtual void SetSize(const u64 size) = 0; | ||
| 266 | }; | 223 | }; |
| 267 | 224 | ||
| 268 | } // namespace FileSys | 225 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index 74974c2df..0709b62a1 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <memory> | ||
| 6 | |||
| 5 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 6 | 8 | ||
| 7 | #include "core/file_sys/archive_romfs.h" | 9 | #include "core/file_sys/archive_romfs.h" |
| @@ -20,17 +22,14 @@ Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) { | |||
| 20 | } | 22 | } |
| 21 | } | 23 | } |
| 22 | 24 | ||
| 23 | Archive_RomFS::~Archive_RomFS() { | ||
| 24 | } | ||
| 25 | |||
| 26 | /** | 25 | /** |
| 27 | * Open a file specified by its path, using the specified mode | 26 | * Open a file specified by its path, using the specified mode |
| 28 | * @param path Path relative to the archive | 27 | * @param path Path relative to the archive |
| 29 | * @param mode Mode to open the file with | 28 | * @param mode Mode to open the file with |
| 30 | * @return Opened file, or nullptr | 29 | * @return Opened file, or nullptr |
| 31 | */ | 30 | */ |
| 32 | std::unique_ptr<File> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { | 31 | std::unique_ptr<FileBackend> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { |
| 33 | return std::unique_ptr<File>(new File_RomFS); | 32 | return std::make_unique<File_RomFS>(this); |
| 34 | } | 33 | } |
| 35 | 34 | ||
| 36 | /** | 35 | /** |
| @@ -78,49 +77,8 @@ bool Archive_RomFS::RenameDirectory(const FileSys::Path& src_path, const FileSys | |||
| 78 | * @param path Path relative to the archive | 77 | * @param path Path relative to the archive |
| 79 | * @return Opened directory, or nullptr | 78 | * @return Opened directory, or nullptr |
| 80 | */ | 79 | */ |
| 81 | std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const Path& path) const { | 80 | std::unique_ptr<DirectoryBackend> Archive_RomFS::OpenDirectory(const Path& path) const { |
| 82 | return std::unique_ptr<Directory>(new Directory_RomFS); | 81 | return std::make_unique<Directory_RomFS>(); |
| 83 | } | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Read data from the archive | ||
| 87 | * @param offset Offset in bytes to start reading data from | ||
| 88 | * @param length Length in bytes of data to read from archive | ||
| 89 | * @param buffer Buffer to read data into | ||
| 90 | * @return Number of bytes read | ||
| 91 | */ | ||
| 92 | size_t Archive_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 93 | LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); | ||
| 94 | memcpy(buffer, &raw_data[(u32)offset], length); | ||
| 95 | return length; | ||
| 96 | } | ||
| 97 | |||
| 98 | /** | ||
| 99 | * Write data to the archive | ||
| 100 | * @param offset Offset in bytes to start writing data to | ||
| 101 | * @param length Length in bytes of data to write to archive | ||
| 102 | * @param buffer Buffer to write data from | ||
| 103 | * @param flush The flush parameters (0 == do not flush) | ||
| 104 | * @return Number of bytes written | ||
| 105 | */ | ||
| 106 | size_t Archive_RomFS::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { | ||
| 107 | LOG_WARNING(Service_FS, "Attempted to write to ROMFS."); | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | /** | ||
| 112 | * Get the size of the archive in bytes | ||
| 113 | * @return Size of the archive in bytes | ||
| 114 | */ | ||
| 115 | size_t Archive_RomFS::GetSize() const { | ||
| 116 | return sizeof(u8) * raw_data.size(); | ||
| 117 | } | ||
| 118 | |||
| 119 | /** | ||
| 120 | * Set the size of the archive in bytes | ||
| 121 | */ | ||
| 122 | void Archive_RomFS::SetSize(const u64 size) { | ||
| 123 | LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS"); | ||
| 124 | } | 82 | } |
| 125 | 83 | ||
| 126 | } // namespace FileSys | 84 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index 222bdc356..5b1ee6332 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | 10 | ||
| 11 | #include "core/file_sys/archive.h" | 11 | #include "core/file_sys/archive_backend.h" |
| 12 | #include "core/loader/loader.h" | 12 | #include "core/loader/loader.h" |
| 13 | 13 | ||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -17,16 +17,11 @@ | |||
| 17 | namespace FileSys { | 17 | namespace FileSys { |
| 18 | 18 | ||
| 19 | /// File system interface to the RomFS archive | 19 | /// File system interface to the RomFS archive |
| 20 | class Archive_RomFS final : public Archive { | 20 | class Archive_RomFS final : public ArchiveBackend { |
| 21 | public: | 21 | public: |
| 22 | Archive_RomFS(const Loader::AppLoader& app_loader); | 22 | Archive_RomFS(const Loader::AppLoader& app_loader); |
| 23 | ~Archive_RomFS() override; | ||
| 24 | 23 | ||
| 25 | /** | 24 | std::string GetName() const override { return "RomFS"; } |
| 26 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | ||
| 27 | * @return IdCode of the archive | ||
| 28 | */ | ||
| 29 | IdCode GetIdCode() const override { return IdCode::RomFS; } | ||
| 30 | 25 | ||
| 31 | /** | 26 | /** |
| 32 | * Open a file specified by its path, using the specified mode | 27 | * Open a file specified by its path, using the specified mode |
| @@ -34,7 +29,7 @@ public: | |||
| 34 | * @param mode Mode to open the file with | 29 | * @param mode Mode to open the file with |
| 35 | * @return Opened file, or nullptr | 30 | * @return Opened file, or nullptr |
| 36 | */ | 31 | */ |
| 37 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; | 32 | std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; |
| 38 | 33 | ||
| 39 | /** | 34 | /** |
| 40 | * Delete a file specified by its path | 35 | * Delete a file specified by its path |
| @@ -78,39 +73,11 @@ public: | |||
| 78 | * @param path Path relative to the archive | 73 | * @param path Path relative to the archive |
| 79 | * @return Opened directory, or nullptr | 74 | * @return Opened directory, or nullptr |
| 80 | */ | 75 | */ |
| 81 | std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; | 76 | std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; |
| 82 | |||
| 83 | /** | ||
| 84 | * Read data from the archive | ||
| 85 | * @param offset Offset in bytes to start reading data from | ||
| 86 | * @param length Length in bytes of data to read from archive | ||
| 87 | * @param buffer Buffer to read data into | ||
| 88 | * @return Number of bytes read | ||
| 89 | */ | ||
| 90 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 91 | |||
| 92 | /** | ||
| 93 | * Write data to the archive | ||
| 94 | * @param offset Offset in bytes to start writing data to | ||
| 95 | * @param length Length in bytes of data to write to archive | ||
| 96 | * @param buffer Buffer to write data from | ||
| 97 | * @param flush The flush parameters (0 == do not flush) | ||
| 98 | * @return Number of bytes written | ||
| 99 | */ | ||
| 100 | size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; | ||
| 101 | |||
| 102 | /** | ||
| 103 | * Get the size of the archive in bytes | ||
| 104 | * @return Size of the archive in bytes | ||
| 105 | */ | ||
| 106 | size_t GetSize() const override; | ||
| 107 | |||
| 108 | /** | ||
| 109 | * Set the size of the archive in bytes | ||
| 110 | */ | ||
| 111 | void SetSize(const u64 size) override; | ||
| 112 | 77 | ||
| 113 | private: | 78 | private: |
| 79 | friend class File_RomFS; | ||
| 80 | |||
| 114 | std::vector<u8> raw_data; | 81 | std::vector<u8> raw_data; |
| 115 | }; | 82 | }; |
| 116 | 83 | ||
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 9e524b60e..9d58668e0 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -49,12 +49,12 @@ bool Archive_SDMC::Initialize() { | |||
| 49 | * @param mode Mode to open the file with | 49 | * @param mode Mode to open the file with |
| 50 | * @return Opened file, or nullptr | 50 | * @return Opened file, or nullptr |
| 51 | */ | 51 | */ |
| 52 | std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { | 52 | std::unique_ptr<FileBackend> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { |
| 53 | LOG_DEBUG(Service_FS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex); | 53 | LOG_DEBUG(Service_FS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex); |
| 54 | File_SDMC* file = new File_SDMC(this, path, mode); | 54 | File_SDMC* file = new File_SDMC(this, path, mode); |
| 55 | if (!file->Open()) | 55 | if (!file->Open()) |
| 56 | return nullptr; | 56 | return nullptr; |
| 57 | return std::unique_ptr<File>(file); | 57 | return std::unique_ptr<FileBackend>(file); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | /** | 60 | /** |
| @@ -97,53 +97,12 @@ bool Archive_SDMC::RenameDirectory(const FileSys::Path& src_path, const FileSys: | |||
| 97 | * @param path Path relative to the archive | 97 | * @param path Path relative to the archive |
| 98 | * @return Opened directory, or nullptr | 98 | * @return Opened directory, or nullptr |
| 99 | */ | 99 | */ |
| 100 | std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const { | 100 | std::unique_ptr<DirectoryBackend> Archive_SDMC::OpenDirectory(const Path& path) const { |
| 101 | LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); | 101 | LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); |
| 102 | Directory_SDMC* directory = new Directory_SDMC(this, path); | 102 | Directory_SDMC* directory = new Directory_SDMC(this, path); |
| 103 | if (!directory->Open()) | 103 | if (!directory->Open()) |
| 104 | return nullptr; | 104 | return nullptr; |
| 105 | return std::unique_ptr<Directory>(directory); | 105 | return std::unique_ptr<DirectoryBackend>(directory); |
| 106 | } | ||
| 107 | |||
| 108 | /** | ||
| 109 | * Read data from the archive | ||
| 110 | * @param offset Offset in bytes to start reading archive from | ||
| 111 | * @param length Length in bytes to read data from archive | ||
| 112 | * @param buffer Buffer to read data into | ||
| 113 | * @return Number of bytes read | ||
| 114 | */ | ||
| 115 | size_t Archive_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 116 | LOG_ERROR(Service_FS, "(UNIMPLEMENTED)"); | ||
| 117 | return -1; | ||
| 118 | } | ||
| 119 | |||
| 120 | /** | ||
| 121 | * Write data to the archive | ||
| 122 | * @param offset Offset in bytes to start writing data to | ||
| 123 | * @param length Length in bytes of data to write to archive | ||
| 124 | * @param buffer Buffer to write data from | ||
| 125 | * @param flush The flush parameters (0 == do not flush) | ||
| 126 | * @return Number of bytes written | ||
| 127 | */ | ||
| 128 | size_t Archive_SDMC::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { | ||
| 129 | LOG_ERROR(Service_FS, "(UNIMPLEMENTED)"); | ||
| 130 | return -1; | ||
| 131 | } | ||
| 132 | |||
| 133 | /** | ||
| 134 | * Get the size of the archive in bytes | ||
| 135 | * @return Size of the archive in bytes | ||
| 136 | */ | ||
| 137 | size_t Archive_SDMC::GetSize() const { | ||
| 138 | LOG_ERROR(Service_FS, "(UNIMPLEMENTED)"); | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | /** | ||
| 143 | * Set the size of the archive in bytes | ||
| 144 | */ | ||
| 145 | void Archive_SDMC::SetSize(const u64 size) { | ||
| 146 | LOG_ERROR(Service_FS, "(UNIMPLEMENTED)"); | ||
| 147 | } | 106 | } |
| 148 | 107 | ||
| 149 | /** | 108 | /** |
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 19f563a62..059045245 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/file_sys/archive.h" | 9 | #include "core/file_sys/archive_backend.h" |
| 10 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 11 | 11 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -15,7 +15,7 @@ | |||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | /// File system interface to the SDMC archive | 17 | /// File system interface to the SDMC archive |
| 18 | class Archive_SDMC final : public Archive { | 18 | class Archive_SDMC final : public ArchiveBackend { |
| 19 | public: | 19 | public: |
| 20 | Archive_SDMC(const std::string& mount_point); | 20 | Archive_SDMC(const std::string& mount_point); |
| 21 | ~Archive_SDMC() override; | 21 | ~Archive_SDMC() override; |
| @@ -26,11 +26,7 @@ public: | |||
| 26 | */ | 26 | */ |
| 27 | bool Initialize(); | 27 | bool Initialize(); |
| 28 | 28 | ||
| 29 | /** | 29 | std::string GetName() const override { return "SDMC"; } |
| 30 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | ||
| 31 | * @return IdCode of the archive | ||
| 32 | */ | ||
| 33 | IdCode GetIdCode() const override { return IdCode::SDMC; } | ||
| 34 | 30 | ||
| 35 | /** | 31 | /** |
| 36 | * Open a file specified by its path, using the specified mode | 32 | * Open a file specified by its path, using the specified mode |
| @@ -38,7 +34,7 @@ public: | |||
| 38 | * @param mode Mode to open the file with | 34 | * @param mode Mode to open the file with |
| 39 | * @return Opened file, or nullptr | 35 | * @return Opened file, or nullptr |
| 40 | */ | 36 | */ |
| 41 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; | 37 | std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; |
| 42 | 38 | ||
| 43 | /** | 39 | /** |
| 44 | * Delete a file specified by its path | 40 | * Delete a file specified by its path |
| @@ -82,37 +78,7 @@ public: | |||
| 82 | * @param path Path relative to the archive | 78 | * @param path Path relative to the archive |
| 83 | * @return Opened directory, or nullptr | 79 | * @return Opened directory, or nullptr |
| 84 | */ | 80 | */ |
| 85 | std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; | 81 | std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; |
| 86 | |||
| 87 | /** | ||
| 88 | * Read data from the archive | ||
| 89 | * @param offset Offset in bytes to start reading archive from | ||
| 90 | * @param length Length in bytes to read data from archive | ||
| 91 | * @param buffer Buffer to read data into | ||
| 92 | * @return Number of bytes read | ||
| 93 | */ | ||
| 94 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 95 | |||
| 96 | /** | ||
| 97 | * Write data to the archive | ||
| 98 | * @param offset Offset in bytes to start writing data to | ||
| 99 | * @param length Length in bytes of data to write to archive | ||
| 100 | * @param buffer Buffer to write data from | ||
| 101 | * @param flush The flush parameters (0 == do not flush) | ||
| 102 | * @return Number of bytes written | ||
| 103 | */ | ||
| 104 | size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; | ||
| 105 | |||
| 106 | /** | ||
| 107 | * Get the size of the archive in bytes | ||
| 108 | * @return Size of the archive in bytes | ||
| 109 | */ | ||
| 110 | size_t GetSize() const override; | ||
| 111 | |||
| 112 | /** | ||
| 113 | * Set the size of the archive in bytes | ||
| 114 | */ | ||
| 115 | void SetSize(const u64 size) override; | ||
| 116 | 82 | ||
| 117 | /** | 83 | /** |
| 118 | * Getter for the path used for this Archive | 84 | * Getter for the path used for this Archive |
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory_backend.h index 1bb4101d6..188746a6f 100644 --- a/src/core/file_sys/directory.h +++ b/src/core/file_sys/directory_backend.h | |||
| @@ -36,10 +36,10 @@ static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension i | |||
| 36 | static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); | 36 | static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); |
| 37 | static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); | 37 | static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); |
| 38 | 38 | ||
| 39 | class Directory : NonCopyable { | 39 | class DirectoryBackend : NonCopyable { |
| 40 | public: | 40 | public: |
| 41 | Directory() { } | 41 | DirectoryBackend() { } |
| 42 | virtual ~Directory() { } | 42 | virtual ~DirectoryBackend() { } |
| 43 | 43 | ||
| 44 | /** | 44 | /** |
| 45 | * Open the directory | 45 | * Open the directory |
diff --git a/src/core/file_sys/directory_romfs.h b/src/core/file_sys/directory_romfs.h index e2944099e..b775f014d 100644 --- a/src/core/file_sys/directory_romfs.h +++ b/src/core/file_sys/directory_romfs.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/file_sys/directory.h" | 9 | #include "core/file_sys/directory_backend.h" |
| 10 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 11 | 11 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | class Directory_RomFS final : public Directory { | 17 | class Directory_RomFS final : public DirectoryBackend { |
| 18 | public: | 18 | public: |
| 19 | Directory_RomFS(); | 19 | Directory_RomFS(); |
| 20 | ~Directory_RomFS() override; | 20 | ~Directory_RomFS() override; |
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h index 4c08b0d61..407a256ef 100644 --- a/src/core/file_sys/directory_sdmc.h +++ b/src/core/file_sys/directory_sdmc.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | 9 | ||
| 10 | #include "core/file_sys/directory.h" | 10 | #include "core/file_sys/directory_backend.h" |
| 11 | #include "core/file_sys/archive_sdmc.h" | 11 | #include "core/file_sys/archive_sdmc.h" |
| 12 | #include "core/loader/loader.h" | 12 | #include "core/loader/loader.h" |
| 13 | 13 | ||
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | namespace FileSys { | 17 | namespace FileSys { |
| 18 | 18 | ||
| 19 | class Directory_SDMC final : public Directory { | 19 | class Directory_SDMC final : public DirectoryBackend { |
| 20 | public: | 20 | public: |
| 21 | Directory_SDMC(); | 21 | Directory_SDMC(); |
| 22 | Directory_SDMC(const Archive_SDMC* archive, const Path& path); | 22 | Directory_SDMC(const Archive_SDMC* archive, const Path& path); |
diff --git a/src/core/file_sys/file.h b/src/core/file_sys/file_backend.h index 4013b6c3e..1b81d5fe9 100644 --- a/src/core/file_sys/file.h +++ b/src/core/file_sys/file_backend.h | |||
| @@ -13,10 +13,10 @@ | |||
| 13 | 13 | ||
| 14 | namespace FileSys { | 14 | namespace FileSys { |
| 15 | 15 | ||
| 16 | class File : NonCopyable { | 16 | class FileBackend : NonCopyable { |
| 17 | public: | 17 | public: |
| 18 | File() { } | 18 | FileBackend() { } |
| 19 | virtual ~File() { } | 19 | virtual ~FileBackend() { } |
| 20 | 20 | ||
| 21 | /** | 21 | /** |
| 22 | * Open the file | 22 | * Open the file |
diff --git a/src/core/file_sys/file_romfs.cpp b/src/core/file_sys/file_romfs.cpp index b55708df4..5f38c2704 100644 --- a/src/core/file_sys/file_romfs.cpp +++ b/src/core/file_sys/file_romfs.cpp | |||
| @@ -5,24 +5,19 @@ | |||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | 6 | ||
| 7 | #include "core/file_sys/file_romfs.h" | 7 | #include "core/file_sys/file_romfs.h" |
| 8 | #include "core/file_sys/archive_romfs.h" | ||
| 8 | 9 | ||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 10 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 10 | // FileSys namespace | 11 | // FileSys namespace |
| 11 | 12 | ||
| 12 | namespace FileSys { | 13 | namespace FileSys { |
| 13 | 14 | ||
| 14 | File_RomFS::File_RomFS() { | ||
| 15 | } | ||
| 16 | |||
| 17 | File_RomFS::~File_RomFS() { | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | 15 | /** |
| 21 | * Open the file | 16 | * Open the file |
| 22 | * @return true if the file opened correctly | 17 | * @return true if the file opened correctly |
| 23 | */ | 18 | */ |
| 24 | bool File_RomFS::Open() { | 19 | bool File_RomFS::Open() { |
| 25 | return false; | 20 | return true; |
| 26 | } | 21 | } |
| 27 | 22 | ||
| 28 | /** | 23 | /** |
| @@ -33,7 +28,9 @@ bool File_RomFS::Open() { | |||
| 33 | * @return Number of bytes read | 28 | * @return Number of bytes read |
| 34 | */ | 29 | */ |
| 35 | size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | 30 | size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { |
| 36 | return -1; | 31 | LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); |
| 32 | memcpy(buffer, &archive->raw_data[(u32)offset], length); | ||
| 33 | return length; | ||
| 37 | } | 34 | } |
| 38 | 35 | ||
| 39 | /** | 36 | /** |
| @@ -45,7 +42,8 @@ size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | |||
| 45 | * @return Number of bytes written | 42 | * @return Number of bytes written |
| 46 | */ | 43 | */ |
| 47 | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | 44 | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { |
| 48 | return -1; | 45 | LOG_WARNING(Service_FS, "Attempted to write to ROMFS."); |
| 46 | return 0; | ||
| 49 | } | 47 | } |
| 50 | 48 | ||
| 51 | /** | 49 | /** |
| @@ -53,7 +51,7 @@ size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, co | |||
| 53 | * @return Size of the file in bytes | 51 | * @return Size of the file in bytes |
| 54 | */ | 52 | */ |
| 55 | size_t File_RomFS::GetSize() const { | 53 | size_t File_RomFS::GetSize() const { |
| 56 | return -1; | 54 | return sizeof(u8) * archive->raw_data.size(); |
| 57 | } | 55 | } |
| 58 | 56 | ||
| 59 | /** | 57 | /** |
| @@ -62,6 +60,7 @@ size_t File_RomFS::GetSize() const { | |||
| 62 | * @return true if successful | 60 | * @return true if successful |
| 63 | */ | 61 | */ |
| 64 | bool File_RomFS::SetSize(const u64 size) const { | 62 | bool File_RomFS::SetSize(const u64 size) const { |
| 63 | LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS"); | ||
| 65 | return false; | 64 | return false; |
| 66 | } | 65 | } |
| 67 | 66 | ||
diff --git a/src/core/file_sys/file_romfs.h b/src/core/file_sys/file_romfs.h index 5196701d3..09fa2e7e3 100644 --- a/src/core/file_sys/file_romfs.h +++ b/src/core/file_sys/file_romfs.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/file_sys/file.h" | 9 | #include "core/file_sys/file_backend.h" |
| 10 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 11 | 11 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -14,10 +14,11 @@ | |||
| 14 | 14 | ||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | class File_RomFS final : public File { | 17 | class Archive_RomFS; |
| 18 | |||
| 19 | class File_RomFS final : public FileBackend { | ||
| 18 | public: | 20 | public: |
| 19 | File_RomFS(); | 21 | File_RomFS(const Archive_RomFS* archive) : archive(archive) {} |
| 20 | ~File_RomFS() override; | ||
| 21 | 22 | ||
| 22 | /** | 23 | /** |
| 23 | * Open the file | 24 | * Open the file |
| @@ -62,6 +63,9 @@ public: | |||
| 62 | * @return true if the file closed correctly | 63 | * @return true if the file closed correctly |
| 63 | */ | 64 | */ |
| 64 | bool Close() const override; | 65 | bool Close() const override; |
| 66 | |||
| 67 | private: | ||
| 68 | const Archive_RomFS* archive; | ||
| 65 | }; | 69 | }; |
| 66 | 70 | ||
| 67 | } // namespace FileSys | 71 | } // namespace FileSys |
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h index 80b445968..e01548598 100644 --- a/src/core/file_sys/file_sdmc.h +++ b/src/core/file_sys/file_sdmc.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | 9 | ||
| 10 | #include "core/file_sys/file.h" | 10 | #include "core/file_sys/file_backend.h" |
| 11 | #include "core/file_sys/archive_sdmc.h" | 11 | #include "core/file_sys/archive_sdmc.h" |
| 12 | #include "core/loader/loader.h" | 12 | #include "core/loader/loader.h" |
| 13 | 13 | ||
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | namespace FileSys { | 17 | namespace FileSys { |
| 18 | 18 | ||
| 19 | class File_SDMC final : public File { | 19 | class File_SDMC final : public FileBackend { |
| 20 | public: | 20 | public: |
| 21 | File_SDMC(); | 21 | File_SDMC(); |
| 22 | File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode); | 22 | File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode); |
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 3f73b5538..cc3d5255a 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "core/hle/hle.h" | 8 | #include "core/hle/hle.h" |
| 9 | #include "core/hle/kernel/thread.h" | 9 | #include "core/hle/kernel/thread.h" |
| 10 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| 11 | #include "core/hle/service/fs/archive.h" | ||
| 11 | 12 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 13 | 14 | ||
| @@ -56,6 +57,7 @@ void RegisterAllModules() { | |||
| 56 | 57 | ||
| 57 | void Init() { | 58 | void Init() { |
| 58 | Service::Init(); | 59 | Service::Init(); |
| 60 | Service::FS::ArchiveInit(); | ||
| 59 | 61 | ||
| 60 | RegisterAllModules(); | 62 | RegisterAllModules(); |
| 61 | 63 | ||
| @@ -63,6 +65,7 @@ void Init() { | |||
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | void Shutdown() { | 67 | void Shutdown() { |
| 68 | Service::FS::ArchiveShutdown(); | ||
| 66 | Service::Shutdown(); | 69 | Service::Shutdown(); |
| 67 | 70 | ||
| 68 | g_module_db.clear(); | 71 | g_module_db.clear(); |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b38be0a49..929422b36 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/thread.h" | 11 | #include "core/hle/kernel/thread.h" |
| 12 | #include "core/hle/kernel/archive.h" | ||
| 13 | 12 | ||
| 14 | namespace Kernel { | 13 | namespace Kernel { |
| 15 | 14 | ||
| @@ -89,13 +88,11 @@ Object* ObjectPool::CreateByIDType(int type) { | |||
| 89 | /// Initialize the kernel | 88 | /// Initialize the kernel |
| 90 | void Init() { | 89 | void Init() { |
| 91 | Kernel::ThreadingInit(); | 90 | Kernel::ThreadingInit(); |
| 92 | Kernel::ArchiveInit(); | ||
| 93 | } | 91 | } |
| 94 | 92 | ||
| 95 | /// Shutdown the kernel | 93 | /// Shutdown the kernel |
| 96 | void Shutdown() { | 94 | void Shutdown() { |
| 97 | Kernel::ThreadingShutdown(); | 95 | Kernel::ThreadingShutdown(); |
| 98 | Kernel::ArchiveShutdown(); | ||
| 99 | 96 | ||
| 100 | g_object_pool.Clear(); // Free all kernel objects | 97 | g_object_pool.Clear(); // Free all kernel objects |
| 101 | } | 98 | } |
| @@ -106,8 +103,6 @@ void Shutdown() { | |||
| 106 | * @return True on success, otherwise false | 103 | * @return True on success, otherwise false |
| 107 | */ | 104 | */ |
| 108 | bool LoadExec(u32 entry_point) { | 105 | bool LoadExec(u32 entry_point) { |
| 109 | Init(); | ||
| 110 | |||
| 111 | Core::g_app_core->SetPC(entry_point); | 106 | Core::g_app_core->SetPC(entry_point); |
| 112 | 107 | ||
| 113 | // 0x30 is the typical main thread priority I've seen used so far | 108 | // 0x30 is the typical main thread priority I've seen used so far |
diff --git a/src/core/hle/service/am_app.cpp b/src/core/hle/service/am_app.cpp new file mode 100644 index 000000000..b8b06418c --- /dev/null +++ b/src/core/hle/service/am_app.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/am_app.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace AM_APP | ||
| 11 | |||
| 12 | namespace AM_APP { | ||
| 13 | |||
| 14 | // Empty arrays are illegal -- commented out until an entry is added. | ||
| 15 | //const Interface::FunctionInfo FunctionTable[] = { }; | ||
| 16 | |||
| 17 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 18 | // Interface class | ||
| 19 | |||
| 20 | Interface::Interface() { | ||
| 21 | //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace | ||
diff --git a/src/core/hle/service/fs_user.h b/src/core/hle/service/am_app.h index 005382540..86a5f5b74 100644 --- a/src/core/hle/service/fs_user.h +++ b/src/core/hle/service/am_app.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2+ |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| @@ -7,24 +7,20 @@ | |||
| 7 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | 8 | ||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 10 | // Namespace FS_User | 10 | // Namespace AM_APP |
| 11 | 11 | ||
| 12 | namespace FS_User { | 12 | namespace AM_APP { |
| 13 | 13 | ||
| 14 | /// Interface to "fs:USER" service | ||
| 15 | class Interface : public Service::Interface { | 14 | class Interface : public Service::Interface { |
| 16 | public: | 15 | public: |
| 17 | |||
| 18 | Interface(); | 16 | Interface(); |
| 19 | 17 | ||
| 20 | ~Interface(); | ||
| 21 | |||
| 22 | /** | 18 | /** |
| 23 | * Gets the string port name used by CTROS for the service | 19 | * Gets the string port name used by CTROS for the service |
| 24 | * @return Port name of service | 20 | * @return Port name of service |
| 25 | */ | 21 | */ |
| 26 | std::string GetPortName() const override { | 22 | std::string GetPortName() const override { |
| 27 | return "fs:USER"; | 23 | return "am:app"; |
| 28 | } | 24 | } |
| 29 | }; | 25 | }; |
| 30 | 26 | ||
diff --git a/src/core/hle/service/cecd_u.cpp b/src/core/hle/service/cecd_u.cpp new file mode 100644 index 000000000..25d903516 --- /dev/null +++ b/src/core/hle/service/cecd_u.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/cecd_u.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace CECD_U | ||
| 11 | |||
| 12 | namespace CECD_U { | ||
| 13 | |||
| 14 | // Empty arrays are illegal -- commented out until an entry is added. | ||
| 15 | //const Interface::FunctionInfo FunctionTable[] = { }; | ||
| 16 | |||
| 17 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 18 | // Interface class | ||
| 19 | |||
| 20 | Interface::Interface() { | ||
| 21 | //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace | ||
diff --git a/src/core/hle/service/cecd_u.h b/src/core/hle/service/cecd_u.h new file mode 100644 index 000000000..969e1ed1b --- /dev/null +++ b/src/core/hle/service/cecd_u.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace CECD_U | ||
| 11 | |||
| 12 | namespace CECD_U { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "cecd:u"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/service/fs/archive.cpp index 0e3eb4564..caf82d556 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp | |||
| @@ -2,23 +2,37 @@ | |||
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <map> | 5 | #include <memory> |
| 6 | #include <unordered_map> | ||
| 6 | 7 | ||
| 7 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 8 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 9 | #include "common/math_util.h" | 10 | #include "common/math_util.h" |
| 10 | 11 | ||
| 11 | #include "core/file_sys/archive.h" | 12 | #include "core/file_sys/archive_backend.h" |
| 12 | #include "core/file_sys/archive_sdmc.h" | 13 | #include "core/file_sys/archive_sdmc.h" |
| 13 | #include "core/file_sys/directory.h" | 14 | #include "core/file_sys/directory_backend.h" |
| 14 | #include "core/hle/kernel/archive.h" | 15 | #include "core/hle/service/fs/archive.h" |
| 15 | #include "core/hle/kernel/session.h" | 16 | #include "core/hle/kernel/session.h" |
| 16 | #include "core/hle/result.h" | 17 | #include "core/hle/result.h" |
| 17 | 18 | ||
| 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 19 | // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. |
| 19 | // Kernel namespace | 20 | // Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 |
| 21 | namespace std { | ||
| 22 | template <> | ||
| 23 | struct hash<Service::FS::ArchiveIdCode> { | ||
| 24 | typedef Service::FS::ArchiveIdCode argument_type; | ||
| 25 | typedef std::size_t result_type; | ||
| 26 | |||
| 27 | result_type operator()(const argument_type& id_code) const { | ||
| 28 | typedef std::underlying_type<argument_type>::type Type; | ||
| 29 | return std::hash<Type>()(static_cast<Type>(id_code)); | ||
| 30 | } | ||
| 31 | }; | ||
| 32 | } | ||
| 20 | 33 | ||
| 21 | namespace Kernel { | 34 | namespace Service { |
| 35 | namespace FS { | ||
| 22 | 36 | ||
| 23 | // Command to access archive file | 37 | // Command to access archive file |
| 24 | enum class FileCommand : u32 { | 38 | enum class FileCommand : u32 { |
| @@ -43,78 +57,28 @@ enum class DirectoryCommand : u32 { | |||
| 43 | Close = 0x08020000, | 57 | Close = 0x08020000, |
| 44 | }; | 58 | }; |
| 45 | 59 | ||
| 46 | class Archive : public Kernel::Session { | 60 | class Archive { |
| 47 | public: | 61 | public: |
| 48 | std::string GetName() const override { return "Archive: " + name; } | 62 | Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) |
| 49 | 63 | : backend(std::move(backend)), id_code(id_code) { | |
| 50 | std::string name; ///< Name of archive (optional) | 64 | } |
| 51 | FileSys::Archive* backend; ///< Archive backend interface | ||
| 52 | |||
| 53 | ResultVal<bool> SyncRequest() override { | ||
| 54 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 55 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | ||
| 56 | 65 | ||
| 57 | switch (cmd) { | 66 | std::string GetName() const { return "Archive: " + backend->GetName(); } |
| 58 | // Read from archive... | ||
| 59 | case FileCommand::Read: | ||
| 60 | { | ||
| 61 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | ||
| 62 | u32 length = cmd_buff[3]; | ||
| 63 | u32 address = cmd_buff[5]; | ||
| 64 | 67 | ||
| 65 | // Number of bytes read | 68 | ArchiveIdCode id_code; ///< Id code of the archive |
| 66 | cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); | 69 | std::unique_ptr<FileSys::ArchiveBackend> backend; ///< Archive backend interface |
| 67 | break; | ||
| 68 | } | ||
| 69 | // Write to archive... | ||
| 70 | case FileCommand::Write: | ||
| 71 | { | ||
| 72 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | ||
| 73 | u32 length = cmd_buff[3]; | ||
| 74 | u32 flush = cmd_buff[4]; | ||
| 75 | u32 address = cmd_buff[6]; | ||
| 76 | |||
| 77 | // Number of bytes written | ||
| 78 | cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | case FileCommand::GetSize: | ||
| 82 | { | ||
| 83 | u64 filesize = (u64) backend->GetSize(); | ||
| 84 | cmd_buff[2] = (u32) filesize; // Lower word | ||
| 85 | cmd_buff[3] = (u32) (filesize >> 32); // Upper word | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | case FileCommand::SetSize: | ||
| 89 | { | ||
| 90 | backend->SetSize(cmd_buff[1] | ((u64)cmd_buff[2] << 32)); | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | case FileCommand::Close: | ||
| 94 | { | ||
| 95 | LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); | ||
| 96 | CloseArchive(backend->GetIdCode()); | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | // Unknown command... | ||
| 100 | default: | ||
| 101 | { | ||
| 102 | LOG_ERROR(Service_FS, "Unknown command=0x%08X", cmd); | ||
| 103 | cmd_buff[0] = UnimplementedFunction(ErrorModule::FS).raw; | ||
| 104 | return MakeResult<bool>(false); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | cmd_buff[1] = 0; // No error | ||
| 108 | return MakeResult<bool>(false); | ||
| 109 | } | ||
| 110 | }; | 70 | }; |
| 111 | 71 | ||
| 112 | class File : public Kernel::Session { | 72 | class File : public Kernel::Session { |
| 113 | public: | 73 | public: |
| 74 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) | ||
| 75 | : backend(std::move(backend)), path(path) { | ||
| 76 | } | ||
| 77 | |||
| 114 | std::string GetName() const override { return "Path: " + path.DebugStr(); } | 78 | std::string GetName() const override { return "Path: " + path.DebugStr(); } |
| 115 | 79 | ||
| 116 | FileSys::Path path; ///< Path of the file | 80 | FileSys::Path path; ///< Path of the file |
| 117 | std::unique_ptr<FileSys::File> backend; ///< File backend interface | 81 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface |
| 118 | 82 | ||
| 119 | ResultVal<bool> SyncRequest() override { | 83 | ResultVal<bool> SyncRequest() override { |
| 120 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 84 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| @@ -185,10 +149,14 @@ public: | |||
| 185 | 149 | ||
| 186 | class Directory : public Kernel::Session { | 150 | class Directory : public Kernel::Session { |
| 187 | public: | 151 | public: |
| 152 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) | ||
| 153 | : backend(std::move(backend)), path(path) { | ||
| 154 | } | ||
| 155 | |||
| 188 | std::string GetName() const override { return "Directory: " + path.DebugStr(); } | 156 | std::string GetName() const override { return "Directory: " + path.DebugStr(); } |
| 189 | 157 | ||
| 190 | FileSys::Path path; ///< Path of the directory | 158 | FileSys::Path path; ///< Path of the directory |
| 191 | std::unique_ptr<FileSys::Directory> backend; ///< File backend interface | 159 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface |
| 192 | 160 | ||
| 193 | ResultVal<bool> SyncRequest() override { | 161 | ResultVal<bool> SyncRequest() override { |
| 194 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 162 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| @@ -230,105 +198,95 @@ public: | |||
| 230 | 198 | ||
| 231 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 199 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 232 | 200 | ||
| 233 | std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode | 201 | /** |
| 202 | * Map of registered archives, identified by id code. Once an archive is registered here, it is | ||
| 203 | * never removed until the FS service is shut down. | ||
| 204 | */ | ||
| 205 | static std::unordered_map<ArchiveIdCode, std::unique_ptr<Archive>> id_code_map; | ||
| 206 | |||
| 207 | /** | ||
| 208 | * Map of active archive handles. Values are pointers to the archives in `idcode_map`. | ||
| 209 | */ | ||
| 210 | static std::unordered_map<ArchiveHandle, Archive*> handle_map; | ||
| 211 | static ArchiveHandle next_handle; | ||
| 212 | |||
| 213 | static Archive* GetArchive(ArchiveHandle handle) { | ||
| 214 | auto itr = handle_map.find(handle); | ||
| 215 | return (itr == handle_map.end()) ? nullptr : itr->second; | ||
| 216 | } | ||
| 217 | |||
| 218 | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code) { | ||
| 219 | LOG_TRACE(Service_FS, "Opening archive with id code 0x%08X", id_code); | ||
| 234 | 220 | ||
| 235 | ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) { | 221 | auto itr = id_code_map.find(id_code); |
| 236 | auto itr = g_archive_map.find(id_code); | 222 | if (itr == id_code_map.end()) { |
| 237 | if (itr == g_archive_map.end()) { | 223 | // TODO: Verify error against hardware |
| 238 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | 224 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 239 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 225 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 240 | } | 226 | } |
| 241 | 227 | ||
| 242 | return MakeResult<Handle>(itr->second); | 228 | // This should never even happen in the first place with 64-bit handles, |
| 229 | while (handle_map.count(next_handle) != 0) { | ||
| 230 | ++next_handle; | ||
| 231 | } | ||
| 232 | handle_map.emplace(next_handle, itr->second.get()); | ||
| 233 | return MakeResult<ArchiveHandle>(next_handle++); | ||
| 243 | } | 234 | } |
| 244 | 235 | ||
| 245 | ResultCode CloseArchive(FileSys::Archive::IdCode id_code) { | 236 | ResultCode CloseArchive(ArchiveHandle handle) { |
| 246 | auto itr = g_archive_map.find(id_code); | 237 | if (handle_map.erase(handle) == 0) |
| 247 | if (itr == g_archive_map.end()) { | ||
| 248 | LOG_ERROR(Service_FS, "Cannot close archive %d, does not exist!", (int)id_code); | ||
| 249 | return InvalidHandle(ErrorModule::FS); | 238 | return InvalidHandle(ErrorModule::FS); |
| 250 | } | 239 | else |
| 251 | 240 | return RESULT_SUCCESS; | |
| 252 | LOG_TRACE(Service_FS, "Closed archive %d", (int) id_code); | ||
| 253 | return RESULT_SUCCESS; | ||
| 254 | } | 241 | } |
| 255 | 242 | ||
| 256 | /** | 243 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in |
| 257 | * Mounts an archive | 244 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 |
| 258 | * @param archive Pointer to the archive to mount | 245 | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) { |
| 259 | */ | 246 | auto result = id_code_map.emplace(id_code, std::make_unique<Archive>(std::move(backend), id_code)); |
| 260 | ResultCode MountArchive(Archive* archive) { | ||
| 261 | FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); | ||
| 262 | ResultVal<Handle> archive_handle = OpenArchive(id_code); | ||
| 263 | if (archive_handle.Succeeded()) { | ||
| 264 | LOG_ERROR(Service_FS, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); | ||
| 265 | return archive_handle.Code(); | ||
| 266 | } | ||
| 267 | g_archive_map[id_code] = archive->GetHandle(); | ||
| 268 | LOG_TRACE(Service_FS, "Mounted archive %s", archive->GetName().c_str()); | ||
| 269 | return RESULT_SUCCESS; | ||
| 270 | } | ||
| 271 | 247 | ||
| 272 | ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name) { | 248 | bool inserted = result.second; |
| 273 | Archive* archive = new Archive; | 249 | _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); |
| 274 | Handle handle = Kernel::g_object_pool.Create(archive); | ||
| 275 | archive->name = name; | ||
| 276 | archive->backend = backend; | ||
| 277 | 250 | ||
| 278 | ResultCode result = MountArchive(archive); | 251 | auto& archive = result.first->second; |
| 279 | if (result.IsError()) { | 252 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); |
| 280 | return result; | ||
| 281 | } | ||
| 282 | |||
| 283 | return RESULT_SUCCESS; | 253 | return RESULT_SUCCESS; |
| 284 | } | 254 | } |
| 285 | 255 | ||
| 286 | ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { | 256 | ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { |
| 287 | // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create | 257 | Archive* archive = GetArchive(archive_handle); |
| 288 | // the archive file handles at app loading, and then keep them persistent throughout execution. | 258 | if (archive == nullptr) |
| 289 | // Archives file handles are just reused and not actually freed until emulation shut down. | ||
| 290 | // Verify if real hardware works this way, or if new handles are created each time | ||
| 291 | if (path.GetType() == FileSys::Binary) | ||
| 292 | // TODO(bunnei): FixMe - this is a hack to compensate for an incorrect FileSys backend | ||
| 293 | // design. While the functionally of this is OK, our implementation decision to separate | ||
| 294 | // normal files from archive file pointers is very likely wrong. | ||
| 295 | // See https://github.com/citra-emu/citra/issues/205 | ||
| 296 | return MakeResult<Handle>(archive_handle); | ||
| 297 | |||
| 298 | File* file = new File; | ||
| 299 | Handle handle = Kernel::g_object_pool.Create(file); | ||
| 300 | |||
| 301 | Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); | ||
| 302 | if (archive == nullptr) { | ||
| 303 | return InvalidHandle(ErrorModule::FS); | 259 | return InvalidHandle(ErrorModule::FS); |
| 304 | } | ||
| 305 | file->path = path; | ||
| 306 | file->backend = archive->backend->OpenFile(path, mode); | ||
| 307 | 260 | ||
| 308 | if (!file->backend) { | 261 | std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); |
| 262 | if (backend == nullptr) { | ||
| 309 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | 263 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 310 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 264 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 311 | } | 265 | } |
| 312 | 266 | ||
| 267 | auto file = std::make_unique<File>(std::move(backend), path); | ||
| 268 | Handle handle = Kernel::g_object_pool.Create(file.release()); | ||
| 313 | return MakeResult<Handle>(handle); | 269 | return MakeResult<Handle>(handle); |
| 314 | } | 270 | } |
| 315 | 271 | ||
| 316 | ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) { | 272 | ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 317 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 273 | Archive* archive = GetArchive(archive_handle); |
| 318 | if (archive == nullptr) | 274 | if (archive == nullptr) |
| 319 | return InvalidHandle(ErrorModule::FS); | 275 | return InvalidHandle(ErrorModule::FS); |
| 276 | |||
| 320 | if (archive->backend->DeleteFile(path)) | 277 | if (archive->backend->DeleteFile(path)) |
| 321 | return RESULT_SUCCESS; | 278 | return RESULT_SUCCESS; |
| 322 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 279 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 323 | ErrorSummary::Canceled, ErrorLevel::Status); | 280 | ErrorSummary::Canceled, ErrorLevel::Status); |
| 324 | } | 281 | } |
| 325 | 282 | ||
| 326 | ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, | 283 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, |
| 327 | Handle dest_archive_handle, const FileSys::Path& dest_path) { | 284 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { |
| 328 | Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle); | 285 | Archive* src_archive = GetArchive(src_archive_handle); |
| 329 | Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle); | 286 | Archive* dest_archive = GetArchive(dest_archive_handle); |
| 330 | if (src_archive == nullptr || dest_archive == nullptr) | 287 | if (src_archive == nullptr || dest_archive == nullptr) |
| 331 | return InvalidHandle(ErrorModule::FS); | 288 | return InvalidHandle(ErrorModule::FS); |
| 289 | |||
| 332 | if (src_archive == dest_archive) { | 290 | if (src_archive == dest_archive) { |
| 333 | if (src_archive->backend->RenameFile(src_path, dest_path)) | 291 | if (src_archive->backend->RenameFile(src_path, dest_path)) |
| 334 | return RESULT_SUCCESS; | 292 | return RESULT_SUCCESS; |
| @@ -336,36 +294,42 @@ ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::P | |||
| 336 | // TODO: Implement renaming across archives | 294 | // TODO: Implement renaming across archives |
| 337 | return UnimplementedFunction(ErrorModule::FS); | 295 | return UnimplementedFunction(ErrorModule::FS); |
| 338 | } | 296 | } |
| 297 | |||
| 298 | // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't | ||
| 299 | // exist or similar. Verify. | ||
| 339 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 300 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 340 | ErrorSummary::NothingHappened, ErrorLevel::Status); | 301 | ErrorSummary::NothingHappened, ErrorLevel::Status); |
| 341 | } | 302 | } |
| 342 | 303 | ||
| 343 | ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | 304 | ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 344 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 305 | Archive* archive = GetArchive(archive_handle); |
| 345 | if (archive == nullptr) | 306 | if (archive == nullptr) |
| 346 | return InvalidHandle(ErrorModule::FS); | 307 | return InvalidHandle(ErrorModule::FS); |
| 308 | |||
| 347 | if (archive->backend->DeleteDirectory(path)) | 309 | if (archive->backend->DeleteDirectory(path)) |
| 348 | return RESULT_SUCCESS; | 310 | return RESULT_SUCCESS; |
| 349 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 311 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 350 | ErrorSummary::Canceled, ErrorLevel::Status); | 312 | ErrorSummary::Canceled, ErrorLevel::Status); |
| 351 | } | 313 | } |
| 352 | 314 | ||
| 353 | ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | 315 | ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 354 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 316 | Archive* archive = GetArchive(archive_handle); |
| 355 | if (archive == nullptr) | 317 | if (archive == nullptr) |
| 356 | return InvalidHandle(ErrorModule::FS); | 318 | return InvalidHandle(ErrorModule::FS); |
| 319 | |||
| 357 | if (archive->backend->CreateDirectory(path)) | 320 | if (archive->backend->CreateDirectory(path)) |
| 358 | return RESULT_SUCCESS; | 321 | return RESULT_SUCCESS; |
| 359 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 322 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 360 | ErrorSummary::Canceled, ErrorLevel::Status); | 323 | ErrorSummary::Canceled, ErrorLevel::Status); |
| 361 | } | 324 | } |
| 362 | 325 | ||
| 363 | ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, | 326 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, |
| 364 | Handle dest_archive_handle, const FileSys::Path& dest_path) { | 327 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { |
| 365 | Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle); | 328 | Archive* src_archive = GetArchive(src_archive_handle); |
| 366 | Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle); | 329 | Archive* dest_archive = GetArchive(dest_archive_handle); |
| 367 | if (src_archive == nullptr || dest_archive == nullptr) | 330 | if (src_archive == nullptr || dest_archive == nullptr) |
| 368 | return InvalidHandle(ErrorModule::FS); | 331 | return InvalidHandle(ErrorModule::FS); |
| 332 | |||
| 369 | if (src_archive == dest_archive) { | 333 | if (src_archive == dest_archive) { |
| 370 | if (src_archive->backend->RenameDirectory(src_path, dest_path)) | 334 | if (src_archive->backend->RenameDirectory(src_path, dest_path)) |
| 371 | return RESULT_SUCCESS; | 335 | return RESULT_SUCCESS; |
| @@ -373,6 +337,9 @@ ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileS | |||
| 373 | // TODO: Implement renaming across archives | 337 | // TODO: Implement renaming across archives |
| 374 | return UnimplementedFunction(ErrorModule::FS); | 338 | return UnimplementedFunction(ErrorModule::FS); |
| 375 | } | 339 | } |
| 340 | |||
| 341 | // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't | ||
| 342 | // exist or similar. Verify. | ||
| 376 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 343 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 377 | ErrorSummary::NothingHappened, ErrorLevel::Status); | 344 | ErrorSummary::NothingHappened, ErrorLevel::Status); |
| 378 | } | 345 | } |
| @@ -383,44 +350,43 @@ ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileS | |||
| 383 | * @param path Path to the Directory inside of the Archive | 350 | * @param path Path to the Directory inside of the Archive |
| 384 | * @return Opened Directory object | 351 | * @return Opened Directory object |
| 385 | */ | 352 | */ |
| 386 | ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | 353 | ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 387 | Directory* directory = new Directory; | 354 | Archive* archive = GetArchive(archive_handle); |
| 388 | Handle handle = Kernel::g_object_pool.Create(directory); | 355 | if (archive == nullptr) |
| 389 | |||
| 390 | Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); | ||
| 391 | if (archive == nullptr) { | ||
| 392 | return InvalidHandle(ErrorModule::FS); | 356 | return InvalidHandle(ErrorModule::FS); |
| 393 | } | ||
| 394 | directory->path = path; | ||
| 395 | directory->backend = archive->backend->OpenDirectory(path); | ||
| 396 | 357 | ||
| 397 | if (!directory->backend) { | 358 | std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path); |
| 359 | if (backend == nullptr) { | ||
| 398 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | 360 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 399 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 361 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 400 | } | 362 | } |
| 401 | 363 | ||
| 364 | auto directory = std::make_unique<Directory>(std::move(backend), path); | ||
| 365 | Handle handle = Kernel::g_object_pool.Create(directory.release()); | ||
| 402 | return MakeResult<Handle>(handle); | 366 | return MakeResult<Handle>(handle); |
| 403 | } | 367 | } |
| 404 | 368 | ||
| 405 | /// Initialize archives | 369 | /// Initialize archives |
| 406 | void ArchiveInit() { | 370 | void ArchiveInit() { |
| 407 | g_archive_map.clear(); | 371 | next_handle = 1; |
| 408 | 372 | ||
| 409 | // TODO(Link Mauve): Add the other archive types (see here for the known types: | 373 | // TODO(Link Mauve): Add the other archive types (see here for the known types: |
| 410 | // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes). Currently the only half-finished | 374 | // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes). Currently the only half-finished |
| 411 | // archive type is SDMC, so it is the only one getting exposed. | 375 | // archive type is SDMC, so it is the only one getting exposed. |
| 412 | 376 | ||
| 413 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); | 377 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); |
| 414 | auto archive = new FileSys::Archive_SDMC(sdmc_directory); | 378 | auto archive = std::make_unique<FileSys::Archive_SDMC>(sdmc_directory); |
| 415 | if (archive->Initialize()) | 379 | if (archive->Initialize()) |
| 416 | CreateArchive(archive, "SDMC"); | 380 | CreateArchive(std::move(archive), ArchiveIdCode::SDMC); |
| 417 | else | 381 | else |
| 418 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | 382 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); |
| 419 | } | 383 | } |
| 420 | 384 | ||
| 421 | /// Shutdown archives | 385 | /// Shutdown archives |
| 422 | void ArchiveShutdown() { | 386 | void ArchiveShutdown() { |
| 423 | g_archive_map.clear(); | 387 | handle_map.clear(); |
| 388 | id_code_map.clear(); | ||
| 424 | } | 389 | } |
| 425 | 390 | ||
| 426 | } // namespace Kernel | 391 | } // namespace FS |
| 392 | } // namespace Service | ||
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/service/fs/archive.h index b50833a2b..a38de92e3 100644 --- a/src/core/hle/kernel/archive.h +++ b/src/core/hle/service/fs/archive.h | |||
| @@ -6,34 +6,45 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/file_sys/archive.h" | 9 | #include "core/file_sys/archive_backend.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/result.h" | 11 | #include "core/hle/result.h" |
| 12 | 12 | ||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 13 | namespace Service { |
| 14 | // Kernel namespace | 14 | namespace FS { |
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | /// Supported archive types |
| 17 | enum class ArchiveIdCode : u32 { | ||
| 18 | RomFS = 0x00000003, | ||
| 19 | SaveData = 0x00000004, | ||
| 20 | ExtSaveData = 0x00000006, | ||
| 21 | SharedExtSaveData = 0x00000007, | ||
| 22 | SystemSaveData = 0x00000008, | ||
| 23 | SDMC = 0x00000009, | ||
| 24 | SDMCWriteOnly = 0x0000000A, | ||
| 25 | }; | ||
| 26 | |||
| 27 | typedef u64 ArchiveHandle; | ||
| 17 | 28 | ||
| 18 | /** | 29 | /** |
| 19 | * Opens an archive | 30 | * Opens an archive |
| 20 | * @param id_code IdCode of the archive to open | 31 | * @param id_code IdCode of the archive to open |
| 21 | * @return Handle to the opened archive | 32 | * @return Handle to the opened archive |
| 22 | */ | 33 | */ |
| 23 | ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code); | 34 | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code); |
| 24 | 35 | ||
| 25 | /** | 36 | /** |
| 26 | * Closes an archive | 37 | * Closes an archive |
| 27 | * @param id_code IdCode of the archive to open | 38 | * @param id_code IdCode of the archive to open |
| 28 | */ | 39 | */ |
| 29 | ResultCode CloseArchive(FileSys::Archive::IdCode id_code); | 40 | ResultCode CloseArchive(ArchiveHandle handle); |
| 30 | 41 | ||
| 31 | /** | 42 | /** |
| 32 | * Creates an Archive | 43 | * Creates an Archive |
| 33 | * @param backend File system backend interface to the archive | 44 | * @param backend File system backend interface to the archive |
| 34 | * @param name Name of Archive | 45 | * @param id_code Id code used to access this type of archive |
| 35 | */ | 46 | */ |
| 36 | ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name); | 47 | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code); |
| 37 | 48 | ||
| 38 | /** | 49 | /** |
| 39 | * Open a File from an Archive | 50 | * Open a File from an Archive |
| @@ -42,7 +53,7 @@ ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name); | |||
| 42 | * @param mode Mode under which to open the File | 53 | * @param mode Mode under which to open the File |
| 43 | * @return Handle to the opened File object | 54 | * @return Handle to the opened File object |
| 44 | */ | 55 | */ |
| 45 | ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); | 56 | ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); |
| 46 | 57 | ||
| 47 | /** | 58 | /** |
| 48 | * Delete a File from an Archive | 59 | * Delete a File from an Archive |
| @@ -50,7 +61,7 @@ ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path | |||
| 50 | * @param path Path to the File inside of the Archive | 61 | * @param path Path to the File inside of the Archive |
| 51 | * @return Whether deletion succeeded | 62 | * @return Whether deletion succeeded |
| 52 | */ | 63 | */ |
| 53 | ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path); | 64 | ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); |
| 54 | 65 | ||
| 55 | /** | 66 | /** |
| 56 | * Rename a File between two Archives | 67 | * Rename a File between two Archives |
| @@ -60,8 +71,8 @@ ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& pat | |||
| 60 | * @param dest_path Path to the File inside of the destination Archive | 71 | * @param dest_path Path to the File inside of the destination Archive |
| 61 | * @return Whether rename succeeded | 72 | * @return Whether rename succeeded |
| 62 | */ | 73 | */ |
| 63 | ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, | 74 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, |
| 64 | Handle dest_archive_handle, const FileSys::Path& dest_path); | 75 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); |
| 65 | 76 | ||
| 66 | /** | 77 | /** |
| 67 | * Delete a Directory from an Archive | 78 | * Delete a Directory from an Archive |
| @@ -69,7 +80,7 @@ ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::P | |||
| 69 | * @param path Path to the Directory inside of the Archive | 80 | * @param path Path to the Directory inside of the Archive |
| 70 | * @return Whether deletion succeeded | 81 | * @return Whether deletion succeeded |
| 71 | */ | 82 | */ |
| 72 | ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); | 83 | ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); |
| 73 | 84 | ||
| 74 | /** | 85 | /** |
| 75 | * Create a Directory from an Archive | 86 | * Create a Directory from an Archive |
| @@ -77,7 +88,7 @@ ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path | |||
| 77 | * @param path Path to the Directory inside of the Archive | 88 | * @param path Path to the Directory inside of the Archive |
| 78 | * @return Whether creation of directory succeeded | 89 | * @return Whether creation of directory succeeded |
| 79 | */ | 90 | */ |
| 80 | ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); | 91 | ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); |
| 81 | 92 | ||
| 82 | /** | 93 | /** |
| 83 | * Rename a Directory between two Archives | 94 | * Rename a Directory between two Archives |
| @@ -87,8 +98,8 @@ ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path | |||
| 87 | * @param dest_path Path to the Directory inside of the destination Archive | 98 | * @param dest_path Path to the Directory inside of the destination Archive |
| 88 | * @return Whether rename succeeded | 99 | * @return Whether rename succeeded |
| 89 | */ | 100 | */ |
| 90 | ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, | 101 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, |
| 91 | Handle dest_archive_handle, const FileSys::Path& dest_path); | 102 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); |
| 92 | 103 | ||
| 93 | /** | 104 | /** |
| 94 | * Open a Directory from an Archive | 105 | * Open a Directory from an Archive |
| @@ -96,7 +107,7 @@ ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileS | |||
| 96 | * @param path Path to the Directory inside of the Archive | 107 | * @param path Path to the Directory inside of the Archive |
| 97 | * @return Handle to the opened File object | 108 | * @return Handle to the opened File object |
| 98 | */ | 109 | */ |
| 99 | ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); | 110 | ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); |
| 100 | 111 | ||
| 101 | /// Initialize archives | 112 | /// Initialize archives |
| 102 | void ArchiveInit(); | 113 | void ArchiveInit(); |
| @@ -104,4 +115,5 @@ void ArchiveInit(); | |||
| 104 | /// Shutdown archives | 115 | /// Shutdown archives |
| 105 | void ArchiveShutdown(); | 116 | void ArchiveShutdown(); |
| 106 | 117 | ||
| 107 | } // namespace FileSys | 118 | } // namespace FS |
| 119 | } // namespace Service | ||
diff --git a/src/core/hle/service/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 672ba2475..0f75d5e3a 100644 --- a/src/core/hle/service/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp | |||
| @@ -3,18 +3,23 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common.h" | 5 | #include "common/common.h" |
| 6 | #include "common/scope_exit.h" | ||
| 6 | 7 | ||
| 7 | #include "common/string_util.h" | 8 | #include "common/string_util.h" |
| 8 | #include "core/hle/kernel/archive.h" | 9 | #include "core/hle/service/fs/archive.h" |
| 9 | #include "core/hle/kernel/archive.h" | ||
| 10 | #include "core/hle/result.h" | 10 | #include "core/hle/result.h" |
| 11 | #include "core/hle/service/fs_user.h" | 11 | #include "core/hle/service/fs/fs_user.h" |
| 12 | #include "core/settings.h" | 12 | #include "core/settings.h" |
| 13 | 13 | ||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 15 | // Namespace FS_User | 15 | // Namespace FS_User |
| 16 | 16 | ||
| 17 | namespace FS_User { | 17 | namespace Service { |
| 18 | namespace FS { | ||
| 19 | |||
| 20 | static ArchiveHandle MakeArchiveHandle(u32 low_word, u32 high_word) { | ||
| 21 | return (u64)low_word | ((u64)high_word << 32); | ||
| 22 | } | ||
| 18 | 23 | ||
| 19 | static void Initialize(Service::Interface* self) { | 24 | static void Initialize(Service::Interface* self) { |
| 20 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 25 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| @@ -57,11 +62,12 @@ static void OpenFile(Service::Interface* self) { | |||
| 57 | 62 | ||
| 58 | LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); | 63 | LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); |
| 59 | 64 | ||
| 60 | ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode); | 65 | ResultVal<Handle> handle = OpenFileFromArchive(archive_handle, file_path, mode); |
| 61 | cmd_buff[1] = handle.Code().raw; | 66 | cmd_buff[1] = handle.Code().raw; |
| 62 | if (handle.Succeeded()) { | 67 | if (handle.Succeeded()) { |
| 63 | cmd_buff[3] = *handle; | 68 | cmd_buff[3] = *handle; |
| 64 | } else { | 69 | } else { |
| 70 | cmd_buff[3] = 0; | ||
| 65 | LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); | 71 | LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |
| 66 | } | 72 | } |
| 67 | } | 73 | } |
| @@ -88,7 +94,7 @@ static void OpenFile(Service::Interface* self) { | |||
| 88 | static void OpenFileDirectly(Service::Interface* self) { | 94 | static void OpenFileDirectly(Service::Interface* self) { |
| 89 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 95 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 90 | 96 | ||
| 91 | auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); | 97 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]); |
| 92 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); | 98 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); |
| 93 | u32 archivename_size = cmd_buff[4]; | 99 | u32 archivename_size = cmd_buff[4]; |
| 94 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); | 100 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); |
| @@ -106,25 +112,25 @@ static void OpenFileDirectly(Service::Interface* self) { | |||
| 106 | if (archive_path.GetType() != FileSys::Empty) { | 112 | if (archive_path.GetType() != FileSys::Empty) { |
| 107 | LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported"); | 113 | LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported"); |
| 108 | cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; | 114 | cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; |
| 115 | cmd_buff[3] = 0; | ||
| 109 | return; | 116 | return; |
| 110 | } | 117 | } |
| 111 | 118 | ||
| 112 | // TODO(Link Mauve): Check if we should even get a handle for the archive, and don't leak it | 119 | ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id); |
| 113 | // TODO(yuriks): Why is there all this duplicate (and seemingly useless) code up here? | ||
| 114 | ResultVal<Handle> archive_handle = Kernel::OpenArchive(archive_id); | ||
| 115 | cmd_buff[1] = archive_handle.Code().raw; | ||
| 116 | if (archive_handle.Failed()) { | 120 | if (archive_handle.Failed()) { |
| 117 | LOG_ERROR(Service_FS, "failed to get a handle for archive"); | 121 | LOG_ERROR(Service_FS, "failed to get a handle for archive"); |
| 122 | cmd_buff[1] = archive_handle.Code().raw; | ||
| 123 | cmd_buff[3] = 0; | ||
| 118 | return; | 124 | return; |
| 119 | } | 125 | } |
| 120 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | 126 | SCOPE_EXIT({ CloseArchive(*archive_handle); }); |
| 121 | cmd_buff[3] = *archive_handle; | ||
| 122 | 127 | ||
| 123 | ResultVal<Handle> handle = Kernel::OpenFileFromArchive(*archive_handle, file_path, mode); | 128 | ResultVal<Handle> handle = OpenFileFromArchive(*archive_handle, file_path, mode); |
| 124 | cmd_buff[1] = handle.Code().raw; | 129 | cmd_buff[1] = handle.Code().raw; |
| 125 | if (handle.Succeeded()) { | 130 | if (handle.Succeeded()) { |
| 126 | cmd_buff[3] = *handle; | 131 | cmd_buff[3] = *handle; |
| 127 | } else { | 132 | } else { |
| 133 | cmd_buff[3] = 0; | ||
| 128 | LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); | 134 | LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); |
| 129 | } | 135 | } |
| 130 | } | 136 | } |
| @@ -140,12 +146,10 @@ static void OpenFileDirectly(Service::Interface* self) { | |||
| 140 | * Outputs: | 146 | * Outputs: |
| 141 | * 1 : Result of function, 0 on success, otherwise error code | 147 | * 1 : Result of function, 0 on success, otherwise error code |
| 142 | */ | 148 | */ |
| 143 | void DeleteFile(Service::Interface* self) { | 149 | static void DeleteFile(Service::Interface* self) { |
| 144 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 150 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 145 | 151 | ||
| 146 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | 152 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 147 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 148 | Handle archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 149 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 153 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 150 | u32 filename_size = cmd_buff[5]; | 154 | u32 filename_size = cmd_buff[5]; |
| 151 | u32 filename_ptr = cmd_buff[7]; | 155 | u32 filename_ptr = cmd_buff[7]; |
| @@ -155,7 +159,7 @@ void DeleteFile(Service::Interface* self) { | |||
| 155 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", | 159 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", |
| 156 | filename_type, filename_size, file_path.DebugStr().c_str()); | 160 | filename_type, filename_size, file_path.DebugStr().c_str()); |
| 157 | 161 | ||
| 158 | cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path).raw; | 162 | cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw; |
| 159 | } | 163 | } |
| 160 | 164 | ||
| 161 | /* | 165 | /* |
| @@ -174,15 +178,13 @@ void DeleteFile(Service::Interface* self) { | |||
| 174 | * Outputs: | 178 | * Outputs: |
| 175 | * 1 : Result of function, 0 on success, otherwise error code | 179 | * 1 : Result of function, 0 on success, otherwise error code |
| 176 | */ | 180 | */ |
| 177 | void RenameFile(Service::Interface* self) { | 181 | static void RenameFile(Service::Interface* self) { |
| 178 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 182 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 179 | 183 | ||
| 180 | // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to | 184 | ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 181 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 182 | Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 183 | auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 185 | auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 184 | u32 src_filename_size = cmd_buff[5]; | 186 | u32 src_filename_size = cmd_buff[5]; |
| 185 | Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]); | 187 | ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);; |
| 186 | auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); | 188 | auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); |
| 187 | u32 dest_filename_size = cmd_buff[9]; | 189 | u32 dest_filename_size = cmd_buff[9]; |
| 188 | u32 src_filename_ptr = cmd_buff[11]; | 190 | u32 src_filename_ptr = cmd_buff[11]; |
| @@ -195,7 +197,7 @@ void RenameFile(Service::Interface* self) { | |||
| 195 | src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), | 197 | src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), |
| 196 | dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); | 198 | dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); |
| 197 | 199 | ||
| 198 | cmd_buff[1] = Kernel::RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; | 200 | cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; |
| 199 | } | 201 | } |
| 200 | 202 | ||
| 201 | /* | 203 | /* |
| @@ -209,12 +211,10 @@ void RenameFile(Service::Interface* self) { | |||
| 209 | * Outputs: | 211 | * Outputs: |
| 210 | * 1 : Result of function, 0 on success, otherwise error code | 212 | * 1 : Result of function, 0 on success, otherwise error code |
| 211 | */ | 213 | */ |
| 212 | void DeleteDirectory(Service::Interface* self) { | 214 | static void DeleteDirectory(Service::Interface* self) { |
| 213 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 215 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 214 | 216 | ||
| 215 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | 217 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 216 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 217 | Handle archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 218 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 218 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 219 | u32 dirname_size = cmd_buff[5]; | 219 | u32 dirname_size = cmd_buff[5]; |
| 220 | u32 dirname_ptr = cmd_buff[7]; | 220 | u32 dirname_ptr = cmd_buff[7]; |
| @@ -224,7 +224,7 @@ void DeleteDirectory(Service::Interface* self) { | |||
| 224 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", | 224 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", |
| 225 | dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 225 | dirname_type, dirname_size, dir_path.DebugStr().c_str()); |
| 226 | 226 | ||
| 227 | cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path).raw; | 227 | cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | /* | 230 | /* |
| @@ -241,9 +241,7 @@ void DeleteDirectory(Service::Interface* self) { | |||
| 241 | static void CreateDirectory(Service::Interface* self) { | 241 | static void CreateDirectory(Service::Interface* self) { |
| 242 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 242 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 243 | 243 | ||
| 244 | // TODO: cmd_buff[2], aka archive handle lower word, isn't used according to | 244 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 245 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 246 | Handle archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 247 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 245 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 248 | u32 dirname_size = cmd_buff[5]; | 246 | u32 dirname_size = cmd_buff[5]; |
| 249 | u32 dirname_ptr = cmd_buff[8]; | 247 | u32 dirname_ptr = cmd_buff[8]; |
| @@ -252,7 +250,7 @@ static void CreateDirectory(Service::Interface* self) { | |||
| 252 | 250 | ||
| 253 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 251 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); |
| 254 | 252 | ||
| 255 | cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path).raw; | 253 | cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw; |
| 256 | } | 254 | } |
| 257 | 255 | ||
| 258 | /* | 256 | /* |
| @@ -271,15 +269,13 @@ static void CreateDirectory(Service::Interface* self) { | |||
| 271 | * Outputs: | 269 | * Outputs: |
| 272 | * 1 : Result of function, 0 on success, otherwise error code | 270 | * 1 : Result of function, 0 on success, otherwise error code |
| 273 | */ | 271 | */ |
| 274 | void RenameDirectory(Service::Interface* self) { | 272 | static void RenameDirectory(Service::Interface* self) { |
| 275 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 273 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 276 | 274 | ||
| 277 | // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to | 275 | ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 278 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 279 | Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 280 | auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 276 | auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 281 | u32 src_dirname_size = cmd_buff[5]; | 277 | u32 src_dirname_size = cmd_buff[5]; |
| 282 | Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]); | 278 | ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]); |
| 283 | auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); | 279 | auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); |
| 284 | u32 dest_dirname_size = cmd_buff[9]; | 280 | u32 dest_dirname_size = cmd_buff[9]; |
| 285 | u32 src_dirname_ptr = cmd_buff[11]; | 281 | u32 src_dirname_ptr = cmd_buff[11]; |
| @@ -292,15 +288,26 @@ void RenameDirectory(Service::Interface* self) { | |||
| 292 | src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), | 288 | src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), |
| 293 | dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); | 289 | dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); |
| 294 | 290 | ||
| 295 | cmd_buff[1] = Kernel::RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; | 291 | cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; |
| 296 | } | 292 | } |
| 297 | 293 | ||
| 294 | /** | ||
| 295 | * FS_User::OpenDirectory service function | ||
| 296 | * Inputs: | ||
| 297 | * 1 : Archive handle low word | ||
| 298 | * 2 : Archive handle high word | ||
| 299 | * 3 : Low path type | ||
| 300 | * 4 : Low path size | ||
| 301 | * 7 : (LowPathSize << 14) | 2 | ||
| 302 | * 8 : Low path data pointer | ||
| 303 | * Outputs: | ||
| 304 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 305 | * 3 : Directory handle | ||
| 306 | */ | ||
| 298 | static void OpenDirectory(Service::Interface* self) { | 307 | static void OpenDirectory(Service::Interface* self) { |
| 299 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 308 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 300 | 309 | ||
| 301 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | 310 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[1], cmd_buff[2]); |
| 302 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 303 | Handle archive_handle = static_cast<Handle>(cmd_buff[2]); | ||
| 304 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); | 311 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); |
| 305 | u32 dirname_size = cmd_buff[4]; | 312 | u32 dirname_size = cmd_buff[4]; |
| 306 | u32 dirname_ptr = cmd_buff[6]; | 313 | u32 dirname_ptr = cmd_buff[6]; |
| @@ -309,7 +316,7 @@ static void OpenDirectory(Service::Interface* self) { | |||
| 309 | 316 | ||
| 310 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 317 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); |
| 311 | 318 | ||
| 312 | ResultVal<Handle> handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_path); | 319 | ResultVal<Handle> handle = OpenDirectoryFromArchive(archive_handle, dir_path); |
| 313 | cmd_buff[1] = handle.Code().raw; | 320 | cmd_buff[1] = handle.Code().raw; |
| 314 | if (handle.Succeeded()) { | 321 | if (handle.Succeeded()) { |
| 315 | cmd_buff[3] = *handle; | 322 | cmd_buff[3] = *handle; |
| @@ -334,7 +341,7 @@ static void OpenDirectory(Service::Interface* self) { | |||
| 334 | static void OpenArchive(Service::Interface* self) { | 341 | static void OpenArchive(Service::Interface* self) { |
| 335 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 342 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 336 | 343 | ||
| 337 | auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); | 344 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); |
| 338 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); | 345 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); |
| 339 | u32 archivename_size = cmd_buff[3]; | 346 | u32 archivename_size = cmd_buff[3]; |
| 340 | u32 archivename_ptr = cmd_buff[5]; | 347 | u32 archivename_ptr = cmd_buff[5]; |
| @@ -348,16 +355,34 @@ static void OpenArchive(Service::Interface* self) { | |||
| 348 | return; | 355 | return; |
| 349 | } | 356 | } |
| 350 | 357 | ||
| 351 | ResultVal<Handle> handle = Kernel::OpenArchive(archive_id); | 358 | ResultVal<ArchiveHandle> handle = OpenArchive(archive_id); |
| 352 | cmd_buff[1] = handle.Code().raw; | 359 | cmd_buff[1] = handle.Code().raw; |
| 353 | if (handle.Succeeded()) { | 360 | if (handle.Succeeded()) { |
| 354 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | 361 | cmd_buff[2] = *handle & 0xFFFFFFFF; |
| 355 | cmd_buff[3] = *handle; | 362 | cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF; |
| 356 | } else { | 363 | } else { |
| 364 | cmd_buff[2] = cmd_buff[3] = 0; | ||
| 357 | LOG_ERROR(Service_FS, "failed to get a handle for archive"); | 365 | LOG_ERROR(Service_FS, "failed to get a handle for archive"); |
| 358 | } | 366 | } |
| 359 | } | 367 | } |
| 360 | 368 | ||
| 369 | /** | ||
| 370 | * FS_User::CloseArchive service function | ||
| 371 | * Inputs: | ||
| 372 | * 0 : 0x080E0080 | ||
| 373 | * 1 : Archive handle low word | ||
| 374 | * 2 : Archive handle high word | ||
| 375 | * Outputs: | ||
| 376 | * 0 : ??? TODO(yuriks): Verify return header | ||
| 377 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 378 | */ | ||
| 379 | static void CloseArchive(Service::Interface* self) { | ||
| 380 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 381 | |||
| 382 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[1], cmd_buff[2]); | ||
| 383 | cmd_buff[1] = CloseArchive(archive_handle).raw; | ||
| 384 | } | ||
| 385 | |||
| 361 | /* | 386 | /* |
| 362 | * FS_User::IsSdmcDetected service function | 387 | * FS_User::IsSdmcDetected service function |
| 363 | * Outputs: | 388 | * Outputs: |
| @@ -373,7 +398,7 @@ static void IsSdmcDetected(Service::Interface* self) { | |||
| 373 | LOG_DEBUG(Service_FS, "called"); | 398 | LOG_DEBUG(Service_FS, "called"); |
| 374 | } | 399 | } |
| 375 | 400 | ||
| 376 | const Interface::FunctionInfo FunctionTable[] = { | 401 | const FSUserInterface::FunctionInfo FunctionTable[] = { |
| 377 | {0x000100C6, nullptr, "Dummy1"}, | 402 | {0x000100C6, nullptr, "Dummy1"}, |
| 378 | {0x040100C4, nullptr, "Control"}, | 403 | {0x040100C4, nullptr, "Control"}, |
| 379 | {0x08010002, Initialize, "Initialize"}, | 404 | {0x08010002, Initialize, "Initialize"}, |
| @@ -389,7 +414,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 389 | {0x080B0102, OpenDirectory, "OpenDirectory"}, | 414 | {0x080B0102, OpenDirectory, "OpenDirectory"}, |
| 390 | {0x080C00C2, OpenArchive, "OpenArchive"}, | 415 | {0x080C00C2, OpenArchive, "OpenArchive"}, |
| 391 | {0x080D0144, nullptr, "ControlArchive"}, | 416 | {0x080D0144, nullptr, "ControlArchive"}, |
| 392 | {0x080E0080, nullptr, "CloseArchive"}, | 417 | {0x080E0080, CloseArchive, "CloseArchive"}, |
| 393 | {0x080F0180, nullptr, "FormatThisUserSaveData"}, | 418 | {0x080F0180, nullptr, "FormatThisUserSaveData"}, |
| 394 | {0x08100200, nullptr, "CreateSystemSaveData"}, | 419 | {0x08100200, nullptr, "CreateSystemSaveData"}, |
| 395 | {0x08110040, nullptr, "DeleteSystemSaveData"}, | 420 | {0x08110040, nullptr, "DeleteSystemSaveData"}, |
| @@ -465,11 +490,12 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 465 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 490 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 466 | // Interface class | 491 | // Interface class |
| 467 | 492 | ||
| 468 | Interface::Interface() { | 493 | FSUserInterface::FSUserInterface() { |
| 469 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | 494 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); |
| 470 | } | 495 | } |
| 471 | 496 | ||
| 472 | Interface::~Interface() { | 497 | FSUserInterface::~FSUserInterface() { |
| 473 | } | 498 | } |
| 474 | 499 | ||
| 475 | } // namespace | 500 | } // namespace FS |
| 501 | } // namespace Service | ||
diff --git a/src/core/hle/service/fs/fs_user.h b/src/core/hle/service/fs/fs_user.h new file mode 100644 index 000000000..80e3804e0 --- /dev/null +++ b/src/core/hle/service/fs/fs_user.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace FS_User | ||
| 11 | |||
| 12 | namespace Service { | ||
| 13 | namespace FS { | ||
| 14 | |||
| 15 | /// Interface to "fs:USER" service | ||
| 16 | class FSUserInterface : public Service::Interface { | ||
| 17 | public: | ||
| 18 | |||
| 19 | FSUserInterface(); | ||
| 20 | |||
| 21 | ~FSUserInterface(); | ||
| 22 | |||
| 23 | /** | ||
| 24 | * Gets the string port name used by CTROS for the service | ||
| 25 | * @return Port name of service | ||
| 26 | */ | ||
| 27 | std::string GetPortName() const override { | ||
| 28 | return "fs:USER"; | ||
| 29 | } | ||
| 30 | }; | ||
| 31 | |||
| 32 | } // namespace FS | ||
| 33 | } // namespace Service | ||
diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp new file mode 100644 index 000000000..91b1a6fc5 --- /dev/null +++ b/src/core/hle/service/ldr_ro.cpp | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/ldr_ro.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace LDR_RO | ||
| 11 | |||
| 12 | namespace LDR_RO { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x000100C2, nullptr, "Initialize"}, | ||
| 16 | {0x00020082, nullptr, "CRR_Load"}, | ||
| 17 | {0x00030042, nullptr, "CRR_Unload"}, | ||
| 18 | {0x000402C2, nullptr, "CRO_LoadAndFix"}, | ||
| 19 | {0x000500C2, nullptr, "CRO_ApplyRelocationPatchesAndLink"} | ||
| 20 | }; | ||
| 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 22 | // Interface class | ||
| 23 | |||
| 24 | Interface::Interface() { | ||
| 25 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 26 | } | ||
| 27 | |||
| 28 | } // namespace | ||
diff --git a/src/core/hle/service/ldr_ro.h b/src/core/hle/service/ldr_ro.h new file mode 100644 index 000000000..32d7c29cf --- /dev/null +++ b/src/core/hle/service/ldr_ro.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace LDR_RO | ||
| 11 | |||
| 12 | namespace LDR_RO { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "ldr:ro"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/nim_aoc.cpp b/src/core/hle/service/nim_aoc.cpp new file mode 100644 index 000000000..04c1e0cf3 --- /dev/null +++ b/src/core/hle/service/nim_aoc.cpp | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/nim_aoc.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace NIM_AOC | ||
| 11 | |||
| 12 | namespace NIM_AOC { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x00030042, nullptr, "SetApplicationId"}, | ||
| 16 | {0x00040042, nullptr, "SetTin"}, | ||
| 17 | {0x000902D0, nullptr, "ListContentSetsEx"}, | ||
| 18 | {0x00180000, nullptr, "GetBalance"}, | ||
| 19 | {0x001D0000, nullptr, "GetCustomerSupportCode"}, | ||
| 20 | {0x00210000, nullptr, "Initialize"}, | ||
| 21 | {0x00240282, nullptr, "CalculateContentsRequiredSize"}, | ||
| 22 | {0x00250000, nullptr, "RefreshServerTime"}, | ||
| 23 | }; | ||
| 24 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 25 | // Interface class | ||
| 26 | |||
| 27 | Interface::Interface() { | ||
| 28 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 29 | } | ||
| 30 | |||
| 31 | } // namespace | ||
diff --git a/src/core/hle/service/nim_aoc.h b/src/core/hle/service/nim_aoc.h new file mode 100644 index 000000000..2cc673118 --- /dev/null +++ b/src/core/hle/service/nim_aoc.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace NIM_AOC | ||
| 11 | |||
| 12 | namespace NIM_AOC { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const override { | ||
| 23 | return "nim:aoc"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index e6973572b..2230045e3 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -7,21 +7,25 @@ | |||
| 7 | 7 | ||
| 8 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 9 | #include "core/hle/service/ac_u.h" | 9 | #include "core/hle/service/ac_u.h" |
| 10 | #include "core/hle/service/am_app.h" | ||
| 10 | #include "core/hle/service/am_net.h" | 11 | #include "core/hle/service/am_net.h" |
| 11 | #include "core/hle/service/apt_u.h" | 12 | #include "core/hle/service/apt_u.h" |
| 12 | #include "core/hle/service/boss_u.h" | 13 | #include "core/hle/service/boss_u.h" |
| 14 | #include "core/hle/service/cecd_u.h" | ||
| 13 | #include "core/hle/service/cfg_i.h" | 15 | #include "core/hle/service/cfg_i.h" |
| 14 | #include "core/hle/service/cfg_u.h" | 16 | #include "core/hle/service/cfg_u.h" |
| 15 | #include "core/hle/service/csnd_snd.h" | 17 | #include "core/hle/service/csnd_snd.h" |
| 16 | #include "core/hle/service/dsp_dsp.h" | 18 | #include "core/hle/service/dsp_dsp.h" |
| 17 | #include "core/hle/service/err_f.h" | 19 | #include "core/hle/service/err_f.h" |
| 18 | #include "core/hle/service/fs_user.h" | 20 | #include "core/hle/service/fs/fs_user.h" |
| 19 | #include "core/hle/service/frd_u.h" | 21 | #include "core/hle/service/frd_u.h" |
| 20 | #include "core/hle/service/gsp_gpu.h" | 22 | #include "core/hle/service/gsp_gpu.h" |
| 21 | #include "core/hle/service/hid_user.h" | 23 | #include "core/hle/service/hid_user.h" |
| 22 | #include "core/hle/service/ir_rst.h" | 24 | #include "core/hle/service/ir_rst.h" |
| 23 | #include "core/hle/service/ir_u.h" | 25 | #include "core/hle/service/ir_u.h" |
| 26 | #include "core/hle/service/ldr_ro.h" | ||
| 24 | #include "core/hle/service/mic_u.h" | 27 | #include "core/hle/service/mic_u.h" |
| 28 | #include "core/hle/service/nim_aoc.h" | ||
| 25 | #include "core/hle/service/ndm_u.h" | 29 | #include "core/hle/service/ndm_u.h" |
| 26 | #include "core/hle/service/nwm_uds.h" | 30 | #include "core/hle/service/nwm_uds.h" |
| 27 | #include "core/hle/service/pm_app.h" | 31 | #include "core/hle/service/pm_app.h" |
| @@ -84,21 +88,25 @@ void Init() { | |||
| 84 | 88 | ||
| 85 | g_manager->AddService(new SRV::Interface); | 89 | g_manager->AddService(new SRV::Interface); |
| 86 | g_manager->AddService(new AC_U::Interface); | 90 | g_manager->AddService(new AC_U::Interface); |
| 91 | g_manager->AddService(new AM_APP::Interface); | ||
| 87 | g_manager->AddService(new AM_NET::Interface); | 92 | g_manager->AddService(new AM_NET::Interface); |
| 88 | g_manager->AddService(new APT_U::Interface); | 93 | g_manager->AddService(new APT_U::Interface); |
| 89 | g_manager->AddService(new BOSS_U::Interface); | 94 | g_manager->AddService(new BOSS_U::Interface); |
| 95 | g_manager->AddService(new CECD_U::Interface); | ||
| 90 | g_manager->AddService(new CFG_I::Interface); | 96 | g_manager->AddService(new CFG_I::Interface); |
| 91 | g_manager->AddService(new CFG_U::Interface); | 97 | g_manager->AddService(new CFG_U::Interface); |
| 92 | g_manager->AddService(new CSND_SND::Interface); | 98 | g_manager->AddService(new CSND_SND::Interface); |
| 93 | g_manager->AddService(new DSP_DSP::Interface); | 99 | g_manager->AddService(new DSP_DSP::Interface); |
| 94 | g_manager->AddService(new ERR_F::Interface); | 100 | g_manager->AddService(new ERR_F::Interface); |
| 95 | g_manager->AddService(new FRD_U::Interface); | 101 | g_manager->AddService(new FRD_U::Interface); |
| 96 | g_manager->AddService(new FS_User::Interface); | 102 | g_manager->AddService(new FS::FSUserInterface); |
| 97 | g_manager->AddService(new GSP_GPU::Interface); | 103 | g_manager->AddService(new GSP_GPU::Interface); |
| 98 | g_manager->AddService(new HID_User::Interface); | 104 | g_manager->AddService(new HID_User::Interface); |
| 99 | g_manager->AddService(new IR_RST::Interface); | 105 | g_manager->AddService(new IR_RST::Interface); |
| 100 | g_manager->AddService(new IR_U::Interface); | 106 | g_manager->AddService(new IR_U::Interface); |
| 107 | g_manager->AddService(new LDR_RO::Interface); | ||
| 101 | g_manager->AddService(new MIC_U::Interface); | 108 | g_manager->AddService(new MIC_U::Interface); |
| 109 | g_manager->AddService(new NIM_AOC::Interface); | ||
| 102 | g_manager->AddService(new NDM_U::Interface); | 110 | g_manager->AddService(new NDM_U::Interface); |
| 103 | g_manager->AddService(new NWM_UDS::Interface); | 111 | g_manager->AddService(new NWM_UDS::Interface); |
| 104 | g_manager->AddService(new PM_APP::Interface); | 112 | g_manager->AddService(new PM_APP::Interface); |
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index f48d13530..0437e5374 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "core/file_sys/archive_romfs.h" | 8 | #include "core/file_sys/archive_romfs.h" |
| 9 | #include "core/loader/elf.h" | 9 | #include "core/loader/elf.h" |
| 10 | #include "core/loader/ncch.h" | 10 | #include "core/loader/ncch.h" |
| 11 | #include "core/hle/kernel/archive.h" | 11 | #include "core/hle/service/fs/archive.h" |
| 12 | #include "core/mem_map.h" | 12 | #include "core/mem_map.h" |
| 13 | 13 | ||
| 14 | #include "3dsx.h" | 14 | #include "3dsx.h" |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 3883e1307..463dacca3 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "core/loader/3dsx.h" | 8 | #include "core/loader/3dsx.h" |
| 9 | #include "core/loader/elf.h" | 9 | #include "core/loader/elf.h" |
| 10 | #include "core/loader/ncch.h" | 10 | #include "core/loader/ncch.h" |
| 11 | #include "core/hle/kernel/archive.h" | 11 | #include "core/hle/service/fs/archive.h" |
| 12 | #include "core/mem_map.h" | 12 | #include "core/mem_map.h" |
| 13 | 13 | ||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -74,7 +74,7 @@ ResultStatus LoadFile(const std::string& filename) { | |||
| 74 | 74 | ||
| 75 | // Load application and RomFS | 75 | // Load application and RomFS |
| 76 | if (ResultStatus::Success == app_loader.Load()) { | 76 | if (ResultStatus::Success == app_loader.Load()) { |
| 77 | Kernel::CreateArchive(new FileSys::Archive_RomFS(app_loader), "RomFS"); | 77 | Service::FS::CreateArchive(std::make_unique<FileSys::Archive_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS); |
| 78 | return ResultStatus::Success; | 78 | return ResultStatus::Success; |
| 79 | } | 79 | } |
| 80 | break; | 80 | break; |
diff --git a/src/core/system.cpp b/src/core/system.cpp index 43d0eef2c..2885ff45f 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp | |||
| @@ -23,10 +23,10 @@ void Init(EmuWindow* emu_window) { | |||
| 23 | Core::Init(); | 23 | Core::Init(); |
| 24 | Memory::Init(); | 24 | Memory::Init(); |
| 25 | HW::Init(); | 25 | HW::Init(); |
| 26 | Kernel::Init(); | ||
| 26 | HLE::Init(); | 27 | HLE::Init(); |
| 27 | CoreTiming::Init(); | 28 | CoreTiming::Init(); |
| 28 | VideoCore::Init(emu_window); | 29 | VideoCore::Init(emu_window); |
| 29 | Kernel::Init(); | ||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | void RunLoopFor(int cycles) { | 32 | void RunLoopFor(int cycles) { |
| @@ -37,13 +37,13 @@ void RunLoopUntil(u64 global_cycles) { | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | void Shutdown() { | 39 | void Shutdown() { |
| 40 | Core::Shutdown(); | ||
| 41 | Memory::Shutdown(); | ||
| 42 | HW::Shutdown(); | ||
| 43 | HLE::Shutdown(); | ||
| 44 | CoreTiming::Shutdown(); | ||
| 45 | VideoCore::Shutdown(); | 40 | VideoCore::Shutdown(); |
| 41 | CoreTiming::Shutdown(); | ||
| 42 | HLE::Shutdown(); | ||
| 46 | Kernel::Shutdown(); | 43 | Kernel::Shutdown(); |
| 44 | HW::Shutdown(); | ||
| 45 | Memory::Shutdown(); | ||
| 46 | Core::Shutdown(); | ||
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | } // namespace | 49 | } // namespace |