mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Sources: Run clang-format on everything.
This commit is contained in:
		
							parent
							
								
									fe948af095
								
							
						
					
					
						commit
						dc8479928c
					
				
					 386 changed files with 19560 additions and 18080 deletions
				
			
		|  | @ -22,13 +22,13 @@ | |||
| #include "video_core/debug_utils/debug_utils.h" | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
| #define APP_NAME        "citra" | ||||
| #define APP_VERSION     "0.1-" VERSION | ||||
| #define APP_TITLE       APP_NAME " " APP_VERSION | ||||
| #define COPYRIGHT       "Copyright (C) 2013-2014 Citra Team" | ||||
| #define APP_NAME "citra" | ||||
| #define APP_VERSION "0.1-" VERSION | ||||
| #define APP_TITLE APP_NAME " " APP_VERSION | ||||
| #define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" | ||||
| 
 | ||||
| EmuThread::EmuThread(GRenderWindow* render_window) : | ||||
|     exec_step(false), running(false), stop_run(false), render_window(render_window) { | ||||
| EmuThread::EmuThread(GRenderWindow* render_window) | ||||
|     : exec_step(false), running(false), stop_run(false), render_window(render_window) { | ||||
| } | ||||
| 
 | ||||
| void EmuThread::run() { | ||||
|  | @ -64,7 +64,7 @@ void EmuThread::run() { | |||
|             was_active = false; | ||||
|         } else { | ||||
|             std::unique_lock<std::mutex> lock(running_mutex); | ||||
|             running_cv.wait(lock, [this]{ return IsRunning() || exec_step || stop_run; }); | ||||
|             running_cv.wait(lock, [this] { return IsRunning() || exec_step || stop_run; }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -78,13 +78,13 @@ void EmuThread::run() { | |||
|     render_window->moveContext(); | ||||
| } | ||||
| 
 | ||||
| // This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL context.
 | ||||
| // This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL
 | ||||
| // context.
 | ||||
| // The corresponding functionality is handled in EmuThread instead
 | ||||
| class GGLWidgetInternal : public QGLWidget | ||||
| { | ||||
| class GGLWidgetInternal : public QGLWidget { | ||||
| public: | ||||
|     GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) | ||||
|                      : QGLWidget(fmt, parent), parent(parent) { | ||||
|         : QGLWidget(fmt, parent), parent(parent) { | ||||
|     } | ||||
| 
 | ||||
|     void paintEvent(QPaintEvent* ev) override { | ||||
|  | @ -98,37 +98,43 @@ public: | |||
|         parent->OnFramebufferSizeChanged(); | ||||
|     } | ||||
| 
 | ||||
|     void DisablePainting() { do_painting = false; } | ||||
|     void EnablePainting() { do_painting = true; } | ||||
|     void DisablePainting() { | ||||
|         do_painting = false; | ||||
|     } | ||||
|     void EnablePainting() { | ||||
|         do_painting = true; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     GRenderWindow* parent; | ||||
|     bool do_painting; | ||||
| }; | ||||
| 
 | ||||
| GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) : | ||||
|     QWidget(parent), keyboard_id(0), emu_thread(emu_thread), child(nullptr) { | ||||
| GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) | ||||
|     : QWidget(parent), keyboard_id(0), emu_thread(emu_thread), child(nullptr) { | ||||
| 
 | ||||
|     std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||||
|     std::string window_title = | ||||
|         Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||||
|     setWindowTitle(QString::fromStdString(window_title)); | ||||
| 
 | ||||
|     keyboard_id = KeyMap::NewDeviceId(); | ||||
|     ReloadSetKeymaps(); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::moveContext() | ||||
| { | ||||
| void GRenderWindow::moveContext() { | ||||
|     DoneCurrent(); | ||||
|     // We need to move GL context to the swapping thread in Qt5
 | ||||
| // We need to move GL context to the swapping thread in Qt5
 | ||||
| #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) | ||||
|     // If the thread started running, move the GL Context to the new thread. Otherwise, move it back.
 | ||||
|     auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) ? emu_thread : qApp->thread(); | ||||
|     // If the thread started running, move the GL Context to the new thread. Otherwise, move it
 | ||||
|     // back.
 | ||||
|     auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) | ||||
|                       ? emu_thread | ||||
|                       : qApp->thread(); | ||||
|     child->context()->moveToThread(thread); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::SwapBuffers() | ||||
| { | ||||
| void GRenderWindow::SwapBuffers() { | ||||
| #if !defined(QT_NO_DEBUG) | ||||
|     // Qt debug runtime prints a bogus warning on the console if you haven't called makeCurrent
 | ||||
|     // since the last time you called swapBuffers. This presumably means something if you're using
 | ||||
|  | @ -139,13 +145,11 @@ void GRenderWindow::SwapBuffers() | |||
|     child->swapBuffers(); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::MakeCurrent() | ||||
| { | ||||
| void GRenderWindow::MakeCurrent() { | ||||
|     child->makeCurrent(); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::DoneCurrent() | ||||
| { | ||||
| void GRenderWindow::DoneCurrent() { | ||||
|     child->doneCurrent(); | ||||
| } | ||||
| 
 | ||||
|  | @ -157,36 +161,33 @@ void GRenderWindow::PollEvents() { | |||
| // Older versions get the window size (density independent pixels),
 | ||||
| // and hence, do not support DPI scaling ("retina" displays).
 | ||||
| // The result will be a viewport that is smaller than the extent of the window.
 | ||||
| void GRenderWindow::OnFramebufferSizeChanged() | ||||
| { | ||||
|     // Screen changes potentially incur a change in screen DPI, hence we should update the framebuffer size
 | ||||
| void GRenderWindow::OnFramebufferSizeChanged() { | ||||
|     // Screen changes potentially incur a change in screen DPI, hence we should update the
 | ||||
|     // framebuffer size
 | ||||
|     qreal pixelRatio = windowPixelRatio(); | ||||
|     unsigned width = child->QPaintDevice::width() * pixelRatio; | ||||
|     unsigned height = child->QPaintDevice::height() * pixelRatio; | ||||
| 
 | ||||
|     NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); | ||||
|     NotifyFramebufferLayoutChanged( | ||||
|         EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::BackupGeometry() | ||||
| { | ||||
| void GRenderWindow::BackupGeometry() { | ||||
|     geometry = ((QGLWidget*)this)->saveGeometry(); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::RestoreGeometry() | ||||
| { | ||||
| void GRenderWindow::RestoreGeometry() { | ||||
|     // We don't want to back up the geometry here (obviously)
 | ||||
|     QWidget::restoreGeometry(geometry); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::restoreGeometry(const QByteArray& geometry) | ||||
| { | ||||
| void GRenderWindow::restoreGeometry(const QByteArray& geometry) { | ||||
|     // Make sure users of this class don't need to deal with backing up the geometry themselves
 | ||||
|     QWidget::restoreGeometry(geometry); | ||||
|     BackupGeometry(); | ||||
| } | ||||
| 
 | ||||
| QByteArray GRenderWindow::saveGeometry() | ||||
| { | ||||
| QByteArray GRenderWindow::saveGeometry() { | ||||
|     // If we are a top-level widget, store the current geometry
 | ||||
|     // otherwise, store the last backup
 | ||||
|     if (parent() == nullptr) | ||||
|  | @ -195,8 +196,7 @@ QByteArray GRenderWindow::saveGeometry() | |||
|         return geometry; | ||||
| } | ||||
| 
 | ||||
| qreal GRenderWindow::windowPixelRatio() | ||||
| { | ||||
| qreal GRenderWindow::windowPixelRatio() { | ||||
| #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||||
|     // windowHandle() might not be accessible until the window is displayed to screen.
 | ||||
|     return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f; | ||||
|  | @ -210,20 +210,16 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { | |||
|     QWidget::closeEvent(event); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::keyPressEvent(QKeyEvent* event) | ||||
| { | ||||
|     KeyMap::PressKey(*this, { event->key(), keyboard_id }); | ||||
| void GRenderWindow::keyPressEvent(QKeyEvent* event) { | ||||
|     KeyMap::PressKey(*this, {event->key(), keyboard_id}); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::keyReleaseEvent(QKeyEvent* event) | ||||
| { | ||||
|     KeyMap::ReleaseKey(*this, { event->key(), keyboard_id }); | ||||
| void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { | ||||
|     KeyMap::ReleaseKey(*this, {event->key(), keyboard_id}); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::mousePressEvent(QMouseEvent *event) | ||||
| { | ||||
|     if (event->button() == Qt::LeftButton) | ||||
|     { | ||||
| void GRenderWindow::mousePressEvent(QMouseEvent* event) { | ||||
|     if (event->button() == Qt::LeftButton) { | ||||
|         auto pos = event->pos(); | ||||
|         qreal pixelRatio = windowPixelRatio(); | ||||
|         this->TouchPressed(static_cast<unsigned>(pos.x() * pixelRatio), | ||||
|  | @ -231,30 +227,28 @@ void GRenderWindow::mousePressEvent(QMouseEvent *event) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::mouseMoveEvent(QMouseEvent *event) | ||||
| { | ||||
| void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | ||||
|     auto pos = event->pos(); | ||||
|     qreal pixelRatio = windowPixelRatio(); | ||||
|     this->TouchMoved(std::max(static_cast<unsigned>(pos.x() * pixelRatio), 0u), | ||||
|                      std::max(static_cast<unsigned>(pos.y() * pixelRatio), 0u)); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::mouseReleaseEvent(QMouseEvent *event) | ||||
| { | ||||
| void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { | ||||
|     if (event->button() == Qt::LeftButton) | ||||
|         this->TouchReleased(); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::ReloadSetKeymaps() | ||||
| { | ||||
| void GRenderWindow::ReloadSetKeymaps() { | ||||
|     KeyMap::ClearKeyMapping(keyboard_id); | ||||
|     for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | ||||
|         KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, KeyMap::mapping_targets[i]); | ||||
|         KeyMap::SetKeyMapping( | ||||
|             {Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, | ||||
|             KeyMap::mapping_targets[i]); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) | ||||
| { | ||||
| void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) { | ||||
|     NotifyClientAreaSizeChanged(std::make_pair(width, height)); | ||||
| } | ||||
| 
 | ||||
|  | @ -267,7 +261,8 @@ void GRenderWindow::InitRenderTarget() { | |||
|         delete layout(); | ||||
|     } | ||||
| 
 | ||||
|     // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose
 | ||||
|     // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
 | ||||
|     // WA_DontShowOnScreen, WA_DeleteOnClose
 | ||||
|     QGLFormat fmt; | ||||
|     fmt.setVersion(3, 3); | ||||
|     fmt.setProfile(QGLFormat::CoreProfile); | ||||
|  | @ -279,7 +274,8 @@ void GRenderWindow::InitRenderTarget() { | |||
|     child = new GGLWidgetInternal(fmt, this); | ||||
|     QBoxLayout* layout = new QHBoxLayout(this); | ||||
| 
 | ||||
|     resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); | ||||
|     resize(VideoCore::kScreenTopWidth, | ||||
|            VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); | ||||
|     layout->addWidget(child); | ||||
|     layout->setMargin(0); | ||||
|     setLayout(layout); | ||||
|  | @ -292,7 +288,8 @@ void GRenderWindow::InitRenderTarget() { | |||
|     BackupGeometry(); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { | ||||
| void GRenderWindow::OnMinimalClientAreaChangeRequest( | ||||
|     const std::pair<unsigned, unsigned>& minimal_size) { | ||||
|     setMinimumSize(minimal_size.first, minimal_size.second); | ||||
| } | ||||
| 
 | ||||
|  | @ -306,11 +303,12 @@ void GRenderWindow::OnEmulationStopping() { | |||
|     child->EnablePainting(); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::showEvent(QShowEvent * event) { | ||||
| void GRenderWindow::showEvent(QShowEvent* event) { | ||||
|     QWidget::showEvent(event); | ||||
| 
 | ||||
|     // windowHandle() is not initialized until the Window is shown, so we connect it here.
 | ||||
|     #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||||
|         connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, SLOT(OnFramebufferSizeChanged()), Qt::UniqueConnection); | ||||
|     #endif | ||||
| // windowHandle() is not initialized until the Window is shown, so we connect it here.
 | ||||
| #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||||
|     connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, | ||||
|             SLOT(OnFramebufferSizeChanged()), Qt::UniqueConnection); | ||||
| #endif | ||||
| } | ||||
|  |  | |||
|  | @ -19,8 +19,7 @@ class GGLWidgetInternal; | |||
| class GMainWindow; | ||||
| class GRenderWindow; | ||||
| 
 | ||||
| class EmuThread : public QThread | ||||
| { | ||||
| class EmuThread : public QThread { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  | @ -58,7 +57,9 @@ public: | |||
|      * @return True if the emulation thread is running, otherwise false | ||||
|      * @note This function is thread-safe | ||||
|      */ | ||||
|     bool IsRunning() { return running; } | ||||
|     bool IsRunning() { | ||||
|         return running; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Requests for the emulation thread to stop running | ||||
|  | @ -81,20 +82,23 @@ signals: | |||
|     /**
 | ||||
|      * Emitted when the CPU has halted execution | ||||
|      * | ||||
|      * @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns) | ||||
|      * @warning When connecting to this signal from other threads, make sure to specify either | ||||
|      * Qt::QueuedConnection (invoke slot within the destination object's message thread) or even | ||||
|      * Qt::BlockingQueuedConnection (additionally block source thread until slot returns) | ||||
|      */ | ||||
|     void DebugModeEntered(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Emitted right before the CPU continues execution | ||||
|      * | ||||
|      * @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns) | ||||
|      * @warning When connecting to this signal from other threads, make sure to specify either | ||||
|      * Qt::QueuedConnection (invoke slot within the destination object's message thread) or even | ||||
|      * Qt::BlockingQueuedConnection (additionally block source thread until slot returns) | ||||
|      */ | ||||
|     void DebugModeLeft(); | ||||
| }; | ||||
| 
 | ||||
| class GRenderWindow : public QWidget, public EmuWindow | ||||
| { | ||||
| class GRenderWindow : public QWidget, public EmuWindow { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  | @ -109,7 +113,7 @@ public: | |||
|     void BackupGeometry(); | ||||
|     void RestoreGeometry(); | ||||
|     void restoreGeometry(const QByteArray& geometry); // overridden
 | ||||
|     QByteArray saveGeometry();  // overridden
 | ||||
|     QByteArray saveGeometry();                        // overridden
 | ||||
| 
 | ||||
|     qreal windowPixelRatio(); | ||||
| 
 | ||||
|  | @ -118,9 +122,9 @@ public: | |||
|     void keyPressEvent(QKeyEvent* event) override; | ||||
|     void keyReleaseEvent(QKeyEvent* event) override; | ||||
| 
 | ||||
|     void mousePressEvent(QMouseEvent *event) override; | ||||
|     void mouseMoveEvent(QMouseEvent *event) override; | ||||
|     void mouseReleaseEvent(QMouseEvent *event) override; | ||||
|     void mousePressEvent(QMouseEvent* event) override; | ||||
|     void mouseMoveEvent(QMouseEvent* event) override; | ||||
|     void mouseReleaseEvent(QMouseEvent* event) override; | ||||
| 
 | ||||
|     void ReloadSetKeymaps() override; | ||||
| 
 | ||||
|  | @ -129,7 +133,7 @@ public: | |||
|     void InitRenderTarget(); | ||||
| 
 | ||||
| public slots: | ||||
|     void moveContext();  // overridden
 | ||||
|     void moveContext(); // overridden
 | ||||
| 
 | ||||
|     void OnEmulationStarting(EmuThread* emu_thread); | ||||
|     void OnEmulationStopping(); | ||||
|  | @ -140,7 +144,8 @@ signals: | |||
|     void Closed(); | ||||
| 
 | ||||
| private: | ||||
|     void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override; | ||||
|     void | ||||
|     OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) override; | ||||
| 
 | ||||
|     GGLWidgetInternal* child; | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,24 +20,23 @@ Config::Config() { | |||
| 
 | ||||
| const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> Config::defaults = { | ||||
|     // directly mapped keys
 | ||||
|     Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, | ||||
|     Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2, | ||||
|     Qt::Key_M, Qt::Key_N, Qt::Key_B, | ||||
|     Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, | ||||
|     Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, | ||||
|     Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2, | ||||
|     Qt::Key_M, Qt::Key_N, Qt::Key_B, Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, Qt::Key_I, | ||||
|     Qt::Key_K, Qt::Key_J, Qt::Key_L, | ||||
| 
 | ||||
|     // indirectly mapped keys
 | ||||
|     Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, | ||||
|     Qt::Key_D, | ||||
|     Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_D, | ||||
| }; | ||||
| 
 | ||||
| void Config::ReadValues() { | ||||
|     qt_config->beginGroup("Controls"); | ||||
|     for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | ||||
|         Settings::values.input_mappings[Settings::NativeInput::All[i]] = | ||||
|             qt_config->value(QString::fromStdString(Settings::NativeInput::Mapping[i]), defaults[i]).toInt(); | ||||
|             qt_config->value(QString::fromStdString(Settings::NativeInput::Mapping[i]), defaults[i]) | ||||
|                 .toInt(); | ||||
|     } | ||||
|     Settings::values.pad_circle_modifier_scale = qt_config->value("pad_circle_modifier_scale", 0.5).toFloat(); | ||||
|     Settings::values.pad_circle_modifier_scale = | ||||
|         qt_config->value("pad_circle_modifier_scale", 0.5).toFloat(); | ||||
|     qt_config->endGroup(); | ||||
| 
 | ||||
|     qt_config->beginGroup("Core"); | ||||
|  | @ -48,17 +47,19 @@ void Config::ReadValues() { | |||
|     qt_config->beginGroup("Renderer"); | ||||
|     Settings::values.use_hw_renderer = qt_config->value("use_hw_renderer", true).toBool(); | ||||
|     Settings::values.use_shader_jit = qt_config->value("use_shader_jit", true).toBool(); | ||||
|     Settings::values.use_scaled_resolution = qt_config->value("use_scaled_resolution", false).toBool(); | ||||
|     Settings::values.use_scaled_resolution = | ||||
|         qt_config->value("use_scaled_resolution", false).toBool(); | ||||
|     Settings::values.use_vsync = qt_config->value("use_vsync", false).toBool(); | ||||
| 
 | ||||
|     Settings::values.bg_red   = qt_config->value("bg_red",   1.0).toFloat(); | ||||
|     Settings::values.bg_red = qt_config->value("bg_red", 1.0).toFloat(); | ||||
|     Settings::values.bg_green = qt_config->value("bg_green", 1.0).toFloat(); | ||||
|     Settings::values.bg_blue  = qt_config->value("bg_blue",  1.0).toFloat(); | ||||
|     Settings::values.bg_blue = qt_config->value("bg_blue", 1.0).toFloat(); | ||||
|     qt_config->endGroup(); | ||||
| 
 | ||||
|     qt_config->beginGroup("Audio"); | ||||
|     Settings::values.sink_id = qt_config->value("output_engine", "auto").toString().toStdString(); | ||||
|     Settings::values.enable_audio_stretching = qt_config->value("enable_audio_stretching", true).toBool(); | ||||
|     Settings::values.enable_audio_stretching = | ||||
|         qt_config->value("enable_audio_stretching", true).toBool(); | ||||
|     qt_config->endGroup(); | ||||
| 
 | ||||
|     qt_config->beginGroup("Data Storage"); | ||||
|  | @ -84,10 +85,14 @@ void Config::ReadValues() { | |||
|     qt_config->beginGroup("UILayout"); | ||||
|     UISettings::values.geometry = qt_config->value("geometry").toByteArray(); | ||||
|     UISettings::values.state = qt_config->value("state").toByteArray(); | ||||
|     UISettings::values.renderwindow_geometry = qt_config->value("geometryRenderWindow").toByteArray(); | ||||
|     UISettings::values.gamelist_header_state = qt_config->value("gameListHeaderState").toByteArray(); | ||||
|     UISettings::values.microprofile_geometry = qt_config->value("microProfileDialogGeometry").toByteArray(); | ||||
|     UISettings::values.microprofile_visible = qt_config->value("microProfileDialogVisible", false).toBool(); | ||||
|     UISettings::values.renderwindow_geometry = | ||||
|         qt_config->value("geometryRenderWindow").toByteArray(); | ||||
|     UISettings::values.gamelist_header_state = | ||||
|         qt_config->value("gameListHeaderState").toByteArray(); | ||||
|     UISettings::values.microprofile_geometry = | ||||
|         qt_config->value("microProfileDialogGeometry").toByteArray(); | ||||
|     UISettings::values.microprofile_visible = | ||||
|         qt_config->value("microProfileDialogVisible", false).toBool(); | ||||
|     qt_config->endGroup(); | ||||
| 
 | ||||
|     qt_config->beginGroup("Paths"); | ||||
|  | @ -106,10 +111,10 @@ void Config::ReadValues() { | |||
|         QStringList hotkeys = qt_config->childGroups(); | ||||
|         for (auto hotkey : hotkeys) { | ||||
|             qt_config->beginGroup(hotkey); | ||||
|             UISettings::values.shortcuts.emplace_back( | ||||
|                         UISettings::Shortcut(group + "/" + hotkey, | ||||
|                                              UISettings::ContextualShortcut(qt_config->value("KeySeq").toString(), | ||||
|                                                                             qt_config->value("Context").toInt()))); | ||||
|             UISettings::values.shortcuts.emplace_back(UISettings::Shortcut( | ||||
|                 group + "/" + hotkey, | ||||
|                 UISettings::ContextualShortcut(qt_config->value("KeySeq").toString(), | ||||
|                                                qt_config->value("Context").toInt()))); | ||||
|             qt_config->endGroup(); | ||||
|         } | ||||
| 
 | ||||
|  | @ -119,7 +124,7 @@ void Config::ReadValues() { | |||
| 
 | ||||
|     UISettings::values.single_window_mode = qt_config->value("singleWindowMode", true).toBool(); | ||||
|     UISettings::values.display_titlebar = qt_config->value("displayTitleBars", true).toBool(); | ||||
|     UISettings::values.confirm_before_closing = qt_config->value("confirmClose",true).toBool(); | ||||
|     UISettings::values.confirm_before_closing = qt_config->value("confirmClose", true).toBool(); | ||||
|     UISettings::values.first_start = qt_config->value("firstStart", true).toBool(); | ||||
| 
 | ||||
|     qt_config->endGroup(); | ||||
|  | @ -129,9 +134,10 @@ void Config::SaveValues() { | |||
|     qt_config->beginGroup("Controls"); | ||||
|     for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | ||||
|         qt_config->setValue(QString::fromStdString(Settings::NativeInput::Mapping[i]), | ||||
|             Settings::values.input_mappings[Settings::NativeInput::All[i]]); | ||||
|                             Settings::values.input_mappings[Settings::NativeInput::All[i]]); | ||||
|     } | ||||
|     qt_config->setValue("pad_circle_modifier_scale", (double)Settings::values.pad_circle_modifier_scale); | ||||
|     qt_config->setValue("pad_circle_modifier_scale", | ||||
|                         (double)Settings::values.pad_circle_modifier_scale); | ||||
|     qt_config->endGroup(); | ||||
| 
 | ||||
|     qt_config->beginGroup("Core"); | ||||
|  | @ -146,9 +152,9 @@ void Config::SaveValues() { | |||
|     qt_config->setValue("use_vsync", Settings::values.use_vsync); | ||||
| 
 | ||||
|     // Cast to double because Qt's written float values are not human-readable
 | ||||
|     qt_config->setValue("bg_red",   (double)Settings::values.bg_red); | ||||
|     qt_config->setValue("bg_red", (double)Settings::values.bg_red); | ||||
|     qt_config->setValue("bg_green", (double)Settings::values.bg_green); | ||||
|     qt_config->setValue("bg_blue",  (double)Settings::values.bg_blue); | ||||
|     qt_config->setValue("bg_blue", (double)Settings::values.bg_blue); | ||||
|     qt_config->endGroup(); | ||||
| 
 | ||||
|     qt_config->beginGroup("Audio"); | ||||
|  |  | |||
|  | @ -4,8 +4,8 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| #include <QVariant> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
|  | @ -17,6 +17,7 @@ class Config { | |||
| 
 | ||||
|     void ReadValues(); | ||||
|     void SaveValues(); | ||||
| 
 | ||||
| public: | ||||
|     Config(); | ||||
|     ~Config(); | ||||
|  |  | |||
|  | @ -9,10 +9,8 @@ | |||
| 
 | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| ConfigureAudio::ConfigureAudio(QWidget* parent) : | ||||
|         QWidget(parent), | ||||
|         ui(std::make_unique<Ui::ConfigureAudio>()) | ||||
| { | ||||
| ConfigureAudio::ConfigureAudio(QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) { | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|     ui->output_sink_combo_box->clear(); | ||||
|  | @ -41,7 +39,9 @@ void ConfigureAudio::setConfiguration() { | |||
| } | ||||
| 
 | ||||
| void ConfigureAudio::applyConfiguration() { | ||||
|     Settings::values.sink_id = ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()).toStdString(); | ||||
|     Settings::values.sink_id = | ||||
|         ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) | ||||
|             .toStdString(); | ||||
|     Settings::values.enable_audio_stretching = ui->toggle_audio_stretching->isChecked(); | ||||
|     Settings::Apply(); | ||||
| } | ||||
|  |  | |||
|  | @ -4,8 +4,8 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QWidget> | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ConfigureAudio; | ||||
|  |  | |||
|  | @ -7,10 +7,7 @@ | |||
| 
 | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| ConfigureDebug::ConfigureDebug(QWidget *parent) : | ||||
|     QWidget(parent), | ||||
|     ui(new Ui::ConfigureDebug) | ||||
| { | ||||
| ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) { | ||||
|     ui->setupUi(this); | ||||
|     this->setConfiguration(); | ||||
| } | ||||
|  |  | |||
|  | @ -4,19 +4,18 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QWidget> | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ConfigureDebug; | ||||
| } | ||||
| 
 | ||||
| class ConfigureDebug : public QWidget | ||||
| { | ||||
| class ConfigureDebug : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureDebug(QWidget *parent = nullptr); | ||||
|     explicit ConfigureDebug(QWidget* parent = nullptr); | ||||
|     ~ConfigureDebug(); | ||||
| 
 | ||||
|     void applyConfiguration(); | ||||
|  |  | |||
|  | @ -6,13 +6,9 @@ | |||
| #include "citra_qt/configure_dialog.h" | ||||
| #include "ui_configure.h" | ||||
| 
 | ||||
| 
 | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| ConfigureDialog::ConfigureDialog(QWidget *parent) : | ||||
|     QDialog(parent), | ||||
|     ui(new Ui::ConfigureDialog) | ||||
| { | ||||
| ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { | ||||
|     ui->setupUi(this); | ||||
|     this->setConfiguration(); | ||||
| } | ||||
|  |  | |||
|  | @ -4,19 +4,18 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QDialog> | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ConfigureDialog; | ||||
| } | ||||
| 
 | ||||
| class ConfigureDialog : public QDialog | ||||
| { | ||||
| class ConfigureDialog : public QDialog { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureDialog(QWidget *parent); | ||||
|     explicit ConfigureDialog(QWidget* parent); | ||||
|     ~ConfigureDialog(); | ||||
| 
 | ||||
|     void applyConfiguration(); | ||||
|  |  | |||
|  | @ -9,10 +9,8 @@ | |||
| #include "core/settings.h" | ||||
| #include "core/system.h" | ||||
| 
 | ||||
| ConfigureGeneral::ConfigureGeneral(QWidget *parent) : | ||||
|     QWidget(parent), | ||||
|     ui(new Ui::ConfigureGeneral) | ||||
| { | ||||
| ConfigureGeneral::ConfigureGeneral(QWidget* parent) | ||||
|     : QWidget(parent), ui(new Ui::ConfigureGeneral) { | ||||
|     ui->setupUi(this); | ||||
|     this->setConfiguration(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,19 +4,18 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QWidget> | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ConfigureGeneral; | ||||
| } | ||||
| 
 | ||||
| class ConfigureGeneral : public QWidget | ||||
| { | ||||
| class ConfigureGeneral : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureGeneral(QWidget *parent = nullptr); | ||||
|     explicit ConfigureGeneral(QWidget* parent = nullptr); | ||||
|     ~ConfigureGeneral(); | ||||
| 
 | ||||
|     void applyConfiguration(); | ||||
|  |  | |||
|  | @ -8,10 +8,8 @@ | |||
| #include "core/settings.h" | ||||
| #include "core/system.h" | ||||
| 
 | ||||
| ConfigureGraphics::ConfigureGraphics(QWidget *parent) : | ||||
|     QWidget(parent), | ||||
|     ui(new Ui::ConfigureGraphics) | ||||
| { | ||||
| ConfigureGraphics::ConfigureGraphics(QWidget* parent) | ||||
|     : QWidget(parent), ui(new Ui::ConfigureGraphics) { | ||||
|     ui->setupUi(this); | ||||
|     this->setConfiguration(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,19 +4,18 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QWidget> | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ConfigureGraphics; | ||||
| } | ||||
| 
 | ||||
| class ConfigureGraphics : public QWidget | ||||
| { | ||||
| class ConfigureGraphics : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureGraphics(QWidget *parent = nullptr); | ||||
|     explicit ConfigureGraphics(QWidget* parent = nullptr); | ||||
|     ~ConfigureGraphics(); | ||||
| 
 | ||||
|     void applyConfiguration(); | ||||
|  |  | |||
|  | @ -2,41 +2,42 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <QTimer> | ||||
| #include <memory> | ||||
| #include <utility> | ||||
| #include <QTimer> | ||||
| 
 | ||||
| #include "citra_qt/configure_input.h" | ||||
| 
 | ||||
| ConfigureInput::ConfigureInput(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { | ||||
| ConfigureInput::ConfigureInput(QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|     // Initialize mapping of input enum to UI button.
 | ||||
|     input_mapping = { | ||||
|         { std::make_pair(Settings::NativeInput::Values::A, ui->buttonA) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::B, ui->buttonB) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::X, ui->buttonX) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::Y, ui->buttonY) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::L, ui->buttonL) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::R, ui->buttonR) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::ZL, ui->buttonZL) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::ZR, ui->buttonZR) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::START, ui->buttonStart) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::SELECT, ui->buttonSelect) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::HOME, ui->buttonHome) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::DUP, ui->buttonDpadUp) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::DDOWN, ui->buttonDpadDown) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::DLEFT, ui->buttonDpadLeft) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::DRIGHT, ui->buttonDpadRight) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CUP, ui->buttonCStickUp) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CDOWN, ui->buttonCStickDown) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CLEFT, ui->buttonCStickLeft) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CRIGHT, ui->buttonCStickRight) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CIRCLE_UP, ui->buttonCircleUp) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CIRCLE_DOWN, ui->buttonCircleDown) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CIRCLE_LEFT, ui->buttonCircleLeft) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CIRCLE_RIGHT, ui->buttonCircleRight) }, | ||||
|         { std::make_pair(Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod) }, | ||||
|         {std::make_pair(Settings::NativeInput::Values::A, ui->buttonA)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::B, ui->buttonB)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::X, ui->buttonX)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::Y, ui->buttonY)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::L, ui->buttonL)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::R, ui->buttonR)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::ZL, ui->buttonZL)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::ZR, ui->buttonZR)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::START, ui->buttonStart)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::SELECT, ui->buttonSelect)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::HOME, ui->buttonHome)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::DUP, ui->buttonDpadUp)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::DDOWN, ui->buttonDpadDown)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::DLEFT, ui->buttonDpadLeft)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::DRIGHT, ui->buttonDpadRight)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CUP, ui->buttonCStickUp)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CDOWN, ui->buttonCStickDown)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CLEFT, ui->buttonCStickLeft)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CRIGHT, ui->buttonCStickRight)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CIRCLE_UP, ui->buttonCircleUp)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CIRCLE_DOWN, ui->buttonCircleDown)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CIRCLE_LEFT, ui->buttonCircleLeft)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CIRCLE_RIGHT, ui->buttonCircleRight)}, | ||||
|         {std::make_pair(Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod)}, | ||||
|     }; | ||||
| 
 | ||||
|     // Attach handle click method to each button click.
 | ||||
|  | @ -47,7 +48,10 @@ ConfigureInput::ConfigureInput(QWidget* parent) : QWidget(parent), ui(std::make_ | |||
|     setFocusPolicy(Qt::ClickFocus); | ||||
|     timer = new QTimer(this); | ||||
|     timer->setSingleShot(true); | ||||
|     connect(timer, &QTimer::timeout, this, [&]() { key_pressed = Qt::Key_Escape; setKey(); }); | ||||
|     connect(timer, &QTimer::timeout, this, [&]() { | ||||
|         key_pressed = Qt::Key_Escape; | ||||
|         setKey(); | ||||
|     }); | ||||
|     this->setConfiguration(); | ||||
| } | ||||
| 
 | ||||
|  | @ -59,7 +63,7 @@ void ConfigureInput::handleClick() { | |||
|     grabKeyboard(); | ||||
|     grabMouse(); | ||||
|     changing_button = sender; | ||||
|     timer->start(5000); //Cancel after 5 seconds
 | ||||
|     timer->start(5000); // Cancel after 5 seconds
 | ||||
| } | ||||
| 
 | ||||
| void ConfigureInput::applyConfiguration() { | ||||
|  |  | |||
|  | @ -4,8 +4,8 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <QWidget> | ||||
| #include <QKeyEvent> | ||||
| #include <QWidget> | ||||
| 
 | ||||
| #include "citra_qt/config.h" | ||||
| #include "core/settings.h" | ||||
|  | @ -16,7 +16,7 @@ class QString; | |||
| class QTimer; | ||||
| 
 | ||||
| namespace Ui { | ||||
|     class ConfigureInput; | ||||
| class ConfigureInput; | ||||
| } | ||||
| 
 | ||||
| class ConfigureInput : public QWidget { | ||||
|  | @ -39,7 +39,8 @@ private: | |||
|     /// Load configuration settings into button text
 | ||||
|     void setConfiguration(); | ||||
| 
 | ||||
|     /// Check all inputs for duplicate keys. Clears out any other button with the same value as this button's new value.
 | ||||
|     /// Check all inputs for duplicate keys. Clears out any other button with the same value as this
 | ||||
|     /// button's new value.
 | ||||
|     void removeDuplicates(const QString& newValue); | ||||
| 
 | ||||
|     /// Handle key press event for input tab when a button is 'waiting'.
 | ||||
|  |  | |||
|  | @ -6,19 +6,16 @@ | |||
| #include "citra_qt/ui_settings.h" | ||||
| #include "ui_configure_system.h" | ||||
| 
 | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/hle/service/cfg/cfg.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/system.h" | ||||
| 
 | ||||
| static const std::array<int, 12> days_in_month = {{ | ||||
|     31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 | ||||
| }}; | ||||
| static const std::array<int, 12> days_in_month = {{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; | ||||
| 
 | ||||
| ConfigureSystem::ConfigureSystem(QWidget *parent) : | ||||
|     QWidget(parent), | ||||
|     ui(new Ui::ConfigureSystem) { | ||||
| ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureSystem) { | ||||
|     ui->setupUi(this); | ||||
|     connect(ui->combo_birthmonth, SIGNAL(currentIndexChanged(int)), SLOT(updateBirthdayComboBox(int))); | ||||
|     connect(ui->combo_birthmonth, SIGNAL(currentIndexChanged(int)), | ||||
|             SLOT(updateBirthdayComboBox(int))); | ||||
| 
 | ||||
|     this->setConfiguration(); | ||||
| } | ||||
|  | @ -54,13 +51,17 @@ void ConfigureSystem::setConfiguration() { | |||
| void ConfigureSystem::ReadSystemSettings() { | ||||
|     // set username
 | ||||
|     username = Service::CFG::GetUsername(); | ||||
|     // ui->edit_username->setText(QString::fromStdU16String(username)); // TODO(wwylele): Use this when we move to Qt 5.5
 | ||||
|     ui->edit_username->setText(QString::fromUtf16(reinterpret_cast<const ushort*>(username.data()))); | ||||
|     // ui->edit_username->setText(QString::fromStdU16String(username)); // TODO(wwylele): Use this
 | ||||
|     // when we move to Qt 5.5
 | ||||
|     ui->edit_username->setText( | ||||
|         QString::fromUtf16(reinterpret_cast<const ushort*>(username.data()))); | ||||
| 
 | ||||
|     // set birthday
 | ||||
|     std::tie(birthmonth, birthday) = Service::CFG::GetBirthday(); | ||||
|     ui->combo_birthmonth->setCurrentIndex(birthmonth - 1); | ||||
|     updateBirthdayComboBox(birthmonth - 1); // explicitly update it because the signal from setCurrentIndex is not reliable
 | ||||
|     updateBirthdayComboBox( | ||||
|         birthmonth - | ||||
|         1); // explicitly update it because the signal from setCurrentIndex is not reliable
 | ||||
|     ui->combo_birthday->setCurrentIndex(birthday - 1); | ||||
| 
 | ||||
|     // set system language
 | ||||
|  | @ -79,8 +80,10 @@ void ConfigureSystem::applyConfiguration() { | |||
|     bool modified = false; | ||||
| 
 | ||||
|     // apply username
 | ||||
|     // std::u16string new_username = ui->edit_username->text().toStdU16String(); // TODO(wwylele): Use this when we move to Qt 5.5
 | ||||
|     std::u16string new_username(reinterpret_cast<const char16_t*>(ui->edit_username->text().utf16())); | ||||
|     // std::u16string new_username = ui->edit_username->text().toStdU16String(); // TODO(wwylele):
 | ||||
|     // Use this when we move to Qt 5.5
 | ||||
|     std::u16string new_username( | ||||
|         reinterpret_cast<const char16_t*>(ui->edit_username->text().utf16())); | ||||
|     if (new_username != username) { | ||||
|         Service::CFG::SetUsername(new_username); | ||||
|         modified = true; | ||||
|  |  | |||
|  | @ -4,19 +4,18 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QWidget> | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ConfigureSystem; | ||||
| } | ||||
| 
 | ||||
| class ConfigureSystem : public QWidget | ||||
| { | ||||
| class ConfigureSystem : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureSystem(QWidget *parent = nullptr); | ||||
|     explicit ConfigureSystem(QWidget* parent = nullptr); | ||||
|     ~ConfigureSystem(); | ||||
| 
 | ||||
|     void applyConfiguration(); | ||||
|  |  | |||
|  | @ -9,13 +9,12 @@ | |||
| #include "common/common_types.h" | ||||
| #include "common/symbols.h" | ||||
| 
 | ||||
| #include "core/core.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/arm/disassembler/arm_disasm.h" | ||||
| #include "core/core.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent) | ||||
| { | ||||
| CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) { | ||||
|     ui.setupUi(this); | ||||
| 
 | ||||
|     callstack_model = new QStandardItemModel(this); | ||||
|  | @ -27,29 +26,26 @@ CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent) | |||
|     ui.treeView->setModel(callstack_model); | ||||
| } | ||||
| 
 | ||||
| void CallstackWidget::OnDebugModeEntered() | ||||
| { | ||||
| void CallstackWidget::OnDebugModeEntered() { | ||||
|     // Stack pointer
 | ||||
|     const u32 sp = Core::g_app_core->GetReg(13); | ||||
| 
 | ||||
|     Clear(); | ||||
| 
 | ||||
|     int counter = 0; | ||||
|     for (u32 addr = 0x10000000; addr >= sp; addr -= 4) | ||||
|     { | ||||
|     for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { | ||||
|         if (!Memory::IsValidVirtualAddress(addr)) | ||||
|             break; | ||||
| 
 | ||||
|         const u32 ret_addr = Memory::Read32(addr); | ||||
|         const u32 call_addr = ret_addr - 4; //get call address???
 | ||||
|         const u32 call_addr = ret_addr - 4; // get call address???
 | ||||
| 
 | ||||
|         if (!Memory::IsValidVirtualAddress(call_addr)) | ||||
|             break; | ||||
| 
 | ||||
|         /* TODO (mattvail) clean me, move to debugger interface */ | ||||
|         u32 insn = Memory::Read32(call_addr); | ||||
|         if (ARM_Disasm::Decode(insn) == OP_BL) | ||||
|         { | ||||
|         if (ARM_Disasm::Decode(insn) == OP_BL) { | ||||
|             std::string name; | ||||
|             // ripped from disasm
 | ||||
|             u8 cond = (insn >> 28) & 0xf; | ||||
|  | @ -63,26 +59,29 @@ void CallstackWidget::OnDebugModeEntered() | |||
|             i_offset += 8; | ||||
|             const u32 func_addr = call_addr + i_offset; | ||||
| 
 | ||||
|             callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); | ||||
|             callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0')))); | ||||
|             callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(call_addr, 8, 16, QLatin1Char('0')))); | ||||
|             callstack_model->setItem( | ||||
|                 counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); | ||||
|             callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg( | ||||
|                                                      ret_addr, 8, 16, QLatin1Char('0')))); | ||||
|             callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg( | ||||
|                                                      call_addr, 8, 16, QLatin1Char('0')))); | ||||
| 
 | ||||
|             name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown"; | ||||
|             callstack_model->setItem(counter, 3, new QStandardItem(QString("%1_%2").arg(QString::fromStdString(name)) | ||||
|                 .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0'))))); | ||||
|             callstack_model->setItem( | ||||
|                 counter, 3, new QStandardItem( | ||||
|                                 QString("%1_%2") | ||||
|                                     .arg(QString::fromStdString(name)) | ||||
|                                     .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0'))))); | ||||
| 
 | ||||
|             counter++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void CallstackWidget::OnDebugModeLeft() | ||||
| { | ||||
| 
 | ||||
| void CallstackWidget::OnDebugModeLeft() { | ||||
| } | ||||
| 
 | ||||
| void CallstackWidget::Clear() | ||||
| { | ||||
| void CallstackWidget::Clear() { | ||||
|     for (int row = 0; row < callstack_model->rowCount(); row++) { | ||||
|         for (int column = 0; column < callstack_model->columnCount(); column++) { | ||||
|             callstack_model->setItem(row, column, new QStandardItem()); | ||||
|  |  | |||
|  | @ -7,8 +7,7 @@ | |||
| 
 | ||||
| class QStandardItemModel; | ||||
| 
 | ||||
| class CallstackWidget : public QDockWidget | ||||
| { | ||||
| class CallstackWidget : public QDockWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  |  | |||
|  | @ -5,20 +5,21 @@ | |||
| #include <QShortcut> | ||||
| 
 | ||||
| #include "citra_qt/bootmanager.h" | ||||
| #include "citra_qt/hotkeys.h" | ||||
| #include "citra_qt/debugger/disassembler.h" | ||||
| #include "citra_qt/hotkeys.h" | ||||
| #include "citra_qt/util/util.h" | ||||
| 
 | ||||
| #include "common/break_points.h" | ||||
| #include "common/symbols.h" | ||||
| 
 | ||||
| #include "core/core.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/arm/disassembler/arm_disasm.h" | ||||
| #include "core/core.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| DisassemblerModel::DisassemblerModel(QObject* parent) : | ||||
|     QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) { | ||||
| DisassemblerModel::DisassemblerModel(QObject* parent) | ||||
|     : QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), | ||||
|       selection(QModelIndex()) { | ||||
| } | ||||
| 
 | ||||
| int DisassemblerModel::columnCount(const QModelIndex& parent) const { | ||||
|  | @ -31,62 +32,60 @@ int DisassemblerModel::rowCount(const QModelIndex& parent) const { | |||
| 
 | ||||
| QVariant DisassemblerModel::data(const QModelIndex& index, int role) const { | ||||
|     switch (role) { | ||||
|         case Qt::DisplayRole: | ||||
|         { | ||||
|             u32 address = base_address + index.row() * 4; | ||||
|             u32 instr = Memory::Read32(address); | ||||
|             std::string disassembly = ARM_Disasm::Disassemble(address, instr); | ||||
|     case Qt::DisplayRole: { | ||||
|         u32 address = base_address + index.row() * 4; | ||||
|         u32 instr = Memory::Read32(address); | ||||
|         std::string disassembly = ARM_Disasm::Disassemble(address, instr); | ||||
| 
 | ||||
|             if (index.column() == 0) { | ||||
|                 return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0')); | ||||
|             } else if (index.column() == 1) { | ||||
|                 return QString::fromStdString(disassembly); | ||||
|             } else if (index.column() == 2) { | ||||
|                 if(Symbols::HasSymbol(address)) { | ||||
|                     TSymbol symbol = Symbols::GetSymbol(address); | ||||
|                     return QString("%1 - Size:%2").arg(QString::fromStdString(symbol.name)) | ||||
|                                                   .arg(symbol.size / 4); // divide by 4 to get instruction count
 | ||||
|                 } else if (ARM_Disasm::Decode(instr) == OP_BL) { | ||||
|                     u32 offset = instr & 0xFFFFFF; | ||||
|         if (index.column() == 0) { | ||||
|             return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0')); | ||||
|         } else if (index.column() == 1) { | ||||
|             return QString::fromStdString(disassembly); | ||||
|         } else if (index.column() == 2) { | ||||
|             if (Symbols::HasSymbol(address)) { | ||||
|                 TSymbol symbol = Symbols::GetSymbol(address); | ||||
|                 return QString("%1 - Size:%2") | ||||
|                     .arg(QString::fromStdString(symbol.name)) | ||||
|                     .arg(symbol.size / 4); // divide by 4 to get instruction count
 | ||||
|             } else if (ARM_Disasm::Decode(instr) == OP_BL) { | ||||
|                 u32 offset = instr & 0xFFFFFF; | ||||
| 
 | ||||
|                     // Sign-extend the 24-bit offset
 | ||||
|                     if ((offset >> 23) & 1) | ||||
|                         offset |= 0xFF000000; | ||||
|                 // Sign-extend the 24-bit offset
 | ||||
|                 if ((offset >> 23) & 1) | ||||
|                     offset |= 0xFF000000; | ||||
| 
 | ||||
|                     // Pre-compute the left-shift and the prefetch offset
 | ||||
|                     offset <<= 2; | ||||
|                     offset += 8; | ||||
|                 // Pre-compute the left-shift and the prefetch offset
 | ||||
|                 offset <<= 2; | ||||
|                 offset += 8; | ||||
| 
 | ||||
|                     TSymbol symbol = Symbols::GetSymbol(address + offset); | ||||
|                     return QString("    --> %1").arg(QString::fromStdString(symbol.name)); | ||||
|                 } | ||||
|                 TSymbol symbol = Symbols::GetSymbol(address + offset); | ||||
|                 return QString("    --> %1").arg(QString::fromStdString(symbol.name)); | ||||
|             } | ||||
| 
 | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case Qt::BackgroundRole: | ||||
|         { | ||||
|             unsigned int address = base_address + 4 * index.row(); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|             if (breakpoints.IsAddressBreakPoint(address)) | ||||
|                 return QBrush(QColor(0xFF, 0xC0, 0xC0)); | ||||
|             else if (address == program_counter) | ||||
|                 return QBrush(QColor(0xC0, 0xC0, 0xFF)); | ||||
|     case Qt::BackgroundRole: { | ||||
|         unsigned int address = base_address + 4 * index.row(); | ||||
| 
 | ||||
|             break; | ||||
|         if (breakpoints.IsAddressBreakPoint(address)) | ||||
|             return QBrush(QColor(0xFF, 0xC0, 0xC0)); | ||||
|         else if (address == program_counter) | ||||
|             return QBrush(QColor(0xC0, 0xC0, 0xFF)); | ||||
| 
 | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Qt::FontRole: { | ||||
|         if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column
 | ||||
|             return GetMonospaceFont(); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|         case Qt::FontRole: | ||||
|         { | ||||
|             if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column
 | ||||
|                 return GetMonospaceFont(); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         default: | ||||
|             break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     return QVariant(); | ||||
|  | @ -103,7 +102,7 @@ const BreakPoints& DisassemblerModel::GetBreakPoints() const { | |||
| void DisassemblerModel::ParseFromAddress(unsigned int address) { | ||||
| 
 | ||||
|     // NOTE: A too large value causes lagging when scrolling the disassembly
 | ||||
|     const unsigned int chunk_size = 1000*500; | ||||
|     const unsigned int chunk_size = 1000 * 500; | ||||
| 
 | ||||
|     // If we haven't loaded anything yet, initialize base address to the parameter address
 | ||||
|     if (code_size == 0) | ||||
|  | @ -165,23 +164,26 @@ void DisassemblerModel::SetNextInstruction(unsigned int address) { | |||
|     emit dataChanged(prev_index, prev_index); | ||||
| } | ||||
| 
 | ||||
| DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) : | ||||
|     QDockWidget(parent), base_addr(0), emu_thread(emu_thread) { | ||||
| DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) | ||||
|     : QDockWidget(parent), base_addr(0), emu_thread(emu_thread) { | ||||
| 
 | ||||
|     disasm_ui.setupUi(this); | ||||
| 
 | ||||
|     RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut); | ||||
|     RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut); | ||||
|     RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut); | ||||
|     RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), Qt::ApplicationShortcut); | ||||
|     RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), | ||||
|                    Qt::ApplicationShortcut); | ||||
| 
 | ||||
|     connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep())); | ||||
|     connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause())); | ||||
|     connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue())); | ||||
| 
 | ||||
|     connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, SLOT(OnToggleStartStop())); | ||||
|     connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, | ||||
|             SLOT(OnToggleStartStop())); | ||||
|     connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep())); | ||||
|     connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, SLOT(OnStepInto())); | ||||
|     connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, | ||||
|             SLOT(OnStepInto())); | ||||
| 
 | ||||
|     setEnabled(false); | ||||
| } | ||||
|  | @ -195,7 +197,8 @@ void DisassemblerWidget::Init() { | |||
| 
 | ||||
|     QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::g_app_core->GetPC()); | ||||
|     disasm_ui.treeView->scrollTo(model_index); | ||||
|     disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | ||||
|     disasm_ui.treeView->selectionModel()->setCurrentIndex( | ||||
|         model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | ||||
| } | ||||
| 
 | ||||
| void DisassemblerWidget::OnContinue() { | ||||
|  | @ -234,7 +237,8 @@ void DisassemblerWidget::OnDebugModeEntered() { | |||
| 
 | ||||
|     QModelIndex model_index = model->IndexFromAbsoluteAddress(next_instr); | ||||
|     disasm_ui.treeView->scrollTo(model_index); | ||||
|     disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | ||||
|     disasm_ui.treeView->selectionModel()->setCurrentIndex( | ||||
|         model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | ||||
| } | ||||
| 
 | ||||
| void DisassemblerWidget::OnDebugModeLeft() { | ||||
|  | @ -254,10 +258,12 @@ void DisassemblerWidget::OnEmulationStarting(EmuThread* emu_thread) { | |||
|     model = new DisassemblerModel(this); | ||||
|     disasm_ui.treeView->setModel(model); | ||||
| 
 | ||||
|     connect(disasm_ui.treeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), | ||||
|         model, SLOT(OnSelectionChanged(const QModelIndex&))); | ||||
|     connect(disasm_ui.treeView->selectionModel(), | ||||
|             SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), model, | ||||
|             SLOT(OnSelectionChanged(const QModelIndex&))); | ||||
|     connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), model, SLOT(OnSetOrUnsetBreakpoint())); | ||||
|     connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model, SLOT(OnSetOrUnsetBreakpoint())); | ||||
|     connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model, | ||||
|             SLOT(OnSetOrUnsetBreakpoint())); | ||||
| 
 | ||||
|     Init(); | ||||
|     setEnabled(true); | ||||
|  |  | |||
|  | @ -15,8 +15,7 @@ | |||
| class QAction; | ||||
| class EmuThread; | ||||
| 
 | ||||
| class DisassemblerModel : public QAbstractListModel | ||||
| { | ||||
| class DisassemblerModel : public QAbstractListModel { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  | @ -46,8 +45,7 @@ private: | |||
|     mutable BreakPoints breakpoints; | ||||
| }; | ||||
| 
 | ||||
| class DisassemblerWidget : public QDockWidget | ||||
| { | ||||
| class DisassemblerWidget : public QDockWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  |  | |||
|  | @ -9,69 +9,62 @@ | |||
| 
 | ||||
| extern GraphicsDebugger g_debugger; | ||||
| 
 | ||||
| GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) : QAbstractListModel(parent), command_count(0) | ||||
| { | ||||
| GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) | ||||
|     : QAbstractListModel(parent), command_count(0) { | ||||
|     connect(this, SIGNAL(GXCommandFinished(int)), this, SLOT(OnGXCommandFinishedInternal(int))); | ||||
| } | ||||
| 
 | ||||
| int GPUCommandStreamItemModel::rowCount(const QModelIndex& parent) const | ||||
| { | ||||
| int GPUCommandStreamItemModel::rowCount(const QModelIndex& parent) const { | ||||
|     return command_count; | ||||
| } | ||||
| 
 | ||||
| QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) const | ||||
| { | ||||
| QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) const { | ||||
|     if (!index.isValid()) | ||||
|         return QVariant(); | ||||
| 
 | ||||
|     int command_index = index.row(); | ||||
|     const GSP_GPU::Command& command = GetDebugger()->ReadGXCommandHistory(command_index); | ||||
|     if (role == Qt::DisplayRole) | ||||
|     { | ||||
|     if (role == Qt::DisplayRole) { | ||||
|         std::map<GSP_GPU::CommandId, const char*> command_names = { | ||||
|             { GSP_GPU::CommandId::REQUEST_DMA, "REQUEST_DMA" }, | ||||
|             { GSP_GPU::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST" }, | ||||
|             { GSP_GPU::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL" }, | ||||
|             { GSP_GPU::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER" }, | ||||
|             { GSP_GPU::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY" }, | ||||
|             { GSP_GPU::CommandId::CACHE_FLUSH, "CACHE_FLUSH" }, | ||||
|             {GSP_GPU::CommandId::REQUEST_DMA, "REQUEST_DMA"}, | ||||
|             {GSP_GPU::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST"}, | ||||
|             {GSP_GPU::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL"}, | ||||
|             {GSP_GPU::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER"}, | ||||
|             {GSP_GPU::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY"}, | ||||
|             {GSP_GPU::CommandId::CACHE_FLUSH, "CACHE_FLUSH"}, | ||||
|         }; | ||||
|         const u32* command_data = reinterpret_cast<const u32*>(&command); | ||||
|         QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9").arg(command_names[command.id]) | ||||
|                         .arg(command_data[0], 8, 16, QLatin1Char('0')) | ||||
|                         .arg(command_data[1], 8, 16, QLatin1Char('0')) | ||||
|                         .arg(command_data[2], 8, 16, QLatin1Char('0')) | ||||
|                         .arg(command_data[3], 8, 16, QLatin1Char('0')) | ||||
|                         .arg(command_data[4], 8, 16, QLatin1Char('0')) | ||||
|                         .arg(command_data[5], 8, 16, QLatin1Char('0')) | ||||
|                         .arg(command_data[6], 8, 16, QLatin1Char('0')) | ||||
|                         .arg(command_data[7], 8, 16, QLatin1Char('0')); | ||||
|         QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9") | ||||
|                           .arg(command_names[command.id]) | ||||
|                           .arg(command_data[0], 8, 16, QLatin1Char('0')) | ||||
|                           .arg(command_data[1], 8, 16, QLatin1Char('0')) | ||||
|                           .arg(command_data[2], 8, 16, QLatin1Char('0')) | ||||
|                           .arg(command_data[3], 8, 16, QLatin1Char('0')) | ||||
|                           .arg(command_data[4], 8, 16, QLatin1Char('0')) | ||||
|                           .arg(command_data[5], 8, 16, QLatin1Char('0')) | ||||
|                           .arg(command_data[6], 8, 16, QLatin1Char('0')) | ||||
|                           .arg(command_data[7], 8, 16, QLatin1Char('0')); | ||||
|         return QVariant(str); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|     } else { | ||||
|         return QVariant(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void GPUCommandStreamItemModel::GXCommandProcessed(int total_command_count) | ||||
| { | ||||
| void GPUCommandStreamItemModel::GXCommandProcessed(int total_command_count) { | ||||
|     emit GXCommandFinished(total_command_count); | ||||
| } | ||||
| 
 | ||||
| void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_count) | ||||
| { | ||||
| void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_count) { | ||||
|     if (total_command_count == 0) | ||||
|         return; | ||||
| 
 | ||||
|     int prev_command_count = command_count; | ||||
|     command_count = total_command_count; | ||||
|     emit dataChanged(index(prev_command_count,0), index(total_command_count-1,0)); | ||||
|     emit dataChanged(index(prev_command_count, 0), index(total_command_count - 1, 0)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) : QDockWidget(tr("Graphics Debugger"), parent) | ||||
| { | ||||
| GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) | ||||
|     : QDockWidget(tr("Graphics Debugger"), parent) { | ||||
|     setObjectName("GraphicsDebugger"); | ||||
| 
 | ||||
|     GPUCommandStreamItemModel* command_model = new GPUCommandStreamItemModel(this); | ||||
|  |  | |||
|  | @ -9,8 +9,8 @@ | |||
| 
 | ||||
| #include "video_core/gpu_debugger.h" | ||||
| 
 | ||||
| class GPUCommandStreamItemModel : public QAbstractListModel, public GraphicsDebugger::DebuggerObserver | ||||
| { | ||||
| class GPUCommandStreamItemModel : public QAbstractListModel, | ||||
|                                   public GraphicsDebugger::DebuggerObserver { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  | @ -32,8 +32,7 @@ private: | |||
|     int command_count; | ||||
| }; | ||||
| 
 | ||||
| class GPUCommandStreamWidget : public QDockWidget | ||||
| { | ||||
| class GPUCommandStreamWidget : public QDockWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  |  | |||
|  | @ -8,25 +8,21 @@ | |||
| 
 | ||||
| BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context, | ||||
|                                                const QString& title, QWidget* parent) | ||||
|     : QDockWidget(title, parent), BreakPointObserver(debug_context) | ||||
| { | ||||
|     : QDockWidget(title, parent), BreakPointObserver(debug_context) { | ||||
|     qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); | ||||
| 
 | ||||
|     connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); | ||||
| 
 | ||||
|     // NOTE: This signal is emitted from a non-GUI thread, but connect() takes
 | ||||
|     //       care of delaying its handling to the GUI thread.
 | ||||
|     connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), | ||||
|             this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), this, | ||||
|             SLOT(OnBreakPointHit(Pica::DebugContext::Event, void*)), Qt::BlockingQueuedConnection); | ||||
| } | ||||
| 
 | ||||
| void BreakPointObserverDock::OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) | ||||
| { | ||||
| void BreakPointObserverDock::OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) { | ||||
|     emit BreakPointHit(event, data); | ||||
| } | ||||
| 
 | ||||
| void BreakPointObserverDock::OnPicaResume() | ||||
| { | ||||
| void BreakPointObserverDock::OnPicaResume() { | ||||
|     emit Resumed(); | ||||
| } | ||||
|  |  | |||
|  | @ -13,7 +13,8 @@ | |||
|  * This is because the Pica breakpoint callbacks are called from a non-GUI thread, while | ||||
|  * the widget usually wants to perform reactions in the GUI thread. | ||||
|  */ | ||||
| class BreakPointObserverDock : public QDockWidget, protected Pica::DebugContext::BreakPointObserver { | ||||
| class BreakPointObserverDock : public QDockWidget, | ||||
|                                protected Pica::DebugContext::BreakPointObserver { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  |  | |||
|  | @ -16,39 +16,33 @@ | |||
| BreakPointModel::BreakPointModel(std::shared_ptr<Pica::DebugContext> debug_context, QObject* parent) | ||||
|     : QAbstractListModel(parent), context_weak(debug_context), | ||||
|       at_breakpoint(debug_context->at_breakpoint), | ||||
|       active_breakpoint(debug_context->active_breakpoint) | ||||
| { | ||||
| 
 | ||||
|       active_breakpoint(debug_context->active_breakpoint) { | ||||
| } | ||||
| 
 | ||||
| int BreakPointModel::columnCount(const QModelIndex& parent) const | ||||
| { | ||||
| int BreakPointModel::columnCount(const QModelIndex& parent) const { | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int BreakPointModel::rowCount(const QModelIndex& parent) const | ||||
| { | ||||
| int BreakPointModel::rowCount(const QModelIndex& parent) const { | ||||
|     return static_cast<int>(Pica::DebugContext::Event::NumEvents); | ||||
| } | ||||
| 
 | ||||
| QVariant BreakPointModel::data(const QModelIndex& index, int role) const | ||||
| { | ||||
| QVariant BreakPointModel::data(const QModelIndex& index, int role) const { | ||||
|     const auto event = static_cast<Pica::DebugContext::Event>(index.row()); | ||||
| 
 | ||||
|     switch (role) { | ||||
|     case Qt::DisplayRole: | ||||
|     { | ||||
|     case Qt::DisplayRole: { | ||||
|         if (index.column() == 0) { | ||||
|             static const std::map<Pica::DebugContext::Event, QString> map = { | ||||
|                 { Pica::DebugContext::Event::PicaCommandLoaded, tr("Pica command loaded") }, | ||||
|                 { Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed") }, | ||||
|                 { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") }, | ||||
|                 { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") }, | ||||
|                 { Pica::DebugContext::Event::VertexShaderInvocation, tr("Vertex shader invocation") }, | ||||
|                 { Pica::DebugContext::Event::IncomingDisplayTransfer, tr("Incoming display transfer") }, | ||||
|                 { Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed") }, | ||||
|                 { Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped") } | ||||
|             }; | ||||
|                 {Pica::DebugContext::Event::PicaCommandLoaded, tr("Pica command loaded")}, | ||||
|                 {Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed")}, | ||||
|                 {Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch")}, | ||||
|                 {Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")}, | ||||
|                 {Pica::DebugContext::Event::VertexShaderInvocation, tr("Vertex shader invocation")}, | ||||
|                 {Pica::DebugContext::Event::IncomingDisplayTransfer, | ||||
|                  tr("Incoming display transfer")}, | ||||
|                 {Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed")}, | ||||
|                 {Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped")}}; | ||||
| 
 | ||||
|             DEBUG_ASSERT(map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); | ||||
|             return (map.find(event) != map.end()) ? map.at(event) : QString(); | ||||
|  | @ -57,23 +51,20 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const | |||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Qt::CheckStateRole: | ||||
|     { | ||||
|     case Qt::CheckStateRole: { | ||||
|         if (index.column() == 0) | ||||
|             return data(index, Role_IsEnabled).toBool() ? Qt::Checked : Qt::Unchecked; | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Qt::BackgroundRole: | ||||
|     { | ||||
|     case Qt::BackgroundRole: { | ||||
|         if (at_breakpoint && index.row() == static_cast<int>(active_breakpoint)) { | ||||
|             return QBrush(QColor(0xE0, 0xE0, 0x10)); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Role_IsEnabled: | ||||
|     { | ||||
|     case Role_IsEnabled: { | ||||
|         auto context = context_weak.lock(); | ||||
|         return context && context->breakpoints[(int)event].enabled; | ||||
|     } | ||||
|  | @ -84,8 +75,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const | |||
|     return QVariant(); | ||||
| } | ||||
| 
 | ||||
| Qt::ItemFlags BreakPointModel::flags(const QModelIndex &index) const | ||||
| { | ||||
| Qt::ItemFlags BreakPointModel::flags(const QModelIndex& index) const { | ||||
|     if (!index.isValid()) | ||||
|         return 0; | ||||
| 
 | ||||
|  | @ -95,14 +85,11 @@ Qt::ItemFlags BreakPointModel::flags(const QModelIndex &index) const | |||
|     return flags; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) | ||||
| { | ||||
| bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) { | ||||
|     const auto event = static_cast<Pica::DebugContext::Event>(index.row()); | ||||
| 
 | ||||
|     switch (role) { | ||||
|     case Qt::CheckStateRole: | ||||
|     { | ||||
|     case Qt::CheckStateRole: { | ||||
|         if (index.column() != 0) | ||||
|             return false; | ||||
| 
 | ||||
|  | @ -120,9 +107,7 @@ bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, i | |||
|     return false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) | ||||
| { | ||||
| void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) { | ||||
|     auto context = context_weak.lock(); | ||||
|     if (!context) | ||||
|         return; | ||||
|  | @ -133,8 +118,7 @@ void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) | |||
|                      createIndex(static_cast<int>(event), 0)); | ||||
| } | ||||
| 
 | ||||
| void BreakPointModel::OnResumed() | ||||
| { | ||||
| void BreakPointModel::OnResumed() { | ||||
|     auto context = context_weak.lock(); | ||||
|     if (!context) | ||||
|         return; | ||||
|  | @ -145,12 +129,10 @@ void BreakPointModel::OnResumed() | |||
|     active_breakpoint = context->active_breakpoint; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::DebugContext> debug_context, | ||||
|                                                      QWidget* parent) | ||||
| GraphicsBreakPointsWidget::GraphicsBreakPointsWidget( | ||||
|     std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent) | ||||
|     : QDockWidget(tr("Pica Breakpoints"), parent), | ||||
|       Pica::DebugContext::BreakPointObserver(debug_context) | ||||
| { | ||||
|       Pica::DebugContext::BreakPointObserver(debug_context) { | ||||
|     setObjectName("PicaBreakPointsWidget"); | ||||
| 
 | ||||
|     status_text = new QLabel(tr("Emulation running")); | ||||
|  | @ -165,23 +147,21 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug | |||
| 
 | ||||
|     qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); | ||||
| 
 | ||||
|     connect(breakpoint_list, SIGNAL(doubleClicked(const QModelIndex&)), | ||||
|             this, SLOT(OnItemDoubleClicked(const QModelIndex&))); | ||||
|     connect(breakpoint_list, SIGNAL(doubleClicked(const QModelIndex&)), this, | ||||
|             SLOT(OnItemDoubleClicked(const QModelIndex&))); | ||||
| 
 | ||||
|     connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested())); | ||||
| 
 | ||||
|     connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), | ||||
|             this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), this, | ||||
|             SLOT(OnBreakPointHit(Pica::DebugContext::Event, void*)), Qt::BlockingQueuedConnection); | ||||
|     connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); | ||||
| 
 | ||||
|     connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), | ||||
|             breakpoint_model, SLOT(OnBreakPointHit(Pica::DebugContext::Event)), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), breakpoint_model, | ||||
|             SLOT(OnBreakPointHit(Pica::DebugContext::Event)), Qt::BlockingQueuedConnection); | ||||
|     connect(this, SIGNAL(Resumed()), breakpoint_model, SLOT(OnResumed())); | ||||
| 
 | ||||
|     connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&,const QModelIndex&)), | ||||
|             breakpoint_model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))); | ||||
|     connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&, const QModelIndex&)), | ||||
|             breakpoint_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&))); | ||||
| 
 | ||||
|     QWidget* main_widget = new QWidget; | ||||
|     auto main_layout = new QVBoxLayout; | ||||
|  | @ -197,38 +177,32 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug | |||
|     setWidget(main_widget); | ||||
| } | ||||
| 
 | ||||
| void GraphicsBreakPointsWidget::OnPicaBreakPointHit(Event event, void* data) | ||||
| { | ||||
| void GraphicsBreakPointsWidget::OnPicaBreakPointHit(Event event, void* data) { | ||||
|     // Process in GUI thread
 | ||||
|     emit BreakPointHit(event, data); | ||||
| } | ||||
| 
 | ||||
| void GraphicsBreakPointsWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) | ||||
| { | ||||
| void GraphicsBreakPointsWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) { | ||||
|     status_text->setText(tr("Emulation halted at breakpoint")); | ||||
|     resume_button->setEnabled(true); | ||||
| } | ||||
| 
 | ||||
| void GraphicsBreakPointsWidget::OnPicaResume() | ||||
| { | ||||
| void GraphicsBreakPointsWidget::OnPicaResume() { | ||||
|     // Process in GUI thread
 | ||||
|     emit Resumed(); | ||||
| } | ||||
| 
 | ||||
| void GraphicsBreakPointsWidget::OnResumed() | ||||
| { | ||||
| void GraphicsBreakPointsWidget::OnResumed() { | ||||
|     status_text->setText(tr("Emulation running")); | ||||
|     resume_button->setEnabled(false); | ||||
| } | ||||
| 
 | ||||
| void GraphicsBreakPointsWidget::OnResumeRequested() | ||||
| { | ||||
| void GraphicsBreakPointsWidget::OnResumeRequested() { | ||||
|     if (auto context = context_weak.lock()) | ||||
|         context->Resume(); | ||||
| } | ||||
| 
 | ||||
| void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index) | ||||
| { | ||||
| void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index) { | ||||
|     if (!index.isValid()) | ||||
|         return; | ||||
| 
 | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ public: | |||
|     int columnCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|     int rowCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; | ||||
|     Qt::ItemFlags flags(const QModelIndex &index) const override; | ||||
|     Qt::ItemFlags flags(const QModelIndex& index) const override; | ||||
| 
 | ||||
|     bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,9 +20,9 @@ | |||
| 
 | ||||
| #include "common/vector_math.h" | ||||
| 
 | ||||
| #include "video_core/debug_utils/debug_utils.h" | ||||
| #include "video_core/pica.h" | ||||
| #include "video_core/pica_state.h" | ||||
| #include "video_core/debug_utils/debug_utils.h" | ||||
| 
 | ||||
| QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { | ||||
|     QImage decoded_image(info.width, info.height, QImage::Format_ARGB32); | ||||
|  | @ -38,7 +38,8 @@ QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { | |||
| 
 | ||||
| class TextureInfoWidget : public QWidget { | ||||
| public: | ||||
|     TextureInfoWidget(u8* src, const Pica::DebugUtils::TextureInfo& info, QWidget* parent = nullptr) : QWidget(parent) { | ||||
|     TextureInfoWidget(u8* src, const Pica::DebugUtils::TextureInfo& info, QWidget* parent = nullptr) | ||||
|         : QWidget(parent) { | ||||
|         QLabel* image_widget = new QLabel; | ||||
|         QPixmap image_pixmap = QPixmap::fromImage(LoadTexture(src, info)); | ||||
|         image_pixmap = image_pixmap.scaled(200, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation); | ||||
|  | @ -51,7 +52,6 @@ public: | |||
| }; | ||||
| 
 | ||||
| GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(parent) { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| int GPUCommandListModel::rowCount(const QModelIndex& parent) const { | ||||
|  | @ -70,7 +70,7 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { | |||
| 
 | ||||
|     if (role == Qt::DisplayRole) { | ||||
|         QString content; | ||||
|         switch ( index.column() ) { | ||||
|         switch (index.column()) { | ||||
|         case 0: | ||||
|             return QString::fromLatin1(Pica::Regs::GetCommandName(write.cmd_id).c_str()); | ||||
|         case 1: | ||||
|  | @ -88,9 +88,8 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { | |||
| } | ||||
| 
 | ||||
| QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientation, int role) const { | ||||
|     switch(role) { | ||||
|     case Qt::DisplayRole: | ||||
|     { | ||||
|     switch (role) { | ||||
|     case Qt::DisplayRole: { | ||||
|         switch (section) { | ||||
|         case 0: | ||||
|             return tr("Command Name"); | ||||
|  | @ -117,14 +116,14 @@ void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& | |||
|     endResetModel(); | ||||
| } | ||||
| 
 | ||||
| #define COMMAND_IN_RANGE(cmd_id, reg_name)   \ | ||||
|     (cmd_id >= PICA_REG_INDEX(reg_name) &&   \ | ||||
| #define COMMAND_IN_RANGE(cmd_id, reg_name)                                                         \ | ||||
|     (cmd_id >= PICA_REG_INDEX(reg_name) &&                                                         \ | ||||
|      cmd_id < PICA_REG_INDEX(reg_name) + sizeof(decltype(Pica::g_state.regs.reg_name)) / 4) | ||||
| 
 | ||||
| void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { | ||||
|     const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); | ||||
|     if (COMMAND_IN_RANGE(command_id, texture0) || | ||||
|         COMMAND_IN_RANGE(command_id, texture1) || | ||||
|     const unsigned int command_id = | ||||
|         list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); | ||||
|     if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || | ||||
|         COMMAND_IN_RANGE(command_id, texture2)) { | ||||
| 
 | ||||
|         unsigned index; | ||||
|  | @ -148,9 +147,9 @@ void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { | |||
| void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { | ||||
|     QWidget* new_info_widget = nullptr; | ||||
| 
 | ||||
|     const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); | ||||
|     if (COMMAND_IN_RANGE(command_id, texture0) || | ||||
|         COMMAND_IN_RANGE(command_id, texture1) || | ||||
|     const unsigned int command_id = | ||||
|         list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); | ||||
|     if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || | ||||
|         COMMAND_IN_RANGE(command_id, texture2)) { | ||||
| 
 | ||||
|         unsigned index; | ||||
|  | @ -179,7 +178,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { | |||
| } | ||||
| #undef COMMAND_IN_RANGE | ||||
| 
 | ||||
| GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pica Command List"), parent) { | ||||
| GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) | ||||
|     : QDockWidget(tr("Pica Command List"), parent) { | ||||
|     setObjectName("Pica Command List"); | ||||
|     GPUCommandListModel* model = new GPUCommandListModel(this); | ||||
| 
 | ||||
|  | @ -191,23 +191,24 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi | |||
|     list_widget->setRootIsDecorated(false); | ||||
|     list_widget->setUniformRowHeights(true); | ||||
| 
 | ||||
| #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | ||||
| #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||||
|     list_widget->header()->setSectionResizeMode(QHeaderView::ResizeToContents); | ||||
| #else | ||||
|     list_widget->header()->setResizeMode(QHeaderView::ResizeToContents); | ||||
| #endif | ||||
| 
 | ||||
|     connect(list_widget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)), | ||||
|             this, SLOT(SetCommandInfo(const QModelIndex&))); | ||||
|     connect(list_widget, SIGNAL(doubleClicked(const QModelIndex&)), | ||||
|             this, SLOT(OnCommandDoubleClicked(const QModelIndex&))); | ||||
|     connect(list_widget->selectionModel(), | ||||
|             SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, | ||||
|             SLOT(SetCommandInfo(const QModelIndex&))); | ||||
|     connect(list_widget, SIGNAL(doubleClicked(const QModelIndex&)), this, | ||||
|             SLOT(OnCommandDoubleClicked(const QModelIndex&))); | ||||
| 
 | ||||
|     toggle_tracing = new QPushButton(tr("Start Tracing")); | ||||
|     QPushButton* copy_all = new QPushButton(tr("Copy All")); | ||||
| 
 | ||||
|     connect(toggle_tracing, SIGNAL(clicked()), this, SLOT(OnToggleTracing())); | ||||
|     connect(this, SIGNAL(TracingFinished(const Pica::DebugUtils::PicaTrace&)), | ||||
|             model, SLOT(OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&))); | ||||
|     connect(this, SIGNAL(TracingFinished(const Pica::DebugUtils::PicaTrace&)), model, | ||||
|             SLOT(OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&))); | ||||
| 
 | ||||
|     connect(copy_all, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard())); | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,14 +7,13 @@ | |||
| #include <QAbstractListModel> | ||||
| #include <QDockWidget> | ||||
| 
 | ||||
| #include "video_core/gpu_debugger.h" | ||||
| #include "video_core/debug_utils/debug_utils.h" | ||||
| #include "video_core/gpu_debugger.h" | ||||
| 
 | ||||
| class QPushButton; | ||||
| class QTreeView; | ||||
| 
 | ||||
| class GPUCommandListModel : public QAbstractListModel | ||||
| { | ||||
| class GPUCommandListModel : public QAbstractListModel { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  | @ -27,7 +26,8 @@ public: | |||
|     int columnCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|     int rowCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; | ||||
|     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; | ||||
|     QVariant headerData(int section, Qt::Orientation orientation, | ||||
|                         int role = Qt::DisplayRole) const override; | ||||
| 
 | ||||
| public slots: | ||||
|     void OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& trace); | ||||
|  | @ -36,8 +36,7 @@ private: | |||
|     Pica::DebugUtils::PicaTrace pica_trace; | ||||
| }; | ||||
| 
 | ||||
| class GPUCommandListWidget : public QDockWidget | ||||
| { | ||||
| class GPUCommandListWidget : public QDockWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  |  | |||
|  | @ -17,18 +17,20 @@ | |||
| 
 | ||||
| #include "common/color.h" | ||||
| 
 | ||||
| #include "core/memory.h" | ||||
| #include "core/hw/gpu.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| #include "video_core/pica.h" | ||||
| #include "video_core/pica_state.h" | ||||
| #include "video_core/utils.h" | ||||
| 
 | ||||
| SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_) : QLabel(parent), surface_widget(surface_widget_) {} | ||||
| SurfacePicture::~SurfacePicture() {} | ||||
| SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_) | ||||
|     : QLabel(parent), surface_widget(surface_widget_) { | ||||
| } | ||||
| SurfacePicture::~SurfacePicture() { | ||||
| } | ||||
| 
 | ||||
| void SurfacePicture::mousePressEvent(QMouseEvent* event) | ||||
| { | ||||
| void SurfacePicture::mousePressEvent(QMouseEvent* event) { | ||||
|     // Only do something while the left mouse button is held down
 | ||||
|     if (!(event->buttons() & Qt::LeftButton)) | ||||
|         return; | ||||
|  | @ -41,18 +43,15 @@ void SurfacePicture::mousePressEvent(QMouseEvent* event) | |||
|                              event->y() * pixmap()->height() / height()); | ||||
| } | ||||
| 
 | ||||
| void SurfacePicture::mouseMoveEvent(QMouseEvent* event) | ||||
| { | ||||
| void SurfacePicture::mouseMoveEvent(QMouseEvent* event) { | ||||
|     // We also want to handle the event if the user moves the mouse while holding down the LMB
 | ||||
|     mousePressEvent(event); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, | ||||
|                                                      QWidget* parent) | ||||
|                                              QWidget* parent) | ||||
|     : BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), | ||||
|       surface_source(Source::ColorBuffer) | ||||
| { | ||||
|       surface_source(Source::ColorBuffer) { | ||||
|     setObjectName("PicaSurface"); | ||||
| 
 | ||||
|     surface_source_list = new QComboBox; | ||||
|  | @ -124,13 +123,20 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> | |||
| 
 | ||||
|     // Connections
 | ||||
|     connect(this, SIGNAL(Update()), this, SLOT(OnUpdate())); | ||||
|     connect(surface_source_list, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSurfaceSourceChanged(int))); | ||||
|     connect(surface_address_control, SIGNAL(ValueChanged(qint64)), this, SLOT(OnSurfaceAddressChanged(qint64))); | ||||
|     connect(surface_width_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfaceWidthChanged(int))); | ||||
|     connect(surface_height_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfaceHeightChanged(int))); | ||||
|     connect(surface_format_control, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSurfaceFormatChanged(int))); | ||||
|     connect(surface_picker_x_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfacePickerXChanged(int))); | ||||
|     connect(surface_picker_y_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfacePickerYChanged(int))); | ||||
|     connect(surface_source_list, SIGNAL(currentIndexChanged(int)), this, | ||||
|             SLOT(OnSurfaceSourceChanged(int))); | ||||
|     connect(surface_address_control, SIGNAL(ValueChanged(qint64)), this, | ||||
|             SLOT(OnSurfaceAddressChanged(qint64))); | ||||
|     connect(surface_width_control, SIGNAL(valueChanged(int)), this, | ||||
|             SLOT(OnSurfaceWidthChanged(int))); | ||||
|     connect(surface_height_control, SIGNAL(valueChanged(int)), this, | ||||
|             SLOT(OnSurfaceHeightChanged(int))); | ||||
|     connect(surface_format_control, SIGNAL(currentIndexChanged(int)), this, | ||||
|             SLOT(OnSurfaceFormatChanged(int))); | ||||
|     connect(surface_picker_x_control, SIGNAL(valueChanged(int)), this, | ||||
|             SLOT(OnSurfacePickerXChanged(int))); | ||||
|     connect(surface_picker_y_control, SIGNAL(valueChanged(int)), this, | ||||
|             SLOT(OnSurfacePickerYChanged(int))); | ||||
|     connect(save_surface, SIGNAL(clicked()), this, SLOT(SaveSurface())); | ||||
| 
 | ||||
|     auto main_widget = new QWidget; | ||||
|  | @ -203,25 +209,21 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) { | ||||
|     emit Update(); | ||||
|     widget()->setEnabled(true); | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnResumed() | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnResumed() { | ||||
|     widget()->setEnabled(false); | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value) | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value) { | ||||
|     surface_source = static_cast<Source>(new_value); | ||||
|     emit Update(); | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) { | ||||
|     if (surface_address != new_value) { | ||||
|         surface_address = static_cast<unsigned>(new_value); | ||||
| 
 | ||||
|  | @ -230,8 +232,7 @@ void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) { | ||||
|     if (surface_width != static_cast<unsigned>(new_value)) { | ||||
|         surface_width = static_cast<unsigned>(new_value); | ||||
| 
 | ||||
|  | @ -240,8 +241,7 @@ void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) { | ||||
|     if (surface_height != static_cast<unsigned>(new_value)) { | ||||
|         surface_height = static_cast<unsigned>(new_value); | ||||
| 
 | ||||
|  | @ -250,8 +250,7 @@ void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) { | ||||
|     if (surface_format != static_cast<Format>(new_value)) { | ||||
|         surface_format = static_cast<Format>(new_value); | ||||
| 
 | ||||
|  | @ -260,24 +259,21 @@ void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnSurfacePickerXChanged(int new_value) | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnSurfacePickerXChanged(int new_value) { | ||||
|     if (surface_picker_x != new_value) { | ||||
|         surface_picker_x = new_value; | ||||
|         Pick(surface_picker_x, surface_picker_y); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnSurfacePickerYChanged(int new_value) | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnSurfacePickerYChanged(int new_value) { | ||||
|     if (surface_picker_y != new_value) { | ||||
|         surface_picker_y = new_value; | ||||
|         Pick(surface_picker_x, surface_picker_y); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::Pick(int x, int y) | ||||
| { | ||||
| void GraphicsSurfaceWidget::Pick(int x, int y) { | ||||
|     surface_picker_x_control->setValue(x); | ||||
|     surface_picker_y_control->setValue(y); | ||||
| 
 | ||||
|  | @ -312,74 +308,63 @@ void GraphicsSurfaceWidget::Pick(int x, int y) | |||
| 
 | ||||
|     auto GetText = [offset](Format format, const u8* pixel) { | ||||
|         switch (format) { | ||||
|         case Format::RGBA8: | ||||
|         { | ||||
|         case Format::RGBA8: { | ||||
|             auto value = Color::DecodeRGBA8(pixel) / 255.0f; | ||||
|             return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") | ||||
|                       .arg(QString::number(value.r(), 'f', 2)) | ||||
|                       .arg(QString::number(value.g(), 'f', 2)) | ||||
|                       .arg(QString::number(value.b(), 'f', 2)) | ||||
|                       .arg(QString::number(value.a(), 'f', 2)); | ||||
|                 .arg(QString::number(value.r(), 'f', 2)) | ||||
|                 .arg(QString::number(value.g(), 'f', 2)) | ||||
|                 .arg(QString::number(value.b(), 'f', 2)) | ||||
|                 .arg(QString::number(value.a(), 'f', 2)); | ||||
|         } | ||||
|         case Format::RGB8: | ||||
|         { | ||||
|         case Format::RGB8: { | ||||
|             auto value = Color::DecodeRGB8(pixel) / 255.0f; | ||||
|             return QString("Red: %1, Green: %2, Blue: %3") | ||||
|                       .arg(QString::number(value.r(), 'f', 2)) | ||||
|                       .arg(QString::number(value.g(), 'f', 2)) | ||||
|                       .arg(QString::number(value.b(), 'f', 2)); | ||||
|                 .arg(QString::number(value.r(), 'f', 2)) | ||||
|                 .arg(QString::number(value.g(), 'f', 2)) | ||||
|                 .arg(QString::number(value.b(), 'f', 2)); | ||||
|         } | ||||
|         case Format::RGB5A1: | ||||
|         { | ||||
|         case Format::RGB5A1: { | ||||
|             auto value = Color::DecodeRGB5A1(pixel) / 255.0f; | ||||
|             return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") | ||||
|                       .arg(QString::number(value.r(), 'f', 2)) | ||||
|                       .arg(QString::number(value.g(), 'f', 2)) | ||||
|                       .arg(QString::number(value.b(), 'f', 2)) | ||||
|                       .arg(QString::number(value.a(), 'f', 2)); | ||||
|                 .arg(QString::number(value.r(), 'f', 2)) | ||||
|                 .arg(QString::number(value.g(), 'f', 2)) | ||||
|                 .arg(QString::number(value.b(), 'f', 2)) | ||||
|                 .arg(QString::number(value.a(), 'f', 2)); | ||||
|         } | ||||
|         case Format::RGB565: | ||||
|         { | ||||
|         case Format::RGB565: { | ||||
|             auto value = Color::DecodeRGB565(pixel) / 255.0f; | ||||
|             return QString("Red: %1, Green: %2, Blue: %3") | ||||
|                       .arg(QString::number(value.r(), 'f', 2)) | ||||
|                       .arg(QString::number(value.g(), 'f', 2)) | ||||
|                       .arg(QString::number(value.b(), 'f', 2)); | ||||
|                 .arg(QString::number(value.r(), 'f', 2)) | ||||
|                 .arg(QString::number(value.g(), 'f', 2)) | ||||
|                 .arg(QString::number(value.b(), 'f', 2)); | ||||
|         } | ||||
|         case Format::RGBA4: | ||||
|         { | ||||
|         case Format::RGBA4: { | ||||
|             auto value = Color::DecodeRGBA4(pixel) / 255.0f; | ||||
|             return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") | ||||
|                       .arg(QString::number(value.r(), 'f', 2)) | ||||
|                       .arg(QString::number(value.g(), 'f', 2)) | ||||
|                       .arg(QString::number(value.b(), 'f', 2)) | ||||
|                       .arg(QString::number(value.a(), 'f', 2)); | ||||
|                 .arg(QString::number(value.r(), 'f', 2)) | ||||
|                 .arg(QString::number(value.g(), 'f', 2)) | ||||
|                 .arg(QString::number(value.b(), 'f', 2)) | ||||
|                 .arg(QString::number(value.a(), 'f', 2)); | ||||
|         } | ||||
|         case Format::IA8: | ||||
|             return QString("Index: %1, Alpha: %2") | ||||
|                       .arg(pixel[0]) | ||||
|                       .arg(pixel[1]); | ||||
|             return QString("Index: %1, Alpha: %2").arg(pixel[0]).arg(pixel[1]); | ||||
|         case Format::RG8: { | ||||
|             auto value = Color::DecodeRG8(pixel) / 255.0f; | ||||
|             return QString("Red: %1, Green: %2") | ||||
|                       .arg(QString::number(value.r(), 'f', 2)) | ||||
|                       .arg(QString::number(value.g(), 'f', 2)); | ||||
|                 .arg(QString::number(value.r(), 'f', 2)) | ||||
|                 .arg(QString::number(value.g(), 'f', 2)); | ||||
|         } | ||||
|         case Format::I8: | ||||
|             return QString("Index: %1").arg(*pixel); | ||||
|         case Format::A8: | ||||
|             return QString("Alpha: %1").arg(QString::number(*pixel / 255.0f, 'f', 2)); | ||||
|         case Format::IA4: | ||||
|             return QString("Index: %1, Alpha: %2") | ||||
|                       .arg(*pixel & 0xF) | ||||
|                       .arg((*pixel & 0xF0) >> 4); | ||||
|         case Format::I4: | ||||
|         { | ||||
|             return QString("Index: %1, Alpha: %2").arg(*pixel & 0xF).arg((*pixel & 0xF0) >> 4); | ||||
|         case Format::I4: { | ||||
|             u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; | ||||
|             return QString("Index: %1").arg(i); | ||||
|         } | ||||
|         case Format::A4: | ||||
|         { | ||||
|         case Format::A4: { | ||||
|             u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; | ||||
|             return QString("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2)); | ||||
|         } | ||||
|  | @ -387,21 +372,20 @@ void GraphicsSurfaceWidget::Pick(int x, int y) | |||
|         case Format::ETC1A4: | ||||
|             // TODO: Display block information or channel values?
 | ||||
|             return QString("Compressed data"); | ||||
|         case Format::D16: | ||||
|         { | ||||
|         case Format::D16: { | ||||
|             auto value = Color::DecodeD16(pixel); | ||||
|             return QString("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4)); | ||||
|         } | ||||
|         case Format::D24: | ||||
|         { | ||||
|         case Format::D24: { | ||||
|             auto value = Color::DecodeD24(pixel); | ||||
|             return QString("Depth: %1").arg(QString::number(value / (float)0xFFFFFF, 'f', 4)); | ||||
|         } | ||||
|         case Format::D24X8: | ||||
|         case Format::X24S8: | ||||
|         { | ||||
|         case Format::X24S8: { | ||||
|             auto values = Color::DecodeD24S8(pixel); | ||||
|             return QString("Depth: %1, Stencil: %2").arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4)).arg(values[1]); | ||||
|             return QString("Depth: %1, Stencil: %2") | ||||
|                 .arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4)) | ||||
|                 .arg(values[1]); | ||||
|         } | ||||
|         case Format::Unknown: | ||||
|             return QString("Unknown format"); | ||||
|  | @ -422,18 +406,18 @@ void GraphicsSurfaceWidget::Pick(int x, int y) | |||
|         nibbles.append(QString::number(nibble, 16).toUpper()); | ||||
|     } | ||||
| 
 | ||||
|     surface_info_label->setText(QString("Raw: 0x%3\n(%4)").arg(nibbles).arg(GetText(surface_format, pixel))); | ||||
|     surface_info_label->setText( | ||||
|         QString("Raw: 0x%3\n(%4)").arg(nibbles).arg(GetText(surface_format, pixel))); | ||||
|     surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); | ||||
| } | ||||
| 
 | ||||
| void GraphicsSurfaceWidget::OnUpdate() | ||||
| { | ||||
| void GraphicsSurfaceWidget::OnUpdate() { | ||||
|     QPixmap pixmap; | ||||
| 
 | ||||
|     switch (surface_source) { | ||||
|     case Source::ColorBuffer: | ||||
|     { | ||||
|         // TODO: Store a reference to the registers in the debug context instead of accessing them directly...
 | ||||
|     case Source::ColorBuffer: { | ||||
|         // TODO: Store a reference to the registers in the debug context instead of accessing them
 | ||||
|         // directly...
 | ||||
| 
 | ||||
|         const auto& framebuffer = Pica::g_state.regs.framebuffer; | ||||
| 
 | ||||
|  | @ -470,8 +454,7 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Source::DepthBuffer: | ||||
|     { | ||||
|     case Source::DepthBuffer: { | ||||
|         const auto& framebuffer = Pica::g_state.regs.framebuffer; | ||||
| 
 | ||||
|         surface_address = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|  | @ -499,8 +482,7 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Source::StencilBuffer: | ||||
|     { | ||||
|     case Source::StencilBuffer: { | ||||
|         const auto& framebuffer = Pica::g_state.regs.framebuffer; | ||||
| 
 | ||||
|         surface_address = framebuffer.GetDepthBufferPhysicalAddress(); | ||||
|  | @ -522,12 +504,14 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 
 | ||||
|     case Source::Texture0: | ||||
|     case Source::Texture1: | ||||
|     case Source::Texture2: | ||||
|     { | ||||
|     case Source::Texture2: { | ||||
|         unsigned texture_index; | ||||
|         if (surface_source == Source::Texture0) texture_index = 0; | ||||
|         else if (surface_source == Source::Texture1) texture_index = 1; | ||||
|         else if (surface_source == Source::Texture2) texture_index = 2; | ||||
|         if (surface_source == Source::Texture0) | ||||
|             texture_index = 0; | ||||
|         else if (surface_source == Source::Texture1) | ||||
|             texture_index = 1; | ||||
|         else if (surface_source == Source::Texture2) | ||||
|             texture_index = 2; | ||||
|         else { | ||||
|             qDebug() << "Unknown texture source " << static_cast<int>(surface_source); | ||||
|             break; | ||||
|  | @ -547,8 +531,7 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Source::Custom: | ||||
|     { | ||||
|     case Source::Custom: { | ||||
|         // Keep user-specified values
 | ||||
|         break; | ||||
|     } | ||||
|  | @ -613,7 +596,8 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 
 | ||||
|     } else { | ||||
| 
 | ||||
|         ASSERT_MSG(nibbles_per_pixel >= 2, "Depth decoder only supports formats with at least one byte per pixel"); | ||||
|         ASSERT_MSG(nibbles_per_pixel >= 2, | ||||
|                    "Depth decoder only supports formats with at least one byte per pixel"); | ||||
|         unsigned bytes_per_pixel = nibbles_per_pixel / 2; | ||||
| 
 | ||||
|         for (unsigned int y = 0; y < surface_height; ++y) { | ||||
|  | @ -621,34 +605,30 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
|                 const u32 coarse_y = y & ~7; | ||||
|                 u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | ||||
|                 const u8* pixel = buffer + offset; | ||||
|                 Math::Vec4<u8> color = { 0, 0, 0, 0 }; | ||||
|                 Math::Vec4<u8> color = {0, 0, 0, 0}; | ||||
| 
 | ||||
|                 switch(surface_format) { | ||||
|                 case Format::D16: | ||||
|                 { | ||||
|                 switch (surface_format) { | ||||
|                 case Format::D16: { | ||||
|                     u32 data = Color::DecodeD16(pixel); | ||||
|                     color.r() = data & 0xFF; | ||||
|                     color.g() = (data >> 8) & 0xFF; | ||||
|                     break; | ||||
|                 } | ||||
|                 case Format::D24: | ||||
|                 { | ||||
|                 case Format::D24: { | ||||
|                     u32 data = Color::DecodeD24(pixel); | ||||
|                     color.r() = data & 0xFF; | ||||
|                     color.g() = (data >> 8) & 0xFF; | ||||
|                     color.b() = (data >> 16) & 0xFF; | ||||
|                     break; | ||||
|                 } | ||||
|                 case Format::D24X8: | ||||
|                 { | ||||
|                 case Format::D24X8: { | ||||
|                     Math::Vec2<u32> data = Color::DecodeD24S8(pixel); | ||||
|                     color.r() = data.x & 0xFF; | ||||
|                     color.g() = (data.x >> 8) & 0xFF; | ||||
|                     color.b() = (data.x >> 16) & 0xFF; | ||||
|                     break; | ||||
|                 } | ||||
|                 case Format::X24S8: | ||||
|                 { | ||||
|                 case Format::X24S8: { | ||||
|                     Math::Vec2<u32> data = Color::DecodeD24S8(pixel); | ||||
|                     color.r() = color.g() = color.b() = data.y; | ||||
|                     break; | ||||
|  | @ -661,7 +641,6 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
|                 decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), 255)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     pixmap = QPixmap::fromImage(decoded_image); | ||||
|  | @ -682,8 +661,10 @@ void GraphicsSurfaceWidget::SaveSurface() { | |||
|     QString bin_filter = tr("Binary data (*.bin)"); | ||||
| 
 | ||||
|     QString selectedFilter; | ||||
|     QString filename = QFileDialog::getSaveFileName(this, tr("Save Surface"), QString("texture-0x%1.png").arg(QString::number(surface_address, 16)), | ||||
|                                                     QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter); | ||||
|     QString filename = QFileDialog::getSaveFileName( | ||||
|         this, tr("Save Surface"), | ||||
|         QString("texture-0x%1.png").arg(QString::number(surface_address, 16)), | ||||
|         QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter); | ||||
| 
 | ||||
|     if (filename.isEmpty()) { | ||||
|         // If the user canceled the dialog, don't save anything.
 | ||||
|  | @ -718,19 +699,19 @@ unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Forma | |||
|     } | ||||
| 
 | ||||
|     switch (format) { | ||||
|         case Format::D24X8: | ||||
|         case Format::X24S8: | ||||
|             return 4 * 2; | ||||
|         case Format::D24: | ||||
|             return 3 * 2; | ||||
|         case Format::D16: | ||||
|             return 2 * 2; | ||||
|         default: | ||||
|             UNREACHABLE_MSG("GraphicsSurfaceWidget::BytesPerPixel: this " | ||||
|                             "should not be reached as this function should " | ||||
|                             "be given a format which is in " | ||||
|                             "GraphicsSurfaceWidget::Format. Instead got %i", | ||||
|                             static_cast<int>(format)); | ||||
|             return 0; | ||||
|     case Format::D24X8: | ||||
|     case Format::X24S8: | ||||
|         return 4 * 2; | ||||
|     case Format::D24: | ||||
|         return 3 * 2; | ||||
|     case Format::D16: | ||||
|         return 2 * 2; | ||||
|     default: | ||||
|         UNREACHABLE_MSG("GraphicsSurfaceWidget::BytesPerPixel: this " | ||||
|                         "should not be reached as this function should " | ||||
|                         "be given a format which is in " | ||||
|                         "GraphicsSurfaceWidget::Format. Instead got %i", | ||||
|                         static_cast<int>(format)); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -15,8 +15,7 @@ class CSpinBox; | |||
| 
 | ||||
| class GraphicsSurfaceWidget; | ||||
| 
 | ||||
| class SurfacePicture : public QLabel | ||||
| { | ||||
| class SurfacePicture : public QLabel { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  | @ -29,7 +28,6 @@ protected slots: | |||
| 
 | ||||
| private: | ||||
|     GraphicsSurfaceWidget* surface_widget; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class GraphicsSurfaceWidget : public BreakPointObserverDock { | ||||
|  | @ -38,43 +36,44 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock { | |||
|     using Event = Pica::DebugContext::Event; | ||||
| 
 | ||||
|     enum class Source { | ||||
|         ColorBuffer   = 0, | ||||
|         DepthBuffer   = 1, | ||||
|         ColorBuffer = 0, | ||||
|         DepthBuffer = 1, | ||||
|         StencilBuffer = 2, | ||||
|         Texture0      = 3, | ||||
|         Texture1      = 4, | ||||
|         Texture2      = 5, | ||||
|         Custom        = 6, | ||||
|         Texture0 = 3, | ||||
|         Texture1 = 4, | ||||
|         Texture2 = 5, | ||||
|         Custom = 6, | ||||
|     }; | ||||
| 
 | ||||
|     enum class Format { | ||||
|         // These must match the TextureFormat type!
 | ||||
|         RGBA8        =  0, | ||||
|         RGB8         =  1, | ||||
|         RGB5A1       =  2, | ||||
|         RGB565       =  3, | ||||
|         RGBA4        =  4, | ||||
|         IA8          =  5, | ||||
|         RG8          =  6,  ///< @note Also called HILO8 in 3DBrew.
 | ||||
|         I8           =  7, | ||||
|         A8           =  8, | ||||
|         IA4          =  9, | ||||
|         I4           = 10, | ||||
|         A4           = 11, | ||||
|         ETC1         = 12,  // compressed
 | ||||
|         ETC1A4       = 13, | ||||
|         RGBA8 = 0, | ||||
|         RGB8 = 1, | ||||
|         RGB5A1 = 2, | ||||
|         RGB565 = 3, | ||||
|         RGBA4 = 4, | ||||
|         IA8 = 5, | ||||
|         RG8 = 6, ///< @note Also called HILO8 in 3DBrew.
 | ||||
|         I8 = 7, | ||||
|         A8 = 8, | ||||
|         IA4 = 9, | ||||
|         I4 = 10, | ||||
|         A4 = 11, | ||||
|         ETC1 = 12, // compressed
 | ||||
|         ETC1A4 = 13, | ||||
|         MaxTextureFormat = 13, | ||||
|         D16          = 14, | ||||
|         D24          = 15, | ||||
|         D24X8        = 16, | ||||
|         X24S8        = 17, | ||||
|         Unknown      = 18, | ||||
|         D16 = 14, | ||||
|         D24 = 15, | ||||
|         D24X8 = 16, | ||||
|         X24S8 = 17, | ||||
|         Unknown = 18, | ||||
|     }; | ||||
| 
 | ||||
|     static unsigned int NibblesPerPixel(Format format); | ||||
| 
 | ||||
| public: | ||||
|     GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent = nullptr); | ||||
|     GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, | ||||
|                           QWidget* parent = nullptr); | ||||
|     void Pick(int x, int y); | ||||
| 
 | ||||
| public slots: | ||||
|  | @ -97,7 +96,6 @@ signals: | |||
|     void Update(); | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
|     QComboBox* surface_source_list; | ||||
|     CSpinBox* surface_address_control; | ||||
|     QSpinBox* surface_width_control; | ||||
|  |  | |||
|  | @ -35,12 +35,16 @@ GraphicsTracingWidget::GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> | |||
|     setObjectName("CiTracing"); | ||||
| 
 | ||||
|     QPushButton* start_recording = new QPushButton(tr("Start Recording")); | ||||
|     QPushButton* stop_recording = new QPushButton(QIcon::fromTheme("document-save"), tr("Stop and Save")); | ||||
|     QPushButton* stop_recording = | ||||
|         new QPushButton(QIcon::fromTheme("document-save"), tr("Stop and Save")); | ||||
|     QPushButton* abort_recording = new QPushButton(tr("Abort Recording")); | ||||
| 
 | ||||
|     connect(this, SIGNAL(SetStartTracingButtonEnabled(bool)), start_recording, SLOT(setVisible(bool))); | ||||
|     connect(this, SIGNAL(SetStopTracingButtonEnabled(bool)), stop_recording, SLOT(setVisible(bool))); | ||||
|     connect(this, SIGNAL(SetAbortTracingButtonEnabled(bool)), abort_recording, SLOT(setVisible(bool))); | ||||
|     connect(this, SIGNAL(SetStartTracingButtonEnabled(bool)), start_recording, | ||||
|             SLOT(setVisible(bool))); | ||||
|     connect(this, SIGNAL(SetStopTracingButtonEnabled(bool)), stop_recording, | ||||
|             SLOT(setVisible(bool))); | ||||
|     connect(this, SIGNAL(SetAbortTracingButtonEnabled(bool)), abort_recording, | ||||
|             SLOT(setVisible(bool))); | ||||
|     connect(start_recording, SIGNAL(clicked()), this, SLOT(StartRecording())); | ||||
|     connect(stop_recording, SIGNAL(clicked()), this, SLOT(StopRecording())); | ||||
|     connect(abort_recording, SIGNAL(clicked()), this, SLOT(AbortRecording())); | ||||
|  | @ -74,26 +78,31 @@ void GraphicsTracingWidget::StartRecording() { | |||
|     std::array<u32, 4 * 16> default_attributes; | ||||
|     for (unsigned i = 0; i < 16; ++i) { | ||||
|         for (unsigned comp = 0; comp < 3; ++comp) { | ||||
|             default_attributes[4 * i + comp] = nihstro::to_float24(Pica::g_state.vs_default_attributes[i][comp].ToFloat32()); | ||||
|             default_attributes[4 * i + comp] = | ||||
|                 nihstro::to_float24(Pica::g_state.vs_default_attributes[i][comp].ToFloat32()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::array<u32, 4 * 96> vs_float_uniforms; | ||||
|     for (unsigned i = 0; i < 96; ++i) | ||||
|         for (unsigned comp = 0; comp < 3; ++comp) | ||||
|             vs_float_uniforms[4 * i + comp] = nihstro::to_float24(Pica::g_state.vs.uniforms.f[i][comp].ToFloat32()); | ||||
|             vs_float_uniforms[4 * i + comp] = | ||||
|                 nihstro::to_float24(Pica::g_state.vs.uniforms.f[i][comp].ToFloat32()); | ||||
| 
 | ||||
|     CiTrace::Recorder::InitialState state; | ||||
|     std::copy_n((u32*)&GPU::g_regs, sizeof(GPU::g_regs) / sizeof(u32), std::back_inserter(state.gpu_registers)); | ||||
|     std::copy_n((u32*)&LCD::g_regs, sizeof(LCD::g_regs) / sizeof(u32), std::back_inserter(state.lcd_registers)); | ||||
|     std::copy_n((u32*)&Pica::g_state.regs, sizeof(Pica::g_state.regs) / sizeof(u32), std::back_inserter(state.pica_registers)); | ||||
|     std::copy_n((u32*)&GPU::g_regs, sizeof(GPU::g_regs) / sizeof(u32), | ||||
|                 std::back_inserter(state.gpu_registers)); | ||||
|     std::copy_n((u32*)&LCD::g_regs, sizeof(LCD::g_regs) / sizeof(u32), | ||||
|                 std::back_inserter(state.lcd_registers)); | ||||
|     std::copy_n((u32*)&Pica::g_state.regs, sizeof(Pica::g_state.regs) / sizeof(u32), | ||||
|                 std::back_inserter(state.pica_registers)); | ||||
|     boost::copy(default_attributes, std::back_inserter(state.default_attributes)); | ||||
|     boost::copy(shader_binary, std::back_inserter(state.vs_program_binary)); | ||||
|     boost::copy(swizzle_data, std::back_inserter(state.vs_swizzle_data)); | ||||
|     boost::copy(vs_float_uniforms, std::back_inserter(state.vs_float_uniforms)); | ||||
|     //boost::copy(TODO: Not implemented, std::back_inserter(state.gs_program_binary));
 | ||||
|     //boost::copy(TODO: Not implemented, std::back_inserter(state.gs_swizzle_data));
 | ||||
|     //boost::copy(TODO: Not implemented, std::back_inserter(state.gs_float_uniforms));
 | ||||
|     // boost::copy(TODO: Not implemented, std::back_inserter(state.gs_program_binary));
 | ||||
|     // boost::copy(TODO: Not implemented, std::back_inserter(state.gs_swizzle_data));
 | ||||
|     // boost::copy(TODO: Not implemented, std::back_inserter(state.gs_float_uniforms));
 | ||||
| 
 | ||||
|     auto recorder = new CiTrace::Recorder(state); | ||||
|     context->recorder = std::shared_ptr<CiTrace::Recorder>(recorder); | ||||
|  | @ -156,11 +165,12 @@ void GraphicsTracingWidget::OnEmulationStopping() { | |||
|     if (!context) | ||||
|         return; | ||||
| 
 | ||||
| 
 | ||||
|     if (context->recorder) { | ||||
|         auto reply = QMessageBox::question(this, tr("CiTracing still active"), | ||||
|                 tr("A CiTrace is still being recorded. Do you want to save it? If not, all recorded data will be discarded."), | ||||
|                 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); | ||||
|         auto reply = | ||||
|             QMessageBox::question(this, tr("CiTracing still active"), | ||||
|                                   tr("A CiTrace is still being recorded. Do you want to save it? " | ||||
|                                      "If not, all recorded data will be discarded."), | ||||
|                                   QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); | ||||
| 
 | ||||
|         if (reply == QMessageBox::Yes) { | ||||
|             StopRecording(); | ||||
|  |  | |||
|  | @ -12,7 +12,8 @@ class GraphicsTracingWidget : public BreakPointObserverDock { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent = nullptr); | ||||
|     GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, | ||||
|                           QWidget* parent = nullptr); | ||||
| 
 | ||||
| private slots: | ||||
|     void StartRecording(); | ||||
|  |  | |||
|  | @ -28,8 +28,8 @@ using nihstro::Instruction; | |||
| using nihstro::SourceRegister; | ||||
| using nihstro::SwizzlePattern; | ||||
| 
 | ||||
| GraphicsVertexShaderModel::GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent): QAbstractTableModel(parent), par(parent) { | ||||
| 
 | ||||
| GraphicsVertexShaderModel::GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent) | ||||
|     : QAbstractTableModel(parent), par(parent) { | ||||
| } | ||||
| 
 | ||||
| int GraphicsVertexShaderModel::columnCount(const QModelIndex& parent) const { | ||||
|  | @ -40,10 +40,10 @@ int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const { | |||
|     return static_cast<int>(par->info.code.size()); | ||||
| } | ||||
| 
 | ||||
| QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, int role) const { | ||||
|     switch(role) { | ||||
|     case Qt::DisplayRole: | ||||
|     { | ||||
| QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, | ||||
|                                                int role) const { | ||||
|     switch (role) { | ||||
|     case Qt::DisplayRole: { | ||||
|         if (section == 0) { | ||||
|             return tr("Offset"); | ||||
|         } else if (section == 1) { | ||||
|  | @ -69,8 +69,8 @@ static std::string SelectorToString(u32 selector) { | |||
| } | ||||
| 
 | ||||
| // e.g. "-c92[a0.x].xyzw"
 | ||||
| static void print_input(std::ostringstream& output, const SourceRegister& input, | ||||
|                         bool negate, const std::string& swizzle_mask, bool align = true, | ||||
| static void print_input(std::ostringstream& output, const SourceRegister& input, bool negate, | ||||
|                         const std::string& swizzle_mask, bool align = true, | ||||
|                         const std::string& address_register_name = std::string()) { | ||||
|     if (align) | ||||
|         output << std::setw(4) << std::right; | ||||
|  | @ -83,20 +83,18 @@ static void print_input(std::ostringstream& output, const SourceRegister& input, | |||
| 
 | ||||
| QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const { | ||||
|     switch (role) { | ||||
|     case Qt::DisplayRole: | ||||
|     { | ||||
|     case Qt::DisplayRole: { | ||||
|         switch (index.column()) { | ||||
|         case 0: | ||||
|             if (par->info.HasLabel(index.row())) | ||||
|                 return QString::fromStdString(par->info.GetLabel(index.row())); | ||||
| 
 | ||||
|             return QString("%1").arg(4*index.row(), 4, 16, QLatin1Char('0')); | ||||
|             return QString("%1").arg(4 * index.row(), 4, 16, QLatin1Char('0')); | ||||
| 
 | ||||
|         case 1: | ||||
|             return QString("%1").arg(par->info.code[index.row()].hex, 8, 16, QLatin1Char('0')); | ||||
| 
 | ||||
|         case 2: | ||||
|         { | ||||
|         case 2: { | ||||
|             std::ostringstream output; | ||||
|             output.flags(std::ios::uppercase); | ||||
| 
 | ||||
|  | @ -117,8 +115,9 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|             const Instruction instr = par->info.code[index.row()]; | ||||
|             const OpCode opcode = instr.opcode; | ||||
|             const OpCode::Info opcode_info = opcode.GetInfo(); | ||||
|             const u32 operand_desc_id = opcode_info.type == OpCode::Type::MultiplyAdd ? | ||||
|                 instr.mad.operand_desc_id.Value() : instr.common.operand_desc_id.Value(); | ||||
|             const u32 operand_desc_id = opcode_info.type == OpCode::Type::MultiplyAdd | ||||
|                                             ? instr.mad.operand_desc_id.Value() | ||||
|                                             : instr.common.operand_desc_id.Value(); | ||||
|             const SwizzlePattern swizzle = par->info.swizzle_info[operand_desc_id].pattern; | ||||
| 
 | ||||
|             // longest known instruction name: "setemit "
 | ||||
|  | @ -136,15 +135,14 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|                 break; | ||||
| 
 | ||||
|             case OpCode::Type::Arithmetic: | ||||
|             case OpCode::Type::MultiplyAdd: | ||||
|             { | ||||
|             case OpCode::Type::MultiplyAdd: { | ||||
|                 // Use custom code for special instructions
 | ||||
|                 switch (opcode.EffectiveOpCode()) { | ||||
|                 case OpCode::Id::CMP: | ||||
|                 { | ||||
|                 case OpCode::Id::CMP: { | ||||
|                     AlignToColumn(kOpcodeColumnWidth); | ||||
| 
 | ||||
|                     // NOTE: CMP always writes both cc components, so we do not consider the dest mask here.
 | ||||
|                     // NOTE: CMP always writes both cc components, so we do not consider the dest
 | ||||
|                     // mask here.
 | ||||
|                     output << " cc.xy"; | ||||
|                     AlignToColumn(kOutputColumnWidth); | ||||
| 
 | ||||
|  | @ -152,22 +150,29 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|                     SourceRegister src2 = instr.common.GetSrc2(false); | ||||
| 
 | ||||
|                     output << ' '; | ||||
|                     print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(0,1), false, instr.common.AddressRegisterName()); | ||||
|                     output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x) << ' '; | ||||
|                     print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(0,1), false); | ||||
|                     print_input(output, src1, swizzle.negate_src1, | ||||
|                                 swizzle.SelectorToString(false).substr(0, 1), false, | ||||
|                                 instr.common.AddressRegisterName()); | ||||
|                     output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x) | ||||
|                            << ' '; | ||||
|                     print_input(output, src2, swizzle.negate_src2, | ||||
|                                 swizzle.SelectorToString(true).substr(0, 1), false); | ||||
| 
 | ||||
|                     output << ", "; | ||||
| 
 | ||||
|                     print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(1,1), false, instr.common.AddressRegisterName()); | ||||
|                     output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y) << ' '; | ||||
|                     print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(1,1), false); | ||||
|                     print_input(output, src1, swizzle.negate_src1, | ||||
|                                 swizzle.SelectorToString(false).substr(1, 1), false, | ||||
|                                 instr.common.AddressRegisterName()); | ||||
|                     output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y) | ||||
|                            << ' '; | ||||
|                     print_input(output, src2, swizzle.negate_src2, | ||||
|                                 swizzle.SelectorToString(true).substr(1, 1), false); | ||||
| 
 | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 case OpCode::Id::MAD: | ||||
|                 case OpCode::Id::MADI: | ||||
|                 { | ||||
|                 case OpCode::Id::MADI: { | ||||
|                     AlignToColumn(kOpcodeColumnWidth); | ||||
| 
 | ||||
|                     bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed); | ||||
|  | @ -175,34 +180,42 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|                     SourceRegister src2 = instr.mad.GetSrc2(src_is_inverted); | ||||
|                     SourceRegister src3 = instr.mad.GetSrc3(src_is_inverted); | ||||
| 
 | ||||
|                     output << std::setw(3) << std::right << instr.mad.dest.Value().GetName() << '.' << swizzle.DestMaskToString(); | ||||
|                     output << std::setw(3) << std::right << instr.mad.dest.Value().GetName() << '.' | ||||
|                            << swizzle.DestMaskToString(); | ||||
|                     AlignToColumn(kOutputColumnWidth); | ||||
|                     print_input(output, src1, swizzle.negate_src1, SelectorToString(swizzle.src1_selector)); | ||||
|                     print_input(output, src1, swizzle.negate_src1, | ||||
|                                 SelectorToString(swizzle.src1_selector)); | ||||
|                     AlignToColumn(kInputOperandColumnWidth); | ||||
|                     if (src_is_inverted) { | ||||
|                       print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector)); | ||||
|                         print_input(output, src2, swizzle.negate_src2, | ||||
|                                     SelectorToString(swizzle.src2_selector)); | ||||
|                     } else { | ||||
|                       print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector), true, instr.mad.AddressRegisterName()); | ||||
|                         print_input(output, src2, swizzle.negate_src2, | ||||
|                                     SelectorToString(swizzle.src2_selector), true, | ||||
|                                     instr.mad.AddressRegisterName()); | ||||
|                     } | ||||
|                     AlignToColumn(kInputOperandColumnWidth); | ||||
|                     if (src_is_inverted) { | ||||
|                       print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector), true, instr.mad.AddressRegisterName()); | ||||
|                         print_input(output, src3, swizzle.negate_src3, | ||||
|                                     SelectorToString(swizzle.src3_selector), true, | ||||
|                                     instr.mad.AddressRegisterName()); | ||||
|                     } else { | ||||
|                       print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector)); | ||||
|                         print_input(output, src3, swizzle.negate_src3, | ||||
|                                     SelectorToString(swizzle.src3_selector)); | ||||
|                     } | ||||
|                     AlignToColumn(kInputOperandColumnWidth); | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 default: | ||||
|                 { | ||||
|                 default: { | ||||
|                     AlignToColumn(kOpcodeColumnWidth); | ||||
| 
 | ||||
|                     bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed); | ||||
| 
 | ||||
|                     if (opcode_info.subtype & OpCode::Info::Dest) { | ||||
|                         // e.g. "r12.xy__"
 | ||||
|                         output << std::setw(3) << std::right << instr.common.dest.Value().GetName() << '.' << swizzle.DestMaskToString(); | ||||
|                         output << std::setw(3) << std::right << instr.common.dest.Value().GetName() | ||||
|                                << '.' << swizzle.DestMaskToString(); | ||||
|                     } else if (opcode_info.subtype == OpCode::Info::MOVA) { | ||||
|                         output << "  a0." << swizzle.DestMaskToString(); | ||||
|                     } | ||||
|  | @ -210,14 +223,18 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 
 | ||||
|                     if (opcode_info.subtype & OpCode::Info::Src1) { | ||||
|                         SourceRegister src1 = instr.common.GetSrc1(src_is_inverted); | ||||
|                         print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false), true, instr.common.AddressRegisterName()); | ||||
|                         print_input(output, src1, swizzle.negate_src1, | ||||
|                                     swizzle.SelectorToString(false), true, | ||||
|                                     instr.common.AddressRegisterName()); | ||||
|                         AlignToColumn(kInputOperandColumnWidth); | ||||
|                     } | ||||
| 
 | ||||
|                     // TODO: In some cases, the Address Register is used as an index for SRC2 instead of SRC1
 | ||||
|                     // TODO: In some cases, the Address Register is used as an index for SRC2
 | ||||
|                     // instead of SRC1
 | ||||
|                     if (opcode_info.subtype & OpCode::Info::Src2) { | ||||
|                         SourceRegister src2 = instr.common.GetSrc2(src_is_inverted); | ||||
|                         print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true)); | ||||
|                         print_input(output, src2, swizzle.negate_src2, | ||||
|                                     swizzle.SelectorToString(true)); | ||||
|                         AlignToColumn(kInputOperandColumnWidth); | ||||
|                     } | ||||
|                     break; | ||||
|  | @ -228,8 +245,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|             } | ||||
| 
 | ||||
|             case OpCode::Type::Conditional: | ||||
|             case OpCode::Type::UniformFlowControl: | ||||
|             { | ||||
|             case OpCode::Type::UniformFlowControl: { | ||||
|                 output << ' '; | ||||
| 
 | ||||
|                 switch (opcode.EffectiveOpCode()) { | ||||
|  | @ -242,7 +258,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|                         output << '('; | ||||
| 
 | ||||
|                         if (instr.flow_control.op != instr.flow_control.JustY) { | ||||
|                             if (instr.flow_control.refx) output << '!'; | ||||
|                             if (instr.flow_control.refx) | ||||
|                                 output << '!'; | ||||
|                             output << "cc.x"; | ||||
|                         } | ||||
| 
 | ||||
|  | @ -253,7 +270,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|                         } | ||||
| 
 | ||||
|                         if (instr.flow_control.op != instr.flow_control.JustX) { | ||||
|                             if (instr.flow_control.refy) output << '!'; | ||||
|                             if (instr.flow_control.refy) | ||||
|                                 output << '!'; | ||||
|                             output << "cc.y"; | ||||
|                         } | ||||
| 
 | ||||
|  | @ -266,17 +284,23 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|                     u32 target_addr_else = instr.flow_control.dest_offset; | ||||
| 
 | ||||
|                     if (opcode_info.subtype & OpCode::Info::HasAlternative) { | ||||
|                         output << "else jump to 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex << (4 * instr.flow_control.dest_offset); | ||||
|                         output << "else jump to 0x" << std::setw(4) << std::right | ||||
|                                << std::setfill('0') << std::hex | ||||
|                                << (4 * instr.flow_control.dest_offset); | ||||
|                     } else if (opcode_info.subtype & OpCode::Info::HasExplicitDest) { | ||||
|                         output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex << (4 * instr.flow_control.dest_offset); | ||||
|                         output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') | ||||
|                                << std::hex << (4 * instr.flow_control.dest_offset); | ||||
|                     } else { | ||||
|                         // TODO: Handle other cases
 | ||||
|                         output << "(unknown destination)"; | ||||
|                     } | ||||
| 
 | ||||
|                     if (opcode_info.subtype & OpCode::Info::HasFinishPoint) { | ||||
|                         output << " (return on 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex | ||||
|                                << (4 * instr.flow_control.dest_offset + 4 * instr.flow_control.num_instructions) << ')'; | ||||
|                         output << " (return on 0x" << std::setw(4) << std::right | ||||
|                                << std::setfill('0') << std::hex | ||||
|                                << (4 * instr.flow_control.dest_offset + | ||||
|                                    4 * instr.flow_control.num_instructions) | ||||
|                                << ')'; | ||||
|                     } | ||||
| 
 | ||||
|                     break; | ||||
|  | @ -300,8 +324,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|     case Qt::FontRole: | ||||
|         return GetMonospaceFont(); | ||||
| 
 | ||||
|     case Qt::BackgroundRole: | ||||
|     { | ||||
|     case Qt::BackgroundRole: { | ||||
|         // Highlight current instruction
 | ||||
|         int current_record_index = par->cycle_index->value(); | ||||
|         if (current_record_index < static_cast<int>(par->debug_data.records.size())) { | ||||
|  | @ -319,10 +342,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
|         return QBrush(QColor(192, 192, 192)); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     // TODO: Draw arrows for each "reachable" instruction to visualize control flow
 | ||||
| 
 | ||||
| 
 | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|  | @ -331,23 +352,24 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| } | ||||
| 
 | ||||
| void GraphicsVertexShaderWidget::DumpShader() { | ||||
|     QString filename = QFileDialog::getSaveFileName(this, tr("Save Shader Dump"), "shader_dump.shbin", | ||||
|                                                     tr("Shader Binary (*.shbin)")); | ||||
|     QString filename = QFileDialog::getSaveFileName( | ||||
|         this, tr("Save Shader Dump"), "shader_dump.shbin", tr("Shader Binary (*.shbin)")); | ||||
| 
 | ||||
|     if (filename.isEmpty()) { | ||||
|         // If the user canceled the dialog, don't dump anything.
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     auto& setup  = Pica::g_state.vs; | ||||
|     auto& setup = Pica::g_state.vs; | ||||
|     auto& config = Pica::g_state.regs.vs; | ||||
| 
 | ||||
|     Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, Pica::g_state.regs.vs_output_attributes); | ||||
|     Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, | ||||
|                                  Pica::g_state.regs.vs_output_attributes); | ||||
| } | ||||
| 
 | ||||
| GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::DebugContext > debug_context, | ||||
|                                                        QWidget* parent) | ||||
|         : BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) { | ||||
| GraphicsVertexShaderWidget::GraphicsVertexShaderWidget( | ||||
|     std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent) | ||||
|     : BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) { | ||||
|     setObjectName("PicaVertexShader"); | ||||
| 
 | ||||
|     // Clear input vertex data so that it contains valid float values in case a debug shader
 | ||||
|  | @ -365,7 +387,8 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De | |||
|         input_data[i]->setValidator(new QDoubleValidator(input_data[i])); | ||||
|     } | ||||
| 
 | ||||
|     breakpoint_warning = new QLabel(tr("(data only available at vertex shader invocation breakpoints)")); | ||||
|     breakpoint_warning = | ||||
|         new QLabel(tr("(data only available at vertex shader invocation breakpoints)")); | ||||
| 
 | ||||
|     // TODO: Add some button for jumping to the shader entry point
 | ||||
| 
 | ||||
|  | @ -442,7 +465,8 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De | |||
| 
 | ||||
|     // Set a minimum height so that the size of this label doesn't cause the rest of the bottom
 | ||||
|     // part of the UI to keep jumping up and down when cycling through instructions.
 | ||||
|     instruction_description->setMinimumHeight(instruction_description->fontMetrics().lineSpacing() * 6); | ||||
|     instruction_description->setMinimumHeight(instruction_description->fontMetrics().lineSpacing() * | ||||
|                                               6); | ||||
|     instruction_description->setAlignment(Qt::AlignLeft | Qt::AlignTop); | ||||
|     main_layout->addWidget(instruction_description); | ||||
| 
 | ||||
|  | @ -471,7 +495,8 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d | |||
|             memcpy(&input_vertex, vertex_data, sizeof(input_vertex)); | ||||
|             for (unsigned attr = 0; attr < 16; ++attr) { | ||||
|                 for (unsigned comp = 0; comp < 4; ++comp) { | ||||
|                     input_data[4 * attr + comp]->setText(QString("%1").arg(input_vertex.attr[attr][comp].ToFloat32())); | ||||
|                     input_data[4 * attr + comp]->setText( | ||||
|                         QString("%1").arg(input_vertex.attr[attr][comp].ToFloat32())); | ||||
|                 } | ||||
|             } | ||||
|             breakpoint_warning->hide(); | ||||
|  | @ -498,10 +523,11 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d | |||
|         info.swizzle_info.push_back({pattern}); | ||||
| 
 | ||||
|     u32 entry_point = Pica::g_state.regs.vs.main_offset; | ||||
|     info.labels.insert({ entry_point, "main" }); | ||||
|     info.labels.insert({entry_point, "main"}); | ||||
| 
 | ||||
|     // Generate debug information
 | ||||
|     debug_data = Pica::g_state.vs.ProduceDebugInfo(input_vertex, num_attributes, shader_config, shader_setup); | ||||
|     debug_data = Pica::g_state.vs.ProduceDebugInfo(input_vertex, num_attributes, shader_config, | ||||
|                                                    shader_setup); | ||||
| 
 | ||||
|     // Reload widget state
 | ||||
|     for (int attr = 0; attr < num_attributes; ++attr) { | ||||
|  | @ -537,29 +563,60 @@ void GraphicsVertexShaderWidget::OnCycleIndexChanged(int index) { | |||
| 
 | ||||
|     auto& record = debug_data.records[index]; | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::SRC1) | ||||
|         text += tr("SRC1: %1, %2, %3, %4\n").arg(record.src1.x.ToFloat32()).arg(record.src1.y.ToFloat32()).arg(record.src1.z.ToFloat32()).arg(record.src1.w.ToFloat32()); | ||||
|         text += tr("SRC1: %1, %2, %3, %4\n") | ||||
|                     .arg(record.src1.x.ToFloat32()) | ||||
|                     .arg(record.src1.y.ToFloat32()) | ||||
|                     .arg(record.src1.z.ToFloat32()) | ||||
|                     .arg(record.src1.w.ToFloat32()); | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::SRC2) | ||||
|         text += tr("SRC2: %1, %2, %3, %4\n").arg(record.src2.x.ToFloat32()).arg(record.src2.y.ToFloat32()).arg(record.src2.z.ToFloat32()).arg(record.src2.w.ToFloat32()); | ||||
|         text += tr("SRC2: %1, %2, %3, %4\n") | ||||
|                     .arg(record.src2.x.ToFloat32()) | ||||
|                     .arg(record.src2.y.ToFloat32()) | ||||
|                     .arg(record.src2.z.ToFloat32()) | ||||
|                     .arg(record.src2.w.ToFloat32()); | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::SRC3) | ||||
|         text += tr("SRC3: %1, %2, %3, %4\n").arg(record.src3.x.ToFloat32()).arg(record.src3.y.ToFloat32()).arg(record.src3.z.ToFloat32()).arg(record.src3.w.ToFloat32()); | ||||
|         text += tr("SRC3: %1, %2, %3, %4\n") | ||||
|                     .arg(record.src3.x.ToFloat32()) | ||||
|                     .arg(record.src3.y.ToFloat32()) | ||||
|                     .arg(record.src3.z.ToFloat32()) | ||||
|                     .arg(record.src3.w.ToFloat32()); | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::DEST_IN) | ||||
|         text += tr("DEST_IN: %1, %2, %3, %4\n").arg(record.dest_in.x.ToFloat32()).arg(record.dest_in.y.ToFloat32()).arg(record.dest_in.z.ToFloat32()).arg(record.dest_in.w.ToFloat32()); | ||||
|         text += tr("DEST_IN: %1, %2, %3, %4\n") | ||||
|                     .arg(record.dest_in.x.ToFloat32()) | ||||
|                     .arg(record.dest_in.y.ToFloat32()) | ||||
|                     .arg(record.dest_in.z.ToFloat32()) | ||||
|                     .arg(record.dest_in.w.ToFloat32()); | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::DEST_OUT) | ||||
|         text += tr("DEST_OUT: %1, %2, %3, %4\n").arg(record.dest_out.x.ToFloat32()).arg(record.dest_out.y.ToFloat32()).arg(record.dest_out.z.ToFloat32()).arg(record.dest_out.w.ToFloat32()); | ||||
|         text += tr("DEST_OUT: %1, %2, %3, %4\n") | ||||
|                     .arg(record.dest_out.x.ToFloat32()) | ||||
|                     .arg(record.dest_out.y.ToFloat32()) | ||||
|                     .arg(record.dest_out.z.ToFloat32()) | ||||
|                     .arg(record.dest_out.w.ToFloat32()); | ||||
| 
 | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::ADDR_REG_OUT) | ||||
|         text += tr("Addres Registers: %1, %2\n").arg(record.address_registers[0]).arg(record.address_registers[1]); | ||||
|         text += tr("Addres Registers: %1, %2\n") | ||||
|                     .arg(record.address_registers[0]) | ||||
|                     .arg(record.address_registers[1]); | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::CMP_RESULT) | ||||
|         text += tr("Compare Result: %1, %2\n").arg(record.conditional_code[0] ? "true" : "false").arg(record.conditional_code[1] ? "true" : "false"); | ||||
|         text += tr("Compare Result: %1, %2\n") | ||||
|                     .arg(record.conditional_code[0] ? "true" : "false") | ||||
|                     .arg(record.conditional_code[1] ? "true" : "false"); | ||||
| 
 | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::COND_BOOL_IN) | ||||
|         text += tr("Static Condition: %1\n").arg(record.cond_bool ? "true" : "false"); | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::COND_CMP_IN) | ||||
|         text += tr("Dynamic Conditions: %1, %2\n").arg(record.cond_cmp[0] ? "true" : "false").arg(record.cond_cmp[1] ? "true" : "false"); | ||||
|         text += tr("Dynamic Conditions: %1, %2\n") | ||||
|                     .arg(record.cond_cmp[0] ? "true" : "false") | ||||
|                     .arg(record.cond_cmp[1] ? "true" : "false"); | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::LOOP_INT_IN) | ||||
|         text += tr("Loop Parameters: %1 (repeats), %2 (initializer), %3 (increment), %4\n").arg(record.loop_int.x).arg(record.loop_int.y).arg(record.loop_int.z).arg(record.loop_int.w); | ||||
|         text += tr("Loop Parameters: %1 (repeats), %2 (initializer), %3 (increment), %4\n") | ||||
|                     .arg(record.loop_int.x) | ||||
|                     .arg(record.loop_int.y) | ||||
|                     .arg(record.loop_int.z) | ||||
|                     .arg(record.loop_int.w); | ||||
| 
 | ||||
|     text += tr("Instruction offset: 0x%1").arg(4 * record.instruction_offset, 4, 16, QLatin1Char('0')); | ||||
|     text += | ||||
|         tr("Instruction offset: 0x%1").arg(4 * record.instruction_offset, 4, 16, QLatin1Char('0')); | ||||
|     if (record.mask & Pica::Shader::DebugDataRecord::NEXT_INSTR) { | ||||
|         text += tr(" -> 0x%2").arg(4 * record.next_instruction, 4, 16, QLatin1Char('0')); | ||||
|     } else { | ||||
|  | @ -570,6 +627,7 @@ void GraphicsVertexShaderWidget::OnCycleIndexChanged(int index) { | |||
| 
 | ||||
|     // Emit model update notification and scroll to current instruction
 | ||||
|     QModelIndex instr_index = model->index(record.instruction_offset, 0); | ||||
|     emit model->dataChanged(instr_index, model->index(record.instruction_offset, model->columnCount())); | ||||
|     emit model->dataChanged(instr_index, | ||||
|                             model->index(record.instruction_offset, model->columnCount())); | ||||
|     binary_list->scrollTo(instr_index, QAbstractItemView::EnsureVisible); | ||||
| } | ||||
|  |  | |||
|  | @ -26,7 +26,8 @@ public: | |||
|     int columnCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|     int rowCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; | ||||
|     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; | ||||
|     QVariant headerData(int section, Qt::Orientation orientation, | ||||
|                         int role = Qt::DisplayRole) const override; | ||||
| 
 | ||||
| private: | ||||
|     GraphicsVertexShaderWidget* par; | ||||
|  | @ -56,7 +57,9 @@ private slots: | |||
|     /**
 | ||||
|      * Reload widget based on the current PICA200 state | ||||
|      * @param replace_vertex_data If true, invalidate all current vertex data | ||||
|      * @param vertex_data New vertex data to use, as passed to OnBreakPointHit. May be nullptr to specify that no valid vertex data can be retrieved currently. Only used if replace_vertex_data is true. | ||||
|      * @param vertex_data New vertex data to use, as passed to OnBreakPointHit. May be nullptr to | ||||
|      * specify that no valid vertex data can be retrieved currently. Only used if | ||||
|      * replace_vertex_data is true. | ||||
|      */ | ||||
|     void Reload(bool replace_vertex_data = false, void* vertex_data = nullptr); | ||||
| 
 | ||||
|  | @ -66,9 +69,12 @@ private: | |||
|     GraphicsVertexShaderModel* model; | ||||
| 
 | ||||
|     /// TODO: Move these into a single struct
 | ||||
|     std::array<QLineEdit*, 4*16> input_data;  // A text box for each of the 4 components of up to 16 vertex attributes
 | ||||
|     std::array<QWidget*, 16> input_data_container; // QWidget containing the QLayout containing each vertex attribute
 | ||||
|     std::array<QLabel*, 16> input_data_mapping; // A QLabel denoting the shader input attribute which the vertex attribute maps to
 | ||||
|     std::array<QLineEdit*, 4 * 16> | ||||
|         input_data; // A text box for each of the 4 components of up to 16 vertex attributes
 | ||||
|     std::array<QWidget*, 16> | ||||
|         input_data_container; // QWidget containing the QLayout containing each vertex attribute
 | ||||
|     std::array<QLabel*, 16> input_data_mapping; // A QLabel denoting the shader input attribute
 | ||||
|                                                 // which the vertex attribute maps to
 | ||||
| 
 | ||||
|     // Text to be shown when input vertex data is not retrievable
 | ||||
|     QLabel* breakpoint_warning; | ||||
|  |  | |||
|  | @ -22,57 +22,58 @@ | |||
| 
 | ||||
| using namespace Common::Profiling; | ||||
| 
 | ||||
| static QVariant GetDataForColumn(int col, const AggregatedDuration& duration) | ||||
| { | ||||
| static QVariant GetDataForColumn(int col, const AggregatedDuration& duration) { | ||||
|     static auto duration_to_float = [](Duration dur) -> float { | ||||
|         using FloatMs = std::chrono::duration<float, std::chrono::milliseconds::period>; | ||||
|         return std::chrono::duration_cast<FloatMs>(dur).count(); | ||||
|     }; | ||||
| 
 | ||||
|     switch (col) { | ||||
|     case 1: return duration_to_float(duration.avg); | ||||
|     case 2: return duration_to_float(duration.min); | ||||
|     case 3: return duration_to_float(duration.max); | ||||
|     default: return QVariant(); | ||||
|     case 1: | ||||
|         return duration_to_float(duration.avg); | ||||
|     case 2: | ||||
|         return duration_to_float(duration.min); | ||||
|     case 3: | ||||
|         return duration_to_float(duration.max); | ||||
|     default: | ||||
|         return QVariant(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent) | ||||
| { | ||||
| ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent) { | ||||
|     updateProfilingInfo(); | ||||
| } | ||||
| 
 | ||||
| QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const | ||||
| { | ||||
| QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const { | ||||
|     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { | ||||
|         switch (section) { | ||||
|         case 0: return tr("Category"); | ||||
|         case 1: return tr("Avg"); | ||||
|         case 2: return tr("Min"); | ||||
|         case 3: return tr("Max"); | ||||
|         case 0: | ||||
|             return tr("Category"); | ||||
|         case 1: | ||||
|             return tr("Avg"); | ||||
|         case 2: | ||||
|             return tr("Min"); | ||||
|         case 3: | ||||
|             return tr("Max"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return QVariant(); | ||||
| } | ||||
| 
 | ||||
| QModelIndex ProfilerModel::index(int row, int column, const QModelIndex& parent) const | ||||
| { | ||||
| QModelIndex ProfilerModel::index(int row, int column, const QModelIndex& parent) const { | ||||
|     return createIndex(row, column); | ||||
| } | ||||
| 
 | ||||
| QModelIndex ProfilerModel::parent(const QModelIndex& child) const | ||||
| { | ||||
| QModelIndex ProfilerModel::parent(const QModelIndex& child) const { | ||||
|     return QModelIndex(); | ||||
| } | ||||
| 
 | ||||
| int ProfilerModel::columnCount(const QModelIndex& parent) const | ||||
| { | ||||
| int ProfilerModel::columnCount(const QModelIndex& parent) const { | ||||
|     return 4; | ||||
| } | ||||
| 
 | ||||
| int ProfilerModel::rowCount(const QModelIndex& parent) const | ||||
| { | ||||
| int ProfilerModel::rowCount(const QModelIndex& parent) const { | ||||
|     if (parent.isValid()) { | ||||
|         return 0; | ||||
|     } else { | ||||
|  | @ -80,8 +81,7 @@ int ProfilerModel::rowCount(const QModelIndex& parent) const | |||
|     } | ||||
| } | ||||
| 
 | ||||
| QVariant ProfilerModel::data(const QModelIndex& index, int role) const | ||||
| { | ||||
| QVariant ProfilerModel::data(const QModelIndex& index, int role) const { | ||||
|     if (role == Qt::DisplayRole) { | ||||
|         if (index.row() == 0) { | ||||
|             if (index.column() == 0) { | ||||
|  | @ -101,14 +101,12 @@ QVariant ProfilerModel::data(const QModelIndex& index, int role) const | |||
|     return QVariant(); | ||||
| } | ||||
| 
 | ||||
| void ProfilerModel::updateProfilingInfo() | ||||
| { | ||||
| void ProfilerModel::updateProfilingInfo() { | ||||
|     results = GetTimingResultsAggregator()->GetAggregatedResults(); | ||||
|     emit dataChanged(createIndex(0, 1), createIndex(rowCount() - 1, 3)); | ||||
| } | ||||
| 
 | ||||
| ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent) | ||||
| { | ||||
| ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent) { | ||||
|     ui.setupUi(this); | ||||
| 
 | ||||
|     model = new ProfilerModel(this); | ||||
|  | @ -118,8 +116,7 @@ ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent) | |||
|     connect(&update_timer, SIGNAL(timeout()), model, SLOT(updateProfilingInfo())); | ||||
| } | ||||
| 
 | ||||
| void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable) | ||||
| { | ||||
| void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable) { | ||||
|     if (enable) { | ||||
|         update_timer.start(100); | ||||
|         model->updateProfilingInfo(); | ||||
|  | @ -157,9 +154,7 @@ private: | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| MicroProfileDialog::MicroProfileDialog(QWidget* parent) | ||||
|     : QWidget(parent, Qt::Dialog) | ||||
| { | ||||
| MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) { | ||||
|     setObjectName("MicroProfile"); | ||||
|     setWindowTitle(tr("MicroProfile")); | ||||
|     resize(1000, 600); | ||||
|  | @ -175,7 +170,8 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent) | |||
|     layout->addWidget(widget); | ||||
|     setLayout(layout); | ||||
| 
 | ||||
|     // Configure focus so that widget is focusable and the dialog automatically forwards focus to it.
 | ||||
|     // Configure focus so that widget is focusable and the dialog automatically forwards focus to
 | ||||
|     // it.
 | ||||
|     setFocusProxy(widget); | ||||
|     widget->setFocusPolicy(Qt::StrongFocus); | ||||
|     widget->setFocus(); | ||||
|  | @ -207,7 +203,6 @@ void MicroProfileDialog::hideEvent(QHideEvent* ev) { | |||
|     QWidget::hideEvent(ev); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #if MICROPROFILE_ENABLED | ||||
| 
 | ||||
| /// There's no way to pass a user pointer to MicroProfile, so this variable is used to make the
 | ||||
|  | @ -308,7 +303,8 @@ void MicroProfileDrawText(int x, int y, u32 hex_color, const char* text, u32 tex | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void MicroProfileDrawBox(int left, int top, int right, int bottom, u32 hex_color, MicroProfileBoxType type) { | ||||
| void MicroProfileDrawBox(int left, int top, int right, int bottom, u32 hex_color, | ||||
|                          MicroProfileBoxType type) { | ||||
|     QColor color = QColor::fromRgba(hex_color); | ||||
|     QBrush brush = color; | ||||
|     if (type == MicroProfileBoxTypeBar) { | ||||
|  | @ -326,7 +322,7 @@ void MicroProfileDrawLine2D(u32 vertices_length, float* vertices, u32 hex_color) | |||
|     static std::vector<QPointF> point_buf; | ||||
| 
 | ||||
|     for (u32 i = 0; i < vertices_length; ++i) { | ||||
|         point_buf.emplace_back(vertices[i*2 + 0], vertices[i*2 + 1]); | ||||
|         point_buf.emplace_back(vertices[i * 2 + 0], vertices[i * 2 + 1]); | ||||
|     } | ||||
| 
 | ||||
|     // hex_color does not include an alpha, so it must be assumed to be 255
 | ||||
|  |  | |||
|  | @ -13,15 +13,16 @@ | |||
| #include "common/microprofile.h" | ||||
| #include "common/profiler_reporting.h" | ||||
| 
 | ||||
| class ProfilerModel : public QAbstractItemModel | ||||
| { | ||||
| class ProfilerModel : public QAbstractItemModel { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     ProfilerModel(QObject* parent); | ||||
| 
 | ||||
|     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; | ||||
|     QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; | ||||
|     QVariant headerData(int section, Qt::Orientation orientation, | ||||
|                         int role = Qt::DisplayRole) const override; | ||||
|     QModelIndex index(int row, int column, | ||||
|                       const QModelIndex& parent = QModelIndex()) const override; | ||||
|     QModelIndex parent(const QModelIndex& child) const override; | ||||
|     int columnCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|     int rowCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|  | @ -34,8 +35,7 @@ private: | |||
|     Common::Profiling::AggregatedFrameResult results; | ||||
| }; | ||||
| 
 | ||||
| class ProfilerWidget : public QDockWidget | ||||
| { | ||||
| class ProfilerWidget : public QDockWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  | @ -51,7 +51,6 @@ private: | |||
|     QTimer update_timer; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| class MicroProfileDialog : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,12 +4,10 @@ | |||
| 
 | ||||
| #include "citra_qt/debugger/ramview.h" | ||||
| 
 | ||||
| GRamView::GRamView(QWidget* parent) : QHexEdit(parent) | ||||
| { | ||||
| GRamView::GRamView(QWidget* parent) : QHexEdit(parent) { | ||||
| } | ||||
| 
 | ||||
| void GRamView::OnCPUStepped() | ||||
| { | ||||
| void GRamView::OnCPUStepped() { | ||||
|     // TODO: QHexEdit doesn't show vertical scroll bars for > 10MB data streams...
 | ||||
|     //setData(QByteArray((const char*)Mem_RAM,sizeof(Mem_RAM)/8));
 | ||||
|     // setData(QByteArray((const char*)Mem_RAM,sizeof(Mem_RAM)/8));
 | ||||
| } | ||||
|  |  | |||
|  | @ -4,8 +4,7 @@ | |||
| 
 | ||||
| #include "qhexedit.h" | ||||
| 
 | ||||
| class GRamView : public QHexEdit | ||||
| { | ||||
| class GRamView : public QHexEdit { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  |  | |||
|  | @ -7,8 +7,8 @@ | |||
| #include "citra_qt/debugger/registers.h" | ||||
| #include "citra_qt/util/util.h" | ||||
| 
 | ||||
| #include "core/core.h" | ||||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/core.h" | ||||
| 
 | ||||
| RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { | ||||
|     cpu_regs_ui.setupUi(this); | ||||
|  | @ -16,7 +16,8 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { | |||
|     tree = cpu_regs_ui.treeWidget; | ||||
|     tree->addTopLevelItem(core_registers = new QTreeWidgetItem(QStringList(tr("Registers")))); | ||||
|     tree->addTopLevelItem(vfp_registers = new QTreeWidgetItem(QStringList(tr("VFP Registers")))); | ||||
|     tree->addTopLevelItem(vfp_system_registers = new QTreeWidgetItem(QStringList(tr("VFP System Registers")))); | ||||
|     tree->addTopLevelItem(vfp_system_registers = | ||||
|                               new QTreeWidgetItem(QStringList(tr("VFP System Registers")))); | ||||
|     tree->addTopLevelItem(cpsr = new QTreeWidgetItem(QStringList("CPSR"))); | ||||
| 
 | ||||
|     for (int i = 0; i < 16; ++i) { | ||||
|  | @ -63,10 +64,12 @@ void RegistersWidget::OnDebugModeEntered() { | |||
|         return; | ||||
| 
 | ||||
|     for (int i = 0; i < core_registers->childCount(); ++i) | ||||
|         core_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0'))); | ||||
|         core_registers->child(i)->setText( | ||||
|             1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0'))); | ||||
| 
 | ||||
|     for (int i = 0; i < vfp_registers->childCount(); ++i) | ||||
|         vfp_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); | ||||
|         vfp_registers->child(i)->setText( | ||||
|             1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); | ||||
| 
 | ||||
|     UpdateCPSRValues(); | ||||
|     UpdateVFPSystemRegisterValues(); | ||||
|  | @ -130,21 +133,24 @@ void RegistersWidget::UpdateCPSRValues() { | |||
|     const u32 cpsr_val = Core::g_app_core->GetCPSR(); | ||||
| 
 | ||||
|     cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); | ||||
|     cpsr->child(0)->setText(1, QString("b%1").arg(cpsr_val & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode
 | ||||
|     cpsr->child(1)->setText(1, QString::number((cpsr_val >> 5) & 1));     // T - State
 | ||||
|     cpsr->child(2)->setText(1, QString::number((cpsr_val >> 6) & 1));     // F - FIQ disable
 | ||||
|     cpsr->child(3)->setText(1, QString::number((cpsr_val >> 7) & 1));     // I - IRQ disable
 | ||||
|     cpsr->child(4)->setText(1, QString::number((cpsr_val >> 8) & 1));     // A - Imprecise abort
 | ||||
|     cpsr->child(5)->setText(1, QString::number((cpsr_val >> 9) & 1));     // E - Data endianess
 | ||||
|     cpsr->child(6)->setText(1, QString::number((cpsr_val >> 10) & 0x3F)); // IT - If-Then state (DNM)
 | ||||
|     cpsr->child(7)->setText(1, QString::number((cpsr_val >> 16) & 0xF));  // GE - Greater-than-or-Equal
 | ||||
|     cpsr->child(8)->setText(1, QString::number((cpsr_val >> 20) & 0xF));  // DNM - Do not modify
 | ||||
|     cpsr->child(9)->setText(1, QString::number((cpsr_val >> 24) & 1));    // J - Jazelle
 | ||||
|     cpsr->child(10)->setText(1, QString::number((cpsr_val >> 27) & 1));   // Q - Saturation
 | ||||
|     cpsr->child(11)->setText(1, QString::number((cpsr_val >> 28) & 1));   // V - Overflow
 | ||||
|     cpsr->child(12)->setText(1, QString::number((cpsr_val >> 29) & 1));   // C - Carry/Borrow/Extend
 | ||||
|     cpsr->child(13)->setText(1, QString::number((cpsr_val >> 30) & 1));   // Z - Zero
 | ||||
|     cpsr->child(14)->setText(1, QString::number((cpsr_val >> 31) & 1));   // N - Negative/Less than
 | ||||
|     cpsr->child(0)->setText( | ||||
|         1, QString("b%1").arg(cpsr_val & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode
 | ||||
|     cpsr->child(1)->setText(1, QString::number((cpsr_val >> 5) & 1));    // T - State
 | ||||
|     cpsr->child(2)->setText(1, QString::number((cpsr_val >> 6) & 1));    // F - FIQ disable
 | ||||
|     cpsr->child(3)->setText(1, QString::number((cpsr_val >> 7) & 1));    // I - IRQ disable
 | ||||
|     cpsr->child(4)->setText(1, QString::number((cpsr_val >> 8) & 1));    // A - Imprecise abort
 | ||||
|     cpsr->child(5)->setText(1, QString::number((cpsr_val >> 9) & 1));    // E - Data endianess
 | ||||
|     cpsr->child(6)->setText(1, | ||||
|                             QString::number((cpsr_val >> 10) & 0x3F)); // IT - If-Then state (DNM)
 | ||||
|     cpsr->child(7)->setText(1, | ||||
|                             QString::number((cpsr_val >> 16) & 0xF)); // GE - Greater-than-or-Equal
 | ||||
|     cpsr->child(8)->setText(1, QString::number((cpsr_val >> 20) & 0xF)); // DNM - Do not modify
 | ||||
|     cpsr->child(9)->setText(1, QString::number((cpsr_val >> 24) & 1));   // J - Jazelle
 | ||||
|     cpsr->child(10)->setText(1, QString::number((cpsr_val >> 27) & 1));  // Q - Saturation
 | ||||
|     cpsr->child(11)->setText(1, QString::number((cpsr_val >> 28) & 1));  // V - Overflow
 | ||||
|     cpsr->child(12)->setText(1, QString::number((cpsr_val >> 29) & 1));  // C - Carry/Borrow/Extend
 | ||||
|     cpsr->child(13)->setText(1, QString::number((cpsr_val >> 30) & 1));  // Z - Zero
 | ||||
|     cpsr->child(14)->setText(1, QString::number((cpsr_val >> 31) & 1));  // N - Negative/Less than
 | ||||
| } | ||||
| 
 | ||||
| void RegistersWidget::CreateVFPSystemRegisterChildren() { | ||||
|  | @ -188,9 +194,9 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() { | |||
| } | ||||
| 
 | ||||
| void RegistersWidget::UpdateVFPSystemRegisterValues() { | ||||
|     const u32 fpscr_val   = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR); | ||||
|     const u32 fpexc_val   = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC); | ||||
|     const u32 fpinst_val  = Core::g_app_core->GetVFPSystemReg(VFP_FPINST); | ||||
|     const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR); | ||||
|     const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC); | ||||
|     const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST); | ||||
|     const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2); | ||||
| 
 | ||||
|     QTreeWidgetItem* const fpscr = vfp_system_registers->child(0); | ||||
|  | @ -228,6 +234,8 @@ void RegistersWidget::UpdateVFPSystemRegisterValues() { | |||
|     fpexc->child(6)->setText(1, QString::number((fpexc_val >> 30) & 1)); | ||||
|     fpexc->child(7)->setText(1, QString::number((fpexc_val >> 31) & 1)); | ||||
| 
 | ||||
|     vfp_system_registers->child(2)->setText(1, QString("0x%1").arg(fpinst_val, 8, 16, QLatin1Char('0'))); | ||||
|     vfp_system_registers->child(3)->setText(1, QString("0x%1").arg(fpinst2_val, 8, 16, QLatin1Char('0'))); | ||||
|     vfp_system_registers->child(2)->setText( | ||||
|         1, QString("0x%1").arg(fpinst_val, 8, 16, QLatin1Char('0'))); | ||||
|     vfp_system_registers->child(3)->setText( | ||||
|         1, QString("0x%1").arg(fpinst2_val, 8, 16, QLatin1Char('0'))); | ||||
| } | ||||
|  |  | |||
|  | @ -10,8 +10,7 @@ class QTreeWidget; | |||
| class QTreeWidgetItem; | ||||
| class EmuThread; | ||||
| 
 | ||||
| class RegistersWidget : public QDockWidget | ||||
| { | ||||
| class RegistersWidget : public QDockWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  |  | |||
|  | @ -16,8 +16,7 @@ | |||
| #include "common/logging/log.h" | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| GameList::GameList(QWidget* parent) | ||||
| { | ||||
| GameList::GameList(QWidget* parent) { | ||||
|     QVBoxLayout* layout = new QVBoxLayout; | ||||
| 
 | ||||
|     tree_view = new QTreeView; | ||||
|  | @ -38,9 +37,11 @@ GameList::GameList(QWidget* parent) | |||
|     item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); | ||||
|     item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); | ||||
| 
 | ||||
|     connect(tree_view, SIGNAL(activated(const QModelIndex&)), this, SLOT(ValidateEntry(const QModelIndex&))); | ||||
|     connect(tree_view, SIGNAL(activated(const QModelIndex&)), this, | ||||
|             SLOT(ValidateEntry(const QModelIndex&))); | ||||
| 
 | ||||
|     // We must register all custom types with the Qt Automoc system so that we are able to use it with
 | ||||
|     // We must register all custom types with the Qt Automoc system so that we are able to use it
 | ||||
|     // with
 | ||||
|     // signals/slots. In this case, QList falls under the umbrells of custom types.
 | ||||
|     qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); | ||||
| 
 | ||||
|  | @ -48,18 +49,15 @@ GameList::GameList(QWidget* parent) | |||
|     setLayout(layout); | ||||
| } | ||||
| 
 | ||||
| GameList::~GameList() | ||||
| { | ||||
| GameList::~GameList() { | ||||
|     emit ShouldCancelWorker(); | ||||
| } | ||||
| 
 | ||||
| void GameList::AddEntry(QList<QStandardItem*> entry_items) | ||||
| { | ||||
| void GameList::AddEntry(QList<QStandardItem*> entry_items) { | ||||
|     item_model->invisibleRootItem()->appendRow(entry_items); | ||||
| } | ||||
| 
 | ||||
| void GameList::ValidateEntry(const QModelIndex& item) | ||||
| { | ||||
| void GameList::ValidateEntry(const QModelIndex& item) { | ||||
|     // We don't care about the individual QStandardItem that was selected, but its row.
 | ||||
|     int row = item_model->itemFromIndex(item)->row(); | ||||
|     QStandardItem* child_file = item_model->invisibleRootItem()->child(row, COLUMN_NAME); | ||||
|  | @ -73,14 +71,13 @@ void GameList::ValidateEntry(const QModelIndex& item) | |||
|     emit GameChosen(file_path); | ||||
| } | ||||
| 
 | ||||
| void GameList::DonePopulating() | ||||
| { | ||||
| void GameList::DonePopulating() { | ||||
|     tree_view->setEnabled(true); | ||||
| } | ||||
| 
 | ||||
| void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) | ||||
| { | ||||
|     if (!FileUtil::Exists(dir_path.toStdString()) || !FileUtil::IsDirectory(dir_path.toStdString())) { | ||||
| void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { | ||||
|     if (!FileUtil::Exists(dir_path.toStdString()) || | ||||
|         !FileUtil::IsDirectory(dir_path.toStdString())) { | ||||
|         LOG_ERROR(Frontend, "Could not find game list folder at %s", dir_path.toLocal8Bit().data()); | ||||
|         return; | ||||
|     } | ||||
|  | @ -92,22 +89,22 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) | |||
|     emit ShouldCancelWorker(); | ||||
|     GameListWorker* worker = new GameListWorker(dir_path, deep_scan); | ||||
| 
 | ||||
|     connect(worker, SIGNAL(EntryReady(QList<QStandardItem*>)), this, SLOT(AddEntry(QList<QStandardItem*>)), Qt::QueuedConnection); | ||||
|     connect(worker, SIGNAL(EntryReady(QList<QStandardItem*>)), this, | ||||
|             SLOT(AddEntry(QList<QStandardItem*>)), Qt::QueuedConnection); | ||||
|     connect(worker, SIGNAL(Finished()), this, SLOT(DonePopulating()), Qt::QueuedConnection); | ||||
|     // Use DirectConnection here because worker->Cancel() is thread-safe and we want it to cancel without delay.
 | ||||
|     // Use DirectConnection here because worker->Cancel() is thread-safe and we want it to cancel
 | ||||
|     // without delay.
 | ||||
|     connect(this, SIGNAL(ShouldCancelWorker()), worker, SLOT(Cancel()), Qt::DirectConnection); | ||||
| 
 | ||||
|     QThreadPool::globalInstance()->start(worker); | ||||
|     current_worker = std::move(worker); | ||||
| } | ||||
| 
 | ||||
| void GameList::SaveInterfaceLayout() | ||||
| { | ||||
| void GameList::SaveInterfaceLayout() { | ||||
|     UISettings::values.gamelist_header_state = tree_view->header()->saveState(); | ||||
| } | ||||
| 
 | ||||
| void GameList::LoadInterfaceLayout() | ||||
| { | ||||
| void GameList::LoadInterfaceLayout() { | ||||
|     auto header = tree_view->header(); | ||||
|     if (!header->restoreState(UISettings::values.gamelist_header_state)) { | ||||
|         // We are using the name column to display icons and titles
 | ||||
|  | @ -118,10 +115,8 @@ void GameList::LoadInterfaceLayout() | |||
|     item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); | ||||
| } | ||||
| 
 | ||||
| void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) | ||||
| { | ||||
|     const auto callback = [this, recursion](unsigned* num_entries_out, | ||||
|                                             const std::string& directory, | ||||
| void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) { | ||||
|     const auto callback = [this, recursion](unsigned* num_entries_out, const std::string& directory, | ||||
|                                             const std::string& virtual_name) -> bool { | ||||
|         std::string physical_name = directory + DIR_SEP + virtual_name; | ||||
| 
 | ||||
|  | @ -138,7 +133,8 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign | |||
| 
 | ||||
|             emit EntryReady({ | ||||
|                 new GameListItemPath(QString::fromStdString(physical_name), smdh), | ||||
|                 new GameListItem(QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), | ||||
|                 new GameListItem( | ||||
|                     QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), | ||||
|                 new GameListItemSize(FileUtil::GetSize(physical_name)), | ||||
|             }); | ||||
|         } else if (recursion > 0) { | ||||
|  | @ -151,15 +147,13 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign | |||
|     FileUtil::ForeachDirectoryEntry(nullptr, dir_path, callback); | ||||
| } | ||||
| 
 | ||||
| void GameListWorker::run() | ||||
| { | ||||
| void GameListWorker::run() { | ||||
|     stop_processing = false; | ||||
|     AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0); | ||||
|     emit Finished(); | ||||
| } | ||||
| 
 | ||||
| void GameListWorker::Cancel() | ||||
| { | ||||
| void GameListWorker::Cancel() { | ||||
|     disconnect(this, 0, 0, 0); | ||||
|     stop_processing = true; | ||||
| } | ||||
|  |  | |||
|  | @ -14,7 +14,6 @@ | |||
| 
 | ||||
| class GameListWorker; | ||||
| 
 | ||||
| 
 | ||||
| class GameList : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,8 +12,8 @@ | |||
| #include <QString> | ||||
| 
 | ||||
| #include "citra_qt/util/util.h" | ||||
| #include "common/string_util.h" | ||||
| #include "common/color.h" | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| #include "core/loader/smdh.h" | ||||
| 
 | ||||
|  | @ -51,19 +51,22 @@ static QPixmap GetDefaultIcon(bool large) { | |||
|  * @param language title language | ||||
|  * @return QString short title | ||||
|  */ | ||||
| static QString GetQStringShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) { | ||||
| static QString GetQStringShortTitleFromSMDH(const Loader::SMDH& smdh, | ||||
|                                             Loader::SMDH::TitleLanguage language) { | ||||
|     return QString::fromUtf16(smdh.GetShortTitle(language).data()); | ||||
| } | ||||
| 
 | ||||
| class GameListItem : public QStandardItem { | ||||
| 
 | ||||
| public: | ||||
|     GameListItem(): QStandardItem() {} | ||||
|     GameListItem(const QString& string): QStandardItem(string) {} | ||||
|     virtual ~GameListItem() override {} | ||||
|     GameListItem() : QStandardItem() { | ||||
|     } | ||||
|     GameListItem(const QString& string) : QStandardItem(string) { | ||||
|     } | ||||
|     virtual ~GameListItem() override { | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * A specialization of GameListItem for path values. | ||||
|  * This class ensures that for every full path value it holds, a correct string representation | ||||
|  | @ -76,9 +79,9 @@ public: | |||
|     static const int FullPathRole = Qt::UserRole + 1; | ||||
|     static const int TitleRole = Qt::UserRole + 2; | ||||
| 
 | ||||
|     GameListItemPath(): GameListItem() {} | ||||
|     GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data): GameListItem() | ||||
|     { | ||||
|     GameListItemPath() : GameListItem() { | ||||
|     } | ||||
|     GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data) : GameListItem() { | ||||
|         setData(game_path, FullPathRole); | ||||
| 
 | ||||
|         if (!Loader::IsValidSMDH(smdh_data)) { | ||||
|  | @ -94,13 +97,15 @@ public: | |||
|         setData(GetQPixmapFromSMDH(smdh, true), Qt::DecorationRole); | ||||
| 
 | ||||
|         // Get title form SMDH
 | ||||
|         setData(GetQStringShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole); | ||||
|         setData(GetQStringShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), | ||||
|                 TitleRole); | ||||
|     } | ||||
| 
 | ||||
|     QVariant data(int role) const override { | ||||
|         if (role == Qt::DisplayRole) { | ||||
|             std::string filename; | ||||
|             Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename, nullptr); | ||||
|             Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename, | ||||
|                               nullptr); | ||||
|             QString title = data(TitleRole).toString(); | ||||
|             return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n    " + title); | ||||
|         } else { | ||||
|  | @ -109,7 +114,6 @@ public: | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * A specialization of GameListItem for size values. | ||||
|  * This class ensures that for every numerical size value it holds (in bytes), a correct | ||||
|  | @ -120,14 +124,13 @@ class GameListItemSize : public GameListItem { | |||
| public: | ||||
|     static const int SizeRole = Qt::UserRole + 1; | ||||
| 
 | ||||
|     GameListItemSize(): GameListItem() {} | ||||
|     GameListItemSize(const qulonglong size_bytes): GameListItem() | ||||
|     { | ||||
|     GameListItemSize() : GameListItem() { | ||||
|     } | ||||
|     GameListItemSize(const qulonglong size_bytes) : GameListItem() { | ||||
|         setData(size_bytes, SizeRole); | ||||
|     } | ||||
| 
 | ||||
|     void setData(const QVariant& value, int role) override | ||||
|     { | ||||
|     void setData(const QVariant& value, int role) override { | ||||
|         // By specializing setData for SizeRole, we can ensure that the numerical and string
 | ||||
|         // representations of the data are always accurate and in the correct format.
 | ||||
|         if (role == SizeRole) { | ||||
|  | @ -141,15 +144,14 @@ public: | |||
| 
 | ||||
|     /**
 | ||||
|      * This operator is, in practice, only used by the TreeView sorting systems. | ||||
|      * Override it so that it will correctly sort by numerical value instead of by string representation. | ||||
|      * Override it so that it will correctly sort by numerical value instead of by string | ||||
|      * representation. | ||||
|      */ | ||||
|     bool operator<(const QStandardItem& other) const override | ||||
|     { | ||||
|     bool operator<(const QStandardItem& other) const override { | ||||
|         return data(SizeRole).toULongLong() < other.data(SizeRole).toULongLong(); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Asynchronous worker object for populating the game list. | ||||
|  * Communicates with other threads through Qt's signal/slot system. | ||||
|  | @ -158,8 +160,9 @@ class GameListWorker : public QObject, public QRunnable { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     GameListWorker(QString dir_path, bool deep_scan): | ||||
|             QObject(), QRunnable(), dir_path(dir_path), deep_scan(deep_scan) {} | ||||
|     GameListWorker(QString dir_path, bool deep_scan) | ||||
|         : QObject(), QRunnable(), dir_path(dir_path), deep_scan(deep_scan) { | ||||
|     } | ||||
| 
 | ||||
| public slots: | ||||
|     /// Starts the processing of directory tree information.
 | ||||
|  |  | |||
|  | @ -4,16 +4,16 @@ | |||
| 
 | ||||
| #include <map> | ||||
| 
 | ||||
| #include <QtGlobal> | ||||
| #include <QKeySequence> | ||||
| #include <QShortcut> | ||||
| #include <QtGlobal> | ||||
| 
 | ||||
| #include "citra_qt/hotkeys.h" | ||||
| #include "citra_qt/ui_settings.h" | ||||
| 
 | ||||
| struct Hotkey | ||||
| { | ||||
|     Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) {} | ||||
| struct Hotkey { | ||||
|     Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) { | ||||
|     } | ||||
| 
 | ||||
|     QKeySequence keyseq; | ||||
|     QShortcut* shortcut; | ||||
|  | @ -25,33 +25,28 @@ typedef std::map<QString, HotkeyMap> HotkeyGroupMap; | |||
| 
 | ||||
| HotkeyGroupMap hotkey_groups; | ||||
| 
 | ||||
| void SaveHotkeys() | ||||
| { | ||||
| void SaveHotkeys() { | ||||
|     UISettings::values.shortcuts.clear(); | ||||
|     for (auto group : hotkey_groups) | ||||
|     { | ||||
|         for (auto hotkey : group.second) | ||||
|         { | ||||
|     for (auto group : hotkey_groups) { | ||||
|         for (auto hotkey : group.second) { | ||||
|             UISettings::values.shortcuts.emplace_back( | ||||
|                         UISettings::Shortcut(group.first + "/" + hotkey.first, | ||||
|                                              UISettings::ContextualShortcut(hotkey.second.keyseq.toString(), | ||||
|                                                                            hotkey.second.context))); | ||||
|                 UISettings::Shortcut(group.first + "/" + hotkey.first, | ||||
|                                      UISettings::ContextualShortcut(hotkey.second.keyseq.toString(), | ||||
|                                                                     hotkey.second.context))); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void LoadHotkeys() | ||||
| { | ||||
|     // Make sure NOT to use a reference here because it would become invalid once we call beginGroup()
 | ||||
|     for (auto shortcut : UISettings::values.shortcuts) | ||||
|     { | ||||
| void LoadHotkeys() { | ||||
|     // Make sure NOT to use a reference here because it would become invalid once we call
 | ||||
|     // beginGroup()
 | ||||
|     for (auto shortcut : UISettings::values.shortcuts) { | ||||
|         QStringList cat = shortcut.first.split("/"); | ||||
|         Q_ASSERT(cat.size() >= 2); | ||||
| 
 | ||||
|         // RegisterHotkey assigns default keybindings, so use old values as default parameters
 | ||||
|         Hotkey& hk = hotkey_groups[cat[0]][cat[1]]; | ||||
|         if (!shortcut.second.first.isEmpty()) | ||||
|         { | ||||
|         if (!shortcut.second.first.isEmpty()) { | ||||
|             hk.keyseq = QKeySequence::fromString(shortcut.second.first); | ||||
|             hk.context = (Qt::ShortcutContext)shortcut.second.second; | ||||
|         } | ||||
|  | @ -60,17 +55,15 @@ void LoadHotkeys() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void RegisterHotkey(const QString& group, const QString& action, const QKeySequence& default_keyseq, Qt::ShortcutContext default_context) | ||||
| { | ||||
|     if (hotkey_groups[group].find(action) == hotkey_groups[group].end()) | ||||
|     { | ||||
| void RegisterHotkey(const QString& group, const QString& action, const QKeySequence& default_keyseq, | ||||
|                     Qt::ShortcutContext default_context) { | ||||
|     if (hotkey_groups[group].find(action) == hotkey_groups[group].end()) { | ||||
|         hotkey_groups[group][action].keyseq = default_keyseq; | ||||
|         hotkey_groups[group][action].context = default_context; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget) | ||||
| { | ||||
| QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget) { | ||||
|     Hotkey& hk = hotkey_groups[group][action]; | ||||
| 
 | ||||
|     if (!hk.shortcut) | ||||
|  | @ -79,16 +72,12 @@ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widge | |||
|     return hk.shortcut; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GHotkeysDialog::GHotkeysDialog(QWidget* parent): QWidget(parent) | ||||
| { | ||||
| GHotkeysDialog::GHotkeysDialog(QWidget* parent) : QWidget(parent) { | ||||
|     ui.setupUi(this); | ||||
| 
 | ||||
|     for (auto group : hotkey_groups) | ||||
|     { | ||||
|     for (auto group : hotkey_groups) { | ||||
|         QTreeWidgetItem* toplevel_item = new QTreeWidgetItem(QStringList(group.first)); | ||||
|         for (auto hotkey : group.second) | ||||
|         { | ||||
|         for (auto hotkey : group.second) { | ||||
|             QStringList columns; | ||||
|             columns << hotkey.first << hotkey.second.keyseq.toString(); | ||||
|             QTreeWidgetItem* item = new QTreeWidgetItem(columns); | ||||
|  |  | |||
|  | @ -16,36 +16,42 @@ class QShortcut; | |||
|  * | ||||
|  * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger") | ||||
|  * @param action Name of the action (e.g. "Start Emulation", "Load Image") | ||||
|  * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the settings file before | ||||
|  * @param default_context Default context to assign if the hotkey wasn't present in the settings file before | ||||
|  * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the settings | ||||
|  * file before | ||||
|  * @param default_context Default context to assign if the hotkey wasn't present in the settings | ||||
|  * file before | ||||
|  * @warning Both the group and action strings will be displayed in the hotkey settings dialog | ||||
|  */ | ||||
| void RegisterHotkey(const QString& group, const QString& action, const QKeySequence& default_keyseq = QKeySequence(), Qt::ShortcutContext default_context = Qt::WindowShortcut); | ||||
| void RegisterHotkey(const QString& group, const QString& action, | ||||
|                     const QKeySequence& default_keyseq = QKeySequence(), | ||||
|                     Qt::ShortcutContext default_context = Qt::WindowShortcut); | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns a QShortcut object whose activated() signal can be connected to other QObjects' slots. | ||||
|  * | ||||
|  * @param widget Parent widget of the returned QShortcut. | ||||
|  * @warning If multiple QWidgets' call this function for the same action, the returned QShortcut will be the same. Thus, you shouldn't rely on the caller really being the QShortcut's parent. | ||||
|  * @warning If multiple QWidgets' call this function for the same action, the returned QShortcut | ||||
|  * will be the same. Thus, you shouldn't rely on the caller really being the QShortcut's parent. | ||||
|  */ | ||||
| QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget); | ||||
| 
 | ||||
| /**
 | ||||
|  * Saves all registered hotkeys to the settings file. | ||||
|  * | ||||
|  * @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a settings group will be created to store the key sequence and the hotkey context. | ||||
|  * @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a | ||||
|  * settings group will be created to store the key sequence and the hotkey context. | ||||
|  */ | ||||
| void SaveHotkeys(); | ||||
| 
 | ||||
| /**
 | ||||
|  * Loads hotkeys from the settings file. | ||||
|  * | ||||
|  * @note Yet unregistered hotkeys which are present in the settings will automatically be registered. | ||||
|  * @note Yet unregistered hotkeys which are present in the settings will automatically be | ||||
|  * registered. | ||||
|  */ | ||||
| void LoadHotkeys(); | ||||
| 
 | ||||
| class GHotkeysDialog : public QWidget | ||||
| { | ||||
| class GHotkeysDialog : public QWidget { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|  |  | |||
|  | @ -10,9 +10,9 @@ | |||
| 
 | ||||
| #define QT_NO_OPENGL | ||||
| #include <QDesktopWidget> | ||||
| #include <QtGui> | ||||
| #include <QFileDialog> | ||||
| #include <QMessageBox> | ||||
| #include <QtGui> | ||||
| #include "qhexedit.h" | ||||
| 
 | ||||
| #include "citra_qt/bootmanager.h" | ||||
|  | @ -36,27 +36,26 @@ | |||
| #include "citra_qt/debugger/ramview.h" | ||||
| #include "citra_qt/debugger/registers.h" | ||||
| 
 | ||||
| #include "common/logging/backend.h" | ||||
| #include "common/logging/filter.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/logging/text_formatter.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/platform.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/scope_exit.h" | ||||
| #include "common/string_util.h" | ||||
| #include "common/logging/backend.h" | ||||
| #include "common/logging/filter.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/logging/text_formatter.h" | ||||
| 
 | ||||
| #include "core/core.h" | ||||
| #include "core/settings.h" | ||||
| #include "core/system.h" | ||||
| #include "core/arm/disassembler/load_symbol_map.h" | ||||
| #include "core/core.h" | ||||
| #include "core/gdbstub/gdbstub.h" | ||||
| #include "core/loader/loader.h" | ||||
| #include "core/settings.h" | ||||
| #include "core/system.h" | ||||
| 
 | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
| GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) | ||||
| { | ||||
| GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { | ||||
|     Pica::g_debug_context = Pica::DebugContext::Construct(); | ||||
| 
 | ||||
|     ui.setupUi(this); | ||||
|  | @ -91,7 +90,7 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) | |||
| 
 | ||||
|     graphicsWidget = new GPUCommandStreamWidget(this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, graphicsWidget); | ||||
|     graphicsWidget ->hide(); | ||||
|     graphicsWidget->hide(); | ||||
| 
 | ||||
|     graphicsCommandsWidget = new GPUCommandListWidget(this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); | ||||
|  | @ -110,7 +109,8 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) | |||
|     graphicsTracingWidget->hide(); | ||||
| 
 | ||||
|     auto graphicsSurfaceViewerAction = new QAction(tr("Create Pica surface viewer"), this); | ||||
|     connect(graphicsSurfaceViewerAction, SIGNAL(triggered()), this, SLOT(OnCreateGraphicsSurfaceViewer())); | ||||
|     connect(graphicsSurfaceViewerAction, SIGNAL(triggered()), this, | ||||
|             SLOT(OnCreateGraphicsSurfaceViewer())); | ||||
| 
 | ||||
|     QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); | ||||
|     debug_menu->addAction(graphicsSurfaceViewerAction); | ||||
|  | @ -167,35 +167,44 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) | |||
|     UpdateRecentFiles(); | ||||
| 
 | ||||
|     // Setup connections
 | ||||
|     connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)), Qt::DirectConnection); | ||||
|     connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)), | ||||
|             Qt::DirectConnection); | ||||
|     connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure())); | ||||
|     connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()),Qt::DirectConnection); | ||||
|     connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()), | ||||
|             Qt::DirectConnection); | ||||
|     connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap())); | ||||
|     connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this, SLOT(OnMenuSelectGameListRoot())); | ||||
|     connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this, | ||||
|             SLOT(OnMenuSelectGameListRoot())); | ||||
|     connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame())); | ||||
|     connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame())); | ||||
|     connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame())); | ||||
|     connect(ui.action_Single_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode())); | ||||
| 
 | ||||
|     connect(this, SIGNAL(EmulationStarting(EmuThread*)), disasmWidget, SLOT(OnEmulationStarting(EmuThread*))); | ||||
|     connect(this, SIGNAL(EmulationStarting(EmuThread*)), disasmWidget, | ||||
|             SLOT(OnEmulationStarting(EmuThread*))); | ||||
|     connect(this, SIGNAL(EmulationStopping()), disasmWidget, SLOT(OnEmulationStopping())); | ||||
|     connect(this, SIGNAL(EmulationStarting(EmuThread*)), registersWidget, SLOT(OnEmulationStarting(EmuThread*))); | ||||
|     connect(this, SIGNAL(EmulationStarting(EmuThread*)), registersWidget, | ||||
|             SLOT(OnEmulationStarting(EmuThread*))); | ||||
|     connect(this, SIGNAL(EmulationStopping()), registersWidget, SLOT(OnEmulationStopping())); | ||||
|     connect(this, SIGNAL(EmulationStarting(EmuThread*)), render_window, SLOT(OnEmulationStarting(EmuThread*))); | ||||
|     connect(this, SIGNAL(EmulationStarting(EmuThread*)), render_window, | ||||
|             SLOT(OnEmulationStarting(EmuThread*))); | ||||
|     connect(this, SIGNAL(EmulationStopping()), render_window, SLOT(OnEmulationStopping())); | ||||
|     connect(this, SIGNAL(EmulationStarting(EmuThread*)), graphicsTracingWidget, SLOT(OnEmulationStarting(EmuThread*))); | ||||
|     connect(this, SIGNAL(EmulationStarting(EmuThread*)), graphicsTracingWidget, | ||||
|             SLOT(OnEmulationStarting(EmuThread*))); | ||||
|     connect(this, SIGNAL(EmulationStopping()), graphicsTracingWidget, SLOT(OnEmulationStopping())); | ||||
| 
 | ||||
| 
 | ||||
|     // Setup hotkeys
 | ||||
|     RegisterHotkey("Main Window", "Load File", QKeySequence::Open); | ||||
|     RegisterHotkey("Main Window", "Start Emulation"); | ||||
|     LoadHotkeys(); | ||||
| 
 | ||||
|     connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile())); | ||||
|     connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); | ||||
|     connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, | ||||
|             SLOT(OnMenuLoadFile())); | ||||
|     connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, | ||||
|             SLOT(OnStartGame())); | ||||
| 
 | ||||
|     std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||||
|     std::string window_title = | ||||
|         Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||||
|     setWindowTitle(window_title.c_str()); | ||||
| 
 | ||||
|     show(); | ||||
|  | @ -208,8 +217,7 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| GMainWindow::~GMainWindow() | ||||
| { | ||||
| GMainWindow::~GMainWindow() { | ||||
|     // will get automatically deleted otherwise
 | ||||
|     if (render_window->parent() == nullptr) | ||||
|         delete render_window; | ||||
|  | @ -217,19 +225,18 @@ GMainWindow::~GMainWindow() | |||
|     Pica::g_debug_context.reset(); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnDisplayTitleBars(bool show) | ||||
| { | ||||
| void GMainWindow::OnDisplayTitleBars(bool show) { | ||||
|     QList<QDockWidget*> widgets = findChildren<QDockWidget*>(); | ||||
| 
 | ||||
|     if (show) { | ||||
|         for (QDockWidget* widget: widgets) { | ||||
|         for (QDockWidget* widget : widgets) { | ||||
|             QWidget* old = widget->titleBarWidget(); | ||||
|             widget->setTitleBarWidget(nullptr); | ||||
|             if (old != nullptr) | ||||
|                 delete old; | ||||
|         } | ||||
|     } else { | ||||
|         for (QDockWidget* widget: widgets) { | ||||
|         for (QDockWidget* widget : widgets) { | ||||
|             QWidget* old = widget->titleBarWidget(); | ||||
|             widget->setTitleBarWidget(new QWidget()); | ||||
|             if (old != nullptr) | ||||
|  | @ -249,7 +256,8 @@ bool GMainWindow::InitializeSystem() { | |||
|     if (!gladLoadGL()) { | ||||
|         QMessageBox::critical(this, tr("Error while starting Citra!"), | ||||
|                               tr("Failed to initialize the video core!\n\n" | ||||
|                                  "Please ensure that your GPU supports OpenGL 3.3 and that you have the latest graphics driver.")); | ||||
|                                  "Please ensure that your GPU supports OpenGL 3.3 and that you " | ||||
|                                  "have the latest graphics driver.")); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|  | @ -260,7 +268,8 @@ bool GMainWindow::InitializeSystem() { | |||
|         case System::Result::ErrorInitVideoCore: | ||||
|             QMessageBox::critical(this, tr("Error while starting Citra!"), | ||||
|                                   tr("Failed to initialize the video core!\n\n" | ||||
|                                      "Please ensure that your GPU supports OpenGL 3.3 and that you have the latest graphics driver.")); | ||||
|                                      "Please ensure that your GPU supports OpenGL 3.3 and that you " | ||||
|                                      "have the latest graphics driver.")); | ||||
|             break; | ||||
| 
 | ||||
|         default: | ||||
|  | @ -293,8 +302,12 @@ bool GMainWindow::LoadROM(const std::string& filename) { | |||
|             QMessageBox popup_error; | ||||
|             popup_error.setTextFormat(Qt::RichText); | ||||
|             popup_error.setWindowTitle(tr("Error while loading ROM!")); | ||||
|             popup_error.setText(tr("The game that you are trying to load must be decrypted before being used with Citra.<br/><br/>" | ||||
|                                   "For more information on dumping and decrypting games, please see: <a href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://citra-emu.org/wiki/Dumping-Game-Cartridges</a>")); | ||||
|             popup_error.setText( | ||||
|                 tr("The game that you are trying to load must be decrypted before being used with " | ||||
|                    "Citra.<br/><br/>" | ||||
|                    "For more information on dumping and decrypting games, please see: <a " | ||||
|                    "href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://" | ||||
|                    "citra-emu.org/wiki/Dumping-Game-Cartridges</a>")); | ||||
|             popup_error.setIcon(QMessageBox::Critical); | ||||
|             popup_error.exec(); | ||||
|             break; | ||||
|  | @ -306,8 +319,7 @@ bool GMainWindow::LoadROM(const std::string& filename) { | |||
|         case Loader::ResultStatus::Error: | ||||
| 
 | ||||
|         default: | ||||
|             QMessageBox::critical(this, tr("Error while loading ROM!"), | ||||
|                                   tr("Unknown error!")); | ||||
|             QMessageBox::critical(this, tr("Error while loading ROM!"), tr("Unknown error!")); | ||||
|             break; | ||||
|         } | ||||
|         return false; | ||||
|  | @ -332,13 +344,20 @@ void GMainWindow::BootGame(const std::string& filename) { | |||
|     emu_thread->start(); | ||||
| 
 | ||||
|     connect(render_window, SIGNAL(Closed()), this, SLOT(OnStopGame())); | ||||
|     // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues
 | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection); | ||||
|     // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
 | ||||
|     // before the CPU continues
 | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget, | ||||
|             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget, | ||||
|             SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
|     connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), | ||||
|             Qt::BlockingQueuedConnection); | ||||
| 
 | ||||
|     // Update the GUI
 | ||||
|     registersWidget->OnDebugModeEntered(); | ||||
|  | @ -393,10 +412,12 @@ void GMainWindow::StoreRecentFile(const std::string& filename) { | |||
| } | ||||
| 
 | ||||
| void GMainWindow::UpdateRecentFiles() { | ||||
|     unsigned int num_recent_files = std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item)); | ||||
|     unsigned int num_recent_files = | ||||
|         std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item)); | ||||
| 
 | ||||
|     for (unsigned int i = 0; i < num_recent_files; i++) { | ||||
|         QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(UISettings::values.recent_files[i]).fileName()); | ||||
|         QString text = QString("&%1. %2").arg(i + 1).arg( | ||||
|             QFileInfo(UISettings::values.recent_files[i]).fileName()); | ||||
|         actions_recent_files[i]->setText(text); | ||||
|         actions_recent_files[i]->setData(UISettings::values.recent_files[i]); | ||||
|         actions_recent_files[i]->setToolTip(UISettings::values.recent_files[i]); | ||||
|  | @ -420,7 +441,9 @@ void GMainWindow::OnGameListLoadFile(QString game_path) { | |||
| } | ||||
| 
 | ||||
| void GMainWindow::OnMenuLoadFile() { | ||||
|     QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)")); | ||||
|     QString filename = | ||||
|         QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path, | ||||
|                                      tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)")); | ||||
|     if (!filename.isEmpty()) { | ||||
|         UISettings::values.roms_path = QFileInfo(filename).path(); | ||||
| 
 | ||||
|  | @ -429,7 +452,8 @@ void GMainWindow::OnMenuLoadFile() { | |||
| } | ||||
| 
 | ||||
| void GMainWindow::OnMenuLoadSymbolMap() { | ||||
|     QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol map (*)")); | ||||
|     QString filename = QFileDialog::getOpenFileName( | ||||
|         this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol map (*)")); | ||||
|     if (!filename.isEmpty()) { | ||||
|         UISettings::values.symbols_path = QFileInfo(filename).path(); | ||||
| 
 | ||||
|  | @ -455,7 +479,8 @@ void GMainWindow::OnMenuRecentFile() { | |||
|         BootGame(filename.toStdString()); | ||||
|     } else { | ||||
|         // Display an error message and remove the file from the list.
 | ||||
|         QMessageBox::information(this, tr("File not found"), tr("File \"%1\" not found").arg(filename)); | ||||
|         QMessageBox::information(this, tr("File not found"), | ||||
|                                  tr("File \"%1\" not found").arg(filename)); | ||||
| 
 | ||||
|         UISettings::values.recent_files.removeOne(filename); | ||||
|         UpdateRecentFiles(); | ||||
|  | @ -512,8 +537,7 @@ void GMainWindow::ToggleWindowMode() { | |||
| void GMainWindow::OnConfigure() { | ||||
|     ConfigureDialog configureDialog(this); | ||||
|     auto result = configureDialog.exec(); | ||||
|     if (result == QDialog::Accepted) | ||||
|     { | ||||
|     if (result == QDialog::Accepted) { | ||||
|         configureDialog.applyConfiguration(); | ||||
|         render_window->ReloadSetKeymaps(); | ||||
|         config->Save(); | ||||
|  | @ -531,9 +555,9 @@ bool GMainWindow::ConfirmClose() { | |||
|     if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) | ||||
|         return true; | ||||
| 
 | ||||
|     auto answer = QMessageBox::question(this, tr("Citra"), | ||||
|                                         tr("Are you sure you want to close Citra?"), | ||||
|                                         QMessageBox::Yes | QMessageBox::No, QMessageBox::No); | ||||
|     auto answer = | ||||
|         QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"), | ||||
|                               QMessageBox::Yes | QMessageBox::No, QMessageBox::No); | ||||
|     return answer != QMessageBox::No; | ||||
| } | ||||
| 
 | ||||
|  | @ -575,9 +599,7 @@ int main(int argc, char* argv[]) { | |||
|     Log::SetFilter(&log_filter); | ||||
| 
 | ||||
|     MicroProfileOnThreadCreate("Frontend"); | ||||
|     SCOPE_EXIT({ | ||||
|         MicroProfileShutdown(); | ||||
|     }); | ||||
|     SCOPE_EXIT({ MicroProfileShutdown(); }); | ||||
| 
 | ||||
|     // Init settings params
 | ||||
|     QCoreApplication::setOrganizationName("Citra team"); | ||||
|  | @ -586,7 +608,8 @@ int main(int argc, char* argv[]) { | |||
|     QApplication::setAttribute(Qt::AA_X11InitThreads); | ||||
|     QApplication app(argc, argv); | ||||
| 
 | ||||
|     // Qt changes the locale and causes issues in float conversion using std::to_string() when generating shaders
 | ||||
|     // Qt changes the locale and causes issues in float conversion using std::to_string() when
 | ||||
|     // generating shaders
 | ||||
|     setlocale(LC_ALL, "C"); | ||||
| 
 | ||||
|     GMainWindow main_window; | ||||
|  |  | |||
|  | @ -5,8 +5,8 @@ | |||
| #ifndef _CITRA_QT_MAIN_HXX_ | ||||
| #define _CITRA_QT_MAIN_HXX_ | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QMainWindow> | ||||
| #include <memory> | ||||
| 
 | ||||
| #include "ui_main.h" | ||||
| 
 | ||||
|  | @ -23,11 +23,11 @@ class CallstackWidget; | |||
| class GPUCommandStreamWidget; | ||||
| class GPUCommandListWidget; | ||||
| 
 | ||||
| class GMainWindow : public QMainWindow | ||||
| { | ||||
| class GMainWindow : public QMainWindow { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
|     static const int max_recent_files_item = 10; ///< Max number of recently loaded items to keep track
 | ||||
|     static const int max_recent_files_item = | ||||
|         10; ///< Max number of recently loaded items to keep track
 | ||||
| 
 | ||||
|     // TODO: Make use of this!
 | ||||
|     enum { | ||||
|  |  | |||
|  | @ -7,5 +7,4 @@ | |||
| namespace UISettings { | ||||
| 
 | ||||
| Values values = {}; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -5,14 +5,14 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <QByteArray> | ||||
| #include <QStringList> | ||||
| #include <QString> | ||||
| #include <QStringList> | ||||
| 
 | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace UISettings { | ||||
| 
 | ||||
| using ContextualShortcut = std::pair<QString, int> ; | ||||
| using ContextualShortcut = std::pair<QString, int>; | ||||
| using Shortcut = std::pair<QString, ContextualShortcut>; | ||||
| 
 | ||||
| struct Values { | ||||
|  | @ -43,5 +43,4 @@ struct Values { | |||
| }; | ||||
| 
 | ||||
| extern Values values; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| 
 | ||||
| // Copyright 2014 Tony Wasserka
 | ||||
| // All rights reserved.
 | ||||
| //
 | ||||
|  | @ -29,15 +28,15 @@ | |||
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | ||||
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | ||||
| 
 | ||||
| #include <cstdlib> | ||||
| #include <QLineEdit> | ||||
| #include <QRegExpValidator> | ||||
| #include <cstdlib> | ||||
| 
 | ||||
| #include "citra_qt/util/spinbox.h" | ||||
| #include "common/assert.h" | ||||
| 
 | ||||
| CSpinBox::CSpinBox(QWidget* parent) : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) | ||||
| { | ||||
| CSpinBox::CSpinBox(QWidget* parent) | ||||
|     : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) { | ||||
|     // TODO: Might be nice to not immediately call the slot.
 | ||||
|     //       Think of an address that is being replaced by a different one, in which case a lot
 | ||||
|     //       invalid intermediate addresses would be read from during editing.
 | ||||
|  | @ -46,8 +45,7 @@ CSpinBox::CSpinBox(QWidget* parent) : QAbstractSpinBox(parent), min_value(-100), | |||
|     UpdateText(); | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::SetValue(qint64 val) | ||||
| { | ||||
| void CSpinBox::SetValue(qint64 val) { | ||||
|     auto old_value = value; | ||||
|     value = std::max(std::min(val, max_value), min_value); | ||||
| 
 | ||||
|  | @ -57,8 +55,7 @@ void CSpinBox::SetValue(qint64 val) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::SetRange(qint64 min, qint64 max) | ||||
| { | ||||
| void CSpinBox::SetRange(qint64 min, qint64 max) { | ||||
|     min_value = min; | ||||
|     max_value = max; | ||||
| 
 | ||||
|  | @ -66,8 +63,7 @@ void CSpinBox::SetRange(qint64 min, qint64 max) | |||
|     UpdateText(); | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::stepBy(int steps) | ||||
| { | ||||
| void CSpinBox::stepBy(int steps) { | ||||
|     auto new_value = value; | ||||
|     // Scale number of steps by the currently selected digit
 | ||||
|     // TODO: Move this code elsewhere and enable it.
 | ||||
|  | @ -93,8 +89,7 @@ void CSpinBox::stepBy(int steps) | |||
|     UpdateText(); | ||||
| } | ||||
| 
 | ||||
| QAbstractSpinBox::StepEnabled CSpinBox::stepEnabled() const | ||||
| { | ||||
| QAbstractSpinBox::StepEnabled CSpinBox::stepEnabled() const { | ||||
|     StepEnabled ret = StepNone; | ||||
| 
 | ||||
|     if (value > min_value) | ||||
|  | @ -106,29 +101,25 @@ QAbstractSpinBox::StepEnabled CSpinBox::stepEnabled() const | |||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::SetBase(int base) | ||||
| { | ||||
| void CSpinBox::SetBase(int base) { | ||||
|     this->base = base; | ||||
| 
 | ||||
|     UpdateText(); | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::SetNumDigits(int num_digits) | ||||
| { | ||||
| void CSpinBox::SetNumDigits(int num_digits) { | ||||
|     this->num_digits = num_digits; | ||||
| 
 | ||||
|     UpdateText(); | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::SetPrefix(const QString& prefix) | ||||
| { | ||||
| void CSpinBox::SetPrefix(const QString& prefix) { | ||||
|     this->prefix = prefix; | ||||
| 
 | ||||
|     UpdateText(); | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::SetSuffix(const QString& suffix) | ||||
| { | ||||
| void CSpinBox::SetSuffix(const QString& suffix) { | ||||
|     this->suffix = suffix; | ||||
| 
 | ||||
|     UpdateText(); | ||||
|  | @ -161,8 +152,7 @@ static QString StringToInputMask(const QString& input) { | |||
|     return mask; | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::UpdateText() | ||||
| { | ||||
| void CSpinBox::UpdateText() { | ||||
|     // If a fixed number of digits is used, we put the line edit in insertion mode by setting an
 | ||||
|     // input mask.
 | ||||
|     QString mask; | ||||
|  | @ -179,10 +169,9 @@ void CSpinBox::UpdateText() | |||
|         // The greatest signed 64-bit number has 19 decimal digits.
 | ||||
|         // TODO: Could probably make this more generic with some logarithms.
 | ||||
|         // For reference, unsigned 64-bit can have up to 20 decimal digits.
 | ||||
|         int digits = (num_digits != 0) ? num_digits | ||||
|                      : (base == 16) ? 16 | ||||
|                      : (base == 10) ? 19 | ||||
|                      : 0xFF; // fallback case...
 | ||||
|         int digits = (num_digits != 0) | ||||
|                          ? num_digits | ||||
|                          : (base == 16) ? 16 : (base == 10) ? 19 : 0xFF; // fallback case...
 | ||||
| 
 | ||||
|         // Match num_digits digits
 | ||||
|         // Digits irrelevant to the chosen number base are filtered in the validator
 | ||||
|  | @ -203,29 +192,24 @@ void CSpinBox::UpdateText() | |||
|     lineEdit()->setCursorPosition(cursor_position); | ||||
| } | ||||
| 
 | ||||
| QString CSpinBox::TextFromValue() | ||||
| { | ||||
|     return prefix | ||||
|            + QString(HasSign() ? ((value < 0) ? "-" : "+") : "") | ||||
|            + QString("%1").arg(std::abs(value), num_digits, base, QLatin1Char('0')).toUpper() | ||||
|            + suffix; | ||||
| QString CSpinBox::TextFromValue() { | ||||
|     return prefix + QString(HasSign() ? ((value < 0) ? "-" : "+") : "") + | ||||
|            QString("%1").arg(std::abs(value), num_digits, base, QLatin1Char('0')).toUpper() + | ||||
|            suffix; | ||||
| } | ||||
| 
 | ||||
| qint64 CSpinBox::ValueFromText() | ||||
| { | ||||
| qint64 CSpinBox::ValueFromText() { | ||||
|     unsigned strpos = prefix.length(); | ||||
| 
 | ||||
|     QString num_string = text().mid(strpos, text().length() - strpos - suffix.length()); | ||||
|     return num_string.toLongLong(nullptr, base); | ||||
| } | ||||
| 
 | ||||
| bool CSpinBox::HasSign() const | ||||
| { | ||||
| bool CSpinBox::HasSign() const { | ||||
|     return base == 10 && min_value < 0; | ||||
| } | ||||
| 
 | ||||
| void CSpinBox::OnEditingFinished() | ||||
| { | ||||
| void CSpinBox::OnEditingFinished() { | ||||
|     // Only update for valid input
 | ||||
|     QString input = lineEdit()->text(); | ||||
|     int pos = 0; | ||||
|  | @ -233,8 +217,7 @@ void CSpinBox::OnEditingFinished() | |||
|         SetValue(ValueFromText()); | ||||
| } | ||||
| 
 | ||||
| QValidator::State CSpinBox::validate(QString& input, int& pos) const | ||||
| { | ||||
| QValidator::State CSpinBox::validate(QString& input, int& pos) const { | ||||
|     if (!prefix.isEmpty() && input.left(prefix.length()) != prefix) | ||||
|         return QValidator::Invalid; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| 
 | ||||
| // Copyright 2014 Tony Wasserka
 | ||||
| // All rights reserved.
 | ||||
| //
 | ||||
|  | @ -29,7 +28,6 @@ | |||
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | ||||
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | ||||
| 
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <QAbstractSpinBox> | ||||
|  |  | |||
|  | @ -16,10 +16,12 @@ QFont GetMonospaceFont() { | |||
| } | ||||
| 
 | ||||
| QString ReadableByteSize(qulonglong size) { | ||||
|     static const std::array<const char*, 6> units = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; | ||||
|     static const std::array<const char*, 6> units = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; | ||||
|     if (size == 0) | ||||
|         return "0"; | ||||
|     int digit_groups = std::min<int>(static_cast<int>(std::log10(size) / std::log10(1024)), static_cast<int>(units.size())); | ||||
|     return QString("%L1 %2").arg(size / std::pow(1024, digit_groups), 0, 'f', 1) | ||||
|                             .arg(units[digit_groups]); | ||||
|     int digit_groups = std::min<int>(static_cast<int>(std::log10(size) / std::log10(1024)), | ||||
|                                      static_cast<int>(units.size())); | ||||
|     return QString("%L1 %2") | ||||
|         .arg(size / std::pow(1024, digit_groups), 0, 'f', 1) | ||||
|         .arg(units[digit_groups]); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue