mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #5088 from zhaowenlan1779/layered-fs
core/file_sys: LayeredFS support
This commit is contained in:
		
						commit
						5b54a99f96
					
				
					 16 changed files with 950 additions and 31 deletions
				
			
		|  | @ -468,6 +468,8 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra | |||
|     QAction* open_texture_dump_location = context_menu.addAction(tr("Open Texture Dump Location")); | ||||
|     QAction* open_texture_load_location = | ||||
|         context_menu.addAction(tr("Open Custom Texture Location")); | ||||
|     QAction* open_mods_location = context_menu.addAction(tr("Open Mods Location")); | ||||
|     QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS")); | ||||
|     QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); | ||||
| 
 | ||||
|     const bool is_application = | ||||
|  | @ -497,6 +499,8 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra | |||
| 
 | ||||
|     open_texture_dump_location->setVisible(is_application); | ||||
|     open_texture_load_location->setVisible(is_application); | ||||
|     open_mods_location->setVisible(is_application); | ||||
|     dump_romfs->setVisible(is_application); | ||||
| 
 | ||||
|     navigate_to_gamedb_entry->setVisible(it != compatibility_list.end()); | ||||
| 
 | ||||
|  | @ -526,6 +530,15 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra | |||
|             emit OpenFolderRequested(program_id, GameListOpenTarget::TEXTURE_LOAD); | ||||
|         } | ||||
|     }); | ||||
|     connect(open_mods_location, &QAction::triggered, [this, program_id] { | ||||
|         if (FileUtil::CreateFullPath(fmt::format("{}mods/{:016X}/", | ||||
|                                                  FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), | ||||
|                                                  program_id))) { | ||||
|             emit OpenFolderRequested(program_id, GameListOpenTarget::MODS); | ||||
|         } | ||||
|     }); | ||||
|     connect(dump_romfs, &QAction::triggered, | ||||
|             [this, path, program_id] { emit DumpRomFSRequested(path, program_id); }); | ||||
|     connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() { | ||||
|         emit NavigateToGamedbEntryRequested(program_id, compatibility_list); | ||||
|     }); | ||||
|  |  | |||
|  | @ -35,7 +35,8 @@ enum class GameListOpenTarget { | |||
|     APPLICATION = 2, | ||||
|     UPDATE_DATA = 3, | ||||
|     TEXTURE_DUMP = 4, | ||||
|     TEXTURE_LOAD = 5 | ||||
|     TEXTURE_LOAD = 5, | ||||
|     MODS = 6, | ||||
| }; | ||||
| 
 | ||||
| class GameList : public QWidget { | ||||
|  | @ -81,6 +82,7 @@ signals: | |||
|     void OpenFolderRequested(u64 program_id, GameListOpenTarget target); | ||||
|     void NavigateToGamedbEntryRequested(u64 program_id, | ||||
|                                         const CompatibilityList& compatibility_list); | ||||
|     void DumpRomFSRequested(QString game_path, u64 program_id); | ||||
|     void OpenDirectory(const QString& directory); | ||||
|     void AddDirectory(); | ||||
|     void ShowList(bool show); | ||||
|  |  | |||
|  | @ -568,6 +568,7 @@ void GMainWindow::ConnectWidgetEvents() { | |||
|     connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); | ||||
|     connect(game_list, &GameList::NavigateToGamedbEntryRequested, this, | ||||
|             &GMainWindow::OnGameListNavigateToGamedbEntry); | ||||
|     connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS); | ||||
|     connect(game_list, &GameList::AddDirectory, this, &GMainWindow::OnGameListAddDirectory); | ||||
|     connect(game_list_placeholder, &GameListPlaceholder::AddDirectory, this, | ||||
|             &GMainWindow::OnGameListAddDirectory); | ||||
|  | @ -1144,6 +1145,11 @@ void GMainWindow::OnGameListOpenFolder(u64 data_id, GameListOpenTarget target) { | |||
|         path = fmt::format("{}textures/{:016X}/", | ||||
|                            FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), data_id); | ||||
|         break; | ||||
|     case GameListOpenTarget::MODS: | ||||
|         open_target = "Mods"; | ||||
|         path = fmt::format("{}mods/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), | ||||
|                            data_id); | ||||
|         break; | ||||
|     default: | ||||
|         LOG_ERROR(Frontend, "Unexpected target {}", static_cast<int>(target)); | ||||
|         return; | ||||
|  | @ -1175,6 +1181,46 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id, | |||
|     QDesktopServices::openUrl(QUrl(QStringLiteral("https://citra-emu.org/game/") + directory)); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnGameListDumpRomFS(QString game_path, u64 program_id) { | ||||
|     auto* dialog = new QProgressDialog(tr("Dumping..."), tr("Cancel"), 0, 0, this); | ||||
|     dialog->setWindowModality(Qt::WindowModal); | ||||
|     dialog->setWindowFlags(dialog->windowFlags() & | ||||
|                            ~(Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)); | ||||
|     dialog->setCancelButton(nullptr); | ||||
|     dialog->setMinimumDuration(0); | ||||
|     dialog->setValue(0); | ||||
| 
 | ||||
|     const auto base_path = fmt::format( | ||||
|         "{}romfs/{:016X}", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), program_id); | ||||
|     const auto update_path = | ||||
|         fmt::format("{}romfs/{:016X}", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), | ||||
|                     program_id | 0x0004000e00000000); | ||||
|     using FutureWatcher = QFutureWatcher<std::pair<Loader::ResultStatus, Loader::ResultStatus>>; | ||||
|     auto* future_watcher = new FutureWatcher(this); | ||||
|     connect(future_watcher, &FutureWatcher::finished, | ||||
|             [this, program_id, dialog, base_path, update_path, future_watcher] { | ||||
|                 dialog->hide(); | ||||
|                 const auto& [base, update] = future_watcher->result(); | ||||
|                 if (base != Loader::ResultStatus::Success) { | ||||
|                     QMessageBox::critical( | ||||
|                         this, tr("Citra"), | ||||
|                         tr("Could not dump base RomFS.\nRefer to the log for details.")); | ||||
|                     return; | ||||
|                 } | ||||
|                 QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(base_path))); | ||||
|                 if (update == Loader::ResultStatus::Success) { | ||||
|                     QDesktopServices::openUrl( | ||||
|                         QUrl::fromLocalFile(QString::fromStdString(update_path))); | ||||
|                 } | ||||
|             }); | ||||
| 
 | ||||
|     auto future = QtConcurrent::run([game_path, base_path, update_path] { | ||||
|         std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(game_path.toStdString()); | ||||
|         return std::make_pair(loader->DumpRomFS(base_path), loader->DumpUpdateRomFS(update_path)); | ||||
|     }); | ||||
|     future_watcher->setFuture(future); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnGameListOpenDirectory(const QString& directory) { | ||||
|     QString path; | ||||
|     if (directory == QStringLiteral("INSTALLED")) { | ||||
|  |  | |||
|  | @ -169,6 +169,7 @@ private slots: | |||
|     void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target); | ||||
|     void OnGameListNavigateToGamedbEntry(u64 program_id, | ||||
|                                          const CompatibilityList& compatibility_list); | ||||
|     void OnGameListDumpRomFS(QString game_path, u64 program_id); | ||||
|     void OnGameListOpenDirectory(const QString& directory); | ||||
|     void OnGameListAddDirectory(); | ||||
|     void OnGameListShowList(bool show); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue