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:
Sebastian Valle 2017-09-25 18:24:12 -05:00 committed by GitHub
commit fd30d48ceb
6 changed files with 66 additions and 19 deletions

View file

@ -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;
if (Loader::ResultStatus::Success ==
app_loader.ReadRomFS(romfs_file, ncch_data.romfs_offset, ncch_data.romfs_size)) {
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");
}
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;
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));
}

View file

@ -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

View file

@ -20,6 +20,7 @@
#include "core/file_sys/archive_savedata.h"
#include "core/file_sys/archive_sdmc.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/directory_backend.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));
}
};
}
} // namespace std
static constexpr Kernel::Handle INVALID_HANDLE{};
@ -564,6 +565,21 @@ void RegisterArchiveTypes() {
auto systemsavedata_factory =
std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
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() {

View file

@ -21,6 +21,10 @@ static constexpr char SYSTEM_ID[]{"00000000000000000000000000000000"};
/// The scrambled SD card CID, also known as ID1
static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"};
namespace Loader {
class AppLoader;
}
namespace Service {
namespace FS {
@ -259,6 +263,9 @@ void ArchiveInit();
/// Shutdown archives
void ArchiveShutdown();
/// Registers a new NCCH file with the SelfNCCH archive factory
void RegisterSelfNCCH(Loader::AppLoader& app_loader);
/// Register all archive types
void RegisterArchiveTypes();

View file

@ -278,8 +278,7 @@ ResultStatus AppLoader_THREEDSX::Load() {
Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this),
Service::FS::ArchiveIdCode::SelfNCCH);
Service::FS::RegisterSelfNCCH(*this);
is_loaded = true;
return ResultStatus::Success;

View file

@ -187,8 +187,7 @@ ResultStatus AppLoader_NCCH::Load() {
if (ResultStatus::Success != result)
return result;
Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this),
Service::FS::ArchiveIdCode::SelfNCCH);
Service::FS::RegisterSelfNCCH(*this);
ParseRegionLockoutInfo();