diff --git a/citra.sln b/citra.sln
index 8d6deada2..ebba4c2f0 100644
--- a/citra.sln
+++ b/citra.sln
@@ -1,5 +1,7 @@
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2013 for Windows Desktop
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "src\common\common.vcxproj", "{DFE335FC-755D-4BAA-8452-94434F8A1EDB}"
ProjectSection(ProjectDependencies) = postProject
{69F00340-5C3D-449F-9A80-958435C6CF06} = {69F00340-5C3D-449F-9A80-958435C6CF06}
@@ -17,6 +19,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "src\core\core.vcxpr
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scm_rev_gen", "src\common\scm_rev_gen.vcxproj", "{69F00340-5C3D-449F-9A80-958435C6CF06}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "citra_qt", "src\citra_qt\citra_qt.vcxproj", "{A587F714-490F-407A-9E36-7AB7FA0D7BAB}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -57,6 +61,14 @@ Global
{69F00340-5C3D-449F-9A80-958435C6CF06}.Release|Win32.Build.0 = Release|Win32
{69F00340-5C3D-449F-9A80-958435C6CF06}.Release|x64.ActiveCfg = Release|x64
{69F00340-5C3D-449F-9A80-958435C6CF06}.Release|x64.Build.0 = Release|x64
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Debug|Win32.Build.0 = Debug|Win32
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Debug|x64.ActiveCfg = Debug|x64
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Debug|x64.Build.0 = Debug|x64
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|Win32.ActiveCfg = Release|Win32
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|Win32.Build.0 = Release|Win32
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|x64.ActiveCfg = Release|x64
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
new file mode 100644
index 000000000..facb99e90
--- /dev/null
+++ b/src/citra_qt/CMakeLists.txt
@@ -0,0 +1,38 @@
+set(SRCS
+ src/bootmanager.cpp
+ src/callstack.cpp
+ src/disasm.cpp
+ src/cpu_regs.cpp
+ src/hotkeys.cpp
+ src/main.cpp
+ src/ramview.cpp
+ src/config/controller_config.cpp
+ src/config/controller_config_util.cpp)
+
+qt4_wrap_ui(UI_HDRS
+ src/callstack.ui
+ src/disasm.ui
+ src/cpu_regs.ui
+ src/hotkeys.ui
+ src/main.ui
+ src/config/controller_config.ui)
+
+qt4_wrap_cpp(MOC_SRCS
+ src/bootmanager.hxx
+ src/callstack.hxx
+ src/disasm.hxx
+ src/cpu_regs.hxx
+ src/hotkeys.hxx
+ src/main.hxx
+ src/ramview.hxx
+ src/config/controller_config.hxx
+ src/config/controller_config_util.hxx)
+
+# add uic results to include directories
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+include_directories(./src/)
+
+add_executable(citra-qt ${SRCS} ${MOC_SRCS} ${UI_HDRS})
+target_link_libraries(citra-qt core common qhexedit ${QT_LIBRARIES} ${OPENGL_LIBRARIES} ${SDL2_LIBRARY} rt GLEW ${GLFW_LIBRARIES})
+
+#install(TARGETS citra-qt RUNTIME DESTINATION ${bindir})
diff --git a/src/citra_qt/citra_qt.vcxproj b/src/citra_qt/citra_qt.vcxproj
new file mode 100644
index 000000000..9164b280b
--- /dev/null
+++ b/src/citra_qt/citra_qt.vcxproj
@@ -0,0 +1,180 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {A587F714-490F-407A-9E36-7AB7FA0D7BAB}
+ citra_qt
+
+
+
+ Application
+ true
+ v120
+
+
+ Application
+ true
+ v120
+
+
+ Application
+ false
+ v120
+
+
+ Application
+ false
+ v120
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ src/config/ui_
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {dfe335fc-755d-4baa-8452-94434f8a1edb}
+
+
+ {8aea7f29-3466-4786-a10d-6a4bd0610977}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/citra_qt/citra_qt.vcxproj.filters b/src/citra_qt/citra_qt.vcxproj.filters
new file mode 100644
index 000000000..3900cc8e0
--- /dev/null
+++ b/src/citra_qt/citra_qt.vcxproj.filters
@@ -0,0 +1,103 @@
+
+
+
+
+ {1b8f77c1-61e8-4a9f-95f8-8d1c53015ad8}
+
+
+ {dede739c-939b-4147-9e72-4a326b97d237}
+
+
+ {80178741-d3ab-4031-892c-ec58490ea8bf}
+
+
+
+
+
+ debugger
+
+
+ debugger
+
+
+
+ debugger
+
+
+ debugger
+
+
+ qhexedit
+
+
+ qhexedit
+
+
+ qhexedit
+
+
+ qhexedit
+
+
+
+ config
+
+
+ config
+
+
+
+
+
+ debugger
+
+
+ debugger
+
+
+ qhexedit
+
+
+ qhexedit
+
+
+ qhexedit
+
+
+ qhexedit
+
+
+ debugger
+
+
+ debugger
+
+
+
+
+ config
+
+
+ config
+
+
+
+
+
+ debugger
+
+
+ debugger
+
+
+ debugger
+
+
+
+ config
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/citra_qt/qt-build.props b/src/citra_qt/qt-build.props
new file mode 100644
index 000000000..d4600006c
--- /dev/null
+++ b/src/citra_qt/qt-build.props
@@ -0,0 +1,56 @@
+
+
+
+ Midl
+ CustomBuild
+
+
+
+ .hpp
+ ui_
+ %QTDIR%\bin\uic.exe [inputs] -o "[QtUicPrefix]%(FileName)[QtUicExt]"
+ [QtUicPrefix]%(FileName)[QtUicExt]
+ %(FileName).ui
+
+
+
+ Midl
+ CustomBuild
+
+
+
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ False
+ False
+ _moc
+ %(FileName)%(QtMocPfx)
+ %QTDIR%\bin\moc.exe [QtMocNoWarnings] [QtCoreLib] [QtShared] [QtThread] [QtUnicode] [QtLargeFile] [QtKeywords] [QtOpenGLLib] [QtNoDebug] [QtGuiLib] -DWIN32 -D_MSC_VER=1500 -DWIN32 [Inputs] -o$(IntDir)%(QtMocFilename).cpp && cl.exe $(IntDir)%(QtMocFilename).cpp [QtCommandLine] /c /Fo"$(IntDir)%(QtMocFilename).obj"
+ $(IntDir)%(QtMocFilename).obj
+ %(FileName).hxx
+ true
+
+
+
+ Midl
+ CustomBuild
+
+
+
+ _qrc
+ %(FileName)%(QtQrcPfx)
+ %QTDIR%\bin\rcc.exe [inputs] -o $(IntDir)%(QtQrcFileName).cpp && cl.exe $(IntDir)%(QtQrcFileName).cpp /c /Fo"$(IntDir)%(QtQrcFileName)" [QtCommandLine]
+ $(IntDir)%(QtQrcFileName).obj
+ %(FileName).qrc
+
+
+
\ No newline at end of file
diff --git a/src/citra_qt/qt-build.targets b/src/citra_qt/qt-build.targets
new file mode 100644
index 000000000..febec73c4
--- /dev/null
+++ b/src/citra_qt/qt-build.targets
@@ -0,0 +1,242 @@
+
+
+
+
+
+ _UIC
+
+
+ _MOC
+
+
+ _QRC
+
+
+
+ $(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml
+
+
+ $(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml
+
+
+ $(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ComputeLinkInputsTargets);
+ ComputeUICOutput;
+
+
+ $(ComputeLibInputsTargets);
+ ComputeUICOutput;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ComputeLinkInputsTargets);
+ ComputeMOCOutput;
+
+
+ $(ComputeLibInputsTargets);
+ ComputeMOCOutput;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ComputeLinkInputsTargets);
+ ComputeQRCOutput;
+
+
+ $(ComputeLibInputsTargets);
+ ComputeQRCOutput;
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/citra_qt/qt-build.xml b/src/citra_qt/qt-build.xml
new file mode 100644
index 000000000..1bc84aa99
--- /dev/null
+++ b/src/citra_qt/qt-build.xml
@@ -0,0 +1,486 @@
+
+
+
+
+
+
+
+
+
+ General
+
+
+
+
+ Command Line
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Execute Before
+
+
+ Specifies the targets for the build customization to run before.
+
+
+
+
+
+
+
+
+
+
+ Execute After
+
+
+ Specifies the targets for the build customization to run after.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Additional Options
+
+
+ Additional Options
+
+
+
+
+
+
+
+
+
+
+
+
+
+ General
+
+
+
+
+ Command Line
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Execute Before
+
+
+ Specifies the targets for the build customization to run before.
+
+
+
+
+
+
+
+
+
+
+ Execute After
+
+
+ Specifies the targets for the build customization to run after.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Additional Options
+
+
+ Additional Options
+
+
+
+
+
+
+
+
+
+
+
+
+
+ General
+
+
+
+
+ Command Line
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Execute Before
+
+
+ Specifies the targets for the build customization to run before.
+
+
+
+
+
+
+
+
+
+
+ Execute After
+
+
+ Specifies the targets for the build customization to run after.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Additional Options
+
+
+ Additional Options
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/citra_qt/src/bootmanager.cpp b/src/citra_qt/src/bootmanager.cpp
new file mode 100644
index 000000000..8d7b5e446
--- /dev/null
+++ b/src/citra_qt/src/bootmanager.cpp
@@ -0,0 +1,246 @@
+#include
+#include
+
+#include "common.h"
+#include "bootmanager.hxx"
+
+#include "core.h"
+
+#include "version.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"
+
+EmuThread::EmuThread(GRenderWindow* render_window) : exec_cpu_step(false), cpu_running(true), render_window(render_window)
+{
+}
+
+void EmuThread::SetFilename(const char* filename)
+{
+ strcpy(this->filename, filename);
+}
+
+void EmuThread::run()
+{
+ //u32 tight_loop;
+
+ NOTICE_LOG(MASTER_LOG, APP_NAME " starting...\n");
+
+ if (Core::Init(/*render_window*/)) {
+ ERROR_LOG(MASTER_LOG, "core initialization failed, exiting...");
+ Core::Stop();
+ exit(1);
+ }
+
+ // Load a game or die...
+ Core::Start(); //autoboot for now
+ /*
+ if (E_OK == dvd::LoadBootableFile(filename)) {
+ if (common::g_config->enable_auto_boot()) {
+ core::Start();
+ } else {
+ LOG_ERROR(TMASTER, "Autoboot required in no-GUI mode... Exiting!\n");
+ }
+ } else {
+ LOG_ERROR(TMASTER, "Failed to load a bootable file... Exiting!\n");
+ exit(E_ERR);
+ }
+ */
+
+ /*
+ while(core::SYS_DIE != core::g_state)
+ {
+ if (core::SYS_RUNNING == core::g_state)
+ {
+ if(!cpu->is_on)
+ {
+ cpu->Start(); // Initialize and start CPU.
+ }
+ else
+ {
+ for(tight_loop = 0; tight_loop < 10000; ++tight_loop)
+ {
+ if (!cpu_running)
+ {
+ emit CPUStepped();
+ exec_cpu_step = false;
+ cpu->step = true;
+ while (!exec_cpu_step && !cpu_running && core::SYS_DIE != core::g_state);
+ }
+ cpu->execStep();
+ cpu->step = false;
+ }
+ }
+ }
+ else if (core::SYS_HALTED == core::g_state)
+ {
+ core::Stop();
+ }
+ }
+ */
+ Core::Stop();
+}
+
+void EmuThread::Stop()
+{
+ if (!isRunning())
+ {
+ INFO_LOG(MASTER_LOG, "EmuThread::Stop called while emu thread wasn't running, returning...");
+ return;
+ }
+
+ //core::g_state = core::SYS_DIE;
+
+ wait(1000);
+ if (isRunning())
+ {
+ WARN_LOG(MASTER_LOG, "EmuThread still running, terminating...");
+ terminate();
+ wait(1000);
+ if (isRunning())
+ WARN_LOG(MASTER_LOG, "EmuThread STILL running, something is wrong here...");
+ }
+ INFO_LOG(MASTER_LOG, "EmuThread stopped");
+}
+
+
+// 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
+{
+public:
+ GGLWidgetInternal(GRenderWindow* parent) : QGLWidget(parent)
+ {
+ setAutoBufferSwap(false);
+ doneCurrent();
+ parent_ = parent;
+ }
+
+ void paintEvent(QPaintEvent* ev)
+ {
+ // Apparently, Windows doesn't display anything if we don't call this here.
+ // TODO: Breaks linux though because we aren't calling doneCurrent() ... -.-
+// makeCurrent();
+ }
+ void resizeEvent(QResizeEvent* ev) {
+ parent_->set_client_area_width(size().width());
+ parent_->set_client_area_height(size().height());
+ }
+private:
+ GRenderWindow* parent_;
+};
+
+
+EmuThread& GRenderWindow::GetEmuThread()
+{
+ return emu_thread;
+}
+
+GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this)
+{
+ // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose
+
+ child = new GGLWidgetInternal(this);
+
+ QBoxLayout* layout = new QHBoxLayout(this);
+ resize(640, 480); // TODO: Load size from config instead
+ layout->addWidget(child);
+ layout->setMargin(0);
+ setLayout(layout);
+
+ BackupGeometry();
+}
+
+GRenderWindow::~GRenderWindow()
+{
+ emu_thread.Stop();
+}
+
+void GRenderWindow::SwapBuffers()
+{
+ child->makeCurrent(); // TODO: Not necessary?
+ child->swapBuffers();
+}
+
+void GRenderWindow::closeEvent(QCloseEvent* event)
+{
+ emu_thread.Stop();
+ QWidget::closeEvent(event);
+}
+
+void GRenderWindow::MakeCurrent()
+{
+ child->makeCurrent();
+}
+
+void GRenderWindow::DoneCurrent()
+{
+ child->doneCurrent();
+}
+
+void GRenderWindow::PollEvents() {
+ // TODO(ShizZy): Does this belong here? This is a reasonable place to update the window title
+ // from the main thread, but this should probably be in an event handler...
+ /*
+ static char title[128];
+ sprintf(title, "%s (FPS: %02.02f)", window_title_.c_str(),
+ video_core::g_renderer->current_fps());
+ setWindowTitle(title);
+ */
+}
+
+void GRenderWindow::BackupGeometry()
+{
+ geometry = ((QGLWidget*)this)->saveGeometry();
+}
+
+void GRenderWindow::RestoreGeometry()
+{
+ // We don't want to back up the geometry here (obviously)
+ QWidget::restoreGeometry(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()
+{
+ // If we are a top-level widget, store the current geometry
+ // otherwise, store the last backup
+ if (parent() == NULL)
+ return ((QGLWidget*)this)->saveGeometry();
+ else
+ return geometry;
+}
+
+void GRenderWindow::keyPressEvent(QKeyEvent* event)
+{
+ /*
+ bool key_processed = false;
+ for (unsigned int channel = 0; channel < 4 && controller_interface(); ++channel)
+ if (controller_interface()->SetControllerStatus(channel, event->key(), input_common::GCController::PRESSED))
+ key_processed = true;
+
+ if (!key_processed)
+ QWidget::keyPressEvent(event);
+ */
+}
+
+void GRenderWindow::keyReleaseEvent(QKeyEvent* event)
+{
+ /*
+ bool key_processed = false;
+ for (unsigned int channel = 0; channel < 4 && controller_interface(); ++channel)
+ if (controller_interface()->SetControllerStatus(channel, event->key(), input_common::GCController::RELEASED))
+ key_processed = true;
+
+ if (!key_processed)
+ QWidget::keyPressEvent(event);
+ */
+}
\ No newline at end of file
diff --git a/src/citra_qt/src/bootmanager.hxx b/src/citra_qt/src/bootmanager.hxx
new file mode 100644
index 000000000..943945961
--- /dev/null
+++ b/src/citra_qt/src/bootmanager.hxx
@@ -0,0 +1,104 @@
+#include
+#include
+#include "common.h"
+#include "emu_window.h"
+
+class GRenderWindow;
+class QKeyEvent;
+
+class EmuThread : public QThread
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Set image filename
+ *
+ * @param filename
+ * @warning Only call when not running!
+ */
+ void SetFilename(const char* filename);
+
+ /**
+ * Start emulation (on new thread)
+ *
+ * @warning Only call when not running!
+ */
+ void run();
+
+ /**
+ * Allow the CPU to process a single instruction (if cpu is not running)
+ *
+ * @note This function is thread-safe
+ */
+ void ExecStep() { exec_cpu_step = true; }
+
+ /**
+ * Allow the CPU to continue processing instructions without interruption
+ *
+ * @note This function is thread-safe
+ */
+ void SetCpuRunning(bool running) { cpu_running = running; }
+
+public slots:
+ /**
+ * Stop emulation and wait for the thread to finish.
+ *
+ * @details: This function will wait a second for the thread to finish; if it hasn't finished until then, we'll terminate() it and wait another second, hoping that it will be terminated by then.
+ * @note: This function is thread-safe.
+ */
+ void Stop();
+
+private:
+ friend class GRenderWindow;
+
+ EmuThread(GRenderWindow* render_window);
+
+ char filename[MAX_PATH];
+
+ bool exec_cpu_step;
+ bool cpu_running;
+
+ GRenderWindow* render_window;
+
+signals:
+ /**
+ * Emitted when CPU when we've finished processing a single Gekko instruction
+ *
+ * @warning This will only be emitted when the CPU is not running (SetCpuRunning(false))
+ * @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 CPUStepped();
+};
+
+class GRenderWindow : public QWidget, public EmuWindow
+{
+public:
+ GRenderWindow(QWidget* parent = NULL);
+ ~GRenderWindow();
+
+ void closeEvent(QCloseEvent*);
+
+ // EmuWindow implementation
+ void SwapBuffers();
+ void MakeCurrent();
+ void DoneCurrent();
+ void PollEvents();
+
+ void BackupGeometry();
+ void RestoreGeometry();
+ void restoreGeometry(const QByteArray& geometry); // overridden
+ QByteArray saveGeometry(); // overridden
+
+ EmuThread& GetEmuThread();
+
+ void keyPressEvent(QKeyEvent* event);
+ void keyReleaseEvent(QKeyEvent* event);
+
+private:
+ QGLWidget* child;
+
+ EmuThread emu_thread;
+
+ QByteArray geometry;
+};
diff --git a/src/citra_qt/src/callstack.cpp b/src/citra_qt/src/callstack.cpp
new file mode 100644
index 000000000..2d62cb0d0
--- /dev/null
+++ b/src/citra_qt/src/callstack.cpp
@@ -0,0 +1,36 @@
+#include
+#include "callstack.hxx"
+
+//#include "debugger/debugger.h"
+
+GCallstackView::GCallstackView(QWidget* parent): QDockWidget(parent)
+{
+ ui.setupUi(this);
+
+ callstack_model = new QStandardItemModel(this);
+ callstack_model->setColumnCount(3);
+ callstack_model->setHeaderData(0, Qt::Horizontal, "Depth");
+ callstack_model->setHeaderData(1, Qt::Horizontal, "Address");
+ callstack_model->setHeaderData(2, Qt::Horizontal, "Function Name");
+ ui.treeView->setModel(callstack_model);
+
+ // TODO: Make single clicking a callstack entry jump to the corresponding disassembly position
+}
+
+void GCallstackView::OnCPUStepped()
+{
+ /*
+ Debugger::Callstack callstack;
+ Debugger::GetCallstack(callstack);
+ callstack_model->setRowCount(callstack.size());
+
+ for (int i = 0; i < callstack.size(); ++i)
+ for (Debugger::CallstackIterator it = callstack.begin(); it != callstack.end(); ++it)
+ {
+ Debugger::CallstackEntry entry = callstack[i];
+ callstack_model->setItem(i, 0, new QStandardItem(QString("%1").arg(i+1)));
+ callstack_model->setItem(i, 1, new QStandardItem(QString("0x%1").arg(entry.addr, 8, 16, QLatin1Char('0'))));
+ callstack_model->setItem(i, 2, new QStandardItem(QString::fromStdString(entry.name)));
+ }
+ */
+}
\ No newline at end of file
diff --git a/src/citra_qt/src/callstack.hxx b/src/citra_qt/src/callstack.hxx
new file mode 100644
index 000000000..60b24f236
--- /dev/null
+++ b/src/citra_qt/src/callstack.hxx
@@ -0,0 +1,20 @@
+#include
+#include "ui_callstack.h"
+#include "platform.h"
+
+class QStandardItemModel;
+
+class GCallstackView : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ GCallstackView(QWidget* parent = 0);
+
+public slots:
+ void OnCPUStepped();
+
+private:
+ Ui::CallStack ui;
+ QStandardItemModel* callstack_model;
+};
diff --git a/src/citra_qt/src/callstack.ui b/src/citra_qt/src/callstack.ui
new file mode 100644
index 000000000..b3c4db632
--- /dev/null
+++ b/src/citra_qt/src/callstack.ui
@@ -0,0 +1,36 @@
+
+
+ CallStack
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Call stack
+
+
+
+ -
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
diff --git a/src/citra_qt/src/config/controller_config.cpp b/src/citra_qt/src/config/controller_config.cpp
new file mode 100644
index 000000000..52dfb627c
--- /dev/null
+++ b/src/citra_qt/src/config/controller_config.cpp
@@ -0,0 +1,91 @@
+#include
+
+#include "controller_config.hxx"
+#include "controller_config_util.hxx"
+
+/* TODO(bunnei): ImplementMe
+
+using common::Config;
+
+GControllerConfig::GControllerConfig(common::Config::ControllerPort* initial_config, QWidget* parent) : QWidget(parent)
+{
+ ui.setupUi(this);
+ ((QGridLayout*)ui.mainStickTab->layout())->addWidget(new GStickConfig(Config::ANALOG_LEFT, Config::ANALOG_RIGHT, Config::ANALOG_UP, Config::ANALOG_DOWN, this, this), 1, 1);
+ ((QGridLayout*)ui.cStickTab->layout())->addWidget(new GStickConfig(Config::C_LEFT, Config::C_RIGHT, Config::C_UP, Config::C_DOWN, this, this), 1, 1);
+ ((QGridLayout*)ui.dPadTab->layout())->addWidget(new GStickConfig(Config::DPAD_LEFT, Config::DPAD_RIGHT, Config::DPAD_UP, Config::DPAD_DOWN, this, this), 1, 1);
+
+ // TODO: Arrange these more compactly?
+ QVBoxLayout* layout = (QVBoxLayout*)ui.buttonsTab->layout();
+ layout->addWidget(new GButtonConfigGroup("A Button", Config::BUTTON_A, this, ui.buttonsTab));
+ layout->addWidget(new GButtonConfigGroup("B Button", Config::BUTTON_B, this, ui.buttonsTab));
+ layout->addWidget(new GButtonConfigGroup("X Button", Config::BUTTON_X, this, ui.buttonsTab));
+ layout->addWidget(new GButtonConfigGroup("Y Button", Config::BUTTON_Y, this, ui.buttonsTab));
+ layout->addWidget(new GButtonConfigGroup("Z Button", Config::BUTTON_Z, this, ui.buttonsTab));
+ layout->addWidget(new GButtonConfigGroup("L Trigger", Config::TRIGGER_L, this, ui.buttonsTab));
+ layout->addWidget(new GButtonConfigGroup("R Trigger", Config::TRIGGER_R, this, ui.buttonsTab));
+ layout->addWidget(new GButtonConfigGroup("Start Button", Config::BUTTON_START, this, ui.buttonsTab));
+
+ memcpy(config, initial_config, sizeof(config));
+
+ emit ActivePortChanged(config[0]);
+}
+
+void GControllerConfig::OnKeyConfigChanged(common::Config::Control id, int key, const QString& name)
+{
+ if (InputSourceJoypad())
+ {
+ config[GetActiveController()].pads.key_code[id] = key;
+ }
+ else
+ {
+ config[GetActiveController()].keys.key_code[id] = key;
+ }
+ emit ActivePortChanged(config[GetActiveController()]);
+}
+
+int GControllerConfig::GetActiveController()
+{
+ return ui.activeControllerCB->currentIndex();
+}
+
+bool GControllerConfig::InputSourceJoypad()
+{
+ return ui.inputSourceCB->currentIndex() == 1;
+}
+
+GControllerConfigDialog::GControllerConfigDialog(common::Config::ControllerPort* controller_ports, QWidget* parent) : QDialog(parent), config_ptr(controller_ports)
+{
+ setWindowTitle(tr("Input configuration"));
+
+ QVBoxLayout* layout = new QVBoxLayout(this);
+ config_widget = new GControllerConfig(controller_ports, this);
+ layout->addWidget(config_widget);
+
+ QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ layout->addWidget(buttons);
+
+ connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
+
+ connect(this, SIGNAL(accepted()), this, SLOT(EnableChanges()));
+
+ layout->setSizeConstraint(QLayout::SetFixedSize);
+ setLayout(layout);
+ setModal(true);
+ show();
+}
+
+void GControllerConfigDialog::EnableChanges()
+{
+ for (unsigned int i = 0; i < 4; ++i)
+ {
+ memcpy(&config_ptr[i], &config_widget->GetControllerConfig(i), sizeof(common::Config::ControllerPort));
+
+ if (common::g_config) {
+ // Apply changes if running a game
+ memcpy(&common::g_config->controller_ports(i), &config_widget->GetControllerConfig(i), sizeof(common::Config::ControllerPort));
+ }
+ }
+}
+
+*/
\ No newline at end of file
diff --git a/src/citra_qt/src/config/controller_config.hxx b/src/citra_qt/src/config/controller_config.hxx
new file mode 100644
index 000000000..9ff86a110
--- /dev/null
+++ b/src/citra_qt/src/config/controller_config.hxx
@@ -0,0 +1,52 @@
+#ifndef _CONTROLLER_CONFIG_HXX_
+#define _CONTROLLER_CONFIG_HXX_
+
+#include
+
+#include "ui_controller_config.h"
+
+/* TODO(bunnei): ImplementMe
+
+#include "config.h"
+
+class GControllerConfig : public QWidget
+{
+ Q_OBJECT
+
+public:
+ GControllerConfig(common::Config::ControllerPort* initial_config, QWidget* parent = NULL);
+
+ const common::Config::ControllerPort& GetControllerConfig(int index) const { return config[index]; }
+
+signals:
+ void ActivePortChanged(const common::Config::ControllerPort&);
+
+public slots:
+ void OnKeyConfigChanged(common::Config::Control id, int key, const QString& name);
+
+private:
+ int GetActiveController();
+ bool InputSourceJoypad();
+
+ Ui::ControllerConfig ui;
+ common::Config::ControllerPort config[4];
+};
+
+class GControllerConfigDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ GControllerConfigDialog(common::Config::ControllerPort* controller_ports, QWidget* parent = NULL);
+
+public slots:
+ void EnableChanges();
+
+private:
+ GControllerConfig* config_widget;
+ common::Config::ControllerPort* config_ptr;
+};
+
+*/
+
+#endif // _CONTROLLER_CONFIG_HXX_
diff --git a/src/citra_qt/src/config/controller_config.ui b/src/citra_qt/src/config/controller_config.ui
new file mode 100644
index 000000000..9f650047b
--- /dev/null
+++ b/src/citra_qt/src/config/controller_config.ui
@@ -0,0 +1,308 @@
+
+
+ ControllerConfig
+
+
+
+ 0
+ 0
+ 503
+ 293
+
+
+
+
+ 0
+ 0
+
+
+
+ Controller Configuration
+
+
+
+ QLayout::SetFixedSize
+
+ -
+
+
-
+
+
-
+
+ Controller 1
+
+
+ -
+
+ Controller 2
+
+
+ -
+
+ Controller 3
+
+
+ -
+
+ Controller 4
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Enabled
+
+
+
+ -
+
+
-
+
+ Keyboard
+
+
+ -
+
+ Joypad
+
+
+
+
+ -
+
+
+ Active Controller:
+
+
+
+ -
+
+
+ Input Source:
+
+
+
+
+
+ -
+
+
+ 0
+
+
+
+ Main Stick
+
+
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ C-Stick
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 0
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ D-Pad
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ Buttons
+
+
+
+
+
+
+
+
+
+
+ ControlsChanged()
+ MainStickCleared()
+ CStickCleared()
+ DPadCleared()
+ ButtonsCleared()
+ OnControlsChanged()
+ OnMainStickCleared()
+ OnCStickCleared()
+ OnDPadCleared()
+ OnButtonsCleared()
+
+
diff --git a/src/citra_qt/src/config/controller_config_util.cpp b/src/citra_qt/src/config/controller_config_util.cpp
new file mode 100644
index 000000000..c5426570b
--- /dev/null
+++ b/src/citra_qt/src/config/controller_config_util.cpp
@@ -0,0 +1,121 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "controller_config_util.hxx"
+
+/* TODO(bunnei): ImplementMe
+GStickConfig::GStickConfig(common::Config::Control leftid, common::Config::Control rightid, common::Config::Control upid, common::Config::Control downid, QObject* change_receiver, QWidget* parent) : QWidget(parent)
+{
+ left = new GKeyConfigButton(leftid, style()->standardIcon(QStyle::SP_ArrowLeft), QString(), change_receiver, this);
+ right = new GKeyConfigButton(rightid, style()->standardIcon(QStyle::SP_ArrowRight), QString(), change_receiver, this);
+ up = new GKeyConfigButton(upid, style()->standardIcon(QStyle::SP_ArrowUp), QString(), change_receiver, this);
+ down = new GKeyConfigButton(downid, style()->standardIcon(QStyle::SP_ArrowDown), QString(), change_receiver, this);
+ clear = new QPushButton(tr("Clear"), this);
+
+ QGridLayout* layout = new QGridLayout(this);
+ layout->addWidget(left, 1, 0);
+ layout->addWidget(right, 1, 2);
+ layout->addWidget(up, 0, 1);
+ layout->addWidget(down, 2, 1);
+ layout->addWidget(clear, 1, 1);
+
+ setLayout(layout);
+}
+
+GKeyConfigButton::GKeyConfigButton(common::Config::Control id, const QIcon& icon, const QString& text, QObject* change_receiver, QWidget* parent) : QPushButton(icon, text, parent), id(id), inputGrabbed(false)
+{
+ connect(this, SIGNAL(clicked()), this, SLOT(OnClicked()));
+ connect(this, SIGNAL(KeyAssigned(common::Config::Control, int, const QString&)), change_receiver, SLOT(OnKeyConfigChanged(common::Config::Control, int, const QString&)));
+ connect(change_receiver, SIGNAL(ActivePortChanged(const common::Config::ControllerPort&)), this, SLOT(OnActivePortChanged(const common::Config::ControllerPort&)));
+}
+
+GKeyConfigButton::GKeyConfigButton(common::Config::Control id, const QString& text, QObject* change_receiver, QWidget* parent) : QPushButton(text, parent), id(id), inputGrabbed(false)
+{
+ connect(this, SIGNAL(clicked()), this, SLOT(OnClicked()));
+ connect(this, SIGNAL(KeyAssigned(common::Config::Control, int, const QString&)), change_receiver, SLOT(OnKeyConfigChanged(common::Config::Control, int, const QString&)));
+ connect(change_receiver, SIGNAL(ActivePortChanged(const common::Config::ControllerPort&)), this, SLOT(OnActivePortChanged(const common::Config::ControllerPort&)));
+}
+
+void GKeyConfigButton::OnActivePortChanged(const common::Config::ControllerPort& config)
+{
+ // TODO: Doesn't use joypad struct if that's the input source...
+ QString text = QKeySequence(config.keys.key_code[id]).toString(); // has a nicer format
+ if (config.keys.key_code[id] == Qt::Key_Shift) text = tr("Shift");
+ else if (config.keys.key_code[id] == Qt::Key_Control) text = tr("Control");
+ else if (config.keys.key_code[id] == Qt::Key_Alt) text = tr("Alt");
+ else if (config.keys.key_code[id] == Qt::Key_Meta) text = tr("Meta");
+ setText(text);
+}
+
+void GKeyConfigButton::OnClicked()
+{
+ grabKeyboard();
+ grabMouse();
+ inputGrabbed = true;
+
+ old_text = text();
+ setText(tr("Input..."));
+}
+
+void GKeyConfigButton::keyPressEvent(QKeyEvent* event)
+{
+ if (inputGrabbed)
+ {
+ releaseKeyboard();
+ releaseMouse();
+ setText(QString());
+
+ // TODO: Doesn't capture "return" key
+ // TODO: This doesn't quite work well, yet... find a better way
+ QString text = QKeySequence(event->key()).toString(); // has a nicer format than event->text()
+ int key = event->key();
+ if (event->modifiers() == Qt::ShiftModifier) { text = tr("Shift"); key = Qt::Key_Shift; }
+ else if (event->modifiers() == Qt::ControlModifier) { text = tr("Ctrl"); key = Qt::Key_Control; }
+ else if (event->modifiers() == Qt::AltModifier) { text = tr("Alt"); key = Qt::Key_Alt; }
+ else if (event->modifiers() == Qt::MetaModifier) { text = tr("Meta"); key = Qt::Key_Meta; }
+
+ setText(old_text);
+ emit KeyAssigned(id, key, text);
+
+ inputGrabbed = false;
+
+ // TODO: Keys like "return" cause another keyPressEvent to be generated after this one...
+ }
+
+ QPushButton::keyPressEvent(event); // TODO: Necessary?
+}
+
+void GKeyConfigButton::mousePressEvent(QMouseEvent* event)
+{
+ // Abort key assignment
+ if (inputGrabbed)
+ {
+ releaseKeyboard();
+ releaseMouse();
+ setText(old_text);
+ inputGrabbed = false;
+ }
+
+ QAbstractButton::mousePressEvent(event);
+}
+
+GButtonConfigGroup::GButtonConfigGroup(const QString& name, common::Config::Control id, QObject* change_receiver, QWidget* parent) : QWidget(parent), id(id)
+{
+ QHBoxLayout* layout = new QHBoxLayout(this);
+
+ QPushButton* clear_button = new QPushButton(tr("Clear"));
+
+ layout->addWidget(new QLabel(name, this));
+ layout->addWidget(config_button = new GKeyConfigButton(id, QString(), change_receiver, this));
+ layout->addWidget(clear_button);
+
+ // TODO: connect config_button, clear_button
+
+ setLayout(layout);
+}
+
+*/
\ No newline at end of file
diff --git a/src/citra_qt/src/config/controller_config_util.hxx b/src/citra_qt/src/config/controller_config_util.hxx
new file mode 100644
index 000000000..af38f126c
--- /dev/null
+++ b/src/citra_qt/src/config/controller_config_util.hxx
@@ -0,0 +1,78 @@
+#ifndef _CONTROLLER_CONFIG_UTIL_HXX_
+#define _CONTROLLER_CONFIG_UTIL_HXX_
+
+#include
+#include
+
+/* TODO(bunnei): ImplementMe
+
+#include "config.h"
+
+class GStickConfig : public QWidget
+{
+ Q_OBJECT
+
+public:
+ // change_receiver needs to have a OnKeyConfigChanged(common::Config::Control, int, const QString&) slot!
+ GStickConfig(common::Config::Control leftid, common::Config::Control rightid, common::Config::Control upid, common::Config::Control downid, QObject* change_receiver, QWidget* parent = NULL);
+
+signals:
+ void LeftChanged();
+ void RightChanged();
+ void UpChanged();
+ void DownChanged();
+
+private:
+ QPushButton* left;
+ QPushButton* right;
+ QPushButton* up;
+ QPushButton* down;
+
+ QPushButton* clear;
+};
+
+class GKeyConfigButton : public QPushButton
+{
+ Q_OBJECT
+
+public:
+ // TODO: change_receiver also needs to have an ActivePortChanged(const common::Config::ControllerPort&) signal
+ // change_receiver needs to have a OnKeyConfigChanged(common::Config::Control, int, const QString&) slot!
+ GKeyConfigButton(common::Config::Control id, const QIcon& icon, const QString& text, QObject* change_receiver, QWidget* parent);
+ GKeyConfigButton(common::Config::Control id, const QString& text, QObject* change_receiver, QWidget* parent);
+
+signals:
+ void KeyAssigned(common::Config::Control id, int key, const QString& text);
+
+private slots:
+ void OnActivePortChanged(const common::Config::ControllerPort& config);
+
+ void OnClicked();
+
+ void keyPressEvent(QKeyEvent* event); // TODO: bGrabbed?
+ void mousePressEvent(QMouseEvent* event);
+
+private:
+ common::Config::Control id;
+ bool inputGrabbed;
+
+ QString old_text;
+};
+
+class GButtonConfigGroup : public QWidget
+{
+ Q_OBJECT
+
+public:
+ // change_receiver needs to have a OnKeyConfigChanged(common::Config::Control, int, const QString&) slot!
+ GButtonConfigGroup(const QString& name, common::Config::Control id, QObject* change_receiver, QWidget* parent = NULL);
+
+private:
+ GKeyConfigButton* config_button;
+
+ common::Config::Control id;
+};
+
+*/
+
+#endif // _CONTROLLER_CONFIG_HXX_
diff --git a/src/citra_qt/src/config/ui_controller_config.h b/src/citra_qt/src/config/ui_controller_config.h
new file mode 100644
index 000000000..f84364a77
--- /dev/null
+++ b/src/citra_qt/src/config/ui_controller_config.h
@@ -0,0 +1,222 @@
+/********************************************************************************
+** Form generated from reading UI file 'controller_config.ui'
+**
+** Created by: Qt User Interface Compiler version 4.8.5
+**
+** WARNING! All changes made in this file will be lost when recompiling UI file!
+********************************************************************************/
+
+#ifndef UI_CONTROLLER_CONFIG_H
+#define UI_CONTROLLER_CONFIG_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+class Ui_ControllerConfig
+{
+public:
+ QVBoxLayout *verticalLayout;
+ QGridLayout *gridLayout;
+ QComboBox *activeControllerCB;
+ QSpacerItem *horizontalSpacer;
+ QCheckBox *checkBox;
+ QComboBox *inputSourceCB;
+ QLabel *label_2;
+ QLabel *label;
+ QTabWidget *tabWidget;
+ QWidget *mainStickTab;
+ QGridLayout *gridLayout_3;
+ QSpacerItem *verticalSpacer_2;
+ QSpacerItem *verticalSpacer_3;
+ QSpacerItem *horizontalSpacer_4;
+ QSpacerItem *horizontalSpacer_3;
+ QWidget *cStickTab;
+ QGridLayout *gridLayout_4;
+ QSpacerItem *horizontalSpacer_6;
+ QSpacerItem *verticalSpacer_5;
+ QSpacerItem *verticalSpacer_4;
+ QSpacerItem *horizontalSpacer_5;
+ QWidget *dPadTab;
+ QGridLayout *gridLayout_5;
+ QSpacerItem *horizontalSpacer_7;
+ QSpacerItem *verticalSpacer_7;
+ QSpacerItem *verticalSpacer_6;
+ QSpacerItem *horizontalSpacer_8;
+ QWidget *buttonsTab;
+ QVBoxLayout *verticalLayout_2;
+
+ void setupUi(QWidget *ControllerConfig)
+ {
+ if (ControllerConfig->objectName().isEmpty())
+ ControllerConfig->setObjectName(QString::fromUtf8("ControllerConfig"));
+ ControllerConfig->resize(503, 293);
+ QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ sizePolicy.setHeightForWidth(ControllerConfig->sizePolicy().hasHeightForWidth());
+ ControllerConfig->setSizePolicy(sizePolicy);
+ verticalLayout = new QVBoxLayout(ControllerConfig);
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
+ verticalLayout->setSizeConstraint(QLayout::SetFixedSize);
+ gridLayout = new QGridLayout();
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ activeControllerCB = new QComboBox(ControllerConfig);
+ activeControllerCB->setObjectName(QString::fromUtf8("activeControllerCB"));
+
+ gridLayout->addWidget(activeControllerCB, 1, 1, 1, 1);
+
+ horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ gridLayout->addItem(horizontalSpacer, 0, 2, 1, 1);
+
+ checkBox = new QCheckBox(ControllerConfig);
+ checkBox->setObjectName(QString::fromUtf8("checkBox"));
+
+ gridLayout->addWidget(checkBox, 1, 2, 1, 1);
+
+ inputSourceCB = new QComboBox(ControllerConfig);
+ inputSourceCB->setObjectName(QString::fromUtf8("inputSourceCB"));
+
+ gridLayout->addWidget(inputSourceCB, 0, 1, 1, 1);
+
+ label_2 = new QLabel(ControllerConfig);
+ label_2->setObjectName(QString::fromUtf8("label_2"));
+
+ gridLayout->addWidget(label_2, 1, 0, 1, 1);
+
+ label = new QLabel(ControllerConfig);
+ label->setObjectName(QString::fromUtf8("label"));
+
+ gridLayout->addWidget(label, 0, 0, 1, 1);
+
+
+ verticalLayout->addLayout(gridLayout);
+
+ tabWidget = new QTabWidget(ControllerConfig);
+ tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
+ mainStickTab = new QWidget();
+ mainStickTab->setObjectName(QString::fromUtf8("mainStickTab"));
+ gridLayout_3 = new QGridLayout(mainStickTab);
+ gridLayout_3->setObjectName(QString::fromUtf8("gridLayout_3"));
+ verticalSpacer_2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ gridLayout_3->addItem(verticalSpacer_2, 2, 2, 1, 1);
+
+ verticalSpacer_3 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ gridLayout_3->addItem(verticalSpacer_3, 0, 2, 1, 1);
+
+ horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ gridLayout_3->addItem(horizontalSpacer_4, 1, 0, 1, 1);
+
+ horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ gridLayout_3->addItem(horizontalSpacer_3, 1, 4, 1, 1);
+
+ tabWidget->addTab(mainStickTab, QString());
+ cStickTab = new QWidget();
+ cStickTab->setObjectName(QString::fromUtf8("cStickTab"));
+ gridLayout_4 = new QGridLayout(cStickTab);
+ gridLayout_4->setObjectName(QString::fromUtf8("gridLayout_4"));
+ horizontalSpacer_6 = new QSpacerItem(40, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ gridLayout_4->addItem(horizontalSpacer_6, 1, 0, 1, 1);
+
+ verticalSpacer_5 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ gridLayout_4->addItem(verticalSpacer_5, 0, 1, 1, 1);
+
+ verticalSpacer_4 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ gridLayout_4->addItem(verticalSpacer_4, 2, 1, 1, 1);
+
+ horizontalSpacer_5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ gridLayout_4->addItem(horizontalSpacer_5, 1, 2, 1, 1);
+
+ tabWidget->addTab(cStickTab, QString());
+ dPadTab = new QWidget();
+ dPadTab->setObjectName(QString::fromUtf8("dPadTab"));
+ gridLayout_5 = new QGridLayout(dPadTab);
+ gridLayout_5->setObjectName(QString::fromUtf8("gridLayout_5"));
+ horizontalSpacer_7 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ gridLayout_5->addItem(horizontalSpacer_7, 1, 2, 1, 1);
+
+ verticalSpacer_7 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ gridLayout_5->addItem(verticalSpacer_7, 0, 1, 1, 1);
+
+ verticalSpacer_6 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ gridLayout_5->addItem(verticalSpacer_6, 2, 1, 1, 1);
+
+ horizontalSpacer_8 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ gridLayout_5->addItem(horizontalSpacer_8, 1, 0, 1, 1);
+
+ tabWidget->addTab(dPadTab, QString());
+ buttonsTab = new QWidget();
+ buttonsTab->setObjectName(QString::fromUtf8("buttonsTab"));
+ verticalLayout_2 = new QVBoxLayout(buttonsTab);
+ verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
+ tabWidget->addTab(buttonsTab, QString());
+
+ verticalLayout->addWidget(tabWidget);
+
+
+ retranslateUi(ControllerConfig);
+
+ tabWidget->setCurrentIndex(0);
+
+
+ QMetaObject::connectSlotsByName(ControllerConfig);
+ } // setupUi
+
+ void retranslateUi(QWidget *ControllerConfig)
+ {
+ ControllerConfig->setWindowTitle(QApplication::translate("ControllerConfig", "Controller Configuration", 0, QApplication::UnicodeUTF8));
+ activeControllerCB->clear();
+ activeControllerCB->insertItems(0, QStringList()
+ << QApplication::translate("ControllerConfig", "Controller 1", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("ControllerConfig", "Controller 2", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("ControllerConfig", "Controller 3", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("ControllerConfig", "Controller 4", 0, QApplication::UnicodeUTF8)
+ );
+ checkBox->setText(QApplication::translate("ControllerConfig", "Enabled", 0, QApplication::UnicodeUTF8));
+ inputSourceCB->clear();
+ inputSourceCB->insertItems(0, QStringList()
+ << QApplication::translate("ControllerConfig", "Keyboard", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("ControllerConfig", "Joypad", 0, QApplication::UnicodeUTF8)
+ );
+ label_2->setText(QApplication::translate("ControllerConfig", "Active Controller:", 0, QApplication::UnicodeUTF8));
+ label->setText(QApplication::translate("ControllerConfig", "Input Source:", 0, QApplication::UnicodeUTF8));
+ tabWidget->setTabText(tabWidget->indexOf(mainStickTab), QApplication::translate("ControllerConfig", "Main Stick", 0, QApplication::UnicodeUTF8));
+ tabWidget->setTabText(tabWidget->indexOf(cStickTab), QApplication::translate("ControllerConfig", "C-Stick", 0, QApplication::UnicodeUTF8));
+ tabWidget->setTabText(tabWidget->indexOf(dPadTab), QApplication::translate("ControllerConfig", "D-Pad", 0, QApplication::UnicodeUTF8));
+ tabWidget->setTabText(tabWidget->indexOf(buttonsTab), QApplication::translate("ControllerConfig", "Buttons", 0, QApplication::UnicodeUTF8));
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class ControllerConfig: public Ui_ControllerConfig {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_CONTROLLER_CONFIG_H
diff --git a/src/citra_qt/src/cpu_regs.cpp b/src/citra_qt/src/cpu_regs.cpp
new file mode 100644
index 000000000..5d240b4bc
--- /dev/null
+++ b/src/citra_qt/src/cpu_regs.cpp
@@ -0,0 +1,64 @@
+#include "cpu_regs.hxx"
+
+//#include "powerpc/cpu_core_regs.h"
+
+GARM11RegsView::GARM11RegsView(QWidget* parent) : QDockWidget(parent)
+{
+ cpu_regs_ui.setupUi(this);
+
+ tree = cpu_regs_ui.treeWidget;
+ tree->addTopLevelItem(registers = new QTreeWidgetItem(QStringList("Registers")));
+ tree->addTopLevelItem(CSPR = new QTreeWidgetItem(QStringList("CSPR")));
+
+ //const Qt::ItemFlags child_flags = Qt::ItemIsEditable | Qt::ItemIsEnabled;
+ //registers->setFlags(child_flags);
+ //CSPR->setFlags(child_flags);
+
+ for (int i = 0; i < 16; ++i)
+ {
+ QTreeWidgetItem* child = new QTreeWidgetItem(QStringList(QString("R[%1]").arg(i, 2, 10, QLatin1Char('0'))));
+ //child->setFlags(child_flags);
+ registers->addChild(child);
+ }
+
+ CSPR->addChild(new QTreeWidgetItem(QStringList("M")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("T")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("F")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("I")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("A")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("E")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("IT")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("GE")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("DNM")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("J")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("Q")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("V")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("C")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("Z")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("N")));
+}
+
+void GARM11RegsView::OnCPUStepped()
+{
+ //TODO (Vail) replace values
+ int value = 0;
+ for (int i = 0; i < 16; ++i)
+ registers->child(i)->setText(1, QString("0x%1").arg(i, 8, 16, QLatin1Char('0')));
+
+ CSPR->child(0)->setText(1, QString("%1").arg(value));
+ CSPR->child(1)->setText(1, QString("%1").arg(value));
+ CSPR->child(2)->setText(1, QString("%1").arg(value));
+ CSPR->child(3)->setText(1, QString("%1").arg(value));
+ CSPR->child(4)->setText(1, QString("%1").arg(value));
+ CSPR->child(5)->setText(1, QString("%1").arg(value));
+ CSPR->child(6)->setText(1, QString("%1").arg(value));
+ CSPR->child(7)->setText(1, QString("%1").arg(value));
+ CSPR->child(8)->setText(1, QString("%1").arg(value));
+ CSPR->child(9)->setText(1, QString("%1").arg(value));
+ CSPR->child(10)->setText(1, QString("%1").arg(value));
+ CSPR->child(11)->setText(1, QString("%1").arg(value));
+ CSPR->child(12)->setText(1, QString("%1").arg(value));
+ CSPR->child(13)->setText(1, QString("%1").arg(value));
+ CSPR->child(14)->setText(1, QString("%1").arg(value));
+ CSPR->child(15)->setText(1, QString("%1").arg(value));
+}
diff --git a/src/citra_qt/src/cpu_regs.hxx b/src/citra_qt/src/cpu_regs.hxx
new file mode 100644
index 000000000..27c194bde
--- /dev/null
+++ b/src/citra_qt/src/cpu_regs.hxx
@@ -0,0 +1,27 @@
+#include "ui_cpu_regs.h"
+
+#include
+#include
+
+//#include "ui_gekko_regs.h"
+
+class QTreeWidget;
+
+class GARM11RegsView : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ GARM11RegsView(QWidget* parent = NULL);
+
+public slots:
+ void OnCPUStepped();
+
+private:
+ Ui::ARMRegisters cpu_regs_ui;
+
+ QTreeWidget* tree;
+
+ QTreeWidgetItem* registers;
+ QTreeWidgetItem* CSPR;
+};
diff --git a/src/citra_qt/src/cpu_regs.ui b/src/citra_qt/src/cpu_regs.ui
new file mode 100644
index 000000000..6537c9cd6
--- /dev/null
+++ b/src/citra_qt/src/cpu_regs.ui
@@ -0,0 +1,40 @@
+
+
+ ARMRegisters
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ ARM registers
+
+
+
+ -
+
+
+ true
+
+
+
+ Register
+
+
+
+
+ Value
+
+
+
+
+
+
+
+
+
+
diff --git a/src/citra_qt/src/disasm.cpp b/src/citra_qt/src/disasm.cpp
new file mode 100644
index 000000000..6e4087b23
--- /dev/null
+++ b/src/citra_qt/src/disasm.cpp
@@ -0,0 +1,144 @@
+#include
+#include "ui_disasm.h"
+#include "disasm.hxx"
+
+#include "bootmanager.hxx"
+#include "hotkeys.hxx"
+
+#include "common.h"
+#include "mem_map.h"
+
+#include "break_points.h"
+//#include "powerpc/cpu_core_regs.h"
+#include "arm/disassembler/arm_disasm.h"
+
+//#include "powerpc/interpreter/cpu_int.h"
+
+GDisAsmView::GDisAsmView(QWidget* parent, EmuThread& emu_thread) : QDockWidget(parent), base_addr(0), emu_thread(emu_thread)
+{
+ disasm_ui.setupUi(this);
+
+ breakpoints = new BreakPoints();
+
+ model = new QStandardItemModel(this);
+ model->setColumnCount(3);
+ disasm_ui.treeView->setModel(model);
+
+ RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut);
+ RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut);
+// RegisterHotkey("Disassembler", "Pause", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut);
+ RegisterHotkey("Disassembler", "Continue", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut);
+ RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), Qt::ApplicationShortcut);
+
+ connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), this, SLOT(OnSetBreakpoint()));
+ 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", "Step", this), SIGNAL(activated()), this, SLOT(OnStep()));
+ connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, SLOT(OnStepInto()));
+// connect(GetHotkey("Disassembler", "Pause", this), SIGNAL(activated()), this, SLOT(OnPause()));
+ connect(GetHotkey("Disassembler", "Continue", this), SIGNAL(activated()), this, SLOT(OnContinue()));
+ connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), this, SLOT(OnSetBreakpoint()));
+}
+
+void GDisAsmView::OnSetBreakpoint()
+{
+ if (SelectedRow() == -1)
+ return;
+
+ u32 address = base_addr + 4 * SelectedRow();
+ if (breakpoints->IsAddressBreakPoint(address))
+ {
+ breakpoints->Remove(address);
+ model->item(SelectedRow(), 0)->setBackground(QBrush());
+ model->item(SelectedRow(), 1)->setBackground(QBrush());
+ model->item(SelectedRow(), 2)->setBackground(QBrush());
+ }
+ else
+ {
+ breakpoints->Add(address);
+ model->item(SelectedRow(), 0)->setBackground(Qt::red);
+ model->item(SelectedRow(), 1)->setBackground(Qt::red);
+ model->item(SelectedRow(), 2)->setBackground(Qt::red);
+ }
+}
+
+void GDisAsmView::OnStep()
+{
+ emu_thread.SetCpuRunning(false);
+ emu_thread.ExecStep();
+}
+
+void GDisAsmView::OnPause()
+{
+ emu_thread.SetCpuRunning(false);
+}
+
+void GDisAsmView::OnContinue()
+{
+ emu_thread.SetCpuRunning(true);
+}
+
+void GDisAsmView::OnCPUStepped()
+{
+ /*
+ base_addr = ireg.PC - 52;
+ unsigned int curInstAddr = base_addr;
+ int counter = 0;
+ QModelIndex cur_instr_index;
+ model->setRowCount(100);
+ while(true)
+ {
+ u32 opcode = *(u32*)(&Mem_RAM[curInstAddr & RAM_MASK]);
+
+ char out1[64];
+ char out2[128];
+ u32 out3 = 0;
+ memset(out1, 0, sizeof(out1));
+ memset(out2, 0, sizeof(out2));
+
+ // NOTE: out3 (nextInstAddr) seems to be bugged, better don't use it...
+ DisassembleGekko(out1, out2, opcode, curInstAddr, &out3);
+ model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg((uint)curInstAddr, 8, 16, QLatin1Char('0'))));
+ model->setItem(counter, 1, new QStandardItem(QString(out1)));
+ model->setItem(counter, 2, new QStandardItem(QString(out2)));
+
+ if (ireg.PC == curInstAddr)
+ {
+ model->item(counter, 0)->setBackground(Qt::yellow);
+ model->item(counter, 1)->setBackground(Qt::yellow);
+ model->item(counter, 2)->setBackground(Qt::yellow);
+ cur_instr_index = model->index(counter, 0);
+ }
+ else if (Debugger::IsBreakpoint(curInstAddr))
+ {
+ model->item(counter, 0)->setBackground(Qt::red);
+ model->item(counter, 1)->setBackground(Qt::red);
+ model->item(counter, 2)->setBackground(Qt::red);
+ }
+ else
+ {
+ model->item(counter, 0)->setBackground(QBrush());
+ model->item(counter, 1)->setBackground(QBrush());
+ model->item(counter, 2)->setBackground(QBrush());
+ }
+ curInstAddr += 4;
+
+ ++counter;
+ if (counter >= 100) break;
+ }
+ disasm_ui.treeView->resizeColumnToContents(0);
+ disasm_ui.treeView->resizeColumnToContents(1);
+ disasm_ui.treeView->resizeColumnToContents(2);
+ disasm_ui.treeView->scrollTo(cur_instr_index); // QAbstractItemView::PositionAtCenter?
+ */
+}
+
+int GDisAsmView::SelectedRow()
+{
+ QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex();
+ if (!index.isValid())
+ return -1;
+
+ return model->itemFromIndex(disasm_ui.treeView->selectionModel()->currentIndex())->row();
+}
\ No newline at end of file
diff --git a/src/citra_qt/src/disasm.hxx b/src/citra_qt/src/disasm.hxx
new file mode 100644
index 000000000..648107114
--- /dev/null
+++ b/src/citra_qt/src/disasm.hxx
@@ -0,0 +1,38 @@
+#include
+#include "ui_disasm.h"
+
+#include "common.h"
+#include "break_points.h"
+
+class QAction;
+class QStandardItemModel;
+class EmuThread;
+
+class GDisAsmView : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ GDisAsmView(QWidget* parent, EmuThread& emu_thread);
+
+public slots:
+ void OnSetBreakpoint();
+ void OnStep();
+ void OnPause();
+ void OnContinue();
+
+ void OnCPUStepped();
+
+private:
+ // returns -1 if no row is selected
+ int SelectedRow();
+
+ Ui::DockWidget disasm_ui;
+ QStandardItemModel* model;
+
+ u32 base_addr;
+
+ BreakPoints* breakpoints;
+
+ EmuThread& emu_thread;
+};
diff --git a/src/citra_qt/src/disasm.ui b/src/citra_qt/src/disasm.ui
new file mode 100644
index 000000000..fb3845164
--- /dev/null
+++ b/src/citra_qt/src/disasm.ui
@@ -0,0 +1,78 @@
+
+
+ DockWidget
+
+
+
+ 0
+ 0
+ 430
+ 401
+
+
+
+ Disassembly
+
+
+
+ -
+
+
-
+
+
+ Step
+
+
+
+ -
+
+
+ Pause
+
+
+
+ -
+
+
+ Continue
+
+
+
+ -
+
+
+ Step Into
+
+
+
+ -
+
+
+ Set Breakpoint
+
+
+
+
+
+ -
+
+
+ true
+
+
+ 20
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
diff --git a/src/citra_qt/src/hotkeys.cpp b/src/citra_qt/src/hotkeys.cpp
new file mode 100644
index 000000000..1aa1e8b96
--- /dev/null
+++ b/src/citra_qt/src/hotkeys.cpp
@@ -0,0 +1,111 @@
+#include
+#include
+#include "hotkeys.hxx"
+#include