summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar bunnei2018-03-01 22:14:31 -0500
committerGravatar GitHub2018-03-01 22:14:31 -0500
commit46fc7d85023f4449b542f0c58830421d667f92b7 (patch)
treea605aabd8c776bebea1111fccd8df01d569d5170 /src/core
parentMerge pull request #224 from Armada651/clear-process (diff)
parentSaveData: Use the current titleid when opening the savedata archive. (diff)
downloadyuzu-46fc7d85023f4449b542f0c58830421d667f92b7.tar.gz
yuzu-46fc7d85023f4449b542f0c58830421d667f92b7.tar.xz
yuzu-46fc7d85023f4449b542f0c58830421d667f92b7.zip
Merge pull request #216 from Subv/savedata
Implemented the SaveData archive and MountSaveData.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/file_sys/disk_filesystem.cpp147
-rw-r--r--src/core/file_sys/disk_filesystem.h66
-rw-r--r--src/core/file_sys/filesystem.h25
-rw-r--r--src/core/file_sys/romfs_filesystem.cpp12
-rw-r--r--src/core/file_sys/romfs_filesystem.h7
-rw-r--r--src/core/file_sys/savedata_factory.cpp42
-rw-r--r--src/core/file_sys/savedata_factory.h31
-rw-r--r--src/core/hle/kernel/process.cpp8
-rw-r--r--src/core/hle/kernel/process.h9
-rw-r--r--src/core/hle/result.h4
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp11
-rw-r--r--src/core/hle/service/filesystem/filesystem.h1
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp188
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h1
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp6
-rw-r--r--src/core/loader/elf.cpp4
-rw-r--r--src/core/loader/nro.cpp4
-rw-r--r--src/core/loader/nso.cpp8
-rw-r--r--src/core/loader/nso.h2
20 files changed, 541 insertions, 39 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 1bc536075..6ad04d19d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -7,6 +7,8 @@ add_library(core STATIC
7 core_timing.cpp 7 core_timing.cpp
8 core_timing.h 8 core_timing.h
9 file_sys/directory.h 9 file_sys/directory.h
10 file_sys/disk_filesystem.cpp
11 file_sys/disk_filesystem.h
10 file_sys/errors.h 12 file_sys/errors.h
11 file_sys/filesystem.cpp 13 file_sys/filesystem.cpp
12 file_sys/filesystem.h 14 file_sys/filesystem.h
@@ -18,6 +20,8 @@ add_library(core STATIC
18 file_sys/romfs_factory.h 20 file_sys/romfs_factory.h
19 file_sys/romfs_filesystem.cpp 21 file_sys/romfs_filesystem.cpp
20 file_sys/romfs_filesystem.h 22 file_sys/romfs_filesystem.h
23 file_sys/savedata_factory.cpp
24 file_sys/savedata_factory.h
21 file_sys/storage.h 25 file_sys/storage.h
22 frontend/emu_window.cpp 26 frontend/emu_window.cpp
23 frontend/emu_window.h 27 frontend/emu_window.h
diff --git a/src/core/file_sys/disk_filesystem.cpp b/src/core/file_sys/disk_filesystem.cpp
new file mode 100644
index 000000000..be7574fdb
--- /dev/null
+++ b/src/core/file_sys/disk_filesystem.cpp
@@ -0,0 +1,147 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include <memory>
7#include "common/common_types.h"
8#include "common/logging/log.h"
9#include "core/file_sys/disk_filesystem.h"
10
11namespace FileSys {
12
13std::string Disk_FileSystem::GetName() const {
14 return "Disk";
15}
16
17ResultVal<std::unique_ptr<StorageBackend>> Disk_FileSystem::OpenFile(const std::string& path,
18 Mode mode) const {
19 ASSERT_MSG(mode == Mode::Read || mode == Mode::Write, "Other file modes are not supported");
20
21 std::string full_path = base_directory + path;
22 auto file = std::make_shared<FileUtil::IOFile>(full_path, mode == Mode::Read ? "rb" : "wb");
23
24 if (!file->IsOpen()) {
25 // TODO(Subv): Find out the correct error code.
26 return ResultCode(-1);
27 }
28
29 return MakeResult<std::unique_ptr<StorageBackend>>(
30 std::make_unique<Disk_Storage>(std::move(file)));
31}
32
33ResultCode Disk_FileSystem::DeleteFile(const Path& path) const {
34 LOG_WARNING(Service_FS, "(STUBBED) called");
35 // TODO(bunnei): Use correct error code
36 return ResultCode(-1);
37}
38
39ResultCode Disk_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const {
40 LOG_WARNING(Service_FS, "(STUBBED) called");
41 // TODO(wwylele): Use correct error code
42 return ResultCode(-1);
43}
44
45ResultCode Disk_FileSystem::DeleteDirectory(const Path& path) const {
46 LOG_WARNING(Service_FS, "(STUBBED) called");
47 // TODO(wwylele): Use correct error code
48 return ResultCode(-1);
49}
50
51ResultCode Disk_FileSystem::DeleteDirectoryRecursively(const Path& path) const {
52 LOG_WARNING(Service_FS, "(STUBBED) called");
53 // TODO(wwylele): Use correct error code
54 return ResultCode(-1);
55}
56
57ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const {
58 LOG_WARNING(Service_FS, "(STUBBED) called");
59
60 std::string full_path = base_directory + path;
61 if (size == 0) {
62 FileUtil::CreateEmptyFile(full_path);
63 return RESULT_SUCCESS;
64 }
65
66 FileUtil::IOFile file(full_path, "wb");
67 // Creates a sparse file (or a normal file on filesystems without the concept of sparse files)
68 // We do this by seeking to the right size, then writing a single null byte.
69 if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1) {
70 return RESULT_SUCCESS;
71 }
72
73 LOG_ERROR(Service_FS, "Too large file");
74 // TODO(Subv): Find out the correct error code
75 return ResultCode(-1);
76}
77
78ResultCode Disk_FileSystem::CreateDirectory(const Path& path) const {
79 LOG_WARNING(Service_FS, "(STUBBED) called");
80 // TODO(wwylele): Use correct error code
81 return ResultCode(-1);
82}
83
84ResultCode Disk_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const {
85 LOG_WARNING(Service_FS, "(STUBBED) called");
86 // TODO(wwylele): Use correct error code
87 return ResultCode(-1);
88}
89
90ResultVal<std::unique_ptr<DirectoryBackend>> Disk_FileSystem::OpenDirectory(
91 const Path& path) const {
92 return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<Disk_Directory>());
93}
94
95u64 Disk_FileSystem::GetFreeSpaceSize() const {
96 LOG_WARNING(Service_FS, "(STUBBED) called");
97 return 0;
98}
99
100ResultVal<FileSys::EntryType> Disk_FileSystem::GetEntryType(const std::string& path) const {
101 std::string full_path = base_directory + path;
102 if (!FileUtil::Exists(full_path)) {
103 // TODO(Subv): Find out what this actually means
104 return ResultCode(ErrorModule::FS, 1);
105 }
106
107 // TODO(Subv): Find out the EntryType values
108 UNIMPLEMENTED_MSG("Unimplemented GetEntryType");
109}
110
111ResultVal<size_t> Disk_Storage::Read(const u64 offset, const size_t length, u8* buffer) const {
112 LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length);
113 file->Seek(offset, SEEK_SET);
114 return MakeResult<size_t>(file->ReadBytes(buffer, length));
115}
116
117ResultVal<size_t> Disk_Storage::Write(const u64 offset, const size_t length, const bool flush,
118 const u8* buffer) const {
119 LOG_WARNING(Service_FS, "(STUBBED) called");
120 file->Seek(offset, SEEK_SET);
121 size_t written = file->WriteBytes(buffer, length);
122 if (flush) {
123 file->Flush();
124 }
125 return MakeResult<size_t>(written);
126}
127
128u64 Disk_Storage::GetSize() const {
129 return file->GetSize();
130}
131
132bool Disk_Storage::SetSize(const u64 size) const {
133 LOG_WARNING(Service_FS, "(STUBBED) called");
134 return false;
135}
136
137u32 Disk_Directory::Read(const u32 count, Entry* entries) {
138 LOG_WARNING(Service_FS, "(STUBBED) called");
139 return 0;
140}
141
142bool Disk_Directory::Close() const {
143 LOG_WARNING(Service_FS, "(STUBBED) called");
144 return true;
145}
146
147} // namespace FileSys
diff --git a/src/core/file_sys/disk_filesystem.h b/src/core/file_sys/disk_filesystem.h
new file mode 100644
index 000000000..53767b949
--- /dev/null
+++ b/src/core/file_sys/disk_filesystem.h
@@ -0,0 +1,66 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <cstddef>
8#include <memory>
9#include <string>
10#include "common/common_types.h"
11#include "common/file_util.h"
12#include "core/file_sys/directory.h"
13#include "core/file_sys/filesystem.h"
14#include "core/file_sys/storage.h"
15#include "core/hle/result.h"
16
17namespace FileSys {
18
19class Disk_FileSystem : public FileSystemBackend {
20public:
21 explicit Disk_FileSystem(std::string base_directory)
22 : base_directory(std::move(base_directory)) {}
23
24 std::string GetName() const override;
25
26 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
27 Mode mode) const override;
28 ResultCode DeleteFile(const Path& path) const override;
29 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override;
30 ResultCode DeleteDirectory(const Path& path) const override;
31 ResultCode DeleteDirectoryRecursively(const Path& path) const override;
32 ResultCode CreateFile(const std::string& path, u64 size) const override;
33 ResultCode CreateDirectory(const Path& path) const override;
34 ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override;
35 ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override;
36 u64 GetFreeSpaceSize() const override;
37 ResultVal<EntryType> GetEntryType(const std::string& path) const override;
38
39protected:
40 std::string base_directory;
41};
42
43class Disk_Storage : public StorageBackend {
44public:
45 Disk_Storage(std::shared_ptr<FileUtil::IOFile> file) : file(std::move(file)) {}
46
47 ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override;
48 ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
49 u64 GetSize() const override;
50 bool SetSize(u64 size) const override;
51 bool Close() const override {
52 return false;
53 }
54 void Flush() const override {}
55
56private:
57 std::shared_ptr<FileUtil::IOFile> file;
58};
59
60class Disk_Directory : public DirectoryBackend {
61public:
62 u32 Read(const u32 count, Entry* entries) override;
63 bool Close() const override;
64};
65
66} // namespace FileSys
diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h
index 02705506b..df4e66a0b 100644
--- a/src/core/file_sys/filesystem.h
+++ b/src/core/file_sys/filesystem.h
@@ -27,11 +27,14 @@ enum LowPathType : u32 {
27 Wchar = 4, 27 Wchar = 4,
28}; 28};
29 29
30union Mode { 30enum EntryType : u32 {
31 u32 hex; 31 Directory = 0,
32 BitField<0, 1, u32> read_flag; 32 File = 1,
33 BitField<1, 1, u32> write_flag; 33};
34 BitField<2, 1, u32> create_flag; 34
35enum class Mode : u32 {
36 Read = 1,
37 Write = 2,
35}; 38};
36 39
37class Path { 40class Path {
@@ -86,7 +89,7 @@ public:
86 * @param size The size of the new file, filled with zeroes 89 * @param size The size of the new file, filled with zeroes
87 * @return Result of the operation 90 * @return Result of the operation
88 */ 91 */
89 virtual ResultCode CreateFile(const Path& path, u64 size) const = 0; 92 virtual ResultCode CreateFile(const std::string& path, u64 size) const = 0;
90 93
91 /** 94 /**
92 * Delete a file specified by its path 95 * Delete a file specified by its path
@@ -138,8 +141,8 @@ public:
138 * @param mode Mode to open the file with 141 * @param mode Mode to open the file with
139 * @return Opened file, or error code 142 * @return Opened file, or error code
140 */ 143 */
141 virtual ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const Path& path, 144 virtual ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
142 const Mode& mode) const = 0; 145 Mode mode) const = 0;
143 146
144 /** 147 /**
145 * Open a directory specified by its path 148 * Open a directory specified by its path
@@ -153,6 +156,12 @@ public:
153 * @return The number of free bytes in the archive 156 * @return The number of free bytes in the archive
154 */ 157 */
155 virtual u64 GetFreeSpaceSize() const = 0; 158 virtual u64 GetFreeSpaceSize() const = 0;
159
160 /**
161 * Get the type of the specified path
162 * @return The type of the specified path or error code
163 */
164 virtual ResultVal<EntryType> GetEntryType(const std::string& path) const = 0;
156}; 165};
157 166
158class FileSystemFactory : NonCopyable { 167class FileSystemFactory : NonCopyable {
diff --git a/src/core/file_sys/romfs_filesystem.cpp b/src/core/file_sys/romfs_filesystem.cpp
index ca1463d7c..f1f9b4d04 100644
--- a/src/core/file_sys/romfs_filesystem.cpp
+++ b/src/core/file_sys/romfs_filesystem.cpp
@@ -14,8 +14,8 @@ std::string RomFS_FileSystem::GetName() const {
14 return "RomFS"; 14 return "RomFS";
15} 15}
16 16
17ResultVal<std::unique_ptr<StorageBackend>> RomFS_FileSystem::OpenFile(const Path& path, 17ResultVal<std::unique_ptr<StorageBackend>> RomFS_FileSystem::OpenFile(const std::string& path,
18 const Mode& mode) const { 18 Mode mode) const {
19 return MakeResult<std::unique_ptr<StorageBackend>>( 19 return MakeResult<std::unique_ptr<StorageBackend>>(
20 std::make_unique<RomFS_Storage>(romfs_file, data_offset, data_size)); 20 std::make_unique<RomFS_Storage>(romfs_file, data_offset, data_size));
21} 21}
@@ -48,7 +48,7 @@ ResultCode RomFS_FileSystem::DeleteDirectoryRecursively(const Path& path) const
48 return ResultCode(-1); 48 return ResultCode(-1);
49} 49}
50 50
51ResultCode RomFS_FileSystem::CreateFile(const Path& path, u64 size) const { 51ResultCode RomFS_FileSystem::CreateFile(const std::string& path, u64 size) const {
52 LOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive (%s).", 52 LOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive (%s).",
53 GetName().c_str()); 53 GetName().c_str());
54 // TODO(bunnei): Use correct error code 54 // TODO(bunnei): Use correct error code
@@ -79,6 +79,12 @@ u64 RomFS_FileSystem::GetFreeSpaceSize() const {
79 return 0; 79 return 0;
80} 80}
81 81
82ResultVal<FileSys::EntryType> RomFS_FileSystem::GetEntryType(const std::string& path) const {
83 LOG_CRITICAL(Service_FS, "Called within an ROMFS archive (path %s).", path.c_str());
84 // TODO(wwylele): Use correct error code
85 return ResultCode(-1);
86}
87
82ResultVal<size_t> RomFS_Storage::Read(const u64 offset, const size_t length, u8* buffer) const { 88ResultVal<size_t> RomFS_Storage::Read(const u64 offset, const size_t length, u8* buffer) const {
83 LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); 89 LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length);
84 romfs_file->Seek(data_offset + offset, SEEK_SET); 90 romfs_file->Seek(data_offset + offset, SEEK_SET);
diff --git a/src/core/file_sys/romfs_filesystem.h b/src/core/file_sys/romfs_filesystem.h
index 900ea567a..cedd70645 100644
--- a/src/core/file_sys/romfs_filesystem.h
+++ b/src/core/file_sys/romfs_filesystem.h
@@ -29,17 +29,18 @@ public:
29 29
30 std::string GetName() const override; 30 std::string GetName() const override;
31 31
32 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const Path& path, 32 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
33 const Mode& mode) const override; 33 Mode mode) const override;
34 ResultCode DeleteFile(const Path& path) const override; 34 ResultCode DeleteFile(const Path& path) const override;
35 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; 35 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override;
36 ResultCode DeleteDirectory(const Path& path) const override; 36 ResultCode DeleteDirectory(const Path& path) const override;
37 ResultCode DeleteDirectoryRecursively(const Path& path) const override; 37 ResultCode DeleteDirectoryRecursively(const Path& path) const override;
38 ResultCode CreateFile(const Path& path, u64 size) const override; 38 ResultCode CreateFile(const std::string& path, u64 size) const override;
39 ResultCode CreateDirectory(const Path& path) const override; 39 ResultCode CreateDirectory(const Path& path) const override;
40 ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; 40 ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override;
41 ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override; 41 ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override;
42 u64 GetFreeSpaceSize() const override; 42 u64 GetFreeSpaceSize() const override;
43 ResultVal<EntryType> GetEntryType(const std::string& path) const override;
43 44
44protected: 45protected:
45 std::shared_ptr<FileUtil::IOFile> romfs_file; 46 std::shared_ptr<FileUtil::IOFile> romfs_file;
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
new file mode 100644
index 000000000..4d83e100f
--- /dev/null
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -0,0 +1,42 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cinttypes>
6#include <memory>
7#include "common/common_types.h"
8#include "common/logging/log.h"
9#include "common/string_util.h"
10#include "core/file_sys/disk_filesystem.h"
11#include "core/file_sys/savedata_factory.h"
12#include "core/hle/kernel/process.h"
13
14namespace FileSys {
15
16SaveData_Factory::SaveData_Factory(std::string nand_directory)
17 : nand_directory(std::move(nand_directory)) {}
18
19ResultVal<std::unique_ptr<FileSystemBackend>> SaveData_Factory::Open(const Path& path) {
20 u64 title_id = Kernel::g_current_process->program_id;
21 // TODO(Subv): Somehow obtain this value.
22 u32 user = 0;
23 std::string save_directory = Common::StringFromFormat("%ssave/%016" PRIX64 "/%08X",
24 nand_directory.c_str(), title_id, user);
25 auto archive = std::make_unique<Disk_FileSystem>(save_directory);
26 return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive));
27}
28
29ResultCode SaveData_Factory::Format(const Path& path,
30 const FileSys::ArchiveFormatInfo& format_info) {
31 LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str());
32 // TODO(bunnei): Find the right error code for this
33 return ResultCode(-1);
34}
35
36ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) const {
37 LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str());
38 // TODO(bunnei): Find the right error code for this
39 return ResultCode(-1);
40}
41
42} // namespace FileSys
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
new file mode 100644
index 000000000..726743fde
--- /dev/null
+++ b/src/core/file_sys/savedata_factory.h
@@ -0,0 +1,31 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <string>
9#include "common/common_types.h"
10#include "core/file_sys/filesystem.h"
11#include "core/hle/result.h"
12
13namespace FileSys {
14
15/// File system interface to the SaveData archive
16class SaveData_Factory final : public FileSystemFactory {
17public:
18 explicit SaveData_Factory(std::string nand_directory);
19
20 std::string GetName() const override {
21 return "SaveData_Factory";
22 }
23 ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) override;
24 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
25 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
26
27private:
28 std::string nand_directory;
29};
30
31} // namespace FileSys
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 8e74059ea..bb6dc28d7 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -20,12 +20,9 @@ namespace Kernel {
20// Lists all processes that exist in the current session. 20// Lists all processes that exist in the current session.
21static std::vector<SharedPtr<Process>> process_list; 21static std::vector<SharedPtr<Process>> process_list;
22 22
23SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) { 23SharedPtr<CodeSet> CodeSet::Create(std::string name) {
24 SharedPtr<CodeSet> codeset(new CodeSet); 24 SharedPtr<CodeSet> codeset(new CodeSet);
25
26 codeset->name = std::move(name); 25 codeset->name = std::move(name);
27 codeset->program_id = program_id;
28
29 return codeset; 26 return codeset;
30} 27}
31 28
@@ -34,13 +31,14 @@ CodeSet::~CodeSet() {}
34 31
35u32 Process::next_process_id; 32u32 Process::next_process_id;
36 33
37SharedPtr<Process> Process::Create(std::string&& name) { 34SharedPtr<Process> Process::Create(std::string&& name, u64 program_id) {
38 SharedPtr<Process> process(new Process); 35 SharedPtr<Process> process(new Process);
39 36
40 process->name = std::move(name); 37 process->name = std::move(name);
41 process->flags.raw = 0; 38 process->flags.raw = 0;
42 process->flags.memory_region.Assign(MemoryRegion::APPLICATION); 39 process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
43 process->status = ProcessStatus::Created; 40 process->status = ProcessStatus::Created;
41 process->program_id = program_id;
44 42
45 process_list.push_back(process); 43 process_list.push_back(process);
46 return process; 44 return process;
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index add98472f..1de12efd3 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -56,7 +56,7 @@ class ResourceLimit;
56struct MemoryRegionInfo; 56struct MemoryRegionInfo;
57 57
58struct CodeSet final : public Object { 58struct CodeSet final : public Object {
59 static SharedPtr<CodeSet> Create(std::string name, u64 program_id); 59 static SharedPtr<CodeSet> Create(std::string name);
60 60
61 std::string GetTypeName() const override { 61 std::string GetTypeName() const override {
62 return "CodeSet"; 62 return "CodeSet";
@@ -72,8 +72,6 @@ struct CodeSet final : public Object {
72 72
73 /// Name of the process 73 /// Name of the process
74 std::string name; 74 std::string name;
75 /// Title ID corresponding to the process
76 u64 program_id;
77 75
78 std::shared_ptr<std::vector<u8>> memory; 76 std::shared_ptr<std::vector<u8>> memory;
79 77
@@ -97,7 +95,7 @@ private:
97 95
98class Process final : public Object { 96class Process final : public Object {
99public: 97public:
100 static SharedPtr<Process> Create(std::string&& name); 98 static SharedPtr<Process> Create(std::string&& name, u64 program_id);
101 99
102 std::string GetTypeName() const override { 100 std::string GetTypeName() const override {
103 return "Process"; 101 return "Process";
@@ -113,6 +111,9 @@ public:
113 111
114 static u32 next_process_id; 112 static u32 next_process_id;
115 113
114 /// Title ID corresponding to the process
115 u64 program_id;
116
116 /// Resource limit descriptor for this process 117 /// Resource limit descriptor for this process
117 SharedPtr<ResourceLimit> resource_limit; 118 SharedPtr<ResourceLimit> resource_limit;
118 119
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 656e1b4a7..97fef7a48 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -108,11 +108,11 @@ union ResultCode {
108 } 108 }
109 109
110 constexpr bool IsSuccess() const { 110 constexpr bool IsSuccess() const {
111 return is_error.ExtractValue(raw) == 0; 111 return raw == 0;
112 } 112 }
113 113
114 constexpr bool IsError() const { 114 constexpr bool IsError() const {
115 return is_error.ExtractValue(raw) == 1; 115 return raw != 0;
116 } 116 }
117}; 117};
118 118
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 4b47548fd..32752aea5 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -3,7 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <boost/container/flat_map.hpp> 5#include <boost/container/flat_map.hpp>
6#include "common/file_util.h"
6#include "core/file_sys/filesystem.h" 7#include "core/file_sys/filesystem.h"
8#include "core/file_sys/savedata_factory.h"
7#include "core/hle/service/filesystem/filesystem.h" 9#include "core/hle/service/filesystem/filesystem.h"
8#include "core/hle/service/filesystem/fsp_srv.h" 10#include "core/hle/service/filesystem/fsp_srv.h"
9 11
@@ -41,12 +43,17 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
41 return itr->second->Open(path); 43 return itr->second->Open(path);
42} 44}
43 45
44void UnregisterFileSystems() { 46void RegisterFileSystems() {
45 filesystem_map.clear(); 47 filesystem_map.clear();
48
49 std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
50
51 auto savedata = std::make_unique<FileSys::SaveData_Factory>(std::move(nand_directory));
52 RegisterFileSystem(std::move(savedata), Type::SaveData);
46} 53}
47 54
48void InstallInterfaces(SM::ServiceManager& service_manager) { 55void InstallInterfaces(SM::ServiceManager& service_manager) {
49 UnregisterFileSystems(); 56 RegisterFileSystems();
50 std::make_shared<FSP_SRV>()->InstallAsService(service_manager); 57 std::make_shared<FSP_SRV>()->InstallAsService(service_manager);
51} 58}
52 59
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index a674c9493..80f318676 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -25,6 +25,7 @@ namespace FileSystem {
25/// Supported FileSystem types 25/// Supported FileSystem types
26enum class Type { 26enum class Type {
27 RomFS = 1, 27 RomFS = 1,
28 SaveData = 2,
28}; 29};
29 30
30/** 31/**
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 87a07e457..3ac5a96cb 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cinttypes>
5#include "common/logging/log.h" 6#include "common/logging/log.h"
6#include "core/core.h" 7#include "core/core.h"
7#include "core/file_sys/filesystem.h" 8#include "core/file_sys/filesystem.h"
@@ -65,10 +66,186 @@ private:
65 } 66 }
66}; 67};
67 68
69class IFile final : public ServiceFramework<IFile> {
70public:
71 explicit IFile(std::unique_ptr<FileSys::StorageBackend>&& backend)
72 : ServiceFramework("IFile"), backend(std::move(backend)) {
73 static const FunctionInfo functions[] = {
74 {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, {2, nullptr, "Flush"},
75 {3, nullptr, "SetSize"}, {4, nullptr, "GetSize"},
76 };
77 RegisterHandlers(functions);
78 }
79
80private:
81 std::unique_ptr<FileSys::StorageBackend> backend;
82
83 void Read(Kernel::HLERequestContext& ctx) {
84 IPC::RequestParser rp{ctx};
85 const u64 unk = rp.Pop<u64>();
86 const s64 offset = rp.Pop<s64>();
87 const s64 length = rp.Pop<s64>();
88
89 LOG_DEBUG(Service_FS, "called, offset=0x%llx, length=0x%llx", offset, length);
90
91 // Error checking
92 if (length < 0) {
93 IPC::ResponseBuilder rb{ctx, 2};
94 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength));
95 return;
96 }
97 if (offset < 0) {
98 IPC::ResponseBuilder rb{ctx, 2};
99 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset));
100 return;
101 }
102
103 // Read the data from the Storage backend
104 std::vector<u8> output(length);
105 ResultVal<size_t> res = backend->Read(offset, length, output.data());
106 if (res.Failed()) {
107 IPC::ResponseBuilder rb{ctx, 2};
108 rb.Push(res.Code());
109 return;
110 }
111
112 // Write the data to memory
113 ctx.WriteBuffer(output);
114
115 IPC::ResponseBuilder rb{ctx, 4};
116 rb.Push(RESULT_SUCCESS);
117 rb.Push(static_cast<u64>(*res));
118 }
119
120 void Write(Kernel::HLERequestContext& ctx) {
121 IPC::RequestParser rp{ctx};
122 const u64 unk = rp.Pop<u64>();
123 const s64 offset = rp.Pop<s64>();
124 const s64 length = rp.Pop<s64>();
125
126 LOG_DEBUG(Service_FS, "called, offset=0x%llx, length=0x%llx", offset, length);
127
128 // Error checking
129 if (length < 0) {
130 IPC::ResponseBuilder rb{ctx, 2};
131 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength));
132 return;
133 }
134 if (offset < 0) {
135 IPC::ResponseBuilder rb{ctx, 2};
136 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset));
137 return;
138 }
139
140 // Write the data to the Storage backend
141 std::vector<u8> data = ctx.ReadBuffer();
142 ResultVal<size_t> res = backend->Write(offset, length, true, data.data());
143 if (res.Failed()) {
144 IPC::ResponseBuilder rb{ctx, 2};
145 rb.Push(res.Code());
146 return;
147 }
148
149 IPC::ResponseBuilder rb{ctx, 2};
150 rb.Push(RESULT_SUCCESS);
151 }
152};
153
154class IFileSystem final : public ServiceFramework<IFileSystem> {
155public:
156 explicit IFileSystem(std::unique_ptr<FileSys::FileSystemBackend>&& backend)
157 : ServiceFramework("IFileSystem"), backend(std::move(backend)) {
158 static const FunctionInfo functions[] = {
159 {0, &IFileSystem::CreateFile, "CreateFile"},
160 {7, &IFileSystem::GetEntryType, "GetEntryType"},
161 {8, &IFileSystem::OpenFile, "OpenFile"},
162 {10, &IFileSystem::Commit, "Commit"},
163 };
164 RegisterHandlers(functions);
165 }
166
167 void CreateFile(Kernel::HLERequestContext& ctx) {
168 IPC::RequestParser rp{ctx};
169
170 auto file_buffer = ctx.ReadBuffer();
171 auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
172
173 std::string name(file_buffer.begin(), end);
174
175 u64 mode = rp.Pop<u64>();
176 u32 size = rp.Pop<u32>();
177
178 LOG_DEBUG(Service_FS, "called file %s mode 0x%" PRIX64 " size 0x%08X", name.c_str(), mode,
179 size);
180
181 IPC::ResponseBuilder rb{ctx, 2};
182 rb.Push(backend->CreateFile(name, size));
183 }
184
185 void OpenFile(Kernel::HLERequestContext& ctx) {
186 IPC::RequestParser rp{ctx};
187
188 auto file_buffer = ctx.ReadBuffer();
189 auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
190
191 std::string name(file_buffer.begin(), end);
192
193 auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>());
194
195 LOG_DEBUG(Service_FS, "called file %s mode %u", name.c_str(), static_cast<u32>(mode));
196
197 auto result = backend->OpenFile(name, mode);
198 if (result.Failed()) {
199 IPC::ResponseBuilder rb{ctx, 2};
200 rb.Push(result.Code());
201 return;
202 }
203
204 auto file = std::move(result.Unwrap());
205
206 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
207 rb.Push(RESULT_SUCCESS);
208 rb.PushIpcInterface<IFile>(std::move(file));
209 }
210
211 void GetEntryType(Kernel::HLERequestContext& ctx) {
212 IPC::RequestParser rp{ctx};
213
214 auto file_buffer = ctx.ReadBuffer();
215 auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
216
217 std::string name(file_buffer.begin(), end);
218
219 LOG_DEBUG(Service_FS, "called file %s", name.c_str());
220
221 auto result = backend->GetEntryType(name);
222 if (result.Failed()) {
223 IPC::ResponseBuilder rb{ctx, 2};
224 rb.Push(result.Code());
225 return;
226 }
227
228 IPC::ResponseBuilder rb{ctx, 3};
229 rb.Push(RESULT_SUCCESS);
230 rb.Push<u32>(static_cast<u32>(*result));
231 }
232
233 void Commit(Kernel::HLERequestContext& ctx) {
234 LOG_WARNING(Service_FS, "(STUBBED) called");
235
236 IPC::ResponseBuilder rb{ctx, 2};
237 rb.Push(RESULT_SUCCESS);
238 }
239
240private:
241 std::unique_ptr<FileSys::FileSystemBackend> backend;
242};
243
68FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { 244FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
69 static const FunctionInfo functions[] = { 245 static const FunctionInfo functions[] = {
70 {1, &FSP_SRV::Initalize, "Initalize"}, 246 {1, &FSP_SRV::Initalize, "Initalize"},
71 {18, &FSP_SRV::MountSdCard, "MountSdCard"}, 247 {18, &FSP_SRV::MountSdCard, "MountSdCard"},
248 {51, &FSP_SRV::MountSaveData, "MountSaveData"},
72 {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, 249 {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
73 {202, nullptr, "OpenDataStorageByDataId"}, 250 {202, nullptr, "OpenDataStorageByDataId"},
74 {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"}, 251 {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"},
@@ -102,6 +279,17 @@ void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
102 rb.Push(RESULT_SUCCESS); 279 rb.Push(RESULT_SUCCESS);
103} 280}
104 281
282void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
283 LOG_WARNING(Service_FS, "(STUBBED) called");
284
285 FileSys::Path unused;
286 auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap();
287
288 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
289 rb.Push(RESULT_SUCCESS);
290 rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
291}
292
105void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { 293void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
106 LOG_WARNING(Service_FS, "(STUBBED) called"); 294 LOG_WARNING(Service_FS, "(STUBBED) called");
107 295
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 56afc4b90..f19b2f2c4 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -24,6 +24,7 @@ private:
24 24
25 void Initalize(Kernel::HLERequestContext& ctx); 25 void Initalize(Kernel::HLERequestContext& ctx);
26 void MountSdCard(Kernel::HLERequestContext& ctx); 26 void MountSdCard(Kernel::HLERequestContext& ctx);
27 void MountSaveData(Kernel::HLERequestContext& ctx);
27 void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); 28 void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
28 void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); 29 void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
29 void OpenRomStorage(Kernel::HLERequestContext& ctx); 30 void OpenRomStorage(Kernel::HLERequestContext& ctx);
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 864cf25cd..459d127c2 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -110,8 +110,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
110 return ResultStatus::Error; 110 return ResultStatus::Error;
111 } 111 }
112 112
113 process = Kernel::Process::Create("main");
114
115 const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP; 113 const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP;
116 const std::string npdm_path = directory + DIR_SEP + "main.npdm"; 114 const std::string npdm_path = directory + DIR_SEP + "main.npdm";
117 115
@@ -121,13 +119,15 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
121 } 119 }
122 metadata.Print(); 120 metadata.Print();
123 121
122 process = Kernel::Process::Create("main", metadata.GetTitleID());
123
124 // Load NSO modules 124 // Load NSO modules
125 VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; 125 VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
126 for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", 126 for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
127 "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { 127 "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
128 const std::string path = directory + DIR_SEP + module; 128 const std::string path = directory + DIR_SEP + module;
129 const VAddr load_addr = next_load_addr; 129 const VAddr load_addr = next_load_addr;
130 next_load_addr = AppLoader_NSO::LoadModule(path, load_addr, metadata.GetTitleID()); 130 next_load_addr = AppLoader_NSO::LoadModule(path, load_addr);
131 if (next_load_addr) { 131 if (next_load_addr) {
132 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, module, load_addr); 132 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, module, load_addr);
133 } else { 133 } else {
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index b87320656..cdd41f237 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -300,7 +300,7 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
300 std::vector<u8> program_image(total_image_size); 300 std::vector<u8> program_image(total_image_size);
301 size_t current_image_position = 0; 301 size_t current_image_position = 0;
302 302
303 SharedPtr<CodeSet> codeset = CodeSet::Create("", 0); 303 SharedPtr<CodeSet> codeset = CodeSet::Create("");
304 304
305 for (unsigned int i = 0; i < header->e_phnum; ++i) { 305 for (unsigned int i = 0; i < header->e_phnum; ++i) {
306 Elf32_Phdr* p = &segments[i]; 306 Elf32_Phdr* p = &segments[i];
@@ -406,7 +406,7 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
406 SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); 406 SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR);
407 codeset->name = filename; 407 codeset->name = filename;
408 408
409 process = Kernel::Process::Create("main"); 409 process = Kernel::Process::Create("main", 0);
410 process->LoadModule(codeset, codeset->entrypoint); 410 process->LoadModule(codeset, codeset->entrypoint);
411 process->svc_access_mask.set(); 411 process->svc_access_mask.set();
412 process->address_mappings = default_address_mappings; 412 process->address_mappings = default_address_mappings;
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 6f8a2f21e..c557b66dc 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -83,7 +83,7 @@ bool AppLoader_NRO::LoadNro(const std::string& path, VAddr load_base) {
83 } 83 }
84 84
85 // Build program image 85 // Build program image
86 Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create("", 0); 86 Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create("");
87 std::vector<u8> program_image; 87 std::vector<u8> program_image;
88 program_image.resize(PageAlignSize(nro_header.file_size)); 88 program_image.resize(PageAlignSize(nro_header.file_size));
89 file.Seek(0, SEEK_SET); 89 file.Seek(0, SEEK_SET);
@@ -125,7 +125,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
125 return ResultStatus::Error; 125 return ResultStatus::Error;
126 } 126 }
127 127
128 process = Kernel::Process::Create("main"); 128 process = Kernel::Process::Create("main", 0);
129 129
130 // Load NRO 130 // Load NRO
131 static constexpr VAddr base_addr{Memory::PROCESS_IMAGE_VADDR}; 131 static constexpr VAddr base_addr{Memory::PROCESS_IMAGE_VADDR};
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 7f8d24dd6..00b5d1d49 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -92,7 +92,7 @@ static constexpr u32 PageAlignSize(u32 size) {
92 return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; 92 return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
93} 93}
94 94
95VAddr AppLoader_NSO::LoadModule(const std::string& path, VAddr load_base, u64 tid) { 95VAddr AppLoader_NSO::LoadModule(const std::string& path, VAddr load_base) {
96 FileUtil::IOFile file(path, "rb"); 96 FileUtil::IOFile file(path, "rb");
97 if (!file.IsOpen()) { 97 if (!file.IsOpen()) {
98 return {}; 98 return {};
@@ -109,7 +109,7 @@ VAddr AppLoader_NSO::LoadModule(const std::string& path, VAddr load_base, u64 ti
109 } 109 }
110 110
111 // Build program image 111 // Build program image
112 Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create("", tid); 112 Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create("");
113 std::vector<u8> program_image; 113 std::vector<u8> program_image;
114 for (int i = 0; i < nso_header.segments.size(); ++i) { 114 for (int i = 0; i < nso_header.segments.size(); ++i) {
115 std::vector<u8> data = 115 std::vector<u8> data =
@@ -155,10 +155,10 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
155 return ResultStatus::Error; 155 return ResultStatus::Error;
156 } 156 }
157 157
158 process = Kernel::Process::Create("main"); 158 process = Kernel::Process::Create("main", 0);
159 159
160 // Load module 160 // Load module
161 LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR, 0); 161 LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR);
162 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, filepath.c_str(), 162 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, filepath.c_str(),
163 Memory::PROCESS_IMAGE_VADDR); 163 Memory::PROCESS_IMAGE_VADDR);
164 164
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h
index 14eb1d87e..1ae30a824 100644
--- a/src/core/loader/nso.h
+++ b/src/core/loader/nso.h
@@ -29,7 +29,7 @@ public:
29 return IdentifyType(file, filepath); 29 return IdentifyType(file, filepath);
30 } 30 }
31 31
32 static VAddr LoadModule(const std::string& path, VAddr load_base, u64 tid); 32 static VAddr LoadModule(const std::string& path, VAddr load_base);
33 33
34 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; 34 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
35 35