Merge master

This commit is contained in:
PabloMK7 2023-08-23 19:54:37 +02:00
commit bf97245c7f
131 changed files with 1617 additions and 1509 deletions

View File

@ -26,6 +26,7 @@
#include "core/hle/service/nfc/nfc.h"
#include "core/loader/loader.h"
#include "core/savestate.h"
#include "core/telemetry_session.h"
#include "jni/android_common/android_common.h"
#include "jni/applets/mii_selector.h"
#include "jni/applets/swkbd.h"
@ -156,7 +157,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>());
// Register microphone permission check
Core::System::GetInstance().RegisterMicPermissionCheck(&CheckMicPermission);
system.RegisterMicPermissionCheck(&CheckMicPermission);
InputManager::Init();
@ -166,7 +167,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
return load_result;
}
auto& telemetry_session = Core::System::GetInstance().TelemetrySession();
auto& telemetry_session = system.TelemetrySession();
telemetry_session.AddField(Common::Telemetry::FieldType::App, "Frontend", "Android");
stop_run = false;
@ -187,8 +188,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
audio_stretching_event =
system.CoreTiming().RegisterEvent("AudioStretchingEvent", [&](u64, s64 cycles_late) {
if (Settings::values.enable_audio_stretching) {
Core::DSP().EnableStretching(
Core::System::GetInstance().GetAndResetPerfStats().emulation_speed < 0.95);
system.DSP().EnableStretching(system.GetAndResetPerfStats().emulation_speed < 0.95);
}
system.CoreTiming().ScheduleEvent(audio_stretching_ticks - cycles_late,
@ -219,7 +219,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
SCOPE_EXIT({ Settings::values.volume = volume; });
Settings::values.volume = 0;
std::unique_lock<std::mutex> pause_lock(paused_mutex);
std::unique_lock pause_lock{paused_mutex};
running_cv.wait(pause_lock, [] { return !pause_emulation || stop_run; });
window->PollEvents();
}
@ -621,7 +621,7 @@ jobjectArray Java_org_citra_citra_1emu_NativeLibrary_GetSavestateInfo(
return nullptr;
}
const auto savestates = Core::ListSaveStates(title_id);
const auto savestates = Core::ListSaveStates(title_id, system.Movie().GetCurrentMovieID());
const jobjectArray array =
env->NewObjectArray(static_cast<jsize>(savestates.size()), savestate_info_class, nullptr);
for (std::size_t i = 0; i < savestates.size(); ++i) {

View File

@ -8,6 +8,7 @@
#include <boost/serialization/vector.hpp>
#include <boost/serialization/weak_ptr.hpp>
#include "audio_core/audio_types.h"
#include "common/archives.h"
#ifdef HAVE_MF
#include "audio_core/hle/wmf_decoder.h"
#elif HAVE_AUDIOTOOLBOX

View File

@ -19,7 +19,6 @@
#include "common/detached_tasks.h"
#include "common/file_util.h"
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
@ -28,18 +27,15 @@
#include "core/core.h"
#include "core/dumping/backend.h"
#include "core/dumping/ffmpeg_backend.h"
#include "core/file_sys/cia_container.h"
#include "core/frontend/applets/default_applets.h"
#include "core/frontend/framebuffer_layout.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/cfg/cfg.h"
#include "core/loader/loader.h"
#include "core/movie.h"
#include "core/telemetry_session.h"
#include "input_common/main.h"
#include "network/network.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
#undef _UNICODE
#include <getopt.h>
@ -331,7 +327,7 @@ int main(int argc, char** argv) {
}
auto& system = Core::System::GetInstance();
auto& movie = Core::Movie::GetInstance();
auto& movie = system.Movie();
if (!movie_record.empty()) {
movie.PrepareForRecording();

View File

@ -9,6 +9,7 @@
#include "citra_qt/compatdb.h"
#include "common/telemetry.h"
#include "core/core.h"
#include "core/telemetry_session.h"
#include "ui_compatdb.h"
CompatDB::CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent)

View File

@ -21,68 +21,8 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>-1</number>
</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>
</item>
</layout>

View File

@ -10,14 +10,13 @@
#include "citra_qt/configuration/configuration_shared.h"
#include "citra_qt/configuration/configure_audio.h"
#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_audio.h"
#if defined(__APPLE__)
#include "common/apple_authorization.h"
#endif
ConfigureAudio::ConfigureAudio(QWidget* parent)
ConfigureAudio::ConfigureAudio(bool is_powered_on, QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) {
ui->setupUi(this);
@ -27,8 +26,7 @@ ConfigureAudio::ConfigureAudio(QWidget* parent)
AudioCore::GetSinkName(static_cast<AudioCore::SinkType>(type)).data()));
}
const bool is_running = Core::System::GetInstance().IsPoweredOn();
ui->emulation_combo_box->setEnabled(!is_running);
ui->emulation_combo_box->setEnabled(!is_powered_on);
connect(ui->volume_slider, &QSlider::valueChanged, this,
&ConfigureAudio::SetVolumeIndicatorText);

View File

@ -19,7 +19,7 @@ class ConfigureAudio : public QWidget {
Q_OBJECT
public:
explicit ConfigureAudio(QWidget* parent = nullptr);
explicit ConfigureAudio(bool is_powered_on, QWidget* parent = nullptr);
~ConfigureAudio() override;
void ApplyConfiguration();

View File

@ -47,8 +47,7 @@ ConfigureCamera::~ConfigureCamera() {
}
void ConfigureCamera::ConnectEvents() {
connect(ui->image_source,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
connect(ui->image_source, qOverload<int>(&QComboBox::currentIndexChanged), this,
[this](int index) {
StopPreviewing();
UpdateImageSourceUI();
@ -58,36 +57,33 @@ void ConfigureCamera::ConnectEvents() {
}
#endif
});
connect(ui->camera_selection,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] {
StopPreviewing();
if (GetCameraSelection() != current_selected) {
RecordConfig();
}
if (ui->camera_selection->currentIndex() == 1) {
ui->camera_mode->setCurrentIndex(1); // Double
if (camera_name[0] == camera_name[2] && camera_config[0] == camera_config[2]) {
ui->camera_mode->setCurrentIndex(0); // Single
}
}
UpdateCameraMode();
SetConfiguration();
});
connect(ui->camera_mode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, [this] {
StopPreviewing();
ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1);
ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1);
current_selected = GetCameraSelection();
});
connect(ui->camera_position,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] {
StopPreviewing();
if (GetCameraSelection() != current_selected) {
RecordConfig();
}
SetConfiguration();
});
connect(ui->camera_selection, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
StopPreviewing();
if (GetCameraSelection() != current_selected) {
RecordConfig();
}
if (ui->camera_selection->currentIndex() == 1) {
ui->camera_mode->setCurrentIndex(1); // Double
if (camera_name[0] == camera_name[2] && camera_config[0] == camera_config[2]) {
ui->camera_mode->setCurrentIndex(0); // Single
}
}
UpdateCameraMode();
SetConfiguration();
});
connect(ui->camera_mode, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
StopPreviewing();
ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1);
ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1);
current_selected = GetCameraSelection();
});
connect(ui->camera_position, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
StopPreviewing();
if (GetCameraSelection() != current_selected) {
RecordConfig();
}
SetConfiguration();
});
connect(ui->toolButton, &QToolButton::clicked, this, &ConfigureCamera::OnToolButtonClicked);
connect(ui->preview_button, &QPushButton::clicked, this, [this] { StartPreviewing(); });
connect(ui->prompt_before_load, &QCheckBox::stateChanged, this, [this](int state) {

View File

@ -9,11 +9,9 @@
#include "core/cheats/cheat_base.h"
#include "core/cheats/cheats.h"
#include "core/cheats/gateway_cheat.h"
#include "core/core.h"
#include "core/hle/kernel/process.h"
#include "ui_configure_cheats.h"
ConfigureCheats::ConfigureCheats(u64 title_id_, QWidget* parent)
ConfigureCheats::ConfigureCheats(Core::System& system, u64 title_id_, QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureCheats>()), title_id{title_id_} {
// Setup gui control settings
ui->setupUi(this);
@ -36,7 +34,7 @@ ConfigureCheats::ConfigureCheats(u64 title_id_, QWidget* parent)
[this] { SaveCheat(ui->tableCheats->currentRow()); });
connect(ui->buttonDelete, &QPushButton::clicked, this, &ConfigureCheats::OnDeleteCheat);
cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, Core::System::GetInstance());
cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, system);
LoadCheats();
}

View File

@ -5,6 +5,7 @@
#pragma once
#include <memory>
#include <QWidget>
#include "common/common_types.h"
namespace Cheats {
@ -12,6 +13,10 @@ class CheatBase;
class CheatEngine;
} // namespace Cheats
namespace Core {
class System;
}
namespace Ui {
class ConfigureCheats;
} // namespace Ui
@ -20,7 +25,7 @@ class ConfigureCheats : public QWidget {
Q_OBJECT
public:
explicit ConfigureCheats(u64 title_id_, QWidget* parent = nullptr);
explicit ConfigureCheats(Core::System& system, u64 title_id, QWidget* parent = nullptr);
~ConfigureCheats();
bool ApplyConfiguration();

View File

@ -11,7 +11,6 @@
#include "common/file_util.h"
#include "common/logging/backend.h"
#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_debug.h"
// The QSlider doesn't have an easy way to set a custom step amount,
@ -25,8 +24,8 @@ static constexpr int SettingsToSlider(int value) {
return (value - 5) / 5;
}
ConfigureDebug::ConfigureDebug(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureDebug>()) {
ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureDebug>()), is_powered_on{is_powered_on_} {
ui->setupUi(this);
SetConfiguration();
@ -35,7 +34,6 @@ ConfigureDebug::ConfigureDebug(QWidget* parent)
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
});
const bool is_powered_on = Core::System::GetInstance().IsPoweredOn();
ui->toggle_cpu_jit->setEnabled(!is_powered_on);
ui->toggle_renderer_debug->setEnabled(!is_powered_on);
@ -59,7 +57,7 @@ void ConfigureDebug::SetConfiguration() {
ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue());
ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue());
ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue());
ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->toggle_console->setEnabled(!is_powered_on);
ui->toggle_console->setChecked(UISettings::values.show_console.GetValue());
ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue()));
ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue());

View File

@ -15,7 +15,7 @@ class ConfigureDebug : public QWidget {
Q_OBJECT
public:
explicit ConfigureDebug(QWidget* parent = nullptr);
explicit ConfigureDebug(bool is_powered_on, QWidget* parent = nullptr);
~ConfigureDebug() override;
void ApplyConfiguration();
@ -25,4 +25,5 @@ public:
private:
std::unique_ptr<Ui::ConfigureDebug> ui;
bool is_powered_on;
};

View File

@ -4,8 +4,19 @@
#include <map>
#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_enhancements.h"
#include "citra_qt/configuration/configure_general.h"
#include "citra_qt/configuration/configure_graphics.h"
#include "citra_qt/configuration/configure_hotkeys.h"
#include "citra_qt/configuration/configure_input.h"
#include "citra_qt/configuration/configure_storage.h"
#include "citra_qt/configuration/configure_system.h"
#include "citra_qt/configuration/configure_ui.h"
#include "citra_qt/configuration/configure_web.h"
#include "citra_qt/hotkeys.h"
#include "common/settings.h"
#include "core/core.h"
@ -14,16 +25,41 @@
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_,
bool enable_web_config)
: QDialog(parent), ui{std::make_unique<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);
ui->setupUi(this);
ui->hotkeysTab->Populate(registry);
ui->webTab->SetWebServiceConfigEnabled(enable_web_config);
ui->tabWidget->addTab(general_tab.get(), tr("General"));
ui->tabWidget->addTab(system_tab.get(), tr("System"));
ui->tabWidget->addTab(input_tab.get(), tr("Input"));
ui->tabWidget->addTab(hotkeys_tab.get(), tr("Hotkeys"));
ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics"));
ui->tabWidget->addTab(enhancements_tab.get(), tr("Enhancements"));
ui->tabWidget->addTab(audio_tab.get(), tr("Audio"));
ui->tabWidget->addTab(camera_tab.get(), tr("Camera"));
ui->tabWidget->addTab(debug_tab.get(), tr("Debug"));
ui->tabWidget->addTab(storage_tab.get(), tr("Storage"));
ui->tabWidget->addTab(web_tab.get(), tr("Web"));
ui->tabWidget->addTab(ui_tab.get(), tr("UI"));
hotkeys_tab->Populate(registry);
web_tab->SetWebServiceConfigEnabled(enable_web_config);
PopulateSelectionList();
connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
connect(ui_tab.get(), &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
&ConfigureDialog::UpdateVisibleTabs);
@ -31,46 +67,46 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor
ui->selectorList->setCurrentRow(0);
// Set up used key list synchronisation
connect(ui->inputTab, &ConfigureInput::InputKeysChanged, ui->hotkeysTab,
connect(input_tab.get(), &ConfigureInput::InputKeysChanged, hotkeys_tab.get(),
&ConfigureHotkeys::OnInputKeysChanged);
connect(ui->hotkeysTab, &ConfigureHotkeys::HotkeysChanged, ui->inputTab,
connect(hotkeys_tab.get(), &ConfigureHotkeys::HotkeysChanged, input_tab.get(),
&ConfigureInput::OnHotkeysChanged);
// Synchronise lists upon initialisation
ui->inputTab->EmitInputKeysChanged();
ui->hotkeysTab->EmitHotkeysChanged();
input_tab->EmitInputKeysChanged();
hotkeys_tab->EmitHotkeysChanged();
}
ConfigureDialog::~ConfigureDialog() = default;
void ConfigureDialog::SetConfiguration() {
ui->generalTab->SetConfiguration();
ui->systemTab->SetConfiguration();
ui->inputTab->LoadConfiguration();
ui->graphicsTab->SetConfiguration();
ui->enhancementsTab->SetConfiguration();
ui->audioTab->SetConfiguration();
ui->cameraTab->SetConfiguration();
ui->debugTab->SetConfiguration();
ui->webTab->SetConfiguration();
ui->uiTab->SetConfiguration();
ui->storageTab->SetConfiguration();
general_tab->SetConfiguration();
system_tab->SetConfiguration();
input_tab->LoadConfiguration();
graphics_tab->SetConfiguration();
enhancements_tab->SetConfiguration();
audio_tab->SetConfiguration();
camera_tab->SetConfiguration();
debug_tab->SetConfiguration();
web_tab->SetConfiguration();
ui_tab->SetConfiguration();
storage_tab->SetConfiguration();
}
void ConfigureDialog::ApplyConfiguration() {
ui->generalTab->ApplyConfiguration();
ui->systemTab->ApplyConfiguration();
ui->inputTab->ApplyConfiguration();
ui->inputTab->ApplyProfile();
ui->hotkeysTab->ApplyConfiguration(registry);
ui->graphicsTab->ApplyConfiguration();
ui->enhancementsTab->ApplyConfiguration();
ui->audioTab->ApplyConfiguration();
ui->cameraTab->ApplyConfiguration();
ui->debugTab->ApplyConfiguration();
ui->webTab->ApplyConfiguration();
ui->uiTab->ApplyConfiguration();
ui->storageTab->ApplyConfiguration();
general_tab->ApplyConfiguration();
system_tab->ApplyConfiguration();
input_tab->ApplyConfiguration();
input_tab->ApplyProfile();
hotkeys_tab->ApplyConfiguration(registry);
graphics_tab->ApplyConfiguration();
enhancements_tab->ApplyConfiguration();
audio_tab->ApplyConfiguration();
camera_tab->ApplyConfiguration();
debug_tab->ApplyConfiguration();
web_tab->ApplyConfiguration();
ui_tab->ApplyConfiguration();
storage_tab->ApplyConfiguration();
system.ApplySettings();
Settings::LogSettings();
}
@ -81,11 +117,11 @@ void ConfigureDialog::PopulateSelectionList() {
ui->selectorList->clear();
const std::array<std::pair<QString, QList<QWidget*>>, 5> items{
{{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}},
{tr("System"), {ui->systemTab, ui->cameraTab, ui->storageTab}},
{tr("Graphics"), {ui->enhancementsTab, ui->graphicsTab}},
{tr("Audio"), {ui->audioTab}},
{tr("Controls"), {ui->inputTab, ui->hotkeysTab}}}};
{{tr("General"), {general_tab.get(), web_tab.get(), debug_tab.get(), ui_tab.get()}},
{tr("System"), {system_tab.get(), camera_tab.get(), storage_tab.get()}},
{tr("Graphics"), {enhancements_tab.get(), graphics_tab.get()}},
{tr("Audio"), {audio_tab.get()}},
{tr("Controls"), {input_tab.get(), hotkeys_tab.get()}}}};
for (const auto& entry : items) {
auto* const item = new QListWidgetItem(entry.first);
@ -112,18 +148,18 @@ void ConfigureDialog::RetranslateUI() {
ui->selectorList->setCurrentRow(old_row);
ui->tabWidget->setCurrentIndex(old_index);
ui->generalTab->RetranslateUI();
ui->systemTab->RetranslateUI();
ui->inputTab->RetranslateUI();
ui->hotkeysTab->RetranslateUI();
ui->graphicsTab->RetranslateUI();
ui->enhancementsTab->RetranslateUI();
ui->audioTab->RetranslateUI();
ui->cameraTab->RetranslateUI();
ui->debugTab->RetranslateUI();
ui->webTab->RetranslateUI();
ui->uiTab->RetranslateUI();
ui->storageTab->RetranslateUI();
general_tab->RetranslateUI();
system_tab->RetranslateUI();
input_tab->RetranslateUI();
hotkeys_tab->RetranslateUI();
graphics_tab->RetranslateUI();
enhancements_tab->RetranslateUI();
audio_tab->RetranslateUI();
camera_tab->RetranslateUI();
debug_tab->RetranslateUI();
web_tab->RetranslateUI();
ui_tab->RetranslateUI();
storage_tab->RetranslateUI();
}
void ConfigureDialog::UpdateVisibleTabs() {
@ -131,18 +167,18 @@ void ConfigureDialog::UpdateVisibleTabs() {
if (items.isEmpty())
return;
const std::map<QWidget*, QString> widgets = {{ui->generalTab, tr("General")},
{ui->systemTab, tr("System")},
{ui->inputTab, tr("Input")},
{ui->hotkeysTab, tr("Hotkeys")},
{ui->enhancementsTab, tr("Enhancements")},
{ui->graphicsTab, tr("Advanced")},
{ui->audioTab, tr("Audio")},
{ui->cameraTab, tr("Camera")},
{ui->debugTab, tr("Debug")},
{ui->storageTab, tr("Storage")},
{ui->webTab, tr("Web")},
{ui->uiTab, tr("UI")}};
const std::map<QWidget*, QString> widgets = {{general_tab.get(), tr("General")},
{system_tab.get(), tr("System")},
{input_tab.get(), tr("Input")},
{hotkeys_tab.get(), tr("Hotkeys")},
{enhancements_tab.get(), tr("Enhancements")},
{graphics_tab.get(), tr("Advanced")},
{audio_tab.get(), tr("Audio")},
{camera_tab.get(), tr("Camera")},
{debug_tab.get(), tr("Debug")},
{storage_tab.get(), tr("Storage")},
{web_tab.get(), tr("Web")},
{ui_tab.get(), tr("UI")}};
ui->tabWidget->clear();

View File

@ -17,6 +17,19 @@ namespace Core {
class System;
}
class ConfigureGeneral;
class ConfigureSystem;
class ConfigureInput;
class ConfigureHotkeys;
class ConfigureGraphics;
class ConfigureEnhancements;
class ConfigureAudio;
class ConfigureCamera;
class ConfigureDebug;
class ConfigureStorage;
class ConfigureWeb;
class ConfigureUi;
class ConfigureDialog : public QDialog {
Q_OBJECT
@ -42,4 +55,18 @@ private:
std::unique_ptr<Ui::ConfigureDialog> ui;
HotkeyRegistry& registry;
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;
};

View File

@ -22,8 +22,7 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent)
const bool res_scale_enabled = graphics_api != Settings::GraphicsAPI::Software;
ui->resolution_factor_combobox->setEnabled(res_scale_enabled);
connect(ui->render_3d_combobox,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
connect(ui->render_3d_combobox, qOverload<int>(&QComboBox::currentIndexChanged), this,
[this](int currentIndex) {
updateShaders(static_cast<Settings::StereoRenderOption>(currentIndex));
});

View File

@ -6,14 +6,13 @@
#include "citra_qt/configuration/configuration_shared.h"
#include "citra_qt/configuration/configure_graphics.h"
#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_graphics.h"
ConfigureGraphics::ConfigureGraphics(QWidget* parent)
ConfigureGraphics::ConfigureGraphics(bool is_powered_on, QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) {
ui->setupUi(this);
ui->toggle_vsync_new->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->toggle_vsync_new->setEnabled(!is_powered_on);
// Set the index to -1 to ensure the below lambda is called with setCurrentIndex
ui->graphics_api_combo->setCurrentIndex(-1);

View File

@ -19,7 +19,7 @@ class ConfigureGraphics : public QWidget {
Q_OBJECT
public:
explicit ConfigureGraphics(QWidget* parent = nullptr);
explicit ConfigureGraphics(bool is_powered_on, QWidget* parent = nullptr);
~ConfigureGraphics() override;
void ApplyConfiguration();

View File

@ -19,6 +19,9 @@
<property name="windowTitle">
<string>Form</string>
</property>
<property name="accessibleName">
<string>Graphics</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="apiBox">

View File

@ -9,7 +9,6 @@
#include "citra_qt/configuration/configure_hotkeys.h"
#include "citra_qt/hotkeys.h"
#include "citra_qt/util/sequence_dialog/sequence_dialog.h"
#include "common/settings.h"
#include "ui_configure_hotkeys.h"
constexpr int name_column = 0;
@ -189,9 +188,9 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) {
QAction* clear = context_menu.addAction(tr("Clear"));
const auto hotkey_index = index.sibling(index.row(), hotkey_column);
connect(restore_default, &QAction::triggered,
connect(restore_default, &QAction::triggered, this,
[this, hotkey_index] { RestoreHotkey(hotkey_index); });
connect(clear, &QAction::triggered,
connect(clear, &QAction::triggered, this,
[this, hotkey_index] { model->setData(hotkey_index, QString{}); });
context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location));

View File

@ -31,13 +31,14 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString
: fmt::format("{:016X}", title_id);
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);
enhancements_tab = std::make_unique<ConfigureEnhancements>(this);
graphics_tab = std::make_unique<ConfigureGraphics>(this);
system_tab = std::make_unique<ConfigureSystem>(this);
debug_tab = std::make_unique<ConfigureDebug>(this);
cheat_tab = std::make_unique<ConfigureCheats>(title_id, this);
graphics_tab = std::make_unique<ConfigureGraphics>(is_powered_on, this);
system_tab = std::make_unique<ConfigureSystem>(system, this);
debug_tab = std::make_unique<ConfigureDebug>(is_powered_on, this);
cheat_tab = std::make_unique<ConfigureCheats>(system, title_id, this);
ui->setupUi(this);

View File

@ -6,12 +6,12 @@
#include <QFileDialog>
#include <QUrl>
#include "citra_qt/configuration/configure_storage.h"
#include "common/file_util.h"
#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_storage.h"
ConfigureStorage::ConfigureStorage(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureStorage>()) {
ConfigureStorage::ConfigureStorage(bool is_powered_on_, QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureStorage>()), is_powered_on{is_powered_on_} {
ui->setupUi(this);
SetConfiguration();
@ -74,7 +74,7 @@ void ConfigureStorage::SetConfiguration() {
ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue());
ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage.GetValue());
ui->storage_group->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->storage_group->setEnabled(!is_powered_on);
}
void ConfigureStorage::ApplyConfiguration() {

View File

@ -15,7 +15,7 @@ class ConfigureStorage : public QWidget {
Q_OBJECT
public:
explicit ConfigureStorage(QWidget* parent = nullptr);
explicit ConfigureStorage(bool is_powered_on, QWidget* parent = nullptr);
~ConfigureStorage() override;
void ApplyConfiguration();
@ -23,4 +23,5 @@ public:
void SetConfiguration();
std::unique_ptr<Ui::ConfigureStorage> ui;
bool is_powered_on;
};

View File

@ -223,14 +223,12 @@ static const std::array<const char*, 187> country_names = {
QT_TRANSLATE_NOOP("ConfigureSystem", "Bermuda"), // 180-186
};
ConfigureSystem::ConfigureSystem(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureSystem>()) {
ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureSystem>()), system{system_} {
ui->setupUi(this);
connect(ui->combo_birthmonth,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
connect(ui->combo_birthmonth, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureSystem::UpdateBirthdayComboBox);
connect(ui->combo_init_clock,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
connect(ui->combo_init_clock, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureSystem::UpdateInitTime);
connect(ui->button_regenerate_console_id, &QPushButton::clicked, this,
&ConfigureSystem::RefreshConsoleID);
@ -280,7 +278,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent)
ConfigureSystem::~ConfigureSystem() = default;
void ConfigureSystem::SetConfiguration() {
enabled = !Core::System::GetInstance().IsPoweredOn();
enabled = !system.IsPoweredOn();
ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock.GetValue()));
QDateTime date_time;
@ -296,7 +294,7 @@ void ConfigureSystem::SetConfiguration() {
ui->edit_init_time_offset_time->setTime(time);
if (!enabled) {
cfg = Service::CFG::GetModule(Core::System::GetInstance());
cfg = Service::CFG::GetModule(system);
ASSERT_MSG(cfg, "CFG Module missing!");
ReadSystemSettings();
ui->group_system_settings->setEnabled(false);

View File

@ -16,6 +16,10 @@ namespace ConfigurationShared {
enum class CheckState;
}
namespace Core {
class System;
}
namespace Service {
namespace CFG {
class Module;
@ -26,7 +30,7 @@ class ConfigureSystem : public QWidget {
Q_OBJECT
public:
explicit ConfigureSystem(QWidget* parent = nullptr);
explicit ConfigureSystem(Core::System& system, QWidget* parent = nullptr);
~ConfigureSystem() override;
void ApplyConfiguration();
@ -45,8 +49,10 @@ private:
void DownloadFromNUS();
ConfigurationShared::CheckState is_new_3ds;
private:
std::unique_ptr<Ui::ConfigureSystem> ui;
Core::System& system;
ConfigurationShared::CheckState is_new_3ds;
bool enabled = false;
std::shared_ptr<Service::CFG::Module> cfg;

View File

@ -16,7 +16,6 @@
#include "citra_qt/debugger/graphics/graphics_cmdlists.h"
#include "citra_qt/util/util.h"
#include "common/vector_math.h"
#include "core/core.h"
#include "core/memory.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/pica_state.h"
@ -167,8 +166,7 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
const auto format = texture.format;
const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format);
const u8* src =
Core::System::GetInstance().Memory().GetPhysicalPointer(config.GetPhysicalAddress());
const u8* src = memory.GetPhysicalPointer(config.GetPhysicalAddress());
new_info_widget = new TextureInfoWidget(src, info);
}
if (command_info_widget) {
@ -182,8 +180,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
}
#undef COMMAND_IN_RANGE
GPUCommandListWidget::GPUCommandListWidget(QWidget* parent)
: QDockWidget(tr("Pica Command List"), parent) {
GPUCommandListWidget::GPUCommandListWidget(Memory::MemorySystem& memory_, QWidget* parent)
: QDockWidget(tr("Pica Command List"), parent), memory{memory_} {
setObjectName(QStringLiteral("Pica Command List"));
GPUCommandListModel* model = new GPUCommandListModel(this);

View File

@ -7,11 +7,14 @@
#include <QAbstractListModel>
#include <QDockWidget>
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu_debugger.h"
class QPushButton;
class QTreeView;
namespace Memory {
class MemorySystem;
}
class GPUCommandListModel : public QAbstractListModel {
Q_OBJECT
@ -39,7 +42,7 @@ class GPUCommandListWidget : public QDockWidget {
Q_OBJECT
public:
explicit GPUCommandListWidget(QWidget* parent = nullptr);
explicit GPUCommandListWidget(Memory::MemorySystem& memory, QWidget* parent = nullptr);
public slots:
void OnToggleTracing();
@ -54,7 +57,7 @@ signals:
private:
std::unique_ptr<Pica::DebugUtils::PicaTrace> pica_trace;
Memory::MemorySystem& memory;
QTreeView* list_widget;
QWidget* command_info_widget;
QPushButton* toggle_tracing;

View File

@ -15,8 +15,6 @@
#include "citra_qt/debugger/graphics/graphics_surface.h"
#include "citra_qt/util/spinbox.h"
#include "common/color.h"
#include "core/core.h"
#include "core/hw/gpu.h"
#include "core/memory.h"
#include "video_core/pica_state.h"
#include "video_core/regs_framebuffer.h"
@ -51,9 +49,10 @@ void SurfacePicture::mouseMoveEvent(QMouseEvent* event) {
mousePressEvent(event);
}
GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
GraphicsSurfaceWidget::GraphicsSurfaceWidget(Memory::MemorySystem& memory_,
std::shared_ptr<Pica::DebugContext> debug_context,
QWidget* parent)
: BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent),
: BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), memory{memory_},
surface_source(Source::ColorBuffer) {
setObjectName(QStringLiteral("PicaSurface"));
@ -290,57 +289,57 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
return;
}
u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
if (buffer == nullptr) {
const u8* buffer = memory.GetPhysicalPointer(surface_address);
if (!buffer) {
surface_info_label->setText(tr("(unable to access pixel data)"));
surface_info_label->setAlignment(Qt::AlignCenter);
return;
}
unsigned nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format);
unsigned stride = nibbles_per_pixel * surface_width / 2;
unsigned bytes_per_pixel;
bool nibble_mode = (nibbles_per_pixel == 1);
if (nibble_mode) {
// As nibbles are contained in a byte we still need to access one byte per nibble
bytes_per_pixel = 1;
} else {
bytes_per_pixel = nibbles_per_pixel / 2;
}
const u32 nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format);
const u32 stride = nibbles_per_pixel * surface_width / 2;
const bool nibble_mode = (nibbles_per_pixel == 1);
const u32 bytes_per_pixel = [&] {
if (nibble_mode) {
// As nibbles are contained in a byte we still need to access one byte per nibble
return 1u;
} else {
return nibbles_per_pixel / 2;
}
}();
const u32 coarse_y = y & ~7;
u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
const u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
const u8* pixel = buffer + (nibble_mode ? (offset / 2) : offset);
auto GetText = [offset](Format format, const u8* pixel) {
const auto get_text = [offset](Format format, const u8* pixel) {
switch (format) {
case Format::RGBA8: {
auto value = Common::Color::DecodeRGBA8(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGBA8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
}
case Format::RGB8: {
auto value = Common::Color::DecodeRGB8(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGB8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2));
}
case Format::RGB5A1: {
auto value = Common::Color::DecodeRGB5A1(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGB5A1(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
}
case Format::RGB565: {
auto value = Common::Color::DecodeRGB565(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGB565(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2));
}
case Format::RGBA4: {
auto value = Common::Color::DecodeRGBA4(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGBA4(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
@ -348,7 +347,7 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
case Format::IA8:
return QStringLiteral("Index: %1, Alpha: %2").arg(pixel[0], pixel[1]);
case Format::RG8: {
auto value = Common::Color::DecodeRG8(pixel) / 255.0f;
const auto value = Common::Color::DecodeRG8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2));
}
@ -359,11 +358,11 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
case Format::IA4:
return QStringLiteral("Index: %1, Alpha: %2").arg(*pixel & 0xF, (*pixel & 0xF0) >> 4);
case Format::I4: {
u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
const u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
return QStringLiteral("Index: %1").arg(i);
}
case Format::A4: {
u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
const u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
return QStringLiteral("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2));
}
case Format::ETC1:
@ -371,17 +370,17 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
// TODO: Display block information or channel values?
return QStringLiteral("Compressed data");
case Format::D16: {
auto value = Common::Color::DecodeD16(pixel);
const auto value = Common::Color::DecodeD16(pixel);
return QStringLiteral("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4));
}
case Format::D24: {
auto value = Common::Color::DecodeD24(pixel);
const auto value = Common::Color::DecodeD24(pixel);
return QStringLiteral("Depth: %1")
.arg(QString::number(value / (float)0xFFFFFF, 'f', 4));
}
case Format::D24X8:
case Format::X24S8: {
auto values = Common::Color::DecodeD24S8(pixel);
const auto values = Common::Color::DecodeD24S8(pixel);
return QStringLiteral("Depth: %1, Stencil: %2")
.arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4), values[1]);
}
@ -398,13 +397,13 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
if (nibble_mode) {
nibble_index += (offset % 2) ? 0 : 1;
}
u8 byte = pixel[nibble_index / 2];
u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF;
const u8 byte = pixel[nibble_index / 2];
const u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF;
nibbles.append(QString::number(nibble, 16).toUpper());
}
surface_info_label->setText(
QStringLiteral("Raw: 0x%3\n(%4)").arg(nibbles, GetText(surface_format, pixel)));
QStringLiteral("Raw: 0x%3\n(%4)").arg(nibbles, get_text(surface_format, pixel)));
surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
}
@ -546,9 +545,9 @@ void GraphicsSurfaceWidget::OnUpdate() {
// TODO: Implement a good way to visualize alpha components!
QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
const u8* buffer = memory.GetPhysicalPointer(surface_address);
if (buffer == nullptr) {
if (!buffer) {
surface_picture_label->hide();
surface_info_label->setText(tr("(invalid surface address)"));
surface_info_label->setAlignment(Qt::AlignCenter);
@ -682,9 +681,8 @@ void GraphicsSurfaceWidget::SaveSurface() {
tr("Failed to save surface data to file '%1'").arg(filename));
}
} else if (selected_filter == bin_filter) {
const u8* const buffer =
Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
ASSERT_MSG(buffer != nullptr, "Memory not accessible");
const u8* const buffer = memory.GetPhysicalPointer(surface_address);
ASSERT_MSG(buffer, "Memory not accessible");
QFile file{filename};
if (!file.open(QIODevice::WriteOnly)) {

View File

@ -14,6 +14,10 @@ class CSpinBox;
class GraphicsSurfaceWidget;
namespace Memory {
class MemorySystem;
}
class SurfacePicture : public QLabel {
Q_OBJECT
@ -72,7 +76,8 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock {
static unsigned int NibblesPerPixel(Format format);
public:
explicit GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
explicit GraphicsSurfaceWidget(Memory::MemorySystem& memory,
std::shared_ptr<Pica::DebugContext> debug_context,
QWidget* parent = nullptr);
void Pick(int x, int y);
@ -95,6 +100,7 @@ private:
void SaveSurface();
Memory::MemorySystem& memory;
QComboBox* surface_source_list;
CSpinBox* surface_address_control;
QSpinBox* surface_width_control;

View File

@ -16,13 +16,13 @@
#include "core/hle/service/sm/sm.h"
#include "ui_recorder.h"
IPCRecorderWidget::IPCRecorderWidget(QWidget* parent)
: QDockWidget(parent), ui(std::make_unique<Ui::IPCRecorder>()) {
IPCRecorderWidget::IPCRecorderWidget(Core::System& system_, QWidget* parent)
: QDockWidget(parent), ui(std::make_unique<Ui::IPCRecorder>()), system{system_} {
ui->setupUi(this);
qRegisterMetaType<IPCDebugger::RequestRecord>();
connect(ui->enabled, &QCheckBox::stateChanged,
connect(ui->enabled, &QCheckBox::stateChanged, this,
[this](int new_state) { SetEnabled(new_state == Qt::Checked); });
connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear);
connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll);
@ -90,7 +90,7 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) {
(record.status == IPCDebugger::RequestStatus::Handled &&
record.translated_reply_cmdbuf[1] != RESULT_SUCCESS.raw)) { // Unimplemented / Error
auto* item = ui->main->invisibleRootItem()->child(row_id);
auto item = ui->main->invisibleRootItem()->child(row_id);
for (int column = 0; column < item->columnCount(); ++column) {
item->setBackground(column, QBrush(QColor::fromRgb(255, 0, 0)));
}
@ -100,11 +100,11 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) {
}
void IPCRecorderWidget::SetEnabled(bool enabled) {
if (!Core::System::GetInstance().IsPoweredOn()) {
if (!system.IsPoweredOn()) {
return;
}
auto& ipc_recorder = Core::System::GetInstance().Kernel().GetIPCRecorder();
auto& ipc_recorder = system.Kernel().GetIPCRecorder();
ipc_recorder.SetEnabled(enabled);
if (enabled) {
@ -123,10 +123,10 @@ void IPCRecorderWidget::Clear() {
}
QString IPCRecorderWidget::GetServiceName(const IPCDebugger::RequestRecord& record) const {
if (Core::System::GetInstance().IsPoweredOn() && record.client_port.id != -1) {
const auto service_name =
Core::System::GetInstance().ServiceManager().GetServiceNameByPortId(
static_cast<u32>(record.client_port.id));
if (system.IsPoweredOn() && record.client_port.id != -1) {
const Service::SM::ServiceManager& sm = system.ServiceManager();
const u32 port_id = static_cast<u32>(record.client_port.id);
const auto service_name = sm.GetServiceNameByPortId(port_id);
if (!service_name.empty()) {
return QString::fromStdString(service_name);

View File

@ -14,11 +14,15 @@ namespace Ui {
class IPCRecorder;
}
namespace Core {
class System;
}
class IPCRecorderWidget : public QDockWidget {
Q_OBJECT
public:
explicit IPCRecorderWidget(QWidget* parent = nullptr);
explicit IPCRecorderWidget(Core::System& system, QWidget* parent = nullptr);
~IPCRecorderWidget();
void OnEmulationStarting();
@ -37,9 +41,10 @@ private:
QString GetFunctionName(const IPCDebugger::RequestRecord& record) const;
void OpenRecordDialog(QTreeWidgetItem* item, int column);
private:
std::unique_ptr<Ui::IPCRecorder> ui;
IPCDebugger::CallbackHandle handle;
Core::System& system;
// The offset between record id and row id, assuming record ids are assigned
// continuously and only the 'Clear' action can be performed, this is enough.
// The initial value is 1, which means record 1 = row 0.

View File

@ -9,8 +9,8 @@
#include "core/core.h"
#include "ui_registers.h"
RegistersWidget::RegistersWidget(QWidget* parent)
: QDockWidget(parent), cpu_regs_ui(std::make_unique<Ui::ARMRegisters>()) {
RegistersWidget::RegistersWidget(const Core::System& system_, QWidget* parent)
: QDockWidget(parent), cpu_regs_ui(std::make_unique<Ui::ARMRegisters>()), system{system_} {
cpu_regs_ui->setupUi(this);
tree = cpu_regs_ui->treeWidget;
@ -62,17 +62,21 @@ RegistersWidget::RegistersWidget(QWidget* parent)
RegistersWidget::~RegistersWidget() = default;
void RegistersWidget::OnDebugModeEntered() {
if (!Core::System::GetInstance().IsPoweredOn())
if (!system.IsPoweredOn()) {
return;
}
// Todo: Handle all cores
for (int i = 0; i < core_registers->childCount(); ++i)
// TODO: Handle all cores
const ARM_Interface& core = system.GetCore(0);
for (int i = 0; i < core_registers->childCount(); ++i) {
core_registers->child(i)->setText(
1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetReg(i), 8, 16, QLatin1Char('0')));
1, QStringLiteral("0x%1").arg(core.GetReg(i), 8, 16, QLatin1Char('0')));
}
for (int i = 0; i < vfp_registers->childCount(); ++i)
for (int i = 0; i < vfp_registers->childCount(); ++i) {
vfp_registers->child(i)->setText(
1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetVFPReg(i), 8, 16, QLatin1Char('0')));
1, QStringLiteral("0x%1").arg(core.GetVFPReg(i), 8, 16, QLatin1Char('0')));
}
UpdateCPSRValues();
UpdateVFPSystemRegisterValues();
@ -86,24 +90,29 @@ void RegistersWidget::OnEmulationStarting(EmuThread* emu_thread) {
void RegistersWidget::OnEmulationStopping() {
// Reset widget text
for (int i = 0; i < core_registers->childCount(); ++i)
for (int i = 0; i < core_registers->childCount(); ++i) {
core_registers->child(i)->setText(1, QString{});
}
for (int i = 0; i < vfp_registers->childCount(); ++i)
for (int i = 0; i < vfp_registers->childCount(); ++i) {
vfp_registers->child(i)->setText(1, QString{});
}
for (int i = 0; i < cpsr->childCount(); ++i)
for (int i = 0; i < cpsr->childCount(); ++i) {
cpsr->child(i)->setText(1, QString{});
}
cpsr->setText(1, QString{});
// FPSCR
for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i)
for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i) {
vfp_system_registers->child(0)->child(i)->setText(1, QString{});
}
// FPEXC
for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i)
for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i) {
vfp_system_registers->child(1)->child(i)->setText(1, QString{});
}
vfp_system_registers->child(0)->setText(1, QString{});
vfp_system_registers->child(1)->setText(1, QString{});
@ -130,8 +139,8 @@ void RegistersWidget::CreateCPSRChildren() {
}
void RegistersWidget::UpdateCPSRValues() {
// Todo: Handle all cores
const u32 cpsr_val = Core::GetCore(0).GetCPSR();
// TODO: Handle all cores
const u32 cpsr_val = system.GetCore(0).GetCPSR();
cpsr->setText(1, QStringLiteral("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
cpsr->child(0)->setText(
@ -193,9 +202,10 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
}
void RegistersWidget::UpdateVFPSystemRegisterValues() {
// Todo: handle all cores
const u32 fpscr_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPSCR);
const u32 fpexc_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPEXC);
// TODO: handle all cores
const ARM_Interface& core = system.GetCore(0);
const u32 fpscr_val = core.GetVFPSystemReg(VFP_FPSCR);
const u32 fpexc_val = core.GetVFPSystemReg(VFP_FPEXC);
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
fpscr->setText(1, QStringLiteral("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));

View File

@ -15,11 +15,15 @@ namespace Ui {
class ARMRegisters;
}
namespace Core {
class System;
}
class RegistersWidget : public QDockWidget {
Q_OBJECT
public:
explicit RegistersWidget(QWidget* parent = nullptr);
explicit RegistersWidget(const Core::System& system, QWidget* parent = nullptr);
~RegistersWidget();
public slots:
@ -37,7 +41,7 @@ private:
void UpdateVFPSystemRegisterValues();
std::unique_ptr<Ui::ARMRegisters> cpu_regs_ui;
const Core::System& system;
QTreeWidget* tree;
QTreeWidgetItem* core_registers;

View File

@ -5,11 +5,10 @@
#include <array>
#include "citra_qt/debugger/wait_tree.h"
#include "citra_qt/uisettings.h"
#include "citra_qt/util/util.h"
#include "common/assert.h"
#include "common/settings.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/semaphore.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
@ -76,13 +75,13 @@ std::size_t WaitTreeItem::Row() const {
return row;
}
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {
const u32 num_cores = Core::GetNumCores();
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList(
Core::System& system) {
const u32 num_cores = system.GetNumCores();
std::vector<std::unique_ptr<WaitTreeThread>> item_list;
item_list.reserve(num_cores);
for (u32 i = 0; i < num_cores; ++i) {
const auto& threads =
Core::System::GetInstance().Kernel().GetThreadManager(i).GetThreadList();
const auto threads = system.Kernel().GetThreadManager(i).GetThreadList();
item_list.reserve(item_list.size() + threads.size());
for (std::size_t j = 0; j < threads.size(); ++j) {
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[j]));
@ -436,11 +435,12 @@ void WaitTreeModel::ClearItems() {
thread_items.clear();
}
void WaitTreeModel::InitItems() {
thread_items = WaitTreeItem::MakeThreadItemList();
void WaitTreeModel::InitItems(Core::System& system) {
thread_items = WaitTreeItem::MakeThreadItemList(system);
}
WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), parent) {
WaitTreeWidget::WaitTreeWidget(Core::System& system_, QWidget* parent)
: QDockWidget(tr("Wait Tree"), parent), system{system_} {
setObjectName(QStringLiteral("WaitTreeWidget"));
view = new QTreeView(this);
view->setHeaderHidden(true);
@ -449,9 +449,10 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p
}
void WaitTreeWidget::OnDebugModeEntered() {
if (!Core::System::GetInstance().IsPoweredOn())
if (!system.IsPoweredOn()) {
return;
model->InitItems();
}
model->InitItems(system);
view->setModel(model);
setEnabled(true);
}

View File

@ -23,6 +23,10 @@ class Thread;
class Timer;
} // namespace Kernel
namespace Core {
class System;
}
class WaitTreeThread;
class WaitTreeItem : public QObject {
@ -39,7 +43,7 @@ public:
WaitTreeItem* Parent() const;
std::span<const std::unique_ptr<WaitTreeItem>> Children() 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:
std::size_t row;
@ -166,7 +170,7 @@ public:
int columnCount(const QModelIndex& parent) const override;
void ClearItems();
void InitItems();
void InitItems(Core::System& system);
private:
std::vector<std::unique_ptr<WaitTreeThread>> thread_items;
@ -176,7 +180,7 @@ class WaitTreeWidget : public QDockWidget {
Q_OBJECT
public:
explicit WaitTreeWidget(QWidget* parent = nullptr);
explicit WaitTreeWidget(Core::System& system, QWidget* parent = nullptr);
public slots:
void OnDebugModeEntered();
@ -188,4 +192,5 @@ public slots:
private:
QTreeView* view;
WaitTreeModel* model;
Core::System& system;
};

View File

@ -9,10 +9,11 @@
#include "citra_qt/uisettings.h"
#include "common/common_types.h"
#include "core/core.h"
#include "core/loader/loader.h"
namespace DiscordRPC {
DiscordImpl::DiscordImpl() {
DiscordImpl::DiscordImpl(const Core::System& system_) : system{system_} {
DiscordEventHandlers handlers{};
// The number is the client ID for Citra, it's used for images and the
@ -34,12 +35,15 @@ void DiscordImpl::Update() {
std::chrono::system_clock::now().time_since_epoch())
.count();
std::string title;
if (Core::System::GetInstance().IsPoweredOn())
Core::System::GetInstance().GetAppLoader().ReadTitle(title);
const bool is_powered_on = system.IsPoweredOn();
if (is_powered_on) {
system.GetAppLoader().ReadTitle(title);
}
DiscordRichPresence presence{};
presence.largeImageKey = "citra";
presence.largeImageText = "Citra is an emulator for the Nintendo 3DS";
if (Core::System::GetInstance().IsPoweredOn()) {
if (is_powered_on) {
presence.state = title.c_str();
presence.details = "Currently in game";
} else {

View File

@ -6,15 +6,22 @@
#include "citra_qt/discord.h"
namespace Core {
class System;
}
namespace DiscordRPC {
class DiscordImpl : public DiscordInterface {
public:
DiscordImpl();
DiscordImpl(const Core::System& system);
~DiscordImpl() override;
void Pause() override;
void Update() override;
private:
const Core::System& system;
};
} // namespace DiscordRPC

View File

@ -14,6 +14,7 @@
#include <QtGui>
#include <QtWidgets>
#include <fmt/format.h>
#include "core/telemetry_session.h"
#ifdef __APPLE__
#include <unistd.h> // for chdir
#endif
@ -73,7 +74,6 @@
#include "common/microprofile.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
#include "common/string_util.h"
#if CITRA_ARCH(x86_64)
#include "common/x64/cpu_detect.h"
#endif
@ -173,7 +173,7 @@ static QString PrettyProductName() {
}
GMainWindow::GMainWindow(Core::System& system_)
: ui{std::make_unique<Ui::MainWindow>()}, system{system_}, movie{Core::Movie::GetInstance()},
: ui{std::make_unique<Ui::MainWindow>()}, system{system_}, movie{system.Movie()},
config{std::make_unique<Config>()}, emu_thread{nullptr} {
Common::Log::Initialize();
Common::Log::Start();
@ -353,8 +353,8 @@ void GMainWindow::InitializeWidgets() {
});
InputCommon::Init();
multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room,
ui->action_Show_Room);
multiplayer_state = new MultiplayerState(system, this, game_list->GetModel(),
ui->action_Leave_Room, ui->action_Show_Room);
multiplayer_state->setVisible(false);
#if ENABLE_QT_UPDATER
@ -434,7 +434,7 @@ void GMainWindow::InitializeDebugWidgets() {
debug_menu->addAction(microProfileDialog->toggleViewAction());
#endif
registersWidget = new RegistersWidget(this);
registersWidget = new RegistersWidget(system, this);
addDockWidget(Qt::RightDockWidgetArea, registersWidget);
registersWidget->hide();
debug_menu->addAction(registersWidget->toggleViewAction());
@ -448,7 +448,7 @@ void GMainWindow::InitializeDebugWidgets() {
graphicsWidget->hide();
debug_menu->addAction(graphicsWidget->toggleViewAction());
graphicsCommandsWidget = new GPUCommandListWidget(this);
graphicsCommandsWidget = new GPUCommandListWidget(system.Memory(), this);
addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget);
graphicsCommandsWidget->hide();
debug_menu->addAction(graphicsCommandsWidget->toggleViewAction());
@ -472,7 +472,7 @@ void GMainWindow::InitializeDebugWidgets() {
connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget,
&GraphicsTracingWidget::OnEmulationStopping);
waitTreeWidget = new WaitTreeWidget(this);
waitTreeWidget = new WaitTreeWidget(system, this);
addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
waitTreeWidget->hide();
debug_menu->addAction(waitTreeWidget->toggleViewAction());
@ -490,7 +490,7 @@ void GMainWindow::InitializeDebugWidgets() {
connect(this, &GMainWindow::EmulationStopping, waitTreeWidget,
[this] { lleServiceModulesWidget->setDisabled(false); });
ipcRecorderWidget = new IPCRecorderWidget(this);
ipcRecorderWidget = new IPCRecorderWidget(system, this);
addDockWidget(Qt::RightDockWidgetArea, ipcRecorderWidget);
ipcRecorderWidget->hide();
debug_menu->addAction(ipcRecorderWidget->toggleViewAction());
@ -1413,7 +1413,7 @@ void GMainWindow::UpdateSaveStates() {
if (system.GetAppLoader().ReadProgramId(title_id) != Loader::ResultStatus::Success) {
return;
}
auto savestates = Core::ListSaveStates(title_id);
auto savestates = Core::ListSaveStates(title_id, movie.GetCurrentMovieID());
for (u32 i = 0; i < Core::SaveStateSlotCount; ++i) {
actions_load_state[i]->setEnabled(false);
actions_load_state[i]->setText(tr("Slot %1").arg(i + 1));
@ -2046,7 +2046,6 @@ void GMainWindow::OnLoadAmiibo() {
return;
}
Core::System& system{Core::System::GetInstance()};
Service::SM::ServiceManager& sm = system.ServiceManager();
auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u");
if (nfc == nullptr) {
@ -2118,14 +2117,15 @@ void GMainWindow::OnToggleFilterBar() {
}
void GMainWindow::OnCreateGraphicsSurfaceViewer() {
auto graphicsSurfaceViewerWidget = new GraphicsSurfaceWidget(Pica::g_debug_context, this);
auto graphicsSurfaceViewerWidget =
new GraphicsSurfaceWidget(system.Memory(), Pica::g_debug_context, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsSurfaceViewerWidget);
// TODO: Maybe graphicsSurfaceViewerWidget->setFloating(true);
graphicsSurfaceViewerWidget->show();
}
void GMainWindow::OnRecordMovie() {
MovieRecordDialog dialog(this);
MovieRecordDialog dialog(this, system);
if (dialog.exec() != QDialog::Accepted) {
return;
}
@ -2142,7 +2142,7 @@ void GMainWindow::OnRecordMovie() {
}
void GMainWindow::OnPlayMovie() {
MoviePlayDialog dialog(this, game_list);
MoviePlayDialog dialog(this, game_list, system);
if (dialog.exec() != QDialog::Accepted) {
return;
}
@ -2847,7 +2847,7 @@ void GMainWindow::RetranslateStatusBar() {
void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
#ifdef USE_DISCORD_PRESENCE
if (state) {
discord_rpc = std::make_unique<DiscordRPC::DiscordImpl>();
discord_rpc = std::make_unique<DiscordRPC::DiscordImpl>(system);
} else {
discord_rpc = std::make_unique<DiscordRPC::NullImpl>();
}

View File

@ -15,8 +15,9 @@
#include "core/movie.h"
#include "ui_movie_play_dialog.h"
MoviePlayDialog::MoviePlayDialog(QWidget* parent, GameList* game_list_)
: QDialog(parent), ui(std::make_unique<Ui::MoviePlayDialog>()), game_list(game_list_) {
MoviePlayDialog::MoviePlayDialog(QWidget* parent, GameList* game_list_, const Core::System& system_)
: QDialog(parent),
ui(std::make_unique<Ui::MoviePlayDialog>()), game_list{game_list_}, system{system_} {
ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
@ -26,10 +27,10 @@ MoviePlayDialog::MoviePlayDialog(QWidget* parent, GameList* game_list_)
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &MoviePlayDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &MoviePlayDialog::reject);
if (Core::System::GetInstance().IsPoweredOn()) {
if (system.IsPoweredOn()) {
QString note_text;
note_text = tr("Current running game will be stopped.");
if (Core::Movie::GetInstance().GetPlayMode() == Core::Movie::PlayMode::Recording) {
if (system.Movie().GetPlayMode() == Core::Movie::PlayMode::Recording) {
note_text.append(tr("<br>Current recording will be discarded."));
}
ui->note2Label->setText(note_text);
@ -43,7 +44,7 @@ QString MoviePlayDialog::GetMoviePath() const {
}
QString MoviePlayDialog::GetGamePath() const {
const auto metadata = Core::Movie::GetInstance().GetMovieMetadata(GetMoviePath().toStdString());
const auto metadata = system.Movie().GetMovieMetadata(GetMoviePath().toStdString());
return game_list->FindGameByProgramID(metadata.program_id, GameListItemPath::FullPathRole);
}
@ -67,9 +68,10 @@ void MoviePlayDialog::UpdateUIDisplay() {
ui->lengthLineEdit->clear();
ui->note1Label->setVisible(true);
const auto& movie = system.Movie();
const auto path = GetMoviePath().toStdString();
const auto validation_result = Core::Movie::GetInstance().ValidateMovie(path);
const auto validation_result = movie.ValidateMovie(path);
if (validation_result == Core::Movie::ValidationResult::Invalid) {
ui->note1Label->setText(tr("Invalid movie file."));
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
@ -94,7 +96,7 @@ void MoviePlayDialog::UpdateUIDisplay() {
UNREACHABLE();
}
const auto metadata = Core::Movie::GetInstance().GetMovieMetadata(path);
const auto metadata = movie.GetMovieMetadata(path);
// Format game title
const auto title =

View File

@ -11,11 +11,15 @@ namespace Ui {
class MoviePlayDialog;
}
namespace Core {
class System;
}
class MoviePlayDialog : public QDialog {
Q_OBJECT
public:
explicit MoviePlayDialog(QWidget* parent, GameList* game_list);
explicit MoviePlayDialog(QWidget* parent, GameList* game_list, const Core::System& system);
~MoviePlayDialog() override;
QString GetMoviePath() const;
@ -27,4 +31,5 @@ private:
std::unique_ptr<Ui::MoviePlayDialog> ui;
GameList* game_list;
const Core::System& system;
};

View File

@ -10,8 +10,8 @@
#include "core/movie.h"
#include "ui_movie_record_dialog.h"
MovieRecordDialog::MovieRecordDialog(QWidget* parent)
: QDialog(parent), ui(std::make_unique<Ui::MovieRecordDialog>()) {
MovieRecordDialog::MovieRecordDialog(QWidget* parent, const Core::System& system_)
: QDialog(parent), ui(std::make_unique<Ui::MovieRecordDialog>()), system{system_} {
ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
@ -23,9 +23,9 @@ MovieRecordDialog::MovieRecordDialog(QWidget* parent)
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &MovieRecordDialog::reject);
QString note_text;
if (Core::System::GetInstance().IsPoweredOn()) {
if (system.IsPoweredOn()) {
note_text = tr("Current running game will be restarted.");
if (Core::Movie::GetInstance().GetPlayMode() == Core::Movie::PlayMode::Recording) {
if (system.Movie().GetPlayMode() == Core::Movie::PlayMode::Recording) {
note_text.append(tr("<br>Current recording will be discarded."));
}
} else {

View File

@ -9,11 +9,15 @@ namespace Ui {
class MovieRecordDialog;
}
namespace Core {
class System;
}
class MovieRecordDialog : public QDialog {
Q_OBJECT
public:
explicit MovieRecordDialog(QWidget* parent);
explicit MovieRecordDialog(QWidget* parent, const Core::System& system);
~MovieRecordDialog() override;
QString GetPath() const;
@ -24,4 +28,5 @@ private:
void UpdateUIDisplay();
std::unique_ptr<Ui::MovieRecordDialog> ui;
const Core::System& system;
};

View File

@ -9,10 +9,8 @@
#include <QString>
#include <QtConcurrent/QtConcurrentRun>
#include "citra_qt/main.h"
#include "citra_qt/multiplayer/client_room.h"
#include "citra_qt/multiplayer/direct_connect.h"
#include "citra_qt/multiplayer/message.h"
#include "citra_qt/multiplayer/state.h"
#include "citra_qt/multiplayer/validation.h"
#include "citra_qt/uisettings.h"
#include "core/hle/service/cfg/cfg.h"
@ -22,9 +20,9 @@
enum class ConnectionType : u8 { TraversalServer, IP };
DirectConnectWindow::DirectConnectWindow(QWidget* parent)
DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
ui(std::make_unique<Ui::DirectConnect>()) {
ui(std::make_unique<Ui::DirectConnect>()), system{system_} {
ui->setupUi(this);
@ -91,7 +89,7 @@ void DirectConnectWindow::Connect() {
if (auto room_member = Network::GetRoomMember().lock()) {
auto port = UISettings::values.port.toUInt();
room_member->Join(ui->nickname->text().toStdString(),
Service::CFG::GetConsoleIdHash(Core::System::GetInstance()),
Service::CFG::GetConsoleIdHash(system),
ui->ip->text().toStdString().c_str(), port, 0,
Network::NoPreferredMac, ui->password->text().toStdString().c_str());
}

View File

@ -13,11 +13,15 @@ namespace Ui {
class DirectConnect;
}
namespace Core {
class System;
}
class DirectConnectWindow : public QDialog {
Q_OBJECT
public:
explicit DirectConnectWindow(QWidget* parent = nullptr);
explicit DirectConnectWindow(Core::System& system, QWidget* parent = nullptr);
~DirectConnectWindow();
void RetranslateUi();
@ -39,5 +43,6 @@ private:
QFutureWatcher<void>* watcher;
std::unique_ptr<Ui::DirectConnect> ui;
Core::System& system;
Validation validation;
};

View File

@ -12,7 +12,6 @@
#include <QTime>
#include <QtConcurrent/QtConcurrentRun>
#include "citra_qt/game_list_p.h"
#include "citra_qt/main.h"
#include "citra_qt/multiplayer/host_room.h"
#include "citra_qt/multiplayer/message.h"
#include "citra_qt/multiplayer/state.h"
@ -27,10 +26,10 @@
#include "web_service/verify_user_jwt.h"
#endif
HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
HostRoomWindow::HostRoomWindow(Core::System& system_, QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Network::AnnounceMultiplayerSession> session)
: 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);
// set up validation for all of the fields
@ -196,9 +195,8 @@ void HostRoomWindow::Host() {
}
}
#endif
member->Join(ui->username->text().toStdString(),
Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), "127.0.0.1", port,
0, Network::NoPreferredMac, password, token);
member->Join(ui->username->text().toStdString(), Service::CFG::GetConsoleIdHash(system),
"127.0.0.1", port, 0, Network::NoPreferredMac, password, token);
// Store settings
UISettings::values.room_nickname = ui->username->text();

View File

@ -9,14 +9,16 @@
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include <QVariant>
#include "citra_qt/multiplayer/chat_room.h"
#include "citra_qt/multiplayer/validation.h"
#include "network/network.h"
namespace Ui {
class HostRoom;
}
namespace Core {
class System;
}
namespace Network {
class AnnounceMultiplayerSession;
}
@ -34,7 +36,7 @@ class HostRoomWindow : public QDialog {
Q_OBJECT
public:
explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list,
explicit HostRoomWindow(Core::System& system, QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Network::AnnounceMultiplayerSession> session);
~HostRoomWindow();
@ -50,6 +52,7 @@ private:
std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) const;
std::unique_ptr<Ui::HostRoom> ui;
Core::System& system;
std::weak_ptr<Network::AnnounceMultiplayerSession> announce_multiplayer_session;
QStandardItemModel* game_list;
ComboBoxProxyModel* proxy;

View File

@ -7,11 +7,9 @@
#include <QtConcurrent/QtConcurrentRun>
#include "citra_qt/game_list_p.h"
#include "citra_qt/main.h"
#include "citra_qt/multiplayer/client_room.h"
#include "citra_qt/multiplayer/lobby.h"
#include "citra_qt/multiplayer/lobby_p.h"
#include "citra_qt/multiplayer/message.h"
#include "citra_qt/multiplayer/state.h"
#include "citra_qt/multiplayer/validation.h"
#include "citra_qt/uisettings.h"
#include "common/logging/log.h"
@ -23,10 +21,10 @@
#include "web_service/web_backend.h"
#endif
Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
Lobby::Lobby(Core::System& system_, QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Network::AnnounceMultiplayerSession> session)
: 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);
// setup the watcher for background connections
@ -152,8 +150,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
const std::string verify_UID =
proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString();
// attempt to connect in a different thread
QFuture<void> f = QtConcurrent::run([nickname, ip, port, password, verify_UID] {
// Attempt to connect in a different thread
QFuture<void> f = QtConcurrent::run([this, nickname, ip, port, password, verify_UID] {
std::string token;
#ifdef ENABLE_WEB_SERVICE
if (!NetSettings::values.citra_username.empty() &&
@ -170,8 +168,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
}
#endif
if (auto room_member = Network::GetRoomMember().lock()) {
room_member->Join(nickname, Service::CFG::GetConsoleIdHash(Core::System::GetInstance()),
ip.c_str(), port, 0, Network::NoPreferredMac, password, token);
room_member->Join(nickname, Service::CFG::GetConsoleIdHash(system), ip.c_str(), port, 0,
Network::NoPreferredMac, password, token);
}
});
watcher->setFuture(f);

View File

@ -12,12 +12,16 @@
#include "citra_qt/multiplayer/validation.h"
#include "common/announce_multiplayer_room.h"
#include "network/announce_multiplayer_session.h"
#include "network/network.h"
#include "network/room_member.h"
namespace Ui {
class Lobby;
}
namespace Core {
class System;
}
class LobbyModel;
class LobbyFilterProxyModel;
@ -29,7 +33,7 @@ class Lobby : public QDialog {
Q_OBJECT
public:
explicit Lobby(QWidget* parent, QStandardItemModel* list,
explicit Lobby(Core::System& system, QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Network::AnnounceMultiplayerSession> session);
~Lobby() override;
@ -84,7 +88,9 @@ private:
*/
QString PasswordPrompt();
private:
std::unique_ptr<Ui::Lobby> ui;
Core::System& system;
QStandardItemModel* model{};
QStandardItemModel* game_list{};

View File

@ -17,9 +17,10 @@
#include "citra_qt/util/clickable_label.h"
#include "common/logging/log.h"
MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model,
QAction* leave_room, QAction* show_room)
: QWidget(parent), game_list_model(game_list_model), leave_room(leave_room),
MultiplayerState::MultiplayerState(Core::System& system_, QWidget* parent,
QStandardItemModel* game_list_model, QAction* leave_room,
QAction* show_room)
: QWidget(parent), system{system_}, game_list_model(game_list_model), leave_room(leave_room),
show_room(show_room) {
if (auto member = Network::GetRoomMember().lock()) {
// register the network structs to use in slots and signals
@ -203,14 +204,14 @@ static void BringWidgetToFront(QWidget* widget) {
void MultiplayerState::OnViewLobby() {
if (lobby == nullptr) {
lobby = new Lobby(this, game_list_model, announce_multiplayer_session);
lobby = new Lobby(system, this, game_list_model, announce_multiplayer_session);
}
BringWidgetToFront(lobby);
}
void MultiplayerState::OnCreateRoom() {
if (host_room == nullptr) {
host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session);
host_room = new HostRoomWindow(system, this, game_list_model, announce_multiplayer_session);
}
BringWidgetToFront(host_room);
}
@ -274,7 +275,7 @@ void MultiplayerState::OnOpenNetworkRoom() {
void MultiplayerState::OnDirectConnectToRoom() {
if (direct_connect == nullptr) {
direct_connect = new DirectConnectWindow(this);
direct_connect = new DirectConnectWindow(system, this);
}
BringWidgetToFront(direct_connect);
}

View File

@ -15,12 +15,16 @@ class ClientRoomWindow;
class DirectConnectWindow;
class ClickableLabel;
namespace Core {
class System;
}
class MultiplayerState : public QWidget {
Q_OBJECT;
public:
explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room,
QAction* show_room);
explicit MultiplayerState(Core::System& system, QWidget* parent, QStandardItemModel* game_list,
QAction* leave_room, QAction* show_room);
~MultiplayerState();
/**
@ -71,6 +75,7 @@ signals:
void AnnounceFailed(const Common::WebResult&);
private:
Core::System& system;
Lobby* lobby = nullptr;
HostRoomWindow* host_room = nullptr;
ClientRoomWindow* client_room = nullptr;

View File

@ -130,11 +130,9 @@ bool UpdaterPrivate::StartUpdateCheck() {
main_process->setProgram(tool_info.absoluteFilePath());
main_process->setArguments({QStringLiteral("--checkupdates"), QStringLiteral("-v")});
connect(main_process,
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this,
connect(main_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
&UpdaterPrivate::UpdaterReady, Qt::QueuedConnection);
connect(main_process,
static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::errorOccurred), this,
connect(main_process, qOverload<QProcess::ProcessError>(&QProcess::errorOccurred), this,
&UpdaterPrivate::UpdaterError, Qt::QueuedConnection);
main_process->start(QIODevice::ReadOnly);
@ -156,7 +154,7 @@ void UpdaterPrivate::StopUpdateCheck(int delay, bool async) {
QTimer* timer = new QTimer(this);
timer->setSingleShot(true);
connect(timer, &QTimer::timeout, [this, timer]() {
connect(timer, &QTimer::timeout, this, [this, timer]() {
StopUpdateCheck(0, false);
timer->deleteLater();
});

View File

@ -176,6 +176,9 @@ endif()
if (CITRA_USE_PRECOMPILED_HEADERS)
target_precompile_headers(citra_common PRIVATE precompiled_headers.h)
endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL GNU)
target_link_libraries(citra_common PRIVATE backtrace dl)
find_library(BACKTRACE_LIBRARY backtrace)
if (BACKTRACE_LIBRARY AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL GNU)
target_link_libraries(citra_common PRIVATE ${BACKTRACE_LIBRARY} dl)
target_compile_definitions(citra_common PRIVATE CITRA_LINUX_GCC_BACKTRACE)
endif()

View File

@ -13,12 +13,11 @@
#define _SH_DENYWR 0
#endif
#if defined(__linux__) && defined(__GNUG__) && !defined(__clang__)
#ifdef CITRA_LINUX_GCC_BACKTRACE
#define BOOST_STACKTRACE_USE_BACKTRACE
#include <boost/stacktrace.hpp>
#undef BOOST_STACKTRACE_USE_BACKTRACE
#include <signal.h>
#define CITRA_LINUX_GCC_BACKTRACE
#endif
#include "common/bounded_threadsafe_queue.h"

View File

@ -62,12 +62,29 @@ public:
return SlotId{index};
}
template <typename... Args>
[[nodiscard]] SlotId swap_and_insert(SlotId existing_id, Args&&... args) noexcept {
const u32 index = FreeValueIndex();
T& existing_value = values[existing_id.index].object;
new (&values[index].object) T(std::move(existing_value));
existing_value.~T();
new (&values[existing_id.index].object) T(std::forward<Args>(args)...);
SetStorageBit(index);
return SlotId{index};
}
void erase(SlotId id) noexcept {
values[id.index].object.~T();
free_list.push_back(id.index);
ResetStorageBit(id.index);
}
size_t size() const noexcept {
return values_capacity - free_list.size();
}
private:
struct NonTrivialDummy {
NonTrivialDummy() noexcept {}
@ -93,7 +110,7 @@ private:
return ((stored_bitset[index / 64] >> (index % 64)) & 1) != 0;
}
void ValidateIndex(SlotId id) const noexcept {
void ValidateIndex([[maybe_unused]] SlotId id) const noexcept {
DEBUG_ASSERT(id);
DEBUG_ASSERT(id.index / 64 < stored_bitset.size());
DEBUG_ASSERT(((stored_bitset[id.index / 64] >> (id.index % 64)) & 1) != 0);

View File

@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <exception>
#include <memory>
#include <stdexcept>
#include <utility>
#include <boost/serialization/array.hpp>
@ -16,6 +14,8 @@
#include "core/arm/arm_interface.h"
#include "core/arm/exclusive_monitor.h"
#include "core/hle/service/cam/cam.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/ir/ir_user.h"
#if CITRA_ARCH(x86_64) || CITRA_ARCH(arm64)
#include "core/arm/dynarmic/arm_dynarmic.h"
#endif
@ -35,9 +35,7 @@
#include "core/hle/service/cam/cam.h"
#include "core/hle/service/fs/archive.h"
#include "core/hle/service/gsp/gsp.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/ir/ir_rst.h"
#include "core/hle/service/ir/ir_user.h"
#include "core/hle/service/mic/mic_u.h"
#include "core/hle/service/plgldr/plgldr.h"
#include "core/hle/service/service.h"
@ -48,6 +46,7 @@
#include "core/loader/loader.h"
#include "core/movie.h"
#include "core/rpc/server.h"
#include "core/telemetry_session.h"
#include "network/network.h"
#include "video_core/custom_textures/custom_tex_manager.h"
#include "video_core/renderer_base.h"
@ -72,6 +71,8 @@ Core::Timing& Global() {
return System::GetInstance().CoreTiming();
}
System::System() : movie{*this} {}
System::~System() = default;
System::ResultStatus System::RunLoop(bool tight_loop) {
@ -85,7 +86,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
if (thread && running_core) {
running_core->SaveContext(thread->context);
}
GDBStub::HandlePacket();
GDBStub::HandlePacket(*this);
// If the loop is halted and we want to step, use a tiny (1) number of instructions to
// execute. Otherwise, get out of the loop function.
@ -320,12 +321,12 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, *this);
perf_stats = std::make_unique<PerfStats>(title_id);
if (Settings::values.dump_textures) {
custom_tex_manager->PrepareDumping(title_id);
}
if (Settings::values.custom_textures) {
custom_tex_manager->FindCustomTextures();
}
if (Settings::values.dump_textures) {
custom_tex_manager->WriteConfig();
}
status = ResultStatus::Success;
m_emu_window = &emu_window;
@ -367,12 +368,13 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
const Kernel::New3dsHwCapabilities& n3ds_hw_caps, u32 num_cores) {
LOG_DEBUG(HW_Memory, "initialized OK");
memory = std::make_unique<Memory::MemorySystem>();
memory = std::make_unique<Memory::MemorySystem>(*this);
timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage.GetValue());
kernel = std::make_unique<Kernel::KernelSystem>(
*memory, *timing, [this] { PrepareReschedule(); }, memory_mode, num_cores, n3ds_hw_caps);
*memory, *timing, [this] { PrepareReschedule(); }, memory_mode, num_cores, n3ds_hw_caps,
movie.GetOverrideInitTime());
exclusive_monitor = MakeExclusiveMonitor(*memory, num_cores);
cpu_cores.reserve(num_cores);
@ -508,6 +510,14 @@ const VideoCore::CustomTexManager& System::CustomTexManager() const {
return *custom_tex_manager;
}
Core::Movie& System::Movie() {
return movie;
}
const Core::Movie& System::Movie() const {
return movie;
}
void System::RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector) {
registered_mii_selector = std::move(mii_selector);
}
@ -617,16 +627,14 @@ void System::ApplySettings() {
if (VideoCore::g_renderer) {
auto& settings = VideoCore::g_renderer->Settings();
settings.bg_color_update_requested = true;
settings.sampler_update_requested = true;
settings.shader_update_requested = true;
settings.texture_filter_update_requested = true;
}
if (IsPoweredOn()) {
CoreTiming().UpdateClockSpeed(Settings::values.cpu_clock_percentage.GetValue());
Core::DSP().SetSink(Settings::values.output_type.GetValue(),
Settings::values.output_device.GetValue());
Core::DSP().EnableStretching(Settings::values.enable_audio_stretching.GetValue());
dsp_core->SetSink(Settings::values.output_type.GetValue(),
Settings::values.output_device.GetValue());
dsp_core->EnableStretching(Settings::values.enable_audio_stretching.GetValue());
auto hid = Service::HID::GetModule(*this);
if (hid) {
@ -704,7 +712,7 @@ void System::serialize(Archive& ar, const unsigned int file_version) {
ar&* kernel.get();
VideoCore::serialize(ar, file_version);
if (file_version >= 1) {
ar& Movie::GetInstance();
ar& movie;
}
// This needs to be set from somewhere - might as well be here!

View File

@ -10,18 +10,17 @@
#include <string>
#include <boost/serialization/version.hpp>
#include "common/common_types.h"
#include "core/frontend/applets/mii_selector.h"
#include "core/frontend/applets/swkbd.h"
#include "core/loader/loader.h"
#include "core/memory.h"
#include "core/arm/arm_interface.h"
#include "core/movie.h"
#include "core/perf_stats.h"
#include "core/telemetry_session.h"
class ARM_Interface;
namespace Frontend {
class EmuWindow;
class ImageInterface;
class MiiSelector;
class SoftwareKeyboard;
} // namespace Frontend
namespace Memory {
@ -47,7 +46,9 @@ class ArchiveManager;
namespace Kernel {
class KernelSystem;
}
struct New3dsHwCapabilities;
enum class MemoryMode : u8;
} // namespace Kernel
namespace Cheats {
class CheatEngine;
@ -62,8 +63,13 @@ class CustomTexManager;
class RendererBase;
} // namespace VideoCore
namespace Loader {
class AppLoader;
}
namespace Core {
class TelemetrySession;
class ExclusiveMonitor;
class Timing;
@ -95,6 +101,7 @@ public:
ErrorUnknown ///< Any other error
};
explicit System();
~System();
/**
@ -187,6 +194,10 @@ public:
return *cpu_cores[core_id];
};
[[nodiscard]] const ARM_Interface& GetCore(u32 core_id) const {
return *cpu_cores[core_id];
};
[[nodiscard]] u32 GetNumCores() const {
return static_cast<u32>(cpu_cores.size());
}
@ -258,6 +269,12 @@ public:
/// Gets a const reference to the custom texture cache system
[[nodiscard]] const VideoCore::CustomTexManager& CustomTexManager() const;
/// Gets a reference to the movie recorder
[[nodiscard]] Core::Movie& Movie();
/// Gets a const reference to the movie recorder
[[nodiscard]] const Core::Movie& Movie() const;
/// Video Dumper interface
void RegisterVideoDumper(std::shared_ptr<VideoDumper::Backend> video_dumper);
@ -373,6 +390,9 @@ private:
std::shared_ptr<Frontend::MiiSelector> registered_mii_selector;
std::shared_ptr<Frontend::SoftwareKeyboard> registered_swkbd;
/// Movie recorder
Core::Movie movie;
/// Cheats manager
std::unique_ptr<Cheats::CheatEngine> cheat_engine;
@ -435,10 +455,6 @@ private:
return System::GetInstance().GetNumCores();
}
[[nodiscard]] inline AudioCore::DspInterface& DSP() {
return System::GetInstance().DSP();
}
} // namespace Core
BOOST_CLASS_VERSION(Core::System, 1)

View File

@ -12,8 +12,8 @@
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/swap.h"
#include "core/core.h"
#include "core/file_sys/romfs_reader.h"
#include "core/loader/loader.h"
enum NCSDContentIndex { Main = 0, Manual = 1, DLP = 2, New3DSUpdate = 6, Update = 7 };

View File

@ -36,7 +36,6 @@
#include "core/gdbstub/gdbstub.h"
#include "core/gdbstub/hio.h"
#include "core/hle/kernel/process.h"
#include "core/loader/loader.h"
#include "core/memory.h"
namespace GDBStub {
@ -1035,7 +1034,7 @@ static void RemoveBreakpoint() {
SendReply("OK");
}
void HandlePacket() {
void HandlePacket(Core::System& system) {
if (!IsConnected()) {
if (defer_start) {
ToggleServer(true);
@ -1076,7 +1075,7 @@ void HandlePacket() {
Continue();
return;
case 'F':
HandleHioReply(command_buffer, command_length);
HandleHioReply(system, command_buffer, command_length);
break;
case 'g':
ReadRegisters();

View File

@ -10,6 +10,10 @@
#include "common/common_types.h"
#include "core/hle/kernel/thread.h"
namespace Core {
class System;
}
namespace GDBStub {
/// Breakpoint Method
@ -70,7 +74,7 @@ void Break(bool is_memory_break = false);
bool IsMemoryBreak();
/// Read and handle packet from gdb client.
void HandlePacket();
void HandlePacket(Core::System& system);
/**
* Get the nearest breakpoint of the specified type at the given address.

View File

@ -54,7 +54,7 @@ static void SendErrorReply(int error_code, int retval = -1) {
SendReply(packet.data());
}
void SetHioRequest(const VAddr addr) {
void SetHioRequest(Core::System& system, const VAddr addr) {
if (!IsServerEnabled()) {
LOG_WARNING(Debug_GDBStub, "HIO requested but GDB stub is not running");
return;
@ -69,15 +69,15 @@ void SetHioRequest(const VAddr addr) {
LOG_INFO(Debug_GDBStub, "overwriting existing HIO request that was not sent yet");
}
auto& memory = Core::System::GetInstance().Memory();
const auto process = Core::System::GetInstance().Kernel().GetCurrentProcess();
auto& memory = system.Memory();
const auto process = system.Kernel().GetCurrentProcess();
if (!memory.IsValidVirtualAddress(*process, addr)) {
LOG_WARNING(Debug_GDBStub, "Invalid address for HIO request");
return;
}
memory.ReadBlock(*process, addr, &current_hio_request, sizeof(PackedGdbHioRequest));
memory.ReadBlock(addr, &current_hio_request, sizeof(PackedGdbHioRequest));
if (current_hio_request.magic != std::array{'G', 'D', 'B', '\0'}) {
std::string_view bad_magic{
@ -105,10 +105,11 @@ void SetHioRequest(const VAddr addr) {
Break();
SetCpuHaltFlag(true);
SetCpuStepFlag(false);
Core::GetRunningCore().ClearInstructionCache();
system.GetRunningCore().ClearInstructionCache();
}
void HandleHioReply(const u8* const command_buffer, const u32 command_length) {
void HandleHioReply(Core::System& system, const u8* const command_buffer,
const u32 command_length) {
if (!IsWaitingForHioReply()) {
LOG_WARNING(Debug_GDBStub, "Got HIO reply but never sent a request");
return;
@ -176,8 +177,8 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) {
current_hio_request.retval, current_hio_request.gdb_errno,
current_hio_request.ctrl_c);
const auto process = Core::System::GetInstance().Kernel().GetCurrentProcess();
auto& memory = Core::System::GetInstance().Memory();
const auto process = system.Kernel().GetCurrentProcess();
auto& memory = system.Memory();
// should have been checked when we first initialized the request,
// but just double check again before we write to memory
@ -187,8 +188,7 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) {
return;
}
memory.WriteBlock(*process, current_hio_request_addr, &current_hio_request,
sizeof(PackedGdbHioRequest));
memory.WriteBlock(current_hio_request_addr, &current_hio_request, sizeof(PackedGdbHioRequest));
current_hio_request = {};
current_hio_request_addr = 0;
@ -197,7 +197,7 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) {
// Restore state from before the request came in
SetCpuStepFlag(was_stepping);
SetCpuHaltFlag(was_halted);
Core::GetRunningCore().ClearInstructionCache();
system.GetRunningCore().ClearInstructionCache();
}
bool HandlePendingHioRequestPacket() {

View File

@ -6,6 +6,10 @@
#include "common/common_types.h"
namespace Core {
class System;
}
namespace GDBStub {
/**
@ -47,7 +51,7 @@ static_assert(sizeof(PackedGdbHioRequest) == 152,
*
* @param address The memory address of the \ref PackedGdbHioRequest.
*/
void SetHioRequest(const VAddr address);
void SetHioRequest(Core::System& system, const VAddr address);
/**
* If there is a pending HIO request, send it to the client.
@ -59,6 +63,6 @@ bool HandlePendingHioRequestPacket();
/**
* Process an HIO reply from the client.
*/
void HandleHioReply(const u8* const command_buffer, const u32 command_length);
void HandleHioReply(Core::System& system, const u8* const command_buffer, const u32 command_length);
} // namespace GDBStub

View File

@ -4,6 +4,7 @@
#include <algorithm>
#include <vector>
#include "common/archives.h"
#include "common/assert.h"
#include "common/common_types.h"
#include "core/core.h"

View File

@ -25,13 +25,13 @@ namespace Kernel {
KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
std::function<void()> prepare_reschedule_callback,
MemoryMode memory_mode, u32 num_cores,
const New3dsHwCapabilities& n3ds_hw_caps)
const New3dsHwCapabilities& n3ds_hw_caps, u64 override_init_time)
: memory(memory), timing(timing),
prepare_reschedule_callback(std::move(prepare_reschedule_callback)), memory_mode(memory_mode),
n3ds_hw_caps(n3ds_hw_caps) {
std::generate(memory_regions.begin(), memory_regions.end(),
[] { return std::make_shared<MemoryRegionInfo>(); });
MemoryInit(memory_mode, n3ds_hw_caps.memory_mode);
MemoryInit(memory_mode, n3ds_hw_caps.memory_mode, override_init_time);
resource_limits = std::make_unique<ResourceLimitList>(*this);
for (u32 core_id = 0; core_id < num_cores; ++core_id) {

View File

@ -134,7 +134,8 @@ class KernelSystem {
public:
explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
std::function<void()> prepare_reschedule_callback, MemoryMode memory_mode,
u32 num_cores, const New3dsHwCapabilities& n3ds_hw_caps);
u32 num_cores, const New3dsHwCapabilities& n3ds_hw_caps,
u64 override_init_time = 0);
~KernelSystem();
using PortPair = std::pair<std::shared_ptr<ServerPort>, std::shared_ptr<ClientPort>>;
@ -330,7 +331,7 @@ public:
Core::Timing& timing;
private:
void MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode);
void MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode, u64 override_init_time);
std::function<void()> prepare_reschedule_callback;

View File

@ -37,7 +37,8 @@ static const u32 memory_region_sizes[8][3] = {
{0x0B200000, 0x02E00000, 0x02000000}, // 7
};
void KernelSystem::MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode) {
void KernelSystem::MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode,
u64 override_init_time) {
const bool is_new_3ds = Settings::values.is_new_3ds.GetValue();
u32 mem_type_index = static_cast<u32>(memory_mode);
u32 reported_mem_type = static_cast<u32>(memory_mode);
@ -73,7 +74,7 @@ void KernelSystem::MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode
config_mem.sys_mem_alloc = memory_regions[1]->size;
config_mem.base_mem_alloc = memory_regions[2]->size;
shared_page_handler = std::make_shared<SharedPage::Handler>(timing);
shared_page_handler = std::make_shared<SharedPage::Handler>(timing, override_init_time);
}
std::shared_ptr<MemoryRegionInfo> KernelSystem::GetMemoryRegion(MemoryRegion region) {

View File

@ -19,7 +19,8 @@ namespace boost::serialization {
template <class Archive>
void load_construct_data(Archive& ar, SharedPage::Handler* t, const unsigned int) {
::new (t) SharedPage::Handler(Core::System::GetInstance().CoreTiming());
::new (t) SharedPage::Handler(Core::System::GetInstance().CoreTiming(),
Core::System::GetInstance().Movie().GetOverrideInitTime());
}
template void load_construct_data<iarchive>(iarchive& ar, SharedPage::Handler* t,
const unsigned int);
@ -28,8 +29,7 @@ template void load_construct_data<iarchive>(iarchive& ar, SharedPage::Handler* t
namespace SharedPage {
static std::chrono::seconds GetInitTime() {
const u64 override_init_time = Core::Movie::GetInstance().GetOverrideInitTime();
static std::chrono::seconds GetInitTime(u64 override_init_time) {
if (override_init_time != 0) {
// Override the clock init time with the one in the movie
return std::chrono::seconds(override_init_time);
@ -62,7 +62,7 @@ static std::chrono::seconds GetInitTime() {
}
}
Handler::Handler(Core::Timing& timing) : timing(timing) {
Handler::Handler(Core::Timing& timing, u64 override_init_time) : timing(timing) {
std::memset(&shared_page, 0, sizeof(shared_page));
shared_page.running_hw = 0x1; // product
@ -76,7 +76,7 @@ Handler::Handler(Core::Timing& timing) : timing(timing) {
shared_page.battery_state.is_adapter_connected.Assign(1);
shared_page.battery_state.is_charging.Assign(1);
init_time = GetInitTime();
init_time = GetInitTime(override_init_time);
using namespace std::placeholders;
update_time_event = timing.RegisterEvent("SharedPage::UpdateTimeCallback",

View File

@ -86,7 +86,7 @@ static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE,
class Handler : public BackingMem {
public:
Handler(Core::Timing& timing);
Handler(Core::Timing& timing, u64 override_init_time);
void SetMacAddress(const MacAddress&);

View File

@ -5,6 +5,7 @@
#include <algorithm>
#include <array>
#include <fmt/format.h>
#include "common/archives.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scm_rev.h"
@ -38,7 +39,6 @@
#include "core/hle/lock.h"
#include "core/hle/result.h"
#include "core/hle/service/plgldr/plgldr.h"
#include "core/hle/service/service.h"
namespace Kernel {
@ -1128,7 +1128,7 @@ void SVC::OutputDebugString(VAddr address, s32 len) {
}
if (len == 0) {
GDBStub::SetHioRequest(address);
GDBStub::SetHioRequest(system, address);
return;
}
@ -1953,12 +1953,12 @@ ResultCode SVC::GetProcessList(s32* process_count, VAddr out_process_array,
}
ResultCode SVC::InvalidateInstructionCacheRange(u32 addr, u32 size) {
Core::GetRunningCore().InvalidateCacheRange(addr, size);
system.GetRunningCore().InvalidateCacheRange(addr, size);
return RESULT_SUCCESS;
}
ResultCode SVC::InvalidateEntireInstructionCache() {
Core::GetRunningCore().ClearInstructionCache();
system.GetRunningCore().ClearInstructionCache();
return RESULT_SUCCESS;
}

View File

@ -13,6 +13,7 @@
#include <boost/serialization/split_member.hpp>
#include "common/common_types.h"
#include "common/memory_ref.h"
#include "core/hle/kernel/memory.h"
#include "core/hle/result.h"
#include "core/memory.h"
#include "core/mmio.h"

View File

@ -4,6 +4,7 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/act/act.h"
#include "core/hle/service/act/act_a.h"
#include "core/hle/service/act/act_u.h"

View File

@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/archives.h"
#include "common/file_util.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/frontend/input.h"

View File

@ -33,6 +33,8 @@
#include "core/hle/service/service.h"
#include "core/hw/aes/ccm.h"
#include "core/hw/aes/key.h"
#include "core/loader/loader.h"
#include "core/telemetry_session.h"
SERVICE_CONSTRUCT_IMPL(Service::APT::Module)

View File

@ -6,9 +6,9 @@
#include <cstring>
#include <ctime>
#include <vector>
#include "common/archives.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/result.h"

View File

@ -150,7 +150,7 @@ void Module::UpdatePadCallback(std::uintptr_t user_data, s64 cycles_late) {
circle_pad_old_y.erase(circle_pad_old_y.begin());
circle_pad_old_y.push_back(circle_pad_new_y);
Core::Movie::GetInstance().HandlePadAndCircleStatus(state, circle_pad_x, circle_pad_y);
system.Movie().HandlePadAndCircleStatus(state, circle_pad_x, circle_pad_y);
const DirectionState direction = GetStickDirectionState(circle_pad_x, circle_pad_y);
state.circle_up.Assign(direction.up);
@ -200,7 +200,7 @@ void Module::UpdatePadCallback(std::uintptr_t user_data, s64 cycles_late) {
touch_entry.y = static_cast<u16>(y * Core::kScreenBottomHeight);
touch_entry.valid.Assign(pressed ? 1 : 0);
Core::Movie::GetInstance().HandleTouchStatus(touch_entry);
system.Movie().HandleTouchStatus(touch_entry);
// TODO(bunnei): We're not doing anything with offset 0xA8 + 0x18 of HID SharedMemory, which
// supposedly is "Touch-screen entry, which contains the raw coordinate data prior to being
@ -246,7 +246,7 @@ void Module::UpdateAccelerometerCallback(std::uintptr_t user_data, s64 cycles_la
accelerometer_entry.y = static_cast<s16>(accel.y);
accelerometer_entry.z = static_cast<s16>(accel.z);
Core::Movie::GetInstance().HandleAccelerometerStatus(accelerometer_entry);
system.Movie().HandleAccelerometerStatus(accelerometer_entry);
// Make up "raw" entry
// TODO(wwylele):
@ -287,7 +287,7 @@ void Module::UpdateGyroscopeCallback(std::uintptr_t user_data, s64 cycles_late)
gyroscope_entry.y = static_cast<s16>(gyro.y);
gyroscope_entry.z = static_cast<s16>(gyro.z);
Core::Movie::GetInstance().HandleGyroscopeStatus(gyroscope_entry);
system.Movie().HandleGyroscopeStatus(gyroscope_entry);
// Make up "raw" entry
mem->gyroscope.raw_entry.x = gyroscope_entry.x;

View File

@ -31,6 +31,10 @@ namespace Core {
class System;
}
namespace IPC {
class RequestParser;
}
namespace Service::HTTP {
enum class RequestMethod : u8 {
@ -362,6 +366,37 @@ private:
void SetProxyDefault(Kernel::HLERequestContext& ctx);
/**
* HTTP_C::ReceiveData service function
* Inputs:
* 1 : Context handle
* 2 : Buffer size
* 3 : (OutSize<<4) | 12
* 4 : Output data pointer
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void ReceiveData(Kernel::HLERequestContext& ctx);
/**
* HTTP_C::ReceiveDataTimeout service function
* Inputs:
* 1 : Context handle
* 2 : Buffer size
* 3-4 : u64 nanoseconds delay
* 5 : (OutSize<<4) | 12
* 6 : Output data pointer
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void ReceiveDataTimeout(Kernel::HLERequestContext& ctx);
/**
* ReceiveDataImpl:
* Implements ReceiveData and ReceiveDataTimeout service functions
*/
void ReceiveDataImpl(Kernel::HLERequestContext& ctx, bool timeout);
/**
* HTTP_C::AddRequestHeader service function
* Inputs:

View File

@ -5,8 +5,6 @@
#include <fmt/format.h>
#include "common/alignment.h"
#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/service/ir/extra_hid.h"
#include "core/movie.h"
@ -65,7 +63,8 @@ enum class ResponseID : u8 {
ReadCalibrationData = 0x11,
};
ExtraHID::ExtraHID(SendFunc send_func, Core::Timing& timing) : IRDevice(send_func), timing(timing) {
ExtraHID::ExtraHID(SendFunc send_func, Core::Timing& timing_, Core::Movie& movie_)
: IRDevice(send_func), timing{timing_}, movie{movie_} {
LoadInputDevices();
// The data below was retrieved from a New 3DS
@ -249,7 +248,7 @@ void ExtraHID::SendHIDStatus() {
response.buttons.r_not_held.Assign(1);
response.unknown = 0;
Core::Movie::GetInstance().HandleExtraHidResponse(response);
movie.HandleExtraHidResponse(response);
std::vector<u8> response_buffer(sizeof(response));
memcpy(response_buffer.data(), &response, sizeof(response));

View File

@ -16,6 +16,7 @@
namespace Core {
struct TimingEventType;
class Timing;
class Movie;
} // namespace Core
namespace Service::IR {
@ -43,7 +44,7 @@ static_assert(sizeof(ExtraHIDResponse) == 6, "HID status response has wrong size
*/
class ExtraHID final : public IRDevice {
public:
explicit ExtraHID(SendFunc send_func, Core::Timing& timing);
explicit ExtraHID(SendFunc send_func, Core::Timing& timing, Core::Movie& movie);
~ExtraHID();
void OnConnect() override;
@ -60,6 +61,7 @@ private:
void LoadInputDevices();
Core::Timing& timing;
Core::Movie& movie;
u8 hid_period;
Core::TimingEventType* hid_polling_callback_id;
std::array<u8, 0x40> calibration_data;

View File

@ -83,7 +83,7 @@ void IR_RST::UpdateCallback(std::uintptr_t user_data, s64 cycles_late) {
s16 c_stick_x = static_cast<s16>(c_stick_x_f * MAX_CSTICK_RADIUS);
s16 c_stick_y = static_cast<s16>(c_stick_y_f * MAX_CSTICK_RADIUS);
Core::Movie::GetInstance().HandleIrRst(state, c_stick_x, c_stick_y);
system.Movie().HandleIrRst(state, c_stick_x, c_stick_y);
if (!raw_c_stick) {
const HID::DirectionState direction = HID::GetStickDirectionState(c_stick_x, c_stick_y);

View File

@ -9,7 +9,7 @@
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <fmt/format.h>
#include "common/string_util.h"
#include "common/archives.h"
#include "common/swap.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
@ -467,7 +467,7 @@ IR_USER::IR_USER(Core::System& system) : ServiceFramework("ir:USER", 1) {
receive_event = system.Kernel().CreateEvent(ResetType::OneShot, "IR:ReceiveEvent");
extra_hid = std::make_unique<ExtraHID>([this](std::span<const u8> data) { PutToReceive(data); },
system.CoreTiming());
system.CoreTiming(), system.Movie());
}
IR_USER::~IR_USER() {

View File

@ -7,13 +7,14 @@
#include <boost/crc.hpp>
#include <cryptopp/osrng.h>
#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/kernel/shared_page.h"
#include "core/hle/service/nfc/amiibo_crypto.h"
#include "core/hle/service/nfc/nfc_device.h"
#include "core/hw/aes/key.h"
#include "core/loader/loader.h"
SERVICE_CONSTRUCT_IMPL(Service::NFC::NfcDevice)

View File

@ -6,6 +6,7 @@
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/nim/nim_u.h"
SERVICE_CONSTRUCT_IMPL(Service::NIM::NIM_U)

View File

@ -53,6 +53,7 @@
#include "core/hle/service/sm/srv.h"
#include "core/hle/service/soc/soc_u.h"
#include "core/hle/service/ssl/ssl_c.h"
#include "core/loader/loader.h"
namespace Service {

View File

@ -14,7 +14,6 @@
#include "common/file_util.h"
#include "core/file_sys/romfs_reader.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
namespace Kernel {
struct AddressMapping;

View File

@ -27,6 +27,7 @@
#include "core/loader/smdh.h"
#include "core/memory.h"
#include "core/system_titles.h"
#include "core/telemetry_session.h"
#include "network/network.h"
namespace Loader {

View File

@ -17,9 +17,7 @@
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/global.h"
#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h"
#include "core/hle/lock.h"
#include "core/hle/service/plgldr/plgldr.h"
#include "core/hw/hw.h"
#include "core/memory.h"
@ -89,12 +87,13 @@ private:
class MemorySystem::Impl {
public:
// Visual Studio would try to allocate these on compile time if they are std::array, which would
// exceed the memory limit.
// Visual Studio would try to allocate these on compile time
// if they are std::array which would exceed the memory limit.
std::unique_ptr<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[]> n3ds_extra_ram = std::make_unique<u8[]>(Memory::N3DS_EXTRA_RAM_SIZE);
Core::System& system;
std::shared_ptr<PageTable> current_page_table = nullptr;
RasterizerCacheMarker cache_marker;
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> dsp_mem;
Impl();
Impl(Core::System& system_);
const u8* GetPtr(Region r) const {
switch (r) {
@ -153,6 +152,10 @@ public:
}
}
u32 GetPC() const noexcept {
return system.GetRunningCore().GetPC();
}
/**
* This function should only be called for virtual addreses with attribute `PageType::Special`.
*/
@ -187,7 +190,7 @@ public:
HW_Memory,
"unmapped ReadBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
"0x{:08X}",
current_vaddr, src_addr, size, Core::GetRunningCore().GetPC());
current_vaddr, src_addr, size, GetPC());
std::memset(dest_buffer, 0, copy_amount);
break;
}
@ -242,7 +245,7 @@ public:
HW_Memory,
"unmapped WriteBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
"0x{:08X}",
current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC());
current_vaddr, dest_addr, size, GetPC());
break;
}
case PageType::Memory: {
@ -345,13 +348,13 @@ private:
friend class boost::serialization::access;
};
MemorySystem::Impl::Impl()
: fcram_mem(std::make_shared<BackingMemImpl<Region::FCRAM>>(*this)),
MemorySystem::Impl::Impl(Core::System& system_)
: system{system_}, fcram_mem(std::make_shared<BackingMemImpl<Region::FCRAM>>(*this)),
vram_mem(std::make_shared<BackingMemImpl<Region::VRAM>>(*this)),
n3ds_extra_ram_mem(std::make_shared<BackingMemImpl<Region::N3DS>>(*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;
template <class Archive>
@ -467,7 +470,7 @@ T MemorySystem::Read(const VAddr vaddr) {
switch (type) {
case PageType::Unmapped:
LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X} at PC 0x{:08X}", sizeof(T) * 8, vaddr,
Core::GetRunningCore().GetPC());
impl->GetPC());
return 0;
case PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr);
@ -518,7 +521,7 @@ void MemorySystem::Write(const VAddr vaddr, const T data) {
switch (type) {
case PageType::Unmapped:
LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}",
sizeof(data) * 8, (u32)data, vaddr, Core::GetRunningCore().GetPC());
sizeof(data) * 8, (u32)data, vaddr, impl->GetPC());
return;
case PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr);
@ -550,7 +553,7 @@ bool MemorySystem::WriteExclusive(const VAddr vaddr, const T data, const T expec
switch (type) {
case PageType::Unmapped:
LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}",
sizeof(data) * 8, (u32)data, vaddr, Core::GetRunningCore().GetPC());
sizeof(data) * 8, static_cast<u32>(data), vaddr, impl->GetPC());
return true;
case PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr);
@ -606,8 +609,7 @@ u8* MemorySystem::GetPointer(const VAddr vaddr) {
return GetPointerForRasterizerCache(vaddr);
}
LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x} at PC 0x{:08X}", vaddr,
Core::GetRunningCore().GetPC());
LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x} at PC 0x{:08X}", vaddr, impl->GetPC());
return nullptr;
}
@ -663,7 +665,7 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const {
if (area == memory_areas.end()) {
LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#08X} at PC {:#08X}", address,
Core::GetRunningCore().GetPC());
impl->GetPC());
return nullptr;
}
@ -693,8 +695,7 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const {
return {target_mem, offset_into_region};
}
/// For a rasterizer-accessible PAddr, gets a list of all possible VAddr
static std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr) {
std::vector<VAddr> MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr addr) {
if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
return {addr - VRAM_PADDR + VRAM_VADDR};
}
@ -714,7 +715,7 @@ static std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr) {
// parts of the texture.
LOG_ERROR(HW_Memory,
"Trying to use invalid physical address for rasterizer: {:08X} at PC 0x{:08X}", addr,
Core::GetRunningCore().GetPC());
impl->GetPC());
return {};
}
@ -729,7 +730,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached
for (unsigned i = 0; i < num_pages; ++i, paddr += CITRA_PAGE_SIZE) {
for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) {
impl->cache_marker.Mark(vaddr, cached);
for (auto page_table : impl->page_table_list) {
for (auto& page_table : impl->page_table_list) {
PageType& page_type = page_table->attributes[vaddr >> CITRA_PAGE_BITS];
if (cached) {
@ -868,7 +869,7 @@ void MemorySystem::ReadBlock(const Kernel::Process& process, const VAddr src_add
}
void MemorySystem::ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) {
const auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess();
const auto& process = *impl->system.Kernel().GetCurrentProcess();
return impl->ReadBlockImpl<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,
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);
}
@ -934,7 +935,7 @@ void MemorySystem::ZeroBlock(const Kernel::Process& process, const VAddr dest_ad
LOG_ERROR(HW_Memory,
"unmapped ZeroBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
"0x{:08X}",
current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC());
current_vaddr, dest_addr, size, impl->GetPC());
break;
}
case PageType::Memory: {
@ -989,7 +990,7 @@ void MemorySystem::CopyBlock(const Kernel::Process& dest_process,
LOG_ERROR(HW_Memory,
"unmapped CopyBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
"0x{:08X}",
current_vaddr, src_addr, size, Core::GetRunningCore().GetPC());
current_vaddr, src_addr, size, impl->GetPC());
ZeroBlock(dest_process, dest_addr, copy_amount);
break;
}

View File

@ -18,6 +18,10 @@ namespace Kernel {
class Process;
}
namespace Core {
class System;
}
namespace AudioCore {
class DspInterface;
}
@ -287,7 +291,7 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode);
class MemorySystem {
public:
MemorySystem();
explicit MemorySystem(Core::System& system);
~MemorySystem();
/**
@ -575,6 +579,9 @@ public:
*/
void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached);
/// For a rasterizer-accessible PAddr, gets a list of all possible VAddr
std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr);
/// Gets a pointer to the memory region beginning at the specified physical address.
u8* GetPhysicalPointer(PAddr address) const;
@ -627,6 +634,7 @@ private:
void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type);
private:
class Impl;
std::unique_ptr<Impl> impl;

View File

@ -10,13 +10,11 @@
#include <boost/optional.hpp>
#include <cryptopp/hex.h>
#include <cryptopp/osrng.h>
#include <fmt/format.h>
#include "common/archives.h"
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
#include "common/string_util.h"
#include "common/swap.h"
#include "common/timer.h"
#include "core/core.h"
@ -24,12 +22,11 @@
#include "core/hle/service/ir/extra_hid.h"
#include "core/hle/service/ir/ir_rst.h"
#include "core/hw/gpu.h"
#include "core/loader/loader.h"
#include "core/movie.h"
namespace Core {
/*static*/ Movie Movie::s_instance;
enum class ControllerStateType : u8 {
PadAndCircle,
Touch,
@ -146,6 +143,10 @@ static u64 GetInputCount(std::span<const u8> input) {
return input_count;
}
Movie::Movie(const Core::System& system_) : system{system_} {}
Movie::~Movie() = default;
template <class Archive>
void Movie::serialize(Archive& ar, const unsigned int file_version) {
// Only serialize what's needed to make savestates useful for TAS:
@ -565,7 +566,7 @@ void Movie::StartRecording(const std::string& movie_file, const std::string& aut
// Get program ID
program_id = 0;
Core::System::GetInstance().GetAppLoader().ReadProgramId(program_id);
system.GetAppLoader().ReadProgramId(program_id);
LOG_INFO(Movie, "Enabling Movie recording, ID: {:016X}", id);
}

View File

@ -23,25 +23,29 @@ union PadState;
} // namespace Service
namespace Core {
class System;
struct CTMHeader;
struct ControllerState;
class Movie {
public:
enum class PlayMode { None, Recording, Playing, MovieFinished };
enum class ValidationResult {
enum class PlayMode : u32 {
None,
Recording,
Playing,
MovieFinished,
};
enum class ValidationResult : u32 {
OK,
RevisionDismatch,
InputCountDismatch,
Invalid,
};
/**
* Gets the instance of the Movie singleton class.
* @returns Reference to the instance of the Movie singleton class.
*/
static Movie& GetInstance() {
return s_instance;
}
explicit Movie(const Core::System& system);
~Movie();
void SetPlaybackCompletionCallback(std::function<void()> completion_callback);
void StartPlayback(const std::string& movie_file);
@ -133,8 +137,6 @@ public:
void SaveMovie();
private:
static Movie s_instance;
void CheckInputEnd();
template <typename... Targs>
@ -159,6 +161,8 @@ private:
ValidationResult ValidateHeader(const CTMHeader& header) const;
ValidationResult ValidateInput(std::span<const u8> input, u64 expected_count) const;
private:
const Core::System& system;
PlayMode play_mode;
std::string record_movie_file;

View File

@ -3,11 +3,14 @@
// Refer to the license.txt file included.
#include <chrono>
#include <sstream>
#include <cryptopp/hex.h>
#include <fmt/format.h>
#include "common/archives.h"
#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
#include "common/swap.h"
#include "common/zstd_compression.h"
#include "core/core.h"
#include "core/movie.h"
@ -30,8 +33,7 @@ static_assert(sizeof(CSTHeader) == 256, "CSTHeader should be 256 bytes");
constexpr std::array<u8, 4> header_magic_bytes{{'C', 'S', 'T', 0x1B}};
static std::string GetSaveStatePath(u64 program_id, u32 slot) {
const u64 movie_id = Movie::GetInstance().GetCurrentMovieID();
static std::string GetSaveStatePath(u64 program_id, u64 movie_id, u32 slot) {
if (movie_id) {
return fmt::format("{}{:016X}.movie{:016X}.{:02d}.cst",
FileUtil::GetUserPath(FileUtil::UserPath::StatesDir), program_id,
@ -43,8 +45,8 @@ static std::string GetSaveStatePath(u64 program_id, u32 slot) {
}
static bool ValidateSaveState(const CSTHeader& header, SaveStateInfo& info, u64 program_id,
u32 slot) {
const auto path = GetSaveStatePath(program_id, slot);
u64 movie_id, u32 slot) {
const auto path = GetSaveStatePath(program_id, movie_id, slot);
if (header.filetype != header_magic_bytes) {
LOG_WARNING(Core, "Invalid save state file {}", path);
return false;
@ -66,11 +68,11 @@ static bool ValidateSaveState(const CSTHeader& header, SaveStateInfo& info, u64
return true;
}
std::vector<SaveStateInfo> ListSaveStates(u64 program_id) {
std::vector<SaveStateInfo> ListSaveStates(u64 program_id, u64 movie_id) {
std::vector<SaveStateInfo> result;
result.reserve(SaveStateSlotCount);
for (u32 slot = 1; slot <= SaveStateSlotCount; ++slot) {
const auto path = GetSaveStatePath(program_id, slot);
const auto path = GetSaveStatePath(program_id, movie_id, slot);
if (!FileUtil::Exists(path)) {
continue;
}
@ -92,7 +94,7 @@ std::vector<SaveStateInfo> ListSaveStates(u64 program_id) {
LOG_ERROR(Core, "Could not read from file {}", path);
continue;
}
if (!ValidateSaveState(header, info, program_id, slot)) {
if (!ValidateSaveState(header, info, program_id, movie_id, slot)) {
continue;
}
@ -111,7 +113,8 @@ void System::SaveState(u32 slot) const {
const auto data = std::span<const u8>{reinterpret_cast<const u8*>(str.data()), str.size()};
auto buffer = Common::Compression::CompressDataZSTDDefault(data);
const auto path = GetSaveStatePath(title_id, slot);
const u64 movie_id = movie.GetCurrentMovieID();
const auto path = GetSaveStatePath(title_id, movie_id, slot);
if (!FileUtil::CreateFullPath(path)) {
throw std::runtime_error("Could not create path " + path);
}
@ -143,7 +146,8 @@ void System::LoadState(u32 slot) {
throw std::runtime_error("Unable to load while connected to multiplayer");
}
const auto path = GetSaveStatePath(title_id, slot);
const u64 movie_id = movie.GetCurrentMovieID();
const auto path = GetSaveStatePath(title_id, movie_id, slot);
std::vector<u8> decompressed;
{
@ -159,7 +163,7 @@ void System::LoadState(u32 slot) {
// validate header
SaveStateInfo info;
if (!ValidateSaveState(header, info, title_id, slot)) {
if (!ValidateSaveState(header, info, title_id, movie_id, slot)) {
throw std::runtime_error("Invalid savestate");
}

View File

@ -20,6 +20,6 @@ struct SaveStateInfo {
constexpr u32 SaveStateSlotCount = 10; // Maximum count of savestate slots
std::vector<SaveStateInfo> ListSaveStates(u64 program_id);
std::vector<SaveStateInfo> ListSaveStates(u64 program_id, u64 movie_id);
} // namespace Core

View File

@ -11,6 +11,7 @@
#include "common/scm_rev.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/loader/loader.h"
#include "core/telemetry_session.h"
#include "network/network_settings.h"

View File

@ -20,7 +20,8 @@
#include "audio_fixures.h"
TEST_CASE("DSP HLE Audio Decoder", "[audio_core]") {
Memory::MemorySystem memory;
Core::System system;
Memory::MemorySystem memory{system};
SECTION("decoder should produce correct samples") {
auto decoder =
#ifdef HAVE_MF

View File

@ -7,14 +7,17 @@
#include "audio_core/hle/hle.h"
#include "audio_core/lle/lle.h"
#include "common/common_paths.h"
#include "common/file_util.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/memory.h"
TEST_CASE("DSP LLE vs HLE", "[audio_core][hle]") {
Memory::MemorySystem hle_memory;
Core::System system;
Memory::MemorySystem hle_memory{system};
Core::Timing hle_core_timing(1, 100);
Memory::MemorySystem lle_memory;
Memory::MemorySystem lle_memory{system};
Core::Timing lle_core_timing(1, 100);
AudioCore::DspHle hle(hle_memory, hle_core_timing);

View File

@ -6,11 +6,14 @@
#include "audio_core/hle/decoder.h"
#include "audio_core/lle/lle.h"
#include "common/common_paths.h"
#include "common/file_util.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/memory.h"
TEST_CASE("DSP LLE Sanity", "[audio_core][lle]") {
Memory::MemorySystem memory;
Core::System system;
Memory::MemorySystem memory{system};
Core::Timing core_timing(1, 100);
AudioCore::DspLle lle(memory, core_timing, true);

View File

@ -16,7 +16,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
: mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) {
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>(
*memory, *timing, [] {}, Kernel::MemoryMode::Prod, 1,
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});

View File

@ -85,6 +85,7 @@ private:
std::vector<WriteRecord> write_records;
std::unique_ptr<Core::Timing> timing;
std::unique_ptr<Core::System> system;
std::unique_ptr<Memory::MemorySystem> memory;
std::unique_ptr<Kernel::KernelSystem> kernel;
};

View File

@ -3,12 +3,10 @@
// Refer to the license.txt file included.
#include <catch2/catch_test_macros.hpp>
#include "common/archives.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/ipc.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
@ -23,7 +21,8 @@ static std::shared_ptr<Object> MakeObject(Kernel::KernelSystem& kernel) {
TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") {
Core::Timing timing(1, 100);
Memory::MemorySystem memory;
Core::System system;
Memory::MemorySystem memory{system};
Kernel::KernelSystem kernel(
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});
@ -247,7 +246,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
Core::Timing timing(1, 100);
Memory::MemorySystem memory;
Core::System system;
Memory::MemorySystem memory{system};
Kernel::KernelSystem kernel(
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});

View File

@ -3,13 +3,15 @@
// Refer to the license.txt file included.
#include <catch2/catch_test_macros.hpp>
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/process.h"
#include "core/memory.h"
TEST_CASE("memory.IsValidVirtualAddress", "[core][memory]") {
Core::Timing timing(1, 100);
Memory::MemorySystem memory;
Core::System system;
Memory::MemorySystem memory{system};
Kernel::KernelSystem kernel(
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});

View File

@ -4,9 +4,9 @@
#include <vector>
#include <catch2/catch_test_macros.hpp>
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/vm_manager.h"
#include "core/memory.h"
@ -15,7 +15,8 @@ TEST_CASE("Memory Basics", "[kernel][memory]") {
auto mem = std::make_shared<BufferMem>(Memory::CITRA_PAGE_SIZE);
MemoryRef block{mem};
Core::Timing timing(1, 100);
Memory::MemorySystem memory;
Core::System system;
Memory::MemorySystem memory{system};
Kernel::KernelSystem kernel(
memory, timing, [] {}, Kernel::MemoryMode::Prod, 1,
Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy});

View File

@ -34,7 +34,6 @@ add_library(video_core STATIC
regs_texturing.h
renderer_base.cpp
renderer_base.h
rasterizer_cache/framebuffer_base.cpp
rasterizer_cache/framebuffer_base.h
rasterizer_cache/pixel_format.cpp
rasterizer_cache/pixel_format.h
@ -76,6 +75,8 @@ add_library(video_core STATIC
renderer_opengl/gl_state.h
renderer_opengl/gl_stream_buffer.cpp
renderer_opengl/gl_stream_buffer.h
renderer_opengl/gl_texture_mailbox.cpp
renderer_opengl/gl_texture_mailbox.h
renderer_opengl/gl_texture_runtime.cpp
renderer_opengl/gl_texture_runtime.h
renderer_opengl/gl_vars.cpp

View File

@ -11,6 +11,8 @@
#include "common/texture.h"
#include "core/core.h"
#include "core/frontend/image_interface.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "video_core/custom_textures/custom_tex_manager.h"
#include "video_core/rasterizer_cache/surface_params.h"
#include "video_core/rasterizer_cache/utils.h"
@ -88,19 +90,12 @@ void CustomTexManager::FindCustomTextures() {
CreateWorkers();
}
const u64 program_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
const std::string load_path =
fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::LoadDir), program_id);
if (!FileUtil::Exists(load_path)) {
FileUtil::CreateFullPath(load_path);
const u64 title_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
const auto textures = GetTextures(title_id);
if (!ReadConfig(title_id)) {
use_new_hash = false;
skip_mipmap = true;
}
ReadConfig(load_path);
FileUtil::FSTEntry texture_dir;
std::vector<FileUtil::FSTEntry> textures;
FileUtil::ScanDirectoryTree(load_path, texture_dir, 64);
FileUtil::GetAllFilesFromNestedEntries(texture_dir, textures);
custom_textures.reserve(textures.size());
for (const FileUtil::FSTEntry& file : textures) {
@ -135,8 +130,8 @@ bool CustomTexManager::ParseFilename(const FileUtil::FSTEntry& file, CustomTextu
if (file_format == CustomFileFormat::None) {
return false;
}
if (file_format == CustomFileFormat::DDS && refuse_dds) {
LOG_ERROR(Render, "Legacy pack is attempting to use DDS textures, skipping!");
if (file_format == CustomFileFormat::DDS && skip_mipmap) {
LOG_ERROR(Render, "Mipmap skip is incompatible with DDS textures, skipping!");
return false;
}
texture->file_format = file_format;
@ -174,10 +169,14 @@ bool CustomTexManager::ParseFilename(const FileUtil::FSTEntry& file, CustomTextu
return true;
}
void CustomTexManager::WriteConfig() {
const u64 program_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
void CustomTexManager::PrepareDumping(u64 title_id) {
// If a pack exists in the load folder that uses the old hash
// dump textures using the old hash.
ReadConfig(title_id, true);
// Write template config file
const std::string dump_path =
fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::DumpDir), program_id);
fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::DumpDir), title_id);
const std::string pack_config = dump_path + "pack.json";
if (FileUtil::Exists(pack_config)) {
return;
@ -305,18 +304,23 @@ bool CustomTexManager::Decode(Material* material, std::function<bool()>&& upload
return false;
}
void CustomTexManager::ReadConfig(const std::string& load_path) {
bool CustomTexManager::ReadConfig(u64 title_id, bool options_only) {
const std::string load_path =
fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::LoadDir), title_id);
if (!FileUtil::Exists(load_path)) {
FileUtil::CreateFullPath(load_path);
}
const std::string config_path = load_path + "pack.json";
FileUtil::IOFile config_file{config_path, "r"};
if (!config_file.IsOpen()) {
LOG_INFO(Render, "Unable to find pack config file, using legacy defaults");
refuse_dds = true;
return;
return false;
}
std::string config(config_file.GetSize(), '\0');
const std::size_t read_size = config_file.ReadBytes(config.data(), config.size());
if (!read_size) {
return;
return false;
}
nlohmann::json json = nlohmann::json::parse(config, nullptr, false, true);
@ -325,7 +329,10 @@ void CustomTexManager::ReadConfig(const std::string& load_path) {
skip_mipmap = options["skip_mipmap"].get<bool>();
flip_png_files = options["flip_png_files"].get<bool>();
use_new_hash = options["use_new_hash"].get<bool>();
refuse_dds = skip_mipmap || !use_new_hash;
if (options_only) {
return true;
}
const auto& textures = json["textures"];
for (const auto& material : textures.items()) {
@ -353,6 +360,21 @@ void CustomTexManager::ReadConfig(const std::string& load_path) {
LOG_ERROR(Render, "Material with key {} is invalid", material.key());
}
}
return true;
}
std::vector<FileUtil::FSTEntry> CustomTexManager::GetTextures(u64 title_id) {
const std::string load_path =
fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::LoadDir), title_id);
if (!FileUtil::Exists(load_path)) {
FileUtil::CreateFullPath(load_path);
}
FileUtil::FSTEntry texture_dir;
std::vector<FileUtil::FSTEntry> textures;
FileUtil::ScanDirectoryTree(load_path, texture_dir, 64);
FileUtil::GetAllFilesFromNestedEntries(texture_dir, textures);
return textures;
}
void CustomTexManager::CreateWorkers() {

Some files were not shown because too many files have changed in this diff Show More