Add per game configuration options (#6187)

* common: Move settings to common from core.

- Removes a dependency on core and input_common from common.

* code: Wrap settings values

* Port from yuzu to allow per game settings

* citra_qt: Initial per-game settings dialog

* citra_qt: Use new API for read/save of config values

* citra_qt: Per game audio settings

* citra_qt: Per game graphics settings

* citra_qt: Per game system settings

* citra_qt: Per game general settings

* citra_qt: Document and run clang format

* citra_qt: Make icon smaller and centered

* citra_qt: Remove version number

* Not sure how to extract that, can always add it back later

* citra_qt: Wrap UISettings

* citra_qt: Fix unthottled fps setting

* citra_qt: Remove margin in emulation tab

* citra_qt: Implement some suggestions

* Bring back speed switch hotkey

* Allow configuration when game is running

* Rename/adjust UI stuff

* citra_qt: Fix build with separate windows

* citra_qt: Address feedback

* citra_qt: Log per-game settings before launching games

* citra_qt: Add shader cache options

* Also fix android build

* citra_qt: Add DLC menu option

* citra_qt: Run clang-format

* citra_qt: Adjust for time offset

* citra_qt: Implement suggestions

* Run clang-format

Co-authored-by: bunnei <bunneidev@gmail.com>
This commit is contained in:
GPUCode 2022-12-08 13:27:25 +02:00 committed by GitHub
parent f261daf2fa
commit 48ee112ceb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
92 changed files with 3171 additions and 1546 deletions

View file

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <QApplication>
#include <QDir>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QHBoxLayout>
@ -28,9 +29,11 @@
#include "citra_qt/main.h"
#include "citra_qt/uisettings.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "core/file_sys/archive_extsavedata.h"
#include "core/file_sys/archive_source_sd_savedata.h"
#include "core/hle/service/fs/archive.h"
#include "qcursor.h"
GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent)
: QObject(parent), gamelist{gamelist} {}
@ -462,9 +465,20 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
default:
break;
}
context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location));
}
void ForEachOpenGLCacheFile(u64 program_id, auto func) {
for (const std::string_view cache_type : {"separable", "conventional"}) {
const std::string path = fmt::format("{}opengl/precompiled/{}/{:016X}.bin",
FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir),
cache_type, program_id);
QFile file{QString::fromStdString(path)};
func(file);
}
}
void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 program_id,
u64 extdata_id) {
QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location"));
@ -475,19 +489,32 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra
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* open_dlc_location = context_menu.addAction(tr("Open DLC Data Location"));
QMenu* shader_menu = context_menu.addMenu(tr("Disk Shader Cache"));
QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS"));
QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry"));
context_menu.addSeparator();
QAction* properties = context_menu.addAction(tr("Properties"));
QAction* open_shader_cache_location = shader_menu->addAction(tr("Open Shader Cache Location"));
shader_menu->addSeparator();
QAction* delete_opengl_disk_shader_cache =
shader_menu->addAction(tr("Delete OpenGL Shader Cache"));
const bool is_application =
0x0004000000000000 <= program_id && program_id <= 0x00040000FFFFFFFF;
bool opengl_cache_exists = false;
ForEachOpenGLCacheFile(
program_id, [&opengl_cache_exists](QFile& file) { opengl_cache_exists |= file.exists(); });
std::string sdmc_dir = FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir);
open_save_location->setVisible(
open_save_location->setEnabled(
is_application && FileUtil::Exists(FileSys::ArchiveSource_SDSaveData::GetSaveDataPathFor(
sdmc_dir, program_id)));
if (extdata_id) {
open_extdata_location->setVisible(
open_extdata_location->setEnabled(
is_application &&
FileUtil::Exists(FileSys::GetExtDataPathFromId(sdmc_dir, extdata_id)));
} else {
@ -495,18 +522,20 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra
}
auto media_type = Service::AM::GetTitleMediaType(program_id);
open_application_location->setVisible(path.toStdString() ==
open_application_location->setEnabled(path.toStdString() ==
Service::AM::GetTitleContentPath(media_type, program_id));
open_update_location->setVisible(
open_update_location->setEnabled(
is_application && FileUtil::Exists(Service::AM::GetTitlePath(Service::FS::MediaType::SDMC,
program_id + 0xe00000000) +
"content/"));
auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
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);
open_texture_dump_location->setEnabled(is_application);
open_texture_load_location->setEnabled(is_application);
open_mods_location->setEnabled(is_application);
open_dlc_location->setEnabled(is_application);
dump_romfs->setEnabled(is_application);
delete_opengl_disk_shader_cache->setEnabled(opengl_cache_exists);
navigate_to_gamedb_entry->setVisible(it != compatibility_list.end());
@ -543,11 +572,32 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra
emit OpenFolderRequested(program_id, GameListOpenTarget::MODS);
}
});
connect(open_dlc_location, &QAction::triggered, this, [this, program_id] {
const u64 trimmed_id = program_id & 0xFFFFFFF;
const std::string dlc_path =
fmt::format("{}Nintendo 3DS/00000000000000000000000000000000/"
"00000000000000000000000000000000/title/0004008c/{:08x}/content/",
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), trimmed_id);
fmt::print("DLC path {}\n", dlc_path);
if (FileUtil::CreateFullPath(dlc_path)) {
emit OpenFolderRequested(trimmed_id, GameListOpenTarget::DLC_DATA);
}
});
connect(dump_romfs, &QAction::triggered, this,
[this, path, program_id] { emit DumpRomFSRequested(path, program_id); });
connect(navigate_to_gamedb_entry, &QAction::triggered, this, [this, program_id]() {
emit NavigateToGamedbEntryRequested(program_id, compatibility_list);
});
connect(properties, &QAction::triggered, this,
[this, path]() { emit OpenPerGameGeneralRequested(path); });
connect(open_shader_cache_location, &QAction::triggered, this, [this, program_id] {
if (FileUtil::CreateFullPath(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir))) {
emit OpenFolderRequested(program_id, GameListOpenTarget::SHADER_CACHE);
}
});
connect(delete_opengl_disk_shader_cache, &QAction::triggered, this, [program_id] {
ForEachOpenGLCacheFile(program_id, [](QFile& file) { file.remove(); });
});
};
void GameList::AddCustomDirPopup(QMenu& context_menu, QModelIndex selected) {