diff options
Diffstat (limited to 'src/yuzu/main.cpp')
-rw-r--r-- | src/yuzu/main.cpp | 157 |
1 files changed, 92 insertions, 65 deletions
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 592993c36..a1b61d119 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -94,6 +94,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "core/perf_stats.h" #include "core/settings.h" #include "core/telemetry_session.h" +#include "input_common/main.h" #include "video_core/gpu.h" #include "video_core/shader_notify.h" #include "yuzu/about_dialog.h" @@ -177,8 +178,8 @@ static void InitializeLogging() { log_filter.ParseFilterString(Settings::values.log_filter); Log::SetGlobalFilter(log_filter); - const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); - FileUtil::CreateFullPath(log_dir); + const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); + Common::FS::CreateFullPath(log_dir); Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); #ifdef _WIN32 Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); @@ -186,9 +187,9 @@ static void InitializeLogging() { } GMainWindow::GMainWindow() - : config(new Config()), emu_thread(nullptr), - vfs(std::make_shared<FileSys::RealVfsFilesystem>()), - provider(std::make_unique<FileSys::ManualContentProvider>()) { + : input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, + config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()}, + provider{std::make_unique<FileSys::ManualContentProvider>()} { InitializeLogging(); LoadTranslation(); @@ -473,7 +474,7 @@ void GMainWindow::InitializeWidgets() { #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING ui.action_Report_Compatibility->setVisible(true); #endif - render_window = new GRenderWindow(this, emu_thread.get()); + render_window = new GRenderWindow(this, emu_thread.get(), input_subsystem); render_window->hide(); game_list = new GameList(vfs, provider.get(), this); @@ -894,6 +895,8 @@ void GMainWindow::ConnectMenuEvents() { connect(ui.action_Open_FAQ, &QAction::triggered, this, &GMainWindow::OnOpenFAQ); connect(ui.action_Restart, &QAction::triggered, this, [this] { BootGame(QString(game_path)); }); connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); + connect(ui.action_Configure_Current_Game, &QAction::triggered, this, + &GMainWindow::OnConfigurePerGame); // View connect(ui.action_Single_Window_Mode, &QAction::triggered, this, @@ -1039,7 +1042,7 @@ bool GMainWindow::LoadROM(const QString& filename) { } game_path = filename; - system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "Qt"); + system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt"); return true; } @@ -1121,7 +1124,7 @@ void GMainWindow::BootGame(const QString& filename) { title_name = metadata.first->GetApplicationName(); } if (res != Loader::ResultStatus::Success || title_name.empty()) { - title_name = FileUtil::GetFilename(filename.toStdString()); + title_name = Common::FS::GetFilename(filename.toStdString()); } LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); UpdateWindowTitle(title_name, title_version); @@ -1167,6 +1170,7 @@ void GMainWindow::ShutdownGame() { ui.action_Pause->setEnabled(false); ui.action_Stop->setEnabled(false); ui.action_Restart->setEnabled(false); + ui.action_Configure_Current_Game->setEnabled(false); ui.action_Report_Compatibility->setEnabled(false); ui.action_Load_Amiibo->setEnabled(false); ui.action_Capture_Screenshot->setEnabled(false); @@ -1239,27 +1243,36 @@ void GMainWindow::OnGameListLoadFile(QString game_path) { BootGame(game_path); } -void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path) { +void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, + const std::string& game_path) { std::string path; QString open_target; - const auto v_file = Core::GetGameFileFromPath(vfs, game_path); - const auto loader = Loader::GetLoader(v_file); - FileSys::NACP control{}; - u64 program_id{}; + const auto [user_save_size, device_save_size] = [this, &program_id, &game_path] { + FileSys::PatchManager pm{program_id}; + const auto control = pm.GetControlMetadata().first; + if (control != nullptr) { + return std::make_pair(control->GetDefaultNormalSaveSize(), + control->GetDeviceSaveDataSize()); + } else { + const auto file = Core::GetGameFileFromPath(vfs, game_path); + const auto loader = Loader::GetLoader(file); - loader->ReadControlData(control); - loader->ReadProgramId(program_id); + FileSys::NACP nacp{}; + loader->ReadControlData(nacp); + return std::make_pair(nacp.GetDefaultNormalSaveSize(), nacp.GetDeviceSaveDataSize()); + } + }(); - const bool has_user_save{control.GetDefaultNormalSaveSize() > 0}; - const bool has_device_save{control.GetDeviceSaveDataSize() > 0}; + const bool has_user_save{user_save_size > 0}; + const bool has_device_save{device_save_size > 0}; ASSERT_MSG(has_user_save != has_device_save, "Game uses both user and device savedata?"); switch (target) { case GameListOpenTarget::SaveData: { open_target = tr("Save Data"); - const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); + const std::string nand_dir = Common::FS::GetUserPath(Common::FS::UserPath::NANDDir); if (has_user_save) { // User save data @@ -1294,16 +1307,16 @@ void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::str FileSys::SaveDataType::SaveData, program_id, {}, 0); } - if (!FileUtil::Exists(path)) { - FileUtil::CreateFullPath(path); - FileUtil::CreateDir(path); + if (!Common::FS::Exists(path)) { + Common::FS::CreateFullPath(path); + Common::FS::CreateDir(path); } break; } case GameListOpenTarget::ModData: { open_target = tr("Mod Data"); - const auto load_dir = FileUtil::GetUserPath(FileUtil::UserPath::LoadDir); + const auto load_dir = Common::FS::GetUserPath(Common::FS::UserPath::LoadDir); path = fmt::format("{}{:016X}", load_dir, program_id); break; } @@ -1325,7 +1338,7 @@ void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::str void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { const QString shader_dir = - QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)); + QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ShaderDir)); const QString transferable_shader_cache_folder_path = shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable"); const QString transferable_shader_cache_file_path = @@ -1428,8 +1441,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT RemoveAddOnContent(program_id, entry_type); break; } - FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + - "game_list"); + Common::FS::DeleteDirRecursively(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + + DIR_SEP + "game_list"); game_list->PopulateAsync(UISettings::values.game_dirs); } @@ -1519,7 +1532,7 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget targ void GMainWindow::RemoveTransferableShaderCache(u64 program_id) { const QString shader_dir = - QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)); + QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ShaderDir)); const QString transferable_shader_cache_folder_path = shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable"); const QString transferable_shader_cache_file_path = @@ -1543,7 +1556,7 @@ void GMainWindow::RemoveTransferableShaderCache(u64 program_id) { void GMainWindow::RemoveCustomConfiguration(u64 program_id) { const QString config_dir = - QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir)); + QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir)); const QString custom_config_file_path = config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id)); @@ -1590,7 +1603,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa } const auto path = fmt::format( - "{}{:016X}/romfs", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), *romfs_title_id); + "{}{:016X}/romfs", Common::FS::GetUserPath(Common::FS::UserPath::DumpDir), *romfs_title_id); FileSys::VirtualFile romfs; @@ -1670,13 +1683,13 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id, void GMainWindow::OnGameListOpenDirectory(const QString& directory) { QString path; if (directory == QStringLiteral("SDMC")) { - path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + + path = QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir) + "Nintendo/Contents/registered"); } else if (directory == QStringLiteral("UserNAND")) { - path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + + path = QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + "user/Contents/registered"); } else if (directory == QStringLiteral("SysNAND")) { - path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + + path = QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + "system/Contents/registered"); } else { path = directory; @@ -1690,8 +1703,10 @@ void GMainWindow::OnGameListOpenDirectory(const QString& directory) { void GMainWindow::OnGameListAddDirectory() { const QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); - if (dir_path.isEmpty()) + if (dir_path.isEmpty()) { return; + } + UISettings::GameDir game_dir{dir_path, false, true}; if (!UISettings::values.game_dirs.contains(game_dir)) { UISettings::values.game_dirs.append(game_dir); @@ -1718,26 +1733,7 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { return; } - ConfigurePerGame dialog(this, title_id); - dialog.LoadFromFile(v_file); - auto result = dialog.exec(); - if (result == QDialog::Accepted) { - dialog.ApplyConfiguration(); - - const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); - if (reload) { - game_list->PopulateAsync(UISettings::values.game_dirs); - } - - // Do not cause the global config to write local settings into the config file - Settings::RestoreGlobalState(); - - if (!Core::System::GetInstance().IsPoweredOn()) { - config->Save(); - } - } else { - Settings::RestoreGlobalState(); - } + OpenPerGameConfiguration(title_id, file); } void GMainWindow::OnMenuLoadFile() { @@ -1882,8 +1878,8 @@ void GMainWindow::OnMenuInstallToNAND() { : tr("%n file(s) failed to install\n", "", failed_files.size())); QMessageBox::information(this, tr("Install Results"), install_results); - FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + - "game_list"); + Common::FS::DeleteDirRecursively(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + + DIR_SEP + "game_list"); game_list->PopulateAsync(UISettings::values.game_dirs); ui.action_Install_File_NAND->setEnabled(true); } @@ -2066,6 +2062,7 @@ void GMainWindow::OnStartGame() { ui.action_Pause->setEnabled(true); ui.action_Stop->setEnabled(true); ui.action_Restart->setEnabled(true); + ui.action_Configure_Current_Game->setEnabled(true); ui.action_Report_Compatibility->setEnabled(true); discord_rpc->Update(); @@ -2217,7 +2214,7 @@ void GMainWindow::OnConfigure() { const auto old_theme = UISettings::values.theme; const bool old_discord_presence = UISettings::values.enable_discord_presence; - ConfigureDialog configure_dialog(this, hotkey_registry); + ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get()); connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, &GMainWindow::OnLanguageChanged); @@ -2255,6 +2252,36 @@ void GMainWindow::OnConfigure() { UpdateStatusButtons(); } +void GMainWindow::OnConfigurePerGame() { + const u64 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); + OpenPerGameConfiguration(title_id, game_path.toStdString()); +} + +void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) { + const auto v_file = Core::GetGameFileFromPath(vfs, file_name); + + ConfigurePerGame dialog(this, title_id); + dialog.LoadFromFile(v_file); + auto result = dialog.exec(); + if (result == QDialog::Accepted) { + dialog.ApplyConfiguration(); + + const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); + if (reload) { + game_list->PopulateAsync(UISettings::values.game_dirs); + } + + // Do not cause the global config to write local settings into the config file + Settings::RestoreGlobalState(); + + if (!Core::System::GetInstance().IsPoweredOn()) { + config->Save(); + } + } else { + Settings::RestoreGlobalState(); + } +} + void GMainWindow::OnLoadAmiibo() { const QString extensions{QStringLiteral("*.bin")}; const QString file_filter = tr("Amiibo File (%1);; All Files (*.*)").arg(extensions); @@ -2302,7 +2329,7 @@ void GMainWindow::LoadAmiibo(const QString& filename) { void GMainWindow::OnOpenYuzuFolder() { QDesktopServices::openUrl(QUrl::fromLocalFile( - QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir)))); + QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::UserDir)))); } void GMainWindow::OnAbout() { @@ -2324,7 +2351,7 @@ void GMainWindow::OnCaptureScreenshot() { const u64 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); const auto screenshot_path = - QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ScreenshotsDir)); + QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir)); const auto date = QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd_hh-mm-ss-zzz")); QString filename = QStringLiteral("%1%2_%3.png") @@ -2527,18 +2554,18 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { if (res == QMessageBox::Cancel) return; - FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::KeysDir) + - "prod.keys_autogenerated"); - FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::KeysDir) + - "console.keys_autogenerated"); - FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::KeysDir) + - "title.keys_autogenerated"); + Common::FS::Delete(Common::FS::GetUserPath(Common::FS::UserPath::KeysDir) + + "prod.keys_autogenerated"); + Common::FS::Delete(Common::FS::GetUserPath(Common::FS::UserPath::KeysDir) + + "console.keys_autogenerated"); + Common::FS::Delete(Common::FS::GetUserPath(Common::FS::UserPath::KeysDir) + + "title.keys_autogenerated"); } Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); if (keys.BaseDeriveNecessary()) { Core::Crypto::PartitionDataManager pdm{vfs->OpenDirectory( - FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir), FileSys::Mode::Read)}; + Common::FS::GetUserPath(Common::FS::UserPath::SysDataDir), FileSys::Mode::Read)}; const auto function = [this, &keys, &pdm] { keys.PopulateFromPartitionData(pdm); @@ -2870,7 +2897,7 @@ int main(int argc, char* argv[]) { // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". // But since we require the working directory to be the executable path for the location of // the user folder in the Qt Frontend, we need to cd into that working directory - const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; + const std::string bin_path = Common::FS::GetBundleDirectory() + DIR_SEP + ".."; chdir(bin_path.c_str()); #endif |