summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis-build.sh1
-rw-r--r--.travis-deps.sh5
-rw-r--r--CMakeLists.txt3
-rw-r--r--README.md20
-rw-r--r--src/citra_qt/main.cpp6
-rw-r--r--src/core/CMakeLists.txt22
-rw-r--r--src/core/arm/interpreter/armemu.cpp35
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp7
-rw-r--r--src/core/file_sys/archive_backend.h (renamed from src/core/file_sys/archive.h)59
-rw-r--r--src/core/file_sys/archive_romfs.cpp54
-rw-r--r--src/core/file_sys/archive_romfs.h47
-rw-r--r--src/core/file_sys/archive_sdmc.cpp49
-rw-r--r--src/core/file_sys/archive_sdmc.h44
-rw-r--r--src/core/file_sys/directory_backend.h (renamed from src/core/file_sys/directory.h)6
-rw-r--r--src/core/file_sys/directory_romfs.h4
-rw-r--r--src/core/file_sys/directory_sdmc.h4
-rw-r--r--src/core/file_sys/file_backend.h (renamed from src/core/file_sys/file.h)6
-rw-r--r--src/core/file_sys/file_romfs.cpp19
-rw-r--r--src/core/file_sys/file_romfs.h12
-rw-r--r--src/core/file_sys/file_sdmc.h4
-rw-r--r--src/core/hle/hle.cpp3
-rw-r--r--src/core/hle/kernel/kernel.cpp5
-rw-r--r--src/core/hle/service/am_app.cpp24
-rw-r--r--src/core/hle/service/am_app.h (renamed from src/core/hle/service/fs_user.h)12
-rw-r--r--src/core/hle/service/cecd_u.cpp24
-rw-r--r--src/core/hle/service/cecd_u.h27
-rw-r--r--src/core/hle/service/fs/archive.cpp (renamed from src/core/hle/kernel/archive.cpp)284
-rw-r--r--src/core/hle/service/fs/archive.h (renamed from src/core/hle/kernel/archive.h)48
-rw-r--r--src/core/hle/service/fs/fs_user.cpp (renamed from src/core/hle/service/fs_user.cpp)130
-rw-r--r--src/core/hle/service/fs/fs_user.h33
-rw-r--r--src/core/hle/service/ldr_ro.cpp28
-rw-r--r--src/core/hle/service/ldr_ro.h27
-rw-r--r--src/core/hle/service/nim_aoc.cpp31
-rw-r--r--src/core/hle/service/nim_aoc.h27
-rw-r--r--src/core/hle/service/service.cpp12
-rw-r--r--src/core/loader/3dsx.cpp2
-rw-r--r--src/core/loader/loader.cpp4
-rw-r--r--src/core/system.cpp12
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
3set -e 3set -e
4set -x
4 5
5#if OS is linux or is not set 6#if OS is linux or is not set
6if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then 7if [ "$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
3set -e 3set -e
4set -x
4 5
5#if OS is linux or is not set 6#if OS is linux or is not set
6if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then 7if [ "$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)
5project(citra) 5project(citra)
6 6
7if (NOT MSVC) 7if (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")
9else() 10else()
10 # Silence deprecation warnings 11 # Silence deprecation warnings
11 add_definitions(/D_CRT_SECURE_NO_WARNINGS) 12 add_definitions(/D_CRT_SECURE_NO_WARNINGS)
diff --git a/README.md b/README.md
index 554553ee8..a76520c93 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,12 @@
1citra emulator 1Citra Emulator
2============== 2==============
3[![Travis CI Build Status](https://travis-ci.org/citra-emu/citra.svg)](https://travis-ci.org/citra-emu/citra) 3[![Travis CI Build Status](https://travis-ci.org/citra-emu/citra.svg)](https://travis-ci.org/citra-emu/citra)
4 4
5An 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. 5Citra 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
7For development discussion, please join us @ #citra on [freenode](http://webchat.freenode.net/). 7Citra 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
9For 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
23If 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
31We 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
163class Archive : NonCopyable { 163class ArchiveBackend : NonCopyable {
164public: 164public:
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
23Archive_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 */
32std::unique_ptr<File> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { 31std::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 */
81std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const Path& path) const { 80std::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 */
92size_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 */
106size_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 */
115size_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 */
122void 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 @@
17namespace FileSys { 17namespace FileSys {
18 18
19/// File system interface to the RomFS archive 19/// File system interface to the RomFS archive
20class Archive_RomFS final : public Archive { 20class Archive_RomFS final : public ArchiveBackend {
21public: 21public:
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
113private: 78private:
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 */
52std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { 52std::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 */
100std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const { 100std::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 */
115size_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 */
128size_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 */
137size_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 */
145void 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 @@
15namespace FileSys { 15namespace FileSys {
16 16
17/// File system interface to the SDMC archive 17/// File system interface to the SDMC archive
18class Archive_SDMC final : public Archive { 18class Archive_SDMC final : public ArchiveBackend {
19public: 19public:
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
36static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); 36static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry.");
37static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); 37static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry.");
38 38
39class Directory : NonCopyable { 39class DirectoryBackend : NonCopyable {
40public: 40public:
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
15namespace FileSys { 15namespace FileSys {
16 16
17class Directory_RomFS final : public Directory { 17class Directory_RomFS final : public DirectoryBackend {
18public: 18public:
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
17namespace FileSys { 17namespace FileSys {
18 18
19class Directory_SDMC final : public Directory { 19class Directory_SDMC final : public DirectoryBackend {
20public: 20public:
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
14namespace FileSys { 14namespace FileSys {
15 15
16class File : NonCopyable { 16class FileBackend : NonCopyable {
17public: 17public:
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
12namespace FileSys { 13namespace FileSys {
13 14
14File_RomFS::File_RomFS() {
15}
16
17File_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 */
24bool File_RomFS::Open() { 19bool 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 */
35size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { 30size_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 */
47size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { 44size_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 */
55size_t File_RomFS::GetSize() const { 53size_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 */
64bool File_RomFS::SetSize(const u64 size) const { 62bool 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
15namespace FileSys { 15namespace FileSys {
16 16
17class File_RomFS final : public File { 17class Archive_RomFS;
18
19class File_RomFS final : public FileBackend {
18public: 20public:
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
67private:
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
17namespace FileSys { 17namespace FileSys {
18 18
19class File_SDMC final : public File { 19class File_SDMC final : public FileBackend {
20public: 20public:
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
57void Init() { 58void 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
65void Shutdown() { 67void 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
14namespace Kernel { 13namespace Kernel {
15 14
@@ -89,13 +88,11 @@ Object* ObjectPool::CreateByIDType(int type) {
89/// Initialize the kernel 88/// Initialize the kernel
90void Init() { 89void Init() {
91 Kernel::ThreadingInit(); 90 Kernel::ThreadingInit();
92 Kernel::ArchiveInit();
93} 91}
94 92
95/// Shutdown the kernel 93/// Shutdown the kernel
96void Shutdown() { 94void 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 */
108bool LoadExec(u32 entry_point) { 105bool 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
12namespace 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
20Interface::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
12namespace FS_User { 12namespace AM_APP {
13 13
14/// Interface to "fs:USER" service
15class Interface : public Service::Interface { 14class Interface : public Service::Interface {
16public: 15public:
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
12namespace 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
20Interface::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
12namespace CECD_U {
13
14class Interface : public Service::Interface {
15public:
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
21namespace 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
21namespace Kernel { 34namespace Service {
35namespace FS {
22 36
23// Command to access archive file 37// Command to access archive file
24enum class FileCommand : u32 { 38enum class FileCommand : u32 {
@@ -43,78 +57,28 @@ enum class DirectoryCommand : u32 {
43 Close = 0x08020000, 57 Close = 0x08020000,
44}; 58};
45 59
46class Archive : public Kernel::Session { 60class Archive {
47public: 61public:
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
112class File : public Kernel::Session { 72class File : public Kernel::Session {
113public: 73public:
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
186class Directory : public Kernel::Session { 150class Directory : public Kernel::Session {
187public: 151public:
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
233std::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 */
205static 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 */
210static std::unordered_map<ArchiveHandle, Archive*> handle_map;
211static ArchiveHandle next_handle;
212
213static Archive* GetArchive(ArchiveHandle handle) {
214 auto itr = handle_map.find(handle);
215 return (itr == handle_map.end()) ? nullptr : itr->second;
216}
217
218ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code) {
219 LOG_TRACE(Service_FS, "Opening archive with id code 0x%08X", id_code);
234 220
235ResultVal<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
245ResultCode CloseArchive(FileSys::Archive::IdCode id_code) { 236ResultCode 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 245ResultCode 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));
260ResultCode 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
272ResultCode 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
286ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { 256ResultVal<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
316ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) { 272ResultCode 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
326ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, 283ResultCode 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
343ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { 304ResultCode 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
353ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { 315ResultCode 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
363ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, 326ResultCode 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 */
386ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { 353ResultVal<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
406void ArchiveInit() { 370void 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
422void ArchiveShutdown() { 386void 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//////////////////////////////////////////////////////////////////////////////////////////////////// 13namespace Service {
14// Kernel namespace 14namespace FS {
15 15
16namespace Kernel { 16/// Supported archive types
17enum 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
27typedef 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 */
23ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code); 34ResultVal<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 */
29ResultCode CloseArchive(FileSys::Archive::IdCode id_code); 40ResultCode 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 */
36ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name); 47ResultCode 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 */
45ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); 56ResultVal<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 */
53ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path); 64ResultCode 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 */
63ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, 74ResultCode 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 */
72ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 83ResultCode 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 */
80ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 91ResultCode 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 */
90ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, 101ResultCode 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 */
99ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 110ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path);
100 111
101/// Initialize archives 112/// Initialize archives
102void ArchiveInit(); 113void ArchiveInit();
@@ -104,4 +115,5 @@ void ArchiveInit();
104/// Shutdown archives 115/// Shutdown archives
105void ArchiveShutdown(); 116void 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
17namespace FS_User { 17namespace Service {
18namespace FS {
19
20static ArchiveHandle MakeArchiveHandle(u32 low_word, u32 high_word) {
21 return (u64)low_word | ((u64)high_word << 32);
22}
18 23
19static void Initialize(Service::Interface* self) { 24static 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) {
88static void OpenFileDirectly(Service::Interface* self) { 94static 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 */
143void DeleteFile(Service::Interface* self) { 149static 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 */
177void RenameFile(Service::Interface* self) { 181static 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 */
212void DeleteDirectory(Service::Interface* self) { 214static 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) {
241static void CreateDirectory(Service::Interface* self) { 241static 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 */
274void RenameDirectory(Service::Interface* self) { 272static 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 */
298static void OpenDirectory(Service::Interface* self) { 307static 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) {
334static void OpenArchive(Service::Interface* self) { 341static 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 */
379static 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
376const Interface::FunctionInfo FunctionTable[] = { 401const 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
468Interface::Interface() { 493FSUserInterface::FSUserInterface() {
469 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 494 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
470} 495}
471 496
472Interface::~Interface() { 497FSUserInterface::~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
12namespace Service {
13namespace FS {
14
15/// Interface to "fs:USER" service
16class FSUserInterface : public Service::Interface {
17public:
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
12namespace LDR_RO {
13
14const 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
24Interface::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
12namespace LDR_RO {
13
14class Interface : public Service::Interface {
15public:
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
12namespace NIM_AOC {
13
14const 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
27Interface::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
12namespace NIM_AOC {
13
14class Interface : public Service::Interface {
15public:
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
32void RunLoopFor(int cycles) { 32void RunLoopFor(int cycles) {
@@ -37,13 +37,13 @@ void RunLoopUntil(u64 global_cycles) {
37} 37}
38 38
39void Shutdown() { 39void 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