summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra/citra.cpp3
-rw-r--r--src/citra_qt/bootmanager.cpp6
-rw-r--r--src/citra_qt/configure_general.cpp2
-rw-r--r--src/citra_qt/configure_graphics.cpp2
-rw-r--r--src/citra_qt/configure_system.cpp1
-rw-r--r--src/citra_qt/debugger/callstack.cpp2
-rw-r--r--src/citra_qt/debugger/disassembler.cpp10
-rw-r--r--src/citra_qt/debugger/registers.cpp16
-rw-r--r--src/citra_qt/debugger/wait_tree.cpp2
-rw-r--r--src/citra_qt/main.cpp1
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/core.cpp112
-rw-r--r--src/core/core.h132
-rw-r--r--src/core/core_timing.cpp27
-rw-r--r--src/core/gdbstub/gdbstub.cpp39
-rw-r--r--src/core/hle/function_wrappers.h60
-rw-r--r--src/core/hle/hle.cpp4
-rw-r--r--src/core/hle/kernel/thread.cpp6
-rw-r--r--src/core/hle/service/ldr_ro/ldr_ro.cpp8
-rw-r--r--src/core/hle/svc.cpp12
-rw-r--r--src/core/system.cpp90
-rw-r--r--src/core/system.h83
22 files changed, 284 insertions, 336 deletions
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp
index 5e2829b54..febfc5dc8 100644
--- a/src/citra/citra.cpp
+++ b/src/citra/citra.cpp
@@ -33,7 +33,6 @@
33#include "core/gdbstub/gdbstub.h" 33#include "core/gdbstub/gdbstub.h"
34#include "core/loader/loader.h" 34#include "core/loader/loader.h"
35#include "core/settings.h" 35#include "core/settings.h"
36#include "core/system.h"
37#include "video_core/video_core.h" 36#include "video_core/video_core.h"
38 37
39static void PrintHelp(const char* argv0) { 38static void PrintHelp(const char* argv0) {
@@ -145,7 +144,7 @@ int main(int argc, char** argv) {
145 } 144 }
146 145
147 while (emu_window->IsOpen()) { 146 while (emu_window->IsOpen()) {
148 Core::RunLoop(); 147 system.RunLoop();
149 } 148 }
150 149
151 return 0; 150 return 0;
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 5e8ae3066..bb75633b6 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -14,8 +14,6 @@
14#include "common/scm_rev.h" 14#include "common/scm_rev.h"
15#include "common/string_util.h" 15#include "common/string_util.h"
16#include "core/core.h" 16#include "core/core.h"
17#include "core/settings.h"
18#include "core/system.h"
19#include "video_core/debug_utils/debug_utils.h" 17#include "video_core/debug_utils/debug_utils.h"
20#include "video_core/video_core.h" 18#include "video_core/video_core.h"
21 19
@@ -38,7 +36,7 @@ void EmuThread::run() {
38 if (!was_active) 36 if (!was_active)
39 emit DebugModeLeft(); 37 emit DebugModeLeft();
40 38
41 Core::RunLoop(); 39 Core::System::GetInstance().RunLoop();
42 40
43 was_active = running || exec_step; 41 was_active = running || exec_step;
44 if (!was_active && !stop_run) 42 if (!was_active && !stop_run)
@@ -48,7 +46,7 @@ void EmuThread::run() {
48 emit DebugModeLeft(); 46 emit DebugModeLeft();
49 47
50 exec_step = false; 48 exec_step = false;
51 Core::SingleStep(); 49 Core::System::GetInstance().SingleStep();
52 emit DebugModeEntered(); 50 emit DebugModeEntered();
53 yieldCurrentThread(); 51 yieldCurrentThread();
54 52
diff --git a/src/citra_qt/configure_general.cpp b/src/citra_qt/configure_general.cpp
index f576f6f7a..03cd8835b 100644
--- a/src/citra_qt/configure_general.cpp
+++ b/src/citra_qt/configure_general.cpp
@@ -4,8 +4,8 @@
4 4
5#include "citra_qt/configure_general.h" 5#include "citra_qt/configure_general.h"
6#include "citra_qt/ui_settings.h" 6#include "citra_qt/ui_settings.h"
7#include "core/core.h"
7#include "core/settings.h" 8#include "core/settings.h"
8#include "core/system.h"
9#include "ui_configure_general.h" 9#include "ui_configure_general.h"
10 10
11ConfigureGeneral::ConfigureGeneral(QWidget* parent) 11ConfigureGeneral::ConfigureGeneral(QWidget* parent)
diff --git a/src/citra_qt/configure_graphics.cpp b/src/citra_qt/configure_graphics.cpp
index 1e6f7f880..cea7db388 100644
--- a/src/citra_qt/configure_graphics.cpp
+++ b/src/citra_qt/configure_graphics.cpp
@@ -3,8 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "citra_qt/configure_graphics.h" 5#include "citra_qt/configure_graphics.h"
6#include "core/core.h"
6#include "core/settings.h" 7#include "core/settings.h"
7#include "core/system.h"
8#include "ui_configure_graphics.h" 8#include "ui_configure_graphics.h"
9 9
10ConfigureGraphics::ConfigureGraphics(QWidget* parent) 10ConfigureGraphics::ConfigureGraphics(QWidget* parent)
diff --git a/src/citra_qt/configure_system.cpp b/src/citra_qt/configure_system.cpp
index 545261c01..eb1276ef3 100644
--- a/src/citra_qt/configure_system.cpp
+++ b/src/citra_qt/configure_system.cpp
@@ -6,7 +6,6 @@
6#include "citra_qt/ui_settings.h" 6#include "citra_qt/ui_settings.h"
7#include "core/hle/service/cfg/cfg.h" 7#include "core/hle/service/cfg/cfg.h"
8#include "core/hle/service/fs/archive.h" 8#include "core/hle/service/fs/archive.h"
9#include "core/system.h"
10#include "ui_configure_system.h" 9#include "ui_configure_system.h"
11 10
12static const std::array<int, 12> days_in_month = {{ 11static const std::array<int, 12> days_in_month = {{
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp
index c66f2b96a..5e176be48 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 25
26void CallstackWidget::OnDebugModeEntered() { 26void CallstackWidget::OnDebugModeEntered() {
27 // Stack pointer 27 // Stack pointer
28 const u32 sp = Core::g_app_core->GetReg(13); 28 const u32 sp = Core::AppCore().GetReg(13);
29 29
30 Clear(); 30 Clear();
31 31
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index 1ee6bbd6a..712e35f7f 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -185,13 +185,13 @@ DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread)
185} 185}
186 186
187void DisassemblerWidget::Init() { 187void DisassemblerWidget::Init() {
188 model->ParseFromAddress(Core::g_app_core->GetPC()); 188 model->ParseFromAddress(Core::AppCore().GetPC());
189 189
190 disasm_ui.treeView->resizeColumnToContents(0); 190 disasm_ui.treeView->resizeColumnToContents(0);
191 disasm_ui.treeView->resizeColumnToContents(1); 191 disasm_ui.treeView->resizeColumnToContents(1);
192 disasm_ui.treeView->resizeColumnToContents(2); 192 disasm_ui.treeView->resizeColumnToContents(2);
193 193
194 QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::g_app_core->GetPC()); 194 QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::AppCore().GetPC());
195 disasm_ui.treeView->scrollTo(model_index); 195 disasm_ui.treeView->scrollTo(model_index);
196 disasm_ui.treeView->selectionModel()->setCurrentIndex( 196 disasm_ui.treeView->selectionModel()->setCurrentIndex(
197 model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); 197 model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
@@ -214,8 +214,8 @@ void DisassemblerWidget::OnPause() {
214 emu_thread->SetRunning(false); 214 emu_thread->SetRunning(false);
215 215
216 // TODO: By now, the CPU might not have actually stopped... 216 // TODO: By now, the CPU might not have actually stopped...
217 if (Core::g_app_core) { 217 if (Core::System::GetInstance().IsPoweredOn()) {
218 model->SetNextInstruction(Core::g_app_core->GetPC()); 218 model->SetNextInstruction(Core::AppCore().GetPC());
219 } 219 }
220} 220}
221 221
@@ -224,7 +224,7 @@ void DisassemblerWidget::OnToggleStartStop() {
224} 224}
225 225
226void DisassemblerWidget::OnDebugModeEntered() { 226void DisassemblerWidget::OnDebugModeEntered() {
227 u32 next_instr = Core::g_app_core->GetPC(); 227 u32 next_instr = Core::AppCore().GetPC();
228 228
229 if (model->GetBreakPoints().IsAddressBreakPoint(next_instr)) 229 if (model->GetBreakPoints().IsAddressBreakPoint(next_instr))
230 emu_thread->SetRunning(false); 230 emu_thread->SetRunning(false);
diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp
index 4c529d3c3..d5b6542bd 100644
--- a/src/citra_qt/debugger/registers.cpp
+++ b/src/citra_qt/debugger/registers.cpp
@@ -58,16 +58,16 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) {
58} 58}
59 59
60void RegistersWidget::OnDebugModeEntered() { 60void RegistersWidget::OnDebugModeEntered() {
61 if (!Core::g_app_core) 61 if (!Core::System::GetInstance().IsPoweredOn())
62 return; 62 return;
63 63
64 for (int i = 0; i < core_registers->childCount(); ++i) 64 for (int i = 0; i < core_registers->childCount(); ++i)
65 core_registers->child(i)->setText( 65 core_registers->child(i)->setText(
66 1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0'))); 66 1, QString("0x%1").arg(Core::AppCore().GetReg(i), 8, 16, QLatin1Char('0')));
67 67
68 for (int i = 0; i < vfp_registers->childCount(); ++i) 68 for (int i = 0; i < vfp_registers->childCount(); ++i)
69 vfp_registers->child(i)->setText( 69 vfp_registers->child(i)->setText(
70 1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); 70 1, QString("0x%1").arg(Core::AppCore().GetVFPReg(i), 8, 16, QLatin1Char('0')));
71 71
72 UpdateCPSRValues(); 72 UpdateCPSRValues();
73 UpdateVFPSystemRegisterValues(); 73 UpdateVFPSystemRegisterValues();
@@ -127,7 +127,7 @@ void RegistersWidget::CreateCPSRChildren() {
127} 127}
128 128
129void RegistersWidget::UpdateCPSRValues() { 129void RegistersWidget::UpdateCPSRValues() {
130 const u32 cpsr_val = Core::g_app_core->GetCPSR(); 130 const u32 cpsr_val = Core::AppCore().GetCPSR();
131 131
132 cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); 132 cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
133 cpsr->child(0)->setText( 133 cpsr->child(0)->setText(
@@ -191,10 +191,10 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
191} 191}
192 192
193void RegistersWidget::UpdateVFPSystemRegisterValues() { 193void RegistersWidget::UpdateVFPSystemRegisterValues() {
194 const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR); 194 const u32 fpscr_val = Core::AppCore().GetVFPSystemReg(VFP_FPSCR);
195 const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC); 195 const u32 fpexc_val = Core::AppCore().GetVFPSystemReg(VFP_FPEXC);
196 const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST); 196 const u32 fpinst_val = Core::AppCore().GetVFPSystemReg(VFP_FPINST);
197 const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2); 197 const u32 fpinst2_val = Core::AppCore().GetVFPSystemReg(VFP_FPINST2);
198 198
199 QTreeWidgetItem* const fpscr = vfp_system_registers->child(0); 199 QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
200 fpscr->setText(1, QString("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0'))); 200 fpscr->setText(1, QString("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));
diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp
index 5a308bf7f..1d2de5185 100644
--- a/src/citra_qt/debugger/wait_tree.cpp
+++ b/src/citra_qt/debugger/wait_tree.cpp
@@ -391,7 +391,7 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p
391} 391}
392 392
393void WaitTreeWidget::OnDebugModeEntered() { 393void WaitTreeWidget::OnDebugModeEntered() {
394 if (!Core::g_app_core) 394 if (!Core::System::GetInstance().IsPoweredOn())
395 return; 395 return;
396 model->InitItems(); 396 model->InitItems();
397 view->setModel(model); 397 view->setModel(model);
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 0c7723b0a..e27c09b53 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -46,7 +46,6 @@
46#include "core/gdbstub/gdbstub.h" 46#include "core/gdbstub/gdbstub.h"
47#include "core/loader/loader.h" 47#include "core/loader/loader.h"
48#include "core/settings.h" 48#include "core/settings.h"
49#include "core/system.h"
50#include "qhexedit.h" 49#include "qhexedit.h"
51#include "video_core/video_core.h" 50#include "video_core/video_core.h"
52 51
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index af224166a..d547b0746 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -155,7 +155,6 @@ set(SRCS
155 tracer/recorder.cpp 155 tracer/recorder.cpp
156 memory.cpp 156 memory.cpp
157 settings.cpp 157 settings.cpp
158 system.cpp
159 ) 158 )
160 159
161set(HEADERS 160set(HEADERS
@@ -325,7 +324,6 @@ set(HEADERS
325 memory_setup.h 324 memory_setup.h
326 mmio.h 325 mmio.h
327 settings.h 326 settings.h
328 system.h
329 ) 327 )
330 328
331include_directories(../../externals/dynarmic/include) 329include_directories(../../externals/dynarmic/include)
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 6efa18159..b4df90efd 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -3,6 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6
7#include "audio_core/audio_core.h"
6#include "common/logging/log.h" 8#include "common/logging/log.h"
7#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
8#include "core/arm/dynarmic/arm_dynarmic.h" 10#include "core/arm/dynarmic/arm_dynarmic.h"
@@ -11,17 +13,23 @@
11#include "core/core_timing.h" 13#include "core/core_timing.h"
12#include "core/gdbstub/gdbstub.h" 14#include "core/gdbstub/gdbstub.h"
13#include "core/hle/hle.h" 15#include "core/hle/hle.h"
16#include "core/hle/kernel/kernel.h"
17#include "core/hle/kernel/memory.h"
14#include "core/hle/kernel/thread.h" 18#include "core/hle/kernel/thread.h"
15#include "core/hw/hw.h" 19#include "core/hw/hw.h"
20#include "core/loader/loader.h"
16#include "core/settings.h" 21#include "core/settings.h"
22#include "video_core/video_core.h"
17 23
18namespace Core { 24namespace Core {
19 25
20std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core 26/*static*/ System System::s_instance;
21std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core 27
28System::ResultStatus System::RunLoop(int tight_loop) {
29 if (!app_core) {
30 return ResultStatus::ErrorNotInitialized;
31 }
22 32
23/// Run the core CPU loop
24void RunLoop(int tight_loop) {
25 if (GDBStub::IsServerEnabled()) { 33 if (GDBStub::IsServerEnabled()) {
26 GDBStub::HandlePacket(); 34 GDBStub::HandlePacket();
27 35
@@ -32,7 +40,7 @@ void RunLoop(int tight_loop) {
32 GDBStub::SetCpuStepFlag(false); 40 GDBStub::SetCpuStepFlag(false);
33 tight_loop = 1; 41 tight_loop = 1;
34 } else { 42 } else {
35 return; 43 return ResultStatus::Success;
36 } 44 }
37 } 45 }
38 } 46 }
@@ -45,46 +53,100 @@ void RunLoop(int tight_loop) {
45 CoreTiming::Advance(); 53 CoreTiming::Advance();
46 HLE::Reschedule(__func__); 54 HLE::Reschedule(__func__);
47 } else { 55 } else {
48 g_app_core->Run(tight_loop); 56 app_core->Run(tight_loop);
49 } 57 }
50 58
51 HW::Update(); 59 HW::Update();
52 if (HLE::IsReschedulePending()) { 60 if (HLE::IsReschedulePending()) {
53 Kernel::Reschedule(); 61 Kernel::Reschedule();
54 } 62 }
55}
56 63
57/// Step the CPU one instruction 64 return ResultStatus::Success;
58void SingleStep() {
59 RunLoop(1);
60} 65}
61 66
62/// Halt the core 67System::ResultStatus System::SingleStep() {
63void Halt(const char* msg) { 68 return RunLoop(1);
64 // TODO(ShizZy): ImplementMe
65} 69}
66 70
67/// Kill the core 71System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
68void Stop() { 72 if (app_loader) {
69 // TODO(ShizZy): ImplementMe 73 app_loader.reset();
74 }
75
76 app_loader = Loader::GetLoader(filepath);
77
78 if (!app_loader) {
79 LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str());
80 return ResultStatus::ErrorGetLoader;
81 }
82
83 boost::optional<u32> system_mode{ app_loader->LoadKernelSystemMode() };
84 if (!system_mode) {
85 LOG_CRITICAL(Core, "Failed to determine system mode!");
86 return ResultStatus::ErrorSystemMode;
87 }
88
89 ResultStatus init_result{ Init(emu_window, system_mode.get()) };
90 if (init_result != ResultStatus::Success) {
91 LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!", init_result);
92 System::Shutdown();
93 return init_result;
94 }
95
96 const Loader::ResultStatus load_result{ app_loader->Load() };
97 if (Loader::ResultStatus::Success != load_result) {
98 LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result);
99 System::Shutdown();
100
101 switch (load_result) {
102 case Loader::ResultStatus::ErrorEncrypted:
103 return ResultStatus::ErrorLoader_ErrorEncrypted;
104 case Loader::ResultStatus::ErrorInvalidFormat:
105 return ResultStatus::ErrorLoader_ErrorInvalidFormat;
106 default:
107 return ResultStatus::ErrorLoader;
108 }
109 }
110 return ResultStatus::Success;
70} 111}
71 112
72/// Initialize the core 113System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
73void Init() { 114 if (app_core) {
115 app_core.reset();
116 }
117
118 Memory::Init();
119
74 if (Settings::values.use_cpu_jit) { 120 if (Settings::values.use_cpu_jit) {
75 g_sys_core = std::make_unique<ARM_Dynarmic>(USER32MODE); 121 app_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
76 g_app_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
77 } else { 122 } else {
78 g_sys_core = std::make_unique<ARM_DynCom>(USER32MODE); 123 app_core = std::make_unique<ARM_DynCom>(USER32MODE);
79 g_app_core = std::make_unique<ARM_DynCom>(USER32MODE); 124 }
125
126 CoreTiming::Init();
127 HW::Init();
128 Kernel::Init(system_mode);
129 HLE::Init();
130 AudioCore::Init();
131 GDBStub::Init();
132
133 if (!VideoCore::Init(emu_window)) {
134 return ResultStatus::ErrorVideoCore;
80 } 135 }
81 136
82 LOG_DEBUG(Core, "Initialized OK"); 137 LOG_DEBUG(Core, "Initialized OK");
138
139 return ResultStatus::Success;
83} 140}
84 141
85void Shutdown() { 142void System::Shutdown() {
86 g_app_core.reset(); 143 GDBStub::Shutdown();
87 g_sys_core.reset(); 144 AudioCore::Shutdown();
145 VideoCore::Shutdown();
146 HLE::Shutdown();
147 Kernel::Shutdown();
148 HW::Shutdown();
149 CoreTiming::Shutdown();
88 150
89 LOG_DEBUG(Core, "Shutdown OK"); 151 LOG_DEBUG(Core, "Shutdown OK");
90} 152}
diff --git a/src/core/core.h b/src/core/core.h
index ffbfa91c3..f4326161d 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -5,11 +5,17 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <string>
9
8#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/memory.h"
9 12
13class EmuWindow;
10class ARM_Interface; 14class ARM_Interface;
11 15
12//////////////////////////////////////////////////////////////////////////////////////////////////// 16namespace Loader {
17class AppLoader;
18}
13 19
14namespace Core { 20namespace Core {
15 21
@@ -24,37 +30,97 @@ struct ThreadContext {
24 u32 fpexc; 30 u32 fpexc;
25}; 31};
26 32
27extern std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core 33class System {
28extern std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core 34public:
29 35 /**
30//////////////////////////////////////////////////////////////////////////////////////////////////// 36 * Gets the instance of the System singleton class.
31 37 * @returns Reference to the instance of the System singleton class.
32/// Start the core 38 */
33void Start(); 39 static System& GetInstance() {
34 40 return s_instance;
35/** 41 }
36 * Run the core CPU loop 42
37 * This function runs the core for the specified number of CPU instructions before trying to update 43 /// Enumeration representing the return values of the System Initialize and Load process.
38 * hardware. This is much faster than SingleStep (and should be equivalent), as the CPU is not 44 enum class ResultStatus : u32 {
39 * required to do a full dispatch with each instruction. NOTE: the number of instructions requested 45 Success, ///< Succeeded
40 * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is 46 ErrorNotInitialized, ///< Error trying to use core prior to initialization
41 * requested (e.g. on a thread switch). 47 ErrorGetLoader, ///< Error finding the correct application loader
42 */ 48 ErrorSystemMode, ///< Error determining the system mode
43void RunLoop(int tight_loop = 1000); 49 ErrorLoader, ///< Error loading the specified application
44 50 ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
45/// Step the CPU one instruction 51 ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an invalid format
46void SingleStep(); 52 ErrorVideoCore, ///< Error in the video core
47 53 };
48/// Halt the core 54
49void Halt(const char* msg); 55 /**
50 56 * Initialize the emulated system.
51/// Kill the core 57 * @param emu_window Pointer to the host-system window used for video output and keyboard input.
52void Stop(); 58 * @param system_mode The system mode.
53 59 * @return ResultStatus code, indicating if the operation succeeded.
54/// Initialize the core 60 */
55void Init(); 61 ResultStatus Init(EmuWindow* emu_window, u32 system_mode);
62
63 /// Start the core
64 void Start();
65
66 /**
67 * Run the core CPU loop
68 * This function runs the core for the specified number of CPU instructions before trying to update
69 * hardware. This is much faster than SingleStep (and should be equivalent), as the CPU is not
70 * required to do a full dispatch with each instruction. NOTE: the number of instructions requested
71 * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is
72 * requested (e.g. on a thread switch).
73 * @param tight_loop Number of instructions to execute.
74 * @return Result status, indicating whethor or not the operation succeeded.
75 */
76 ResultStatus RunLoop(int tight_loop = 1000);
77
78 /**
79 * Step the CPU one instruction
80 * @return Result status, indicating whethor or not the operation succeeded.
81 */
82 ResultStatus SingleStep();
83
84 /// Shutdown the emulated system.
85 void Shutdown();
86
87 /**
88 * Load an executable application.
89 * @param emu_window Pointer to the host-system window used for video output and keyboard input.
90 * @param filepath String path to the executable application to load on the host file system.
91 * @returns ResultStatus code, indicating if the operation succeeded.
92 */
93 ResultStatus Load(EmuWindow* emu_window, const std::string& filepath);
94
95 /**
96 * Indicates if the emulated system is powered on (all subsystems initialized and able to run an
97 * application).
98 * @returns True if the emulated system is powered on, otherwise false.
99 */
100 bool IsPoweredOn() const {
101 return app_core != nullptr;
102 }
103
104 /**
105 * Gets a reference to the emulated AppCore CPU.
106 * @returns A reference to the emulated AppCore CPU.
107 */
108 ARM_Interface& AppCore() {
109 return *app_core;
110 }
111
112private:
113 /// AppLoader used to load the current executing application
114 std::unique_ptr<Loader::AppLoader> app_loader;
115
116 ///< ARM11 application core
117 std::unique_ptr<ARM_Interface> app_core;
118
119 static System s_instance;
120};
56 121
57/// Shutdown the core 122static ARM_Interface& AppCore() {
58void Shutdown(); 123 return System::GetInstance().AppCore();
124}
59 125
60} // namespace 126} // namespace Core
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 5220b55ea..9fe374795 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -130,7 +130,6 @@ int RegisterEvent(const char* name, TimedCallback callback) {
130 130
131static void AntiCrashCallback(u64 userdata, int cycles_late) { 131static void AntiCrashCallback(u64 userdata, int cycles_late) {
132 LOG_CRITICAL(Core_Timing, "Savestate broken: an unregistered event was called."); 132 LOG_CRITICAL(Core_Timing, "Savestate broken: an unregistered event was called.");
133 Core::Halt("invalid timing events");
134} 133}
135 134
136void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callback) { 135void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callback) {
@@ -147,7 +146,7 @@ void UnregisterAllEvents() {
147} 146}
148 147
149void Init() { 148void Init() {
150 Core::g_app_core->down_count = INITIAL_SLICE_LENGTH; 149 Core::AppCore().down_count = INITIAL_SLICE_LENGTH;
151 g_slice_length = INITIAL_SLICE_LENGTH; 150 g_slice_length = INITIAL_SLICE_LENGTH;
152 global_timer = 0; 151 global_timer = 0;
153 idled_cycles = 0; 152 idled_cycles = 0;
@@ -187,7 +186,7 @@ void Shutdown() {
187} 186}
188 187
189u64 GetTicks() { 188u64 GetTicks() {
190 return (u64)global_timer + g_slice_length - Core::g_app_core->down_count; 189 return (u64)global_timer + g_slice_length - Core::AppCore().down_count;
191} 190}
192 191
193u64 GetIdleTicks() { 192u64 GetIdleTicks() {
@@ -461,18 +460,18 @@ void MoveEvents() {
461} 460}
462 461
463void ForceCheck() { 462void ForceCheck() {
464 s64 cycles_executed = g_slice_length - Core::g_app_core->down_count; 463 s64 cycles_executed = g_slice_length - Core::AppCore().down_count;
465 global_timer += cycles_executed; 464 global_timer += cycles_executed;
466 // This will cause us to check for new events immediately. 465 // This will cause us to check for new events immediately.
467 Core::g_app_core->down_count = 0; 466 Core::AppCore().down_count = 0;
468 // But let's not eat a bunch more time in Advance() because of this. 467 // But let's not eat a bunch more time in Advance() because of this.
469 g_slice_length = 0; 468 g_slice_length = 0;
470} 469}
471 470
472void Advance() { 471void Advance() {
473 s64 cycles_executed = g_slice_length - Core::g_app_core->down_count; 472 s64 cycles_executed = g_slice_length - Core::AppCore().down_count;
474 global_timer += cycles_executed; 473 global_timer += cycles_executed;
475 Core::g_app_core->down_count = g_slice_length; 474 Core::AppCore().down_count = g_slice_length;
476 475
477 if (has_ts_events) 476 if (has_ts_events)
478 MoveEvents(); 477 MoveEvents();
@@ -481,7 +480,7 @@ void Advance() {
481 if (!first) { 480 if (!first) {
482 if (g_slice_length < 10000) { 481 if (g_slice_length < 10000) {
483 g_slice_length += 10000; 482 g_slice_length += 10000;
484 Core::g_app_core->down_count += g_slice_length; 483 Core::AppCore().down_count += g_slice_length;
485 } 484 }
486 } else { 485 } else {
487 // Note that events can eat cycles as well. 486 // Note that events can eat cycles as well.
@@ -491,7 +490,7 @@ void Advance() {
491 490
492 const int diff = target - g_slice_length; 491 const int diff = target - g_slice_length;
493 g_slice_length += diff; 492 g_slice_length += diff;
494 Core::g_app_core->down_count += diff; 493 Core::AppCore().down_count += diff;
495 } 494 }
496 if (advance_callback) 495 if (advance_callback)
497 advance_callback(static_cast<int>(cycles_executed)); 496 advance_callback(static_cast<int>(cycles_executed));
@@ -507,12 +506,12 @@ void LogPendingEvents() {
507} 506}
508 507
509void Idle(int max_idle) { 508void Idle(int max_idle) {
510 s64 cycles_down = Core::g_app_core->down_count; 509 s64 cycles_down = Core::AppCore().down_count;
511 if (max_idle != 0 && cycles_down > max_idle) 510 if (max_idle != 0 && cycles_down > max_idle)
512 cycles_down = max_idle; 511 cycles_down = max_idle;
513 512
514 if (first && cycles_down > 0) { 513 if (first && cycles_down > 0) {
515 s64 cycles_executed = g_slice_length - Core::g_app_core->down_count; 514 s64 cycles_executed = g_slice_length - Core::AppCore().down_count;
516 s64 cycles_next_event = first->time - global_timer; 515 s64 cycles_next_event = first->time - global_timer;
517 516
518 if (cycles_next_event < cycles_executed + cycles_down) { 517 if (cycles_next_event < cycles_executed + cycles_down) {
@@ -527,9 +526,9 @@ void Idle(int max_idle) {
527 cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); 526 cycles_down / (float)(g_clock_rate_arm11 * 0.001f));
528 527
529 idled_cycles += cycles_down; 528 idled_cycles += cycles_down;
530 Core::g_app_core->down_count -= cycles_down; 529 Core::AppCore().down_count -= cycles_down;
531 if (Core::g_app_core->down_count == 0) 530 if (Core::AppCore().down_count == 0)
532 Core::g_app_core->down_count = -1; 531 Core::AppCore().down_count = -1;
533} 532}
534 533
535std::string GetScheduledEventsSummary() { 534std::string GetScheduledEventsSummary() {
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index f96cbde64..9acdd402b 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -30,6 +30,7 @@
30#include <unistd.h> 30#include <unistd.h>
31#endif 31#endif
32 32
33#include "core/loader/loader.h"
33#include "common/logging/log.h" 34#include "common/logging/log.h"
34#include "common/string_util.h" 35#include "common/string_util.h"
35#include "core/arm/arm_interface.h" 36#include "core/arm/arm_interface.h"
@@ -450,8 +451,8 @@ static void SendSignal(u32 signal) {
450 latest_signal = signal; 451 latest_signal = signal;
451 452
452 std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15, 453 std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15,
453 htonl(Core::g_app_core->GetPC()), 13, 454 htonl(Core::AppCore().GetPC()), 13,
454 htonl(Core::g_app_core->GetReg(13))); 455 htonl(Core::AppCore().GetReg(13)));
455 LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); 456 LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str());
456 SendReply(buffer.c_str()); 457 SendReply(buffer.c_str());
457} 458}
@@ -538,15 +539,15 @@ static void ReadRegister() {
538 } 539 }
539 540
540 if (id <= R15_REGISTER) { 541 if (id <= R15_REGISTER) {
541 IntToGdbHex(reply, Core::g_app_core->GetReg(id)); 542 IntToGdbHex(reply, Core::AppCore().GetReg(id));
542 } else if (id == CPSR_REGISTER) { 543 } else if (id == CPSR_REGISTER) {
543 IntToGdbHex(reply, Core::g_app_core->GetCPSR()); 544 IntToGdbHex(reply, Core::AppCore().GetCPSR());
544 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { 545 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
545 IntToGdbHex(reply, Core::g_app_core->GetVFPReg( 546 IntToGdbHex(reply, Core::AppCore().GetVFPReg(
546 id - CPSR_REGISTER - 547 id - CPSR_REGISTER -
547 1)); // VFP registers should start at 26, so one after CSPR_REGISTER 548 1)); // VFP registers should start at 26, so one after CSPR_REGISTER
548 } else if (id == FPSCR_REGISTER) { 549 } else if (id == FPSCR_REGISTER) {
549 IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR 550 IntToGdbHex(reply, Core::AppCore().GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR
550 IntToGdbHex(reply + 8, 0); 551 IntToGdbHex(reply + 8, 0);
551 } else { 552 } else {
552 return SendReply("E01"); 553 return SendReply("E01");
@@ -563,22 +564,22 @@ static void ReadRegisters() {
563 u8* bufptr = buffer; 564 u8* bufptr = buffer;
564 565
565 for (int reg = 0; reg <= R15_REGISTER; reg++) { 566 for (int reg = 0; reg <= R15_REGISTER; reg++) {
566 IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetReg(reg)); 567 IntToGdbHex(bufptr + reg * CHAR_BIT, Core::AppCore().GetReg(reg));
567 } 568 }
568 569
569 bufptr += (16 * CHAR_BIT); 570 bufptr += (16 * CHAR_BIT);
570 571
571 IntToGdbHex(bufptr, Core::g_app_core->GetCPSR()); 572 IntToGdbHex(bufptr, Core::AppCore().GetCPSR());
572 573
573 bufptr += CHAR_BIT; 574 bufptr += CHAR_BIT;
574 575
575 for (int reg = 0; reg <= 31; reg++) { 576 for (int reg = 0; reg <= 31; reg++) {
576 IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetVFPReg(reg)); 577 IntToGdbHex(bufptr + reg * CHAR_BIT, Core::AppCore().GetVFPReg(reg));
577 } 578 }
578 579
579 bufptr += (32 * CHAR_BIT); 580 bufptr += (32 * CHAR_BIT);
580 581
581 IntToGdbHex(bufptr, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); 582 IntToGdbHex(bufptr, Core::AppCore().GetVFPSystemReg(VFP_FPSCR));
582 583
583 SendReply(reinterpret_cast<char*>(buffer)); 584 SendReply(reinterpret_cast<char*>(buffer));
584} 585}
@@ -595,13 +596,13 @@ static void WriteRegister() {
595 } 596 }
596 597
597 if (id <= R15_REGISTER) { 598 if (id <= R15_REGISTER) {
598 Core::g_app_core->SetReg(id, GdbHexToInt(buffer_ptr)); 599 Core::AppCore().SetReg(id, GdbHexToInt(buffer_ptr));
599 } else if (id == CPSR_REGISTER) { 600 } else if (id == CPSR_REGISTER) {
600 Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr)); 601 Core::AppCore().SetCPSR(GdbHexToInt(buffer_ptr));
601 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { 602 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
602 Core::g_app_core->SetVFPReg(id - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr)); 603 Core::AppCore().SetVFPReg(id - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr));
603 } else if (id == FPSCR_REGISTER) { 604 } else if (id == FPSCR_REGISTER) {
604 Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr)); 605 Core::AppCore().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr));
605 } else { 606 } else {
606 return SendReply("E01"); 607 return SendReply("E01");
607 } 608 }
@@ -618,20 +619,20 @@ static void WriteRegisters() {
618 619
619 for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) { 620 for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) {
620 if (reg <= R15_REGISTER) { 621 if (reg <= R15_REGISTER) {
621 Core::g_app_core->SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); 622 Core::AppCore().SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
622 } else if (reg == CPSR_REGISTER) { 623 } else if (reg == CPSR_REGISTER) {
623 Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT)); 624 Core::AppCore().SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT));
624 } else if (reg == CPSR_REGISTER - 1) { 625 } else if (reg == CPSR_REGISTER - 1) {
625 // Dummy FPA register, ignore 626 // Dummy FPA register, ignore
626 } else if (reg < CPSR_REGISTER) { 627 } else if (reg < CPSR_REGISTER) {
627 // Dummy FPA registers, ignore 628 // Dummy FPA registers, ignore
628 i += 2; 629 i += 2;
629 } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) { 630 } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) {
630 Core::g_app_core->SetVFPReg(reg - CPSR_REGISTER - 1, 631 Core::AppCore().SetVFPReg(reg - CPSR_REGISTER - 1,
631 GdbHexToInt(buffer_ptr + i * CHAR_BIT)); 632 GdbHexToInt(buffer_ptr + i * CHAR_BIT));
632 i++; // Skip padding 633 i++; // Skip padding
633 } else if (reg == FPSCR_REGISTER) { 634 } else if (reg == FPSCR_REGISTER) {
634 Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); 635 Core::AppCore().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
635 } 636 }
636 } 637 }
637 638
@@ -908,7 +909,7 @@ void ToggleServer(bool status) {
908 server_enabled = status; 909 server_enabled = status;
909 910
910 // Start server 911 // Start server
911 if (!IsConnected() && Core::g_sys_core != nullptr) { 912 if (!IsConnected() && Core::System().GetInstance().IsPoweredOn()) {
912 Init(); 913 Init();
913 } 914 }
914 } else { 915 } else {
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 8ce0f6d2b..0f2a04e30 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -14,7 +14,7 @@
14 14
15namespace HLE { 15namespace HLE {
16 16
17#define PARAM(n) Core::g_app_core->GetReg(n) 17#define PARAM(n) Core::AppCore().GetReg(n)
18 18
19/// An invalid result code that is meant to be overwritten when a thread resumes from waiting 19/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
20static const ResultCode RESULT_INVALID(0xDEADC0DE); 20static const ResultCode RESULT_INVALID(0xDEADC0DE);
@@ -24,7 +24,7 @@ static const ResultCode RESULT_INVALID(0xDEADC0DE);
24 * @param res Result to return 24 * @param res Result to return
25 */ 25 */
26static inline void FuncReturn(u32 res) { 26static inline void FuncReturn(u32 res) {
27 Core::g_app_core->SetReg(0, res); 27 Core::AppCore().SetReg(0, res);
28} 28}
29 29
30/** 30/**
@@ -33,8 +33,8 @@ static inline void FuncReturn(u32 res) {
33 * @todo Verify that this function is correct 33 * @todo Verify that this function is correct
34 */ 34 */
35static inline void FuncReturn64(u64 res) { 35static inline void FuncReturn64(u64 res) {
36 Core::g_app_core->SetReg(0, (u32)(res & 0xFFFFFFFF)); 36 Core::AppCore().SetReg(0, (u32)(res & 0xFFFFFFFF));
37 Core::g_app_core->SetReg(1, (u32)((res >> 32) & 0xFFFFFFFF)); 37 Core::AppCore().SetReg(1, (u32)((res >> 32) & 0xFFFFFFFF));
38} 38}
39 39
40//////////////////////////////////////////////////////////////////////////////////////////////////// 40////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -49,7 +49,7 @@ template <ResultCode func(u32*, u32, u32, u32, u32, u32)>
49void Wrap() { 49void Wrap() {
50 u32 param_1 = 0; 50 u32 param_1 = 0;
51 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; 51 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
52 Core::g_app_core->SetReg(1, param_1); 52 Core::AppCore().SetReg(1, param_1);
53 FuncReturn(retval); 53 FuncReturn(retval);
54} 54}
55 55
@@ -57,7 +57,7 @@ template <ResultCode func(u32*, s32, u32, u32, u32, s32)>
57void Wrap() { 57void Wrap() {
58 u32 param_1 = 0; 58 u32 param_1 = 0;
59 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; 59 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
60 Core::g_app_core->SetReg(1, param_1); 60 Core::AppCore().SetReg(1, param_1);
61 FuncReturn(retval); 61 FuncReturn(retval);
62} 62}
63 63
@@ -69,7 +69,7 @@ void Wrap() {
69 .raw; 69 .raw;
70 70
71 if (retval != RESULT_INVALID.raw) { 71 if (retval != RESULT_INVALID.raw) {
72 Core::g_app_core->SetReg(1, (u32)param_1); 72 Core::AppCore().SetReg(1, (u32)param_1);
73 FuncReturn(retval); 73 FuncReturn(retval);
74 } 74 }
75} 75}
@@ -84,7 +84,7 @@ template <ResultCode func(u32*)>
84void Wrap() { 84void Wrap() {
85 u32 param_1 = 0; 85 u32 param_1 = 0;
86 u32 retval = func(&param_1).raw; 86 u32 retval = func(&param_1).raw;
87 Core::g_app_core->SetReg(1, param_1); 87 Core::AppCore().SetReg(1, param_1);
88 FuncReturn(retval); 88 FuncReturn(retval);
89} 89}
90 90
@@ -102,11 +102,11 @@ void Wrap() {
102 MemoryInfo memory_info = {}; 102 MemoryInfo memory_info = {};
103 PageInfo page_info = {}; 103 PageInfo page_info = {};
104 u32 retval = func(&memory_info, &page_info, PARAM(2)).raw; 104 u32 retval = func(&memory_info, &page_info, PARAM(2)).raw;
105 Core::g_app_core->SetReg(1, memory_info.base_address); 105 Core::AppCore().SetReg(1, memory_info.base_address);
106 Core::g_app_core->SetReg(2, memory_info.size); 106 Core::AppCore().SetReg(2, memory_info.size);
107 Core::g_app_core->SetReg(3, memory_info.permission); 107 Core::AppCore().SetReg(3, memory_info.permission);
108 Core::g_app_core->SetReg(4, memory_info.state); 108 Core::AppCore().SetReg(4, memory_info.state);
109 Core::g_app_core->SetReg(5, page_info.flags); 109 Core::AppCore().SetReg(5, page_info.flags);
110 FuncReturn(retval); 110 FuncReturn(retval);
111} 111}
112 112
@@ -115,11 +115,11 @@ void Wrap() {
115 MemoryInfo memory_info = {}; 115 MemoryInfo memory_info = {};
116 PageInfo page_info = {}; 116 PageInfo page_info = {};
117 u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw; 117 u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw;
118 Core::g_app_core->SetReg(1, memory_info.base_address); 118 Core::AppCore().SetReg(1, memory_info.base_address);
119 Core::g_app_core->SetReg(2, memory_info.size); 119 Core::AppCore().SetReg(2, memory_info.size);
120 Core::g_app_core->SetReg(3, memory_info.permission); 120 Core::AppCore().SetReg(3, memory_info.permission);
121 Core::g_app_core->SetReg(4, memory_info.state); 121 Core::AppCore().SetReg(4, memory_info.state);
122 Core::g_app_core->SetReg(5, page_info.flags); 122 Core::AppCore().SetReg(5, page_info.flags);
123 FuncReturn(retval); 123 FuncReturn(retval);
124} 124}
125 125
@@ -127,7 +127,7 @@ template <ResultCode func(s32*, u32)>
127void Wrap() { 127void Wrap() {
128 s32 param_1 = 0; 128 s32 param_1 = 0;
129 u32 retval = func(&param_1, PARAM(1)).raw; 129 u32 retval = func(&param_1, PARAM(1)).raw;
130 Core::g_app_core->SetReg(1, param_1); 130 Core::AppCore().SetReg(1, param_1);
131 FuncReturn(retval); 131 FuncReturn(retval);
132} 132}
133 133
@@ -140,7 +140,7 @@ template <ResultCode func(u32*, u32)>
140void Wrap() { 140void Wrap() {
141 u32 param_1 = 0; 141 u32 param_1 = 0;
142 u32 retval = func(&param_1, PARAM(1)).raw; 142 u32 retval = func(&param_1, PARAM(1)).raw;
143 Core::g_app_core->SetReg(1, param_1); 143 Core::AppCore().SetReg(1, param_1);
144 FuncReturn(retval); 144 FuncReturn(retval);
145} 145}
146 146
@@ -160,7 +160,7 @@ template <ResultCode func(u32*, const char*)>
160void Wrap() { 160void Wrap() {
161 u32 param_1 = 0; 161 u32 param_1 = 0;
162 u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw; 162 u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw;
163 Core::g_app_core->SetReg(1, param_1); 163 Core::AppCore().SetReg(1, param_1);
164 FuncReturn(retval); 164 FuncReturn(retval);
165} 165}
166 166
@@ -168,7 +168,7 @@ template <ResultCode func(u32*, s32, s32)>
168void Wrap() { 168void Wrap() {
169 u32 param_1 = 0; 169 u32 param_1 = 0;
170 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 170 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
171 Core::g_app_core->SetReg(1, param_1); 171 Core::AppCore().SetReg(1, param_1);
172 FuncReturn(retval); 172 FuncReturn(retval);
173} 173}
174 174
@@ -176,7 +176,7 @@ template <ResultCode func(s32*, u32, s32)>
176void Wrap() { 176void Wrap() {
177 s32 param_1 = 0; 177 s32 param_1 = 0;
178 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 178 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
179 Core::g_app_core->SetReg(1, param_1); 179 Core::AppCore().SetReg(1, param_1);
180 FuncReturn(retval); 180 FuncReturn(retval);
181} 181}
182 182
@@ -184,8 +184,8 @@ template <ResultCode func(s64*, u32, s32)>
184void Wrap() { 184void Wrap() {
185 s64 param_1 = 0; 185 s64 param_1 = 0;
186 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 186 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
187 Core::g_app_core->SetReg(1, (u32)param_1); 187 Core::AppCore().SetReg(1, (u32)param_1);
188 Core::g_app_core->SetReg(2, (u32)(param_1 >> 32)); 188 Core::AppCore().SetReg(2, (u32)(param_1 >> 32));
189 FuncReturn(retval); 189 FuncReturn(retval);
190} 190}
191 191
@@ -194,7 +194,7 @@ void Wrap() {
194 u32 param_1 = 0; 194 u32 param_1 = 0;
195 // The last parameter is passed in R0 instead of R4 195 // The last parameter is passed in R0 instead of R4
196 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw; 196 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw;
197 Core::g_app_core->SetReg(1, param_1); 197 Core::AppCore().SetReg(1, param_1);
198 FuncReturn(retval); 198 FuncReturn(retval);
199} 199}
200 200
@@ -209,8 +209,8 @@ template <ResultCode func(s64*, Handle, u32)>
209void Wrap() { 209void Wrap() {
210 s64 param_1 = 0; 210 s64 param_1 = 0;
211 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 211 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
212 Core::g_app_core->SetReg(1, (u32)param_1); 212 Core::AppCore().SetReg(1, (u32)param_1);
213 Core::g_app_core->SetReg(2, (u32)(param_1 >> 32)); 213 Core::AppCore().SetReg(2, (u32)(param_1 >> 32));
214 FuncReturn(retval); 214 FuncReturn(retval);
215} 215}
216 216
@@ -227,8 +227,8 @@ void Wrap() {
227 reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)) 227 reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3))
228 .raw; 228 .raw;
229 // The first out parameter is moved into R2 and the second is moved into R1. 229 // The first out parameter is moved into R2 and the second is moved into R1.
230 Core::g_app_core->SetReg(1, param_2); 230 Core::AppCore().SetReg(1, param_2);
231 Core::g_app_core->SetReg(2, param_1); 231 Core::AppCore().SetReg(2, param_1);
232 FuncReturn(retval); 232 FuncReturn(retval);
233} 233}
234 234
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 41b772163..d73d98a70 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -26,9 +26,9 @@ void Reschedule(const char* reason) {
26 // routines. This simulates that time by artificially advancing the number of CPU "ticks". 26 // routines. This simulates that time by artificially advancing the number of CPU "ticks".
27 // The value was chosen empirically, it seems to work well enough for everything tested, but 27 // The value was chosen empirically, it seems to work well enough for everything tested, but
28 // is likely not ideal. We should find a more accurate way to simulate timing with HLE. 28 // is likely not ideal. We should find a more accurate way to simulate timing with HLE.
29 Core::g_app_core->AddTicks(4000); 29 Core::AppCore().AddTicks(4000);
30 30
31 Core::g_app_core->PrepareReschedule(); 31 Core::AppCore().PrepareReschedule();
32 32
33 reschedule = true; 33 reschedule = true;
34} 34}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 18b696f72..91c05fc42 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -188,7 +188,7 @@ static void SwitchContext(Thread* new_thread) {
188 // Save context for previous thread 188 // Save context for previous thread
189 if (previous_thread) { 189 if (previous_thread) {
190 previous_thread->last_running_ticks = CoreTiming::GetTicks(); 190 previous_thread->last_running_ticks = CoreTiming::GetTicks();
191 Core::g_app_core->SaveContext(previous_thread->context); 191 Core::AppCore().SaveContext(previous_thread->context);
192 192
193 if (previous_thread->status == THREADSTATUS_RUNNING) { 193 if (previous_thread->status == THREADSTATUS_RUNNING) {
194 // This is only the case when a reschedule is triggered without the current thread 194 // This is only the case when a reschedule is triggered without the current thread
@@ -214,8 +214,8 @@ static void SwitchContext(Thread* new_thread) {
214 // Restores thread to its nominal priority if it has been temporarily changed 214 // Restores thread to its nominal priority if it has been temporarily changed
215 new_thread->current_priority = new_thread->nominal_priority; 215 new_thread->current_priority = new_thread->nominal_priority;
216 216
217 Core::g_app_core->LoadContext(new_thread->context); 217 Core::AppCore().LoadContext(new_thread->context);
218 Core::g_app_core->SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); 218 Core::AppCore().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress());
219 } else { 219 } else {
220 current_thread = nullptr; 220 current_thread = nullptr;
221 } 221 }
diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp
index 9e5d6a318..614f16d44 100644
--- a/src/core/hle/service/ldr_ro/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp
@@ -457,7 +457,7 @@ static void LoadCRO(Interface* self, bool link_on_load_bug_fix) {
457 } 457 }
458 } 458 }
459 459
460 Core::g_app_core->ClearInstructionCache(); 460 Core::AppCore().ClearInstructionCache();
461 461
462 LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(), 462 LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(),
463 cro_address, cro_address + fix_size); 463 cro_address, cro_address + fix_size);
@@ -562,7 +562,7 @@ static void UnloadCRO(Interface* self) {
562 memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr); 562 memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr);
563 } 563 }
564 564
565 Core::g_app_core->ClearInstructionCache(); 565 Core::AppCore().ClearInstructionCache();
566 566
567 cmd_buff[1] = result.raw; 567 cmd_buff[1] = result.raw;
568} 568}
@@ -624,7 +624,7 @@ static void LinkCRO(Interface* self) {
624 } 624 }
625 625
626 memory_synchronizer.SynchronizeOriginalMemory(); 626 memory_synchronizer.SynchronizeOriginalMemory();
627 Core::g_app_core->ClearInstructionCache(); 627 Core::AppCore().ClearInstructionCache();
628 628
629 cmd_buff[1] = result.raw; 629 cmd_buff[1] = result.raw;
630} 630}
@@ -686,7 +686,7 @@ static void UnlinkCRO(Interface* self) {
686 } 686 }
687 687
688 memory_synchronizer.SynchronizeOriginalMemory(); 688 memory_synchronizer.SynchronizeOriginalMemory();
689 Core::g_app_core->ClearInstructionCache(); 689 Core::AppCore().ClearInstructionCache();
690 690
691 cmd_buff[1] = result.raw; 691 cmd_buff[1] = result.raw;
692} 692}
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 5839d7230..b20f2aaa4 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -582,7 +582,7 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point
582 582
583/// Called when a thread exits 583/// Called when a thread exits
584static void ExitThread() { 584static void ExitThread() {
585 LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); 585 LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::AppCore().GetPC());
586 586
587 Kernel::ExitCurrentThread(); 587 Kernel::ExitCurrentThread();
588} 588}
@@ -612,7 +612,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
612 using Kernel::Mutex; 612 using Kernel::Mutex;
613 613
614 SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0); 614 SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0);
615 mutex->name = Common::StringFromFormat("mutex-%08x", Core::g_app_core->GetReg(14)); 615 mutex->name = Common::StringFromFormat("mutex-%08x", Core::AppCore().GetReg(14));
616 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); 616 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
617 617
618 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 618 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
@@ -683,7 +683,7 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max
683 using Kernel::Semaphore; 683 using Kernel::Semaphore;
684 684
685 CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count)); 685 CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count));
686 semaphore->name = Common::StringFromFormat("semaphore-%08x", Core::g_app_core->GetReg(14)); 686 semaphore->name = Common::StringFromFormat("semaphore-%08x", Core::AppCore().GetReg(14));
687 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); 687 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
688 688
689 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 689 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
@@ -740,7 +740,7 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
740 using Kernel::Event; 740 using Kernel::Event;
741 741
742 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); 742 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type));
743 evt->name = Common::StringFromFormat("event-%08x", Core::g_app_core->GetReg(14)); 743 evt->name = Common::StringFromFormat("event-%08x", Core::AppCore().GetReg(14));
744 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); 744 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
745 745
746 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, 746 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
@@ -787,7 +787,7 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
787 using Kernel::Timer; 787 using Kernel::Timer;
788 788
789 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); 789 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type));
790 timer->name = Common::StringFromFormat("timer-%08x", Core::g_app_core->GetReg(14)); 790 timer->name = Common::StringFromFormat("timer-%08x", Core::AppCore().GetReg(14));
791 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); 791 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
792 792
793 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, 793 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
@@ -854,7 +854,7 @@ static void SleepThread(s64 nanoseconds) {
854static s64 GetSystemTick() { 854static s64 GetSystemTick() {
855 s64 result = CoreTiming::GetTicks(); 855 s64 result = CoreTiming::GetTicks();
856 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. 856 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end.
857 Core::g_app_core->AddTicks( 857 Core::AppCore().AddTicks(
858 150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b 858 150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b
859 return result; 859 return result;
860} 860}
diff --git a/src/core/system.cpp b/src/core/system.cpp
deleted file mode 100644
index fa8bd0317..000000000
--- a/src/core/system.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "audio_core/audio_core.h"
6#include "core/core.h"
7#include "core/core_timing.h"
8#include "core/gdbstub/gdbstub.h"
9#include "core/hle/hle.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/memory.h"
12#include "core/hw/hw.h"
13#include "core/system.h"
14#include "video_core/video_core.h"
15
16namespace Core {
17
18/*static*/ System System::s_instance;
19
20System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
21 Core::Init();
22 CoreTiming::Init();
23 Memory::Init();
24 HW::Init();
25 Kernel::Init(system_mode);
26 HLE::Init();
27 AudioCore::Init();
28 GDBStub::Init();
29
30 if (!VideoCore::Init(emu_window)) {
31 return ResultStatus::ErrorVideoCore;
32 }
33
34 is_powered_on = true;
35
36 return ResultStatus::Success;
37}
38
39void System::Shutdown() {
40 GDBStub::Shutdown();
41 AudioCore::Shutdown();
42 VideoCore::Shutdown();
43 HLE::Shutdown();
44 Kernel::Shutdown();
45 HW::Shutdown();
46 CoreTiming::Shutdown();
47 Core::Shutdown();
48
49 is_powered_on = false;
50}
51
52System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
53 state.app_loader = Loader::GetLoader(filepath);
54
55 if (!state.app_loader) {
56 LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str());
57 return ResultStatus::ErrorGetLoader;
58 }
59
60 boost::optional<u32> system_mode{ state.app_loader->LoadKernelSystemMode() };
61 if (!system_mode) {
62 LOG_CRITICAL(Frontend, "Failed to determine system mode!");
63 return ResultStatus::ErrorSystemMode;
64 }
65
66 ResultStatus init_result{ Init(emu_window, system_mode.get()) };
67 if (init_result != ResultStatus::Success) {
68 LOG_CRITICAL(Frontend, "Failed to initialize system (Error %i)!", init_result);
69 System::Shutdown();
70 return init_result;
71 }
72
73 const Loader::ResultStatus load_result{ state.app_loader->Load() };
74 if (Loader::ResultStatus::Success != load_result) {
75 LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result);
76 System::Shutdown();
77
78 switch (load_result) {
79 case Loader::ResultStatus::ErrorEncrypted:
80 return ResultStatus::ErrorLoader_ErrorEncrypted;
81 case Loader::ResultStatus::ErrorInvalidFormat:
82 return ResultStatus::ErrorLoader_ErrorInvalidFormat;
83 default:
84 return ResultStatus::ErrorLoader;
85 }
86 }
87 return ResultStatus::Success;
88}
89
90} // namespace Core
diff --git a/src/core/system.h b/src/core/system.h
deleted file mode 100644
index 192a9c447..000000000
--- a/src/core/system.h
+++ /dev/null
@@ -1,83 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string>
8
9#include "core/loader/loader.h"
10
11class EmuWindow;
12
13namespace Core {
14
15class System {
16public:
17 struct State {
18 std::unique_ptr<Loader::AppLoader> app_loader;
19 };
20
21 /**
22 * Gets the instance of the System singleton class.
23 * @returns Reference to the instance of the System singleton class.
24 */
25 static System& GetInstance() {
26 return s_instance;
27 }
28
29 /// Enumeration representing the return values of the System Initialize and Load process.
30 enum class ResultStatus : u32 {
31 Success, ///< Succeeded
32 ErrorGetLoader, ///< Error finding the correct application loader
33 ErrorSystemMode, ///< Error determining the system mode
34 ErrorLoader, ///< Error loading the specified application
35 ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
36 ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an invalid format
37 ErrorVideoCore, ///< Error in the video core
38 };
39
40 /**
41 * Initialize the emulated system.
42 * @param emu_window Pointer to the host-system window used for video output and keyboard input.
43 * @param system_mode The system mode.
44 * @returns ResultStatus code, indicating if the operation succeeded.
45 */
46 ResultStatus Init(EmuWindow* emu_window, u32 system_mode);
47
48 /// Shutdown the emulated system.
49 void Shutdown();
50
51 /**
52 * Load an executable application.
53 * @param emu_window Pointer to the host-system window used for video output and keyboard input.
54 * @param filepath String path to the executable application to load on the host file system.
55 * @returns ResultStatus code, indicating if the operation succeeded.
56 */
57 ResultStatus Load(EmuWindow* emu_window, const std::string& filepath);
58
59 /**
60 * Indicates if the emulated system is powered on (all subsystems initialized and able to run an
61 * application).
62 * @returns True if the emulated system is powered on, otherwise false.
63 */
64 bool IsPoweredOn() const {
65 return is_powered_on;
66 }
67
68 /**
69 * Gets the internal state of the emulated system.
70 * @returns The internal state of the emulated system
71 */
72 State& GetState() {
73 return state;
74 }
75
76private:
77 bool is_powered_on{};
78 State state;
79
80 static System s_instance;
81};
82
83} // namespace Core