summaryrefslogtreecommitdiff
path: root/src/core/file_sys
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2017-09-23 20:32:18 -0500
committerSubv <subv2112@gmail.com>2017-09-25 09:45:02 -0500
commit774e7deae8655a6f09530770c56ae2e75d55309b (patch)
tree897ebb18a3cff721f402d0be73559f4694d4b1d8 /src/core/file_sys
parentd881dee818e7e59b72cb11cea634eb70bdcd3d35 (diff)
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 'src/core/file_sys')
-rw-r--r--src/core/file_sys/archive_selfncch.cpp43
-rw-r--r--src/core/file_sys/archive_selfncch.h9
2 files changed, 39 insertions, 13 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 @@
// Refer to the license.txt file included.
#include <array>
+#include <cinttypes>
#include "common/common_types.h"
#include "common/logging/log.h"
#include "common/swap.h"
#include "core/file_sys/archive_selfncch.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/ivfc_archive.h"
+#include "core/hle/kernel/process.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// FileSys namespace
@@ -227,38 +229,57 @@ private:
NCCHData ncch_data;
};
-ArchiveFactory_SelfNCCH::ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader) {
- std::shared_ptr<FileUtil::IOFile> romfs_file;
+void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) {
+ u64 program_id = 0;
+ if (app_loader.ReadProgramId(program_id) != Loader::ResultStatus::Success) {
+ LOG_WARNING(
+ Service_FS,
+ "Could not read program id when registering with SelfNCCH, this might be a 3dsx file");
+ }
+
+ LOG_DEBUG(Service_FS, "Registering program %016" PRIX64 " with the SelfNCCH archive factory",
+ program_id);
+
+ if (ncch_data.find(program_id) != ncch_data.end()) {
+ LOG_WARNING(Service_FS, "Registering program %016" PRIX64
+ " with SelfNCCH will override existing mapping",
+ program_id);
+ }
+
+ NCCHData& data = ncch_data[program_id];
+
+ std::shared_ptr<FileUtil::IOFile> romfs_file_;
if (Loader::ResultStatus::Success ==
- app_loader.ReadRomFS(romfs_file, ncch_data.romfs_offset, ncch_data.romfs_size)) {
+ app_loader.ReadRomFS(romfs_file_, data.romfs_offset, data.romfs_size)) {
- ncch_data.romfs_file = std::move(romfs_file);
+ data.romfs_file = std::move(romfs_file_);
}
std::shared_ptr<FileUtil::IOFile> update_romfs_file;
if (Loader::ResultStatus::Success ==
- app_loader.ReadUpdateRomFS(update_romfs_file, ncch_data.update_romfs_offset,
- ncch_data.update_romfs_size)) {
+ app_loader.ReadUpdateRomFS(update_romfs_file, data.update_romfs_offset,
+ data.update_romfs_size)) {
- ncch_data.update_romfs_file = std::move(update_romfs_file);
+ data.update_romfs_file = std::move(update_romfs_file);
}
std::vector<u8> buffer;
if (Loader::ResultStatus::Success == app_loader.ReadIcon(buffer))
- ncch_data.icon = std::make_shared<std::vector<u8>>(std::move(buffer));
+ data.icon = std::make_shared<std::vector<u8>>(std::move(buffer));
buffer.clear();
if (Loader::ResultStatus::Success == app_loader.ReadLogo(buffer))
- ncch_data.logo = std::make_shared<std::vector<u8>>(std::move(buffer));
+ data.logo = std::make_shared<std::vector<u8>>(std::move(buffer));
buffer.clear();
if (Loader::ResultStatus::Success == app_loader.ReadBanner(buffer))
- ncch_data.banner = std::make_shared<std::vector<u8>>(std::move(buffer));
+ data.banner = std::make_shared<std::vector<u8>>(std::move(buffer));
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) {
- auto archive = std::make_unique<SelfNCCHArchive>(ncch_data);
+ auto archive = std::make_unique<SelfNCCHArchive>(
+ ncch_data[Kernel::g_current_process->codeset->program_id]);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
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 @@
#include <memory>
#include <string>
+#include <unordered_map>
#include <vector>
#include "common/common_types.h"
#include "core/file_sys/archive_backend.h"
@@ -33,7 +34,10 @@ struct NCCHData {
/// File system interface to the SelfNCCH archive
class ArchiveFactory_SelfNCCH final : public ArchiveFactory {
public:
- explicit ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader);
+ ArchiveFactory_SelfNCCH() = default;
+
+ /// Registers a loaded application so that we can open its SelfNCCH archive when requested.
+ void Register(Loader::AppLoader& app_loader);
std::string GetName() const override {
return "SelfNCCH";
@@ -43,7 +47,8 @@ public:
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
private:
- NCCHData ncch_data;
+ /// Mapping of ProgramId -> NCCHData
+ std::unordered_map<u64, NCCHData> ncch_data;
};
} // namespace FileSys