summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--appveyor.yml17
-rw-r--r--src/citra_qt/bootmanager.cpp19
-rw-r--r--src/citra_qt/bootmanager.h12
-rw-r--r--src/citra_qt/debugger/callstack.cpp7
-rw-r--r--src/citra_qt/debugger/callstack.h3
-rw-r--r--src/citra_qt/debugger/disassembler.cpp7
-rw-r--r--src/citra_qt/debugger/disassembler.h3
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.cpp8
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.h4
-rw-r--r--src/citra_qt/debugger/registers.cpp7
-rw-r--r--src/citra_qt/debugger/registers.h3
-rw-r--r--src/citra_qt/main.cpp14
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp60
-rw-r--r--src/core/hle/kernel/thread.cpp3
14 files changed, 117 insertions, 50 deletions
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 000000000..83d3b900e
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,17 @@
1# it seems that Qt is only installed by default on unstable os at the moment
2os: unstable
3
4# shallow clone
5clone_depth: 1
6
7environment:
8 QTDIR: C:\Qt\5.4\msvc2013_opengl
9
10install:
11 - git submodule update --init --recursive
12
13before_build:
14 - mkdir build
15 - cd build
16 - cmake ..
17 - cd ..
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 3e24da596..196380105 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -40,18 +40,35 @@ void EmuThread::SetFilename(std::string filename)
40void EmuThread::run() 40void EmuThread::run()
41{ 41{
42 stop_run = false; 42 stop_run = false;
43
44 // holds whether the cpu was running during the last iteration,
45 // so that the DebugModeLeft signal can be emitted before the
46 // next execution step
47 bool was_active = false;
43 while (!stop_run) 48 while (!stop_run)
44 { 49 {
45 if (cpu_running) 50 if (cpu_running)
46 { 51 {
52 if (!was_active)
53 emit DebugModeLeft();
54
47 Core::RunLoop(); 55 Core::RunLoop();
56
57 was_active = cpu_running || exec_cpu_step;
58 if (!was_active)
59 emit DebugModeEntered();
48 } 60 }
49 else if (exec_cpu_step) 61 else if (exec_cpu_step)
50 { 62 {
63 if (!was_active)
64 emit DebugModeLeft();
65
51 exec_cpu_step = false; 66 exec_cpu_step = false;
52 Core::SingleStep(); 67 Core::SingleStep();
53 emit CPUStepped(); 68 emit DebugModeEntered();
54 yieldCurrentThread(); 69 yieldCurrentThread();
70
71 was_active = false;
55 } 72 }
56 } 73 }
57 render_window->moveContext(); 74 render_window->moveContext();
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index 1c893384c..a55db682a 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -81,12 +81,18 @@ private:
81 81
82signals: 82signals:
83 /** 83 /**
84 * Emitted when CPU when we've finished processing a single Gekko instruction 84 * Emitted when the CPU has halted execution
85 * 85 *
86 * @warning This will only be emitted when the CPU is not running (SetCpuRunning(false))
87 * @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) 86 * @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)
88 */ 87 */
89 void CPUStepped(); 88 void DebugModeEntered();
89
90 /**
91 * Emitted right before the CPU continues execution
92 *
93 * @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)
94 */
95 void DebugModeLeft();
90}; 96};
91 97
92class GRenderWindow : public QWidget, public EmuWindow 98class GRenderWindow : public QWidget, public EmuWindow
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp
index 274c5cccd..025a5896b 100644
--- a/src/citra_qt/debugger/callstack.cpp
+++ b/src/citra_qt/debugger/callstack.cpp
@@ -25,7 +25,7 @@ CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent)
25 ui.treeView->setModel(callstack_model); 25 ui.treeView->setModel(callstack_model);
26} 26}
27 27
28void CallstackWidget::OnCPUStepped() 28void CallstackWidget::OnDebugModeEntered()
29{ 29{
30 ARM_Disasm* disasm = new ARM_Disasm(); 30 ARM_Disasm* disasm = new ARM_Disasm();
31 ARM_Interface* app_core = Core::g_app_core; 31 ARM_Interface* app_core = Core::g_app_core;
@@ -71,3 +71,8 @@ void CallstackWidget::OnCPUStepped()
71 } 71 }
72 } 72 }
73} 73}
74
75void CallstackWidget::OnDebugModeLeft()
76{
77
78}
diff --git a/src/citra_qt/debugger/callstack.h b/src/citra_qt/debugger/callstack.h
index 4f4f74823..fb390f5c3 100644
--- a/src/citra_qt/debugger/callstack.h
+++ b/src/citra_qt/debugger/callstack.h
@@ -15,7 +15,8 @@ public:
15 CallstackWidget(QWidget* parent = 0); 15 CallstackWidget(QWidget* parent = 0);
16 16
17public slots: 17public slots:
18 void OnCPUStepped(); 18 void OnDebugModeEntered();
19 void OnDebugModeLeft();
19 20
20private: 21private:
21 Ui::CallStack ui; 22 Ui::CallStack ui;
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index da084ab24..c61ace925 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -235,7 +235,7 @@ void DisassemblerWidget::OnToggleStartStop()
235 emu_thread.SetCpuRunning(!emu_thread.IsCpuRunning()); 235 emu_thread.SetCpuRunning(!emu_thread.IsCpuRunning());
236} 236}
237 237
238void DisassemblerWidget::OnCPUStepped() 238void DisassemblerWidget::OnDebugModeEntered()
239{ 239{
240 ARMword next_instr = Core::g_app_core->GetPC(); 240 ARMword next_instr = Core::g_app_core->GetPC();
241 241
@@ -252,6 +252,11 @@ void DisassemblerWidget::OnCPUStepped()
252 disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); 252 disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
253} 253}
254 254
255void DisassemblerWidget::OnDebugModeLeft()
256{
257
258}
259
255int DisassemblerWidget::SelectedRow() 260int DisassemblerWidget::SelectedRow()
256{ 261{
257 QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex(); 262 QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex();
diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h
index 6d3cef108..0deccc240 100644
--- a/src/citra_qt/debugger/disassembler.h
+++ b/src/citra_qt/debugger/disassembler.h
@@ -61,7 +61,8 @@ public slots:
61 void OnPause(); 61 void OnPause();
62 void OnToggleStartStop(); 62 void OnToggleStartStop();
63 63
64 void OnCPUStepped(); 64 void OnDebugModeEntered();
65 void OnDebugModeLeft();
65 66
66private: 67private:
67 // returns -1 if no row is selected 68 // returns -1 if no row is selected
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index caa6896f9..a9423d6c7 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -158,17 +158,17 @@ void GraphicsFramebufferWidget::OnFramebufferAddressChanged(qint64 new_value)
158 } 158 }
159} 159}
160 160
161void GraphicsFramebufferWidget::OnFramebufferWidthChanged(unsigned int new_value) 161void GraphicsFramebufferWidget::OnFramebufferWidthChanged(int new_value)
162{ 162{
163 if (framebuffer_width != new_value) { 163 if (framebuffer_width != static_cast<unsigned>(new_value)) {
164 framebuffer_width = new_value; 164 framebuffer_width = static_cast<unsigned>(new_value);
165 165
166 framebuffer_source_list->setCurrentIndex(static_cast<int>(Source::Custom)); 166 framebuffer_source_list->setCurrentIndex(static_cast<int>(Source::Custom));
167 emit Update(); 167 emit Update();
168 } 168 }
169} 169}
170 170
171void GraphicsFramebufferWidget::OnFramebufferHeightChanged(unsigned int new_value) 171void GraphicsFramebufferWidget::OnFramebufferHeightChanged(int new_value)
172{ 172{
173 if (framebuffer_height != new_value) { 173 if (framebuffer_height != new_value) {
174 framebuffer_height = new_value; 174 framebuffer_height = new_value;
diff --git a/src/citra_qt/debugger/graphics_framebuffer.h b/src/citra_qt/debugger/graphics_framebuffer.h
index 02813525c..56215761e 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.h
+++ b/src/citra_qt/debugger/graphics_framebuffer.h
@@ -62,8 +62,8 @@ public:
62public slots: 62public slots:
63 void OnFramebufferSourceChanged(int new_value); 63 void OnFramebufferSourceChanged(int new_value);
64 void OnFramebufferAddressChanged(qint64 new_value); 64 void OnFramebufferAddressChanged(qint64 new_value);
65 void OnFramebufferWidthChanged(unsigned int new_value); 65 void OnFramebufferWidthChanged(int new_value);
66 void OnFramebufferHeightChanged(unsigned int new_value); 66 void OnFramebufferHeightChanged(int new_value);
67 void OnFramebufferFormatChanged(int new_value); 67 void OnFramebufferFormatChanged(int new_value);
68 void OnUpdate(); 68 void OnUpdate();
69 69
diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp
index e982dfb3f..ab3666156 100644
--- a/src/citra_qt/debugger/registers.cpp
+++ b/src/citra_qt/debugger/registers.cpp
@@ -41,7 +41,7 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent)
41 CSPR->addChild(new QTreeWidgetItem(QStringList("N"))); 41 CSPR->addChild(new QTreeWidgetItem(QStringList("N")));
42} 42}
43 43
44void RegistersWidget::OnCPUStepped() 44void RegistersWidget::OnDebugModeEntered()
45{ 45{
46 ARM_Interface* app_core = Core::g_app_core; 46 ARM_Interface* app_core = Core::g_app_core;
47 47
@@ -65,3 +65,8 @@ void RegistersWidget::OnCPUStepped()
65 CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero 65 CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero
66 CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than 66 CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than
67} 67}
68
69void RegistersWidget::OnDebugModeLeft()
70{
71
72}
diff --git a/src/citra_qt/debugger/registers.h b/src/citra_qt/debugger/registers.h
index ac8429f2b..bf8955625 100644
--- a/src/citra_qt/debugger/registers.h
+++ b/src/citra_qt/debugger/registers.h
@@ -17,7 +17,8 @@ public:
17 RegistersWidget(QWidget* parent = NULL); 17 RegistersWidget(QWidget* parent = NULL);
18 18
19public slots: 19public slots:
20 void OnCPUStepped(); 20 void OnDebugModeEntered();
21 void OnDebugModeLeft();
21 22
22private: 23private:
23 Ui::ARMRegisters cpu_regs_ui; 24 Ui::ARMRegisters cpu_regs_ui;
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index c6671bef1..ece593e5d 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -124,9 +124,13 @@ GMainWindow::GMainWindow()
124 connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog())); 124 connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog()));
125 125
126 // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues 126 // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues
127 connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), disasmWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); 127 connect(&render_window->GetEmuThread(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
128 connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), registersWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); 128 connect(&render_window->GetEmuThread(), SIGNAL(DebugModeEntered()), registersWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
129 connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), callstackWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); 129 connect(&render_window->GetEmuThread(), SIGNAL(DebugModeEntered()), callstackWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
130
131 connect(&render_window->GetEmuThread(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection);
132 connect(&render_window->GetEmuThread(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection);
133 connect(&render_window->GetEmuThread(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection);
130 134
131 // Setup hotkeys 135 // Setup hotkeys
132 RegisterHotkey("Main Window", "Load File", QKeySequence::Open); 136 RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
@@ -167,8 +171,8 @@ void GMainWindow::BootGame(std::string filename)
167 } 171 }
168 172
169 disasmWidget->Init(); 173 disasmWidget->Init();
170 registersWidget->OnCPUStepped(); 174 registersWidget->OnDebugModeEntered();
171 callstackWidget->OnCPUStepped(); 175 callstackWidget->OnDebugModeEntered();
172 176
173 render_window->GetEmuThread().SetFilename(filename); 177 render_window->GetEmuThread().SetFilename(filename);
174 render_window->GetEmuThread().start(); 178 render_window->GetEmuThread().start();
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index e3ca02e98..4759c7653 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -4964,39 +4964,41 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4964 } 4964 }
4965 MSR_INST: 4965 MSR_INST:
4966 { 4966 {
4967 msr_inst *inst_cream = (msr_inst *)inst_base->component; 4967 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4968 const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; 4968 msr_inst *inst_cream = (msr_inst *)inst_base->component;
4969 unsigned int inst = inst_cream->inst; 4969 const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
4970 unsigned int operand; 4970 unsigned int inst = inst_cream->inst;
4971 unsigned int operand;
4971 4972
4972 if (BIT(inst, 25)) { 4973 if (BIT(inst, 25)) {
4973 int rot_imm = BITS(inst, 8, 11) * 2; 4974 int rot_imm = BITS(inst, 8, 11) * 2;
4974 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); 4975 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
4975 } else {
4976 operand = cpu->Reg[BITS(inst, 0, 3)];
4977 }
4978 uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
4979 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
4980 uint32_t mask;
4981 if (!inst_cream->R) {
4982 if (InAPrivilegedMode(cpu)) {
4983 if ((operand & StateMask) != 0) {
4984 /// UNPREDICTABLE
4985 DEBUG_MSG;
4986 } else
4987 mask = byte_mask & (UserMask | PrivMask);
4988 } else { 4976 } else {
4989 mask = byte_mask & UserMask; 4977 operand = cpu->Reg[BITS(inst, 0, 3)];
4990 } 4978 }
4991 SAVE_NZCVT; 4979 uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
4980 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
4981 uint32_t mask;
4982 if (!inst_cream->R) {
4983 if (InAPrivilegedMode(cpu)) {
4984 if ((operand & StateMask) != 0) {
4985 /// UNPREDICTABLE
4986 DEBUG_MSG;
4987 } else
4988 mask = byte_mask & (UserMask | PrivMask);
4989 } else {
4990 mask = byte_mask & UserMask;
4991 }
4992 SAVE_NZCVT;
4992 4993
4993 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); 4994 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
4994 switch_mode(cpu, cpu->Cpsr & 0x1f); 4995 switch_mode(cpu, cpu->Cpsr & 0x1f);
4995 LOAD_NZCVT; 4996 LOAD_NZCVT;
4996 } else { 4997 } else {
4997 if (CurrentModeHasSPSR) { 4998 if (CurrentModeHasSPSR) {
4998 mask = byte_mask & (UserMask | PrivMask | StateMask); 4999 mask = byte_mask & (UserMask | PrivMask | StateMask);
4999 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); 5000 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
5001 }
5000 } 5002 }
5001 } 5003 }
5002 cpu->Reg[15] += GET_INST_SIZE(cpu); 5004 cpu->Reg[15] += GET_INST_SIZE(cpu);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index dd20ca30e..bc86a7c59 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -263,6 +263,9 @@ void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) {
263 263
264/// Resumes a thread from waiting by marking it as "ready" 264/// Resumes a thread from waiting by marking it as "ready"
265void Thread::ResumeFromWait() { 265void Thread::ResumeFromWait() {
266 // Cancel any outstanding wakeup events
267 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle());
268
266 status &= ~THREADSTATUS_WAIT; 269 status &= ~THREADSTATUS_WAIT;
267 wait_object = nullptr; 270 wait_object = nullptr;
268 wait_type = WAITTYPE_NONE; 271 wait_type = WAITTYPE_NONE;