diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 3fddd13fa..2a722f37d 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -157,7 +157,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { system.RegisterSoftwareKeyboard(std::make_shared()); // Register microphone permission check - Core::System::GetInstance().RegisterMicPermissionCheck(&CheckMicPermission); + system.RegisterMicPermissionCheck(&CheckMicPermission); InputManager::Init(); @@ -167,7 +167,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { return load_result; } - auto& telemetry_session = Core::System::GetInstance().TelemetrySession(); + auto& telemetry_session = system.TelemetrySession(); telemetry_session.AddField(Common::Telemetry::FieldType::App, "Frontend", "Android"); stop_run = false; @@ -188,8 +188,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { audio_stretching_event = system.CoreTiming().RegisterEvent("AudioStretchingEvent", [&](u64, s64 cycles_late) { if (Settings::values.enable_audio_stretching) { - Core::DSP().EnableStretching( - Core::System::GetInstance().GetAndResetPerfStats().emulation_speed < 0.95); + system.DSP().EnableStretching(system.GetAndResetPerfStats().emulation_speed < 0.95); } system.CoreTiming().ScheduleEvent(audio_stretching_ticks - cycles_late, @@ -220,7 +219,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { SCOPE_EXIT({ Settings::values.volume = volume; }); Settings::values.volume = 0; - std::unique_lock pause_lock(paused_mutex); + std::unique_lock pause_lock{paused_mutex}; running_cv.wait(pause_lock, [] { return !pause_emulation || stop_run; }); window->PollEvents(); } diff --git a/src/citra_qt/configuration/configure.ui b/src/citra_qt/configuration/configure.ui index 1774ccbc1..f6f5a517a 100644 --- a/src/citra_qt/configuration/configure.ui +++ b/src/citra_qt/configuration/configure.ui @@ -21,68 +21,8 @@ - 0 + -1 - - - General - - - - - System - - - - - Input - - - - - Hotkeys - - - - - Graphics - - - - - Enhancements - - - - - Audio - - - - - Camera - - - - - Debug - - - - - Storage - - - - - Web - - - - - UI - - diff --git a/src/citra_qt/configuration/configure_audio.cpp b/src/citra_qt/configuration/configure_audio.cpp index c32bebc19..f921c3a62 100644 --- a/src/citra_qt/configuration/configure_audio.cpp +++ b/src/citra_qt/configuration/configure_audio.cpp @@ -10,14 +10,13 @@ #include "citra_qt/configuration/configuration_shared.h" #include "citra_qt/configuration/configure_audio.h" #include "common/settings.h" -#include "core/core.h" #include "ui_configure_audio.h" #if defined(__APPLE__) #include "common/apple_authorization.h" #endif -ConfigureAudio::ConfigureAudio(QWidget* parent) +ConfigureAudio::ConfigureAudio(bool is_powered_on, QWidget* parent) : QWidget(parent), ui(std::make_unique()) { ui->setupUi(this); @@ -27,8 +26,7 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) AudioCore::GetSinkName(static_cast(type)).data())); } - const bool is_running = Core::System::GetInstance().IsPoweredOn(); - ui->emulation_combo_box->setEnabled(!is_running); + ui->emulation_combo_box->setEnabled(!is_powered_on); connect(ui->volume_slider, &QSlider::valueChanged, this, &ConfigureAudio::SetVolumeIndicatorText); diff --git a/src/citra_qt/configuration/configure_audio.h b/src/citra_qt/configuration/configure_audio.h index a25153c50..001d574ed 100644 --- a/src/citra_qt/configuration/configure_audio.h +++ b/src/citra_qt/configuration/configure_audio.h @@ -19,7 +19,7 @@ class ConfigureAudio : public QWidget { Q_OBJECT public: - explicit ConfigureAudio(QWidget* parent = nullptr); + explicit ConfigureAudio(bool is_powered_on, QWidget* parent = nullptr); ~ConfigureAudio() override; void ApplyConfiguration(); diff --git a/src/citra_qt/configuration/configure_camera.cpp b/src/citra_qt/configuration/configure_camera.cpp index de270726e..08368fe5c 100644 --- a/src/citra_qt/configuration/configure_camera.cpp +++ b/src/citra_qt/configuration/configure_camera.cpp @@ -47,8 +47,7 @@ ConfigureCamera::~ConfigureCamera() { } void ConfigureCamera::ConnectEvents() { - connect(ui->image_source, - static_cast(&QComboBox::currentIndexChanged), this, + connect(ui->image_source, qOverload(&QComboBox::currentIndexChanged), this, [this](int index) { StopPreviewing(); UpdateImageSourceUI(); @@ -58,36 +57,33 @@ void ConfigureCamera::ConnectEvents() { } #endif }); - connect(ui->camera_selection, - static_cast(&QComboBox::currentIndexChanged), this, [this] { - StopPreviewing(); - if (GetCameraSelection() != current_selected) { - RecordConfig(); - } - if (ui->camera_selection->currentIndex() == 1) { - ui->camera_mode->setCurrentIndex(1); // Double - if (camera_name[0] == camera_name[2] && camera_config[0] == camera_config[2]) { - ui->camera_mode->setCurrentIndex(0); // Single - } - } - UpdateCameraMode(); - SetConfiguration(); - }); - connect(ui->camera_mode, static_cast(&QComboBox::currentIndexChanged), - this, [this] { - StopPreviewing(); - ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1); - ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1); - current_selected = GetCameraSelection(); - }); - connect(ui->camera_position, - static_cast(&QComboBox::currentIndexChanged), this, [this] { - StopPreviewing(); - if (GetCameraSelection() != current_selected) { - RecordConfig(); - } - SetConfiguration(); - }); + connect(ui->camera_selection, qOverload(&QComboBox::currentIndexChanged), this, [this] { + StopPreviewing(); + if (GetCameraSelection() != current_selected) { + RecordConfig(); + } + if (ui->camera_selection->currentIndex() == 1) { + ui->camera_mode->setCurrentIndex(1); // Double + if (camera_name[0] == camera_name[2] && camera_config[0] == camera_config[2]) { + ui->camera_mode->setCurrentIndex(0); // Single + } + } + UpdateCameraMode(); + SetConfiguration(); + }); + connect(ui->camera_mode, qOverload(&QComboBox::currentIndexChanged), this, [this] { + StopPreviewing(); + ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1); + ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1); + current_selected = GetCameraSelection(); + }); + connect(ui->camera_position, qOverload(&QComboBox::currentIndexChanged), this, [this] { + StopPreviewing(); + if (GetCameraSelection() != current_selected) { + RecordConfig(); + } + SetConfiguration(); + }); connect(ui->toolButton, &QToolButton::clicked, this, &ConfigureCamera::OnToolButtonClicked); connect(ui->preview_button, &QPushButton::clicked, this, [this] { StartPreviewing(); }); connect(ui->prompt_before_load, &QCheckBox::stateChanged, this, [this](int state) { diff --git a/src/citra_qt/configuration/configure_cheats.cpp b/src/citra_qt/configuration/configure_cheats.cpp index 4569f7ed8..c589a62e6 100644 --- a/src/citra_qt/configuration/configure_cheats.cpp +++ b/src/citra_qt/configuration/configure_cheats.cpp @@ -9,11 +9,9 @@ #include "core/cheats/cheat_base.h" #include "core/cheats/cheats.h" #include "core/cheats/gateway_cheat.h" -#include "core/core.h" -#include "core/hle/kernel/process.h" #include "ui_configure_cheats.h" -ConfigureCheats::ConfigureCheats(u64 title_id_, QWidget* parent) +ConfigureCheats::ConfigureCheats(Core::System& system, u64 title_id_, QWidget* parent) : QWidget(parent), ui(std::make_unique()), title_id{title_id_} { // Setup gui control settings ui->setupUi(this); @@ -36,7 +34,7 @@ ConfigureCheats::ConfigureCheats(u64 title_id_, QWidget* parent) [this] { SaveCheat(ui->tableCheats->currentRow()); }); connect(ui->buttonDelete, &QPushButton::clicked, this, &ConfigureCheats::OnDeleteCheat); - cheat_engine = std::make_unique(title_id, Core::System::GetInstance()); + cheat_engine = std::make_unique(title_id, system); LoadCheats(); } diff --git a/src/citra_qt/configuration/configure_cheats.h b/src/citra_qt/configuration/configure_cheats.h index 5242c82d8..28dcb72e5 100644 --- a/src/citra_qt/configuration/configure_cheats.h +++ b/src/citra_qt/configuration/configure_cheats.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "common/common_types.h" namespace Cheats { @@ -12,6 +13,10 @@ class CheatBase; class CheatEngine; } // namespace Cheats +namespace Core { +class System; +} + namespace Ui { class ConfigureCheats; } // namespace Ui @@ -20,7 +25,7 @@ class ConfigureCheats : public QWidget { Q_OBJECT public: - explicit ConfigureCheats(u64 title_id_, QWidget* parent = nullptr); + explicit ConfigureCheats(Core::System& system, u64 title_id, QWidget* parent = nullptr); ~ConfigureCheats(); bool ApplyConfiguration(); diff --git a/src/citra_qt/configuration/configure_debug.cpp b/src/citra_qt/configuration/configure_debug.cpp index d0b244133..3e166834b 100644 --- a/src/citra_qt/configuration/configure_debug.cpp +++ b/src/citra_qt/configuration/configure_debug.cpp @@ -11,7 +11,6 @@ #include "common/file_util.h" #include "common/logging/backend.h" #include "common/settings.h" -#include "core/core.h" #include "ui_configure_debug.h" // The QSlider doesn't have an easy way to set a custom step amount, @@ -25,8 +24,8 @@ static constexpr int SettingsToSlider(int value) { return (value - 5) / 5; } -ConfigureDebug::ConfigureDebug(QWidget* parent) - : QWidget(parent), ui(std::make_unique()) { +ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent) + : QWidget(parent), ui(std::make_unique()), is_powered_on{is_powered_on_} { ui->setupUi(this); SetConfiguration(); @@ -35,7 +34,6 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) QDesktopServices::openUrl(QUrl::fromLocalFile(path)); }); - const bool is_powered_on = Core::System::GetInstance().IsPoweredOn(); ui->toggle_cpu_jit->setEnabled(!is_powered_on); ui->toggle_renderer_debug->setEnabled(!is_powered_on); @@ -59,7 +57,7 @@ void ConfigureDebug::SetConfiguration() { ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue()); ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue()); ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue()); - ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn()); + ui->toggle_console->setEnabled(!is_powered_on); ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue()); diff --git a/src/citra_qt/configuration/configure_debug.h b/src/citra_qt/configuration/configure_debug.h index 02101016f..f511e260e 100644 --- a/src/citra_qt/configuration/configure_debug.h +++ b/src/citra_qt/configuration/configure_debug.h @@ -15,7 +15,7 @@ class ConfigureDebug : public QWidget { Q_OBJECT public: - explicit ConfigureDebug(QWidget* parent = nullptr); + explicit ConfigureDebug(bool is_powered_on, QWidget* parent = nullptr); ~ConfigureDebug() override; void ApplyConfiguration(); @@ -25,4 +25,5 @@ public: private: std::unique_ptr ui; + bool is_powered_on; }; diff --git a/src/citra_qt/configuration/configure_dialog.cpp b/src/citra_qt/configuration/configure_dialog.cpp index 254a63641..ee46ff5fb 100644 --- a/src/citra_qt/configuration/configure_dialog.cpp +++ b/src/citra_qt/configuration/configure_dialog.cpp @@ -4,8 +4,19 @@ #include #include -#include "citra_qt/configuration/config.h" +#include "citra_qt/configuration/configure_audio.h" +#include "citra_qt/configuration/configure_camera.h" +#include "citra_qt/configuration/configure_debug.h" #include "citra_qt/configuration/configure_dialog.h" +#include "citra_qt/configuration/configure_enhancements.h" +#include "citra_qt/configuration/configure_general.h" +#include "citra_qt/configuration/configure_graphics.h" +#include "citra_qt/configuration/configure_hotkeys.h" +#include "citra_qt/configuration/configure_input.h" +#include "citra_qt/configuration/configure_storage.h" +#include "citra_qt/configuration/configure_system.h" +#include "citra_qt/configuration/configure_ui.h" +#include "citra_qt/configuration/configure_web.h" #include "citra_qt/hotkeys.h" #include "common/settings.h" #include "core/core.h" @@ -14,16 +25,41 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_, bool enable_web_config) : QDialog(parent), ui{std::make_unique()}, registry{registry_}, - system{system_} { + system{system_}, is_powered_on{system.IsPoweredOn()}, + general_tab{std::make_unique(this)}, + system_tab{std::make_unique(system, this)}, + input_tab{std::make_unique(this)}, + hotkeys_tab{std::make_unique(this)}, + graphics_tab{std::make_unique(is_powered_on, this)}, + enhancements_tab{std::make_unique(this)}, + audio_tab{std::make_unique(is_powered_on, this)}, + camera_tab{std::make_unique(this)}, + debug_tab{std::make_unique(is_powered_on, this)}, + storage_tab{std::make_unique(is_powered_on, this)}, + web_tab{std::make_unique(this)}, ui_tab{std::make_unique(this)} { Settings::SetConfiguringGlobal(true); ui->setupUi(this); - ui->hotkeysTab->Populate(registry); - ui->webTab->SetWebServiceConfigEnabled(enable_web_config); + + ui->tabWidget->addTab(general_tab.get(), tr("General")); + ui->tabWidget->addTab(system_tab.get(), tr("System")); + ui->tabWidget->addTab(input_tab.get(), tr("Input")); + ui->tabWidget->addTab(hotkeys_tab.get(), tr("Hotkeys")); + ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); + ui->tabWidget->addTab(enhancements_tab.get(), tr("Enhancements")); + ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); + ui->tabWidget->addTab(camera_tab.get(), tr("Camera")); + ui->tabWidget->addTab(debug_tab.get(), tr("Debug")); + ui->tabWidget->addTab(storage_tab.get(), tr("Storage")); + ui->tabWidget->addTab(web_tab.get(), tr("Web")); + ui->tabWidget->addTab(ui_tab.get(), tr("UI")); + + hotkeys_tab->Populate(registry); + web_tab->SetWebServiceConfigEnabled(enable_web_config); PopulateSelectionList(); - connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); + connect(ui_tab.get(), &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, &ConfigureDialog::UpdateVisibleTabs); @@ -31,46 +67,46 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor ui->selectorList->setCurrentRow(0); // Set up used key list synchronisation - connect(ui->inputTab, &ConfigureInput::InputKeysChanged, ui->hotkeysTab, + connect(input_tab.get(), &ConfigureInput::InputKeysChanged, hotkeys_tab.get(), &ConfigureHotkeys::OnInputKeysChanged); - connect(ui->hotkeysTab, &ConfigureHotkeys::HotkeysChanged, ui->inputTab, + connect(hotkeys_tab.get(), &ConfigureHotkeys::HotkeysChanged, input_tab.get(), &ConfigureInput::OnHotkeysChanged); // Synchronise lists upon initialisation - ui->inputTab->EmitInputKeysChanged(); - ui->hotkeysTab->EmitHotkeysChanged(); + input_tab->EmitInputKeysChanged(); + hotkeys_tab->EmitHotkeysChanged(); } ConfigureDialog::~ConfigureDialog() = default; void ConfigureDialog::SetConfiguration() { - ui->generalTab->SetConfiguration(); - ui->systemTab->SetConfiguration(); - ui->inputTab->LoadConfiguration(); - ui->graphicsTab->SetConfiguration(); - ui->enhancementsTab->SetConfiguration(); - ui->audioTab->SetConfiguration(); - ui->cameraTab->SetConfiguration(); - ui->debugTab->SetConfiguration(); - ui->webTab->SetConfiguration(); - ui->uiTab->SetConfiguration(); - ui->storageTab->SetConfiguration(); + general_tab->SetConfiguration(); + system_tab->SetConfiguration(); + input_tab->LoadConfiguration(); + graphics_tab->SetConfiguration(); + enhancements_tab->SetConfiguration(); + audio_tab->SetConfiguration(); + camera_tab->SetConfiguration(); + debug_tab->SetConfiguration(); + web_tab->SetConfiguration(); + ui_tab->SetConfiguration(); + storage_tab->SetConfiguration(); } void ConfigureDialog::ApplyConfiguration() { - ui->generalTab->ApplyConfiguration(); - ui->systemTab->ApplyConfiguration(); - ui->inputTab->ApplyConfiguration(); - ui->inputTab->ApplyProfile(); - ui->hotkeysTab->ApplyConfiguration(registry); - ui->graphicsTab->ApplyConfiguration(); - ui->enhancementsTab->ApplyConfiguration(); - ui->audioTab->ApplyConfiguration(); - ui->cameraTab->ApplyConfiguration(); - ui->debugTab->ApplyConfiguration(); - ui->webTab->ApplyConfiguration(); - ui->uiTab->ApplyConfiguration(); - ui->storageTab->ApplyConfiguration(); + general_tab->ApplyConfiguration(); + system_tab->ApplyConfiguration(); + input_tab->ApplyConfiguration(); + input_tab->ApplyProfile(); + hotkeys_tab->ApplyConfiguration(registry); + graphics_tab->ApplyConfiguration(); + enhancements_tab->ApplyConfiguration(); + audio_tab->ApplyConfiguration(); + camera_tab->ApplyConfiguration(); + debug_tab->ApplyConfiguration(); + web_tab->ApplyConfiguration(); + ui_tab->ApplyConfiguration(); + storage_tab->ApplyConfiguration(); system.ApplySettings(); Settings::LogSettings(); } @@ -81,11 +117,11 @@ void ConfigureDialog::PopulateSelectionList() { ui->selectorList->clear(); const std::array>, 5> items{ - {{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}}, - {tr("System"), {ui->systemTab, ui->cameraTab, ui->storageTab}}, - {tr("Graphics"), {ui->enhancementsTab, ui->graphicsTab}}, - {tr("Audio"), {ui->audioTab}}, - {tr("Controls"), {ui->inputTab, ui->hotkeysTab}}}}; + {{tr("General"), {general_tab.get(), web_tab.get(), debug_tab.get(), ui_tab.get()}}, + {tr("System"), {system_tab.get(), camera_tab.get(), storage_tab.get()}}, + {tr("Graphics"), {enhancements_tab.get(), graphics_tab.get()}}, + {tr("Audio"), {audio_tab.get()}}, + {tr("Controls"), {input_tab.get(), hotkeys_tab.get()}}}}; for (const auto& entry : items) { auto* const item = new QListWidgetItem(entry.first); @@ -112,18 +148,18 @@ void ConfigureDialog::RetranslateUI() { ui->selectorList->setCurrentRow(old_row); ui->tabWidget->setCurrentIndex(old_index); - ui->generalTab->RetranslateUI(); - ui->systemTab->RetranslateUI(); - ui->inputTab->RetranslateUI(); - ui->hotkeysTab->RetranslateUI(); - ui->graphicsTab->RetranslateUI(); - ui->enhancementsTab->RetranslateUI(); - ui->audioTab->RetranslateUI(); - ui->cameraTab->RetranslateUI(); - ui->debugTab->RetranslateUI(); - ui->webTab->RetranslateUI(); - ui->uiTab->RetranslateUI(); - ui->storageTab->RetranslateUI(); + general_tab->RetranslateUI(); + system_tab->RetranslateUI(); + input_tab->RetranslateUI(); + hotkeys_tab->RetranslateUI(); + graphics_tab->RetranslateUI(); + enhancements_tab->RetranslateUI(); + audio_tab->RetranslateUI(); + camera_tab->RetranslateUI(); + debug_tab->RetranslateUI(); + web_tab->RetranslateUI(); + ui_tab->RetranslateUI(); + storage_tab->RetranslateUI(); } void ConfigureDialog::UpdateVisibleTabs() { @@ -131,18 +167,18 @@ void ConfigureDialog::UpdateVisibleTabs() { if (items.isEmpty()) return; - const std::map widgets = {{ui->generalTab, tr("General")}, - {ui->systemTab, tr("System")}, - {ui->inputTab, tr("Input")}, - {ui->hotkeysTab, tr("Hotkeys")}, - {ui->enhancementsTab, tr("Enhancements")}, - {ui->graphicsTab, tr("Advanced")}, - {ui->audioTab, tr("Audio")}, - {ui->cameraTab, tr("Camera")}, - {ui->debugTab, tr("Debug")}, - {ui->storageTab, tr("Storage")}, - {ui->webTab, tr("Web")}, - {ui->uiTab, tr("UI")}}; + const std::map widgets = {{general_tab.get(), tr("General")}, + {system_tab.get(), tr("System")}, + {input_tab.get(), tr("Input")}, + {hotkeys_tab.get(), tr("Hotkeys")}, + {enhancements_tab.get(), tr("Enhancements")}, + {graphics_tab.get(), tr("Advanced")}, + {audio_tab.get(), tr("Audio")}, + {camera_tab.get(), tr("Camera")}, + {debug_tab.get(), tr("Debug")}, + {storage_tab.get(), tr("Storage")}, + {web_tab.get(), tr("Web")}, + {ui_tab.get(), tr("UI")}}; ui->tabWidget->clear(); diff --git a/src/citra_qt/configuration/configure_dialog.h b/src/citra_qt/configuration/configure_dialog.h index 23b32a197..7a4ae96d2 100644 --- a/src/citra_qt/configuration/configure_dialog.h +++ b/src/citra_qt/configuration/configure_dialog.h @@ -17,6 +17,19 @@ namespace Core { class System; } +class ConfigureGeneral; +class ConfigureSystem; +class ConfigureInput; +class ConfigureHotkeys; +class ConfigureGraphics; +class ConfigureEnhancements; +class ConfigureAudio; +class ConfigureCamera; +class ConfigureDebug; +class ConfigureStorage; +class ConfigureWeb; +class ConfigureUi; + class ConfigureDialog : public QDialog { Q_OBJECT @@ -42,4 +55,18 @@ private: std::unique_ptr ui; HotkeyRegistry& registry; Core::System& system; + bool is_powered_on; + + std::unique_ptr general_tab; + std::unique_ptr system_tab; + std::unique_ptr input_tab; + std::unique_ptr hotkeys_tab; + std::unique_ptr graphics_tab; + std::unique_ptr enhancements_tab; + std::unique_ptr audio_tab; + std::unique_ptr camera_tab; + std::unique_ptr debug_tab; + std::unique_ptr storage_tab; + std::unique_ptr web_tab; + std::unique_ptr ui_tab; }; diff --git a/src/citra_qt/configuration/configure_enhancements.cpp b/src/citra_qt/configuration/configure_enhancements.cpp index 90dfbf44d..55b8a79eb 100644 --- a/src/citra_qt/configuration/configure_enhancements.cpp +++ b/src/citra_qt/configuration/configure_enhancements.cpp @@ -22,8 +22,7 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent) const bool res_scale_enabled = graphics_api != Settings::GraphicsAPI::Software; ui->resolution_factor_combobox->setEnabled(res_scale_enabled); - connect(ui->render_3d_combobox, - static_cast(&QComboBox::currentIndexChanged), this, + connect(ui->render_3d_combobox, qOverload(&QComboBox::currentIndexChanged), this, [this](int currentIndex) { updateShaders(static_cast(currentIndex)); }); diff --git a/src/citra_qt/configuration/configure_graphics.cpp b/src/citra_qt/configuration/configure_graphics.cpp index c4fcd81c2..300a2736d 100644 --- a/src/citra_qt/configuration/configure_graphics.cpp +++ b/src/citra_qt/configuration/configure_graphics.cpp @@ -6,14 +6,13 @@ #include "citra_qt/configuration/configuration_shared.h" #include "citra_qt/configuration/configure_graphics.h" #include "common/settings.h" -#include "core/core.h" #include "ui_configure_graphics.h" -ConfigureGraphics::ConfigureGraphics(QWidget* parent) +ConfigureGraphics::ConfigureGraphics(bool is_powered_on, QWidget* parent) : QWidget(parent), ui(std::make_unique()) { ui->setupUi(this); - ui->toggle_vsync_new->setEnabled(!Core::System::GetInstance().IsPoweredOn()); + ui->toggle_vsync_new->setEnabled(!is_powered_on); // Set the index to -1 to ensure the below lambda is called with setCurrentIndex ui->graphics_api_combo->setCurrentIndex(-1); diff --git a/src/citra_qt/configuration/configure_graphics.h b/src/citra_qt/configuration/configure_graphics.h index 389bfba85..44b12cfa9 100644 --- a/src/citra_qt/configuration/configure_graphics.h +++ b/src/citra_qt/configuration/configure_graphics.h @@ -19,7 +19,7 @@ class ConfigureGraphics : public QWidget { Q_OBJECT public: - explicit ConfigureGraphics(QWidget* parent = nullptr); + explicit ConfigureGraphics(bool is_powered_on, QWidget* parent = nullptr); ~ConfigureGraphics() override; void ApplyConfiguration(); diff --git a/src/citra_qt/configuration/configure_graphics.ui b/src/citra_qt/configuration/configure_graphics.ui index 74fe21786..4235759cb 100644 --- a/src/citra_qt/configuration/configure_graphics.ui +++ b/src/citra_qt/configuration/configure_graphics.ui @@ -19,6 +19,9 @@ Form + + Graphics + diff --git a/src/citra_qt/configuration/configure_hotkeys.cpp b/src/citra_qt/configuration/configure_hotkeys.cpp index e4015aa25..b07370528 100644 --- a/src/citra_qt/configuration/configure_hotkeys.cpp +++ b/src/citra_qt/configuration/configure_hotkeys.cpp @@ -9,7 +9,6 @@ #include "citra_qt/configuration/configure_hotkeys.h" #include "citra_qt/hotkeys.h" #include "citra_qt/util/sequence_dialog/sequence_dialog.h" -#include "common/settings.h" #include "ui_configure_hotkeys.h" constexpr int name_column = 0; @@ -189,9 +188,9 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) { QAction* clear = context_menu.addAction(tr("Clear")); const auto hotkey_index = index.sibling(index.row(), hotkey_column); - connect(restore_default, &QAction::triggered, + connect(restore_default, &QAction::triggered, this, [this, hotkey_index] { RestoreHotkey(hotkey_index); }); - connect(clear, &QAction::triggered, + connect(clear, &QAction::triggered, this, [this, hotkey_index] { model->setData(hotkey_index, QString{}); }); context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location)); diff --git a/src/citra_qt/configuration/configure_per_game.cpp b/src/citra_qt/configuration/configure_per_game.cpp index c422a74f9..a9896e0ad 100644 --- a/src/citra_qt/configuration/configure_per_game.cpp +++ b/src/citra_qt/configuration/configure_per_game.cpp @@ -31,13 +31,14 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString : fmt::format("{:016X}", title_id); game_config = std::make_unique(config_file_name, Config::ConfigType::PerGameConfig); - audio_tab = std::make_unique(this); + const bool is_powered_on = system.IsPoweredOn(); + audio_tab = std::make_unique(is_powered_on, this); general_tab = std::make_unique(this); enhancements_tab = std::make_unique(this); - graphics_tab = std::make_unique(this); - system_tab = std::make_unique(this); - debug_tab = std::make_unique(this); - cheat_tab = std::make_unique(title_id, this); + graphics_tab = std::make_unique(is_powered_on, this); + system_tab = std::make_unique(system, this); + debug_tab = std::make_unique(is_powered_on, this); + cheat_tab = std::make_unique(system, title_id, this); ui->setupUi(this); diff --git a/src/citra_qt/configuration/configure_storage.cpp b/src/citra_qt/configuration/configure_storage.cpp index dfcfcc3cb..d46cb0614 100644 --- a/src/citra_qt/configuration/configure_storage.cpp +++ b/src/citra_qt/configuration/configure_storage.cpp @@ -8,11 +8,10 @@ #include "citra_qt/configuration/configure_storage.h" #include "common/file_util.h" #include "common/settings.h" -#include "core/core.h" #include "ui_configure_storage.h" -ConfigureStorage::ConfigureStorage(QWidget* parent) - : QWidget(parent), ui(std::make_unique()) { +ConfigureStorage::ConfigureStorage(bool is_powered_on_, QWidget* parent) + : QWidget(parent), ui(std::make_unique()), is_powered_on{is_powered_on_} { ui->setupUi(this); SetConfiguration(); @@ -75,7 +74,7 @@ void ConfigureStorage::SetConfiguration() { ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue()); ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage.GetValue()); - ui->storage_group->setEnabled(!Core::System::GetInstance().IsPoweredOn()); + ui->storage_group->setEnabled(!is_powered_on); } void ConfigureStorage::ApplyConfiguration() { diff --git a/src/citra_qt/configuration/configure_storage.h b/src/citra_qt/configuration/configure_storage.h index e79d3c008..48850fbc2 100644 --- a/src/citra_qt/configuration/configure_storage.h +++ b/src/citra_qt/configuration/configure_storage.h @@ -15,7 +15,7 @@ class ConfigureStorage : public QWidget { Q_OBJECT public: - explicit ConfigureStorage(QWidget* parent = nullptr); + explicit ConfigureStorage(bool is_powered_on, QWidget* parent = nullptr); ~ConfigureStorage() override; void ApplyConfiguration(); @@ -23,4 +23,5 @@ public: void SetConfiguration(); std::unique_ptr ui; + bool is_powered_on; }; diff --git a/src/citra_qt/configuration/configure_system.cpp b/src/citra_qt/configuration/configure_system.cpp index bf2b46ce9..0a5c14a84 100644 --- a/src/citra_qt/configuration/configure_system.cpp +++ b/src/citra_qt/configuration/configure_system.cpp @@ -223,14 +223,12 @@ static const std::array country_names = { QT_TRANSLATE_NOOP("ConfigureSystem", "Bermuda"), // 180-186 }; -ConfigureSystem::ConfigureSystem(QWidget* parent) - : QWidget(parent), ui(std::make_unique()) { +ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent) + : QWidget(parent), ui(std::make_unique()), system{system_} { ui->setupUi(this); - connect(ui->combo_birthmonth, - static_cast(&QComboBox::currentIndexChanged), this, + connect(ui->combo_birthmonth, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureSystem::UpdateBirthdayComboBox); - connect(ui->combo_init_clock, - static_cast(&QComboBox::currentIndexChanged), this, + connect(ui->combo_init_clock, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureSystem::UpdateInitTime); connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, &ConfigureSystem::RefreshConsoleID); @@ -280,7 +278,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) ConfigureSystem::~ConfigureSystem() = default; void ConfigureSystem::SetConfiguration() { - enabled = !Core::System::GetInstance().IsPoweredOn(); + enabled = !system.IsPoweredOn(); ui->combo_init_clock->setCurrentIndex(static_cast(Settings::values.init_clock.GetValue())); QDateTime date_time; @@ -296,7 +294,7 @@ void ConfigureSystem::SetConfiguration() { ui->edit_init_time_offset_time->setTime(time); if (!enabled) { - cfg = Service::CFG::GetModule(Core::System::GetInstance()); + cfg = Service::CFG::GetModule(system); ASSERT_MSG(cfg, "CFG Module missing!"); ReadSystemSettings(); ui->group_system_settings->setEnabled(false); diff --git a/src/citra_qt/configuration/configure_system.h b/src/citra_qt/configuration/configure_system.h index 6e2408465..86b6b7016 100644 --- a/src/citra_qt/configuration/configure_system.h +++ b/src/citra_qt/configuration/configure_system.h @@ -16,6 +16,10 @@ namespace ConfigurationShared { enum class CheckState; } +namespace Core { +class System; +} + namespace Service { namespace CFG { class Module; @@ -26,7 +30,7 @@ class ConfigureSystem : public QWidget { Q_OBJECT public: - explicit ConfigureSystem(QWidget* parent = nullptr); + explicit ConfigureSystem(Core::System& system, QWidget* parent = nullptr); ~ConfigureSystem() override; void ApplyConfiguration(); @@ -45,8 +49,10 @@ private: void DownloadFromNUS(); - ConfigurationShared::CheckState is_new_3ds; +private: std::unique_ptr ui; + Core::System& system; + ConfigurationShared::CheckState is_new_3ds; bool enabled = false; std::shared_ptr cfg; diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp index c34a5d153..6711644e6 100644 --- a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp @@ -16,7 +16,6 @@ #include "citra_qt/debugger/graphics/graphics_cmdlists.h" #include "citra_qt/util/util.h" #include "common/vector_math.h" -#include "core/core.h" #include "core/memory.h" #include "video_core/debug_utils/debug_utils.h" #include "video_core/pica_state.h" @@ -167,8 +166,7 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { const auto format = texture.format; const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format); - const u8* src = - Core::System::GetInstance().Memory().GetPhysicalPointer(config.GetPhysicalAddress()); + const u8* src = memory.GetPhysicalPointer(config.GetPhysicalAddress()); new_info_widget = new TextureInfoWidget(src, info); } if (command_info_widget) { @@ -182,8 +180,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { } #undef COMMAND_IN_RANGE -GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) - : QDockWidget(tr("Pica Command List"), parent) { +GPUCommandListWidget::GPUCommandListWidget(Memory::MemorySystem& memory_, QWidget* parent) + : QDockWidget(tr("Pica Command List"), parent), memory{memory_} { setObjectName(QStringLiteral("Pica Command List")); GPUCommandListModel* model = new GPUCommandListModel(this); diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.h b/src/citra_qt/debugger/graphics/graphics_cmdlists.h index 8f40b94c5..5ea4d125b 100644 --- a/src/citra_qt/debugger/graphics/graphics_cmdlists.h +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.h @@ -7,11 +7,14 @@ #include #include #include "video_core/debug_utils/debug_utils.h" -#include "video_core/gpu_debugger.h" class QPushButton; class QTreeView; +namespace Memory { +class MemorySystem; +} + class GPUCommandListModel : public QAbstractListModel { Q_OBJECT @@ -39,7 +42,7 @@ class GPUCommandListWidget : public QDockWidget { Q_OBJECT public: - explicit GPUCommandListWidget(QWidget* parent = nullptr); + explicit GPUCommandListWidget(Memory::MemorySystem& memory, QWidget* parent = nullptr); public slots: void OnToggleTracing(); @@ -54,7 +57,7 @@ signals: private: std::unique_ptr pica_trace; - + Memory::MemorySystem& memory; QTreeView* list_widget; QWidget* command_info_widget; QPushButton* toggle_tracing; diff --git a/src/citra_qt/debugger/graphics/graphics_surface.cpp b/src/citra_qt/debugger/graphics/graphics_surface.cpp index 9089c5724..13d6556cd 100644 --- a/src/citra_qt/debugger/graphics/graphics_surface.cpp +++ b/src/citra_qt/debugger/graphics/graphics_surface.cpp @@ -15,8 +15,6 @@ #include "citra_qt/debugger/graphics/graphics_surface.h" #include "citra_qt/util/spinbox.h" #include "common/color.h" -#include "core/core.h" -#include "core/hw/gpu.h" #include "core/memory.h" #include "video_core/pica_state.h" #include "video_core/regs_framebuffer.h" @@ -51,9 +49,10 @@ void SurfacePicture::mouseMoveEvent(QMouseEvent* event) { mousePressEvent(event); } -GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr debug_context, +GraphicsSurfaceWidget::GraphicsSurfaceWidget(Memory::MemorySystem& memory_, + std::shared_ptr debug_context, QWidget* parent) - : BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), + : BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), memory{memory_}, surface_source(Source::ColorBuffer) { setObjectName(QStringLiteral("PicaSurface")); @@ -290,57 +289,57 @@ void GraphicsSurfaceWidget::Pick(int x, int y) { return; } - u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address); - if (buffer == nullptr) { + const u8* buffer = memory.GetPhysicalPointer(surface_address); + if (!buffer) { surface_info_label->setText(tr("(unable to access pixel data)")); surface_info_label->setAlignment(Qt::AlignCenter); return; } - unsigned nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format); - unsigned stride = nibbles_per_pixel * surface_width / 2; - - unsigned bytes_per_pixel; - bool nibble_mode = (nibbles_per_pixel == 1); - if (nibble_mode) { - // As nibbles are contained in a byte we still need to access one byte per nibble - bytes_per_pixel = 1; - } else { - bytes_per_pixel = nibbles_per_pixel / 2; - } + const u32 nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format); + const u32 stride = nibbles_per_pixel * surface_width / 2; + const bool nibble_mode = (nibbles_per_pixel == 1); + const u32 bytes_per_pixel = [&] { + if (nibble_mode) { + // As nibbles are contained in a byte we still need to access one byte per nibble + return 1u; + } else { + return nibbles_per_pixel / 2; + } + }(); const u32 coarse_y = y & ~7; - u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; + const u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; const u8* pixel = buffer + (nibble_mode ? (offset / 2) : offset); - auto GetText = [offset](Format format, const u8* pixel) { + const auto get_text = [offset](Format format, const u8* pixel) { switch (format) { case Format::RGBA8: { - auto value = Common::Color::DecodeRGBA8(pixel) / 255.0f; + const auto value = Common::Color::DecodeRGBA8(pixel) / 255.0f; return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4") .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2)); } case Format::RGB8: { - auto value = Common::Color::DecodeRGB8(pixel) / 255.0f; + const auto value = Common::Color::DecodeRGB8(pixel) / 255.0f; return QStringLiteral("Red: %1, Green: %2, Blue: %3") .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), QString::number(value.b(), 'f', 2)); } case Format::RGB5A1: { - auto value = Common::Color::DecodeRGB5A1(pixel) / 255.0f; + const auto value = Common::Color::DecodeRGB5A1(pixel) / 255.0f; return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4") .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2)); } case Format::RGB565: { - auto value = Common::Color::DecodeRGB565(pixel) / 255.0f; + const auto value = Common::Color::DecodeRGB565(pixel) / 255.0f; return QStringLiteral("Red: %1, Green: %2, Blue: %3") .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), QString::number(value.b(), 'f', 2)); } case Format::RGBA4: { - auto value = Common::Color::DecodeRGBA4(pixel) / 255.0f; + const auto value = Common::Color::DecodeRGBA4(pixel) / 255.0f; return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4") .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2)); @@ -348,7 +347,7 @@ void GraphicsSurfaceWidget::Pick(int x, int y) { case Format::IA8: return QStringLiteral("Index: %1, Alpha: %2").arg(pixel[0], pixel[1]); case Format::RG8: { - auto value = Common::Color::DecodeRG8(pixel) / 255.0f; + const auto value = Common::Color::DecodeRG8(pixel) / 255.0f; return QStringLiteral("Red: %1, Green: %2") .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2)); } @@ -359,11 +358,11 @@ void GraphicsSurfaceWidget::Pick(int x, int y) { case Format::IA4: return QStringLiteral("Index: %1, Alpha: %2").arg(*pixel & 0xF, (*pixel & 0xF0) >> 4); case Format::I4: { - u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; + const u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; return QStringLiteral("Index: %1").arg(i); } case Format::A4: { - u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; + const u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; return QStringLiteral("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2)); } case Format::ETC1: @@ -371,17 +370,17 @@ void GraphicsSurfaceWidget::Pick(int x, int y) { // TODO: Display block information or channel values? return QStringLiteral("Compressed data"); case Format::D16: { - auto value = Common::Color::DecodeD16(pixel); + const auto value = Common::Color::DecodeD16(pixel); return QStringLiteral("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4)); } case Format::D24: { - auto value = Common::Color::DecodeD24(pixel); + const auto value = Common::Color::DecodeD24(pixel); return QStringLiteral("Depth: %1") .arg(QString::number(value / (float)0xFFFFFF, 'f', 4)); } case Format::D24X8: case Format::X24S8: { - auto values = Common::Color::DecodeD24S8(pixel); + const auto values = Common::Color::DecodeD24S8(pixel); return QStringLiteral("Depth: %1, Stencil: %2") .arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4), values[1]); } @@ -398,13 +397,13 @@ void GraphicsSurfaceWidget::Pick(int x, int y) { if (nibble_mode) { nibble_index += (offset % 2) ? 0 : 1; } - u8 byte = pixel[nibble_index / 2]; - u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF; + const u8 byte = pixel[nibble_index / 2]; + const u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF; nibbles.append(QString::number(nibble, 16).toUpper()); } surface_info_label->setText( - QStringLiteral("Raw: 0x%3\n(%4)").arg(nibbles, GetText(surface_format, pixel))); + QStringLiteral("Raw: 0x%3\n(%4)").arg(nibbles, get_text(surface_format, pixel))); surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); } @@ -546,9 +545,9 @@ void GraphicsSurfaceWidget::OnUpdate() { // TODO: Implement a good way to visualize alpha components! QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32); - u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address); + const u8* buffer = memory.GetPhysicalPointer(surface_address); - if (buffer == nullptr) { + if (!buffer) { surface_picture_label->hide(); surface_info_label->setText(tr("(invalid surface address)")); surface_info_label->setAlignment(Qt::AlignCenter); @@ -682,9 +681,8 @@ void GraphicsSurfaceWidget::SaveSurface() { tr("Failed to save surface data to file '%1'").arg(filename)); } } else if (selected_filter == bin_filter) { - const u8* const buffer = - Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address); - ASSERT_MSG(buffer != nullptr, "Memory not accessible"); + const u8* const buffer = memory.GetPhysicalPointer(surface_address); + ASSERT_MSG(buffer, "Memory not accessible"); QFile file{filename}; if (!file.open(QIODevice::WriteOnly)) { diff --git a/src/citra_qt/debugger/graphics/graphics_surface.h b/src/citra_qt/debugger/graphics/graphics_surface.h index 7f4c9d3ca..7fd6b8111 100644 --- a/src/citra_qt/debugger/graphics/graphics_surface.h +++ b/src/citra_qt/debugger/graphics/graphics_surface.h @@ -14,6 +14,10 @@ class CSpinBox; class GraphicsSurfaceWidget; +namespace Memory { +class MemorySystem; +} + class SurfacePicture : public QLabel { Q_OBJECT @@ -72,7 +76,8 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock { static unsigned int NibblesPerPixel(Format format); public: - explicit GraphicsSurfaceWidget(std::shared_ptr debug_context, + explicit GraphicsSurfaceWidget(Memory::MemorySystem& memory, + std::shared_ptr debug_context, QWidget* parent = nullptr); void Pick(int x, int y); @@ -95,6 +100,7 @@ private: void SaveSurface(); + Memory::MemorySystem& memory; QComboBox* surface_source_list; CSpinBox* surface_address_control; QSpinBox* surface_width_control; diff --git a/src/citra_qt/debugger/ipc/recorder.cpp b/src/citra_qt/debugger/ipc/recorder.cpp index b9ba70446..27382bbec 100644 --- a/src/citra_qt/debugger/ipc/recorder.cpp +++ b/src/citra_qt/debugger/ipc/recorder.cpp @@ -16,13 +16,13 @@ #include "core/hle/service/sm/sm.h" #include "ui_recorder.h" -IPCRecorderWidget::IPCRecorderWidget(QWidget* parent) - : QDockWidget(parent), ui(std::make_unique()) { +IPCRecorderWidget::IPCRecorderWidget(Core::System& system_, QWidget* parent) + : QDockWidget(parent), ui(std::make_unique()), system{system_} { ui->setupUi(this); qRegisterMetaType(); - connect(ui->enabled, &QCheckBox::stateChanged, + connect(ui->enabled, &QCheckBox::stateChanged, this, [this](int new_state) { SetEnabled(new_state == Qt::Checked); }); connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear); connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll); @@ -90,7 +90,7 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) { (record.status == IPCDebugger::RequestStatus::Handled && record.translated_reply_cmdbuf[1] != RESULT_SUCCESS.raw)) { // Unimplemented / Error - auto* item = ui->main->invisibleRootItem()->child(row_id); + auto item = ui->main->invisibleRootItem()->child(row_id); for (int column = 0; column < item->columnCount(); ++column) { item->setBackground(column, QBrush(QColor::fromRgb(255, 0, 0))); } @@ -100,11 +100,11 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) { } void IPCRecorderWidget::SetEnabled(bool enabled) { - if (!Core::System::GetInstance().IsPoweredOn()) { + if (!system.IsPoweredOn()) { return; } - auto& ipc_recorder = Core::System::GetInstance().Kernel().GetIPCRecorder(); + auto& ipc_recorder = system.Kernel().GetIPCRecorder(); ipc_recorder.SetEnabled(enabled); if (enabled) { @@ -123,10 +123,10 @@ void IPCRecorderWidget::Clear() { } QString IPCRecorderWidget::GetServiceName(const IPCDebugger::RequestRecord& record) const { - if (Core::System::GetInstance().IsPoweredOn() && record.client_port.id != -1) { - const auto service_name = - Core::System::GetInstance().ServiceManager().GetServiceNameByPortId( - static_cast(record.client_port.id)); + if (system.IsPoweredOn() && record.client_port.id != -1) { + const Service::SM::ServiceManager& sm = system.ServiceManager(); + const u32 port_id = static_cast(record.client_port.id); + const auto service_name = sm.GetServiceNameByPortId(port_id); if (!service_name.empty()) { return QString::fromStdString(service_name); diff --git a/src/citra_qt/debugger/ipc/recorder.h b/src/citra_qt/debugger/ipc/recorder.h index aa02041e8..de0e512be 100644 --- a/src/citra_qt/debugger/ipc/recorder.h +++ b/src/citra_qt/debugger/ipc/recorder.h @@ -14,11 +14,15 @@ namespace Ui { class IPCRecorder; } +namespace Core { +class System; +} + class IPCRecorderWidget : public QDockWidget { Q_OBJECT public: - explicit IPCRecorderWidget(QWidget* parent = nullptr); + explicit IPCRecorderWidget(Core::System& system, QWidget* parent = nullptr); ~IPCRecorderWidget(); void OnEmulationStarting(); @@ -37,9 +41,10 @@ private: QString GetFunctionName(const IPCDebugger::RequestRecord& record) const; void OpenRecordDialog(QTreeWidgetItem* item, int column); +private: std::unique_ptr ui; IPCDebugger::CallbackHandle handle; - + Core::System& system; // The offset between record id and row id, assuming record ids are assigned // continuously and only the 'Clear' action can be performed, this is enough. // The initial value is 1, which means record 1 = row 0. diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp index 6e07869d0..df065ca5c 100644 --- a/src/citra_qt/debugger/registers.cpp +++ b/src/citra_qt/debugger/registers.cpp @@ -9,8 +9,8 @@ #include "core/core.h" #include "ui_registers.h" -RegistersWidget::RegistersWidget(QWidget* parent) - : QDockWidget(parent), cpu_regs_ui(std::make_unique()) { +RegistersWidget::RegistersWidget(const Core::System& system_, QWidget* parent) + : QDockWidget(parent), cpu_regs_ui(std::make_unique()), system{system_} { cpu_regs_ui->setupUi(this); tree = cpu_regs_ui->treeWidget; @@ -62,17 +62,21 @@ RegistersWidget::RegistersWidget(QWidget* parent) RegistersWidget::~RegistersWidget() = default; void RegistersWidget::OnDebugModeEntered() { - if (!Core::System::GetInstance().IsPoweredOn()) + if (!system.IsPoweredOn()) { return; + } - // Todo: Handle all cores - for (int i = 0; i < core_registers->childCount(); ++i) + // TODO: Handle all cores + const ARM_Interface& core = system.GetCore(0); + for (int i = 0; i < core_registers->childCount(); ++i) { core_registers->child(i)->setText( - 1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetReg(i), 8, 16, QLatin1Char('0'))); + 1, QStringLiteral("0x%1").arg(core.GetReg(i), 8, 16, QLatin1Char('0'))); + } - for (int i = 0; i < vfp_registers->childCount(); ++i) + for (int i = 0; i < vfp_registers->childCount(); ++i) { vfp_registers->child(i)->setText( - 1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetVFPReg(i), 8, 16, QLatin1Char('0'))); + 1, QStringLiteral("0x%1").arg(core.GetVFPReg(i), 8, 16, QLatin1Char('0'))); + } UpdateCPSRValues(); UpdateVFPSystemRegisterValues(); @@ -86,24 +90,29 @@ void RegistersWidget::OnEmulationStarting(EmuThread* emu_thread) { void RegistersWidget::OnEmulationStopping() { // Reset widget text - for (int i = 0; i < core_registers->childCount(); ++i) + for (int i = 0; i < core_registers->childCount(); ++i) { core_registers->child(i)->setText(1, QString{}); + } - for (int i = 0; i < vfp_registers->childCount(); ++i) + for (int i = 0; i < vfp_registers->childCount(); ++i) { vfp_registers->child(i)->setText(1, QString{}); + } - for (int i = 0; i < cpsr->childCount(); ++i) + for (int i = 0; i < cpsr->childCount(); ++i) { cpsr->child(i)->setText(1, QString{}); + } cpsr->setText(1, QString{}); // FPSCR - for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i) + for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i) { vfp_system_registers->child(0)->child(i)->setText(1, QString{}); + } // FPEXC - for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i) + for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i) { vfp_system_registers->child(1)->child(i)->setText(1, QString{}); + } vfp_system_registers->child(0)->setText(1, QString{}); vfp_system_registers->child(1)->setText(1, QString{}); @@ -130,8 +139,8 @@ void RegistersWidget::CreateCPSRChildren() { } void RegistersWidget::UpdateCPSRValues() { - // Todo: Handle all cores - const u32 cpsr_val = Core::GetCore(0).GetCPSR(); + // TODO: Handle all cores + const u32 cpsr_val = system.GetCore(0).GetCPSR(); cpsr->setText(1, QStringLiteral("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); cpsr->child(0)->setText( @@ -193,9 +202,10 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() { } void RegistersWidget::UpdateVFPSystemRegisterValues() { - // Todo: handle all cores - const u32 fpscr_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPSCR); - const u32 fpexc_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPEXC); + // TODO: handle all cores + const ARM_Interface& core = system.GetCore(0); + const u32 fpscr_val = core.GetVFPSystemReg(VFP_FPSCR); + const u32 fpexc_val = core.GetVFPSystemReg(VFP_FPEXC); QTreeWidgetItem* const fpscr = vfp_system_registers->child(0); fpscr->setText(1, QStringLiteral("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0'))); diff --git a/src/citra_qt/debugger/registers.h b/src/citra_qt/debugger/registers.h index 5d3c1df22..19ed374ea 100644 --- a/src/citra_qt/debugger/registers.h +++ b/src/citra_qt/debugger/registers.h @@ -15,11 +15,15 @@ namespace Ui { class ARMRegisters; } +namespace Core { +class System; +} + class RegistersWidget : public QDockWidget { Q_OBJECT public: - explicit RegistersWidget(QWidget* parent = nullptr); + explicit RegistersWidget(const Core::System& system, QWidget* parent = nullptr); ~RegistersWidget(); public slots: @@ -37,7 +41,7 @@ private: void UpdateVFPSystemRegisterValues(); std::unique_ptr cpu_regs_ui; - + const Core::System& system; QTreeWidget* tree; QTreeWidgetItem* core_registers; diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp index 67baf0fec..a277dc81a 100644 --- a/src/citra_qt/debugger/wait_tree.cpp +++ b/src/citra_qt/debugger/wait_tree.cpp @@ -75,13 +75,13 @@ std::size_t WaitTreeItem::Row() const { return row; } -std::vector> WaitTreeItem::MakeThreadItemList() { - const u32 num_cores = Core::GetNumCores(); +std::vector> WaitTreeItem::MakeThreadItemList( + Core::System& system) { + const u32 num_cores = system.GetNumCores(); std::vector> item_list; item_list.reserve(num_cores); for (u32 i = 0; i < num_cores; ++i) { - const auto& threads = - Core::System::GetInstance().Kernel().GetThreadManager(i).GetThreadList(); + const auto threads = system.Kernel().GetThreadManager(i).GetThreadList(); item_list.reserve(item_list.size() + threads.size()); for (std::size_t j = 0; j < threads.size(); ++j) { item_list.push_back(std::make_unique(*threads[j])); @@ -435,11 +435,12 @@ void WaitTreeModel::ClearItems() { thread_items.clear(); } -void WaitTreeModel::InitItems() { - thread_items = WaitTreeItem::MakeThreadItemList(); +void WaitTreeModel::InitItems(Core::System& system) { + thread_items = WaitTreeItem::MakeThreadItemList(system); } -WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), parent) { +WaitTreeWidget::WaitTreeWidget(Core::System& system_, QWidget* parent) + : QDockWidget(tr("Wait Tree"), parent), system{system_} { setObjectName(QStringLiteral("WaitTreeWidget")); view = new QTreeView(this); view->setHeaderHidden(true); @@ -448,9 +449,10 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p } void WaitTreeWidget::OnDebugModeEntered() { - if (!Core::System::GetInstance().IsPoweredOn()) + if (!system.IsPoweredOn()) { return; - model->InitItems(); + } + model->InitItems(system); view->setModel(model); setEnabled(true); } diff --git a/src/citra_qt/debugger/wait_tree.h b/src/citra_qt/debugger/wait_tree.h index eca8534c5..bb9385649 100644 --- a/src/citra_qt/debugger/wait_tree.h +++ b/src/citra_qt/debugger/wait_tree.h @@ -23,6 +23,10 @@ class Thread; class Timer; } // namespace Kernel +namespace Core { +class System; +} + class WaitTreeThread; class WaitTreeItem : public QObject { @@ -39,7 +43,7 @@ public: WaitTreeItem* Parent() const; std::span> Children() const; std::size_t Row() const; - static std::vector> MakeThreadItemList(); + static std::vector> MakeThreadItemList(Core::System& system); private: std::size_t row; @@ -166,7 +170,7 @@ public: int columnCount(const QModelIndex& parent) const override; void ClearItems(); - void InitItems(); + void InitItems(Core::System& system); private: std::vector> thread_items; @@ -176,7 +180,7 @@ class WaitTreeWidget : public QDockWidget { Q_OBJECT public: - explicit WaitTreeWidget(QWidget* parent = nullptr); + explicit WaitTreeWidget(Core::System& system, QWidget* parent = nullptr); public slots: void OnDebugModeEntered(); @@ -188,4 +192,5 @@ public slots: private: QTreeView* view; WaitTreeModel* model; + Core::System& system; }; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index c9e9cdc6f..b447af323 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -353,8 +353,8 @@ void GMainWindow::InitializeWidgets() { }); InputCommon::Init(); - multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room, - ui->action_Show_Room); + multiplayer_state = new MultiplayerState(system, this, game_list->GetModel(), + ui->action_Leave_Room, ui->action_Show_Room); multiplayer_state->setVisible(false); #if ENABLE_QT_UPDATER @@ -434,7 +434,7 @@ void GMainWindow::InitializeDebugWidgets() { debug_menu->addAction(microProfileDialog->toggleViewAction()); #endif - registersWidget = new RegistersWidget(this); + registersWidget = new RegistersWidget(system, this); addDockWidget(Qt::RightDockWidgetArea, registersWidget); registersWidget->hide(); debug_menu->addAction(registersWidget->toggleViewAction()); @@ -448,7 +448,7 @@ void GMainWindow::InitializeDebugWidgets() { graphicsWidget->hide(); debug_menu->addAction(graphicsWidget->toggleViewAction()); - graphicsCommandsWidget = new GPUCommandListWidget(this); + graphicsCommandsWidget = new GPUCommandListWidget(system.Memory(), this); addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); graphicsCommandsWidget->hide(); debug_menu->addAction(graphicsCommandsWidget->toggleViewAction()); @@ -472,7 +472,7 @@ void GMainWindow::InitializeDebugWidgets() { connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget, &GraphicsTracingWidget::OnEmulationStopping); - waitTreeWidget = new WaitTreeWidget(this); + waitTreeWidget = new WaitTreeWidget(system, this); addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget); waitTreeWidget->hide(); debug_menu->addAction(waitTreeWidget->toggleViewAction()); @@ -490,7 +490,7 @@ void GMainWindow::InitializeDebugWidgets() { connect(this, &GMainWindow::EmulationStopping, waitTreeWidget, [this] { lleServiceModulesWidget->setDisabled(false); }); - ipcRecorderWidget = new IPCRecorderWidget(this); + ipcRecorderWidget = new IPCRecorderWidget(system, this); addDockWidget(Qt::RightDockWidgetArea, ipcRecorderWidget); ipcRecorderWidget->hide(); debug_menu->addAction(ipcRecorderWidget->toggleViewAction()); @@ -2046,7 +2046,6 @@ void GMainWindow::OnLoadAmiibo() { return; } - Core::System& system{Core::System::GetInstance()}; Service::SM::ServiceManager& sm = system.ServiceManager(); auto nfc = sm.GetService("nfc:u"); if (nfc == nullptr) { @@ -2118,7 +2117,8 @@ void GMainWindow::OnToggleFilterBar() { } void GMainWindow::OnCreateGraphicsSurfaceViewer() { - auto graphicsSurfaceViewerWidget = new GraphicsSurfaceWidget(Pica::g_debug_context, this); + auto graphicsSurfaceViewerWidget = + new GraphicsSurfaceWidget(system.Memory(), Pica::g_debug_context, this); addDockWidget(Qt::RightDockWidgetArea, graphicsSurfaceViewerWidget); // TODO: Maybe graphicsSurfaceViewerWidget->setFloating(true); graphicsSurfaceViewerWidget->show(); diff --git a/src/citra_qt/multiplayer/direct_connect.cpp b/src/citra_qt/multiplayer/direct_connect.cpp index 3b2b6549e..936fd0435 100644 --- a/src/citra_qt/multiplayer/direct_connect.cpp +++ b/src/citra_qt/multiplayer/direct_connect.cpp @@ -9,10 +9,8 @@ #include #include #include "citra_qt/main.h" -#include "citra_qt/multiplayer/client_room.h" #include "citra_qt/multiplayer/direct_connect.h" #include "citra_qt/multiplayer/message.h" -#include "citra_qt/multiplayer/state.h" #include "citra_qt/multiplayer/validation.h" #include "citra_qt/uisettings.h" #include "core/hle/service/cfg/cfg.h" @@ -22,9 +20,9 @@ enum class ConnectionType : u8 { TraversalServer, IP }; -DirectConnectWindow::DirectConnectWindow(QWidget* parent) +DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique()) { + ui(std::make_unique()), system{system_} { ui->setupUi(this); @@ -91,7 +89,7 @@ void DirectConnectWindow::Connect() { if (auto room_member = Network::GetRoomMember().lock()) { auto port = UISettings::values.port.toUInt(); room_member->Join(ui->nickname->text().toStdString(), - Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), + Service::CFG::GetConsoleIdHash(system), ui->ip->text().toStdString().c_str(), port, 0, Network::NoPreferredMac, ui->password->text().toStdString().c_str()); } diff --git a/src/citra_qt/multiplayer/direct_connect.h b/src/citra_qt/multiplayer/direct_connect.h index 757ec24a0..b03fa06c7 100644 --- a/src/citra_qt/multiplayer/direct_connect.h +++ b/src/citra_qt/multiplayer/direct_connect.h @@ -13,11 +13,15 @@ namespace Ui { class DirectConnect; } +namespace Core { +class System; +} + class DirectConnectWindow : public QDialog { Q_OBJECT public: - explicit DirectConnectWindow(QWidget* parent = nullptr); + explicit DirectConnectWindow(Core::System& system, QWidget* parent = nullptr); ~DirectConnectWindow(); void RetranslateUi(); @@ -39,5 +43,6 @@ private: QFutureWatcher* watcher; std::unique_ptr ui; + Core::System& system; Validation validation; }; diff --git a/src/citra_qt/multiplayer/host_room.cpp b/src/citra_qt/multiplayer/host_room.cpp index 498ce943b..8a1ca02e2 100644 --- a/src/citra_qt/multiplayer/host_room.cpp +++ b/src/citra_qt/multiplayer/host_room.cpp @@ -12,7 +12,6 @@ #include #include #include "citra_qt/game_list_p.h" -#include "citra_qt/main.h" #include "citra_qt/multiplayer/host_room.h" #include "citra_qt/multiplayer/message.h" #include "citra_qt/multiplayer/state.h" @@ -27,10 +26,10 @@ #include "web_service/verify_user_jwt.h" #endif -HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, +HostRoomWindow::HostRoomWindow(Core::System& system_, QWidget* parent, QStandardItemModel* list, std::shared_ptr session) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique()), announce_multiplayer_session(session) { + ui(std::make_unique()), system{system_}, announce_multiplayer_session(session) { ui->setupUi(this); // set up validation for all of the fields @@ -196,9 +195,8 @@ void HostRoomWindow::Host() { } } #endif - member->Join(ui->username->text().toStdString(), - Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), "127.0.0.1", port, - 0, Network::NoPreferredMac, password, token); + member->Join(ui->username->text().toStdString(), Service::CFG::GetConsoleIdHash(system), + "127.0.0.1", port, 0, Network::NoPreferredMac, password, token); // Store settings UISettings::values.room_nickname = ui->username->text(); diff --git a/src/citra_qt/multiplayer/host_room.h b/src/citra_qt/multiplayer/host_room.h index b6f84f078..e481bd000 100644 --- a/src/citra_qt/multiplayer/host_room.h +++ b/src/citra_qt/multiplayer/host_room.h @@ -9,14 +9,16 @@ #include #include #include -#include "citra_qt/multiplayer/chat_room.h" #include "citra_qt/multiplayer/validation.h" -#include "network/network.h" namespace Ui { class HostRoom; } +namespace Core { +class System; +} + namespace Network { class AnnounceMultiplayerSession; } @@ -34,7 +36,7 @@ class HostRoomWindow : public QDialog { Q_OBJECT public: - explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list, + explicit HostRoomWindow(Core::System& system, QWidget* parent, QStandardItemModel* list, std::shared_ptr session); ~HostRoomWindow(); @@ -50,6 +52,7 @@ private: std::unique_ptr CreateVerifyBackend(bool use_validation) const; std::unique_ptr ui; + Core::System& system; std::weak_ptr announce_multiplayer_session; QStandardItemModel* game_list; ComboBoxProxyModel* proxy; diff --git a/src/citra_qt/multiplayer/lobby.cpp b/src/citra_qt/multiplayer/lobby.cpp index 72f11b9db..862ed19a5 100644 --- a/src/citra_qt/multiplayer/lobby.cpp +++ b/src/citra_qt/multiplayer/lobby.cpp @@ -7,11 +7,9 @@ #include #include "citra_qt/game_list_p.h" #include "citra_qt/main.h" -#include "citra_qt/multiplayer/client_room.h" #include "citra_qt/multiplayer/lobby.h" #include "citra_qt/multiplayer/lobby_p.h" #include "citra_qt/multiplayer/message.h" -#include "citra_qt/multiplayer/state.h" #include "citra_qt/multiplayer/validation.h" #include "citra_qt/uisettings.h" #include "common/logging/log.h" @@ -23,10 +21,10 @@ #include "web_service/web_backend.h" #endif -Lobby::Lobby(QWidget* parent, QStandardItemModel* list, +Lobby::Lobby(Core::System& system_, QWidget* parent, QStandardItemModel* list, std::shared_ptr session) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique()), announce_multiplayer_session(session) { + ui(std::make_unique()), system{system_}, announce_multiplayer_session(session) { ui->setupUi(this); // setup the watcher for background connections @@ -152,8 +150,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { const std::string verify_UID = proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString(); - // attempt to connect in a different thread - QFuture f = QtConcurrent::run([nickname, ip, port, password, verify_UID] { + // Attempt to connect in a different thread + QFuture f = QtConcurrent::run([this, nickname, ip, port, password, verify_UID] { std::string token; #ifdef ENABLE_WEB_SERVICE if (!NetSettings::values.citra_username.empty() && @@ -170,8 +168,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { } #endif if (auto room_member = Network::GetRoomMember().lock()) { - room_member->Join(nickname, Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), - ip.c_str(), port, 0, Network::NoPreferredMac, password, token); + room_member->Join(nickname, Service::CFG::GetConsoleIdHash(system), ip.c_str(), port, 0, + Network::NoPreferredMac, password, token); } }); watcher->setFuture(f); diff --git a/src/citra_qt/multiplayer/lobby.h b/src/citra_qt/multiplayer/lobby.h index 129b25497..f245c7ac6 100644 --- a/src/citra_qt/multiplayer/lobby.h +++ b/src/citra_qt/multiplayer/lobby.h @@ -12,12 +12,16 @@ #include "citra_qt/multiplayer/validation.h" #include "common/announce_multiplayer_room.h" #include "network/announce_multiplayer_session.h" -#include "network/network.h" +#include "network/room_member.h" namespace Ui { class Lobby; } +namespace Core { +class System; +} + class LobbyModel; class LobbyFilterProxyModel; @@ -29,7 +33,7 @@ class Lobby : public QDialog { Q_OBJECT public: - explicit Lobby(QWidget* parent, QStandardItemModel* list, + explicit Lobby(Core::System& system, QWidget* parent, QStandardItemModel* list, std::shared_ptr session); ~Lobby() override; @@ -84,7 +88,9 @@ private: */ QString PasswordPrompt(); +private: std::unique_ptr ui; + Core::System& system; QStandardItemModel* model{}; QStandardItemModel* game_list{}; diff --git a/src/citra_qt/multiplayer/state.cpp b/src/citra_qt/multiplayer/state.cpp index 2835cae75..72a36c6af 100644 --- a/src/citra_qt/multiplayer/state.cpp +++ b/src/citra_qt/multiplayer/state.cpp @@ -17,9 +17,10 @@ #include "citra_qt/util/clickable_label.h" #include "common/logging/log.h" -MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model, - QAction* leave_room, QAction* show_room) - : QWidget(parent), game_list_model(game_list_model), leave_room(leave_room), +MultiplayerState::MultiplayerState(Core::System& system_, QWidget* parent, + QStandardItemModel* game_list_model, QAction* leave_room, + QAction* show_room) + : QWidget(parent), system{system_}, game_list_model(game_list_model), leave_room(leave_room), show_room(show_room) { if (auto member = Network::GetRoomMember().lock()) { // register the network structs to use in slots and signals @@ -203,14 +204,14 @@ static void BringWidgetToFront(QWidget* widget) { void MultiplayerState::OnViewLobby() { if (lobby == nullptr) { - lobby = new Lobby(this, game_list_model, announce_multiplayer_session); + lobby = new Lobby(system, this, game_list_model, announce_multiplayer_session); } BringWidgetToFront(lobby); } void MultiplayerState::OnCreateRoom() { if (host_room == nullptr) { - host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session); + host_room = new HostRoomWindow(system, this, game_list_model, announce_multiplayer_session); } BringWidgetToFront(host_room); } @@ -274,7 +275,7 @@ void MultiplayerState::OnOpenNetworkRoom() { void MultiplayerState::OnDirectConnectToRoom() { if (direct_connect == nullptr) { - direct_connect = new DirectConnectWindow(this); + direct_connect = new DirectConnectWindow(system, this); } BringWidgetToFront(direct_connect); } diff --git a/src/citra_qt/multiplayer/state.h b/src/citra_qt/multiplayer/state.h index 3607d97af..ccdec4933 100644 --- a/src/citra_qt/multiplayer/state.h +++ b/src/citra_qt/multiplayer/state.h @@ -15,12 +15,16 @@ class ClientRoomWindow; class DirectConnectWindow; class ClickableLabel; +namespace Core { +class System; +} + class MultiplayerState : public QWidget { Q_OBJECT; public: - explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room, - QAction* show_room); + explicit MultiplayerState(Core::System& system, QWidget* parent, QStandardItemModel* game_list, + QAction* leave_room, QAction* show_room); ~MultiplayerState(); /** @@ -71,6 +75,7 @@ signals: void AnnounceFailed(const Common::WebResult&); private: + Core::System& system; Lobby* lobby = nullptr; HostRoomWindow* host_room = nullptr; ClientRoomWindow* client_room = nullptr; diff --git a/src/citra_qt/updater/updater.cpp b/src/citra_qt/updater/updater.cpp index 498ba986c..d88e2cb0f 100644 --- a/src/citra_qt/updater/updater.cpp +++ b/src/citra_qt/updater/updater.cpp @@ -130,11 +130,9 @@ bool UpdaterPrivate::StartUpdateCheck() { main_process->setProgram(tool_info.absoluteFilePath()); main_process->setArguments({QStringLiteral("--checkupdates"), QStringLiteral("-v")}); - connect(main_process, - static_cast(&QProcess::finished), this, + connect(main_process, qOverload(&QProcess::finished), this, &UpdaterPrivate::UpdaterReady, Qt::QueuedConnection); - connect(main_process, - static_cast(&QProcess::errorOccurred), this, + connect(main_process, qOverload(&QProcess::errorOccurred), this, &UpdaterPrivate::UpdaterError, Qt::QueuedConnection); main_process->start(QIODevice::ReadOnly); @@ -156,7 +154,7 @@ void UpdaterPrivate::StopUpdateCheck(int delay, bool async) { QTimer* timer = new QTimer(this); timer->setSingleShot(true); - connect(timer, &QTimer::timeout, [this, timer]() { + connect(timer, &QTimer::timeout, this, [this, timer]() { StopUpdateCheck(0, false); timer->deleteLater(); }); diff --git a/src/core/core.cpp b/src/core/core.cpp index f0528724e..97f71d7d6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -86,7 +86,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) { if (thread && running_core) { running_core->SaveContext(thread->context); } - GDBStub::HandlePacket(); + GDBStub::HandlePacket(*this); // If the loop is halted and we want to step, use a tiny (1) number of instructions to // execute. Otherwise, get out of the loop function. @@ -368,7 +368,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, const Kernel::New3dsHwCapabilities& n3ds_hw_caps, u32 num_cores) { LOG_DEBUG(HW_Memory, "initialized OK"); - memory = std::make_unique(); + memory = std::make_unique(*this); timing = std::make_unique(num_cores, Settings::values.cpu_clock_percentage.GetValue()); @@ -632,9 +632,9 @@ void System::ApplySettings() { if (IsPoweredOn()) { CoreTiming().UpdateClockSpeed(Settings::values.cpu_clock_percentage.GetValue()); - Core::DSP().SetSink(Settings::values.output_type.GetValue(), - Settings::values.output_device.GetValue()); - Core::DSP().EnableStretching(Settings::values.enable_audio_stretching.GetValue()); + dsp_core->SetSink(Settings::values.output_type.GetValue(), + Settings::values.output_device.GetValue()); + dsp_core->EnableStretching(Settings::values.enable_audio_stretching.GetValue()); auto hid = Service::HID::GetModule(*this); if (hid) { diff --git a/src/core/core.h b/src/core/core.h index d0ac12a3c..4c401b736 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -194,6 +194,10 @@ public: return *cpu_cores[core_id]; }; + [[nodiscard]] const ARM_Interface& GetCore(u32 core_id) const { + return *cpu_cores[core_id]; + }; + [[nodiscard]] u32 GetNumCores() const { return static_cast(cpu_cores.size()); } @@ -451,10 +455,6 @@ private: return System::GetInstance().GetNumCores(); } -[[nodiscard]] inline AudioCore::DspInterface& DSP() { - return System::GetInstance().DSP(); -} - } // namespace Core BOOST_CLASS_VERSION(Core::System, 1) diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 592078aa2..e0257f0a6 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -36,7 +36,6 @@ #include "core/gdbstub/gdbstub.h" #include "core/gdbstub/hio.h" #include "core/hle/kernel/process.h" -#include "core/loader/loader.h" #include "core/memory.h" namespace GDBStub { @@ -1035,7 +1034,7 @@ static void RemoveBreakpoint() { SendReply("OK"); } -void HandlePacket() { +void HandlePacket(Core::System& system) { if (!IsConnected()) { if (defer_start) { ToggleServer(true); @@ -1076,7 +1075,7 @@ void HandlePacket() { Continue(); return; case 'F': - HandleHioReply(command_buffer, command_length); + HandleHioReply(system, command_buffer, command_length); break; case 'g': ReadRegisters(); diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h index d361eb1ea..fc0c7df23 100644 --- a/src/core/gdbstub/gdbstub.h +++ b/src/core/gdbstub/gdbstub.h @@ -10,6 +10,10 @@ #include "common/common_types.h" #include "core/hle/kernel/thread.h" +namespace Core { +class System; +} + namespace GDBStub { /// Breakpoint Method @@ -70,7 +74,7 @@ void Break(bool is_memory_break = false); bool IsMemoryBreak(); /// Read and handle packet from gdb client. -void HandlePacket(); +void HandlePacket(Core::System& system); /** * Get the nearest breakpoint of the specified type at the given address. diff --git a/src/core/gdbstub/hio.cpp b/src/core/gdbstub/hio.cpp index c9c1cb161..00eab9061 100644 --- a/src/core/gdbstub/hio.cpp +++ b/src/core/gdbstub/hio.cpp @@ -54,7 +54,7 @@ static void SendErrorReply(int error_code, int retval = -1) { SendReply(packet.data()); } -void SetHioRequest(const VAddr addr) { +void SetHioRequest(Core::System& system, const VAddr addr) { if (!IsServerEnabled()) { LOG_WARNING(Debug_GDBStub, "HIO requested but GDB stub is not running"); return; @@ -69,15 +69,15 @@ void SetHioRequest(const VAddr addr) { LOG_INFO(Debug_GDBStub, "overwriting existing HIO request that was not sent yet"); } - auto& memory = Core::System::GetInstance().Memory(); - const auto process = Core::System::GetInstance().Kernel().GetCurrentProcess(); + auto& memory = system.Memory(); + const auto process = system.Kernel().GetCurrentProcess(); if (!memory.IsValidVirtualAddress(*process, addr)) { LOG_WARNING(Debug_GDBStub, "Invalid address for HIO request"); return; } - memory.ReadBlock(*process, addr, ¤t_hio_request, sizeof(PackedGdbHioRequest)); + memory.ReadBlock(addr, ¤t_hio_request, sizeof(PackedGdbHioRequest)); if (current_hio_request.magic != std::array{'G', 'D', 'B', '\0'}) { std::string_view bad_magic{ @@ -105,10 +105,11 @@ void SetHioRequest(const VAddr addr) { Break(); SetCpuHaltFlag(true); SetCpuStepFlag(false); - Core::GetRunningCore().ClearInstructionCache(); + system.GetRunningCore().ClearInstructionCache(); } -void HandleHioReply(const u8* const command_buffer, const u32 command_length) { +void HandleHioReply(Core::System& system, const u8* const command_buffer, + const u32 command_length) { if (!IsWaitingForHioReply()) { LOG_WARNING(Debug_GDBStub, "Got HIO reply but never sent a request"); return; @@ -176,8 +177,8 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) { current_hio_request.retval, current_hio_request.gdb_errno, current_hio_request.ctrl_c); - const auto process = Core::System::GetInstance().Kernel().GetCurrentProcess(); - auto& memory = Core::System::GetInstance().Memory(); + const auto process = system.Kernel().GetCurrentProcess(); + auto& memory = system.Memory(); // should have been checked when we first initialized the request, // but just double check again before we write to memory @@ -187,8 +188,7 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) { return; } - memory.WriteBlock(*process, current_hio_request_addr, ¤t_hio_request, - sizeof(PackedGdbHioRequest)); + memory.WriteBlock(current_hio_request_addr, ¤t_hio_request, sizeof(PackedGdbHioRequest)); current_hio_request = {}; current_hio_request_addr = 0; @@ -197,7 +197,7 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) { // Restore state from before the request came in SetCpuStepFlag(was_stepping); SetCpuHaltFlag(was_halted); - Core::GetRunningCore().ClearInstructionCache(); + system.GetRunningCore().ClearInstructionCache(); } bool HandlePendingHioRequestPacket() { diff --git a/src/core/gdbstub/hio.h b/src/core/gdbstub/hio.h index d498a2737..827521841 100644 --- a/src/core/gdbstub/hio.h +++ b/src/core/gdbstub/hio.h @@ -6,6 +6,10 @@ #include "common/common_types.h" +namespace Core { +class System; +} + namespace GDBStub { /** @@ -47,7 +51,7 @@ static_assert(sizeof(PackedGdbHioRequest) == 152, * * @param address The memory address of the \ref PackedGdbHioRequest. */ -void SetHioRequest(const VAddr address); +void SetHioRequest(Core::System& system, const VAddr address); /** * If there is a pending HIO request, send it to the client. @@ -59,6 +63,6 @@ bool HandlePendingHioRequestPacket(); /** * Process an HIO reply from the client. */ -void HandleHioReply(const u8* const command_buffer, const u32 command_length); +void HandleHioReply(Core::System& system, const u8* const command_buffer, const u32 command_length); } // namespace GDBStub diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 41401c5c8..c66e5cb03 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1128,7 +1128,7 @@ void SVC::OutputDebugString(VAddr address, s32 len) { } if (len == 0) { - GDBStub::SetHioRequest(address); + GDBStub::SetHioRequest(system, address); return; } @@ -1953,12 +1953,12 @@ ResultCode SVC::GetProcessList(s32* process_count, VAddr out_process_array, } ResultCode SVC::InvalidateInstructionCacheRange(u32 addr, u32 size) { - Core::GetRunningCore().InvalidateCacheRange(addr, size); + system.GetRunningCore().InvalidateCacheRange(addr, size); return RESULT_SUCCESS; } ResultCode SVC::InvalidateEntireInstructionCache() { - Core::GetRunningCore().ClearInstructionCache(); + system.GetRunningCore().ClearInstructionCache(); return RESULT_SUCCESS; } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 3bef55322..dd71cb7f7 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -17,9 +17,7 @@ #include "core/arm/arm_interface.h" #include "core/core.h" #include "core/global.h" -#include "core/hle/kernel/memory.h" #include "core/hle/kernel/process.h" -#include "core/hle/lock.h" #include "core/hle/service/plgldr/plgldr.h" #include "core/hw/hw.h" #include "core/memory.h" @@ -89,12 +87,13 @@ private: class MemorySystem::Impl { public: - // Visual Studio would try to allocate these on compile time if they are std::array, which would - // exceed the memory limit. + // Visual Studio would try to allocate these on compile time + // if they are std::array which would exceed the memory limit. std::unique_ptr fcram = std::make_unique(Memory::FCRAM_N3DS_SIZE); std::unique_ptr vram = std::make_unique(Memory::VRAM_SIZE); std::unique_ptr n3ds_extra_ram = std::make_unique(Memory::N3DS_EXTRA_RAM_SIZE); + Core::System& system; std::shared_ptr current_page_table = nullptr; RasterizerCacheMarker cache_marker; std::vector> page_table_list; @@ -106,7 +105,7 @@ public: std::shared_ptr n3ds_extra_ram_mem; std::shared_ptr dsp_mem; - Impl(); + Impl(Core::System& system_); const u8* GetPtr(Region r) const { switch (r) { @@ -153,6 +152,10 @@ public: } } + u32 GetPC() const noexcept { + return system.GetRunningCore().GetPC(); + } + /** * This function should only be called for virtual addreses with attribute `PageType::Special`. */ @@ -187,7 +190,7 @@ public: HW_Memory, "unmapped ReadBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC " "0x{:08X}", - current_vaddr, src_addr, size, Core::GetRunningCore().GetPC()); + current_vaddr, src_addr, size, GetPC()); std::memset(dest_buffer, 0, copy_amount); break; } @@ -242,7 +245,7 @@ public: HW_Memory, "unmapped WriteBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC " "0x{:08X}", - current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC()); + current_vaddr, dest_addr, size, GetPC()); break; } case PageType::Memory: { @@ -345,13 +348,13 @@ private: friend class boost::serialization::access; }; -MemorySystem::Impl::Impl() - : fcram_mem(std::make_shared>(*this)), +MemorySystem::Impl::Impl(Core::System& system_) + : system{system_}, fcram_mem(std::make_shared>(*this)), vram_mem(std::make_shared>(*this)), n3ds_extra_ram_mem(std::make_shared>(*this)), dsp_mem(std::make_shared>(*this)) {} -MemorySystem::MemorySystem() : impl(std::make_unique()) {} +MemorySystem::MemorySystem(Core::System& system) : impl(std::make_unique(system)) {} MemorySystem::~MemorySystem() = default; template @@ -467,7 +470,7 @@ T MemorySystem::Read(const VAddr vaddr) { switch (type) { case PageType::Unmapped: LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X} at PC 0x{:08X}", sizeof(T) * 8, vaddr, - Core::GetRunningCore().GetPC()); + impl->GetPC()); return 0; case PageType::Memory: ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr); @@ -518,7 +521,7 @@ void MemorySystem::Write(const VAddr vaddr, const T data) { switch (type) { case PageType::Unmapped: LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}", - sizeof(data) * 8, (u32)data, vaddr, Core::GetRunningCore().GetPC()); + sizeof(data) * 8, (u32)data, vaddr, impl->GetPC()); return; case PageType::Memory: ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr); @@ -550,7 +553,7 @@ bool MemorySystem::WriteExclusive(const VAddr vaddr, const T data, const T expec switch (type) { case PageType::Unmapped: LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}", - sizeof(data) * 8, (u32)data, vaddr, Core::GetRunningCore().GetPC()); + sizeof(data) * 8, static_cast(data), vaddr, impl->GetPC()); return true; case PageType::Memory: ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr); @@ -606,8 +609,7 @@ u8* MemorySystem::GetPointer(const VAddr vaddr) { return GetPointerForRasterizerCache(vaddr); } - LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x} at PC 0x{:08X}", vaddr, - Core::GetRunningCore().GetPC()); + LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x} at PC 0x{:08X}", vaddr, impl->GetPC()); return nullptr; } @@ -663,7 +665,7 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const { if (area == memory_areas.end()) { LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#08X} at PC {:#08X}", address, - Core::GetRunningCore().GetPC()); + impl->GetPC()); return nullptr; } @@ -693,8 +695,7 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const { return {target_mem, offset_into_region}; } -/// For a rasterizer-accessible PAddr, gets a list of all possible VAddr -static std::vector PhysicalToVirtualAddressForRasterizer(PAddr addr) { +std::vector MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr addr) { if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { return {addr - VRAM_PADDR + VRAM_VADDR}; } @@ -714,7 +715,7 @@ static std::vector PhysicalToVirtualAddressForRasterizer(PAddr addr) { // parts of the texture. LOG_ERROR(HW_Memory, "Trying to use invalid physical address for rasterizer: {:08X} at PC 0x{:08X}", addr, - Core::GetRunningCore().GetPC()); + impl->GetPC()); return {}; } @@ -729,7 +730,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached for (unsigned i = 0; i < num_pages; ++i, paddr += CITRA_PAGE_SIZE) { for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) { impl->cache_marker.Mark(vaddr, cached); - for (auto page_table : impl->page_table_list) { + for (auto& page_table : impl->page_table_list) { PageType& page_type = page_table->attributes[vaddr >> CITRA_PAGE_BITS]; if (cached) { @@ -868,7 +869,7 @@ void MemorySystem::ReadBlock(const Kernel::Process& process, const VAddr src_add } void MemorySystem::ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) { - const auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess(); + const auto& process = *impl->system.Kernel().GetCurrentProcess(); return impl->ReadBlockImpl(process, src_addr, dest_buffer, size); } @@ -911,7 +912,7 @@ void MemorySystem::WriteBlock(const Kernel::Process& process, const VAddr dest_a void MemorySystem::WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { - auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess(); + auto& process = *impl->system.Kernel().GetCurrentProcess(); return impl->WriteBlockImpl(process, dest_addr, src_buffer, size); } @@ -934,7 +935,7 @@ void MemorySystem::ZeroBlock(const Kernel::Process& process, const VAddr dest_ad LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC " "0x{:08X}", - current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC()); + current_vaddr, dest_addr, size, impl->GetPC()); break; } case PageType::Memory: { @@ -989,7 +990,7 @@ void MemorySystem::CopyBlock(const Kernel::Process& dest_process, LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC " "0x{:08X}", - current_vaddr, src_addr, size, Core::GetRunningCore().GetPC()); + current_vaddr, src_addr, size, impl->GetPC()); ZeroBlock(dest_process, dest_addr, copy_amount); break; } diff --git a/src/core/memory.h b/src/core/memory.h index 56ae6f2b8..69a499434 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -18,6 +18,10 @@ namespace Kernel { class Process; } +namespace Core { +class System; +} + namespace AudioCore { class DspInterface; } @@ -287,7 +291,7 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); class MemorySystem { public: - MemorySystem(); + explicit MemorySystem(Core::System& system); ~MemorySystem(); /** @@ -575,6 +579,9 @@ public: */ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached); + /// For a rasterizer-accessible PAddr, gets a list of all possible VAddr + std::vector PhysicalToVirtualAddressForRasterizer(PAddr addr); + /// Gets a pointer to the memory region beginning at the specified physical address. u8* GetPhysicalPointer(PAddr address) const; @@ -627,6 +634,7 @@ private: void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type); +private: class Impl; std::unique_ptr impl; diff --git a/src/tests/audio_core/decoder_tests.cpp b/src/tests/audio_core/decoder_tests.cpp index 41817cb7a..7dd384c43 100644 --- a/src/tests/audio_core/decoder_tests.cpp +++ b/src/tests/audio_core/decoder_tests.cpp @@ -20,7 +20,8 @@ #include "audio_fixures.h" TEST_CASE("DSP HLE Audio Decoder", "[audio_core]") { - Memory::MemorySystem memory; + Core::System system; + Memory::MemorySystem memory{system}; SECTION("decoder should produce correct samples") { auto decoder = #ifdef HAVE_MF diff --git a/src/tests/audio_core/hle/hle.cpp b/src/tests/audio_core/hle/hle.cpp index df50de8af..5bb1c2afd 100644 --- a/src/tests/audio_core/hle/hle.cpp +++ b/src/tests/audio_core/hle/hle.cpp @@ -8,14 +8,16 @@ #include "audio_core/lle/lle.h" #include "common/common_paths.h" #include "common/file_util.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/memory.h" TEST_CASE("DSP LLE vs HLE", "[audio_core][hle]") { - Memory::MemorySystem hle_memory; + Core::System system; + Memory::MemorySystem hle_memory{system}; Core::Timing hle_core_timing(1, 100); - Memory::MemorySystem lle_memory; + Memory::MemorySystem lle_memory{system}; Core::Timing lle_core_timing(1, 100); AudioCore::DspHle hle(hle_memory, hle_core_timing); diff --git a/src/tests/audio_core/lle/lle.cpp b/src/tests/audio_core/lle/lle.cpp index c21d458ab..8b7d21e90 100644 --- a/src/tests/audio_core/lle/lle.cpp +++ b/src/tests/audio_core/lle/lle.cpp @@ -7,11 +7,13 @@ #include "audio_core/lle/lle.h" #include "common/common_paths.h" #include "common/file_util.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/memory.h" TEST_CASE("DSP LLE Sanity", "[audio_core][lle]") { - Memory::MemorySystem memory; + Core::System system; + Memory::MemorySystem memory{system}; Core::Timing core_timing(1, 100); AudioCore::DspLle lle(memory, core_timing, true); diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 2bbf24860..0a69c01da 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -16,7 +16,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) : mutable_memory(mutable_memory_), test_memory(std::make_shared(this)) { timing = std::make_unique(1, 100); - memory = std::make_unique(); + system = std::make_unique(); + memory = std::make_unique(*system); kernel = std::make_unique( *memory, *timing, [] {}, Kernel::MemoryMode::Prod, 1, Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); diff --git a/src/tests/core/arm/arm_test_common.h b/src/tests/core/arm/arm_test_common.h index 604880d21..e99347b7d 100644 --- a/src/tests/core/arm/arm_test_common.h +++ b/src/tests/core/arm/arm_test_common.h @@ -85,6 +85,7 @@ private: std::vector write_records; std::unique_ptr timing; + std::unique_ptr system; std::unique_ptr memory; std::unique_ptr kernel; }; diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index 0ab4e2ac2..e301fe306 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -3,12 +3,10 @@ // Refer to the license.txt file included. #include -#include "common/archives.h" #include "core/core.h" #include "core/core_timing.h" #include "core/hle/ipc.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/hle_ipc.h" @@ -23,7 +21,8 @@ static std::shared_ptr MakeObject(Kernel::KernelSystem& kernel) { TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") { Core::Timing timing(1, 100); - Memory::MemorySystem memory; + Core::System system; + Memory::MemorySystem memory{system}; Kernel::KernelSystem kernel( memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); @@ -247,7 +246,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { Core::Timing timing(1, 100); - Memory::MemorySystem memory; + Core::System system; + Memory::MemorySystem memory{system}; Kernel::KernelSystem kernel( memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp index f0384ef29..597ac5132 100644 --- a/src/tests/core/memory/memory.cpp +++ b/src/tests/core/memory/memory.cpp @@ -3,13 +3,15 @@ // Refer to the license.txt file included. #include +#include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/process.h" #include "core/memory.h" TEST_CASE("memory.IsValidVirtualAddress", "[core][memory]") { Core::Timing timing(1, 100); - Memory::MemorySystem memory; + Core::System system; + Memory::MemorySystem memory{system}; Kernel::KernelSystem kernel( memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); diff --git a/src/tests/core/memory/vm_manager.cpp b/src/tests/core/memory/vm_manager.cpp index 5d1787b05..38c5c938f 100644 --- a/src/tests/core/memory/vm_manager.cpp +++ b/src/tests/core/memory/vm_manager.cpp @@ -4,9 +4,9 @@ #include #include +#include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/errors.h" -#include "core/hle/kernel/memory.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/vm_manager.h" #include "core/memory.h" @@ -15,7 +15,8 @@ TEST_CASE("Memory Basics", "[kernel][memory]") { auto mem = std::make_shared(Memory::CITRA_PAGE_SIZE); MemoryRef block{mem}; Core::Timing timing(1, 100); - Memory::MemorySystem memory; + Core::System system; + Memory::MemorySystem memory{system}; Kernel::KernelSystem kernel( memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index 82de7c9bf..81e44504e 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -503,26 +503,27 @@ SurfaceId RasterizerCache::GetTextureSurface(const Pica::Texture::TextureInfo const u32 min_width = info.width >> max_level; const u32 min_height = info.height >> max_level; if (min_width % 8 != 0 || min_height % 8 != 0) { - if (min_width % 4 == 0 && min_height % 4 == 0) { - const auto [src_surface_id, rect] = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); - Surface& src_surface = slot_surfaces[src_surface_id]; - - params.res_scale = src_surface.res_scale; - SurfaceId tmp_surface_id = CreateSurface(params); - Surface& tmp_surface = slot_surfaces[tmp_surface_id]; - - const TextureBlit blit = { - .src_level = src_surface.LevelOf(params.addr), - .dst_level = 0, - .src_rect = rect, - .dst_rect = tmp_surface.GetScaledRect(), - }; - runtime.BlitTextures(src_surface, tmp_surface, blit); - return tmp_surface_id; + if (min_width % 4 != 0 || min_height % 4 != 0) { + LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) is not multiple of 4", min_width, + min_height); + return NULL_SURFACE_ID; } + const auto [src_surface_id, rect] = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); + Surface& src_surface = slot_surfaces[src_surface_id]; - LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) is not multiple of 4", min_width, min_height); - return NULL_SURFACE_ID; + params.res_scale = src_surface.res_scale; + SurfaceId tmp_surface_id = CreateSurface(params); + Surface& tmp_surface = slot_surfaces[tmp_surface_id]; + sentenced.emplace_back(tmp_surface_id, frame_tick); + + const TextureBlit blit = { + .src_level = src_surface.LevelOf(params.addr), + .dst_level = 0, + .src_rect = rect, + .dst_rect = tmp_surface.GetScaledRect(), + }; + runtime.BlitTextures(src_surface, tmp_surface, blit); + return tmp_surface_id; } if (info.width != (min_width << max_level) || info.height != (min_height << max_level)) { LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) does not support required mipmap level ({})", @@ -1054,8 +1055,9 @@ bool RasterizerCache::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv ASSERT_MSG(True(surface.flags & SurfaceFlagBits::Custom), "Surface is not suitable for custom upload, aborting!"); if (!surface.IsCustom()) { + const SurfaceBase old_surface{surface}; const SurfaceId old_id = - slot_surfaces.swap_and_insert(surface_id, runtime, surface, material); + slot_surfaces.swap_and_insert(surface_id, runtime, old_surface, material); sentenced.emplace_back(old_id, frame_tick); } surface.UploadCustom(material, level); diff --git a/src/video_core/rasterizer_cache/surface_base.cpp b/src/video_core/rasterizer_cache/surface_base.cpp index 1ad8bfa37..8d310dfe4 100644 --- a/src/video_core/rasterizer_cache/surface_base.cpp +++ b/src/video_core/rasterizer_cache/surface_base.cpp @@ -105,7 +105,7 @@ SurfaceInterval SurfaceBase::GetCopyableInterval(const SurfaceParams& params) co return result; } -Extent SurfaceBase::RealExtent(bool scaled) { +Extent SurfaceBase::RealExtent(bool scaled) const { const bool is_custom = IsCustom(); u32 real_width = width; u32 real_height = height; diff --git a/src/video_core/rasterizer_cache/surface_base.h b/src/video_core/rasterizer_cache/surface_base.h index 7e44dcc85..c3bd7b432 100644 --- a/src/video_core/rasterizer_cache/surface_base.h +++ b/src/video_core/rasterizer_cache/surface_base.h @@ -41,7 +41,7 @@ public: ClearValue MakeClearValue(PAddr copy_addr, PixelFormat dst_format); /// Returns the internal surface extent. - Extent RealExtent(bool scaled = true); + Extent RealExtent(bool scaled = true) const; /// Returns true if the surface contains a custom material with a normal map. bool HasNormalMap() const noexcept; diff --git a/src/video_core/rasterizer_cache/surface_params.h b/src/video_core/rasterizer_cache/surface_params.h index 77a8ea107..89aff6043 100644 --- a/src/video_core/rasterizer_cache/surface_params.h +++ b/src/video_core/rasterizer_cache/surface_params.h @@ -73,12 +73,12 @@ public: return height * res_scale; } - [[nodiscard]] Common::Rectangle GetRect() const noexcept { - return {0, height, width, 0}; + [[nodiscard]] Common::Rectangle GetRect(u32 level = 0) const noexcept { + return {0, height >> level, width >> level, 0}; } - [[nodiscard]] Common::Rectangle GetScaledRect() const noexcept { - return {0, GetScaledHeight(), GetScaledWidth(), 0}; + [[nodiscard]] Common::Rectangle GetScaledRect(u32 level = 0) const noexcept { + return {0, GetScaledHeight() >> level, GetScaledWidth() >> level, 0}; } [[nodiscard]] u32 PixelsInBytes(u32 size) const noexcept { diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 3109567ac..3a86d1eb4 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -9,10 +9,6 @@ #include "common/common_types.h" #include "core/hw/gpu.h" -namespace OpenGL { -struct ScreenInfo; -} - namespace Pica::Shader { struct OutputVertex; } // namespace Pica::Shader @@ -76,14 +72,6 @@ public: return false; } - /// Attempt to use a faster method to display the framebuffer to screen - virtual bool AccelerateDisplay([[maybe_unused]] const GPU::Regs::FramebufferConfig& config, - [[maybe_unused]] PAddr framebuffer_addr, - [[maybe_unused]] u32 pixel_stride, - [[maybe_unused]] OpenGL::ScreenInfo& screen_info) { - return false; - } - /// Attempt to draw using hardware shaders virtual bool AccelerateDrawBatch([[maybe_unused]] bool is_indexed) { return false; diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index d7fba9597..6e1f327e4 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -42,7 +42,7 @@ public: virtual ~RendererBase(); /// Returns the rasterizer owned by the renderer - virtual VideoCore::RasterizerInterface* Rasterizer() const = 0; + virtual VideoCore::RasterizerInterface* Rasterizer() = 0; /// Finalize rendering the guest frame and draw into the presentation texture virtual void SwapBuffers() = 0; @@ -72,9 +72,6 @@ public: /// Ends the current frame void EndFrame(); - // Getter/setter functions: - // ------------------------ - f32 GetCurrentFPS() const { return current_fps; } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index e09f4e8f6..22e568aca 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -12,9 +12,9 @@ #include "video_core/regs_rasterizer.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_shader_gen.h" -#include "video_core/renderer_opengl/gl_vars.h" #include "video_core/renderer_opengl/pica_to_gl.h" #include "video_core/renderer_opengl/renderer_opengl.h" +#include "video_core/texture/texture_decode.h" #include "video_core/video_core.h" namespace OpenGL { @@ -76,8 +76,9 @@ GLenum MakeAttributeType(Pica::PipelineRegs::VertexAttributeFormat format) { RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, VideoCore::CustomTexManager& custom_tex_manager, VideoCore::RendererBase& renderer, Driver& driver_) - : VideoCore::RasterizerAccelerated{memory}, driver{driver_}, runtime{driver, renderer}, - res_cache{memory, custom_tex_manager, runtime, regs, renderer}, + : VideoCore::RasterizerAccelerated{memory}, driver{driver_}, + shader_manager{renderer.GetRenderWindow(), driver, !driver.IsOpenGLES()}, + runtime{driver, renderer}, res_cache{memory, custom_tex_manager, runtime, regs, renderer}, texture_buffer_size{TextureBufferSize()}, vertex_buffer{driver, GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE}, uniform_buffer{driver, GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE}, @@ -89,14 +90,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0 state.clip_distance[0] = true; - // Create a 1x1 clear texture to use in the NULL case, - // instead of OpenGL's default of solid black - glGenTextures(1, &default_texture); - glBindTexture(GL_TEXTURE_2D, default_texture); - // For some reason alpha 0 wraps around to 1.0, so use 1/255 instead - u8 framebuffer_data[4] = {0, 0, 0, 1}; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); - // Generate VAO sw_vao.Create(); hw_vao.Create(); @@ -142,9 +135,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, (GLvoid*)offsetof(HardwareVertex, view)); glEnableVertexAttribArray(ATTRIBUTE_VIEW); - // Create render framebuffer - framebuffer.Create(); - // Allocate and bind texture buffer lut textures texture_buffer_lut_lf.Create(); texture_buffer_lut_rg.Create(); @@ -165,9 +155,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, state.Apply(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle()); - shader_program_manager = - std::make_unique(renderer.GetRenderWindow(), driver, !GLES); - glEnable(GL_BLEND); SyncEntireState(); @@ -181,7 +168,7 @@ void RasterizerOpenGL::TickFrame() { void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback) { - shader_program_manager->LoadDiskCache(stop_loading, callback); + shader_manager.LoadDiskCache(stop_loading, callback); } void RasterizerOpenGL::SyncFixedState() { @@ -277,7 +264,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset, bool RasterizerOpenGL::SetupVertexShader() { MICROPROFILE_SCOPE(OpenGL_VS); - return shader_program_manager->UseProgrammableVertexShader(regs, Pica::g_state.vs); + return shader_manager.UseProgrammableVertexShader(regs, Pica::g_state.vs); } bool RasterizerOpenGL::SetupGeometryShader() { @@ -288,7 +275,7 @@ bool RasterizerOpenGL::SetupGeometryShader() { return false; } - shader_program_manager->UseFixedGeometryShader(regs); + shader_manager.UseFixedGeometryShader(regs); return true; } @@ -302,11 +289,13 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { } } - if (!SetupVertexShader()) + if (!SetupVertexShader()) { return false; + } - if (!SetupGeometryShader()) + if (!SetupGeometryShader()) { return false; + } return Draw(true, is_indexed); } @@ -329,7 +318,7 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) { SetupVertexArray(buffer_ptr, buffer_offset, vs_input_index_min, vs_input_index_max); vertex_buffer.Unmap(vs_input_size); - shader_program_manager->ApplyTo(state); + shader_manager.ApplyTo(state); state.Apply(); if (is_indexed) { @@ -341,9 +330,9 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) { return false; } - const u8* index_data = VideoCore::g_memory->GetPhysicalPointer( - regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + - regs.pipeline.index_array.offset); + const u8* index_data = + memory.GetPhysicalPointer(regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + + regs.pipeline.index_array.offset); std::tie(buffer_ptr, buffer_offset, std::ignore) = index_buffer.Map(index_buffer_size, 4); std::memcpy(buffer_ptr, index_data, index_buffer_size); index_buffer.Unmap(index_buffer_size); @@ -434,7 +423,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) { // Sync and bind the shader if (shader_dirty) { - shader_program_manager->UseFragmentShader(regs, use_custom_normal); + shader_manager.UseFragmentShader(regs, use_custom_normal); shader_dirty = false; } @@ -452,9 +441,9 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) { } else { state.draw.vertex_array = sw_vao.handle; state.draw.vertex_buffer = vertex_buffer.GetHandle(); - shader_program_manager->UseTrivialVertexShader(); - shader_program_manager->UseTrivialGeometryShader(); - shader_program_manager->ApplyTo(state); + shader_manager.UseTrivialVertexShader(); + shader_manager.UseTrivialGeometryShader(); + shader_manager.ApplyTo(state); state.Apply(); std::size_t max_vertices = 3 * (VERTEX_BUFFER_SIZE / (3 * sizeof(HardwareVertex))); @@ -820,7 +809,7 @@ void RasterizerOpenGL::SyncBlendColor() { void RasterizerOpenGL::SyncLogicOp() { state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op); - if (GLES) { + if (driver.IsOpenGLES()) { if (!regs.framebuffer.output_merger.alphablend_enable) { if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) { // Color output is disabled by logic operation. We use color write mask to skip @@ -832,7 +821,7 @@ void RasterizerOpenGL::SyncLogicOp() { } void RasterizerOpenGL::SyncColorWriteMask() { - if (GLES) { + if (driver.IsOpenGLES()) { if (!regs.framebuffer.output_merger.alphablend_enable) { if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) { // Color output is disabled by logic operation. We use color write mask to skip @@ -842,17 +831,19 @@ void RasterizerOpenGL::SyncColorWriteMask() { } } - auto IsColorWriteEnabled = [&](u32 value) { + auto is_color_write_enabled = [&](u32 value) { return (regs.framebuffer.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE : GL_FALSE; }; - state.color_mask.red_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.red_enable); + state.color_mask.red_enabled = + is_color_write_enabled(regs.framebuffer.output_merger.red_enable); state.color_mask.green_enabled = - IsColorWriteEnabled(regs.framebuffer.output_merger.green_enable); - state.color_mask.blue_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.blue_enable); + is_color_write_enabled(regs.framebuffer.output_merger.green_enable); + state.color_mask.blue_enabled = + is_color_write_enabled(regs.framebuffer.output_merger.blue_enable); state.color_mask.alpha_enabled = - IsColorWriteEnabled(regs.framebuffer.output_merger.alpha_enable); + is_color_write_enabled(regs.framebuffer.output_merger.alpha_enable); } void RasterizerOpenGL::SyncStencilWriteMask() { @@ -903,12 +894,10 @@ void RasterizerOpenGL::SyncAndUploadLUTsLF() { return; } - u8* buffer; - GLintptr offset; - bool invalidate; std::size_t bytes_used = 0; glBindBuffer(GL_TEXTURE_BUFFER, texture_lf_buffer.GetHandle()); - std::tie(buffer, offset, invalidate) = texture_lf_buffer.Map(max_size, sizeof(Common::Vec4f)); + const auto [buffer, offset, invalidate] = + texture_lf_buffer.Map(max_size, sizeof(Common::Vec4f)); // Sync the lighting luts if (uniform_block_data.lighting_lut_dirty_any || invalidate) { @@ -973,50 +962,48 @@ void RasterizerOpenGL::SyncAndUploadLUTs() { return; } - u8* buffer; - GLintptr offset; - bool invalidate; std::size_t bytes_used = 0; glBindBuffer(GL_TEXTURE_BUFFER, texture_buffer.GetHandle()); - std::tie(buffer, offset, invalidate) = texture_buffer.Map(max_size, sizeof(Common::Vec4f)); + const auto [buffer, offset, invalidate] = texture_buffer.Map(max_size, sizeof(Common::Vec4f)); // helper function for SyncProcTexNoiseLUT/ColorMap/AlphaMap - auto SyncProcTexValueLUT = [this, buffer, offset, invalidate, &bytes_used]( - const std::array& lut, - std::array& lut_data, GLint& lut_offset) { - std::array new_data; - std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) { - return Common::Vec2f{entry.ToFloat(), entry.DiffToFloat()}; - }); + const auto sync_proc_tex_value_lut = + [this, buffer = buffer, offset = offset, invalidate = invalidate, + &bytes_used](const std::array& lut, + std::array& lut_data, GLint& lut_offset) { + std::array new_data; + std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) { + return Common::Vec2f{entry.ToFloat(), entry.DiffToFloat()}; + }); - if (new_data != lut_data || invalidate) { - lut_data = new_data; - std::memcpy(buffer + bytes_used, new_data.data(), - new_data.size() * sizeof(Common::Vec2f)); - lut_offset = static_cast((offset + bytes_used) / sizeof(Common::Vec2f)); - uniform_block_data.dirty = true; - bytes_used += new_data.size() * sizeof(Common::Vec2f); - } - }; + if (new_data != lut_data || invalidate) { + lut_data = new_data; + std::memcpy(buffer + bytes_used, new_data.data(), + new_data.size() * sizeof(Common::Vec2f)); + lut_offset = static_cast((offset + bytes_used) / sizeof(Common::Vec2f)); + uniform_block_data.dirty = true; + bytes_used += new_data.size() * sizeof(Common::Vec2f); + } + }; // Sync the proctex noise lut if (uniform_block_data.proctex_noise_lut_dirty || invalidate) { - SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data, - uniform_block_data.data.proctex_noise_lut_offset); + sync_proc_tex_value_lut(Pica::g_state.proctex.noise_table, proctex_noise_lut_data, + uniform_block_data.data.proctex_noise_lut_offset); uniform_block_data.proctex_noise_lut_dirty = false; } // Sync the proctex color map if (uniform_block_data.proctex_color_map_dirty || invalidate) { - SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data, - uniform_block_data.data.proctex_color_map_offset); + sync_proc_tex_value_lut(Pica::g_state.proctex.color_map_table, proctex_color_map_data, + uniform_block_data.data.proctex_color_map_offset); uniform_block_data.proctex_color_map_dirty = false; } // Sync the proctex alpha map if (uniform_block_data.proctex_alpha_map_dirty || invalidate) { - SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data, - uniform_block_data.data.proctex_alpha_map_offset); + sync_proc_tex_value_lut(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data, + uniform_block_data.data.proctex_alpha_map_offset); uniform_block_data.proctex_alpha_map_dirty = false; } @@ -1070,28 +1057,25 @@ void RasterizerOpenGL::SyncAndUploadLUTs() { } void RasterizerOpenGL::UploadUniforms(bool accelerate_draw) { - // glBindBufferRange below also changes the generic buffer binding point, so we sync the state - // first + // glBindBufferRange also changes the generic buffer binding point, so we sync the state first. state.draw.uniform_buffer = uniform_buffer.GetHandle(); state.Apply(); - bool sync_vs = accelerate_draw; - bool sync_fs = uniform_block_data.dirty; - - if (!sync_vs && !sync_fs) + const bool sync_vs = accelerate_draw; + const bool sync_fs = uniform_block_data.dirty; + if (!sync_vs && !sync_fs) { return; + } std::size_t uniform_size = uniform_size_aligned_vs + uniform_size_aligned_fs; std::size_t used_bytes = 0; - u8* uniforms; - GLintptr offset; - bool invalidate; - std::tie(uniforms, offset, invalidate) = + + const auto [uniforms, offset, invalidate] = uniform_buffer.Map(uniform_size, uniform_buffer_alignment); if (sync_vs) { Pica::Shader::VSUniformData vs_uniforms; - vs_uniforms.uniforms.SetFromRegs(Pica::g_state.regs.vs, Pica::g_state.vs); + vs_uniforms.uniforms.SetFromRegs(regs.vs, Pica::g_state.vs); std::memcpy(uniforms + used_bytes, &vs_uniforms, sizeof(vs_uniforms)); glBindBufferRange(GL_UNIFORM_BUFFER, static_cast(Pica::Shader::UniformBindings::VS), uniform_buffer.GetHandle(), offset + used_bytes, diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 54f5e0016..22f1b5bd2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -6,7 +6,6 @@ #include "core/hw/gpu.h" #include "video_core/rasterizer_accelerated.h" -#include "video_core/rasterizer_cache/rasterizer_cache.h" #include "video_core/rasterizer_interface.h" #include "video_core/regs_texturing.h" #include "video_core/renderer_opengl/gl_shader_manager.h" @@ -24,6 +23,8 @@ class CustomTexManager; namespace OpenGL { +struct ScreenInfo; + class Driver; class ShaderProgramManager; @@ -48,7 +49,7 @@ public: bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override; bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override; bool AccelerateDisplay(const GPU::Regs::FramebufferConfig& config, PAddr framebuffer_addr, - u32 pixel_stride, ScreenInfo& screen_info) override; + u32 pixel_stride, ScreenInfo& screen_info); bool AccelerateDrawBatch(bool is_indexed) override; private: @@ -132,10 +133,9 @@ private: private: Driver& driver; OpenGLState state; - GLuint default_texture; + ShaderProgramManager shader_manager; TextureRuntime runtime; RasterizerCache res_cache; - std::unique_ptr shader_program_manager; OGLVertexArray sw_vao; // VAO for software shader draw OGLVertexArray hw_vao; // VAO for hardware shader / accelerate draw @@ -147,7 +147,6 @@ private: OGLStreamBuffer index_buffer; OGLStreamBuffer texture_buffer; OGLStreamBuffer texture_lf_buffer; - OGLFramebuffer framebuffer; GLint uniform_buffer_alignment; std::size_t uniform_size_aligned_vs; std::size_t uniform_size_aligned_fs; diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 0b0f38b24..f656705dd 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -8,7 +8,6 @@ #include #include #include -#include "common/scope_exit.h" #include "core/frontend/emu_window.h" #include "video_core/renderer_opengl/gl_driver.h" #include "video_core/renderer_opengl/gl_resource_manager.h" diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 6e2d15380..dc95e2c24 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#include "common/common_types.h" #include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/gl_vars.h" diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index 586236e73..e7ca8179f 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -528,13 +528,13 @@ void Surface::ScaleUp(u32 new_scale) { textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple, DebugName(true)); - VideoCore::TextureBlit blit = { - .src_rect = GetRect(), - .dst_rect = GetScaledRect(), - }; for (u32 level = 0; level < levels; level++) { - blit.src_level = level; - blit.dst_level = level; + const VideoCore::TextureBlit blit = { + .src_level = level, + .dst_level = level, + .src_rect = GetRect(level), + .dst_rect = GetScaledRect(level), + }; BlitScale(blit, true); } } diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 26f3808ac..be778c764 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -78,7 +78,8 @@ static std::array MakeOrthographicMatrix(const float width, cons RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window) : VideoCore::RendererBase{system, window, secondary_window}, driver{system.TelemetrySession()}, - frame_dumper{system, window} { + rasterizer{system.Memory(), system.CustomTexManager(), *this, driver}, frame_dumper{system, + window} { const bool has_debug_tool = driver.HasDebugTool(); window.mailbox = std::make_unique(has_debug_tool); if (secondary_window) { @@ -86,8 +87,6 @@ RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window } frame_dumper.mailbox = std::make_unique(); InitOpenGLObjects(); - rasterizer = std::make_unique(system.Memory(), system.CustomTexManager(), - *this, driver); } RendererOpenGL::~RendererOpenGL() = default; @@ -121,8 +120,7 @@ void RendererOpenGL::SwapBuffers() { EndFrame(); prev_state.Apply(); - - rasterizer->TickFrame(); + rasterizer.TickFrame(); } void RendererOpenGL::RenderScreenshot() { @@ -273,8 +271,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram // only allows rows to have a memory alignement of 4. ASSERT(pixel_stride % 4 == 0); - if (!Rasterizer()->AccelerateDisplay(framebuffer, framebuffer_addr, - static_cast(pixel_stride), screen_info)) { + if (!rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, static_cast(pixel_stride), + screen_info)) { // Reset the screen info's display texture to its own permanent texture screen_info.display_texture = screen_info.texture.resource.handle; screen_info.display_texcoords = Common::Rectangle(0.f, 0.f, 1.f, 1.f); @@ -903,7 +901,7 @@ void RendererOpenGL::CleanupVideoDumping() { } void RendererOpenGL::Sync() { - rasterizer->SyncEntireState(); + rasterizer.SyncEntireState(); } } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index be7c39e8b..5e005e8dc 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -46,8 +46,8 @@ public: Frontend::EmuWindow* secondary_window); ~RendererOpenGL() override; - [[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() const override { - return rasterizer.get(); + [[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() override { + return &rasterizer; } void SwapBuffers() override; @@ -86,8 +86,8 @@ private: private: Driver driver; + RasterizerOpenGL rasterizer; OpenGLState state; - std::unique_ptr rasterizer; // OpenGL object IDs OGLVertexArray vertex_array; diff --git a/src/video_core/renderer_software/renderer_software.cpp b/src/video_core/renderer_software/renderer_software.cpp index 7194be8e1..0a8f88950 100644 --- a/src/video_core/renderer_software/renderer_software.cpp +++ b/src/video_core/renderer_software/renderer_software.cpp @@ -13,7 +13,7 @@ namespace SwRenderer { RendererSoftware::RendererSoftware(Core::System& system, Frontend::EmuWindow& window) : VideoCore::RendererBase{system, window, nullptr}, memory{system.Memory()}, - rasterizer{std::make_unique(system.Memory())} {} + rasterizer{system.Memory()} {} RendererSoftware::~RendererSoftware() = default; diff --git a/src/video_core/renderer_software/renderer_software.h b/src/video_core/renderer_software/renderer_software.h index 6ed86ffa3..2df5550c4 100644 --- a/src/video_core/renderer_software/renderer_software.h +++ b/src/video_core/renderer_software/renderer_software.h @@ -24,8 +24,8 @@ public: explicit RendererSoftware(Core::System& system, Frontend::EmuWindow& window); ~RendererSoftware() override; - [[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() const override { - return rasterizer.get(); + [[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() override { + return &rasterizer; } [[nodiscard]] const ScreenInfo& Screen(VideoCore::ScreenId id) const noexcept { @@ -42,7 +42,7 @@ private: private: Memory::MemorySystem& memory; - std::unique_ptr rasterizer; + RasterizerSoftware rasterizer; std::array screen_infos{}; };