summaryrefslogtreecommitdiff
path: root/src/citra_qt/bootmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt/bootmanager.cpp')
-rw-r--r--src/citra_qt/bootmanager.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
new file mode 100644
index 000000000..095856dc9
--- /dev/null
+++ b/src/citra_qt/bootmanager.cpp
@@ -0,0 +1,206 @@
1#include <QHBoxLayout>
2#include <QKeyEvent>
3
4#include "common.h"
5#include "bootmanager.hxx"
6
7#include "core.h"
8#include "loader.h"
9
10#include "version.h"
11
12#define APP_NAME "citra"
13#define APP_VERSION "0.1-" VERSION
14#define APP_TITLE APP_NAME " " APP_VERSION
15#define COPYRIGHT "Copyright (C) 2013-2014 Citra Team"
16
17EmuThread::EmuThread(GRenderWindow* render_window) : exec_cpu_step(false), cpu_running(false), render_window(render_window)
18{
19}
20
21void EmuThread::SetFilename(const char* filename)
22{
23 strcpy(this->filename, filename);
24}
25
26void EmuThread::run()
27{
28 while (true)
29 {
30 for (int tight_loop = 0; tight_loop < 10000; ++tight_loop)
31 {
32 if (cpu_running || exec_cpu_step)
33 {
34 if (exec_cpu_step)
35 exec_cpu_step = false;
36
37 Core::SingleStep();
38 emit CPUStepped();
39 }
40 }
41 }
42
43 Core::Stop();
44}
45
46void EmuThread::Stop()
47{
48 if (!isRunning())
49 {
50 INFO_LOG(MASTER_LOG, "EmuThread::Stop called while emu thread wasn't running, returning...");
51 return;
52 }
53
54 //core::g_state = core::SYS_DIE;
55
56 wait(1000);
57 if (isRunning())
58 {
59 WARN_LOG(MASTER_LOG, "EmuThread still running, terminating...");
60 terminate();
61 wait(1000);
62 if (isRunning())
63 WARN_LOG(MASTER_LOG, "EmuThread STILL running, something is wrong here...");
64 }
65 INFO_LOG(MASTER_LOG, "EmuThread stopped");
66}
67
68
69// This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL context.
70// The corresponding functionality is handled in EmuThread instead
71class GGLWidgetInternal : public QGLWidget
72{
73public:
74 GGLWidgetInternal(GRenderWindow* parent) : QGLWidget(parent)
75 {
76 setAutoBufferSwap(false);
77 doneCurrent();
78 parent_ = parent;
79 }
80
81 void paintEvent(QPaintEvent* ev)
82 {
83 // Apparently, Windows doesn't display anything if we don't call this here.
84 // TODO: Breaks linux though because we aren't calling doneCurrent() ... -.-
85// makeCurrent();
86 }
87 void resizeEvent(QResizeEvent* ev) {
88 parent_->set_client_area_width(size().width());
89 parent_->set_client_area_height(size().height());
90 }
91private:
92 GRenderWindow* parent_;
93};
94
95
96EmuThread& GRenderWindow::GetEmuThread()
97{
98 return emu_thread;
99}
100
101GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this)
102{
103 // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose
104
105 child = new GGLWidgetInternal(this);
106
107 QBoxLayout* layout = new QHBoxLayout(this);
108 resize(640, 480); // TODO: Load size from config instead
109 layout->addWidget(child);
110 layout->setMargin(0);
111 setLayout(layout);
112
113 BackupGeometry();
114}
115
116GRenderWindow::~GRenderWindow()
117{
118 emu_thread.Stop();
119}
120
121void GRenderWindow::SwapBuffers()
122{
123 child->makeCurrent(); // TODO: Not necessary?
124 child->swapBuffers();
125}
126
127void GRenderWindow::closeEvent(QCloseEvent* event)
128{
129 emu_thread.Stop();
130 QWidget::closeEvent(event);
131}
132
133void GRenderWindow::MakeCurrent()
134{
135 child->makeCurrent();
136}
137
138void GRenderWindow::DoneCurrent()
139{
140 child->doneCurrent();
141}
142
143void GRenderWindow::PollEvents() {
144 // TODO(ShizZy): Does this belong here? This is a reasonable place to update the window title
145 // from the main thread, but this should probably be in an event handler...
146 /*
147 static char title[128];
148 sprintf(title, "%s (FPS: %02.02f)", window_title_.c_str(),
149 video_core::g_renderer->current_fps());
150 setWindowTitle(title);
151 */
152}
153
154void GRenderWindow::BackupGeometry()
155{
156 geometry = ((QGLWidget*)this)->saveGeometry();
157}
158
159void GRenderWindow::RestoreGeometry()
160{
161 // We don't want to back up the geometry here (obviously)
162 QWidget::restoreGeometry(geometry);
163}
164
165void GRenderWindow::restoreGeometry(const QByteArray& geometry)
166{
167 // Make sure users of this class don't need to deal with backing up the geometry themselves
168 QWidget::restoreGeometry(geometry);
169 BackupGeometry();
170}
171
172QByteArray GRenderWindow::saveGeometry()
173{
174 // If we are a top-level widget, store the current geometry
175 // otherwise, store the last backup
176 if (parent() == NULL)
177 return ((QGLWidget*)this)->saveGeometry();
178 else
179 return geometry;
180}
181
182void GRenderWindow::keyPressEvent(QKeyEvent* event)
183{
184 /*
185 bool key_processed = false;
186 for (unsigned int channel = 0; channel < 4 && controller_interface(); ++channel)
187 if (controller_interface()->SetControllerStatus(channel, event->key(), input_common::GCController::PRESSED))
188 key_processed = true;
189
190 if (!key_processed)
191 QWidget::keyPressEvent(event);
192 */
193}
194
195void GRenderWindow::keyReleaseEvent(QKeyEvent* event)
196{
197 /*
198 bool key_processed = false;
199 for (unsigned int channel = 0; channel < 4 && controller_interface(); ++channel)
200 if (controller_interface()->SetControllerStatus(channel, event->key(), input_common::GCController::RELEASED))
201 key_processed = true;
202
203 if (!key_processed)
204 QWidget::keyPressEvent(event);
205 */
206} \ No newline at end of file