summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Subv2017-09-23 20:32:18 -0500
committerGravatar Subv2017-09-25 09:45:02 -0500
commit774e7deae8655a6f09530770c56ae2e75d55309b (patch)
tree897ebb18a3cff721f402d0be73559f4694d4b1d8
parentMerge pull request #2952 from MerryMage/page-tables (diff)
downloadyuzu-774e7deae8655a6f09530770c56ae2e75d55309b.tar.gz
yuzu-774e7deae8655a6f09530770c56ae2e75d55309b.tar.xz
yuzu-774e7deae8655a6f09530770c56ae2e75d55309b.zip
HLE/Archives: Allow multiple loaded applications to access their SelfNCCH archive independently.
The loaders now register each loaded ROM with the SelfNCCH factory, which keeps the data around for the duration of the emulation session. When opening the SelfNCCH archive, the factory queries the current program's programid and uses that as a key to the map that contains the NCCHData structure (RomFS, Icon, Banner, etc). 3dsx files do not have a programid and will use a default of 0 for this value, thus, only 1 3dsx file with RomFS is loadable at the same time.
Diffstat (limited to '')
-rw-r--r--src/core/file_sys/archive_selfncch.cpp43
-rw-r--r--src/core/file_sys/archive_selfncch.h9
-rw-r--r--src/core/hle/service/fs/archive.cpp18
-rw-r--r--src/core/hle/service/fs/archive.h7
-rw-r--r--src/core/loader/3dsx.cpp3
-rw-r--r--src/core/loader/ncch.cpp3
6 files changed, 65 insertions, 18 deletions
diff --git a/src/core/file_sys/archive_selfncch.cpp b/src/core/file_sys/archive_selfncch.cpp
index 7dc91a405..a16941c70 100644
--- a/src/core/file_sys/archive_selfncch.cpp
+++ b/src/core/file_sys/archive_selfncch.cpp
@@ -3,12 +3,14 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array> 5#include <array>
6#include <cinttypes>
6#include "common/common_types.h" 7#include "common/common_types.h"
7#include "common/logging/log.h" 8#include "common/logging/log.h"
8#include "common/swap.h" 9#include "common/swap.h"
9#include "core/file_sys/archive_selfncch.h" 10#include "core/file_sys/archive_selfncch.h"
10#include "core/file_sys/errors.h" 11#include "core/file_sys/errors.h"
11#include "core/file_sys/ivfc_archive.h" 12#include "core/file_sys/ivfc_archive.h"
13#include "core/hle/kernel/process.h"
12 14
13//////////////////////////////////////////////////////////////////////////////////////////////////// 15////////////////////////////////////////////////////////////////////////////////////////////////////
14// FileSys namespace 16// FileSys namespace
@@ -227,38 +229,57 @@ private:
227 NCCHData ncch_data; 229 NCCHData ncch_data;
228}; 230};
229 231
230ArchiveFactory_SelfNCCH::ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader) { 232void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) {
231 std::shared_ptr<FileUtil::IOFile> romfs_file; 233 u64 program_id = 0;
234 if (app_loader.ReadProgramId(program_id) != Loader::ResultStatus::Success) {
235 LOG_WARNING(
236 Service_FS,
237 "Could not read program id when registering with SelfNCCH, this might be a 3dsx file");
238 }
239
240 LOG_DEBUG(Service_FS, "Registering program %016" PRIX64 " with the SelfNCCH archive factory",
241 program_id);
242
243 if (ncch_data.find(program_id) != ncch_data.end()) {
244 LOG_WARNING(Service_FS, "Registering program %016" PRIX64
245 " with SelfNCCH will override existing mapping",
246 program_id);
247 }
248
249 NCCHData& data = ncch_data[program_id];
250
251 std::shared_ptr<FileUtil::IOFile> romfs_file_;
232 if (Loader::ResultStatus::Success == 252 if (Loader::ResultStatus::Success ==
233 app_loader.ReadRomFS(romfs_file, ncch_data.romfs_offset, ncch_data.romfs_size)) { 253 app_loader.ReadRomFS(romfs_file_, data.romfs_offset, data.romfs_size)) {
234 254
235 ncch_data.romfs_file = std::move(romfs_file); 255 data.romfs_file = std::move(romfs_file_);
236 } 256 }
237 257
238 std::shared_ptr<FileUtil::IOFile> update_romfs_file; 258 std::shared_ptr<FileUtil::IOFile> update_romfs_file;
239 if (Loader::ResultStatus::Success == 259 if (Loader::ResultStatus::Success ==
240 app_loader.ReadUpdateRomFS(update_romfs_file, ncch_data.update_romfs_offset, 260 app_loader.ReadUpdateRomFS(update_romfs_file, data.update_romfs_offset,
241 ncch_data.update_romfs_size)) { 261 data.update_romfs_size)) {
242 262
243 ncch_data.update_romfs_file = std::move(update_romfs_file); 263 data.update_romfs_file = std::move(update_romfs_file);
244 } 264 }
245 265
246 std::vector<u8> buffer; 266 std::vector<u8> buffer;
247 267
248 if (Loader::ResultStatus::Success == app_loader.ReadIcon(buffer)) 268 if (Loader::ResultStatus::Success == app_loader.ReadIcon(buffer))
249 ncch_data.icon = std::make_shared<std::vector<u8>>(std::move(buffer)); 269 data.icon = std::make_shared<std::vector<u8>>(std::move(buffer));
250 270
251 buffer.clear(); 271 buffer.clear();
252 if (Loader::ResultStatus::Success == app_loader.ReadLogo(buffer)) 272 if (Loader::ResultStatus::Success == app_loader.ReadLogo(buffer))
253 ncch_data.logo = std::make_shared<std::vector<u8>>(std::move(buffer)); 273 data.logo = std::make_shared<std::vector<u8>>(std::move(buffer));
254 274
255 buffer.clear(); 275 buffer.clear();
256 if (Loader::ResultStatus::Success == app_loader.ReadBanner(buffer)) 276 if (Loader::ResultStatus::Success == app_loader.ReadBanner(buffer))
257 ncch_data.banner = std::make_shared<std::vector<u8>>(std::move(buffer)); 277 data.banner = std::make_shared<std::vector<u8>>(std::move(buffer));
258} 278}
259 279
260ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) { 280ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) {
261 auto archive = std::make_unique<SelfNCCHArchive>(ncch_data); 281 auto archive = std::make_unique<SelfNCCHArchive>(
282 ncch_data[Kernel::g_current_process->codeset->program_id]);
262 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 283 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
263} 284}
264 285
diff --git a/src/core/file_sys/archive_selfncch.h b/src/core/file_sys/archive_selfncch.h
index f1c659948..0d6d6766e 100644
--- a/src/core/file_sys/archive_selfncch.h
+++ b/src/core/file_sys/archive_selfncch.h
@@ -6,6 +6,7 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9#include <unordered_map>
9#include <vector> 10#include <vector>
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "core/file_sys/archive_backend.h" 12#include "core/file_sys/archive_backend.h"
@@ -33,7 +34,10 @@ struct NCCHData {
33/// File system interface to the SelfNCCH archive 34/// File system interface to the SelfNCCH archive
34class ArchiveFactory_SelfNCCH final : public ArchiveFactory { 35class ArchiveFactory_SelfNCCH final : public ArchiveFactory {
35public: 36public:
36 explicit ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader); 37 ArchiveFactory_SelfNCCH() = default;
38
39 /// Registers a loaded application so that we can open its SelfNCCH archive when requested.
40 void Register(Loader::AppLoader& app_loader);
37 41
38 std::string GetName() const override { 42 std::string GetName() const override {
39 return "SelfNCCH"; 43 return "SelfNCCH";
@@ -43,7 +47,8 @@ public:
43 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; 47 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
44 48
45private: 49private:
46 NCCHData ncch_data; 50 /// Mapping of ProgramId -> NCCHData
51 std::unordered_map<u64, NCCHData> ncch_data;
47}; 52};
48 53
49} // namespace FileSys 54} // namespace FileSys
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 033fbc9aa..4ccb3cd32 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -20,6 +20,7 @@
20#include "core/file_sys/archive_savedata.h" 20#include "core/file_sys/archive_savedata.h"
21#include "core/file_sys/archive_sdmc.h" 21#include "core/file_sys/archive_sdmc.h"
22#include "core/file_sys/archive_sdmcwriteonly.h" 22#include "core/file_sys/archive_sdmcwriteonly.h"
23#include "core/file_sys/archive_selfncch.h"
23#include "core/file_sys/archive_systemsavedata.h" 24#include "core/file_sys/archive_systemsavedata.h"
24#include "core/file_sys/directory_backend.h" 25#include "core/file_sys/directory_backend.h"
25#include "core/file_sys/errors.h" 26#include "core/file_sys/errors.h"
@@ -48,7 +49,7 @@ struct hash<Service::FS::ArchiveIdCode> {
48 return std::hash<Type>()(static_cast<Type>(id_code)); 49 return std::hash<Type>()(static_cast<Type>(id_code));
49 } 50 }
50}; 51};
51} 52} // namespace std
52 53
53static constexpr Kernel::Handle INVALID_HANDLE{}; 54static constexpr Kernel::Handle INVALID_HANDLE{};
54 55
@@ -564,6 +565,21 @@ void RegisterArchiveTypes() {
564 auto systemsavedata_factory = 565 auto systemsavedata_factory =
565 std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); 566 std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
566 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); 567 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
568
569 auto selfncch_factory = std::make_unique<FileSys::ArchiveFactory_SelfNCCH>();
570 RegisterArchiveType(std::move(selfncch_factory), ArchiveIdCode::SelfNCCH);
571}
572
573void RegisterSelfNCCH(Loader::AppLoader& app_loader) {
574 auto itr = id_code_map.find(ArchiveIdCode::SelfNCCH);
575 if (itr == id_code_map.end()) {
576 LOG_ERROR(Service_FS,
577 "Could not register a new NCCH because the SelfNCCH archive hasn't been created");
578 return;
579 }
580
581 auto* factory = static_cast<FileSys::ArchiveFactory_SelfNCCH*>(itr->second.get());
582 factory->Register(app_loader);
567} 583}
568 584
569void UnregisterArchiveTypes() { 585void UnregisterArchiveTypes() {
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index 3a3371c88..e3c8fc2ef 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -21,6 +21,10 @@ static constexpr char SYSTEM_ID[]{"00000000000000000000000000000000"};
21/// The scrambled SD card CID, also known as ID1 21/// The scrambled SD card CID, also known as ID1
22static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"}; 22static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"};
23 23
24namespace Loader {
25class AppLoader;
26}
27
24namespace Service { 28namespace Service {
25namespace FS { 29namespace FS {
26 30
@@ -259,6 +263,9 @@ void ArchiveInit();
259/// Shutdown archives 263/// Shutdown archives
260void ArchiveShutdown(); 264void ArchiveShutdown();
261 265
266/// Registers a new NCCH file with the SelfNCCH archive factory
267void RegisterSelfNCCH(Loader::AppLoader& app_loader);
268
262/// Register all archive types 269/// Register all archive types
263void RegisterArchiveTypes(); 270void RegisterArchiveTypes();
264 271
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index a03515e6e..5ad5c5287 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -278,8 +278,7 @@ ResultStatus AppLoader_THREEDSX::Load() {
278 278
279 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 279 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
280 280
281 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this), 281 Service::FS::RegisterSelfNCCH(*this);
282 Service::FS::ArchiveIdCode::SelfNCCH);
283 282
284 is_loaded = true; 283 is_loaded = true;
285 return ResultStatus::Success; 284 return ResultStatus::Success;
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index c46d7cfc6..5107135f9 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -187,8 +187,7 @@ ResultStatus AppLoader_NCCH::Load() {
187 if (ResultStatus::Success != result) 187 if (ResultStatus::Success != result)
188 return result; 188 return result;
189 189
190 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this), 190 Service::FS::RegisterSelfNCCH(*this);
191 Service::FS::ArchiveIdCode::SelfNCCH);
192 191
193 ParseRegionLockoutInfo(); 192 ParseRegionLockoutInfo();
194 193