mirror of
https://gitlab.com/suyu-emu/suyu.git
synced 2024-03-15 23:15:44 +00:00
core: Consolidate core and system state, remove system module & cleanups.
This commit is contained in:
parent
707cc66362
commit
232ef55c1a
|
@ -33,7 +33,6 @@
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/system.h"
|
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
static void PrintHelp(const char* argv0) {
|
static void PrintHelp(const char* argv0) {
|
||||||
|
@ -145,7 +144,7 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (emu_window->IsOpen()) {
|
while (emu_window->IsOpen()) {
|
||||||
Core::RunLoop();
|
system.RunLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/settings.h"
|
|
||||||
#include "core/system.h"
|
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
#include "video_core/debug_utils/debug_utils.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
|
@ -38,7 +36,7 @@ void EmuThread::run() {
|
||||||
if (!was_active)
|
if (!was_active)
|
||||||
emit DebugModeLeft();
|
emit DebugModeLeft();
|
||||||
|
|
||||||
Core::RunLoop();
|
Core::System::GetInstance().RunLoop();
|
||||||
|
|
||||||
was_active = running || exec_step;
|
was_active = running || exec_step;
|
||||||
if (!was_active && !stop_run)
|
if (!was_active && !stop_run)
|
||||||
|
@ -48,7 +46,7 @@ void EmuThread::run() {
|
||||||
emit DebugModeLeft();
|
emit DebugModeLeft();
|
||||||
|
|
||||||
exec_step = false;
|
exec_step = false;
|
||||||
Core::SingleStep();
|
Core::System::GetInstance().SingleStep();
|
||||||
emit DebugModeEntered();
|
emit DebugModeEntered();
|
||||||
yieldCurrentThread();
|
yieldCurrentThread();
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
#include "citra_qt/configure_general.h"
|
#include "citra_qt/configure_general.h"
|
||||||
#include "citra_qt/ui_settings.h"
|
#include "citra_qt/ui_settings.h"
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/system.h"
|
|
||||||
#include "ui_configure_general.h"
|
#include "ui_configure_general.h"
|
||||||
|
|
||||||
ConfigureGeneral::ConfigureGeneral(QWidget* parent)
|
ConfigureGeneral::ConfigureGeneral(QWidget* parent)
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "citra_qt/configure_graphics.h"
|
#include "citra_qt/configure_graphics.h"
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/system.h"
|
|
||||||
#include "ui_configure_graphics.h"
|
#include "ui_configure_graphics.h"
|
||||||
|
|
||||||
ConfigureGraphics::ConfigureGraphics(QWidget* parent)
|
ConfigureGraphics::ConfigureGraphics(QWidget* parent)
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "citra_qt/ui_settings.h"
|
#include "citra_qt/ui_settings.h"
|
||||||
#include "core/hle/service/cfg/cfg.h"
|
#include "core/hle/service/cfg/cfg.h"
|
||||||
#include "core/hle/service/fs/archive.h"
|
#include "core/hle/service/fs/archive.h"
|
||||||
#include "core/system.h"
|
|
||||||
#include "ui_configure_system.h"
|
#include "ui_configure_system.h"
|
||||||
|
|
||||||
static const std::array<int, 12> days_in_month = {{
|
static const std::array<int, 12> days_in_month = {{
|
||||||
|
|
|
@ -25,7 +25,7 @@ CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) {
|
||||||
|
|
||||||
void CallstackWidget::OnDebugModeEntered() {
|
void CallstackWidget::OnDebugModeEntered() {
|
||||||
// Stack pointer
|
// Stack pointer
|
||||||
const u32 sp = Core::g_app_core->GetReg(13);
|
const u32 sp = Core::AppCore().GetReg(13);
|
||||||
|
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
|
|
|
@ -185,13 +185,13 @@ DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblerWidget::Init() {
|
void DisassemblerWidget::Init() {
|
||||||
model->ParseFromAddress(Core::g_app_core->GetPC());
|
model->ParseFromAddress(Core::AppCore().GetPC());
|
||||||
|
|
||||||
disasm_ui.treeView->resizeColumnToContents(0);
|
disasm_ui.treeView->resizeColumnToContents(0);
|
||||||
disasm_ui.treeView->resizeColumnToContents(1);
|
disasm_ui.treeView->resizeColumnToContents(1);
|
||||||
disasm_ui.treeView->resizeColumnToContents(2);
|
disasm_ui.treeView->resizeColumnToContents(2);
|
||||||
|
|
||||||
QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::g_app_core->GetPC());
|
QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::AppCore().GetPC());
|
||||||
disasm_ui.treeView->scrollTo(model_index);
|
disasm_ui.treeView->scrollTo(model_index);
|
||||||
disasm_ui.treeView->selectionModel()->setCurrentIndex(
|
disasm_ui.treeView->selectionModel()->setCurrentIndex(
|
||||||
model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||||
|
@ -214,8 +214,8 @@ void DisassemblerWidget::OnPause() {
|
||||||
emu_thread->SetRunning(false);
|
emu_thread->SetRunning(false);
|
||||||
|
|
||||||
// TODO: By now, the CPU might not have actually stopped...
|
// TODO: By now, the CPU might not have actually stopped...
|
||||||
if (Core::g_app_core) {
|
if (Core::System::GetInstance().IsPoweredOn()) {
|
||||||
model->SetNextInstruction(Core::g_app_core->GetPC());
|
model->SetNextInstruction(Core::AppCore().GetPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ void DisassemblerWidget::OnToggleStartStop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblerWidget::OnDebugModeEntered() {
|
void DisassemblerWidget::OnDebugModeEntered() {
|
||||||
u32 next_instr = Core::g_app_core->GetPC();
|
u32 next_instr = Core::AppCore().GetPC();
|
||||||
|
|
||||||
if (model->GetBreakPoints().IsAddressBreakPoint(next_instr))
|
if (model->GetBreakPoints().IsAddressBreakPoint(next_instr))
|
||||||
emu_thread->SetRunning(false);
|
emu_thread->SetRunning(false);
|
||||||
|
|
|
@ -58,16 +58,16 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegistersWidget::OnDebugModeEntered() {
|
void RegistersWidget::OnDebugModeEntered() {
|
||||||
if (!Core::g_app_core)
|
if (!Core::System::GetInstance().IsPoweredOn())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < core_registers->childCount(); ++i)
|
for (int i = 0; i < core_registers->childCount(); ++i)
|
||||||
core_registers->child(i)->setText(
|
core_registers->child(i)->setText(
|
||||||
1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0')));
|
1, QString("0x%1").arg(Core::AppCore().GetReg(i), 8, 16, QLatin1Char('0')));
|
||||||
|
|
||||||
for (int i = 0; i < vfp_registers->childCount(); ++i)
|
for (int i = 0; i < vfp_registers->childCount(); ++i)
|
||||||
vfp_registers->child(i)->setText(
|
vfp_registers->child(i)->setText(
|
||||||
1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0')));
|
1, QString("0x%1").arg(Core::AppCore().GetVFPReg(i), 8, 16, QLatin1Char('0')));
|
||||||
|
|
||||||
UpdateCPSRValues();
|
UpdateCPSRValues();
|
||||||
UpdateVFPSystemRegisterValues();
|
UpdateVFPSystemRegisterValues();
|
||||||
|
@ -127,7 +127,7 @@ void RegistersWidget::CreateCPSRChildren() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegistersWidget::UpdateCPSRValues() {
|
void RegistersWidget::UpdateCPSRValues() {
|
||||||
const u32 cpsr_val = Core::g_app_core->GetCPSR();
|
const u32 cpsr_val = Core::AppCore().GetCPSR();
|
||||||
|
|
||||||
cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
|
cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
|
||||||
cpsr->child(0)->setText(
|
cpsr->child(0)->setText(
|
||||||
|
@ -191,10 +191,10 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegistersWidget::UpdateVFPSystemRegisterValues() {
|
void RegistersWidget::UpdateVFPSystemRegisterValues() {
|
||||||
const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR);
|
const u32 fpscr_val = Core::AppCore().GetVFPSystemReg(VFP_FPSCR);
|
||||||
const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC);
|
const u32 fpexc_val = Core::AppCore().GetVFPSystemReg(VFP_FPEXC);
|
||||||
const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST);
|
const u32 fpinst_val = Core::AppCore().GetVFPSystemReg(VFP_FPINST);
|
||||||
const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2);
|
const u32 fpinst2_val = Core::AppCore().GetVFPSystemReg(VFP_FPINST2);
|
||||||
|
|
||||||
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
|
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
|
||||||
fpscr->setText(1, QString("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));
|
fpscr->setText(1, QString("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));
|
||||||
|
|
|
@ -391,7 +391,7 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitTreeWidget::OnDebugModeEntered() {
|
void WaitTreeWidget::OnDebugModeEntered() {
|
||||||
if (!Core::g_app_core)
|
if (!Core::System::GetInstance().IsPoweredOn())
|
||||||
return;
|
return;
|
||||||
model->InitItems();
|
model->InitItems();
|
||||||
view->setModel(model);
|
view->setModel(model);
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/system.h"
|
|
||||||
#include "qhexedit.h"
|
#include "qhexedit.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,6 @@ set(SRCS
|
||||||
tracer/recorder.cpp
|
tracer/recorder.cpp
|
||||||
memory.cpp
|
memory.cpp
|
||||||
settings.cpp
|
settings.cpp
|
||||||
system.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
|
@ -325,7 +324,6 @@ set(HEADERS
|
||||||
memory_setup.h
|
memory_setup.h
|
||||||
mmio.h
|
mmio.h
|
||||||
settings.h
|
settings.h
|
||||||
system.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(../../externals/dynarmic/include)
|
include_directories(../../externals/dynarmic/include)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "audio_core/audio_core.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||||
|
@ -11,17 +13,23 @@
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
#include "core/hle/hle.h"
|
#include "core/hle/hle.h"
|
||||||
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
#include "core/hle/kernel/memory.h"
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
#include "core/hw/hw.h"
|
#include "core/hw/hw.h"
|
||||||
|
#include "core/loader/loader.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core
|
/*static*/ System System::s_instance;
|
||||||
std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core
|
|
||||||
|
System::ResultStatus System::RunLoop(int tight_loop) {
|
||||||
|
if (!app_core) {
|
||||||
|
return ResultStatus::ErrorNotInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
/// Run the core CPU loop
|
|
||||||
void RunLoop(int tight_loop) {
|
|
||||||
if (GDBStub::IsServerEnabled()) {
|
if (GDBStub::IsServerEnabled()) {
|
||||||
GDBStub::HandlePacket();
|
GDBStub::HandlePacket();
|
||||||
|
|
||||||
|
@ -32,7 +40,7 @@ void RunLoop(int tight_loop) {
|
||||||
GDBStub::SetCpuStepFlag(false);
|
GDBStub::SetCpuStepFlag(false);
|
||||||
tight_loop = 1;
|
tight_loop = 1;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return ResultStatus::Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,46 +53,100 @@ void RunLoop(int tight_loop) {
|
||||||
CoreTiming::Advance();
|
CoreTiming::Advance();
|
||||||
HLE::Reschedule(__func__);
|
HLE::Reschedule(__func__);
|
||||||
} else {
|
} else {
|
||||||
g_app_core->Run(tight_loop);
|
app_core->Run(tight_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
HW::Update();
|
HW::Update();
|
||||||
if (HLE::IsReschedulePending()) {
|
if (HLE::IsReschedulePending()) {
|
||||||
Kernel::Reschedule();
|
Kernel::Reschedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Step the CPU one instruction
|
System::ResultStatus System::SingleStep() {
|
||||||
void SingleStep() {
|
return RunLoop(1);
|
||||||
RunLoop(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Halt the core
|
System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
|
||||||
void Halt(const char* msg) {
|
if (app_loader) {
|
||||||
// TODO(ShizZy): ImplementMe
|
app_loader.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
app_loader = Loader::GetLoader(filepath);
|
||||||
|
|
||||||
|
if (!app_loader) {
|
||||||
|
LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str());
|
||||||
|
return ResultStatus::ErrorGetLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<u32> system_mode{ app_loader->LoadKernelSystemMode() };
|
||||||
|
if (!system_mode) {
|
||||||
|
LOG_CRITICAL(Core, "Failed to determine system mode!");
|
||||||
|
return ResultStatus::ErrorSystemMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultStatus init_result{ Init(emu_window, system_mode.get()) };
|
||||||
|
if (init_result != ResultStatus::Success) {
|
||||||
|
LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!", init_result);
|
||||||
|
System::Shutdown();
|
||||||
|
return init_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Loader::ResultStatus load_result{ app_loader->Load() };
|
||||||
|
if (Loader::ResultStatus::Success != load_result) {
|
||||||
|
LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result);
|
||||||
|
System::Shutdown();
|
||||||
|
|
||||||
|
switch (load_result) {
|
||||||
|
case Loader::ResultStatus::ErrorEncrypted:
|
||||||
|
return ResultStatus::ErrorLoader_ErrorEncrypted;
|
||||||
|
case Loader::ResultStatus::ErrorInvalidFormat:
|
||||||
|
return ResultStatus::ErrorLoader_ErrorInvalidFormat;
|
||||||
|
default:
|
||||||
|
return ResultStatus::ErrorLoader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Kill the core
|
System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
|
||||||
void Stop() {
|
if (app_core) {
|
||||||
// TODO(ShizZy): ImplementMe
|
app_core.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Memory::Init();
|
||||||
|
|
||||||
/// Initialize the core
|
|
||||||
void Init() {
|
|
||||||
if (Settings::values.use_cpu_jit) {
|
if (Settings::values.use_cpu_jit) {
|
||||||
g_sys_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
|
app_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
|
||||||
g_app_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
|
|
||||||
} else {
|
} else {
|
||||||
g_sys_core = std::make_unique<ARM_DynCom>(USER32MODE);
|
app_core = std::make_unique<ARM_DynCom>(USER32MODE);
|
||||||
g_app_core = std::make_unique<ARM_DynCom>(USER32MODE);
|
}
|
||||||
|
|
||||||
|
CoreTiming::Init();
|
||||||
|
HW::Init();
|
||||||
|
Kernel::Init(system_mode);
|
||||||
|
HLE::Init();
|
||||||
|
AudioCore::Init();
|
||||||
|
GDBStub::Init();
|
||||||
|
|
||||||
|
if (!VideoCore::Init(emu_window)) {
|
||||||
|
return ResultStatus::ErrorVideoCore;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG(Core, "Initialized OK");
|
LOG_DEBUG(Core, "Initialized OK");
|
||||||
|
|
||||||
|
return ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown() {
|
void System::Shutdown() {
|
||||||
g_app_core.reset();
|
GDBStub::Shutdown();
|
||||||
g_sys_core.reset();
|
AudioCore::Shutdown();
|
||||||
|
VideoCore::Shutdown();
|
||||||
|
HLE::Shutdown();
|
||||||
|
Kernel::Shutdown();
|
||||||
|
HW::Shutdown();
|
||||||
|
CoreTiming::Shutdown();
|
||||||
|
|
||||||
LOG_DEBUG(Core, "Shutdown OK");
|
LOG_DEBUG(Core, "Shutdown OK");
|
||||||
}
|
}
|
||||||
|
|
120
src/core/core.h
120
src/core/core.h
|
@ -5,11 +5,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "common/common_types.h"
|
#include <string>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/memory.h"
|
||||||
|
|
||||||
|
class EmuWindow;
|
||||||
class ARM_Interface;
|
class ARM_Interface;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
namespace Loader {
|
||||||
|
class AppLoader;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
|
@ -24,37 +30,97 @@ struct ThreadContext {
|
||||||
u32 fpexc;
|
u32 fpexc;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core
|
class System {
|
||||||
extern std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core
|
public:
|
||||||
|
/**
|
||||||
|
* Gets the instance of the System singleton class.
|
||||||
|
* @returns Reference to the instance of the System singleton class.
|
||||||
|
*/
|
||||||
|
static System& GetInstance() {
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
/// Enumeration representing the return values of the System Initialize and Load process.
|
||||||
|
enum class ResultStatus : u32 {
|
||||||
|
Success, ///< Succeeded
|
||||||
|
ErrorNotInitialized, ///< Error trying to use core prior to initialization
|
||||||
|
ErrorGetLoader, ///< Error finding the correct application loader
|
||||||
|
ErrorSystemMode, ///< Error determining the system mode
|
||||||
|
ErrorLoader, ///< Error loading the specified application
|
||||||
|
ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
|
||||||
|
ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an invalid format
|
||||||
|
ErrorVideoCore, ///< Error in the video core
|
||||||
|
};
|
||||||
|
|
||||||
/// Start the core
|
/**
|
||||||
void Start();
|
* Initialize the emulated system.
|
||||||
|
* @param emu_window Pointer to the host-system window used for video output and keyboard input.
|
||||||
|
* @param system_mode The system mode.
|
||||||
|
* @return ResultStatus code, indicating if the operation succeeded.
|
||||||
|
*/
|
||||||
|
ResultStatus Init(EmuWindow* emu_window, u32 system_mode);
|
||||||
|
|
||||||
/**
|
/// Start the core
|
||||||
* Run the core CPU loop
|
void Start();
|
||||||
* This function runs the core for the specified number of CPU instructions before trying to update
|
|
||||||
* hardware. This is much faster than SingleStep (and should be equivalent), as the CPU is not
|
|
||||||
* required to do a full dispatch with each instruction. NOTE: the number of instructions requested
|
|
||||||
* is not guaranteed to run, as this will be interrupted preemptively if a hardware update is
|
|
||||||
* requested (e.g. on a thread switch).
|
|
||||||
*/
|
|
||||||
void RunLoop(int tight_loop = 1000);
|
|
||||||
|
|
||||||
/// Step the CPU one instruction
|
/**
|
||||||
void SingleStep();
|
* Run the core CPU loop
|
||||||
|
* This function runs the core for the specified number of CPU instructions before trying to update
|
||||||
|
* hardware. This is much faster than SingleStep (and should be equivalent), as the CPU is not
|
||||||
|
* required to do a full dispatch with each instruction. NOTE: the number of instructions requested
|
||||||
|
* is not guaranteed to run, as this will be interrupted preemptively if a hardware update is
|
||||||
|
* requested (e.g. on a thread switch).
|
||||||
|
* @param tight_loop Number of instructions to execute.
|
||||||
|
* @return Result status, indicating whethor or not the operation succeeded.
|
||||||
|
*/
|
||||||
|
ResultStatus RunLoop(int tight_loop = 1000);
|
||||||
|
|
||||||
/// Halt the core
|
/**
|
||||||
void Halt(const char* msg);
|
* Step the CPU one instruction
|
||||||
|
* @return Result status, indicating whethor or not the operation succeeded.
|
||||||
|
*/
|
||||||
|
ResultStatus SingleStep();
|
||||||
|
|
||||||
/// Kill the core
|
/// Shutdown the emulated system.
|
||||||
void Stop();
|
void Shutdown();
|
||||||
|
|
||||||
/// Initialize the core
|
/**
|
||||||
void Init();
|
* Load an executable application.
|
||||||
|
* @param emu_window Pointer to the host-system window used for video output and keyboard input.
|
||||||
|
* @param filepath String path to the executable application to load on the host file system.
|
||||||
|
* @returns ResultStatus code, indicating if the operation succeeded.
|
||||||
|
*/
|
||||||
|
ResultStatus Load(EmuWindow* emu_window, const std::string& filepath);
|
||||||
|
|
||||||
/// Shutdown the core
|
/**
|
||||||
void Shutdown();
|
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
|
||||||
|
* application).
|
||||||
|
* @returns True if the emulated system is powered on, otherwise false.
|
||||||
|
*/
|
||||||
|
bool IsPoweredOn() const {
|
||||||
|
return app_core != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
/**
|
||||||
|
* Gets a reference to the emulated AppCore CPU.
|
||||||
|
* @returns A reference to the emulated AppCore CPU.
|
||||||
|
*/
|
||||||
|
ARM_Interface& AppCore() {
|
||||||
|
return *app_core;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// AppLoader used to load the current executing application
|
||||||
|
std::unique_ptr<Loader::AppLoader> app_loader;
|
||||||
|
|
||||||
|
///< ARM11 application core
|
||||||
|
std::unique_ptr<ARM_Interface> app_core;
|
||||||
|
|
||||||
|
static System s_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ARM_Interface& AppCore() {
|
||||||
|
return System::GetInstance().AppCore();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core
|
||||||
|
|
|
@ -130,7 +130,6 @@ int RegisterEvent(const char* name, TimedCallback callback) {
|
||||||
|
|
||||||
static void AntiCrashCallback(u64 userdata, int cycles_late) {
|
static void AntiCrashCallback(u64 userdata, int cycles_late) {
|
||||||
LOG_CRITICAL(Core_Timing, "Savestate broken: an unregistered event was called.");
|
LOG_CRITICAL(Core_Timing, "Savestate broken: an unregistered event was called.");
|
||||||
Core::Halt("invalid timing events");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callback) {
|
void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callback) {
|
||||||
|
@ -147,7 +146,7 @@ void UnregisterAllEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init() {
|
void Init() {
|
||||||
Core::g_app_core->down_count = INITIAL_SLICE_LENGTH;
|
Core::AppCore().down_count = INITIAL_SLICE_LENGTH;
|
||||||
g_slice_length = INITIAL_SLICE_LENGTH;
|
g_slice_length = INITIAL_SLICE_LENGTH;
|
||||||
global_timer = 0;
|
global_timer = 0;
|
||||||
idled_cycles = 0;
|
idled_cycles = 0;
|
||||||
|
@ -187,7 +186,7 @@ void Shutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetTicks() {
|
u64 GetTicks() {
|
||||||
return (u64)global_timer + g_slice_length - Core::g_app_core->down_count;
|
return (u64)global_timer + g_slice_length - Core::AppCore().down_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetIdleTicks() {
|
u64 GetIdleTicks() {
|
||||||
|
@ -461,18 +460,18 @@ void MoveEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForceCheck() {
|
void ForceCheck() {
|
||||||
s64 cycles_executed = g_slice_length - Core::g_app_core->down_count;
|
s64 cycles_executed = g_slice_length - Core::AppCore().down_count;
|
||||||
global_timer += cycles_executed;
|
global_timer += cycles_executed;
|
||||||
// This will cause us to check for new events immediately.
|
// This will cause us to check for new events immediately.
|
||||||
Core::g_app_core->down_count = 0;
|
Core::AppCore().down_count = 0;
|
||||||
// But let's not eat a bunch more time in Advance() because of this.
|
// But let's not eat a bunch more time in Advance() because of this.
|
||||||
g_slice_length = 0;
|
g_slice_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Advance() {
|
void Advance() {
|
||||||
s64 cycles_executed = g_slice_length - Core::g_app_core->down_count;
|
s64 cycles_executed = g_slice_length - Core::AppCore().down_count;
|
||||||
global_timer += cycles_executed;
|
global_timer += cycles_executed;
|
||||||
Core::g_app_core->down_count = g_slice_length;
|
Core::AppCore().down_count = g_slice_length;
|
||||||
|
|
||||||
if (has_ts_events)
|
if (has_ts_events)
|
||||||
MoveEvents();
|
MoveEvents();
|
||||||
|
@ -481,7 +480,7 @@ void Advance() {
|
||||||
if (!first) {
|
if (!first) {
|
||||||
if (g_slice_length < 10000) {
|
if (g_slice_length < 10000) {
|
||||||
g_slice_length += 10000;
|
g_slice_length += 10000;
|
||||||
Core::g_app_core->down_count += g_slice_length;
|
Core::AppCore().down_count += g_slice_length;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Note that events can eat cycles as well.
|
// Note that events can eat cycles as well.
|
||||||
|
@ -491,7 +490,7 @@ void Advance() {
|
||||||
|
|
||||||
const int diff = target - g_slice_length;
|
const int diff = target - g_slice_length;
|
||||||
g_slice_length += diff;
|
g_slice_length += diff;
|
||||||
Core::g_app_core->down_count += diff;
|
Core::AppCore().down_count += diff;
|
||||||
}
|
}
|
||||||
if (advance_callback)
|
if (advance_callback)
|
||||||
advance_callback(static_cast<int>(cycles_executed));
|
advance_callback(static_cast<int>(cycles_executed));
|
||||||
|
@ -507,12 +506,12 @@ void LogPendingEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Idle(int max_idle) {
|
void Idle(int max_idle) {
|
||||||
s64 cycles_down = Core::g_app_core->down_count;
|
s64 cycles_down = Core::AppCore().down_count;
|
||||||
if (max_idle != 0 && cycles_down > max_idle)
|
if (max_idle != 0 && cycles_down > max_idle)
|
||||||
cycles_down = max_idle;
|
cycles_down = max_idle;
|
||||||
|
|
||||||
if (first && cycles_down > 0) {
|
if (first && cycles_down > 0) {
|
||||||
s64 cycles_executed = g_slice_length - Core::g_app_core->down_count;
|
s64 cycles_executed = g_slice_length - Core::AppCore().down_count;
|
||||||
s64 cycles_next_event = first->time - global_timer;
|
s64 cycles_next_event = first->time - global_timer;
|
||||||
|
|
||||||
if (cycles_next_event < cycles_executed + cycles_down) {
|
if (cycles_next_event < cycles_executed + cycles_down) {
|
||||||
|
@ -527,9 +526,9 @@ void Idle(int max_idle) {
|
||||||
cycles_down / (float)(g_clock_rate_arm11 * 0.001f));
|
cycles_down / (float)(g_clock_rate_arm11 * 0.001f));
|
||||||
|
|
||||||
idled_cycles += cycles_down;
|
idled_cycles += cycles_down;
|
||||||
Core::g_app_core->down_count -= cycles_down;
|
Core::AppCore().down_count -= cycles_down;
|
||||||
if (Core::g_app_core->down_count == 0)
|
if (Core::AppCore().down_count == 0)
|
||||||
Core::g_app_core->down_count = -1;
|
Core::AppCore().down_count = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetScheduledEventsSummary() {
|
std::string GetScheduledEventsSummary() {
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "core/loader/loader.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
|
@ -450,8 +451,8 @@ static void SendSignal(u32 signal) {
|
||||||
latest_signal = signal;
|
latest_signal = signal;
|
||||||
|
|
||||||
std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15,
|
std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15,
|
||||||
htonl(Core::g_app_core->GetPC()), 13,
|
htonl(Core::AppCore().GetPC()), 13,
|
||||||
htonl(Core::g_app_core->GetReg(13)));
|
htonl(Core::AppCore().GetReg(13)));
|
||||||
LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str());
|
LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str());
|
||||||
SendReply(buffer.c_str());
|
SendReply(buffer.c_str());
|
||||||
}
|
}
|
||||||
|
@ -538,15 +539,15 @@ static void ReadRegister() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id <= R15_REGISTER) {
|
if (id <= R15_REGISTER) {
|
||||||
IntToGdbHex(reply, Core::g_app_core->GetReg(id));
|
IntToGdbHex(reply, Core::AppCore().GetReg(id));
|
||||||
} else if (id == CPSR_REGISTER) {
|
} else if (id == CPSR_REGISTER) {
|
||||||
IntToGdbHex(reply, Core::g_app_core->GetCPSR());
|
IntToGdbHex(reply, Core::AppCore().GetCPSR());
|
||||||
} else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
|
} else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
|
||||||
IntToGdbHex(reply, Core::g_app_core->GetVFPReg(
|
IntToGdbHex(reply, Core::AppCore().GetVFPReg(
|
||||||
id - CPSR_REGISTER -
|
id - CPSR_REGISTER -
|
||||||
1)); // VFP registers should start at 26, so one after CSPR_REGISTER
|
1)); // VFP registers should start at 26, so one after CSPR_REGISTER
|
||||||
} else if (id == FPSCR_REGISTER) {
|
} else if (id == FPSCR_REGISTER) {
|
||||||
IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR
|
IntToGdbHex(reply, Core::AppCore().GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR
|
||||||
IntToGdbHex(reply + 8, 0);
|
IntToGdbHex(reply + 8, 0);
|
||||||
} else {
|
} else {
|
||||||
return SendReply("E01");
|
return SendReply("E01");
|
||||||
|
@ -563,22 +564,22 @@ static void ReadRegisters() {
|
||||||
u8* bufptr = buffer;
|
u8* bufptr = buffer;
|
||||||
|
|
||||||
for (int reg = 0; reg <= R15_REGISTER; reg++) {
|
for (int reg = 0; reg <= R15_REGISTER; reg++) {
|
||||||
IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetReg(reg));
|
IntToGdbHex(bufptr + reg * CHAR_BIT, Core::AppCore().GetReg(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
bufptr += (16 * CHAR_BIT);
|
bufptr += (16 * CHAR_BIT);
|
||||||
|
|
||||||
IntToGdbHex(bufptr, Core::g_app_core->GetCPSR());
|
IntToGdbHex(bufptr, Core::AppCore().GetCPSR());
|
||||||
|
|
||||||
bufptr += CHAR_BIT;
|
bufptr += CHAR_BIT;
|
||||||
|
|
||||||
for (int reg = 0; reg <= 31; reg++) {
|
for (int reg = 0; reg <= 31; reg++) {
|
||||||
IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetVFPReg(reg));
|
IntToGdbHex(bufptr + reg * CHAR_BIT, Core::AppCore().GetVFPReg(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
bufptr += (32 * CHAR_BIT);
|
bufptr += (32 * CHAR_BIT);
|
||||||
|
|
||||||
IntToGdbHex(bufptr, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR));
|
IntToGdbHex(bufptr, Core::AppCore().GetVFPSystemReg(VFP_FPSCR));
|
||||||
|
|
||||||
SendReply(reinterpret_cast<char*>(buffer));
|
SendReply(reinterpret_cast<char*>(buffer));
|
||||||
}
|
}
|
||||||
|
@ -595,13 +596,13 @@ static void WriteRegister() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id <= R15_REGISTER) {
|
if (id <= R15_REGISTER) {
|
||||||
Core::g_app_core->SetReg(id, GdbHexToInt(buffer_ptr));
|
Core::AppCore().SetReg(id, GdbHexToInt(buffer_ptr));
|
||||||
} else if (id == CPSR_REGISTER) {
|
} else if (id == CPSR_REGISTER) {
|
||||||
Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr));
|
Core::AppCore().SetCPSR(GdbHexToInt(buffer_ptr));
|
||||||
} else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
|
} else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
|
||||||
Core::g_app_core->SetVFPReg(id - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr));
|
Core::AppCore().SetVFPReg(id - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr));
|
||||||
} else if (id == FPSCR_REGISTER) {
|
} else if (id == FPSCR_REGISTER) {
|
||||||
Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr));
|
Core::AppCore().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr));
|
||||||
} else {
|
} else {
|
||||||
return SendReply("E01");
|
return SendReply("E01");
|
||||||
}
|
}
|
||||||
|
@ -618,20 +619,20 @@ static void WriteRegisters() {
|
||||||
|
|
||||||
for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) {
|
for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) {
|
||||||
if (reg <= R15_REGISTER) {
|
if (reg <= R15_REGISTER) {
|
||||||
Core::g_app_core->SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
|
Core::AppCore().SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
|
||||||
} else if (reg == CPSR_REGISTER) {
|
} else if (reg == CPSR_REGISTER) {
|
||||||
Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT));
|
Core::AppCore().SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT));
|
||||||
} else if (reg == CPSR_REGISTER - 1) {
|
} else if (reg == CPSR_REGISTER - 1) {
|
||||||
// Dummy FPA register, ignore
|
// Dummy FPA register, ignore
|
||||||
} else if (reg < CPSR_REGISTER) {
|
} else if (reg < CPSR_REGISTER) {
|
||||||
// Dummy FPA registers, ignore
|
// Dummy FPA registers, ignore
|
||||||
i += 2;
|
i += 2;
|
||||||
} else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) {
|
} else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) {
|
||||||
Core::g_app_core->SetVFPReg(reg - CPSR_REGISTER - 1,
|
Core::AppCore().SetVFPReg(reg - CPSR_REGISTER - 1,
|
||||||
GdbHexToInt(buffer_ptr + i * CHAR_BIT));
|
GdbHexToInt(buffer_ptr + i * CHAR_BIT));
|
||||||
i++; // Skip padding
|
i++; // Skip padding
|
||||||
} else if (reg == FPSCR_REGISTER) {
|
} else if (reg == FPSCR_REGISTER) {
|
||||||
Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
|
Core::AppCore().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,7 +909,7 @@ void ToggleServer(bool status) {
|
||||||
server_enabled = status;
|
server_enabled = status;
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
if (!IsConnected() && Core::g_sys_core != nullptr) {
|
if (!IsConnected() && Core::System().GetInstance().IsPoweredOn()) {
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
namespace HLE {
|
namespace HLE {
|
||||||
|
|
||||||
#define PARAM(n) Core::g_app_core->GetReg(n)
|
#define PARAM(n) Core::AppCore().GetReg(n)
|
||||||
|
|
||||||
/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
|
/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
|
||||||
static const ResultCode RESULT_INVALID(0xDEADC0DE);
|
static const ResultCode RESULT_INVALID(0xDEADC0DE);
|
||||||
|
@ -24,7 +24,7 @@ static const ResultCode RESULT_INVALID(0xDEADC0DE);
|
||||||
* @param res Result to return
|
* @param res Result to return
|
||||||
*/
|
*/
|
||||||
static inline void FuncReturn(u32 res) {
|
static inline void FuncReturn(u32 res) {
|
||||||
Core::g_app_core->SetReg(0, res);
|
Core::AppCore().SetReg(0, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,8 +33,8 @@ static inline void FuncReturn(u32 res) {
|
||||||
* @todo Verify that this function is correct
|
* @todo Verify that this function is correct
|
||||||
*/
|
*/
|
||||||
static inline void FuncReturn64(u64 res) {
|
static inline void FuncReturn64(u64 res) {
|
||||||
Core::g_app_core->SetReg(0, (u32)(res & 0xFFFFFFFF));
|
Core::AppCore().SetReg(0, (u32)(res & 0xFFFFFFFF));
|
||||||
Core::g_app_core->SetReg(1, (u32)((res >> 32) & 0xFFFFFFFF));
|
Core::AppCore().SetReg(1, (u32)((res >> 32) & 0xFFFFFFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -49,7 +49,7 @@ template <ResultCode func(u32*, u32, u32, u32, u32, u32)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
|
u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ template <ResultCode func(u32*, s32, u32, u32, u32, s32)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
|
u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ void Wrap() {
|
||||||
.raw;
|
.raw;
|
||||||
|
|
||||||
if (retval != RESULT_INVALID.raw) {
|
if (retval != RESULT_INVALID.raw) {
|
||||||
Core::g_app_core->SetReg(1, (u32)param_1);
|
Core::AppCore().SetReg(1, (u32)param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ template <ResultCode func(u32*)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1).raw;
|
u32 retval = func(¶m_1).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,11 +102,11 @@ void Wrap() {
|
||||||
MemoryInfo memory_info = {};
|
MemoryInfo memory_info = {};
|
||||||
PageInfo page_info = {};
|
PageInfo page_info = {};
|
||||||
u32 retval = func(&memory_info, &page_info, PARAM(2)).raw;
|
u32 retval = func(&memory_info, &page_info, PARAM(2)).raw;
|
||||||
Core::g_app_core->SetReg(1, memory_info.base_address);
|
Core::AppCore().SetReg(1, memory_info.base_address);
|
||||||
Core::g_app_core->SetReg(2, memory_info.size);
|
Core::AppCore().SetReg(2, memory_info.size);
|
||||||
Core::g_app_core->SetReg(3, memory_info.permission);
|
Core::AppCore().SetReg(3, memory_info.permission);
|
||||||
Core::g_app_core->SetReg(4, memory_info.state);
|
Core::AppCore().SetReg(4, memory_info.state);
|
||||||
Core::g_app_core->SetReg(5, page_info.flags);
|
Core::AppCore().SetReg(5, page_info.flags);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,11 +115,11 @@ void Wrap() {
|
||||||
MemoryInfo memory_info = {};
|
MemoryInfo memory_info = {};
|
||||||
PageInfo page_info = {};
|
PageInfo page_info = {};
|
||||||
u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw;
|
u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw;
|
||||||
Core::g_app_core->SetReg(1, memory_info.base_address);
|
Core::AppCore().SetReg(1, memory_info.base_address);
|
||||||
Core::g_app_core->SetReg(2, memory_info.size);
|
Core::AppCore().SetReg(2, memory_info.size);
|
||||||
Core::g_app_core->SetReg(3, memory_info.permission);
|
Core::AppCore().SetReg(3, memory_info.permission);
|
||||||
Core::g_app_core->SetReg(4, memory_info.state);
|
Core::AppCore().SetReg(4, memory_info.state);
|
||||||
Core::g_app_core->SetReg(5, page_info.flags);
|
Core::AppCore().SetReg(5, page_info.flags);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ template <ResultCode func(s32*, u32)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
s32 param_1 = 0;
|
s32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1)).raw;
|
u32 retval = func(¶m_1, PARAM(1)).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ template <ResultCode func(u32*, u32)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1)).raw;
|
u32 retval = func(¶m_1, PARAM(1)).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ template <ResultCode func(u32*, const char*)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, (char*)Memory::GetPointer(PARAM(1))).raw;
|
u32 retval = func(¶m_1, (char*)Memory::GetPointer(PARAM(1))).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ template <ResultCode func(u32*, s32, s32)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw;
|
u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ template <ResultCode func(s32*, u32, s32)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
s32 param_1 = 0;
|
s32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw;
|
u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,8 +184,8 @@ template <ResultCode func(s64*, u32, s32)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
s64 param_1 = 0;
|
s64 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw;
|
u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw;
|
||||||
Core::g_app_core->SetReg(1, (u32)param_1);
|
Core::AppCore().SetReg(1, (u32)param_1);
|
||||||
Core::g_app_core->SetReg(2, (u32)(param_1 >> 32));
|
Core::AppCore().SetReg(2, (u32)(param_1 >> 32));
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ void Wrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
// The last parameter is passed in R0 instead of R4
|
// The last parameter is passed in R0 instead of R4
|
||||||
u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw;
|
u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw;
|
||||||
Core::g_app_core->SetReg(1, param_1);
|
Core::AppCore().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,8 +209,8 @@ template <ResultCode func(s64*, Handle, u32)>
|
||||||
void Wrap() {
|
void Wrap() {
|
||||||
s64 param_1 = 0;
|
s64 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw;
|
u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw;
|
||||||
Core::g_app_core->SetReg(1, (u32)param_1);
|
Core::AppCore().SetReg(1, (u32)param_1);
|
||||||
Core::g_app_core->SetReg(2, (u32)(param_1 >> 32));
|
Core::AppCore().SetReg(2, (u32)(param_1 >> 32));
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,8 +227,8 @@ void Wrap() {
|
||||||
reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3))
|
reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3))
|
||||||
.raw;
|
.raw;
|
||||||
// The first out parameter is moved into R2 and the second is moved into R1.
|
// The first out parameter is moved into R2 and the second is moved into R1.
|
||||||
Core::g_app_core->SetReg(1, param_2);
|
Core::AppCore().SetReg(1, param_2);
|
||||||
Core::g_app_core->SetReg(2, param_1);
|
Core::AppCore().SetReg(2, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,9 @@ void Reschedule(const char* reason) {
|
||||||
// routines. This simulates that time by artificially advancing the number of CPU "ticks".
|
// routines. This simulates that time by artificially advancing the number of CPU "ticks".
|
||||||
// The value was chosen empirically, it seems to work well enough for everything tested, but
|
// The value was chosen empirically, it seems to work well enough for everything tested, but
|
||||||
// is likely not ideal. We should find a more accurate way to simulate timing with HLE.
|
// is likely not ideal. We should find a more accurate way to simulate timing with HLE.
|
||||||
Core::g_app_core->AddTicks(4000);
|
Core::AppCore().AddTicks(4000);
|
||||||
|
|
||||||
Core::g_app_core->PrepareReschedule();
|
Core::AppCore().PrepareReschedule();
|
||||||
|
|
||||||
reschedule = true;
|
reschedule = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,7 +188,7 @@ static void SwitchContext(Thread* new_thread) {
|
||||||
// Save context for previous thread
|
// Save context for previous thread
|
||||||
if (previous_thread) {
|
if (previous_thread) {
|
||||||
previous_thread->last_running_ticks = CoreTiming::GetTicks();
|
previous_thread->last_running_ticks = CoreTiming::GetTicks();
|
||||||
Core::g_app_core->SaveContext(previous_thread->context);
|
Core::AppCore().SaveContext(previous_thread->context);
|
||||||
|
|
||||||
if (previous_thread->status == THREADSTATUS_RUNNING) {
|
if (previous_thread->status == THREADSTATUS_RUNNING) {
|
||||||
// This is only the case when a reschedule is triggered without the current thread
|
// This is only the case when a reschedule is triggered without the current thread
|
||||||
|
@ -214,8 +214,8 @@ static void SwitchContext(Thread* new_thread) {
|
||||||
// Restores thread to its nominal priority if it has been temporarily changed
|
// Restores thread to its nominal priority if it has been temporarily changed
|
||||||
new_thread->current_priority = new_thread->nominal_priority;
|
new_thread->current_priority = new_thread->nominal_priority;
|
||||||
|
|
||||||
Core::g_app_core->LoadContext(new_thread->context);
|
Core::AppCore().LoadContext(new_thread->context);
|
||||||
Core::g_app_core->SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress());
|
Core::AppCore().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress());
|
||||||
} else {
|
} else {
|
||||||
current_thread = nullptr;
|
current_thread = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,7 +457,7 @@ static void LoadCRO(Interface* self, bool link_on_load_bug_fix) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::g_app_core->ClearInstructionCache();
|
Core::AppCore().ClearInstructionCache();
|
||||||
|
|
||||||
LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(),
|
LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(),
|
||||||
cro_address, cro_address + fix_size);
|
cro_address, cro_address + fix_size);
|
||||||
|
@ -562,7 +562,7 @@ static void UnloadCRO(Interface* self) {
|
||||||
memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr);
|
memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::g_app_core->ClearInstructionCache();
|
Core::AppCore().ClearInstructionCache();
|
||||||
|
|
||||||
cmd_buff[1] = result.raw;
|
cmd_buff[1] = result.raw;
|
||||||
}
|
}
|
||||||
|
@ -624,7 +624,7 @@ static void LinkCRO(Interface* self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_synchronizer.SynchronizeOriginalMemory();
|
memory_synchronizer.SynchronizeOriginalMemory();
|
||||||
Core::g_app_core->ClearInstructionCache();
|
Core::AppCore().ClearInstructionCache();
|
||||||
|
|
||||||
cmd_buff[1] = result.raw;
|
cmd_buff[1] = result.raw;
|
||||||
}
|
}
|
||||||
|
@ -686,7 +686,7 @@ static void UnlinkCRO(Interface* self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_synchronizer.SynchronizeOriginalMemory();
|
memory_synchronizer.SynchronizeOriginalMemory();
|
||||||
Core::g_app_core->ClearInstructionCache();
|
Core::AppCore().ClearInstructionCache();
|
||||||
|
|
||||||
cmd_buff[1] = result.raw;
|
cmd_buff[1] = result.raw;
|
||||||
}
|
}
|
||||||
|
|
|
@ -582,7 +582,7 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point
|
||||||
|
|
||||||
/// Called when a thread exits
|
/// Called when a thread exits
|
||||||
static void ExitThread() {
|
static void ExitThread() {
|
||||||
LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC());
|
LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::AppCore().GetPC());
|
||||||
|
|
||||||
Kernel::ExitCurrentThread();
|
Kernel::ExitCurrentThread();
|
||||||
}
|
}
|
||||||
|
@ -612,7 +612,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
|
||||||
using Kernel::Mutex;
|
using Kernel::Mutex;
|
||||||
|
|
||||||
SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0);
|
SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0);
|
||||||
mutex->name = Common::StringFromFormat("mutex-%08x", Core::g_app_core->GetReg(14));
|
mutex->name = Common::StringFromFormat("mutex-%08x", Core::AppCore().GetReg(14));
|
||||||
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
|
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
|
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
|
||||||
using Kernel::Semaphore;
|
using Kernel::Semaphore;
|
||||||
|
|
||||||
CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count));
|
CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count));
|
||||||
semaphore->name = Common::StringFromFormat("semaphore-%08x", Core::g_app_core->GetReg(14));
|
semaphore->name = Common::StringFromFormat("semaphore-%08x", Core::AppCore().GetReg(14));
|
||||||
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
|
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
|
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) {
|
||||||
using Kernel::Event;
|
using Kernel::Event;
|
||||||
|
|
||||||
SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type));
|
SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type));
|
||||||
evt->name = Common::StringFromFormat("event-%08x", Core::g_app_core->GetReg(14));
|
evt->name = Common::StringFromFormat("event-%08x", Core::AppCore().GetReg(14));
|
||||||
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
|
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
|
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) {
|
||||||
using Kernel::Timer;
|
using Kernel::Timer;
|
||||||
|
|
||||||
SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type));
|
SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type));
|
||||||
timer->name = Common::StringFromFormat("timer-%08x", Core::g_app_core->GetReg(14));
|
timer->name = Common::StringFromFormat("timer-%08x", Core::AppCore().GetReg(14));
|
||||||
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
|
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
|
LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
|
||||||
|
@ -854,7 +854,7 @@ static void SleepThread(s64 nanoseconds) {
|
||||||
static s64 GetSystemTick() {
|
static s64 GetSystemTick() {
|
||||||
s64 result = CoreTiming::GetTicks();
|
s64 result = CoreTiming::GetTicks();
|
||||||
// Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end.
|
// Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end.
|
||||||
Core::g_app_core->AddTicks(
|
Core::AppCore().AddTicks(
|
||||||
150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b
|
150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include "audio_core/audio_core.h"
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/core_timing.h"
|
|
||||||
#include "core/gdbstub/gdbstub.h"
|
|
||||||
#include "core/hle/hle.h"
|
|
||||||
#include "core/hle/kernel/kernel.h"
|
|
||||||
#include "core/hle/kernel/memory.h"
|
|
||||||
#include "core/hw/hw.h"
|
|
||||||
#include "core/system.h"
|
|
||||||
#include "video_core/video_core.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
|
|
||||||
/*static*/ System System::s_instance;
|
|
||||||
|
|
||||||
System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
|
|
||||||
Core::Init();
|
|
||||||
CoreTiming::Init();
|
|
||||||
Memory::Init();
|
|
||||||
HW::Init();
|
|
||||||
Kernel::Init(system_mode);
|
|
||||||
HLE::Init();
|
|
||||||
AudioCore::Init();
|
|
||||||
GDBStub::Init();
|
|
||||||
|
|
||||||
if (!VideoCore::Init(emu_window)) {
|
|
||||||
return ResultStatus::ErrorVideoCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_powered_on = true;
|
|
||||||
|
|
||||||
return ResultStatus::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
void System::Shutdown() {
|
|
||||||
GDBStub::Shutdown();
|
|
||||||
AudioCore::Shutdown();
|
|
||||||
VideoCore::Shutdown();
|
|
||||||
HLE::Shutdown();
|
|
||||||
Kernel::Shutdown();
|
|
||||||
HW::Shutdown();
|
|
||||||
CoreTiming::Shutdown();
|
|
||||||
Core::Shutdown();
|
|
||||||
|
|
||||||
is_powered_on = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
|
|
||||||
state.app_loader = Loader::GetLoader(filepath);
|
|
||||||
|
|
||||||
if (!state.app_loader) {
|
|
||||||
LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str());
|
|
||||||
return ResultStatus::ErrorGetLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<u32> system_mode{ state.app_loader->LoadKernelSystemMode() };
|
|
||||||
if (!system_mode) {
|
|
||||||
LOG_CRITICAL(Frontend, "Failed to determine system mode!");
|
|
||||||
return ResultStatus::ErrorSystemMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultStatus init_result{ Init(emu_window, system_mode.get()) };
|
|
||||||
if (init_result != ResultStatus::Success) {
|
|
||||||
LOG_CRITICAL(Frontend, "Failed to initialize system (Error %i)!", init_result);
|
|
||||||
System::Shutdown();
|
|
||||||
return init_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Loader::ResultStatus load_result{ state.app_loader->Load() };
|
|
||||||
if (Loader::ResultStatus::Success != load_result) {
|
|
||||||
LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result);
|
|
||||||
System::Shutdown();
|
|
||||||
|
|
||||||
switch (load_result) {
|
|
||||||
case Loader::ResultStatus::ErrorEncrypted:
|
|
||||||
return ResultStatus::ErrorLoader_ErrorEncrypted;
|
|
||||||
case Loader::ResultStatus::ErrorInvalidFormat:
|
|
||||||
return ResultStatus::ErrorLoader_ErrorInvalidFormat;
|
|
||||||
default:
|
|
||||||
return ResultStatus::ErrorLoader;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ResultStatus::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Core
|
|
|
@ -1,83 +0,0 @@
|
||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "core/loader/loader.h"
|
|
||||||
|
|
||||||
class EmuWindow;
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
|
|
||||||
class System {
|
|
||||||
public:
|
|
||||||
struct State {
|
|
||||||
std::unique_ptr<Loader::AppLoader> app_loader;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the instance of the System singleton class.
|
|
||||||
* @returns Reference to the instance of the System singleton class.
|
|
||||||
*/
|
|
||||||
static System& GetInstance() {
|
|
||||||
return s_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enumeration representing the return values of the System Initialize and Load process.
|
|
||||||
enum class ResultStatus : u32 {
|
|
||||||
Success, ///< Succeeded
|
|
||||||
ErrorGetLoader, ///< Error finding the correct application loader
|
|
||||||
ErrorSystemMode, ///< Error determining the system mode
|
|
||||||
ErrorLoader, ///< Error loading the specified application
|
|
||||||
ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
|
|
||||||
ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an invalid format
|
|
||||||
ErrorVideoCore, ///< Error in the video core
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the emulated system.
|
|
||||||
* @param emu_window Pointer to the host-system window used for video output and keyboard input.
|
|
||||||
* @param system_mode The system mode.
|
|
||||||
* @returns ResultStatus code, indicating if the operation succeeded.
|
|
||||||
*/
|
|
||||||
ResultStatus Init(EmuWindow* emu_window, u32 system_mode);
|
|
||||||
|
|
||||||
/// Shutdown the emulated system.
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load an executable application.
|
|
||||||
* @param emu_window Pointer to the host-system window used for video output and keyboard input.
|
|
||||||
* @param filepath String path to the executable application to load on the host file system.
|
|
||||||
* @returns ResultStatus code, indicating if the operation succeeded.
|
|
||||||
*/
|
|
||||||
ResultStatus Load(EmuWindow* emu_window, const std::string& filepath);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
|
|
||||||
* application).
|
|
||||||
* @returns True if the emulated system is powered on, otherwise false.
|
|
||||||
*/
|
|
||||||
bool IsPoweredOn() const {
|
|
||||||
return is_powered_on;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the internal state of the emulated system.
|
|
||||||
* @returns The internal state of the emulated system
|
|
||||||
*/
|
|
||||||
State& GetState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool is_powered_on{};
|
|
||||||
State state;
|
|
||||||
|
|
||||||
static System s_instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Core
|
|
Loading…
Reference in a new issue