Miscallenious fixes to gl backend and qt frontend (#6834)
* renderer_gl: Make rasterizer normal class member * It doesn't need to be heap allocated anymore * gl_rasterizer: Remove default_texture * It's unused * gl_rasterizer: General cleanup * gl_rasterizer: Lower case lambdas * Match style with review comments from vulkan backend * rasterizer_cache: Prevent memory leak * Since the switch from shared_ptr these surfaces were no longer being destroyed properly. Use our garbage collector for that purpose to destroy it safely for both backends * rasterizer_cache: Make temp copy of old surface * The custom surface would override the memory region of the old region resulting in garbage data, this ensures the custom surface is constructed correctly * citra_qt: Manually create dialog tabs * Allows for custom constructors which is very useful. While at it, global state is now eliminated from configuration * citra_qt: Eliminate global system usage * core: Remove global system usage in memory and HIO * citra_qt: Use qOverload * tests: Run clang format * gl_texture_runtime: Fix surface scaling
This commit is contained in:
parent
970f2284d8
commit
88ea66053e
73 changed files with 594 additions and 555 deletions
|
@ -157,7 +157,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||||
system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>());
|
system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>());
|
||||||
|
|
||||||
// Register microphone permission check
|
// Register microphone permission check
|
||||||
Core::System::GetInstance().RegisterMicPermissionCheck(&CheckMicPermission);
|
system.RegisterMicPermissionCheck(&CheckMicPermission);
|
||||||
|
|
||||||
InputManager::Init();
|
InputManager::Init();
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||||
return load_result;
|
return load_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& telemetry_session = Core::System::GetInstance().TelemetrySession();
|
auto& telemetry_session = system.TelemetrySession();
|
||||||
telemetry_session.AddField(Common::Telemetry::FieldType::App, "Frontend", "Android");
|
telemetry_session.AddField(Common::Telemetry::FieldType::App, "Frontend", "Android");
|
||||||
|
|
||||||
stop_run = false;
|
stop_run = false;
|
||||||
|
@ -188,8 +188,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||||
audio_stretching_event =
|
audio_stretching_event =
|
||||||
system.CoreTiming().RegisterEvent("AudioStretchingEvent", [&](u64, s64 cycles_late) {
|
system.CoreTiming().RegisterEvent("AudioStretchingEvent", [&](u64, s64 cycles_late) {
|
||||||
if (Settings::values.enable_audio_stretching) {
|
if (Settings::values.enable_audio_stretching) {
|
||||||
Core::DSP().EnableStretching(
|
system.DSP().EnableStretching(system.GetAndResetPerfStats().emulation_speed < 0.95);
|
||||||
Core::System::GetInstance().GetAndResetPerfStats().emulation_speed < 0.95);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
system.CoreTiming().ScheduleEvent(audio_stretching_ticks - cycles_late,
|
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; });
|
SCOPE_EXIT({ Settings::values.volume = volume; });
|
||||||
Settings::values.volume = 0;
|
Settings::values.volume = 0;
|
||||||
|
|
||||||
std::unique_lock<std::mutex> pause_lock(paused_mutex);
|
std::unique_lock pause_lock{paused_mutex};
|
||||||
running_cv.wait(pause_lock, [] { return !pause_emulation || stop_run; });
|
running_cv.wait(pause_lock, [] { return !pause_emulation || stop_run; });
|
||||||
window->PollEvents();
|
window->PollEvents();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,68 +21,8 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>-1</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="ConfigureGeneral" name="generalTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>General</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureSystem" name="systemTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>System</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureInput" name="inputTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Input</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureHotkeys" name="hotkeysTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Hotkeys</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureGraphics" name="graphicsTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Graphics</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureEnhancements" name="enhancementsTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Enhancements</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureAudio" name="audioTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Audio</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureCamera" name="cameraTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Camera</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureDebug" name="debugTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Debug</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureStorage" name="storageTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Storage</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureWeb" name="webTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Web</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="ConfigureUi" name="uiTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>UI</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -10,14 +10,13 @@
|
||||||
#include "citra_qt/configuration/configuration_shared.h"
|
#include "citra_qt/configuration/configuration_shared.h"
|
||||||
#include "citra_qt/configuration/configure_audio.h"
|
#include "citra_qt/configuration/configure_audio.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "ui_configure_audio.h"
|
#include "ui_configure_audio.h"
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include "common/apple_authorization.h"
|
#include "common/apple_authorization.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConfigureAudio::ConfigureAudio(QWidget* parent)
|
ConfigureAudio::ConfigureAudio(bool is_powered_on, QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
@ -27,8 +26,7 @@ ConfigureAudio::ConfigureAudio(QWidget* parent)
|
||||||
AudioCore::GetSinkName(static_cast<AudioCore::SinkType>(type)).data()));
|
AudioCore::GetSinkName(static_cast<AudioCore::SinkType>(type)).data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_running = Core::System::GetInstance().IsPoweredOn();
|
ui->emulation_combo_box->setEnabled(!is_powered_on);
|
||||||
ui->emulation_combo_box->setEnabled(!is_running);
|
|
||||||
|
|
||||||
connect(ui->volume_slider, &QSlider::valueChanged, this,
|
connect(ui->volume_slider, &QSlider::valueChanged, this,
|
||||||
&ConfigureAudio::SetVolumeIndicatorText);
|
&ConfigureAudio::SetVolumeIndicatorText);
|
||||||
|
|
|
@ -19,7 +19,7 @@ class ConfigureAudio : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureAudio(QWidget* parent = nullptr);
|
explicit ConfigureAudio(bool is_powered_on, QWidget* parent = nullptr);
|
||||||
~ConfigureAudio() override;
|
~ConfigureAudio() override;
|
||||||
|
|
||||||
void ApplyConfiguration();
|
void ApplyConfiguration();
|
||||||
|
|
|
@ -47,8 +47,7 @@ ConfigureCamera::~ConfigureCamera() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureCamera::ConnectEvents() {
|
void ConfigureCamera::ConnectEvents() {
|
||||||
connect(ui->image_source,
|
connect(ui->image_source, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
|
||||||
[this](int index) {
|
[this](int index) {
|
||||||
StopPreviewing();
|
StopPreviewing();
|
||||||
UpdateImageSourceUI();
|
UpdateImageSourceUI();
|
||||||
|
@ -58,8 +57,7 @@ void ConfigureCamera::ConnectEvents() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
connect(ui->camera_selection,
|
connect(ui->camera_selection, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
|
||||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] {
|
|
||||||
StopPreviewing();
|
StopPreviewing();
|
||||||
if (GetCameraSelection() != current_selected) {
|
if (GetCameraSelection() != current_selected) {
|
||||||
RecordConfig();
|
RecordConfig();
|
||||||
|
@ -73,15 +71,13 @@ void ConfigureCamera::ConnectEvents() {
|
||||||
UpdateCameraMode();
|
UpdateCameraMode();
|
||||||
SetConfiguration();
|
SetConfiguration();
|
||||||
});
|
});
|
||||||
connect(ui->camera_mode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
connect(ui->camera_mode, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
|
||||||
this, [this] {
|
|
||||||
StopPreviewing();
|
StopPreviewing();
|
||||||
ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1);
|
ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1);
|
||||||
ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1);
|
ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1);
|
||||||
current_selected = GetCameraSelection();
|
current_selected = GetCameraSelection();
|
||||||
});
|
});
|
||||||
connect(ui->camera_position,
|
connect(ui->camera_position, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
|
||||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] {
|
|
||||||
StopPreviewing();
|
StopPreviewing();
|
||||||
if (GetCameraSelection() != current_selected) {
|
if (GetCameraSelection() != current_selected) {
|
||||||
RecordConfig();
|
RecordConfig();
|
||||||
|
|
|
@ -9,11 +9,9 @@
|
||||||
#include "core/cheats/cheat_base.h"
|
#include "core/cheats/cheat_base.h"
|
||||||
#include "core/cheats/cheats.h"
|
#include "core/cheats/cheats.h"
|
||||||
#include "core/cheats/gateway_cheat.h"
|
#include "core/cheats/gateway_cheat.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/hle/kernel/process.h"
|
|
||||||
#include "ui_configure_cheats.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<Ui::ConfigureCheats>()), title_id{title_id_} {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureCheats>()), title_id{title_id_} {
|
||||||
// Setup gui control settings
|
// Setup gui control settings
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
@ -36,7 +34,7 @@ ConfigureCheats::ConfigureCheats(u64 title_id_, QWidget* parent)
|
||||||
[this] { SaveCheat(ui->tableCheats->currentRow()); });
|
[this] { SaveCheat(ui->tableCheats->currentRow()); });
|
||||||
connect(ui->buttonDelete, &QPushButton::clicked, this, &ConfigureCheats::OnDeleteCheat);
|
connect(ui->buttonDelete, &QPushButton::clicked, this, &ConfigureCheats::OnDeleteCheat);
|
||||||
|
|
||||||
cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, Core::System::GetInstance());
|
cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, system);
|
||||||
|
|
||||||
LoadCheats();
|
LoadCheats();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <QWidget>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Cheats {
|
namespace Cheats {
|
||||||
|
@ -12,6 +13,10 @@ class CheatBase;
|
||||||
class CheatEngine;
|
class CheatEngine;
|
||||||
} // namespace Cheats
|
} // namespace Cheats
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class ConfigureCheats;
|
class ConfigureCheats;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
@ -20,7 +25,7 @@ class ConfigureCheats : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureCheats(u64 title_id_, QWidget* parent = nullptr);
|
explicit ConfigureCheats(Core::System& system, u64 title_id, QWidget* parent = nullptr);
|
||||||
~ConfigureCheats();
|
~ConfigureCheats();
|
||||||
bool ApplyConfiguration();
|
bool ApplyConfiguration();
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "common/logging/backend.h"
|
#include "common/logging/backend.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "ui_configure_debug.h"
|
#include "ui_configure_debug.h"
|
||||||
|
|
||||||
// The QSlider doesn't have an easy way to set a custom step amount,
|
// 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;
|
return (value - 5) / 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureDebug::ConfigureDebug(QWidget* parent)
|
ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureDebug>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureDebug>()), is_powered_on{is_powered_on_} {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
SetConfiguration();
|
SetConfiguration();
|
||||||
|
|
||||||
|
@ -35,7 +34,6 @@ ConfigureDebug::ConfigureDebug(QWidget* parent)
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||||
});
|
});
|
||||||
|
|
||||||
const bool is_powered_on = Core::System::GetInstance().IsPoweredOn();
|
|
||||||
ui->toggle_cpu_jit->setEnabled(!is_powered_on);
|
ui->toggle_cpu_jit->setEnabled(!is_powered_on);
|
||||||
ui->toggle_renderer_debug->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->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue());
|
||||||
ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue());
|
ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue());
|
||||||
ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.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->toggle_console->setChecked(UISettings::values.show_console.GetValue());
|
||||||
ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue()));
|
ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue()));
|
||||||
ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue());
|
ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue());
|
||||||
|
|
|
@ -15,7 +15,7 @@ class ConfigureDebug : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureDebug(QWidget* parent = nullptr);
|
explicit ConfigureDebug(bool is_powered_on, QWidget* parent = nullptr);
|
||||||
~ConfigureDebug() override;
|
~ConfigureDebug() override;
|
||||||
|
|
||||||
void ApplyConfiguration();
|
void ApplyConfiguration();
|
||||||
|
@ -25,4 +25,5 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Ui::ConfigureDebug> ui;
|
std::unique_ptr<Ui::ConfigureDebug> ui;
|
||||||
|
bool is_powered_on;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,8 +4,19 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <QListWidgetItem>
|
#include <QListWidgetItem>
|
||||||
#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_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 "citra_qt/hotkeys.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
@ -14,16 +25,41 @@
|
||||||
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_,
|
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_,
|
||||||
bool enable_web_config)
|
bool enable_web_config)
|
||||||
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_},
|
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_},
|
||||||
system{system_} {
|
system{system_}, is_powered_on{system.IsPoweredOn()},
|
||||||
|
general_tab{std::make_unique<ConfigureGeneral>(this)},
|
||||||
|
system_tab{std::make_unique<ConfigureSystem>(system, this)},
|
||||||
|
input_tab{std::make_unique<ConfigureInput>(this)},
|
||||||
|
hotkeys_tab{std::make_unique<ConfigureHotkeys>(this)},
|
||||||
|
graphics_tab{std::make_unique<ConfigureGraphics>(is_powered_on, this)},
|
||||||
|
enhancements_tab{std::make_unique<ConfigureEnhancements>(this)},
|
||||||
|
audio_tab{std::make_unique<ConfigureAudio>(is_powered_on, this)},
|
||||||
|
camera_tab{std::make_unique<ConfigureCamera>(this)},
|
||||||
|
debug_tab{std::make_unique<ConfigureDebug>(is_powered_on, this)},
|
||||||
|
storage_tab{std::make_unique<ConfigureStorage>(is_powered_on, this)},
|
||||||
|
web_tab{std::make_unique<ConfigureWeb>(this)}, ui_tab{std::make_unique<ConfigureUi>(this)} {
|
||||||
Settings::SetConfiguringGlobal(true);
|
Settings::SetConfiguringGlobal(true);
|
||||||
|
|
||||||
ui->setupUi(this);
|
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();
|
PopulateSelectionList();
|
||||||
|
|
||||||
connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
|
connect(ui_tab.get(), &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
|
||||||
connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
|
connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
|
||||||
&ConfigureDialog::UpdateVisibleTabs);
|
&ConfigureDialog::UpdateVisibleTabs);
|
||||||
|
|
||||||
|
@ -31,46 +67,46 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor
|
||||||
ui->selectorList->setCurrentRow(0);
|
ui->selectorList->setCurrentRow(0);
|
||||||
|
|
||||||
// Set up used key list synchronisation
|
// Set up used key list synchronisation
|
||||||
connect(ui->inputTab, &ConfigureInput::InputKeysChanged, ui->hotkeysTab,
|
connect(input_tab.get(), &ConfigureInput::InputKeysChanged, hotkeys_tab.get(),
|
||||||
&ConfigureHotkeys::OnInputKeysChanged);
|
&ConfigureHotkeys::OnInputKeysChanged);
|
||||||
connect(ui->hotkeysTab, &ConfigureHotkeys::HotkeysChanged, ui->inputTab,
|
connect(hotkeys_tab.get(), &ConfigureHotkeys::HotkeysChanged, input_tab.get(),
|
||||||
&ConfigureInput::OnHotkeysChanged);
|
&ConfigureInput::OnHotkeysChanged);
|
||||||
|
|
||||||
// Synchronise lists upon initialisation
|
// Synchronise lists upon initialisation
|
||||||
ui->inputTab->EmitInputKeysChanged();
|
input_tab->EmitInputKeysChanged();
|
||||||
ui->hotkeysTab->EmitHotkeysChanged();
|
hotkeys_tab->EmitHotkeysChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureDialog::~ConfigureDialog() = default;
|
ConfigureDialog::~ConfigureDialog() = default;
|
||||||
|
|
||||||
void ConfigureDialog::SetConfiguration() {
|
void ConfigureDialog::SetConfiguration() {
|
||||||
ui->generalTab->SetConfiguration();
|
general_tab->SetConfiguration();
|
||||||
ui->systemTab->SetConfiguration();
|
system_tab->SetConfiguration();
|
||||||
ui->inputTab->LoadConfiguration();
|
input_tab->LoadConfiguration();
|
||||||
ui->graphicsTab->SetConfiguration();
|
graphics_tab->SetConfiguration();
|
||||||
ui->enhancementsTab->SetConfiguration();
|
enhancements_tab->SetConfiguration();
|
||||||
ui->audioTab->SetConfiguration();
|
audio_tab->SetConfiguration();
|
||||||
ui->cameraTab->SetConfiguration();
|
camera_tab->SetConfiguration();
|
||||||
ui->debugTab->SetConfiguration();
|
debug_tab->SetConfiguration();
|
||||||
ui->webTab->SetConfiguration();
|
web_tab->SetConfiguration();
|
||||||
ui->uiTab->SetConfiguration();
|
ui_tab->SetConfiguration();
|
||||||
ui->storageTab->SetConfiguration();
|
storage_tab->SetConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureDialog::ApplyConfiguration() {
|
void ConfigureDialog::ApplyConfiguration() {
|
||||||
ui->generalTab->ApplyConfiguration();
|
general_tab->ApplyConfiguration();
|
||||||
ui->systemTab->ApplyConfiguration();
|
system_tab->ApplyConfiguration();
|
||||||
ui->inputTab->ApplyConfiguration();
|
input_tab->ApplyConfiguration();
|
||||||
ui->inputTab->ApplyProfile();
|
input_tab->ApplyProfile();
|
||||||
ui->hotkeysTab->ApplyConfiguration(registry);
|
hotkeys_tab->ApplyConfiguration(registry);
|
||||||
ui->graphicsTab->ApplyConfiguration();
|
graphics_tab->ApplyConfiguration();
|
||||||
ui->enhancementsTab->ApplyConfiguration();
|
enhancements_tab->ApplyConfiguration();
|
||||||
ui->audioTab->ApplyConfiguration();
|
audio_tab->ApplyConfiguration();
|
||||||
ui->cameraTab->ApplyConfiguration();
|
camera_tab->ApplyConfiguration();
|
||||||
ui->debugTab->ApplyConfiguration();
|
debug_tab->ApplyConfiguration();
|
||||||
ui->webTab->ApplyConfiguration();
|
web_tab->ApplyConfiguration();
|
||||||
ui->uiTab->ApplyConfiguration();
|
ui_tab->ApplyConfiguration();
|
||||||
ui->storageTab->ApplyConfiguration();
|
storage_tab->ApplyConfiguration();
|
||||||
system.ApplySettings();
|
system.ApplySettings();
|
||||||
Settings::LogSettings();
|
Settings::LogSettings();
|
||||||
}
|
}
|
||||||
|
@ -81,11 +117,11 @@ void ConfigureDialog::PopulateSelectionList() {
|
||||||
ui->selectorList->clear();
|
ui->selectorList->clear();
|
||||||
|
|
||||||
const std::array<std::pair<QString, QList<QWidget*>>, 5> items{
|
const std::array<std::pair<QString, QList<QWidget*>>, 5> items{
|
||||||
{{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}},
|
{{tr("General"), {general_tab.get(), web_tab.get(), debug_tab.get(), ui_tab.get()}},
|
||||||
{tr("System"), {ui->systemTab, ui->cameraTab, ui->storageTab}},
|
{tr("System"), {system_tab.get(), camera_tab.get(), storage_tab.get()}},
|
||||||
{tr("Graphics"), {ui->enhancementsTab, ui->graphicsTab}},
|
{tr("Graphics"), {enhancements_tab.get(), graphics_tab.get()}},
|
||||||
{tr("Audio"), {ui->audioTab}},
|
{tr("Audio"), {audio_tab.get()}},
|
||||||
{tr("Controls"), {ui->inputTab, ui->hotkeysTab}}}};
|
{tr("Controls"), {input_tab.get(), hotkeys_tab.get()}}}};
|
||||||
|
|
||||||
for (const auto& entry : items) {
|
for (const auto& entry : items) {
|
||||||
auto* const item = new QListWidgetItem(entry.first);
|
auto* const item = new QListWidgetItem(entry.first);
|
||||||
|
@ -112,18 +148,18 @@ void ConfigureDialog::RetranslateUI() {
|
||||||
ui->selectorList->setCurrentRow(old_row);
|
ui->selectorList->setCurrentRow(old_row);
|
||||||
ui->tabWidget->setCurrentIndex(old_index);
|
ui->tabWidget->setCurrentIndex(old_index);
|
||||||
|
|
||||||
ui->generalTab->RetranslateUI();
|
general_tab->RetranslateUI();
|
||||||
ui->systemTab->RetranslateUI();
|
system_tab->RetranslateUI();
|
||||||
ui->inputTab->RetranslateUI();
|
input_tab->RetranslateUI();
|
||||||
ui->hotkeysTab->RetranslateUI();
|
hotkeys_tab->RetranslateUI();
|
||||||
ui->graphicsTab->RetranslateUI();
|
graphics_tab->RetranslateUI();
|
||||||
ui->enhancementsTab->RetranslateUI();
|
enhancements_tab->RetranslateUI();
|
||||||
ui->audioTab->RetranslateUI();
|
audio_tab->RetranslateUI();
|
||||||
ui->cameraTab->RetranslateUI();
|
camera_tab->RetranslateUI();
|
||||||
ui->debugTab->RetranslateUI();
|
debug_tab->RetranslateUI();
|
||||||
ui->webTab->RetranslateUI();
|
web_tab->RetranslateUI();
|
||||||
ui->uiTab->RetranslateUI();
|
ui_tab->RetranslateUI();
|
||||||
ui->storageTab->RetranslateUI();
|
storage_tab->RetranslateUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureDialog::UpdateVisibleTabs() {
|
void ConfigureDialog::UpdateVisibleTabs() {
|
||||||
|
@ -131,18 +167,18 @@ void ConfigureDialog::UpdateVisibleTabs() {
|
||||||
if (items.isEmpty())
|
if (items.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::map<QWidget*, QString> widgets = {{ui->generalTab, tr("General")},
|
const std::map<QWidget*, QString> widgets = {{general_tab.get(), tr("General")},
|
||||||
{ui->systemTab, tr("System")},
|
{system_tab.get(), tr("System")},
|
||||||
{ui->inputTab, tr("Input")},
|
{input_tab.get(), tr("Input")},
|
||||||
{ui->hotkeysTab, tr("Hotkeys")},
|
{hotkeys_tab.get(), tr("Hotkeys")},
|
||||||
{ui->enhancementsTab, tr("Enhancements")},
|
{enhancements_tab.get(), tr("Enhancements")},
|
||||||
{ui->graphicsTab, tr("Advanced")},
|
{graphics_tab.get(), tr("Advanced")},
|
||||||
{ui->audioTab, tr("Audio")},
|
{audio_tab.get(), tr("Audio")},
|
||||||
{ui->cameraTab, tr("Camera")},
|
{camera_tab.get(), tr("Camera")},
|
||||||
{ui->debugTab, tr("Debug")},
|
{debug_tab.get(), tr("Debug")},
|
||||||
{ui->storageTab, tr("Storage")},
|
{storage_tab.get(), tr("Storage")},
|
||||||
{ui->webTab, tr("Web")},
|
{web_tab.get(), tr("Web")},
|
||||||
{ui->uiTab, tr("UI")}};
|
{ui_tab.get(), tr("UI")}};
|
||||||
|
|
||||||
ui->tabWidget->clear();
|
ui->tabWidget->clear();
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,19 @@ namespace Core {
|
||||||
class System;
|
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 {
|
class ConfigureDialog : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -42,4 +55,18 @@ private:
|
||||||
std::unique_ptr<Ui::ConfigureDialog> ui;
|
std::unique_ptr<Ui::ConfigureDialog> ui;
|
||||||
HotkeyRegistry& registry;
|
HotkeyRegistry& registry;
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
bool is_powered_on;
|
||||||
|
|
||||||
|
std::unique_ptr<ConfigureGeneral> general_tab;
|
||||||
|
std::unique_ptr<ConfigureSystem> system_tab;
|
||||||
|
std::unique_ptr<ConfigureInput> input_tab;
|
||||||
|
std::unique_ptr<ConfigureHotkeys> hotkeys_tab;
|
||||||
|
std::unique_ptr<ConfigureGraphics> graphics_tab;
|
||||||
|
std::unique_ptr<ConfigureEnhancements> enhancements_tab;
|
||||||
|
std::unique_ptr<ConfigureAudio> audio_tab;
|
||||||
|
std::unique_ptr<ConfigureCamera> camera_tab;
|
||||||
|
std::unique_ptr<ConfigureDebug> debug_tab;
|
||||||
|
std::unique_ptr<ConfigureStorage> storage_tab;
|
||||||
|
std::unique_ptr<ConfigureWeb> web_tab;
|
||||||
|
std::unique_ptr<ConfigureUi> ui_tab;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,8 +22,7 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent)
|
||||||
const bool res_scale_enabled = graphics_api != Settings::GraphicsAPI::Software;
|
const bool res_scale_enabled = graphics_api != Settings::GraphicsAPI::Software;
|
||||||
ui->resolution_factor_combobox->setEnabled(res_scale_enabled);
|
ui->resolution_factor_combobox->setEnabled(res_scale_enabled);
|
||||||
|
|
||||||
connect(ui->render_3d_combobox,
|
connect(ui->render_3d_combobox, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
|
||||||
[this](int currentIndex) {
|
[this](int currentIndex) {
|
||||||
updateShaders(static_cast<Settings::StereoRenderOption>(currentIndex));
|
updateShaders(static_cast<Settings::StereoRenderOption>(currentIndex));
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,14 +6,13 @@
|
||||||
#include "citra_qt/configuration/configuration_shared.h"
|
#include "citra_qt/configuration/configuration_shared.h"
|
||||||
#include "citra_qt/configuration/configure_graphics.h"
|
#include "citra_qt/configuration/configure_graphics.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "ui_configure_graphics.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::ConfigureGraphics>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) {
|
||||||
ui->setupUi(this);
|
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
|
// Set the index to -1 to ensure the below lambda is called with setCurrentIndex
|
||||||
ui->graphics_api_combo->setCurrentIndex(-1);
|
ui->graphics_api_combo->setCurrentIndex(-1);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ class ConfigureGraphics : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureGraphics(QWidget* parent = nullptr);
|
explicit ConfigureGraphics(bool is_powered_on, QWidget* parent = nullptr);
|
||||||
~ConfigureGraphics() override;
|
~ConfigureGraphics() override;
|
||||||
|
|
||||||
void ApplyConfiguration();
|
void ApplyConfiguration();
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Graphics</string>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="apiBox">
|
<widget class="QGroupBox" name="apiBox">
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "citra_qt/configuration/configure_hotkeys.h"
|
#include "citra_qt/configuration/configure_hotkeys.h"
|
||||||
#include "citra_qt/hotkeys.h"
|
#include "citra_qt/hotkeys.h"
|
||||||
#include "citra_qt/util/sequence_dialog/sequence_dialog.h"
|
#include "citra_qt/util/sequence_dialog/sequence_dialog.h"
|
||||||
#include "common/settings.h"
|
|
||||||
#include "ui_configure_hotkeys.h"
|
#include "ui_configure_hotkeys.h"
|
||||||
|
|
||||||
constexpr int name_column = 0;
|
constexpr int name_column = 0;
|
||||||
|
@ -189,9 +188,9 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) {
|
||||||
QAction* clear = context_menu.addAction(tr("Clear"));
|
QAction* clear = context_menu.addAction(tr("Clear"));
|
||||||
|
|
||||||
const auto hotkey_index = index.sibling(index.row(), hotkey_column);
|
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); });
|
[this, hotkey_index] { RestoreHotkey(hotkey_index); });
|
||||||
connect(clear, &QAction::triggered,
|
connect(clear, &QAction::triggered, this,
|
||||||
[this, hotkey_index] { model->setData(hotkey_index, QString{}); });
|
[this, hotkey_index] { model->setData(hotkey_index, QString{}); });
|
||||||
|
|
||||||
context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location));
|
context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location));
|
||||||
|
|
|
@ -31,13 +31,14 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString
|
||||||
: fmt::format("{:016X}", title_id);
|
: fmt::format("{:016X}", title_id);
|
||||||
game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig);
|
game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig);
|
||||||
|
|
||||||
audio_tab = std::make_unique<ConfigureAudio>(this);
|
const bool is_powered_on = system.IsPoweredOn();
|
||||||
|
audio_tab = std::make_unique<ConfigureAudio>(is_powered_on, this);
|
||||||
general_tab = std::make_unique<ConfigureGeneral>(this);
|
general_tab = std::make_unique<ConfigureGeneral>(this);
|
||||||
enhancements_tab = std::make_unique<ConfigureEnhancements>(this);
|
enhancements_tab = std::make_unique<ConfigureEnhancements>(this);
|
||||||
graphics_tab = std::make_unique<ConfigureGraphics>(this);
|
graphics_tab = std::make_unique<ConfigureGraphics>(is_powered_on, this);
|
||||||
system_tab = std::make_unique<ConfigureSystem>(this);
|
system_tab = std::make_unique<ConfigureSystem>(system, this);
|
||||||
debug_tab = std::make_unique<ConfigureDebug>(this);
|
debug_tab = std::make_unique<ConfigureDebug>(is_powered_on, this);
|
||||||
cheat_tab = std::make_unique<ConfigureCheats>(title_id, this);
|
cheat_tab = std::make_unique<ConfigureCheats>(system, title_id, this);
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,10 @@
|
||||||
#include "citra_qt/configuration/configure_storage.h"
|
#include "citra_qt/configuration/configure_storage.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "ui_configure_storage.h"
|
#include "ui_configure_storage.h"
|
||||||
|
|
||||||
ConfigureStorage::ConfigureStorage(QWidget* parent)
|
ConfigureStorage::ConfigureStorage(bool is_powered_on_, QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureStorage>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureStorage>()), is_powered_on{is_powered_on_} {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
SetConfiguration();
|
SetConfiguration();
|
||||||
|
|
||||||
|
@ -75,7 +74,7 @@ void ConfigureStorage::SetConfiguration() {
|
||||||
ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue());
|
ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue());
|
||||||
ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage.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() {
|
void ConfigureStorage::ApplyConfiguration() {
|
||||||
|
|
|
@ -15,7 +15,7 @@ class ConfigureStorage : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureStorage(QWidget* parent = nullptr);
|
explicit ConfigureStorage(bool is_powered_on, QWidget* parent = nullptr);
|
||||||
~ConfigureStorage() override;
|
~ConfigureStorage() override;
|
||||||
|
|
||||||
void ApplyConfiguration();
|
void ApplyConfiguration();
|
||||||
|
@ -23,4 +23,5 @@ public:
|
||||||
void SetConfiguration();
|
void SetConfiguration();
|
||||||
|
|
||||||
std::unique_ptr<Ui::ConfigureStorage> ui;
|
std::unique_ptr<Ui::ConfigureStorage> ui;
|
||||||
|
bool is_powered_on;
|
||||||
};
|
};
|
||||||
|
|
|
@ -223,14 +223,12 @@ static const std::array<const char*, 187> country_names = {
|
||||||
QT_TRANSLATE_NOOP("ConfigureSystem", "Bermuda"), // 180-186
|
QT_TRANSLATE_NOOP("ConfigureSystem", "Bermuda"), // 180-186
|
||||||
};
|
};
|
||||||
|
|
||||||
ConfigureSystem::ConfigureSystem(QWidget* parent)
|
ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureSystem>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureSystem>()), system{system_} {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
connect(ui->combo_birthmonth,
|
connect(ui->combo_birthmonth, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
|
||||||
&ConfigureSystem::UpdateBirthdayComboBox);
|
&ConfigureSystem::UpdateBirthdayComboBox);
|
||||||
connect(ui->combo_init_clock,
|
connect(ui->combo_init_clock, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
|
||||||
&ConfigureSystem::UpdateInitTime);
|
&ConfigureSystem::UpdateInitTime);
|
||||||
connect(ui->button_regenerate_console_id, &QPushButton::clicked, this,
|
connect(ui->button_regenerate_console_id, &QPushButton::clicked, this,
|
||||||
&ConfigureSystem::RefreshConsoleID);
|
&ConfigureSystem::RefreshConsoleID);
|
||||||
|
@ -280,7 +278,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent)
|
||||||
ConfigureSystem::~ConfigureSystem() = default;
|
ConfigureSystem::~ConfigureSystem() = default;
|
||||||
|
|
||||||
void ConfigureSystem::SetConfiguration() {
|
void ConfigureSystem::SetConfiguration() {
|
||||||
enabled = !Core::System::GetInstance().IsPoweredOn();
|
enabled = !system.IsPoweredOn();
|
||||||
|
|
||||||
ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock.GetValue()));
|
ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock.GetValue()));
|
||||||
QDateTime date_time;
|
QDateTime date_time;
|
||||||
|
@ -296,7 +294,7 @@ void ConfigureSystem::SetConfiguration() {
|
||||||
ui->edit_init_time_offset_time->setTime(time);
|
ui->edit_init_time_offset_time->setTime(time);
|
||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
cfg = Service::CFG::GetModule(Core::System::GetInstance());
|
cfg = Service::CFG::GetModule(system);
|
||||||
ASSERT_MSG(cfg, "CFG Module missing!");
|
ASSERT_MSG(cfg, "CFG Module missing!");
|
||||||
ReadSystemSettings();
|
ReadSystemSettings();
|
||||||
ui->group_system_settings->setEnabled(false);
|
ui->group_system_settings->setEnabled(false);
|
||||||
|
|
|
@ -16,6 +16,10 @@ namespace ConfigurationShared {
|
||||||
enum class CheckState;
|
enum class CheckState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
class Module;
|
class Module;
|
||||||
|
@ -26,7 +30,7 @@ class ConfigureSystem : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureSystem(QWidget* parent = nullptr);
|
explicit ConfigureSystem(Core::System& system, QWidget* parent = nullptr);
|
||||||
~ConfigureSystem() override;
|
~ConfigureSystem() override;
|
||||||
|
|
||||||
void ApplyConfiguration();
|
void ApplyConfiguration();
|
||||||
|
@ -45,8 +49,10 @@ private:
|
||||||
|
|
||||||
void DownloadFromNUS();
|
void DownloadFromNUS();
|
||||||
|
|
||||||
ConfigurationShared::CheckState is_new_3ds;
|
private:
|
||||||
std::unique_ptr<Ui::ConfigureSystem> ui;
|
std::unique_ptr<Ui::ConfigureSystem> ui;
|
||||||
|
Core::System& system;
|
||||||
|
ConfigurationShared::CheckState is_new_3ds;
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
|
|
||||||
std::shared_ptr<Service::CFG::Module> cfg;
|
std::shared_ptr<Service::CFG::Module> cfg;
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "citra_qt/debugger/graphics/graphics_cmdlists.h"
|
#include "citra_qt/debugger/graphics/graphics_cmdlists.h"
|
||||||
#include "citra_qt/util/util.h"
|
#include "citra_qt/util/util.h"
|
||||||
#include "common/vector_math.h"
|
#include "common/vector_math.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
#include "video_core/debug_utils/debug_utils.h"
|
||||||
#include "video_core/pica_state.h"
|
#include "video_core/pica_state.h"
|
||||||
|
@ -167,8 +166,7 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
|
||||||
const auto format = texture.format;
|
const auto format = texture.format;
|
||||||
|
|
||||||
const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format);
|
const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format);
|
||||||
const u8* src =
|
const u8* src = memory.GetPhysicalPointer(config.GetPhysicalAddress());
|
||||||
Core::System::GetInstance().Memory().GetPhysicalPointer(config.GetPhysicalAddress());
|
|
||||||
new_info_widget = new TextureInfoWidget(src, info);
|
new_info_widget = new TextureInfoWidget(src, info);
|
||||||
}
|
}
|
||||||
if (command_info_widget) {
|
if (command_info_widget) {
|
||||||
|
@ -182,8 +180,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
|
||||||
}
|
}
|
||||||
#undef COMMAND_IN_RANGE
|
#undef COMMAND_IN_RANGE
|
||||||
|
|
||||||
GPUCommandListWidget::GPUCommandListWidget(QWidget* parent)
|
GPUCommandListWidget::GPUCommandListWidget(Memory::MemorySystem& memory_, QWidget* parent)
|
||||||
: QDockWidget(tr("Pica Command List"), parent) {
|
: QDockWidget(tr("Pica Command List"), parent), memory{memory_} {
|
||||||
setObjectName(QStringLiteral("Pica Command List"));
|
setObjectName(QStringLiteral("Pica Command List"));
|
||||||
GPUCommandListModel* model = new GPUCommandListModel(this);
|
GPUCommandListModel* model = new GPUCommandListModel(this);
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,14 @@
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
#include "video_core/debug_utils/debug_utils.h"
|
||||||
#include "video_core/gpu_debugger.h"
|
|
||||||
|
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QTreeView;
|
class QTreeView;
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class MemorySystem;
|
||||||
|
}
|
||||||
|
|
||||||
class GPUCommandListModel : public QAbstractListModel {
|
class GPUCommandListModel : public QAbstractListModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -39,7 +42,7 @@ class GPUCommandListWidget : public QDockWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GPUCommandListWidget(QWidget* parent = nullptr);
|
explicit GPUCommandListWidget(Memory::MemorySystem& memory, QWidget* parent = nullptr);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void OnToggleTracing();
|
void OnToggleTracing();
|
||||||
|
@ -54,7 +57,7 @@ signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Pica::DebugUtils::PicaTrace> pica_trace;
|
std::unique_ptr<Pica::DebugUtils::PicaTrace> pica_trace;
|
||||||
|
Memory::MemorySystem& memory;
|
||||||
QTreeView* list_widget;
|
QTreeView* list_widget;
|
||||||
QWidget* command_info_widget;
|
QWidget* command_info_widget;
|
||||||
QPushButton* toggle_tracing;
|
QPushButton* toggle_tracing;
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
#include "citra_qt/debugger/graphics/graphics_surface.h"
|
#include "citra_qt/debugger/graphics/graphics_surface.h"
|
||||||
#include "citra_qt/util/spinbox.h"
|
#include "citra_qt/util/spinbox.h"
|
||||||
#include "common/color.h"
|
#include "common/color.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/hw/gpu.h"
|
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "video_core/pica_state.h"
|
#include "video_core/pica_state.h"
|
||||||
#include "video_core/regs_framebuffer.h"
|
#include "video_core/regs_framebuffer.h"
|
||||||
|
@ -51,9 +49,10 @@ void SurfacePicture::mouseMoveEvent(QMouseEvent* event) {
|
||||||
mousePressEvent(event);
|
mousePressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
|
GraphicsSurfaceWidget::GraphicsSurfaceWidget(Memory::MemorySystem& memory_,
|
||||||
|
std::shared_ptr<Pica::DebugContext> debug_context,
|
||||||
QWidget* parent)
|
QWidget* parent)
|
||||||
: BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent),
|
: BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), memory{memory_},
|
||||||
surface_source(Source::ColorBuffer) {
|
surface_source(Source::ColorBuffer) {
|
||||||
setObjectName(QStringLiteral("PicaSurface"));
|
setObjectName(QStringLiteral("PicaSurface"));
|
||||||
|
|
||||||
|
@ -290,57 +289,57 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
|
const u8* buffer = memory.GetPhysicalPointer(surface_address);
|
||||||
if (buffer == nullptr) {
|
if (!buffer) {
|
||||||
surface_info_label->setText(tr("(unable to access pixel data)"));
|
surface_info_label->setText(tr("(unable to access pixel data)"));
|
||||||
surface_info_label->setAlignment(Qt::AlignCenter);
|
surface_info_label->setAlignment(Qt::AlignCenter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format);
|
const u32 nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format);
|
||||||
unsigned stride = nibbles_per_pixel * surface_width / 2;
|
const u32 stride = nibbles_per_pixel * surface_width / 2;
|
||||||
|
const bool nibble_mode = (nibbles_per_pixel == 1);
|
||||||
unsigned bytes_per_pixel;
|
const u32 bytes_per_pixel = [&] {
|
||||||
bool nibble_mode = (nibbles_per_pixel == 1);
|
|
||||||
if (nibble_mode) {
|
if (nibble_mode) {
|
||||||
// As nibbles are contained in a byte we still need to access one byte per nibble
|
// As nibbles are contained in a byte we still need to access one byte per nibble
|
||||||
bytes_per_pixel = 1;
|
return 1u;
|
||||||
} else {
|
} else {
|
||||||
bytes_per_pixel = nibbles_per_pixel / 2;
|
return nibbles_per_pixel / 2;
|
||||||
}
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
const u32 coarse_y = y & ~7;
|
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);
|
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) {
|
switch (format) {
|
||||||
case Format::RGBA8: {
|
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")
|
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
|
||||||
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
|
.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));
|
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
|
||||||
}
|
}
|
||||||
case Format::RGB8: {
|
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")
|
return QStringLiteral("Red: %1, Green: %2, Blue: %3")
|
||||||
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
|
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
|
||||||
QString::number(value.b(), 'f', 2));
|
QString::number(value.b(), 'f', 2));
|
||||||
}
|
}
|
||||||
case Format::RGB5A1: {
|
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")
|
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
|
||||||
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
|
.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));
|
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
|
||||||
}
|
}
|
||||||
case Format::RGB565: {
|
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")
|
return QStringLiteral("Red: %1, Green: %2, Blue: %3")
|
||||||
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
|
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
|
||||||
QString::number(value.b(), 'f', 2));
|
QString::number(value.b(), 'f', 2));
|
||||||
}
|
}
|
||||||
case Format::RGBA4: {
|
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")
|
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
|
||||||
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
|
.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));
|
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:
|
case Format::IA8:
|
||||||
return QStringLiteral("Index: %1, Alpha: %2").arg(pixel[0], pixel[1]);
|
return QStringLiteral("Index: %1, Alpha: %2").arg(pixel[0], pixel[1]);
|
||||||
case Format::RG8: {
|
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")
|
return QStringLiteral("Red: %1, Green: %2")
|
||||||
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 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:
|
case Format::IA4:
|
||||||
return QStringLiteral("Index: %1, Alpha: %2").arg(*pixel & 0xF, (*pixel & 0xF0) >> 4);
|
return QStringLiteral("Index: %1, Alpha: %2").arg(*pixel & 0xF, (*pixel & 0xF0) >> 4);
|
||||||
case Format::I4: {
|
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);
|
return QStringLiteral("Index: %1").arg(i);
|
||||||
}
|
}
|
||||||
case Format::A4: {
|
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));
|
return QStringLiteral("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2));
|
||||||
}
|
}
|
||||||
case Format::ETC1:
|
case Format::ETC1:
|
||||||
|
@ -371,17 +370,17 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
|
||||||
// TODO: Display block information or channel values?
|
// TODO: Display block information or channel values?
|
||||||
return QStringLiteral("Compressed data");
|
return QStringLiteral("Compressed data");
|
||||||
case Format::D16: {
|
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));
|
return QStringLiteral("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4));
|
||||||
}
|
}
|
||||||
case Format::D24: {
|
case Format::D24: {
|
||||||
auto value = Common::Color::DecodeD24(pixel);
|
const auto value = Common::Color::DecodeD24(pixel);
|
||||||
return QStringLiteral("Depth: %1")
|
return QStringLiteral("Depth: %1")
|
||||||
.arg(QString::number(value / (float)0xFFFFFF, 'f', 4));
|
.arg(QString::number(value / (float)0xFFFFFF, 'f', 4));
|
||||||
}
|
}
|
||||||
case Format::D24X8:
|
case Format::D24X8:
|
||||||
case Format::X24S8: {
|
case Format::X24S8: {
|
||||||
auto values = Common::Color::DecodeD24S8(pixel);
|
const auto values = Common::Color::DecodeD24S8(pixel);
|
||||||
return QStringLiteral("Depth: %1, Stencil: %2")
|
return QStringLiteral("Depth: %1, Stencil: %2")
|
||||||
.arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4), values[1]);
|
.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) {
|
if (nibble_mode) {
|
||||||
nibble_index += (offset % 2) ? 0 : 1;
|
nibble_index += (offset % 2) ? 0 : 1;
|
||||||
}
|
}
|
||||||
u8 byte = pixel[nibble_index / 2];
|
const u8 byte = pixel[nibble_index / 2];
|
||||||
u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF;
|
const u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF;
|
||||||
nibbles.append(QString::number(nibble, 16).toUpper());
|
nibbles.append(QString::number(nibble, 16).toUpper());
|
||||||
}
|
}
|
||||||
|
|
||||||
surface_info_label->setText(
|
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);
|
surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,9 +545,9 @@ void GraphicsSurfaceWidget::OnUpdate() {
|
||||||
// TODO: Implement a good way to visualize alpha components!
|
// TODO: Implement a good way to visualize alpha components!
|
||||||
|
|
||||||
QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
|
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_picture_label->hide();
|
||||||
surface_info_label->setText(tr("(invalid surface address)"));
|
surface_info_label->setText(tr("(invalid surface address)"));
|
||||||
surface_info_label->setAlignment(Qt::AlignCenter);
|
surface_info_label->setAlignment(Qt::AlignCenter);
|
||||||
|
@ -682,9 +681,8 @@ void GraphicsSurfaceWidget::SaveSurface() {
|
||||||
tr("Failed to save surface data to file '%1'").arg(filename));
|
tr("Failed to save surface data to file '%1'").arg(filename));
|
||||||
}
|
}
|
||||||
} else if (selected_filter == bin_filter) {
|
} else if (selected_filter == bin_filter) {
|
||||||
const u8* const buffer =
|
const u8* const buffer = memory.GetPhysicalPointer(surface_address);
|
||||||
Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
|
ASSERT_MSG(buffer, "Memory not accessible");
|
||||||
ASSERT_MSG(buffer != nullptr, "Memory not accessible");
|
|
||||||
|
|
||||||
QFile file{filename};
|
QFile file{filename};
|
||||||
if (!file.open(QIODevice::WriteOnly)) {
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
|
|
|
@ -14,6 +14,10 @@ class CSpinBox;
|
||||||
|
|
||||||
class GraphicsSurfaceWidget;
|
class GraphicsSurfaceWidget;
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class MemorySystem;
|
||||||
|
}
|
||||||
|
|
||||||
class SurfacePicture : public QLabel {
|
class SurfacePicture : public QLabel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -72,7 +76,8 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock {
|
||||||
static unsigned int NibblesPerPixel(Format format);
|
static unsigned int NibblesPerPixel(Format format);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
|
explicit GraphicsSurfaceWidget(Memory::MemorySystem& memory,
|
||||||
|
std::shared_ptr<Pica::DebugContext> debug_context,
|
||||||
QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
void Pick(int x, int y);
|
void Pick(int x, int y);
|
||||||
|
|
||||||
|
@ -95,6 +100,7 @@ private:
|
||||||
|
|
||||||
void SaveSurface();
|
void SaveSurface();
|
||||||
|
|
||||||
|
Memory::MemorySystem& memory;
|
||||||
QComboBox* surface_source_list;
|
QComboBox* surface_source_list;
|
||||||
CSpinBox* surface_address_control;
|
CSpinBox* surface_address_control;
|
||||||
QSpinBox* surface_width_control;
|
QSpinBox* surface_width_control;
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
#include "ui_recorder.h"
|
#include "ui_recorder.h"
|
||||||
|
|
||||||
IPCRecorderWidget::IPCRecorderWidget(QWidget* parent)
|
IPCRecorderWidget::IPCRecorderWidget(Core::System& system_, QWidget* parent)
|
||||||
: QDockWidget(parent), ui(std::make_unique<Ui::IPCRecorder>()) {
|
: QDockWidget(parent), ui(std::make_unique<Ui::IPCRecorder>()), system{system_} {
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
qRegisterMetaType<IPCDebugger::RequestRecord>();
|
qRegisterMetaType<IPCDebugger::RequestRecord>();
|
||||||
|
|
||||||
connect(ui->enabled, &QCheckBox::stateChanged,
|
connect(ui->enabled, &QCheckBox::stateChanged, this,
|
||||||
[this](int new_state) { SetEnabled(new_state == Qt::Checked); });
|
[this](int new_state) { SetEnabled(new_state == Qt::Checked); });
|
||||||
connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear);
|
connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear);
|
||||||
connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll);
|
connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll);
|
||||||
|
@ -90,7 +90,7 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) {
|
||||||
(record.status == IPCDebugger::RequestStatus::Handled &&
|
(record.status == IPCDebugger::RequestStatus::Handled &&
|
||||||
record.translated_reply_cmdbuf[1] != RESULT_SUCCESS.raw)) { // Unimplemented / Error
|
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) {
|
for (int column = 0; column < item->columnCount(); ++column) {
|
||||||
item->setBackground(column, QBrush(QColor::fromRgb(255, 0, 0)));
|
item->setBackground(column, QBrush(QColor::fromRgb(255, 0, 0)));
|
||||||
}
|
}
|
||||||
|
@ -100,11 +100,11 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPCRecorderWidget::SetEnabled(bool enabled) {
|
void IPCRecorderWidget::SetEnabled(bool enabled) {
|
||||||
if (!Core::System::GetInstance().IsPoweredOn()) {
|
if (!system.IsPoweredOn()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& ipc_recorder = Core::System::GetInstance().Kernel().GetIPCRecorder();
|
auto& ipc_recorder = system.Kernel().GetIPCRecorder();
|
||||||
ipc_recorder.SetEnabled(enabled);
|
ipc_recorder.SetEnabled(enabled);
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
@ -123,10 +123,10 @@ void IPCRecorderWidget::Clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString IPCRecorderWidget::GetServiceName(const IPCDebugger::RequestRecord& record) const {
|
QString IPCRecorderWidget::GetServiceName(const IPCDebugger::RequestRecord& record) const {
|
||||||
if (Core::System::GetInstance().IsPoweredOn() && record.client_port.id != -1) {
|
if (system.IsPoweredOn() && record.client_port.id != -1) {
|
||||||
const auto service_name =
|
const Service::SM::ServiceManager& sm = system.ServiceManager();
|
||||||
Core::System::GetInstance().ServiceManager().GetServiceNameByPortId(
|
const u32 port_id = static_cast<u32>(record.client_port.id);
|
||||||
static_cast<u32>(record.client_port.id));
|
const auto service_name = sm.GetServiceNameByPortId(port_id);
|
||||||
|
|
||||||
if (!service_name.empty()) {
|
if (!service_name.empty()) {
|
||||||
return QString::fromStdString(service_name);
|
return QString::fromStdString(service_name);
|
||||||
|
|
|
@ -14,11 +14,15 @@ namespace Ui {
|
||||||
class IPCRecorder;
|
class IPCRecorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
class IPCRecorderWidget : public QDockWidget {
|
class IPCRecorderWidget : public QDockWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit IPCRecorderWidget(QWidget* parent = nullptr);
|
explicit IPCRecorderWidget(Core::System& system, QWidget* parent = nullptr);
|
||||||
~IPCRecorderWidget();
|
~IPCRecorderWidget();
|
||||||
|
|
||||||
void OnEmulationStarting();
|
void OnEmulationStarting();
|
||||||
|
@ -37,9 +41,10 @@ private:
|
||||||
QString GetFunctionName(const IPCDebugger::RequestRecord& record) const;
|
QString GetFunctionName(const IPCDebugger::RequestRecord& record) const;
|
||||||
void OpenRecordDialog(QTreeWidgetItem* item, int column);
|
void OpenRecordDialog(QTreeWidgetItem* item, int column);
|
||||||
|
|
||||||
|
private:
|
||||||
std::unique_ptr<Ui::IPCRecorder> ui;
|
std::unique_ptr<Ui::IPCRecorder> ui;
|
||||||
IPCDebugger::CallbackHandle handle;
|
IPCDebugger::CallbackHandle handle;
|
||||||
|
Core::System& system;
|
||||||
// The offset between record id and row id, assuming record ids are assigned
|
// 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.
|
// continuously and only the 'Clear' action can be performed, this is enough.
|
||||||
// The initial value is 1, which means record 1 = row 0.
|
// The initial value is 1, which means record 1 = row 0.
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "ui_registers.h"
|
#include "ui_registers.h"
|
||||||
|
|
||||||
RegistersWidget::RegistersWidget(QWidget* parent)
|
RegistersWidget::RegistersWidget(const Core::System& system_, QWidget* parent)
|
||||||
: QDockWidget(parent), cpu_regs_ui(std::make_unique<Ui::ARMRegisters>()) {
|
: QDockWidget(parent), cpu_regs_ui(std::make_unique<Ui::ARMRegisters>()), system{system_} {
|
||||||
cpu_regs_ui->setupUi(this);
|
cpu_regs_ui->setupUi(this);
|
||||||
|
|
||||||
tree = cpu_regs_ui->treeWidget;
|
tree = cpu_regs_ui->treeWidget;
|
||||||
|
@ -62,17 +62,21 @@ RegistersWidget::RegistersWidget(QWidget* parent)
|
||||||
RegistersWidget::~RegistersWidget() = default;
|
RegistersWidget::~RegistersWidget() = default;
|
||||||
|
|
||||||
void RegistersWidget::OnDebugModeEntered() {
|
void RegistersWidget::OnDebugModeEntered() {
|
||||||
if (!Core::System::GetInstance().IsPoweredOn())
|
if (!system.IsPoweredOn()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Todo: Handle all cores
|
// TODO: Handle all cores
|
||||||
for (int i = 0; i < core_registers->childCount(); ++i)
|
const ARM_Interface& core = system.GetCore(0);
|
||||||
|
for (int i = 0; i < core_registers->childCount(); ++i) {
|
||||||
core_registers->child(i)->setText(
|
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(
|
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();
|
UpdateCPSRValues();
|
||||||
UpdateVFPSystemRegisterValues();
|
UpdateVFPSystemRegisterValues();
|
||||||
|
@ -86,24 +90,29 @@ void RegistersWidget::OnEmulationStarting(EmuThread* emu_thread) {
|
||||||
|
|
||||||
void RegistersWidget::OnEmulationStopping() {
|
void RegistersWidget::OnEmulationStopping() {
|
||||||
// Reset widget text
|
// 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{});
|
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{});
|
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->child(i)->setText(1, QString{});
|
||||||
|
}
|
||||||
|
|
||||||
cpsr->setText(1, QString{});
|
cpsr->setText(1, QString{});
|
||||||
|
|
||||||
// FPSCR
|
// 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{});
|
vfp_system_registers->child(0)->child(i)->setText(1, QString{});
|
||||||
|
}
|
||||||
|
|
||||||
// FPEXC
|
// 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(1)->child(i)->setText(1, QString{});
|
||||||
|
}
|
||||||
|
|
||||||
vfp_system_registers->child(0)->setText(1, QString{});
|
vfp_system_registers->child(0)->setText(1, QString{});
|
||||||
vfp_system_registers->child(1)->setText(1, QString{});
|
vfp_system_registers->child(1)->setText(1, QString{});
|
||||||
|
@ -130,8 +139,8 @@ void RegistersWidget::CreateCPSRChildren() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegistersWidget::UpdateCPSRValues() {
|
void RegistersWidget::UpdateCPSRValues() {
|
||||||
// Todo: Handle all cores
|
// TODO: Handle all cores
|
||||||
const u32 cpsr_val = Core::GetCore(0).GetCPSR();
|
const u32 cpsr_val = system.GetCore(0).GetCPSR();
|
||||||
|
|
||||||
cpsr->setText(1, QStringLiteral("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
|
cpsr->setText(1, QStringLiteral("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
|
||||||
cpsr->child(0)->setText(
|
cpsr->child(0)->setText(
|
||||||
|
@ -193,9 +202,10 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegistersWidget::UpdateVFPSystemRegisterValues() {
|
void RegistersWidget::UpdateVFPSystemRegisterValues() {
|
||||||
// Todo: handle all cores
|
// TODO: handle all cores
|
||||||
const u32 fpscr_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPSCR);
|
const ARM_Interface& core = system.GetCore(0);
|
||||||
const u32 fpexc_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPEXC);
|
const u32 fpscr_val = core.GetVFPSystemReg(VFP_FPSCR);
|
||||||
|
const u32 fpexc_val = core.GetVFPSystemReg(VFP_FPEXC);
|
||||||
|
|
||||||
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
|
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
|
||||||
fpscr->setText(1, QStringLiteral("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));
|
fpscr->setText(1, QStringLiteral("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));
|
||||||
|
|
|
@ -15,11 +15,15 @@ namespace Ui {
|
||||||
class ARMRegisters;
|
class ARMRegisters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
class RegistersWidget : public QDockWidget {
|
class RegistersWidget : public QDockWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RegistersWidget(QWidget* parent = nullptr);
|
explicit RegistersWidget(const Core::System& system, QWidget* parent = nullptr);
|
||||||
~RegistersWidget();
|
~RegistersWidget();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -37,7 +41,7 @@ private:
|
||||||
void UpdateVFPSystemRegisterValues();
|
void UpdateVFPSystemRegisterValues();
|
||||||
|
|
||||||
std::unique_ptr<Ui::ARMRegisters> cpu_regs_ui;
|
std::unique_ptr<Ui::ARMRegisters> cpu_regs_ui;
|
||||||
|
const Core::System& system;
|
||||||
QTreeWidget* tree;
|
QTreeWidget* tree;
|
||||||
|
|
||||||
QTreeWidgetItem* core_registers;
|
QTreeWidgetItem* core_registers;
|
||||||
|
|
|
@ -75,13 +75,13 @@ std::size_t WaitTreeItem::Row() const {
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {
|
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList(
|
||||||
const u32 num_cores = Core::GetNumCores();
|
Core::System& system) {
|
||||||
|
const u32 num_cores = system.GetNumCores();
|
||||||
std::vector<std::unique_ptr<WaitTreeThread>> item_list;
|
std::vector<std::unique_ptr<WaitTreeThread>> item_list;
|
||||||
item_list.reserve(num_cores);
|
item_list.reserve(num_cores);
|
||||||
for (u32 i = 0; i < num_cores; ++i) {
|
for (u32 i = 0; i < num_cores; ++i) {
|
||||||
const auto& threads =
|
const auto threads = system.Kernel().GetThreadManager(i).GetThreadList();
|
||||||
Core::System::GetInstance().Kernel().GetThreadManager(i).GetThreadList();
|
|
||||||
item_list.reserve(item_list.size() + threads.size());
|
item_list.reserve(item_list.size() + threads.size());
|
||||||
for (std::size_t j = 0; j < threads.size(); ++j) {
|
for (std::size_t j = 0; j < threads.size(); ++j) {
|
||||||
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[j]));
|
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[j]));
|
||||||
|
@ -435,11 +435,12 @@ void WaitTreeModel::ClearItems() {
|
||||||
thread_items.clear();
|
thread_items.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitTreeModel::InitItems() {
|
void WaitTreeModel::InitItems(Core::System& system) {
|
||||||
thread_items = WaitTreeItem::MakeThreadItemList();
|
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"));
|
setObjectName(QStringLiteral("WaitTreeWidget"));
|
||||||
view = new QTreeView(this);
|
view = new QTreeView(this);
|
||||||
view->setHeaderHidden(true);
|
view->setHeaderHidden(true);
|
||||||
|
@ -448,9 +449,10 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitTreeWidget::OnDebugModeEntered() {
|
void WaitTreeWidget::OnDebugModeEntered() {
|
||||||
if (!Core::System::GetInstance().IsPoweredOn())
|
if (!system.IsPoweredOn()) {
|
||||||
return;
|
return;
|
||||||
model->InitItems();
|
}
|
||||||
|
model->InitItems(system);
|
||||||
view->setModel(model);
|
view->setModel(model);
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,10 @@ class Thread;
|
||||||
class Timer;
|
class Timer;
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
class WaitTreeThread;
|
class WaitTreeThread;
|
||||||
|
|
||||||
class WaitTreeItem : public QObject {
|
class WaitTreeItem : public QObject {
|
||||||
|
@ -39,7 +43,7 @@ public:
|
||||||
WaitTreeItem* Parent() const;
|
WaitTreeItem* Parent() const;
|
||||||
std::span<const std::unique_ptr<WaitTreeItem>> Children() const;
|
std::span<const std::unique_ptr<WaitTreeItem>> Children() const;
|
||||||
std::size_t Row() const;
|
std::size_t Row() const;
|
||||||
static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList();
|
static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList(Core::System& system);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t row;
|
std::size_t row;
|
||||||
|
@ -166,7 +170,7 @@ public:
|
||||||
int columnCount(const QModelIndex& parent) const override;
|
int columnCount(const QModelIndex& parent) const override;
|
||||||
|
|
||||||
void ClearItems();
|
void ClearItems();
|
||||||
void InitItems();
|
void InitItems(Core::System& system);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<WaitTreeThread>> thread_items;
|
std::vector<std::unique_ptr<WaitTreeThread>> thread_items;
|
||||||
|
@ -176,7 +180,7 @@ class WaitTreeWidget : public QDockWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WaitTreeWidget(QWidget* parent = nullptr);
|
explicit WaitTreeWidget(Core::System& system, QWidget* parent = nullptr);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void OnDebugModeEntered();
|
void OnDebugModeEntered();
|
||||||
|
@ -188,4 +192,5 @@ public slots:
|
||||||
private:
|
private:
|
||||||
QTreeView* view;
|
QTreeView* view;
|
||||||
WaitTreeModel* model;
|
WaitTreeModel* model;
|
||||||
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
|
|
@ -353,8 +353,8 @@ void GMainWindow::InitializeWidgets() {
|
||||||
});
|
});
|
||||||
|
|
||||||
InputCommon::Init();
|
InputCommon::Init();
|
||||||
multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room,
|
multiplayer_state = new MultiplayerState(system, this, game_list->GetModel(),
|
||||||
ui->action_Show_Room);
|
ui->action_Leave_Room, ui->action_Show_Room);
|
||||||
multiplayer_state->setVisible(false);
|
multiplayer_state->setVisible(false);
|
||||||
|
|
||||||
#if ENABLE_QT_UPDATER
|
#if ENABLE_QT_UPDATER
|
||||||
|
@ -434,7 +434,7 @@ void GMainWindow::InitializeDebugWidgets() {
|
||||||
debug_menu->addAction(microProfileDialog->toggleViewAction());
|
debug_menu->addAction(microProfileDialog->toggleViewAction());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
registersWidget = new RegistersWidget(this);
|
registersWidget = new RegistersWidget(system, this);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, registersWidget);
|
addDockWidget(Qt::RightDockWidgetArea, registersWidget);
|
||||||
registersWidget->hide();
|
registersWidget->hide();
|
||||||
debug_menu->addAction(registersWidget->toggleViewAction());
|
debug_menu->addAction(registersWidget->toggleViewAction());
|
||||||
|
@ -448,7 +448,7 @@ void GMainWindow::InitializeDebugWidgets() {
|
||||||
graphicsWidget->hide();
|
graphicsWidget->hide();
|
||||||
debug_menu->addAction(graphicsWidget->toggleViewAction());
|
debug_menu->addAction(graphicsWidget->toggleViewAction());
|
||||||
|
|
||||||
graphicsCommandsWidget = new GPUCommandListWidget(this);
|
graphicsCommandsWidget = new GPUCommandListWidget(system.Memory(), this);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget);
|
addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget);
|
||||||
graphicsCommandsWidget->hide();
|
graphicsCommandsWidget->hide();
|
||||||
debug_menu->addAction(graphicsCommandsWidget->toggleViewAction());
|
debug_menu->addAction(graphicsCommandsWidget->toggleViewAction());
|
||||||
|
@ -472,7 +472,7 @@ void GMainWindow::InitializeDebugWidgets() {
|
||||||
connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget,
|
connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget,
|
||||||
&GraphicsTracingWidget::OnEmulationStopping);
|
&GraphicsTracingWidget::OnEmulationStopping);
|
||||||
|
|
||||||
waitTreeWidget = new WaitTreeWidget(this);
|
waitTreeWidget = new WaitTreeWidget(system, this);
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
|
addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
|
||||||
waitTreeWidget->hide();
|
waitTreeWidget->hide();
|
||||||
debug_menu->addAction(waitTreeWidget->toggleViewAction());
|
debug_menu->addAction(waitTreeWidget->toggleViewAction());
|
||||||
|
@ -490,7 +490,7 @@ void GMainWindow::InitializeDebugWidgets() {
|
||||||
connect(this, &GMainWindow::EmulationStopping, waitTreeWidget,
|
connect(this, &GMainWindow::EmulationStopping, waitTreeWidget,
|
||||||
[this] { lleServiceModulesWidget->setDisabled(false); });
|
[this] { lleServiceModulesWidget->setDisabled(false); });
|
||||||
|
|
||||||
ipcRecorderWidget = new IPCRecorderWidget(this);
|
ipcRecorderWidget = new IPCRecorderWidget(system, this);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, ipcRecorderWidget);
|
addDockWidget(Qt::RightDockWidgetArea, ipcRecorderWidget);
|
||||||
ipcRecorderWidget->hide();
|
ipcRecorderWidget->hide();
|
||||||
debug_menu->addAction(ipcRecorderWidget->toggleViewAction());
|
debug_menu->addAction(ipcRecorderWidget->toggleViewAction());
|
||||||
|
@ -2046,7 +2046,6 @@ void GMainWindow::OnLoadAmiibo() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::System& system{Core::System::GetInstance()};
|
|
||||||
Service::SM::ServiceManager& sm = system.ServiceManager();
|
Service::SM::ServiceManager& sm = system.ServiceManager();
|
||||||
auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u");
|
auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u");
|
||||||
if (nfc == nullptr) {
|
if (nfc == nullptr) {
|
||||||
|
@ -2118,7 +2117,8 @@ void GMainWindow::OnToggleFilterBar() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnCreateGraphicsSurfaceViewer() {
|
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);
|
addDockWidget(Qt::RightDockWidgetArea, graphicsSurfaceViewerWidget);
|
||||||
// TODO: Maybe graphicsSurfaceViewerWidget->setFloating(true);
|
// TODO: Maybe graphicsSurfaceViewerWidget->setFloating(true);
|
||||||
graphicsSurfaceViewerWidget->show();
|
graphicsSurfaceViewerWidget->show();
|
||||||
|
|
|
@ -9,10 +9,8 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include "citra_qt/main.h"
|
#include "citra_qt/main.h"
|
||||||
#include "citra_qt/multiplayer/client_room.h"
|
|
||||||
#include "citra_qt/multiplayer/direct_connect.h"
|
#include "citra_qt/multiplayer/direct_connect.h"
|
||||||
#include "citra_qt/multiplayer/message.h"
|
#include "citra_qt/multiplayer/message.h"
|
||||||
#include "citra_qt/multiplayer/state.h"
|
|
||||||
#include "citra_qt/multiplayer/validation.h"
|
#include "citra_qt/multiplayer/validation.h"
|
||||||
#include "citra_qt/uisettings.h"
|
#include "citra_qt/uisettings.h"
|
||||||
#include "core/hle/service/cfg/cfg.h"
|
#include "core/hle/service/cfg/cfg.h"
|
||||||
|
@ -22,9 +20,9 @@
|
||||||
|
|
||||||
enum class ConnectionType : u8 { TraversalServer, IP };
|
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),
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
||||||
ui(std::make_unique<Ui::DirectConnect>()) {
|
ui(std::make_unique<Ui::DirectConnect>()), system{system_} {
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
@ -91,7 +89,7 @@ void DirectConnectWindow::Connect() {
|
||||||
if (auto room_member = Network::GetRoomMember().lock()) {
|
if (auto room_member = Network::GetRoomMember().lock()) {
|
||||||
auto port = UISettings::values.port.toUInt();
|
auto port = UISettings::values.port.toUInt();
|
||||||
room_member->Join(ui->nickname->text().toStdString(),
|
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,
|
ui->ip->text().toStdString().c_str(), port, 0,
|
||||||
Network::NoPreferredMac, ui->password->text().toStdString().c_str());
|
Network::NoPreferredMac, ui->password->text().toStdString().c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,15 @@ namespace Ui {
|
||||||
class DirectConnect;
|
class DirectConnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
class DirectConnectWindow : public QDialog {
|
class DirectConnectWindow : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DirectConnectWindow(QWidget* parent = nullptr);
|
explicit DirectConnectWindow(Core::System& system, QWidget* parent = nullptr);
|
||||||
~DirectConnectWindow();
|
~DirectConnectWindow();
|
||||||
|
|
||||||
void RetranslateUi();
|
void RetranslateUi();
|
||||||
|
@ -39,5 +43,6 @@ private:
|
||||||
|
|
||||||
QFutureWatcher<void>* watcher;
|
QFutureWatcher<void>* watcher;
|
||||||
std::unique_ptr<Ui::DirectConnect> ui;
|
std::unique_ptr<Ui::DirectConnect> ui;
|
||||||
|
Core::System& system;
|
||||||
Validation validation;
|
Validation validation;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include "citra_qt/game_list_p.h"
|
#include "citra_qt/game_list_p.h"
|
||||||
#include "citra_qt/main.h"
|
|
||||||
#include "citra_qt/multiplayer/host_room.h"
|
#include "citra_qt/multiplayer/host_room.h"
|
||||||
#include "citra_qt/multiplayer/message.h"
|
#include "citra_qt/multiplayer/message.h"
|
||||||
#include "citra_qt/multiplayer/state.h"
|
#include "citra_qt/multiplayer/state.h"
|
||||||
|
@ -27,10 +26,10 @@
|
||||||
#include "web_service/verify_user_jwt.h"
|
#include "web_service/verify_user_jwt.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
|
HostRoomWindow::HostRoomWindow(Core::System& system_, QWidget* parent, QStandardItemModel* list,
|
||||||
std::shared_ptr<Network::AnnounceMultiplayerSession> session)
|
std::shared_ptr<Network::AnnounceMultiplayerSession> session)
|
||||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
||||||
ui(std::make_unique<Ui::HostRoom>()), announce_multiplayer_session(session) {
|
ui(std::make_unique<Ui::HostRoom>()), system{system_}, announce_multiplayer_session(session) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// set up validation for all of the fields
|
// set up validation for all of the fields
|
||||||
|
@ -196,9 +195,8 @@ void HostRoomWindow::Host() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
member->Join(ui->username->text().toStdString(),
|
member->Join(ui->username->text().toStdString(), Service::CFG::GetConsoleIdHash(system),
|
||||||
Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), "127.0.0.1", port,
|
"127.0.0.1", port, 0, Network::NoPreferredMac, password, token);
|
||||||
0, Network::NoPreferredMac, password, token);
|
|
||||||
|
|
||||||
// Store settings
|
// Store settings
|
||||||
UISettings::values.room_nickname = ui->username->text();
|
UISettings::values.room_nickname = ui->username->text();
|
||||||
|
|
|
@ -9,14 +9,16 @@
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include "citra_qt/multiplayer/chat_room.h"
|
|
||||||
#include "citra_qt/multiplayer/validation.h"
|
#include "citra_qt/multiplayer/validation.h"
|
||||||
#include "network/network.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class HostRoom;
|
class HostRoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Network {
|
namespace Network {
|
||||||
class AnnounceMultiplayerSession;
|
class AnnounceMultiplayerSession;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +36,7 @@ class HostRoomWindow : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list,
|
explicit HostRoomWindow(Core::System& system, QWidget* parent, QStandardItemModel* list,
|
||||||
std::shared_ptr<Network::AnnounceMultiplayerSession> session);
|
std::shared_ptr<Network::AnnounceMultiplayerSession> session);
|
||||||
~HostRoomWindow();
|
~HostRoomWindow();
|
||||||
|
|
||||||
|
@ -50,6 +52,7 @@ private:
|
||||||
std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) const;
|
std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) const;
|
||||||
|
|
||||||
std::unique_ptr<Ui::HostRoom> ui;
|
std::unique_ptr<Ui::HostRoom> ui;
|
||||||
|
Core::System& system;
|
||||||
std::weak_ptr<Network::AnnounceMultiplayerSession> announce_multiplayer_session;
|
std::weak_ptr<Network::AnnounceMultiplayerSession> announce_multiplayer_session;
|
||||||
QStandardItemModel* game_list;
|
QStandardItemModel* game_list;
|
||||||
ComboBoxProxyModel* proxy;
|
ComboBoxProxyModel* proxy;
|
||||||
|
|
|
@ -7,11 +7,9 @@
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include "citra_qt/game_list_p.h"
|
#include "citra_qt/game_list_p.h"
|
||||||
#include "citra_qt/main.h"
|
#include "citra_qt/main.h"
|
||||||
#include "citra_qt/multiplayer/client_room.h"
|
|
||||||
#include "citra_qt/multiplayer/lobby.h"
|
#include "citra_qt/multiplayer/lobby.h"
|
||||||
#include "citra_qt/multiplayer/lobby_p.h"
|
#include "citra_qt/multiplayer/lobby_p.h"
|
||||||
#include "citra_qt/multiplayer/message.h"
|
#include "citra_qt/multiplayer/message.h"
|
||||||
#include "citra_qt/multiplayer/state.h"
|
|
||||||
#include "citra_qt/multiplayer/validation.h"
|
#include "citra_qt/multiplayer/validation.h"
|
||||||
#include "citra_qt/uisettings.h"
|
#include "citra_qt/uisettings.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
@ -23,10 +21,10 @@
|
||||||
#include "web_service/web_backend.h"
|
#include "web_service/web_backend.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
Lobby::Lobby(Core::System& system_, QWidget* parent, QStandardItemModel* list,
|
||||||
std::shared_ptr<Network::AnnounceMultiplayerSession> session)
|
std::shared_ptr<Network::AnnounceMultiplayerSession> session)
|
||||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
||||||
ui(std::make_unique<Ui::Lobby>()), announce_multiplayer_session(session) {
|
ui(std::make_unique<Ui::Lobby>()), system{system_}, announce_multiplayer_session(session) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// setup the watcher for background connections
|
// setup the watcher for background connections
|
||||||
|
@ -152,8 +150,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
|
||||||
const std::string verify_UID =
|
const std::string verify_UID =
|
||||||
proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString();
|
proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString();
|
||||||
|
|
||||||
// attempt to connect in a different thread
|
// Attempt to connect in a different thread
|
||||||
QFuture<void> f = QtConcurrent::run([nickname, ip, port, password, verify_UID] {
|
QFuture<void> f = QtConcurrent::run([this, nickname, ip, port, password, verify_UID] {
|
||||||
std::string token;
|
std::string token;
|
||||||
#ifdef ENABLE_WEB_SERVICE
|
#ifdef ENABLE_WEB_SERVICE
|
||||||
if (!NetSettings::values.citra_username.empty() &&
|
if (!NetSettings::values.citra_username.empty() &&
|
||||||
|
@ -170,8 +168,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (auto room_member = Network::GetRoomMember().lock()) {
|
if (auto room_member = Network::GetRoomMember().lock()) {
|
||||||
room_member->Join(nickname, Service::CFG::GetConsoleIdHash(Core::System::GetInstance()),
|
room_member->Join(nickname, Service::CFG::GetConsoleIdHash(system), ip.c_str(), port, 0,
|
||||||
ip.c_str(), port, 0, Network::NoPreferredMac, password, token);
|
Network::NoPreferredMac, password, token);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
watcher->setFuture(f);
|
watcher->setFuture(f);
|
||||||
|
|
|
@ -12,12 +12,16 @@
|
||||||
#include "citra_qt/multiplayer/validation.h"
|
#include "citra_qt/multiplayer/validation.h"
|
||||||
#include "common/announce_multiplayer_room.h"
|
#include "common/announce_multiplayer_room.h"
|
||||||
#include "network/announce_multiplayer_session.h"
|
#include "network/announce_multiplayer_session.h"
|
||||||
#include "network/network.h"
|
#include "network/room_member.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class Lobby;
|
class Lobby;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
class LobbyModel;
|
class LobbyModel;
|
||||||
class LobbyFilterProxyModel;
|
class LobbyFilterProxyModel;
|
||||||
|
|
||||||
|
@ -29,7 +33,7 @@ class Lobby : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Lobby(QWidget* parent, QStandardItemModel* list,
|
explicit Lobby(Core::System& system, QWidget* parent, QStandardItemModel* list,
|
||||||
std::shared_ptr<Network::AnnounceMultiplayerSession> session);
|
std::shared_ptr<Network::AnnounceMultiplayerSession> session);
|
||||||
~Lobby() override;
|
~Lobby() override;
|
||||||
|
|
||||||
|
@ -84,7 +88,9 @@ private:
|
||||||
*/
|
*/
|
||||||
QString PasswordPrompt();
|
QString PasswordPrompt();
|
||||||
|
|
||||||
|
private:
|
||||||
std::unique_ptr<Ui::Lobby> ui;
|
std::unique_ptr<Ui::Lobby> ui;
|
||||||
|
Core::System& system;
|
||||||
|
|
||||||
QStandardItemModel* model{};
|
QStandardItemModel* model{};
|
||||||
QStandardItemModel* game_list{};
|
QStandardItemModel* game_list{};
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
#include "citra_qt/util/clickable_label.h"
|
#include "citra_qt/util/clickable_label.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
|
||||||
MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model,
|
MultiplayerState::MultiplayerState(Core::System& system_, QWidget* parent,
|
||||||
QAction* leave_room, QAction* show_room)
|
QStandardItemModel* game_list_model, QAction* leave_room,
|
||||||
: QWidget(parent), game_list_model(game_list_model), leave_room(leave_room),
|
QAction* show_room)
|
||||||
|
: QWidget(parent), system{system_}, game_list_model(game_list_model), leave_room(leave_room),
|
||||||
show_room(show_room) {
|
show_room(show_room) {
|
||||||
if (auto member = Network::GetRoomMember().lock()) {
|
if (auto member = Network::GetRoomMember().lock()) {
|
||||||
// register the network structs to use in slots and signals
|
// register the network structs to use in slots and signals
|
||||||
|
@ -203,14 +204,14 @@ static void BringWidgetToFront(QWidget* widget) {
|
||||||
|
|
||||||
void MultiplayerState::OnViewLobby() {
|
void MultiplayerState::OnViewLobby() {
|
||||||
if (lobby == nullptr) {
|
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);
|
BringWidgetToFront(lobby);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplayerState::OnCreateRoom() {
|
void MultiplayerState::OnCreateRoom() {
|
||||||
if (host_room == nullptr) {
|
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);
|
BringWidgetToFront(host_room);
|
||||||
}
|
}
|
||||||
|
@ -274,7 +275,7 @@ void MultiplayerState::OnOpenNetworkRoom() {
|
||||||
|
|
||||||
void MultiplayerState::OnDirectConnectToRoom() {
|
void MultiplayerState::OnDirectConnectToRoom() {
|
||||||
if (direct_connect == nullptr) {
|
if (direct_connect == nullptr) {
|
||||||
direct_connect = new DirectConnectWindow(this);
|
direct_connect = new DirectConnectWindow(system, this);
|
||||||
}
|
}
|
||||||
BringWidgetToFront(direct_connect);
|
BringWidgetToFront(direct_connect);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,16 @@ class ClientRoomWindow;
|
||||||
class DirectConnectWindow;
|
class DirectConnectWindow;
|
||||||
class ClickableLabel;
|
class ClickableLabel;
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
class MultiplayerState : public QWidget {
|
class MultiplayerState : public QWidget {
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room,
|
explicit MultiplayerState(Core::System& system, QWidget* parent, QStandardItemModel* game_list,
|
||||||
QAction* show_room);
|
QAction* leave_room, QAction* show_room);
|
||||||
~MultiplayerState();
|
~MultiplayerState();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,6 +75,7 @@ signals:
|
||||||
void AnnounceFailed(const Common::WebResult&);
|
void AnnounceFailed(const Common::WebResult&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Core::System& system;
|
||||||
Lobby* lobby = nullptr;
|
Lobby* lobby = nullptr;
|
||||||
HostRoomWindow* host_room = nullptr;
|
HostRoomWindow* host_room = nullptr;
|
||||||
ClientRoomWindow* client_room = nullptr;
|
ClientRoomWindow* client_room = nullptr;
|
||||||
|
|
|
@ -130,11 +130,9 @@ bool UpdaterPrivate::StartUpdateCheck() {
|
||||||
main_process->setProgram(tool_info.absoluteFilePath());
|
main_process->setProgram(tool_info.absoluteFilePath());
|
||||||
main_process->setArguments({QStringLiteral("--checkupdates"), QStringLiteral("-v")});
|
main_process->setArguments({QStringLiteral("--checkupdates"), QStringLiteral("-v")});
|
||||||
|
|
||||||
connect(main_process,
|
connect(main_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||||
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this,
|
|
||||||
&UpdaterPrivate::UpdaterReady, Qt::QueuedConnection);
|
&UpdaterPrivate::UpdaterReady, Qt::QueuedConnection);
|
||||||
connect(main_process,
|
connect(main_process, qOverload<QProcess::ProcessError>(&QProcess::errorOccurred), this,
|
||||||
static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::errorOccurred), this,
|
|
||||||
&UpdaterPrivate::UpdaterError, Qt::QueuedConnection);
|
&UpdaterPrivate::UpdaterError, Qt::QueuedConnection);
|
||||||
|
|
||||||
main_process->start(QIODevice::ReadOnly);
|
main_process->start(QIODevice::ReadOnly);
|
||||||
|
@ -156,7 +154,7 @@ void UpdaterPrivate::StopUpdateCheck(int delay, bool async) {
|
||||||
QTimer* timer = new QTimer(this);
|
QTimer* timer = new QTimer(this);
|
||||||
timer->setSingleShot(true);
|
timer->setSingleShot(true);
|
||||||
|
|
||||||
connect(timer, &QTimer::timeout, [this, timer]() {
|
connect(timer, &QTimer::timeout, this, [this, timer]() {
|
||||||
StopUpdateCheck(0, false);
|
StopUpdateCheck(0, false);
|
||||||
timer->deleteLater();
|
timer->deleteLater();
|
||||||
});
|
});
|
||||||
|
|
|
@ -86,7 +86,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
|
||||||
if (thread && running_core) {
|
if (thread && running_core) {
|
||||||
running_core->SaveContext(thread->context);
|
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
|
// 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.
|
// 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) {
|
const Kernel::New3dsHwCapabilities& n3ds_hw_caps, u32 num_cores) {
|
||||||
LOG_DEBUG(HW_Memory, "initialized OK");
|
LOG_DEBUG(HW_Memory, "initialized OK");
|
||||||
|
|
||||||
memory = std::make_unique<Memory::MemorySystem>();
|
memory = std::make_unique<Memory::MemorySystem>(*this);
|
||||||
|
|
||||||
timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage.GetValue());
|
timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage.GetValue());
|
||||||
|
|
||||||
|
@ -632,9 +632,9 @@ void System::ApplySettings() {
|
||||||
|
|
||||||
if (IsPoweredOn()) {
|
if (IsPoweredOn()) {
|
||||||
CoreTiming().UpdateClockSpeed(Settings::values.cpu_clock_percentage.GetValue());
|
CoreTiming().UpdateClockSpeed(Settings::values.cpu_clock_percentage.GetValue());
|
||||||
Core::DSP().SetSink(Settings::values.output_type.GetValue(),
|
dsp_core->SetSink(Settings::values.output_type.GetValue(),
|
||||||
Settings::values.output_device.GetValue());
|
Settings::values.output_device.GetValue());
|
||||||
Core::DSP().EnableStretching(Settings::values.enable_audio_stretching.GetValue());
|
dsp_core->EnableStretching(Settings::values.enable_audio_stretching.GetValue());
|
||||||
|
|
||||||
auto hid = Service::HID::GetModule(*this);
|
auto hid = Service::HID::GetModule(*this);
|
||||||
if (hid) {
|
if (hid) {
|
||||||
|
|
|
@ -194,6 +194,10 @@ public:
|
||||||
return *cpu_cores[core_id];
|
return *cpu_cores[core_id];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] const ARM_Interface& GetCore(u32 core_id) const {
|
||||||
|
return *cpu_cores[core_id];
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] u32 GetNumCores() const {
|
[[nodiscard]] u32 GetNumCores() const {
|
||||||
return static_cast<u32>(cpu_cores.size());
|
return static_cast<u32>(cpu_cores.size());
|
||||||
}
|
}
|
||||||
|
@ -451,10 +455,6 @@ private:
|
||||||
return System::GetInstance().GetNumCores();
|
return System::GetInstance().GetNumCores();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline AudioCore::DspInterface& DSP() {
|
|
||||||
return System::GetInstance().DSP();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
||||||
BOOST_CLASS_VERSION(Core::System, 1)
|
BOOST_CLASS_VERSION(Core::System, 1)
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
#include "core/gdbstub/hio.h"
|
#include "core/gdbstub/hio.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/loader/loader.h"
|
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace GDBStub {
|
namespace GDBStub {
|
||||||
|
@ -1035,7 +1034,7 @@ static void RemoveBreakpoint() {
|
||||||
SendReply("OK");
|
SendReply("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandlePacket() {
|
void HandlePacket(Core::System& system) {
|
||||||
if (!IsConnected()) {
|
if (!IsConnected()) {
|
||||||
if (defer_start) {
|
if (defer_start) {
|
||||||
ToggleServer(true);
|
ToggleServer(true);
|
||||||
|
@ -1076,7 +1075,7 @@ void HandlePacket() {
|
||||||
Continue();
|
Continue();
|
||||||
return;
|
return;
|
||||||
case 'F':
|
case 'F':
|
||||||
HandleHioReply(command_buffer, command_length);
|
HandleHioReply(system, command_buffer, command_length);
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
ReadRegisters();
|
ReadRegisters();
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace GDBStub {
|
namespace GDBStub {
|
||||||
|
|
||||||
/// Breakpoint Method
|
/// Breakpoint Method
|
||||||
|
@ -70,7 +74,7 @@ void Break(bool is_memory_break = false);
|
||||||
bool IsMemoryBreak();
|
bool IsMemoryBreak();
|
||||||
|
|
||||||
/// Read and handle packet from gdb client.
|
/// 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.
|
* Get the nearest breakpoint of the specified type at the given address.
|
||||||
|
|
|
@ -54,7 +54,7 @@ static void SendErrorReply(int error_code, int retval = -1) {
|
||||||
SendReply(packet.data());
|
SendReply(packet.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHioRequest(const VAddr addr) {
|
void SetHioRequest(Core::System& system, const VAddr addr) {
|
||||||
if (!IsServerEnabled()) {
|
if (!IsServerEnabled()) {
|
||||||
LOG_WARNING(Debug_GDBStub, "HIO requested but GDB stub is not running");
|
LOG_WARNING(Debug_GDBStub, "HIO requested but GDB stub is not running");
|
||||||
return;
|
return;
|
||||||
|
@ -69,15 +69,15 @@ void SetHioRequest(const VAddr addr) {
|
||||||
LOG_INFO(Debug_GDBStub, "overwriting existing HIO request that was not sent yet");
|
LOG_INFO(Debug_GDBStub, "overwriting existing HIO request that was not sent yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = Core::System::GetInstance().Memory();
|
auto& memory = system.Memory();
|
||||||
const auto process = Core::System::GetInstance().Kernel().GetCurrentProcess();
|
const auto process = system.Kernel().GetCurrentProcess();
|
||||||
|
|
||||||
if (!memory.IsValidVirtualAddress(*process, addr)) {
|
if (!memory.IsValidVirtualAddress(*process, addr)) {
|
||||||
LOG_WARNING(Debug_GDBStub, "Invalid address for HIO request");
|
LOG_WARNING(Debug_GDBStub, "Invalid address for HIO request");
|
||||||
return;
|
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'}) {
|
if (current_hio_request.magic != std::array{'G', 'D', 'B', '\0'}) {
|
||||||
std::string_view bad_magic{
|
std::string_view bad_magic{
|
||||||
|
@ -105,10 +105,11 @@ void SetHioRequest(const VAddr addr) {
|
||||||
Break();
|
Break();
|
||||||
SetCpuHaltFlag(true);
|
SetCpuHaltFlag(true);
|
||||||
SetCpuStepFlag(false);
|
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()) {
|
if (!IsWaitingForHioReply()) {
|
||||||
LOG_WARNING(Debug_GDBStub, "Got HIO reply but never sent a request");
|
LOG_WARNING(Debug_GDBStub, "Got HIO reply but never sent a request");
|
||||||
return;
|
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.retval, current_hio_request.gdb_errno,
|
||||||
current_hio_request.ctrl_c);
|
current_hio_request.ctrl_c);
|
||||||
|
|
||||||
const auto process = Core::System::GetInstance().Kernel().GetCurrentProcess();
|
const auto process = system.Kernel().GetCurrentProcess();
|
||||||
auto& memory = Core::System::GetInstance().Memory();
|
auto& memory = system.Memory();
|
||||||
|
|
||||||
// should have been checked when we first initialized the request,
|
// should have been checked when we first initialized the request,
|
||||||
// but just double check again before we write to memory
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory.WriteBlock(*process, current_hio_request_addr, ¤t_hio_request,
|
memory.WriteBlock(current_hio_request_addr, ¤t_hio_request, sizeof(PackedGdbHioRequest));
|
||||||
sizeof(PackedGdbHioRequest));
|
|
||||||
|
|
||||||
current_hio_request = {};
|
current_hio_request = {};
|
||||||
current_hio_request_addr = 0;
|
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
|
// Restore state from before the request came in
|
||||||
SetCpuStepFlag(was_stepping);
|
SetCpuStepFlag(was_stepping);
|
||||||
SetCpuHaltFlag(was_halted);
|
SetCpuHaltFlag(was_halted);
|
||||||
Core::GetRunningCore().ClearInstructionCache();
|
system.GetRunningCore().ClearInstructionCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HandlePendingHioRequestPacket() {
|
bool HandlePendingHioRequestPacket() {
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace GDBStub {
|
namespace GDBStub {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +51,7 @@ static_assert(sizeof(PackedGdbHioRequest) == 152,
|
||||||
*
|
*
|
||||||
* @param address The memory address of the \ref PackedGdbHioRequest.
|
* @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.
|
* 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.
|
* 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
|
} // namespace GDBStub
|
||||||
|
|
|
@ -1128,7 +1128,7 @@ void SVC::OutputDebugString(VAddr address, s32 len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
GDBStub::SetHioRequest(address);
|
GDBStub::SetHioRequest(system, address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1953,12 +1953,12 @@ ResultCode SVC::GetProcessList(s32* process_count, VAddr out_process_array,
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode SVC::InvalidateInstructionCacheRange(u32 addr, u32 size) {
|
ResultCode SVC::InvalidateInstructionCacheRange(u32 addr, u32 size) {
|
||||||
Core::GetRunningCore().InvalidateCacheRange(addr, size);
|
system.GetRunningCore().InvalidateCacheRange(addr, size);
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode SVC::InvalidateEntireInstructionCache() {
|
ResultCode SVC::InvalidateEntireInstructionCache() {
|
||||||
Core::GetRunningCore().ClearInstructionCache();
|
system.GetRunningCore().ClearInstructionCache();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/global.h"
|
#include "core/global.h"
|
||||||
#include "core/hle/kernel/memory.h"
|
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/lock.h"
|
|
||||||
#include "core/hle/service/plgldr/plgldr.h"
|
#include "core/hle/service/plgldr/plgldr.h"
|
||||||
#include "core/hw/hw.h"
|
#include "core/hw/hw.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
@ -89,12 +87,13 @@ private:
|
||||||
|
|
||||||
class MemorySystem::Impl {
|
class MemorySystem::Impl {
|
||||||
public:
|
public:
|
||||||
// Visual Studio would try to allocate these on compile time if they are std::array, which would
|
// Visual Studio would try to allocate these on compile time
|
||||||
// exceed the memory limit.
|
// if they are std::array which would exceed the memory limit.
|
||||||
std::unique_ptr<u8[]> fcram = std::make_unique<u8[]>(Memory::FCRAM_N3DS_SIZE);
|
std::unique_ptr<u8[]> fcram = std::make_unique<u8[]>(Memory::FCRAM_N3DS_SIZE);
|
||||||
std::unique_ptr<u8[]> vram = std::make_unique<u8[]>(Memory::VRAM_SIZE);
|
std::unique_ptr<u8[]> vram = std::make_unique<u8[]>(Memory::VRAM_SIZE);
|
||||||
std::unique_ptr<u8[]> n3ds_extra_ram = std::make_unique<u8[]>(Memory::N3DS_EXTRA_RAM_SIZE);
|
std::unique_ptr<u8[]> n3ds_extra_ram = std::make_unique<u8[]>(Memory::N3DS_EXTRA_RAM_SIZE);
|
||||||
|
|
||||||
|
Core::System& system;
|
||||||
std::shared_ptr<PageTable> current_page_table = nullptr;
|
std::shared_ptr<PageTable> current_page_table = nullptr;
|
||||||
RasterizerCacheMarker cache_marker;
|
RasterizerCacheMarker cache_marker;
|
||||||
std::vector<std::shared_ptr<PageTable>> page_table_list;
|
std::vector<std::shared_ptr<PageTable>> page_table_list;
|
||||||
|
@ -106,7 +105,7 @@ public:
|
||||||
std::shared_ptr<BackingMem> n3ds_extra_ram_mem;
|
std::shared_ptr<BackingMem> n3ds_extra_ram_mem;
|
||||||
std::shared_ptr<BackingMem> dsp_mem;
|
std::shared_ptr<BackingMem> dsp_mem;
|
||||||
|
|
||||||
Impl();
|
Impl(Core::System& system_);
|
||||||
|
|
||||||
const u8* GetPtr(Region r) const {
|
const u8* GetPtr(Region r) const {
|
||||||
switch (r) {
|
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`.
|
* This function should only be called for virtual addreses with attribute `PageType::Special`.
|
||||||
*/
|
*/
|
||||||
|
@ -187,7 +190,7 @@ public:
|
||||||
HW_Memory,
|
HW_Memory,
|
||||||
"unmapped ReadBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
"unmapped ReadBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
||||||
"0x{:08X}",
|
"0x{:08X}",
|
||||||
current_vaddr, src_addr, size, Core::GetRunningCore().GetPC());
|
current_vaddr, src_addr, size, GetPC());
|
||||||
std::memset(dest_buffer, 0, copy_amount);
|
std::memset(dest_buffer, 0, copy_amount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +245,7 @@ public:
|
||||||
HW_Memory,
|
HW_Memory,
|
||||||
"unmapped WriteBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
"unmapped WriteBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
||||||
"0x{:08X}",
|
"0x{:08X}",
|
||||||
current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC());
|
current_vaddr, dest_addr, size, GetPC());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PageType::Memory: {
|
case PageType::Memory: {
|
||||||
|
@ -345,13 +348,13 @@ private:
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
||||||
MemorySystem::Impl::Impl()
|
MemorySystem::Impl::Impl(Core::System& system_)
|
||||||
: fcram_mem(std::make_shared<BackingMemImpl<Region::FCRAM>>(*this)),
|
: system{system_}, fcram_mem(std::make_shared<BackingMemImpl<Region::FCRAM>>(*this)),
|
||||||
vram_mem(std::make_shared<BackingMemImpl<Region::VRAM>>(*this)),
|
vram_mem(std::make_shared<BackingMemImpl<Region::VRAM>>(*this)),
|
||||||
n3ds_extra_ram_mem(std::make_shared<BackingMemImpl<Region::N3DS>>(*this)),
|
n3ds_extra_ram_mem(std::make_shared<BackingMemImpl<Region::N3DS>>(*this)),
|
||||||
dsp_mem(std::make_shared<BackingMemImpl<Region::DSP>>(*this)) {}
|
dsp_mem(std::make_shared<BackingMemImpl<Region::DSP>>(*this)) {}
|
||||||
|
|
||||||
MemorySystem::MemorySystem() : impl(std::make_unique<Impl>()) {}
|
MemorySystem::MemorySystem(Core::System& system) : impl(std::make_unique<Impl>(system)) {}
|
||||||
MemorySystem::~MemorySystem() = default;
|
MemorySystem::~MemorySystem() = default;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
|
@ -467,7 +470,7 @@ T MemorySystem::Read(const VAddr vaddr) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PageType::Unmapped:
|
case PageType::Unmapped:
|
||||||
LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X} at PC 0x{:08X}", sizeof(T) * 8, vaddr,
|
LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X} at PC 0x{:08X}", sizeof(T) * 8, vaddr,
|
||||||
Core::GetRunningCore().GetPC());
|
impl->GetPC());
|
||||||
return 0;
|
return 0;
|
||||||
case PageType::Memory:
|
case PageType::Memory:
|
||||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr);
|
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) {
|
switch (type) {
|
||||||
case PageType::Unmapped:
|
case PageType::Unmapped:
|
||||||
LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}",
|
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;
|
return;
|
||||||
case PageType::Memory:
|
case PageType::Memory:
|
||||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr);
|
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) {
|
switch (type) {
|
||||||
case PageType::Unmapped:
|
case PageType::Unmapped:
|
||||||
LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}",
|
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<u32>(data), vaddr, impl->GetPC());
|
||||||
return true;
|
return true;
|
||||||
case PageType::Memory:
|
case PageType::Memory:
|
||||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr);
|
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr);
|
||||||
|
@ -606,8 +609,7 @@ u8* MemorySystem::GetPointer(const VAddr vaddr) {
|
||||||
return GetPointerForRasterizerCache(vaddr);
|
return GetPointerForRasterizerCache(vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x} at PC 0x{:08X}", vaddr,
|
LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x} at PC 0x{:08X}", vaddr, impl->GetPC());
|
||||||
Core::GetRunningCore().GetPC());
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,7 +665,7 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const {
|
||||||
|
|
||||||
if (area == memory_areas.end()) {
|
if (area == memory_areas.end()) {
|
||||||
LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#08X} at PC {:#08X}", address,
|
LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#08X} at PC {:#08X}", address,
|
||||||
Core::GetRunningCore().GetPC());
|
impl->GetPC());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,8 +695,7 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const {
|
||||||
return {target_mem, offset_into_region};
|
return {target_mem, offset_into_region};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a rasterizer-accessible PAddr, gets a list of all possible VAddr
|
std::vector<VAddr> MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr addr) {
|
||||||
static std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr) {
|
|
||||||
if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
|
if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
|
||||||
return {addr - VRAM_PADDR + VRAM_VADDR};
|
return {addr - VRAM_PADDR + VRAM_VADDR};
|
||||||
}
|
}
|
||||||
|
@ -714,7 +715,7 @@ static std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr) {
|
||||||
// parts of the texture.
|
// parts of the texture.
|
||||||
LOG_ERROR(HW_Memory,
|
LOG_ERROR(HW_Memory,
|
||||||
"Trying to use invalid physical address for rasterizer: {:08X} at PC 0x{:08X}", addr,
|
"Trying to use invalid physical address for rasterizer: {:08X} at PC 0x{:08X}", addr,
|
||||||
Core::GetRunningCore().GetPC());
|
impl->GetPC());
|
||||||
return {};
|
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 (unsigned i = 0; i < num_pages; ++i, paddr += CITRA_PAGE_SIZE) {
|
||||||
for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) {
|
for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) {
|
||||||
impl->cache_marker.Mark(vaddr, cached);
|
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];
|
PageType& page_type = page_table->attributes[vaddr >> CITRA_PAGE_BITS];
|
||||||
|
|
||||||
if (cached) {
|
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) {
|
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<false>(process, src_addr, dest_buffer, size);
|
return impl->ReadBlockImpl<false>(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,
|
void MemorySystem::WriteBlock(const VAddr dest_addr, const void* src_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess();
|
auto& process = *impl->system.Kernel().GetCurrentProcess();
|
||||||
return impl->WriteBlockImpl<false>(process, dest_addr, src_buffer, size);
|
return impl->WriteBlockImpl<false>(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,
|
LOG_ERROR(HW_Memory,
|
||||||
"unmapped ZeroBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
"unmapped ZeroBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
||||||
"0x{:08X}",
|
"0x{:08X}",
|
||||||
current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC());
|
current_vaddr, dest_addr, size, impl->GetPC());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PageType::Memory: {
|
case PageType::Memory: {
|
||||||
|
@ -989,7 +990,7 @@ void MemorySystem::CopyBlock(const Kernel::Process& dest_process,
|
||||||
LOG_ERROR(HW_Memory,
|
LOG_ERROR(HW_Memory,
|
||||||
"unmapped CopyBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
"unmapped CopyBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
||||||
"0x{:08X}",
|
"0x{:08X}",
|
||||||
current_vaddr, src_addr, size, Core::GetRunningCore().GetPC());
|
current_vaddr, src_addr, size, impl->GetPC());
|
||||||
ZeroBlock(dest_process, dest_addr, copy_amount);
|
ZeroBlock(dest_process, dest_addr, copy_amount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,10 @@ namespace Kernel {
|
||||||
class Process;
|
class Process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace AudioCore {
|
namespace AudioCore {
|
||||||
class DspInterface;
|
class DspInterface;
|
||||||
}
|
}
|
||||||
|
@ -287,7 +291,7 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode);
|
||||||
|
|
||||||
class MemorySystem {
|
class MemorySystem {
|
||||||
public:
|
public:
|
||||||
MemorySystem();
|
explicit MemorySystem(Core::System& system);
|
||||||
~MemorySystem();
|
~MemorySystem();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -575,6 +579,9 @@ public:
|
||||||
*/
|
*/
|
||||||
void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached);
|
void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached);
|
||||||
|
|
||||||
|
/// For a rasterizer-accessible PAddr, gets a list of all possible VAddr
|
||||||
|
std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr);
|
||||||
|
|
||||||
/// Gets a pointer to the memory region beginning at the specified physical address.
|
/// Gets a pointer to the memory region beginning at the specified physical address.
|
||||||
u8* GetPhysicalPointer(PAddr address) const;
|
u8* GetPhysicalPointer(PAddr address) const;
|
||||||
|
|
||||||
|
@ -627,6 +634,7 @@ private:
|
||||||
|
|
||||||
void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type);
|
void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type);
|
||||||
|
|
||||||
|
private:
|
||||||
class Impl;
|
class Impl;
|
||||||
std::unique_ptr<Impl> impl;
|
std::unique_ptr<Impl> impl;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
#include "audio_fixures.h"
|
#include "audio_fixures.h"
|
||||||
|
|
||||||
TEST_CASE("DSP HLE Audio Decoder", "[audio_core]") {
|
TEST_CASE("DSP HLE Audio Decoder", "[audio_core]") {
|
||||||
Memory::MemorySystem memory;
|
Core::System system;
|
||||||
|
Memory::MemorySystem memory{system};
|
||||||
SECTION("decoder should produce correct samples") {
|
SECTION("decoder should produce correct samples") {
|
||||||
auto decoder =
|
auto decoder =
|
||||||
#ifdef HAVE_MF
|
#ifdef HAVE_MF
|
||||||
|
|
|
@ -8,14 +8,16 @@
|
||||||
#include "audio_core/lle/lle.h"
|
#include "audio_core/lle/lle.h"
|
||||||
#include "common/common_paths.h"
|
#include "common/common_paths.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
TEST_CASE("DSP LLE vs HLE", "[audio_core][hle]") {
|
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);
|
Core::Timing hle_core_timing(1, 100);
|
||||||
|
|
||||||
Memory::MemorySystem lle_memory;
|
Memory::MemorySystem lle_memory{system};
|
||||||
Core::Timing lle_core_timing(1, 100);
|
Core::Timing lle_core_timing(1, 100);
|
||||||
|
|
||||||
AudioCore::DspHle hle(hle_memory, hle_core_timing);
|
AudioCore::DspHle hle(hle_memory, hle_core_timing);
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
#include "audio_core/lle/lle.h"
|
#include "audio_core/lle/lle.h"
|
||||||
#include "common/common_paths.h"
|
#include "common/common_paths.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
TEST_CASE("DSP LLE Sanity", "[audio_core][lle]") {
|
TEST_CASE("DSP LLE Sanity", "[audio_core][lle]") {
|
||||||
Memory::MemorySystem memory;
|
Core::System system;
|
||||||
|
Memory::MemorySystem memory{system};
|
||||||
Core::Timing core_timing(1, 100);
|
Core::Timing core_timing(1, 100);
|
||||||
|
|
||||||
AudioCore::DspLle lle(memory, core_timing, true);
|
AudioCore::DspLle lle(memory, core_timing, true);
|
||||||
|
|
|
@ -16,7 +16,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
|
||||||
: mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) {
|
: mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) {
|
||||||
|
|
||||||
timing = std::make_unique<Core::Timing>(1, 100);
|
timing = std::make_unique<Core::Timing>(1, 100);
|
||||||
memory = std::make_unique<Memory::MemorySystem>();
|
system = std::make_unique<Core::System>();
|
||||||
|
memory = std::make_unique<Memory::MemorySystem>(*system);
|
||||||
kernel = std::make_unique<Kernel::KernelSystem>(
|
kernel = std::make_unique<Kernel::KernelSystem>(
|
||||||
*memory, *timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
*memory, *timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
||||||
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
||||||
|
|
|
@ -85,6 +85,7 @@ private:
|
||||||
std::vector<WriteRecord> write_records;
|
std::vector<WriteRecord> write_records;
|
||||||
|
|
||||||
std::unique_ptr<Core::Timing> timing;
|
std::unique_ptr<Core::Timing> timing;
|
||||||
|
std::unique_ptr<Core::System> system;
|
||||||
std::unique_ptr<Memory::MemorySystem> memory;
|
std::unique_ptr<Memory::MemorySystem> memory;
|
||||||
std::unique_ptr<Kernel::KernelSystem> kernel;
|
std::unique_ptr<Kernel::KernelSystem> kernel;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,12 +3,10 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
#include "common/archives.h"
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/ipc.h"
|
#include "core/hle/ipc.h"
|
||||||
#include "core/hle/kernel/client_port.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/event.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/hle_ipc.h"
|
#include "core/hle/kernel/hle_ipc.h"
|
||||||
|
@ -23,7 +21,8 @@ static std::shared_ptr<Object> MakeObject(Kernel::KernelSystem& kernel) {
|
||||||
|
|
||||||
TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") {
|
TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") {
|
||||||
Core::Timing timing(1, 100);
|
Core::Timing timing(1, 100);
|
||||||
Memory::MemorySystem memory;
|
Core::System system;
|
||||||
|
Memory::MemorySystem memory{system};
|
||||||
Kernel::KernelSystem kernel(
|
Kernel::KernelSystem kernel(
|
||||||
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
||||||
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
||||||
|
@ -247,7 +246,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
||||||
|
|
||||||
TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
||||||
Core::Timing timing(1, 100);
|
Core::Timing timing(1, 100);
|
||||||
Memory::MemorySystem memory;
|
Core::System system;
|
||||||
|
Memory::MemorySystem memory{system};
|
||||||
Kernel::KernelSystem kernel(
|
Kernel::KernelSystem kernel(
|
||||||
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
||||||
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
||||||
|
|
|
@ -3,13 +3,15 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
TEST_CASE("memory.IsValidVirtualAddress", "[core][memory]") {
|
TEST_CASE("memory.IsValidVirtualAddress", "[core][memory]") {
|
||||||
Core::Timing timing(1, 100);
|
Core::Timing timing(1, 100);
|
||||||
Memory::MemorySystem memory;
|
Core::System system;
|
||||||
|
Memory::MemorySystem memory{system};
|
||||||
Kernel::KernelSystem kernel(
|
Kernel::KernelSystem kernel(
|
||||||
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
||||||
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
#include "core/hle/kernel/memory.h"
|
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/vm_manager.h"
|
#include "core/hle/kernel/vm_manager.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
@ -15,7 +15,8 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
|
||||||
auto mem = std::make_shared<BufferMem>(Memory::CITRA_PAGE_SIZE);
|
auto mem = std::make_shared<BufferMem>(Memory::CITRA_PAGE_SIZE);
|
||||||
MemoryRef block{mem};
|
MemoryRef block{mem};
|
||||||
Core::Timing timing(1, 100);
|
Core::Timing timing(1, 100);
|
||||||
Memory::MemorySystem memory;
|
Core::System system;
|
||||||
|
Memory::MemorySystem memory{system};
|
||||||
Kernel::KernelSystem kernel(
|
Kernel::KernelSystem kernel(
|
||||||
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
|
||||||
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
|
||||||
|
|
|
@ -503,13 +503,18 @@ SurfaceId RasterizerCache<T>::GetTextureSurface(const Pica::Texture::TextureInfo
|
||||||
const u32 min_width = info.width >> max_level;
|
const u32 min_width = info.width >> max_level;
|
||||||
const u32 min_height = info.height >> max_level;
|
const u32 min_height = info.height >> max_level;
|
||||||
if (min_width % 8 != 0 || min_height % 8 != 0) {
|
if (min_width % 8 != 0 || min_height % 8 != 0) {
|
||||||
if (min_width % 4 == 0 && min_height % 4 == 0) {
|
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);
|
const auto [src_surface_id, rect] = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
|
||||||
Surface& src_surface = slot_surfaces[src_surface_id];
|
Surface& src_surface = slot_surfaces[src_surface_id];
|
||||||
|
|
||||||
params.res_scale = src_surface.res_scale;
|
params.res_scale = src_surface.res_scale;
|
||||||
SurfaceId tmp_surface_id = CreateSurface(params);
|
SurfaceId tmp_surface_id = CreateSurface(params);
|
||||||
Surface& tmp_surface = slot_surfaces[tmp_surface_id];
|
Surface& tmp_surface = slot_surfaces[tmp_surface_id];
|
||||||
|
sentenced.emplace_back(tmp_surface_id, frame_tick);
|
||||||
|
|
||||||
const TextureBlit blit = {
|
const TextureBlit blit = {
|
||||||
.src_level = src_surface.LevelOf(params.addr),
|
.src_level = src_surface.LevelOf(params.addr),
|
||||||
|
@ -520,10 +525,6 @@ SurfaceId RasterizerCache<T>::GetTextureSurface(const Pica::Texture::TextureInfo
|
||||||
runtime.BlitTextures(src_surface, tmp_surface, blit);
|
runtime.BlitTextures(src_surface, tmp_surface, blit);
|
||||||
return tmp_surface_id;
|
return tmp_surface_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) is not multiple of 4", min_width, min_height);
|
|
||||||
return NULL_SURFACE_ID;
|
|
||||||
}
|
|
||||||
if (info.width != (min_width << max_level) || info.height != (min_height << max_level)) {
|
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 ({})",
|
LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) does not support required mipmap level ({})",
|
||||||
params.width, params.height, max_level);
|
params.width, params.height, max_level);
|
||||||
|
@ -1054,8 +1055,9 @@ bool RasterizerCache<T>::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv
|
||||||
ASSERT_MSG(True(surface.flags & SurfaceFlagBits::Custom),
|
ASSERT_MSG(True(surface.flags & SurfaceFlagBits::Custom),
|
||||||
"Surface is not suitable for custom upload, aborting!");
|
"Surface is not suitable for custom upload, aborting!");
|
||||||
if (!surface.IsCustom()) {
|
if (!surface.IsCustom()) {
|
||||||
|
const SurfaceBase old_surface{surface};
|
||||||
const SurfaceId old_id =
|
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);
|
sentenced.emplace_back(old_id, frame_tick);
|
||||||
}
|
}
|
||||||
surface.UploadCustom(material, level);
|
surface.UploadCustom(material, level);
|
||||||
|
|
|
@ -105,7 +105,7 @@ SurfaceInterval SurfaceBase::GetCopyableInterval(const SurfaceParams& params) co
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Extent SurfaceBase::RealExtent(bool scaled) {
|
Extent SurfaceBase::RealExtent(bool scaled) const {
|
||||||
const bool is_custom = IsCustom();
|
const bool is_custom = IsCustom();
|
||||||
u32 real_width = width;
|
u32 real_width = width;
|
||||||
u32 real_height = height;
|
u32 real_height = height;
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
ClearValue MakeClearValue(PAddr copy_addr, PixelFormat dst_format);
|
ClearValue MakeClearValue(PAddr copy_addr, PixelFormat dst_format);
|
||||||
|
|
||||||
/// Returns the internal surface extent.
|
/// 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.
|
/// Returns true if the surface contains a custom material with a normal map.
|
||||||
bool HasNormalMap() const noexcept;
|
bool HasNormalMap() const noexcept;
|
||||||
|
|
|
@ -73,12 +73,12 @@ public:
|
||||||
return height * res_scale;
|
return height * res_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Common::Rectangle<u32> GetRect() const noexcept {
|
[[nodiscard]] Common::Rectangle<u32> GetRect(u32 level = 0) const noexcept {
|
||||||
return {0, height, width, 0};
|
return {0, height >> level, width >> level, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Common::Rectangle<u32> GetScaledRect() const noexcept {
|
[[nodiscard]] Common::Rectangle<u32> GetScaledRect(u32 level = 0) const noexcept {
|
||||||
return {0, GetScaledHeight(), GetScaledWidth(), 0};
|
return {0, GetScaledHeight() >> level, GetScaledWidth() >> level, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] u32 PixelsInBytes(u32 size) const noexcept {
|
[[nodiscard]] u32 PixelsInBytes(u32 size) const noexcept {
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hw/gpu.h"
|
#include "core/hw/gpu.h"
|
||||||
|
|
||||||
namespace OpenGL {
|
|
||||||
struct ScreenInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Pica::Shader {
|
namespace Pica::Shader {
|
||||||
struct OutputVertex;
|
struct OutputVertex;
|
||||||
} // namespace Pica::Shader
|
} // namespace Pica::Shader
|
||||||
|
@ -76,14 +72,6 @@ public:
|
||||||
return false;
|
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
|
/// Attempt to draw using hardware shaders
|
||||||
virtual bool AccelerateDrawBatch([[maybe_unused]] bool is_indexed) {
|
virtual bool AccelerateDrawBatch([[maybe_unused]] bool is_indexed) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
virtual ~RendererBase();
|
virtual ~RendererBase();
|
||||||
|
|
||||||
/// Returns the rasterizer owned by the renderer
|
/// 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
|
/// Finalize rendering the guest frame and draw into the presentation texture
|
||||||
virtual void SwapBuffers() = 0;
|
virtual void SwapBuffers() = 0;
|
||||||
|
@ -72,9 +72,6 @@ public:
|
||||||
/// Ends the current frame
|
/// Ends the current frame
|
||||||
void EndFrame();
|
void EndFrame();
|
||||||
|
|
||||||
// Getter/setter functions:
|
|
||||||
// ------------------------
|
|
||||||
|
|
||||||
f32 GetCurrentFPS() const {
|
f32 GetCurrentFPS() const {
|
||||||
return current_fps;
|
return current_fps;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
#include "video_core/regs_rasterizer.h"
|
#include "video_core/regs_rasterizer.h"
|
||||||
#include "video_core/renderer_opengl/gl_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_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/pica_to_gl.h"
|
||||||
#include "video_core/renderer_opengl/renderer_opengl.h"
|
#include "video_core/renderer_opengl/renderer_opengl.h"
|
||||||
|
#include "video_core/texture/texture_decode.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
@ -76,8 +76,9 @@ GLenum MakeAttributeType(Pica::PipelineRegs::VertexAttributeFormat format) {
|
||||||
RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
|
RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
|
||||||
VideoCore::CustomTexManager& custom_tex_manager,
|
VideoCore::CustomTexManager& custom_tex_manager,
|
||||||
VideoCore::RendererBase& renderer, Driver& driver_)
|
VideoCore::RendererBase& renderer, Driver& driver_)
|
||||||
: VideoCore::RasterizerAccelerated{memory}, driver{driver_}, runtime{driver, renderer},
|
: VideoCore::RasterizerAccelerated{memory}, driver{driver_},
|
||||||
res_cache{memory, custom_tex_manager, runtime, regs, renderer},
|
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,
|
texture_buffer_size{TextureBufferSize()}, vertex_buffer{driver, GL_ARRAY_BUFFER,
|
||||||
VERTEX_BUFFER_SIZE},
|
VERTEX_BUFFER_SIZE},
|
||||||
uniform_buffer{driver, GL_UNIFORM_BUFFER, UNIFORM_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
|
// Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
|
||||||
state.clip_distance[0] = true;
|
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
|
// Generate VAO
|
||||||
sw_vao.Create();
|
sw_vao.Create();
|
||||||
hw_vao.Create();
|
hw_vao.Create();
|
||||||
|
@ -142,9 +135,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
|
||||||
(GLvoid*)offsetof(HardwareVertex, view));
|
(GLvoid*)offsetof(HardwareVertex, view));
|
||||||
glEnableVertexAttribArray(ATTRIBUTE_VIEW);
|
glEnableVertexAttribArray(ATTRIBUTE_VIEW);
|
||||||
|
|
||||||
// Create render framebuffer
|
|
||||||
framebuffer.Create();
|
|
||||||
|
|
||||||
// Allocate and bind texture buffer lut textures
|
// Allocate and bind texture buffer lut textures
|
||||||
texture_buffer_lut_lf.Create();
|
texture_buffer_lut_lf.Create();
|
||||||
texture_buffer_lut_rg.Create();
|
texture_buffer_lut_rg.Create();
|
||||||
|
@ -165,9 +155,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
|
||||||
state.Apply();
|
state.Apply();
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle());
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle());
|
||||||
|
|
||||||
shader_program_manager =
|
|
||||||
std::make_unique<ShaderProgramManager>(renderer.GetRenderWindow(), driver, !GLES);
|
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
SyncEntireState();
|
SyncEntireState();
|
||||||
|
@ -181,7 +168,7 @@ void RasterizerOpenGL::TickFrame() {
|
||||||
|
|
||||||
void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
|
void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||||
const VideoCore::DiskResourceLoadCallback& callback) {
|
const VideoCore::DiskResourceLoadCallback& callback) {
|
||||||
shader_program_manager->LoadDiskCache(stop_loading, callback);
|
shader_manager.LoadDiskCache(stop_loading, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncFixedState() {
|
void RasterizerOpenGL::SyncFixedState() {
|
||||||
|
@ -277,7 +264,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset,
|
||||||
|
|
||||||
bool RasterizerOpenGL::SetupVertexShader() {
|
bool RasterizerOpenGL::SetupVertexShader() {
|
||||||
MICROPROFILE_SCOPE(OpenGL_VS);
|
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() {
|
bool RasterizerOpenGL::SetupGeometryShader() {
|
||||||
|
@ -288,7 +275,7 @@ bool RasterizerOpenGL::SetupGeometryShader() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_program_manager->UseFixedGeometryShader(regs);
|
shader_manager.UseFixedGeometryShader(regs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,11 +289,13 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetupVertexShader())
|
if (!SetupVertexShader()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SetupGeometryShader())
|
if (!SetupGeometryShader()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return Draw(true, is_indexed);
|
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);
|
SetupVertexArray(buffer_ptr, buffer_offset, vs_input_index_min, vs_input_index_max);
|
||||||
vertex_buffer.Unmap(vs_input_size);
|
vertex_buffer.Unmap(vs_input_size);
|
||||||
|
|
||||||
shader_program_manager->ApplyTo(state);
|
shader_manager.ApplyTo(state);
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
|
@ -341,8 +330,8 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8* index_data = VideoCore::g_memory->GetPhysicalPointer(
|
const u8* index_data =
|
||||||
regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() +
|
memory.GetPhysicalPointer(regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() +
|
||||||
regs.pipeline.index_array.offset);
|
regs.pipeline.index_array.offset);
|
||||||
std::tie(buffer_ptr, buffer_offset, std::ignore) = index_buffer.Map(index_buffer_size, 4);
|
std::tie(buffer_ptr, buffer_offset, std::ignore) = index_buffer.Map(index_buffer_size, 4);
|
||||||
std::memcpy(buffer_ptr, index_data, index_buffer_size);
|
std::memcpy(buffer_ptr, index_data, index_buffer_size);
|
||||||
|
@ -434,7 +423,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
|
||||||
|
|
||||||
// Sync and bind the shader
|
// Sync and bind the shader
|
||||||
if (shader_dirty) {
|
if (shader_dirty) {
|
||||||
shader_program_manager->UseFragmentShader(regs, use_custom_normal);
|
shader_manager.UseFragmentShader(regs, use_custom_normal);
|
||||||
shader_dirty = false;
|
shader_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,9 +441,9 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
|
||||||
} else {
|
} else {
|
||||||
state.draw.vertex_array = sw_vao.handle;
|
state.draw.vertex_array = sw_vao.handle;
|
||||||
state.draw.vertex_buffer = vertex_buffer.GetHandle();
|
state.draw.vertex_buffer = vertex_buffer.GetHandle();
|
||||||
shader_program_manager->UseTrivialVertexShader();
|
shader_manager.UseTrivialVertexShader();
|
||||||
shader_program_manager->UseTrivialGeometryShader();
|
shader_manager.UseTrivialGeometryShader();
|
||||||
shader_program_manager->ApplyTo(state);
|
shader_manager.ApplyTo(state);
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
std::size_t max_vertices = 3 * (VERTEX_BUFFER_SIZE / (3 * sizeof(HardwareVertex)));
|
std::size_t max_vertices = 3 * (VERTEX_BUFFER_SIZE / (3 * sizeof(HardwareVertex)));
|
||||||
|
@ -820,7 +809,7 @@ void RasterizerOpenGL::SyncBlendColor() {
|
||||||
void RasterizerOpenGL::SyncLogicOp() {
|
void RasterizerOpenGL::SyncLogicOp() {
|
||||||
state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op);
|
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.alphablend_enable) {
|
||||||
if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) {
|
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
|
// Color output is disabled by logic operation. We use color write mask to skip
|
||||||
|
@ -832,7 +821,7 @@ void RasterizerOpenGL::SyncLogicOp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncColorWriteMask() {
|
void RasterizerOpenGL::SyncColorWriteMask() {
|
||||||
if (GLES) {
|
if (driver.IsOpenGLES()) {
|
||||||
if (!regs.framebuffer.output_merger.alphablend_enable) {
|
if (!regs.framebuffer.output_merger.alphablend_enable) {
|
||||||
if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) {
|
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
|
// 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
|
return (regs.framebuffer.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE
|
||||||
: GL_FALSE;
|
: 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 =
|
state.color_mask.green_enabled =
|
||||||
IsColorWriteEnabled(regs.framebuffer.output_merger.green_enable);
|
is_color_write_enabled(regs.framebuffer.output_merger.green_enable);
|
||||||
state.color_mask.blue_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.blue_enable);
|
state.color_mask.blue_enabled =
|
||||||
|
is_color_write_enabled(regs.framebuffer.output_merger.blue_enable);
|
||||||
state.color_mask.alpha_enabled =
|
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() {
|
void RasterizerOpenGL::SyncStencilWriteMask() {
|
||||||
|
@ -903,12 +894,10 @@ void RasterizerOpenGL::SyncAndUploadLUTsLF() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* buffer;
|
|
||||||
GLintptr offset;
|
|
||||||
bool invalidate;
|
|
||||||
std::size_t bytes_used = 0;
|
std::size_t bytes_used = 0;
|
||||||
glBindBuffer(GL_TEXTURE_BUFFER, texture_lf_buffer.GetHandle());
|
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
|
// Sync the lighting luts
|
||||||
if (uniform_block_data.lighting_lut_dirty_any || invalidate) {
|
if (uniform_block_data.lighting_lut_dirty_any || invalidate) {
|
||||||
|
@ -973,16 +962,14 @@ void RasterizerOpenGL::SyncAndUploadLUTs() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* buffer;
|
|
||||||
GLintptr offset;
|
|
||||||
bool invalidate;
|
|
||||||
std::size_t bytes_used = 0;
|
std::size_t bytes_used = 0;
|
||||||
glBindBuffer(GL_TEXTURE_BUFFER, texture_buffer.GetHandle());
|
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
|
// helper function for SyncProcTexNoiseLUT/ColorMap/AlphaMap
|
||||||
auto SyncProcTexValueLUT = [this, buffer, offset, invalidate, &bytes_used](
|
const auto sync_proc_tex_value_lut =
|
||||||
const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut,
|
[this, buffer = buffer, offset = offset, invalidate = invalidate,
|
||||||
|
&bytes_used](const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut,
|
||||||
std::array<Common::Vec2f, 128>& lut_data, GLint& lut_offset) {
|
std::array<Common::Vec2f, 128>& lut_data, GLint& lut_offset) {
|
||||||
std::array<Common::Vec2f, 128> new_data;
|
std::array<Common::Vec2f, 128> new_data;
|
||||||
std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) {
|
std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) {
|
||||||
|
@ -1001,21 +988,21 @@ void RasterizerOpenGL::SyncAndUploadLUTs() {
|
||||||
|
|
||||||
// Sync the proctex noise lut
|
// Sync the proctex noise lut
|
||||||
if (uniform_block_data.proctex_noise_lut_dirty || invalidate) {
|
if (uniform_block_data.proctex_noise_lut_dirty || invalidate) {
|
||||||
SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data,
|
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.data.proctex_noise_lut_offset);
|
||||||
uniform_block_data.proctex_noise_lut_dirty = false;
|
uniform_block_data.proctex_noise_lut_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync the proctex color map
|
// Sync the proctex color map
|
||||||
if (uniform_block_data.proctex_color_map_dirty || invalidate) {
|
if (uniform_block_data.proctex_color_map_dirty || invalidate) {
|
||||||
SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data,
|
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.data.proctex_color_map_offset);
|
||||||
uniform_block_data.proctex_color_map_dirty = false;
|
uniform_block_data.proctex_color_map_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync the proctex alpha map
|
// Sync the proctex alpha map
|
||||||
if (uniform_block_data.proctex_alpha_map_dirty || invalidate) {
|
if (uniform_block_data.proctex_alpha_map_dirty || invalidate) {
|
||||||
SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data,
|
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.data.proctex_alpha_map_offset);
|
||||||
uniform_block_data.proctex_alpha_map_dirty = false;
|
uniform_block_data.proctex_alpha_map_dirty = false;
|
||||||
}
|
}
|
||||||
|
@ -1070,28 +1057,25 @@ void RasterizerOpenGL::SyncAndUploadLUTs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::UploadUniforms(bool accelerate_draw) {
|
void RasterizerOpenGL::UploadUniforms(bool accelerate_draw) {
|
||||||
// glBindBufferRange below also changes the generic buffer binding point, so we sync the state
|
// glBindBufferRange also changes the generic buffer binding point, so we sync the state first.
|
||||||
// first
|
|
||||||
state.draw.uniform_buffer = uniform_buffer.GetHandle();
|
state.draw.uniform_buffer = uniform_buffer.GetHandle();
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
bool sync_vs = accelerate_draw;
|
const bool sync_vs = accelerate_draw;
|
||||||
bool sync_fs = uniform_block_data.dirty;
|
const bool sync_fs = uniform_block_data.dirty;
|
||||||
|
if (!sync_vs && !sync_fs) {
|
||||||
if (!sync_vs && !sync_fs)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t uniform_size = uniform_size_aligned_vs + uniform_size_aligned_fs;
|
std::size_t uniform_size = uniform_size_aligned_vs + uniform_size_aligned_fs;
|
||||||
std::size_t used_bytes = 0;
|
std::size_t used_bytes = 0;
|
||||||
u8* uniforms;
|
|
||||||
GLintptr offset;
|
const auto [uniforms, offset, invalidate] =
|
||||||
bool invalidate;
|
|
||||||
std::tie(uniforms, offset, invalidate) =
|
|
||||||
uniform_buffer.Map(uniform_size, uniform_buffer_alignment);
|
uniform_buffer.Map(uniform_size, uniform_buffer_alignment);
|
||||||
|
|
||||||
if (sync_vs) {
|
if (sync_vs) {
|
||||||
Pica::Shader::VSUniformData vs_uniforms;
|
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));
|
std::memcpy(uniforms + used_bytes, &vs_uniforms, sizeof(vs_uniforms));
|
||||||
glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(Pica::Shader::UniformBindings::VS),
|
glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(Pica::Shader::UniformBindings::VS),
|
||||||
uniform_buffer.GetHandle(), offset + used_bytes,
|
uniform_buffer.GetHandle(), offset + used_bytes,
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "core/hw/gpu.h"
|
#include "core/hw/gpu.h"
|
||||||
#include "video_core/rasterizer_accelerated.h"
|
#include "video_core/rasterizer_accelerated.h"
|
||||||
#include "video_core/rasterizer_cache/rasterizer_cache.h"
|
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
#include "video_core/regs_texturing.h"
|
#include "video_core/regs_texturing.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||||
|
@ -24,6 +23,8 @@ class CustomTexManager;
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
|
struct ScreenInfo;
|
||||||
|
|
||||||
class Driver;
|
class Driver;
|
||||||
class ShaderProgramManager;
|
class ShaderProgramManager;
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ public:
|
||||||
bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override;
|
bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override;
|
||||||
bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override;
|
bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override;
|
||||||
bool AccelerateDisplay(const GPU::Regs::FramebufferConfig& config, PAddr framebuffer_addr,
|
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;
|
bool AccelerateDrawBatch(bool is_indexed) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -132,10 +133,9 @@ private:
|
||||||
private:
|
private:
|
||||||
Driver& driver;
|
Driver& driver;
|
||||||
OpenGLState state;
|
OpenGLState state;
|
||||||
GLuint default_texture;
|
ShaderProgramManager shader_manager;
|
||||||
TextureRuntime runtime;
|
TextureRuntime runtime;
|
||||||
RasterizerCache res_cache;
|
RasterizerCache res_cache;
|
||||||
std::unique_ptr<ShaderProgramManager> shader_program_manager;
|
|
||||||
|
|
||||||
OGLVertexArray sw_vao; // VAO for software shader draw
|
OGLVertexArray sw_vao; // VAO for software shader draw
|
||||||
OGLVertexArray hw_vao; // VAO for hardware shader / accelerate draw
|
OGLVertexArray hw_vao; // VAO for hardware shader / accelerate draw
|
||||||
|
@ -147,7 +147,6 @@ private:
|
||||||
OGLStreamBuffer index_buffer;
|
OGLStreamBuffer index_buffer;
|
||||||
OGLStreamBuffer texture_buffer;
|
OGLStreamBuffer texture_buffer;
|
||||||
OGLStreamBuffer texture_lf_buffer;
|
OGLStreamBuffer texture_lf_buffer;
|
||||||
OGLFramebuffer framebuffer;
|
|
||||||
GLint uniform_buffer_alignment;
|
GLint uniform_buffer_alignment;
|
||||||
std::size_t uniform_size_aligned_vs;
|
std::size_t uniform_size_aligned_vs;
|
||||||
std::size_t uniform_size_aligned_fs;
|
std::size_t uniform_size_aligned_fs;
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include "common/scope_exit.h"
|
|
||||||
#include "core/frontend/emu_window.h"
|
#include "core/frontend/emu_window.h"
|
||||||
#include "video_core/renderer_opengl/gl_driver.h"
|
#include "video_core/renderer_opengl/gl_driver.h"
|
||||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include "common/common_types.h"
|
||||||
#include "video_core/renderer_opengl/gl_state.h"
|
#include "video_core/renderer_opengl/gl_state.h"
|
||||||
#include "video_core/renderer_opengl/gl_vars.h"
|
#include "video_core/renderer_opengl/gl_vars.h"
|
||||||
|
|
||||||
|
|
|
@ -528,13 +528,13 @@ void Surface::ScaleUp(u32 new_scale) {
|
||||||
textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple,
|
textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple,
|
||||||
DebugName(true));
|
DebugName(true));
|
||||||
|
|
||||||
VideoCore::TextureBlit blit = {
|
|
||||||
.src_rect = GetRect(),
|
|
||||||
.dst_rect = GetScaledRect(),
|
|
||||||
};
|
|
||||||
for (u32 level = 0; level < levels; level++) {
|
for (u32 level = 0; level < levels; level++) {
|
||||||
blit.src_level = level;
|
const VideoCore::TextureBlit blit = {
|
||||||
blit.dst_level = level;
|
.src_level = level,
|
||||||
|
.dst_level = level,
|
||||||
|
.src_rect = GetRect(level),
|
||||||
|
.dst_rect = GetScaledRect(level),
|
||||||
|
};
|
||||||
BlitScale(blit, true);
|
BlitScale(blit, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,8 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
|
||||||
RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window,
|
RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window,
|
||||||
Frontend::EmuWindow* secondary_window)
|
Frontend::EmuWindow* secondary_window)
|
||||||
: VideoCore::RendererBase{system, window, secondary_window}, driver{system.TelemetrySession()},
|
: 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();
|
const bool has_debug_tool = driver.HasDebugTool();
|
||||||
window.mailbox = std::make_unique<OGLTextureMailbox>(has_debug_tool);
|
window.mailbox = std::make_unique<OGLTextureMailbox>(has_debug_tool);
|
||||||
if (secondary_window) {
|
if (secondary_window) {
|
||||||
|
@ -86,8 +87,6 @@ RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window
|
||||||
}
|
}
|
||||||
frame_dumper.mailbox = std::make_unique<OGLVideoDumpingMailbox>();
|
frame_dumper.mailbox = std::make_unique<OGLVideoDumpingMailbox>();
|
||||||
InitOpenGLObjects();
|
InitOpenGLObjects();
|
||||||
rasterizer = std::make_unique<RasterizerOpenGL>(system.Memory(), system.CustomTexManager(),
|
|
||||||
*this, driver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererOpenGL::~RendererOpenGL() = default;
|
RendererOpenGL::~RendererOpenGL() = default;
|
||||||
|
@ -121,8 +120,7 @@ void RendererOpenGL::SwapBuffers() {
|
||||||
|
|
||||||
EndFrame();
|
EndFrame();
|
||||||
prev_state.Apply();
|
prev_state.Apply();
|
||||||
|
rasterizer.TickFrame();
|
||||||
rasterizer->TickFrame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::RenderScreenshot() {
|
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.
|
// only allows rows to have a memory alignement of 4.
|
||||||
ASSERT(pixel_stride % 4 == 0);
|
ASSERT(pixel_stride % 4 == 0);
|
||||||
|
|
||||||
if (!Rasterizer()->AccelerateDisplay(framebuffer, framebuffer_addr,
|
if (!rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, static_cast<u32>(pixel_stride),
|
||||||
static_cast<u32>(pixel_stride), screen_info)) {
|
screen_info)) {
|
||||||
// Reset the screen info's display texture to its own permanent texture
|
// Reset the screen info's display texture to its own permanent texture
|
||||||
screen_info.display_texture = screen_info.texture.resource.handle;
|
screen_info.display_texture = screen_info.texture.resource.handle;
|
||||||
screen_info.display_texcoords = Common::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
|
screen_info.display_texcoords = Common::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
|
||||||
|
@ -903,7 +901,7 @@ void RendererOpenGL::CleanupVideoDumping() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::Sync() {
|
void RendererOpenGL::Sync() {
|
||||||
rasterizer->SyncEntireState();
|
rasterizer.SyncEntireState();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
|
@ -46,8 +46,8 @@ public:
|
||||||
Frontend::EmuWindow* secondary_window);
|
Frontend::EmuWindow* secondary_window);
|
||||||
~RendererOpenGL() override;
|
~RendererOpenGL() override;
|
||||||
|
|
||||||
[[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() const override {
|
[[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() override {
|
||||||
return rasterizer.get();
|
return &rasterizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapBuffers() override;
|
void SwapBuffers() override;
|
||||||
|
@ -86,8 +86,8 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Driver driver;
|
Driver driver;
|
||||||
|
RasterizerOpenGL rasterizer;
|
||||||
OpenGLState state;
|
OpenGLState state;
|
||||||
std::unique_ptr<RasterizerOpenGL> rasterizer;
|
|
||||||
|
|
||||||
// OpenGL object IDs
|
// OpenGL object IDs
|
||||||
OGLVertexArray vertex_array;
|
OGLVertexArray vertex_array;
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace SwRenderer {
|
||||||
|
|
||||||
RendererSoftware::RendererSoftware(Core::System& system, Frontend::EmuWindow& window)
|
RendererSoftware::RendererSoftware(Core::System& system, Frontend::EmuWindow& window)
|
||||||
: VideoCore::RendererBase{system, window, nullptr}, memory{system.Memory()},
|
: VideoCore::RendererBase{system, window, nullptr}, memory{system.Memory()},
|
||||||
rasterizer{std::make_unique<RasterizerSoftware>(system.Memory())} {}
|
rasterizer{system.Memory()} {}
|
||||||
|
|
||||||
RendererSoftware::~RendererSoftware() = default;
|
RendererSoftware::~RendererSoftware() = default;
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ public:
|
||||||
explicit RendererSoftware(Core::System& system, Frontend::EmuWindow& window);
|
explicit RendererSoftware(Core::System& system, Frontend::EmuWindow& window);
|
||||||
~RendererSoftware() override;
|
~RendererSoftware() override;
|
||||||
|
|
||||||
[[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() const override {
|
[[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() override {
|
||||||
return rasterizer.get();
|
return &rasterizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const ScreenInfo& Screen(VideoCore::ScreenId id) const noexcept {
|
[[nodiscard]] const ScreenInfo& Screen(VideoCore::ScreenId id) const noexcept {
|
||||||
|
@ -42,7 +42,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Memory::MemorySystem& memory;
|
Memory::MemorySystem& memory;
|
||||||
std::unique_ptr<RasterizerSoftware> rasterizer;
|
RasterizerSoftware rasterizer;
|
||||||
std::array<ScreenInfo, 3> screen_infos{};
|
std::array<ScreenInfo, 3> screen_infos{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue