diff options
| author | 2023-08-26 00:11:40 -0400 | |
|---|---|---|
| committer | 2023-08-28 21:03:21 -0400 | |
| commit | f260c74beb4af482f90cdf4e54dfecb90d8c6074 (patch) | |
| tree | dbcd5a0723fffc1e1431ce1df9f41a02ad21f8f4 | |
| parent | Merge pull request #11390 from FearlessTobi/hwopus-multi (diff) | |
| download | yuzu-f260c74beb4af482f90cdf4e54dfecb90d8c6074.tar.gz yuzu-f260c74beb4af482f90cdf4e54dfecb90d8c6074.tar.xz yuzu-f260c74beb4af482f90cdf4e54dfecb90d8c6074.zip | |
qt: fix romfs dumping for multiprogram applications
Diffstat (limited to '')
| -rw-r--r-- | src/yuzu/main.cpp | 113 | ||||
| -rw-r--r-- | src/yuzu/main.h | 3 |
2 files changed, 65 insertions, 51 deletions
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 33c9fd0af..81dfbca22 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2573,50 +2573,41 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 2573 | return; | 2573 | return; |
| 2574 | } | 2574 | } |
| 2575 | 2575 | ||
| 2576 | FileSys::VirtualFile base_romfs; | 2576 | FileSys::VirtualFile packed_update_raw{}; |
| 2577 | if (loader->ReadRomFS(base_romfs) != Loader::ResultStatus::Success) { | 2577 | loader->ReadUpdateRaw(packed_update_raw); |
| 2578 | failed(); | ||
| 2579 | return; | ||
| 2580 | } | ||
| 2581 | 2578 | ||
| 2582 | const auto& installed = system->GetContentProvider(); | 2579 | const auto& installed = system->GetContentProvider(); |
| 2583 | const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id); | ||
| 2584 | 2580 | ||
| 2585 | if (!romfs_title_id) { | 2581 | u64 title_id{}; |
| 2582 | u8 raw_type{}; | ||
| 2583 | if (!SelectRomFSDumpTarget(installed, program_id, &title_id, &raw_type)) { | ||
| 2586 | failed(); | 2584 | failed(); |
| 2587 | return; | 2585 | return; |
| 2588 | } | 2586 | } |
| 2589 | 2587 | ||
| 2590 | const auto type = *romfs_title_id == program_id ? FileSys::ContentRecordType::Program | 2588 | const auto type = static_cast<FileSys::ContentRecordType>(raw_type); |
| 2591 | : FileSys::ContentRecordType::Data; | 2589 | const auto base_nca = installed.GetEntry(title_id, type); |
| 2592 | const auto base_nca = installed.GetEntry(*romfs_title_id, type); | ||
| 2593 | if (!base_nca) { | 2590 | if (!base_nca) { |
| 2594 | failed(); | 2591 | failed(); |
| 2595 | return; | 2592 | return; |
| 2596 | } | 2593 | } |
| 2597 | 2594 | ||
| 2595 | const auto base_romfs = base_nca->GetRomFS(); | ||
| 2596 | if (!base_romfs) { | ||
| 2597 | failed(); | ||
| 2598 | return; | ||
| 2599 | } | ||
| 2600 | |||
| 2598 | const auto dump_dir = | 2601 | const auto dump_dir = |
| 2599 | target == DumpRomFSTarget::Normal | 2602 | target == DumpRomFSTarget::Normal |
| 2600 | ? Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir) | 2603 | ? Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir) |
| 2601 | : Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "atmosphere" / "contents"; | 2604 | : Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "atmosphere" / "contents"; |
| 2602 | const auto romfs_dir = fmt::format("{:016X}/romfs", *romfs_title_id); | 2605 | const auto romfs_dir = fmt::format("{:016X}/romfs", title_id); |
| 2603 | 2606 | ||
| 2604 | const auto path = Common::FS::PathToUTF8String(dump_dir / romfs_dir); | 2607 | const auto path = Common::FS::PathToUTF8String(dump_dir / romfs_dir); |
| 2605 | 2608 | ||
| 2606 | FileSys::VirtualFile romfs; | 2609 | const FileSys::PatchManager pm{title_id, system->GetFileSystemController(), installed}; |
| 2607 | 2610 | auto romfs = pm.PatchRomFS(base_nca.get(), base_romfs, type, packed_update_raw, false); | |
| 2608 | if (*romfs_title_id == program_id) { | ||
| 2609 | const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), installed}; | ||
| 2610 | romfs = pm.PatchRomFS(base_nca.get(), base_romfs, type, nullptr, false); | ||
| 2611 | } else { | ||
| 2612 | romfs = installed.GetEntry(*romfs_title_id, type)->GetRomFS(); | ||
| 2613 | } | ||
| 2614 | |||
| 2615 | const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full); | ||
| 2616 | if (extracted == nullptr) { | ||
| 2617 | failed(); | ||
| 2618 | return; | ||
| 2619 | } | ||
| 2620 | 2611 | ||
| 2621 | const auto out = VfsFilesystemCreateDirectoryWrapper(vfs, path, FileSys::Mode::ReadWrite); | 2612 | const auto out = VfsFilesystemCreateDirectoryWrapper(vfs, path, FileSys::Mode::ReadWrite); |
| 2622 | 2613 | ||
| @@ -2640,6 +2631,12 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 2640 | return; | 2631 | return; |
| 2641 | } | 2632 | } |
| 2642 | 2633 | ||
| 2634 | const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full); | ||
| 2635 | if (extracted == nullptr) { | ||
| 2636 | failed(); | ||
| 2637 | return; | ||
| 2638 | } | ||
| 2639 | |||
| 2643 | const auto full = res == selections.constFirst(); | 2640 | const auto full = res == selections.constFirst(); |
| 2644 | const auto entry_size = CalculateRomFSEntrySize(extracted, full); | 2641 | const auto entry_size = CalculateRomFSEntrySize(extracted, full); |
| 2645 | 2642 | ||
| @@ -4350,28 +4347,41 @@ bool GMainWindow::CheckSystemArchiveDecryption() { | |||
| 4350 | return mii_nca->GetRomFS().get() != nullptr; | 4347 | return mii_nca->GetRomFS().get() != nullptr; |
| 4351 | } | 4348 | } |
| 4352 | 4349 | ||
| 4353 | std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, | 4350 | bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, |
| 4354 | u64 program_id) { | 4351 | u64* selected_title_id, u8* selected_content_record_type) { |
| 4355 | const auto dlc_entries = | 4352 | using ContentInfo = std::pair<FileSys::TitleType, FileSys::ContentRecordType>; |
| 4356 | installed.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); | 4353 | boost::container::flat_map<u64, ContentInfo> available_title_ids; |
| 4357 | std::vector<FileSys::ContentProviderEntry> dlc_match; | 4354 | |
| 4358 | dlc_match.reserve(dlc_entries.size()); | 4355 | const auto RetrieveEntries = [&](FileSys::TitleType title_type, |
| 4359 | std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), | 4356 | FileSys::ContentRecordType record_type) { |
| 4360 | [&program_id, &installed](const FileSys::ContentProviderEntry& entry) { | 4357 | const auto entries = installed.ListEntriesFilter(title_type, record_type); |
| 4361 | return FileSys::GetBaseTitleID(entry.title_id) == program_id && | 4358 | for (const auto& entry : entries) { |
| 4362 | installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success; | 4359 | if (FileSys::GetBaseTitleID(entry.title_id) == program_id && |
| 4363 | }); | 4360 | installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success) { |
| 4364 | 4361 | available_title_ids[entry.title_id] = {title_type, record_type}; | |
| 4365 | std::vector<u64> romfs_tids; | 4362 | } |
| 4366 | romfs_tids.push_back(program_id); | 4363 | } |
| 4367 | for (const auto& entry : dlc_match) { | 4364 | }; |
| 4368 | romfs_tids.push_back(entry.title_id); | 4365 | |
| 4369 | } | 4366 | RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::Program); |
| 4370 | 4367 | RetrieveEntries(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); | |
| 4371 | if (romfs_tids.size() > 1) { | 4368 | |
| 4372 | QStringList list{QStringLiteral("Base")}; | 4369 | if (available_title_ids.empty()) { |
| 4373 | for (std::size_t i = 1; i < romfs_tids.size(); ++i) { | 4370 | return false; |
| 4374 | list.push_back(QStringLiteral("DLC %1").arg(romfs_tids[i] & 0x7FF)); | 4371 | } |
| 4372 | |||
| 4373 | size_t title_index = 0; | ||
| 4374 | |||
| 4375 | if (available_title_ids.size() > 1) { | ||
| 4376 | QStringList list; | ||
| 4377 | for (auto& [title_id, content_info] : available_title_ids) { | ||
| 4378 | const auto hex_title_id = QString::fromStdString(fmt::format("{:X}", title_id)); | ||
| 4379 | if (content_info.first == FileSys::TitleType::Application) { | ||
| 4380 | list.push_back(QStringLiteral("Application [%1]").arg(hex_title_id)); | ||
| 4381 | } else { | ||
| 4382 | list.push_back( | ||
| 4383 | QStringLiteral("DLC %1 [%2]").arg(title_id & 0x7FF).arg(hex_title_id)); | ||
| 4384 | } | ||
| 4375 | } | 4385 | } |
| 4376 | 4386 | ||
| 4377 | bool ok; | 4387 | bool ok; |
| @@ -4379,13 +4389,16 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv | |||
| 4379 | this, tr("Select RomFS Dump Target"), | 4389 | this, tr("Select RomFS Dump Target"), |
| 4380 | tr("Please select which RomFS you would like to dump."), list, 0, false, &ok); | 4390 | tr("Please select which RomFS you would like to dump."), list, 0, false, &ok); |
| 4381 | if (!ok) { | 4391 | if (!ok) { |
| 4382 | return {}; | 4392 | return false; |
| 4383 | } | 4393 | } |
| 4384 | 4394 | ||
| 4385 | return romfs_tids[list.indexOf(res)]; | 4395 | title_index = list.indexOf(res); |
| 4386 | } | 4396 | } |
| 4387 | 4397 | ||
| 4388 | return program_id; | 4398 | const auto selected_info = available_title_ids.nth(title_index); |
| 4399 | *selected_title_id = selected_info->first; | ||
| 4400 | *selected_content_record_type = static_cast<u8>(selected_info->second.second); | ||
| 4401 | return true; | ||
| 4389 | } | 4402 | } |
| 4390 | 4403 | ||
| 4391 | bool GMainWindow::ConfirmClose() { | 4404 | bool GMainWindow::ConfirmClose() { |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 1b7055122..668dbc3b1 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -375,7 +375,8 @@ private: | |||
| 375 | void RemoveAllTransferableShaderCaches(u64 program_id); | 375 | void RemoveAllTransferableShaderCaches(u64 program_id); |
| 376 | void RemoveCustomConfiguration(u64 program_id, const std::string& game_path); | 376 | void RemoveCustomConfiguration(u64 program_id, const std::string& game_path); |
| 377 | void RemoveCacheStorage(u64 program_id); | 377 | void RemoveCacheStorage(u64 program_id); |
| 378 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); | 378 | bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, |
| 379 | u64* selected_title_id, u8* selected_content_record_type); | ||
| 379 | InstallResult InstallNSPXCI(const QString& filename); | 380 | InstallResult InstallNSPXCI(const QString& filename); |
| 380 | InstallResult InstallNCA(const QString& filename); | 381 | InstallResult InstallNCA(const QString& filename); |
| 381 | void MigrateConfigFiles(); | 382 | void MigrateConfigFiles(); |