| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | #include <QtGui>
 | 
					
						
							|  |  |  | #include <QDesktopWidget>
 | 
					
						
							|  |  |  | #include <QFileDialog>
 | 
					
						
							|  |  |  | #include "qhexedit.h"
 | 
					
						
							|  |  |  | #include "main.hxx"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-10 20:50:10 -04:00
										 |  |  | #include "common/common.h"
 | 
					
						
							|  |  |  | #include "common/platform.h"
 | 
					
						
							| 
									
										
										
										
											2014-04-12 19:01:33 -04:00
										 |  |  | #include "common/log_manager.h"
 | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | #if EMU_PLATFORM == PLATFORM_LINUX
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "bootmanager.hxx"
 | 
					
						
							|  |  |  | #include "hotkeys.hxx"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //debugger
 | 
					
						
							| 
									
										
										
										
											2014-04-18 18:30:53 -04:00
										 |  |  | #include "debugger/disassembler.hxx"
 | 
					
						
							|  |  |  | #include "debugger/registers.hxx"
 | 
					
						
							|  |  |  | #include "debugger/callstack.hxx"
 | 
					
						
							|  |  |  | #include "debugger/ramview.hxx"
 | 
					
						
							| 
									
										
										
										
											2014-05-17 22:38:10 +02:00
										 |  |  | #include "debugger/graphics.hxx"
 | 
					
						
							| 
									
										
										
										
											2014-05-18 17:52:22 +02:00
										 |  |  | #include "debugger/graphics_cmdlists.hxx"
 | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-10 20:50:10 -04:00
										 |  |  | #include "core/system.h"
 | 
					
						
							|  |  |  | #include "core/core.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-16 18:03:13 -04:00
										 |  |  | #include "core/loader/loader.h"
 | 
					
						
							| 
									
										
										
										
											2014-04-30 23:46:57 -04:00
										 |  |  | #include "core/arm/disassembler/load_symbol_map.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-16 18:03:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | #include "version.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GMainWindow::GMainWindow() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ui.setupUi(this); | 
					
						
							|  |  |  |     statusBar()->hide(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     render_window = new GRenderWindow; | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     render_window->hide(); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-18 18:30:53 -04:00
										 |  |  |     disasmWidget = new DisassemblerWidget(this, render_window->GetEmuThread()); | 
					
						
							|  |  |  |     addDockWidget(Qt::BottomDockWidgetArea, disasmWidget); | 
					
						
							|  |  |  |     disasmWidget->hide(); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-18 18:30:53 -04:00
										 |  |  |     registersWidget = new RegistersWidget(this); | 
					
						
							|  |  |  |     addDockWidget(Qt::RightDockWidgetArea, registersWidget); | 
					
						
							|  |  |  |     registersWidget->hide(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     callstackWidget = new CallstackWidget(this); | 
					
						
							|  |  |  |     addDockWidget(Qt::RightDockWidgetArea, callstackWidget); | 
					
						
							|  |  |  |     callstackWidget->hide(); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-17 22:38:10 +02:00
										 |  |  |     graphicsWidget = new GPUCommandStreamWidget(this); | 
					
						
							|  |  |  |     addDockWidget(Qt::RightDockWidgetArea, graphicsWidget); | 
					
						
							| 
									
										
										
										
											2014-08-14 19:21:55 +02:00
										 |  |  |     graphicsWidget ->hide(); | 
					
						
							| 
									
										
										
										
											2014-05-17 22:38:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 17:52:22 +02:00
										 |  |  |     graphicsCommandsWidget = new GPUCommandListWidget(this); | 
					
						
							|  |  |  |     addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); | 
					
						
							| 
									
										
										
										
											2014-08-14 19:21:55 +02:00
										 |  |  |     graphicsCommandsWidget->hide(); | 
					
						
							| 
									
										
										
										
											2014-05-18 17:52:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); | 
					
						
							| 
									
										
										
										
											2014-04-18 18:30:53 -04:00
										 |  |  |     debug_menu->addAction(disasmWidget->toggleViewAction()); | 
					
						
							|  |  |  |     debug_menu->addAction(registersWidget->toggleViewAction()); | 
					
						
							|  |  |  |     debug_menu->addAction(callstackWidget->toggleViewAction()); | 
					
						
							| 
									
										
										
										
											2014-05-17 22:38:10 +02:00
										 |  |  |     debug_menu->addAction(graphicsWidget->toggleViewAction()); | 
					
						
							| 
									
										
										
										
											2014-05-18 17:52:22 +02:00
										 |  |  |     debug_menu->addAction(graphicsCommandsWidget->toggleViewAction()); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Set default UI state
 | 
					
						
							|  |  |  |     // geometry: 55% of the window contents are in the upper screen half, 45% in the lower half
 | 
					
						
							|  |  |  |     QDesktopWidget* desktop = ((QApplication*)QApplication::instance())->desktop(); | 
					
						
							|  |  |  |     QRect screenRect = desktop->screenGeometry(this); | 
					
						
							|  |  |  |     int x, y, w, h; | 
					
						
							|  |  |  |     w = screenRect.width() * 2 / 3; | 
					
						
							|  |  |  |     h = screenRect.height() / 2; | 
					
						
							|  |  |  |     x = (screenRect.x() + screenRect.width()) / 2 - w / 2; | 
					
						
							|  |  |  |     y = (screenRect.y() + screenRect.height()) / 2 - h * 55 / 100; | 
					
						
							|  |  |  |     setGeometry(x, y, w, h); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Restore UI state
 | 
					
						
							|  |  |  |     QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Citra team", "Citra"); | 
					
						
							|  |  |  |     restoreGeometry(settings.value("geometry").toByteArray()); | 
					
						
							|  |  |  |     restoreState(settings.value("state").toByteArray()); | 
					
						
							|  |  |  |     render_window->restoreGeometry(settings.value("geometryRenderWindow").toByteArray()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     ui.action_Popout_Window_Mode->setChecked(settings.value("popoutWindowMode", true).toBool()); | 
					
						
							|  |  |  |     ToggleWindowMode(); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Setup connections
 | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile())); | 
					
						
							| 
									
										
										
										
											2014-04-30 23:46:57 -04:00
										 |  |  |     connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap())); | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     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_Popout_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode())); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues
 | 
					
						
							| 
									
										
										
										
											2014-04-18 18:30:53 -04:00
										 |  |  |     connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), disasmWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); | 
					
						
							|  |  |  |     connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), registersWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); | 
					
						
							|  |  |  |     connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), callstackWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Setup hotkeys
 | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     RegisterHotkey("Main Window", "Load File", QKeySequence::Open); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     RegisterHotkey("Main Window", "Start Emulation"); | 
					
						
							|  |  |  |     LoadHotkeys(settings); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile())); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-23 22:49:55 -04:00
										 |  |  |     setWindowTitle(render_window->GetWindowTitle().c_str()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     show(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-12 19:01:33 -04:00
										 |  |  |     LogManager::Init(); | 
					
						
							| 
									
										
										
										
											2014-04-21 22:02:32 -04:00
										 |  |  |     System::Init(render_window); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GMainWindow::~GMainWindow() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // will get automatically deleted otherwise
 | 
					
						
							|  |  |  |     if (render_window->parent() == NULL) | 
					
						
							|  |  |  |         delete render_window; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-14 23:59:31 -07:00
										 |  |  | void GMainWindow::BootGame(std::string filename) | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-03 21:24:07 -04:00
										 |  |  |     NOTICE_LOG(MASTER_LOG, "citra starting...\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     if (Core::Init()) { | 
					
						
							| 
									
										
										
										
											2014-04-03 21:24:07 -04:00
										 |  |  |         ERROR_LOG(MASTER_LOG, "core initialization failed, exiting..."); | 
					
						
							|  |  |  |         Core::Stop(); | 
					
						
							|  |  |  |         exit(1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Load a game or die...
 | 
					
						
							| 
									
										
										
										
											2014-08-14 23:59:31 -07:00
										 |  |  |     if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) { | 
					
						
							| 
									
										
										
										
											2014-06-18 18:58:09 -04:00
										 |  |  |         ERROR_LOG(BOOT, "Failed to load ROM!"); | 
					
						
							| 
									
										
										
										
											2014-04-03 21:24:07 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-18 18:30:53 -04:00
										 |  |  |     disasmWidget->Init(); | 
					
						
							|  |  |  |     registersWidget->OnCPUStepped(); | 
					
						
							|  |  |  |     callstackWidget->OnCPUStepped(); | 
					
						
							| 
									
										
										
										
											2014-04-03 21:24:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     render_window->GetEmuThread().SetFilename(filename); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     render_window->GetEmuThread().start(); | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     render_window->show(); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  | void GMainWindow::OnMenuLoadFile() | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-27 00:04:26 -04:00
										 |  |  |     QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS executable (*.elf *.axf *.bin *.cci *.cxi)")); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     if (filename.size()) | 
					
						
							|  |  |  |        BootGame(filename.toLatin1().data()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-30 23:46:57 -04:00
										 |  |  | void GMainWindow::OnMenuLoadSymbolMap() { | 
					
						
							|  |  |  |     QString filename = QFileDialog::getOpenFileName(this, tr("Load symbol map"), QString(), tr("Symbol map (*)")); | 
					
						
							|  |  |  |     if (filename.size()) | 
					
						
							|  |  |  |         LoadSymbolMap(filename.toLatin1().data()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | void GMainWindow::OnStartGame() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-03 21:24:07 -04:00
										 |  |  |     render_window->GetEmuThread().SetCpuRunning(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui.action_Start->setEnabled(false); | 
					
						
							|  |  |  |     ui.action_Pause->setEnabled(true); | 
					
						
							|  |  |  |     ui.action_Stop->setEnabled(true); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GMainWindow::OnPauseGame() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-03 21:24:07 -04:00
										 |  |  |     render_window->GetEmuThread().SetCpuRunning(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui.action_Start->setEnabled(true); | 
					
						
							|  |  |  |     ui.action_Pause->setEnabled(false); | 
					
						
							|  |  |  |     ui.action_Stop->setEnabled(true); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GMainWindow::OnStopGame() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-03 21:24:07 -04:00
										 |  |  |     render_window->GetEmuThread().SetCpuRunning(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui.action_Start->setEnabled(true); | 
					
						
							|  |  |  |     ui.action_Pause->setEnabled(false); | 
					
						
							|  |  |  |     ui.action_Stop->setEnabled(false); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GMainWindow::OnOpenHotkeysDialog() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GHotkeysDialog dialog(this); | 
					
						
							|  |  |  |     dialog.exec(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-12 19:01:33 -04:00
										 |  |  | void GMainWindow::ToggleWindowMode() | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     bool enable = ui.action_Popout_Window_Mode->isChecked(); | 
					
						
							|  |  |  |     if (enable && render_window->parent() != NULL) | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |         ui.horizontalLayout->removeWidget(render_window); | 
					
						
							|  |  |  |         render_window->setParent(NULL); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |         render_window->setVisible(true); | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |         render_window->RestoreGeometry(); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     else if (!enable && render_window->parent() == NULL) | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |         render_window->BackupGeometry(); | 
					
						
							|  |  |  |         ui.horizontalLayout->addWidget(render_window); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |         render_window->setVisible(true); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GMainWindow::OnConfigure() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     //GControllerConfigDialog* dialog = new GControllerConfigDialog(controller_ports, this);
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GMainWindow::closeEvent(QCloseEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Save window layout
 | 
					
						
							|  |  |  |     QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Citra team", "Citra"); | 
					
						
							|  |  |  |     settings.setValue("geometry", saveGeometry()); | 
					
						
							|  |  |  |     settings.setValue("state", saveState()); | 
					
						
							|  |  |  |     settings.setValue("geometryRenderWindow", render_window->saveGeometry()); | 
					
						
							| 
									
										
										
										
											2014-04-21 23:15:17 -04:00
										 |  |  |     settings.setValue("popoutWindowMode", ui.action_Popout_Window_Mode->isChecked()); | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  |     settings.setValue("firstStart", false); | 
					
						
							|  |  |  |     SaveHotkeys(settings); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     render_window->close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QWidget::closeEvent(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef main
 | 
					
						
							|  |  |  | #undef main
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int __cdecl main(int argc, char* argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QApplication::setAttribute(Qt::AA_X11InitThreads); | 
					
						
							|  |  |  |     QApplication app(argc, argv); | 
					
						
							|  |  |  |     GMainWindow main_window; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     main_window.show(); | 
					
						
							|  |  |  |     return app.exec(); | 
					
						
							|  |  |  | } |