Add system archives import

This commit is contained in:
zhupengfei
2019-10-02 16:00:32 +08:00
parent 9f9d1d85db
commit 5d675d605a
7 changed files with 204 additions and 14 deletions
+75
View File
@@ -72,6 +72,8 @@ bool SDMCImporter::ImportContent(const ContentSpecifier& specifier,
return ImportSavegame(specifier.id, callback);
case ContentType::Extdata:
return ImportExtdata(specifier.id, callback);
case ContentType::SystemArchive:
return ImportSystemArchive(specifier.id, callback);
case ContentType::Sysdata:
return ImportSysdata(specifier.id, callback);
default:
@@ -128,6 +130,45 @@ bool SDMCImporter::ImportExtdata(u64 id, [[maybe_unused]] const ProgressCallback
"Nintendo 3DS/00000000000000000000000000000000/00000000000000000000000000000000/" + path);
}
bool SDMCImporter::ImportSystemArchive(u64 id, [[maybe_unused]] const ProgressCallback& callback) {
const auto path = fmt::format("{}{:08x}/{:08x}.app", config.system_archives_path, (id >> 32),
(id & 0xFFFFFFFF));
FileUtil::IOFile file(path, "rb");
if (!file) {
LOG_ERROR(Core, "Could not open {}", path);
return false;
}
std::vector<u8> data(file.GetSize());
if (file.ReadBytes(data.data(), data.size()) != data.size()) {
LOG_ERROR(Core, "Failed to read from {}", path);
return false;
}
const auto& romfs = LoadSharedRomFS(data);
const auto target_path = fmt::format(
"{}00000000000000000000000000000000/title/{:08x}/{:08x}/content/00000000.app.romfs",
FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), (id >> 32), (id & 0xFFFFFFFF));
if (!FileUtil::CreateFullPath(target_path)) {
LOG_ERROR(Core, "Could not create path {}", target_path);
return false;
}
FileUtil::IOFile target(target_path, "wb");
if (!target) {
LOG_ERROR(Core, "Could not open {}", target_path);
return false;
}
if (target.WriteBytes(romfs.data(), romfs.size()) != romfs.size()) {
LOG_ERROR(Core, "Failed to write to {}", target_path);
return false;
}
return true;
}
bool SDMCImporter::ImportSysdata(u64 id, [[maybe_unused]] const ProgressCallback& callback) {
switch (id) {
case 0: { // boot9.bin
@@ -207,6 +248,7 @@ std::vector<ContentSpecifier> SDMCImporter::ListContent() const {
std::vector<ContentSpecifier> content_list;
ListTitle(content_list);
ListExtdata(content_list);
ListSystemArchive(content_list);
ListSysdata(content_list);
return content_list;
}
@@ -361,6 +403,30 @@ void SDMCImporter::ListExtdata(std::vector<ContentSpecifier>& out) const {
});
}
void SDMCImporter::ListSystemArchive(std::vector<ContentSpecifier>& out) const {
constexpr std::array<std::pair<u64, const char*>, 8> SystemArchives{{
{0x0004009b'00010202, "Mii Data"},
{0x0004009b'00010402, "Region Manifest"},
{0x0004009b'00014002, "Shared Font (JPN/EUR/USA)"},
{0x0004009b'00014102, "Shared Font (CHN)"},
{0x0004009b'00014202, "Shared Font (KOR)"},
{0x0004009b'00014302, "Shared Font (TWN)"},
{0x000400db'00010302, "Bad word list"},
}};
for (const auto& [id, name] : SystemArchives) {
const auto path = fmt::format("{}{:08x}/{:08x}.app", config.system_archives_path,
(id >> 32), (id & 0xFFFFFFFF));
if (FileUtil::Exists(path)) {
const auto target_path = fmt::format(
"{}00000000000000000000000000000000/title/{:08x}/{:08x}/content/",
FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), (id >> 32), (id & 0xFFFFFFFF));
out.push_back({ContentType::SystemArchive, id, FileUtil::Exists(target_path),
FileUtil::GetSize(path), name});
}
}
}
void SDMCImporter::ListSysdata(std::vector<ContentSpecifier>& out) const {
#define CHECK_CONTENT(id, var_path, citra_path, display_name) \
if (!var_path.empty()) { \
@@ -418,6 +484,8 @@ void SDMCImporter::DeleteContent(const ContentSpecifier& specifier) {
return DeleteSavegame(specifier.id);
case ContentType::Extdata:
return DeleteExtdata(specifier.id);
case ContentType::SystemArchive:
return DeleteSystemArchive(specifier.id);
case ContentType::Sysdata:
return DeleteSysdata(specifier.id);
default:
@@ -449,6 +517,12 @@ void SDMCImporter::DeleteExtdata(u64 id) const {
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), (id >> 32), (id & 0xFFFFFFFF)));
}
void SDMCImporter::DeleteSystemArchive(u64 id) const {
FileUtil::DeleteDirRecursively(fmt::format(
"{}00000000000000000000000000000000/title/{:08x}/{:08x}/content/",
FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), (id >> 32), (id & 0xFFFFFFFF)));
}
void SDMCImporter::DeleteSysdata(u64 id) const {
switch (id) {
case 0: { // boot9.bin
@@ -501,6 +575,7 @@ std::vector<Config> LoadPresetConfig(std::string mount_point) {
LOAD_DATA(safe_mode_firm_path, "firm/");
LOAD_DATA(seed_db_path, SEED_DB);
LOAD_DATA(secret_sector_path, SECRET_SECTOR);
LOAD_DATA(system_archives_path, "sysarchives/");
#undef LOAD_DATA
}