mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-24 12:56:53 +02:00
26781e6fea
Port the static instruction patcher from shadPS4.
380 lines
12 KiB
C++
380 lines
12 KiB
C++
#include "configurationEditDialog.h"
|
|
|
|
#include "configuration.h"
|
|
#include "mandatoryLineEdit.h"
|
|
|
|
#include <QAbstractItemView>
|
|
#include <QCheckBox>
|
|
#include <QComboBox>
|
|
#include <QDir>
|
|
#include <QFileDialog>
|
|
#include <QFileInfo>
|
|
#include <QGroupBox>
|
|
#include <QHBoxLayout>
|
|
#include <QLayout>
|
|
#include <QListView>
|
|
#include <QListWidget>
|
|
#include <QMessageBox>
|
|
#include <QPushButton>
|
|
#include <QSettings>
|
|
#include <QSpinBox>
|
|
#include <QStyle>
|
|
#include <QToolButton>
|
|
#include <QTreeView>
|
|
#include <QVBoxLayout>
|
|
#include <QtAlgorithms>
|
|
|
|
#include "ui_configuration_edit_dialog.h"
|
|
|
|
constexpr char SETTINGS_CFG_DIALOG[] = "ConfigurationEditDialog";
|
|
constexpr char SETTINGS_CFG_LAST_GEOMETRY[] = "geometry";
|
|
constexpr int GLOBAL_SETTINGS_GAME_DIRS_MIN_WIDTH = 560;
|
|
|
|
const QStringList CONSOLE_LANGUAGE_NAMES = {
|
|
"Japanese",
|
|
"English (United States)",
|
|
"French (France)",
|
|
"Spanish (Spain)",
|
|
"German",
|
|
"Italian",
|
|
"Dutch",
|
|
"Portuguese (Portugal)",
|
|
"Russian",
|
|
"Korean",
|
|
"Chinese (Traditional)",
|
|
"Chinese (Simplified)",
|
|
"Finnish",
|
|
"Swedish",
|
|
"Danish",
|
|
"Norwegian",
|
|
"Polish",
|
|
"Portuguese (Brazil)",
|
|
"English (United Kingdom)",
|
|
"Turkish",
|
|
"Spanish (Latin America)",
|
|
"Arabic",
|
|
"French (Canada)",
|
|
"Czech",
|
|
"Hungarian",
|
|
"Greek",
|
|
"Romanian",
|
|
"Thai",
|
|
"Vietnamese",
|
|
"Indonesian",
|
|
};
|
|
|
|
static QString NormalizeGameDirectory(const QString& dir) {
|
|
const auto trimmed = dir.trimmed();
|
|
if (trimmed.isEmpty()) {
|
|
return {};
|
|
}
|
|
|
|
return QDir::cleanPath(QDir(trimmed).absolutePath());
|
|
}
|
|
|
|
static QString GameDirectoryKey(const QString& dir) {
|
|
const auto normalized = NormalizeGameDirectory(dir);
|
|
if (normalized.isEmpty()) {
|
|
return {};
|
|
}
|
|
|
|
auto canonical = QFileInfo(normalized).canonicalFilePath();
|
|
if (canonical.isEmpty()) {
|
|
canonical = normalized;
|
|
}
|
|
canonical = QDir::cleanPath(canonical);
|
|
|
|
#ifdef __linux__
|
|
return canonical;
|
|
#else
|
|
return canonical.toCaseFolded();
|
|
#endif
|
|
}
|
|
|
|
ConfigurationEditDialog::ConfigurationEditDialog(Configuration& info, QWidget* parent)
|
|
: QDialog(parent, Qt::WindowCloseButtonHint), m_ui(new Ui::ConfigurationEditDialog),
|
|
m_info(info) {
|
|
m_ui->setupUi(this);
|
|
InitGameDirectories();
|
|
|
|
connect(m_ui->ok_button, &QPushButton::clicked, this, &ConfigurationEditDialog::save);
|
|
connect(m_ui->clear_button, &QPushButton::clicked, this, &ConfigurationEditDialog::clear);
|
|
connect(m_ui->comboBox_shader_log_direction, &QComboBox::currentTextChanged, this,
|
|
[this](const QString& text) {
|
|
auto log = TextToEnum<Configuration::ShaderLogDirection>(text);
|
|
m_ui->lineEdit_shader_log_folder->setEnabled(
|
|
log == Configuration::ShaderLogDirection::File);
|
|
});
|
|
connect(m_ui->checkBox_cmd_dump, &QCheckBox::toggled, this,
|
|
[this](bool flag) { m_ui->lineEdit_cmd_dump_folder->setEnabled(flag); });
|
|
connect(m_ui->comboBox_printf_direction, &QComboBox::currentTextChanged, this,
|
|
[this](const QString& text) {
|
|
auto log = TextToEnum<Configuration::LogDirection>(text);
|
|
m_ui->lineEdit_printf_file->setEnabled(log == Configuration::LogDirection::File);
|
|
});
|
|
|
|
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
|
|
|
restoreGeometry(g_last_geometry);
|
|
|
|
Init(info);
|
|
}
|
|
|
|
QByteArray ConfigurationEditDialog::g_last_geometry;
|
|
|
|
ConfigurationEditDialog::~ConfigurationEditDialog() {
|
|
delete m_ui;
|
|
}
|
|
|
|
void ConfigurationEditDialog::WriteSettings(QSettings& s) {
|
|
s.beginGroup(SETTINGS_CFG_DIALOG);
|
|
|
|
if (!g_last_geometry.isEmpty()) {
|
|
s.setValue(SETTINGS_CFG_LAST_GEOMETRY, g_last_geometry);
|
|
}
|
|
|
|
s.endGroup();
|
|
}
|
|
|
|
void ConfigurationEditDialog::ReadSettings(QSettings& s) {
|
|
s.beginGroup(SETTINGS_CFG_DIALOG);
|
|
|
|
g_last_geometry = s.value(SETTINGS_CFG_LAST_GEOMETRY, g_last_geometry).toByteArray();
|
|
|
|
s.endGroup();
|
|
}
|
|
|
|
template <class T>
|
|
static void ListInit(QComboBox* combo, T value) {
|
|
combo->clear();
|
|
combo->addItems(EnumToList<T>());
|
|
combo->setCurrentText(EnumToText(value));
|
|
}
|
|
|
|
void ConfigurationEditDialog::Init(const Configuration& info) {
|
|
ListInit(m_ui->comboBox_screen_resolution, info.screen_resolution);
|
|
m_ui->checkBox_fullscreen->setChecked(info.fullscreen_enabled);
|
|
m_ui->spinBox_vblank_frequency->setValue(info.vblank_frequency);
|
|
m_ui->comboBox_console_language->clear();
|
|
m_ui->comboBox_console_language->addItems(CONSOLE_LANGUAGE_NAMES);
|
|
m_ui->comboBox_console_language->setCurrentIndex(
|
|
info.console_language >= 0 && info.console_language < CONSOLE_LANGUAGE_NAMES.size()
|
|
? info.console_language
|
|
: Configuration::DEFAULT_CONSOLE_LANGUAGE);
|
|
m_ui->checkBox_shader_validation->setChecked(info.shader_validation_enabled);
|
|
m_ui->checkBox_vulkan_validation->setChecked(info.vulkan_validation_enabled);
|
|
m_ui->checkBox_renderdoc_capture->setChecked(info.renderdoc_enabled);
|
|
#if defined(_WIN32)
|
|
m_ui->checkBox_red_zone_protection->setChecked(info.red_zone_protection_enabled);
|
|
#else
|
|
m_ui->checkBox_red_zone_protection->setVisible(false);
|
|
#endif
|
|
ListInit(m_ui->comboBox_shader_optimization_type, info.shader_optimization_type);
|
|
ListInit(m_ui->comboBox_shader_log_direction, info.shader_log_direction);
|
|
m_ui->lineEdit_shader_log_folder->setText(info.shader_log_folder);
|
|
m_ui->lineEdit_shader_log_folder->setEnabled(info.shader_log_direction ==
|
|
Configuration::ShaderLogDirection::File);
|
|
m_ui->checkBox_cmd_dump->setChecked(info.command_buffer_dump_enabled);
|
|
m_ui->lineEdit_cmd_dump_folder->setText(info.command_buffer_dump_folder);
|
|
m_ui->lineEdit_cmd_dump_folder->setEnabled(info.command_buffer_dump_enabled);
|
|
ListInit(m_ui->comboBox_printf_direction, info.printf_direction);
|
|
m_ui->lineEdit_printf_file->setText(info.printf_output_file);
|
|
m_ui->lineEdit_printf_file->setEnabled(info.printf_direction ==
|
|
Configuration::LogDirection::File);
|
|
ListInit(m_ui->comboBox_profiler_direction, info.profiler_direction);
|
|
}
|
|
|
|
void ConfigurationEditDialog::InitGameDirectories() {
|
|
m_game_dirs_group = new QGroupBox(tr("Game folders"), this);
|
|
|
|
auto* group_layout = new QVBoxLayout(m_game_dirs_group);
|
|
group_layout->setContentsMargins(8, 8, 8, 8);
|
|
group_layout->setSpacing(6);
|
|
|
|
m_game_dirs_list = new QListWidget(m_game_dirs_group);
|
|
m_game_dirs_list->setMinimumHeight(120);
|
|
m_game_dirs_list->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
group_layout->addWidget(m_game_dirs_list);
|
|
|
|
auto* button_layout = new QHBoxLayout;
|
|
button_layout->setContentsMargins(0, 0, 0, 0);
|
|
button_layout->setSpacing(4);
|
|
|
|
auto* add_button = new QToolButton(m_game_dirs_group);
|
|
add_button->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon));
|
|
add_button->setToolTip(tr("Add game folder"));
|
|
add_button->setAutoRaise(true);
|
|
button_layout->addWidget(add_button);
|
|
|
|
m_remove_game_dir_button = new QToolButton(m_game_dirs_group);
|
|
m_remove_game_dir_button->setIcon(style()->standardIcon(QStyle::SP_DialogDiscardButton));
|
|
m_remove_game_dir_button->setToolTip(tr("Remove selected game folders"));
|
|
m_remove_game_dir_button->setAutoRaise(true);
|
|
button_layout->addWidget(m_remove_game_dir_button);
|
|
|
|
button_layout->addStretch(1);
|
|
group_layout->addLayout(button_layout);
|
|
|
|
m_ui->gridLayout->addWidget(m_game_dirs_group, 1, 0, 1, 1);
|
|
m_game_dirs_group->setVisible(false);
|
|
|
|
connect(add_button, &QToolButton::clicked, this, &ConfigurationEditDialog::add_game_directory);
|
|
connect(m_remove_game_dir_button, &QToolButton::clicked, this,
|
|
&ConfigurationEditDialog::remove_selected_game_directories);
|
|
connect(m_game_dirs_list, &QListWidget::itemSelectionChanged, this,
|
|
&ConfigurationEditDialog::update_game_directory_buttons);
|
|
|
|
update_game_directory_buttons();
|
|
}
|
|
|
|
void ConfigurationEditDialog::SetTitle(const QString& str) {
|
|
setWindowTitle(str);
|
|
}
|
|
|
|
void ConfigurationEditDialog::SetGameDirectories(const QStringList& dirs) {
|
|
m_show_game_dirs = true;
|
|
m_game_dirs_list->clear();
|
|
m_game_dirs_group->setMinimumWidth(GLOBAL_SETTINGS_GAME_DIRS_MIN_WIDTH);
|
|
|
|
for (const auto& dir: dirs) {
|
|
AddGameDirectoryItem(dir);
|
|
}
|
|
|
|
m_game_dirs_group->setVisible(true);
|
|
update_game_directory_buttons();
|
|
adjustSize();
|
|
}
|
|
|
|
QStringList ConfigurationEditDialog::GetGameDirectories() const {
|
|
QStringList dirs;
|
|
if (!m_show_game_dirs) {
|
|
return dirs;
|
|
}
|
|
|
|
for (int index = 0; index < m_game_dirs_list->count(); index++) {
|
|
auto* item = m_game_dirs_list->item(index);
|
|
dirs.append(item->text());
|
|
}
|
|
|
|
return dirs;
|
|
}
|
|
|
|
void ConfigurationEditDialog::AddGameDirectoryItem(const QString& dir) {
|
|
const auto normalized = NormalizeGameDirectory(dir);
|
|
const auto key = GameDirectoryKey(normalized);
|
|
if (normalized.isEmpty() || key.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
for (int index = 0; index < m_game_dirs_list->count(); index++) {
|
|
auto* item = m_game_dirs_list->item(index);
|
|
if (GameDirectoryKey(item->text()) == key) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
auto* item = new QListWidgetItem(normalized, m_game_dirs_list);
|
|
item->setToolTip(normalized);
|
|
}
|
|
|
|
void ConfigurationEditDialog::moveEvent(QMoveEvent* event) {
|
|
QDialog::moveEvent(event);
|
|
g_last_geometry = saveGeometry();
|
|
}
|
|
|
|
static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui) {
|
|
info.screen_resolution =
|
|
TextToEnum<Configuration::Resolution>(ui.comboBox_screen_resolution->currentText());
|
|
info.fullscreen_enabled = ui.checkBox_fullscreen->isChecked();
|
|
info.vblank_frequency = ui.spinBox_vblank_frequency->value();
|
|
info.console_language = ui.comboBox_console_language->currentIndex();
|
|
info.vulkan_validation_enabled = ui.checkBox_vulkan_validation->isChecked();
|
|
info.shader_validation_enabled = ui.checkBox_shader_validation->isChecked();
|
|
info.renderdoc_enabled = ui.checkBox_renderdoc_capture->isChecked();
|
|
#if defined(_WIN32)
|
|
info.red_zone_protection_enabled = ui.checkBox_red_zone_protection->isChecked();
|
|
#endif
|
|
info.shader_optimization_type = TextToEnum<Configuration::ShaderOptimizationType>(
|
|
ui.comboBox_shader_optimization_type->currentText());
|
|
info.shader_log_direction = TextToEnum<Configuration::ShaderLogDirection>(
|
|
ui.comboBox_shader_log_direction->currentText());
|
|
info.shader_log_folder = ui.lineEdit_shader_log_folder->text();
|
|
info.command_buffer_dump_enabled = ui.checkBox_cmd_dump->isChecked();
|
|
info.command_buffer_dump_folder = ui.lineEdit_cmd_dump_folder->text();
|
|
info.printf_direction =
|
|
TextToEnum<Configuration::LogDirection>(ui.comboBox_printf_direction->currentText());
|
|
info.printf_output_file = ui.lineEdit_printf_file->text();
|
|
info.profiler_direction =
|
|
TextToEnum<Configuration::ProfilerDirection>(ui.comboBox_profiler_direction->currentText());
|
|
}
|
|
|
|
void ConfigurationEditDialog::update_info() {
|
|
UpdateInfo(m_info, *m_ui);
|
|
}
|
|
|
|
void ConfigurationEditDialog::adjust_size() {
|
|
this->adjustSize();
|
|
}
|
|
|
|
void ConfigurationEditDialog::save() {
|
|
if (MandatoryLineEdit::FindEmpty(this)) {
|
|
QMessageBox::critical(this, tr("Save failed"), tr("Please fill all mandatory fields"));
|
|
return;
|
|
}
|
|
|
|
update_info();
|
|
|
|
emit accept();
|
|
}
|
|
|
|
void ConfigurationEditDialog::clear() {
|
|
Configuration default_info;
|
|
Init(default_info);
|
|
|
|
if (m_show_game_dirs) {
|
|
m_game_dirs_list->clear();
|
|
update_game_directory_buttons();
|
|
}
|
|
}
|
|
|
|
void ConfigurationEditDialog::add_game_directory() {
|
|
QString start_dir = QDir::homePath();
|
|
if (m_game_dirs_list->count() > 0) {
|
|
start_dir = m_game_dirs_list->item(m_game_dirs_list->count() - 1)->text();
|
|
}
|
|
|
|
QFileDialog dialog(this, tr("Select game folders"), start_dir);
|
|
dialog.setFileMode(QFileDialog::Directory);
|
|
dialog.setOption(QFileDialog::ShowDirsOnly, true);
|
|
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
|
|
dialog.setLabelText(QFileDialog::Accept, tr("Add"));
|
|
|
|
auto* list_view = dialog.findChild<QListView*>(QStringLiteral("listView"));
|
|
if (list_view != nullptr) {
|
|
list_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
}
|
|
auto* tree_view = dialog.findChild<QTreeView*>(QStringLiteral("treeView"));
|
|
if (tree_view != nullptr) {
|
|
tree_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
}
|
|
|
|
if (dialog.exec() != QDialog::Accepted) {
|
|
return;
|
|
}
|
|
|
|
for (const auto& dir: dialog.selectedFiles()) {
|
|
AddGameDirectoryItem(dir);
|
|
}
|
|
|
|
update_game_directory_buttons();
|
|
}
|
|
|
|
void ConfigurationEditDialog::remove_selected_game_directories() {
|
|
qDeleteAll(m_game_dirs_list->selectedItems());
|
|
update_game_directory_buttons();
|
|
}
|
|
|
|
void ConfigurationEditDialog::update_game_directory_buttons() {
|
|
m_remove_game_dir_button->setEnabled(!m_game_dirs_list->selectedItems().isEmpty());
|
|
}
|