Merge pull request #2947 from Subv/selfncch_factory
HLE/Archives: Allow multiple loaded applications to access their SelfNCCH archive independently.
This commit is contained in:
commit
fd30d48ceb
|
@ -3,12 +3,14 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cinttypes>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/file_sys/archive_selfncch.h"
|
#include "core/file_sys/archive_selfncch.h"
|
||||||
#include "core/file_sys/errors.h"
|
#include "core/file_sys/errors.h"
|
||||||
#include "core/file_sys/ivfc_archive.h"
|
#include "core/file_sys/ivfc_archive.h"
|
||||||
|
#include "core/hle/kernel/process.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// FileSys namespace
|
// FileSys namespace
|
||||||
|
@ -227,38 +229,57 @@ private:
|
||||||
NCCHData ncch_data;
|
NCCHData ncch_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
ArchiveFactory_SelfNCCH::ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader) {
|
void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) {
|
||||||
std::shared_ptr<FileUtil::IOFile> romfs_file;
|
u64 program_id = 0;
|
||||||
if (Loader::ResultStatus::Success ==
|
if (app_loader.ReadProgramId(program_id) != Loader::ResultStatus::Success) {
|
||||||
app_loader.ReadRomFS(romfs_file, ncch_data.romfs_offset, ncch_data.romfs_size)) {
|
LOG_WARNING(
|
||||||
|
Service_FS,
|
||||||
|
"Could not read program id when registering with SelfNCCH, this might be a 3dsx file");
|
||||||
|
}
|
||||||
|
|
||||||
ncch_data.romfs_file = std::move(romfs_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_, data.romfs_offset, data.romfs_size)) {
|
||||||
|
|
||||||
|
data.romfs_file = std::move(romfs_file_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<FileUtil::IOFile> update_romfs_file;
|
std::shared_ptr<FileUtil::IOFile> update_romfs_file;
|
||||||
if (Loader::ResultStatus::Success ==
|
if (Loader::ResultStatus::Success ==
|
||||||
app_loader.ReadUpdateRomFS(update_romfs_file, ncch_data.update_romfs_offset,
|
app_loader.ReadUpdateRomFS(update_romfs_file, data.update_romfs_offset,
|
||||||
ncch_data.update_romfs_size)) {
|
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;
|
std::vector<u8> buffer;
|
||||||
|
|
||||||
if (Loader::ResultStatus::Success == app_loader.ReadIcon(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();
|
buffer.clear();
|
||||||
if (Loader::ResultStatus::Success == app_loader.ReadLogo(buffer))
|
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();
|
buffer.clear();
|
||||||
if (Loader::ResultStatus::Success == app_loader.ReadBanner(buffer))
|
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) {
|
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));
|
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/archive_backend.h"
|
#include "core/file_sys/archive_backend.h"
|
||||||
|
@ -33,7 +34,10 @@ struct NCCHData {
|
||||||
/// File system interface to the SelfNCCH archive
|
/// File system interface to the SelfNCCH archive
|
||||||
class ArchiveFactory_SelfNCCH final : public ArchiveFactory {
|
class ArchiveFactory_SelfNCCH final : public ArchiveFactory {
|
||||||
public:
|
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 {
|
std::string GetName() const override {
|
||||||
return "SelfNCCH";
|
return "SelfNCCH";
|
||||||
|
@ -43,7 +47,8 @@ public:
|
||||||
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
|
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NCCHData ncch_data;
|
/// Mapping of ProgramId -> NCCHData
|
||||||
|
std::unordered_map<u64, NCCHData> ncch_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "core/file_sys/archive_savedata.h"
|
#include "core/file_sys/archive_savedata.h"
|
||||||
#include "core/file_sys/archive_sdmc.h"
|
#include "core/file_sys/archive_sdmc.h"
|
||||||
#include "core/file_sys/archive_sdmcwriteonly.h"
|
#include "core/file_sys/archive_sdmcwriteonly.h"
|
||||||
|
#include "core/file_sys/archive_selfncch.h"
|
||||||
#include "core/file_sys/archive_systemsavedata.h"
|
#include "core/file_sys/archive_systemsavedata.h"
|
||||||
#include "core/file_sys/directory_backend.h"
|
#include "core/file_sys/directory_backend.h"
|
||||||
#include "core/file_sys/errors.h"
|
#include "core/file_sys/errors.h"
|
||||||
|
@ -48,7 +49,7 @@ struct hash<Service::FS::ArchiveIdCode> {
|
||||||
return std::hash<Type>()(static_cast<Type>(id_code));
|
return std::hash<Type>()(static_cast<Type>(id_code));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace std
|
||||||
|
|
||||||
static constexpr Kernel::Handle INVALID_HANDLE{};
|
static constexpr Kernel::Handle INVALID_HANDLE{};
|
||||||
|
|
||||||
|
@ -564,6 +565,21 @@ void RegisterArchiveTypes() {
|
||||||
auto systemsavedata_factory =
|
auto systemsavedata_factory =
|
||||||
std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
|
std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
|
||||||
RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
|
RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
|
||||||
|
|
||||||
|
auto selfncch_factory = std::make_unique<FileSys::ArchiveFactory_SelfNCCH>();
|
||||||
|
RegisterArchiveType(std::move(selfncch_factory), ArchiveIdCode::SelfNCCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterSelfNCCH(Loader::AppLoader& app_loader) {
|
||||||
|
auto itr = id_code_map.find(ArchiveIdCode::SelfNCCH);
|
||||||
|
if (itr == id_code_map.end()) {
|
||||||
|
LOG_ERROR(Service_FS,
|
||||||
|
"Could not register a new NCCH because the SelfNCCH archive hasn't been created");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* factory = static_cast<FileSys::ArchiveFactory_SelfNCCH*>(itr->second.get());
|
||||||
|
factory->Register(app_loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnregisterArchiveTypes() {
|
void UnregisterArchiveTypes() {
|
||||||
|
|
|
@ -21,6 +21,10 @@ static constexpr char SYSTEM_ID[]{"00000000000000000000000000000000"};
|
||||||
/// The scrambled SD card CID, also known as ID1
|
/// The scrambled SD card CID, also known as ID1
|
||||||
static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"};
|
static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"};
|
||||||
|
|
||||||
|
namespace Loader {
|
||||||
|
class AppLoader;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace FS {
|
namespace FS {
|
||||||
|
|
||||||
|
@ -259,6 +263,9 @@ void ArchiveInit();
|
||||||
/// Shutdown archives
|
/// Shutdown archives
|
||||||
void ArchiveShutdown();
|
void ArchiveShutdown();
|
||||||
|
|
||||||
|
/// Registers a new NCCH file with the SelfNCCH archive factory
|
||||||
|
void RegisterSelfNCCH(Loader::AppLoader& app_loader);
|
||||||
|
|
||||||
/// Register all archive types
|
/// Register all archive types
|
||||||
void RegisterArchiveTypes();
|
void RegisterArchiveTypes();
|
||||||
|
|
||||||
|
|
|
@ -278,8 +278,7 @@ ResultStatus AppLoader_THREEDSX::Load() {
|
||||||
|
|
||||||
Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
|
Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
|
||||||
|
|
||||||
Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this),
|
Service::FS::RegisterSelfNCCH(*this);
|
||||||
Service::FS::ArchiveIdCode::SelfNCCH);
|
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
return ResultStatus::Success;
|
return ResultStatus::Success;
|
||||||
|
|
|
@ -187,8 +187,7 @@ ResultStatus AppLoader_NCCH::Load() {
|
||||||
if (ResultStatus::Success != result)
|
if (ResultStatus::Success != result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this),
|
Service::FS::RegisterSelfNCCH(*this);
|
||||||
Service::FS::ArchiveIdCode::SelfNCCH);
|
|
||||||
|
|
||||||
ParseRegionLockoutInfo();
|
ParseRegionLockoutInfo();
|
||||||
|
|
||||||
|
|
Reference in New Issue