Merge pull request #2343 from bunnei/core-cleanup

Core: Top-level consolidate & misc cleanup
master
bunnei 2016-12-22 11:47:44 +07:00 committed by GitHub
commit aa47af7fb6
45 changed files with 439 additions and 595 deletions

@ -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) {
@ -64,7 +63,7 @@ int main(int argc, char** argv) {
return -1; return -1;
} }
#endif #endif
std::string boot_filename; std::string filepath;
static struct option long_options[] = { static struct option long_options[] = {
{"gdbport", required_argument, 0, 'g'}, {"gdbport", required_argument, 0, 'g'},
@ -97,9 +96,9 @@ int main(int argc, char** argv) {
} }
} else { } else {
#ifdef _WIN32 #ifdef _WIN32
boot_filename = Common::UTF16ToUTF8(argv_w[optind]); filepath = Common::UTF16ToUTF8(argv_w[optind]);
#else #else
boot_filename = argv[optind]; filepath = argv[optind];
#endif #endif
optind++; optind++;
} }
@ -115,7 +114,7 @@ int main(int argc, char** argv) {
MicroProfileOnThreadCreate("EmuThread"); MicroProfileOnThreadCreate("EmuThread");
SCOPE_EXIT({ MicroProfileShutdown(); }); SCOPE_EXIT({ MicroProfileShutdown(); });
if (boot_filename.empty()) { if (filepath.empty()) {
LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified"); LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
return -1; return -1;
} }
@ -127,32 +126,25 @@ int main(int argc, char** argv) {
Settings::values.use_gdbstub = use_gdbstub; Settings::values.use_gdbstub = use_gdbstub;
Settings::Apply(); Settings::Apply();
std::unique_ptr<EmuWindow_SDL2> emu_window = std::make_unique<EmuWindow_SDL2>(); std::unique_ptr<EmuWindow_SDL2> emu_window{std::make_unique<EmuWindow_SDL2>()};
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(boot_filename); Core::System& system{Core::System::GetInstance()};
if (!loader) {
LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", boot_filename.c_str()); SCOPE_EXIT({ system.Shutdown(); });
const Core::System::ResultStatus load_result{system.Load(emu_window.get(), filepath)};
switch (load_result) {
case Core::System::ResultStatus::ErrorGetLoader:
LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str());
return -1; return -1;
} case Core::System::ResultStatus::ErrorLoader:
LOG_CRITICAL(Frontend, "Failed to load ROM!");
boost::optional<u32> system_mode = loader->LoadKernelSystemMode();
if (!system_mode) {
LOG_CRITICAL(Frontend, "Failed to load ROM (Could not determine system mode)!");
return -1;
}
System::Init(emu_window.get(), system_mode.get());
SCOPE_EXIT({ System::Shutdown(); });
Loader::ResultStatus load_result = loader->Load();
if (Loader::ResultStatus::Success != load_result) {
LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result);
return -1; return -1;
} }
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();
@ -60,7 +58,7 @@ void EmuThread::run() {
} }
// Shutdown the core emulation // Shutdown the core emulation
System::Shutdown(); Core::System::GetInstance().Shutdown();
#if MICROPROFILE_ENABLED #if MICROPROFILE_ENABLED
MicroProfileOnThreadExit(); MicroProfileOnThreadExit();

@ -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)
@ -14,7 +14,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
ui->setupUi(this); ui->setupUi(this);
this->setConfiguration(); this->setConfiguration();
ui->toggle_cpu_jit->setEnabled(!System::IsPoweredOn()); ui->toggle_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
} }
ConfigureGeneral::~ConfigureGeneral() {} ConfigureGeneral::~ConfigureGeneral() {}

@ -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)
@ -13,7 +13,7 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
ui->setupUi(this); ui->setupUi(this);
this->setConfiguration(); this->setConfiguration();
ui->toggle_vsync->setEnabled(!System::IsPoweredOn()); ui->toggle_vsync->setEnabled(!Core::System::GetInstance().IsPoweredOn());
} }
ConfigureGraphics::~ConfigureGraphics() {} ConfigureGraphics::~ConfigureGraphics() {}

@ -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 = {{
@ -24,7 +23,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::
ConfigureSystem::~ConfigureSystem() {} ConfigureSystem::~ConfigureSystem() {}
void ConfigureSystem::setConfiguration() { void ConfigureSystem::setConfiguration() {
enabled = !System::IsPoweredOn(); enabled = !Core::System::GetInstance().IsPoweredOn();
if (!enabled) { if (!enabled) {
ReadSystemSettings(); ReadSystemSettings();

@ -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::CPU().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::CPU().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::CPU().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::CPU().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::CPU().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::CPU().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::CPU().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::CPU().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::CPU().GetVFPSystemReg(VFP_FPSCR);
const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC); const u32 fpexc_val = Core::CPU().GetVFPSystemReg(VFP_FPEXC);
const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST); const u32 fpinst_val = Core::CPU().GetVFPSystemReg(VFP_FPINST);
const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2); const u32 fpinst2_val = Core::CPU().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"
@ -274,7 +273,7 @@ void GMainWindow::OnDisplayTitleBars(bool show) {
} }
} }
bool GMainWindow::InitializeSystem(u32 system_mode) { bool GMainWindow::LoadROM(const std::string& filename) {
// Shutdown previous session if the emu thread is still active... // Shutdown previous session if the emu thread is still active...
if (emu_thread != nullptr) if (emu_thread != nullptr)
ShutdownGame(); ShutdownGame();
@ -290,54 +289,25 @@ bool GMainWindow::InitializeSystem(u32 system_mode) {
return false; return false;
} }
// Initialize the core emulation Core::System& system{Core::System::GetInstance()};
System::Result system_result = System::Init(render_window, system_mode);
if (System::Result::Success != system_result) {
switch (system_result) {
case System::Result::ErrorInitVideoCore:
QMessageBox::critical(this, tr("Error while starting Citra!"),
tr("Failed to initialize the video core!\n\n"
"Please ensure that your GPU supports OpenGL 3.3 and that you "
"have the latest graphics driver."));
break;
default: const Core::System::ResultStatus result{system.Load(render_window, filename)};
QMessageBox::critical(this, tr("Error while starting Citra!"),
tr("Unknown error (please check the log)!"));
break;
}
return false;
}
return true;
}
bool GMainWindow::LoadROM(const std::string& filename) {
std::unique_ptr<Loader::AppLoader> app_loader = Loader::GetLoader(filename);
if (!app_loader) {
LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str());
QMessageBox::critical(this, tr("Error while loading ROM!"),
tr("The ROM format is not supported."));
return false;
}
boost::optional<u32> system_mode = app_loader->LoadKernelSystemMode();
if (!system_mode) {
LOG_CRITICAL(Frontend, "Failed to load ROM!");
QMessageBox::critical(this, tr("Error while loading ROM!"),
tr("Could not determine the system mode."));
return false;
}
if (!InitializeSystem(system_mode.get()))
return false;
Loader::ResultStatus result = app_loader->Load();
if (Loader::ResultStatus::Success != result) {
System::Shutdown();
LOG_CRITICAL(Frontend, "Failed to load ROM!");
if (result != Core::System::ResultStatus::Success) {
switch (result) { switch (result) {
case Loader::ResultStatus::ErrorEncrypted: { case Core::System::ResultStatus::ErrorGetLoader:
LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str());
QMessageBox::critical(this, tr("Error while loading ROM!"),
tr("The ROM format is not supported."));
break;
case Core::System::ResultStatus::ErrorSystemMode:
LOG_CRITICAL(Frontend, "Failed to load ROM!");
QMessageBox::critical(this, tr("Error while loading ROM!"),
tr("Could not determine the system mode."));
break;
case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted: {
// Build the MessageBox ourselves to have clickable link // Build the MessageBox ourselves to have clickable link
QMessageBox popup_error; QMessageBox popup_error;
popup_error.setTextFormat(Qt::RichText); popup_error.setTextFormat(Qt::RichText);
@ -352,11 +322,10 @@ bool GMainWindow::LoadROM(const std::string& filename) {
popup_error.exec(); popup_error.exec();
break; break;
} }
case Loader::ResultStatus::ErrorInvalidFormat: case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
QMessageBox::critical(this, tr("Error while loading ROM!"), QMessageBox::critical(this, tr("Error while loading ROM!"),
tr("The ROM format is not supported.")); tr("The ROM format is not supported."));
break; break;
case Loader::ResultStatus::Error:
default: default:
QMessageBox::critical(this, tr("Error while loading ROM!"), tr("Unknown error!")); QMessageBox::critical(this, tr("Error while loading ROM!"), tr("Unknown error!"));

@ -32,22 +32,10 @@
// Subdirs in the User dir returned by GetUserPath(D_USER_IDX) // Subdirs in the User dir returned by GetUserPath(D_USER_IDX)
#define CONFIG_DIR "config" #define CONFIG_DIR "config"
#define GAMECONFIG_DIR "game_config"
#define MAPS_DIR "maps"
#define CACHE_DIR "cache" #define CACHE_DIR "cache"
#define SDMC_DIR "sdmc" #define SDMC_DIR "sdmc"
#define NAND_DIR "nand" #define NAND_DIR "nand"
#define SYSDATA_DIR "sysdata" #define SYSDATA_DIR "sysdata"
#define SHADERCACHE_DIR "shader_cache"
#define STATESAVES_DIR "state_saves"
#define SCREENSHOTS_DIR "screenShots"
#define DUMP_DIR "dump"
#define DUMP_TEXTURES_DIR "textures"
#define DUMP_FRAMES_DIR "frames"
#define DUMP_AUDIO_DIR "audio"
#define LOGS_DIR "logs"
#define SHADERS_DIR "shaders"
#define SYSCONF_DIR "sysconf"
// Filenames // Filenames
// Files in the directory returned by GetUserPath(D_CONFIG_IDX) // Files in the directory returned by GetUserPath(D_CONFIG_IDX)
@ -57,9 +45,3 @@
// Sys files // Sys files
#define SHARED_FONT "shared_font.bin" #define SHARED_FONT "shared_font.bin"
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
#define MAIN_LOG "emu.log"
// Files in the directory returned by GetUserPath(D_SYSCONF_IDX)
#define SYSCONF "SYSCONF"

@ -697,6 +697,9 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new
paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP;
paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP;
paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP;
#else #else
if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) {
paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
@ -712,24 +715,8 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new
paths[D_CACHE_IDX] = cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; paths[D_CACHE_IDX] = cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP;
} }
#endif #endif
paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP;
paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP;
paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP; paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP;
paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP;
paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP;
paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP;
paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP;
paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP;
paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP;
paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP;
paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP;
paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG;
paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG;
paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG;
} }
if (!newPath.empty()) { if (!newPath.empty()) {
@ -743,48 +730,15 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new
switch (DirIDX) { switch (DirIDX) {
case D_ROOT_IDX: case D_ROOT_IDX:
paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP;
paths[D_SYSCONF_IDX] = paths[D_USER_IDX] + SYSCONF_DIR + DIR_SEP;
paths[F_SYSCONF_IDX] = paths[D_SYSCONF_IDX] + SYSCONF;
break; break;
case D_USER_IDX: case D_USER_IDX:
paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP;
paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP;
paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP;
paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP; paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP;
paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP;
paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP;
paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP;
paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP;
paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP;
paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP;
paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP;
paths[D_SYSCONF_IDX] = paths[D_USER_IDX] + SYSCONF_DIR DIR_SEP;
paths[F_EMUCONFIG_IDX] = paths[D_CONFIG_IDX] + EMU_CONFIG;
paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG;
paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG;
paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG;
break; break;
case D_CONFIG_IDX:
paths[F_EMUCONFIG_IDX] = paths[D_CONFIG_IDX] + EMU_CONFIG;
paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG;
paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG;
break;
case D_DUMP_IDX:
paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP;
paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP;
paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP;
break;
case D_LOGS_IDX:
paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG;
} }
} }

@ -21,31 +21,11 @@ enum {
D_USER_IDX, D_USER_IDX,
D_ROOT_IDX, D_ROOT_IDX,
D_CONFIG_IDX, D_CONFIG_IDX,
D_GAMECONFIG_IDX,
D_MAPS_IDX,
D_CACHE_IDX, D_CACHE_IDX,
D_SHADERCACHE_IDX,
D_SHADERS_IDX,
D_STATESAVES_IDX,
D_SCREENSHOTS_IDX,
D_SDMC_IDX, D_SDMC_IDX,
D_NAND_IDX, D_NAND_IDX,
D_SYSDATA_IDX, D_SYSDATA_IDX,
D_HIRESTEXTURES_IDX,
D_DUMP_IDX,
D_DUMPFRAMES_IDX,
D_DUMPAUDIO_IDX,
D_DUMPTEXTURES_IDX,
D_DUMPDSP_IDX,
D_LOGS_IDX, D_LOGS_IDX,
D_SYSCONF_IDX,
F_EMUCONFIG_IDX,
F_DEBUGGERCONFIG_IDX,
F_LOGGERCONFIG_IDX,
F_MAINLOG_IDX,
F_RAMDUMP_IDX,
F_ARAMDUMP_IDX,
F_SYSCONF_IDX,
NUM_PATH_INDICES NUM_PATH_INDICES
}; };

@ -31,7 +31,6 @@ set(SRCS
file_sys/savedata_archive.cpp file_sys/savedata_archive.cpp
gdbstub/gdbstub.cpp gdbstub/gdbstub.cpp
hle/config_mem.cpp hle/config_mem.cpp
hle/hle.cpp
hle/applets/applet.cpp hle/applets/applet.cpp
hle/applets/erreula.cpp hle/applets/erreula.cpp
hle/applets/mii_selector.cpp hle/applets/mii_selector.cpp
@ -155,7 +154,6 @@ set(SRCS
tracer/recorder.cpp tracer/recorder.cpp
memory.cpp memory.cpp
settings.cpp settings.cpp
system.cpp
) )
set(HEADERS set(HEADERS
@ -196,7 +194,6 @@ set(HEADERS
gdbstub/gdbstub.h gdbstub/gdbstub.h
hle/config_mem.h hle/config_mem.h
hle/function_wrappers.h hle/function_wrappers.h
hle/hle.h
hle/ipc.h hle/ipc.h
hle/applets/applet.h hle/applets/applet.h
hle/applets/erreula.h hle/applets/erreula.h
@ -325,7 +322,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)

@ -8,15 +8,22 @@
#include "core/arm/skyeye_common/arm_regformat.h" #include "core/arm/skyeye_common/arm_regformat.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h" #include "core/arm/skyeye_common/vfp/asm_vfp.h"
namespace Core {
struct ThreadContext;
}
/// Generic ARM11 CPU interface /// Generic ARM11 CPU interface
class ARM_Interface : NonCopyable { class ARM_Interface : NonCopyable {
public: public:
virtual ~ARM_Interface() {} virtual ~ARM_Interface() {}
struct ThreadContext {
u32 cpu_registers[13];
u32 sp;
u32 lr;
u32 pc;
u32 cpsr;
u32 fpu_registers[64];
u32 fpscr;
u32 fpexc;
};
/** /**
* Runs the CPU for the given number of instructions * Runs the CPU for the given number of instructions
* @param num_instructions Number of instructions to run * @param num_instructions Number of instructions to run
@ -124,13 +131,13 @@ public:
* Saves the current CPU context * Saves the current CPU context
* @param ctx Thread context to save * @param ctx Thread context to save
*/ */
virtual void SaveContext(Core::ThreadContext& ctx) = 0; virtual void SaveContext(ThreadContext& ctx) = 0;
/** /**
* Loads a CPU context * Loads a CPU context
* @param ctx Thread context to load * @param ctx Thread context to load
*/ */
virtual void LoadContext(const Core::ThreadContext& ctx) = 0; virtual void LoadContext(const ThreadContext& ctx) = 0;
/// Prepare core for thread reschedule (if needed to correctly handle state) /// Prepare core for thread reschedule (if needed to correctly handle state)
virtual void PrepareReschedule() = 0; virtual void PrepareReschedule() = 0;

@ -137,7 +137,7 @@ void ARM_Dynarmic::ExecuteInstructions(int num_instructions) {
AddTicks(ticks_executed); AddTicks(ticks_executed);
} }
void ARM_Dynarmic::SaveContext(Core::ThreadContext& ctx) { void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
memcpy(ctx.cpu_registers, jit->Regs().data(), sizeof(ctx.cpu_registers)); memcpy(ctx.cpu_registers, jit->Regs().data(), sizeof(ctx.cpu_registers));
memcpy(ctx.fpu_registers, jit->ExtRegs().data(), sizeof(ctx.fpu_registers)); memcpy(ctx.fpu_registers, jit->ExtRegs().data(), sizeof(ctx.fpu_registers));
@ -150,7 +150,7 @@ void ARM_Dynarmic::SaveContext(Core::ThreadContext& ctx) {
ctx.fpexc = interpreter_state->VFP[VFP_FPEXC]; ctx.fpexc = interpreter_state->VFP[VFP_FPEXC];
} }
void ARM_Dynarmic::LoadContext(const Core::ThreadContext& ctx) { void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) {
memcpy(jit->Regs().data(), ctx.cpu_registers, sizeof(ctx.cpu_registers)); memcpy(jit->Regs().data(), ctx.cpu_registers, sizeof(ctx.cpu_registers));
memcpy(jit->ExtRegs().data(), ctx.fpu_registers, sizeof(ctx.fpu_registers)); memcpy(jit->ExtRegs().data(), ctx.fpu_registers, sizeof(ctx.fpu_registers));

@ -10,10 +10,6 @@
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/armstate.h"
namespace Core {
struct ThreadContext;
}
class ARM_Dynarmic final : public ARM_Interface { class ARM_Dynarmic final : public ARM_Interface {
public: public:
ARM_Dynarmic(PrivilegeMode initial_mode); ARM_Dynarmic(PrivilegeMode initial_mode);
@ -33,8 +29,8 @@ public:
void AddTicks(u64 ticks) override; void AddTicks(u64 ticks) override;
void SaveContext(Core::ThreadContext& ctx) override; void SaveContext(ThreadContext& ctx) override;
void LoadContext(const Core::ThreadContext& ctx) override; void LoadContext(const ThreadContext& ctx) override;
void PrepareReschedule() override; void PrepareReschedule() override;
void ExecuteInstructions(int num_instructions) override; void ExecuteInstructions(int num_instructions) override;

@ -89,7 +89,7 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
AddTicks(ticks_executed); AddTicks(ticks_executed);
} }
void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { void ARM_DynCom::SaveContext(ThreadContext& ctx) {
memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers)); memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers));
memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers)); memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers));
@ -102,7 +102,7 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
ctx.fpexc = state->VFP[VFP_FPEXC]; ctx.fpexc = state->VFP[VFP_FPEXC];
} }
void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers)); memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers));
memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers)); memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers));

@ -10,10 +10,6 @@
#include "core/arm/skyeye_common/arm_regformat.h" #include "core/arm/skyeye_common/arm_regformat.h"
#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/armstate.h"
namespace Core {
struct ThreadContext;
}
class ARM_DynCom final : public ARM_Interface { class ARM_DynCom final : public ARM_Interface {
public: public:
ARM_DynCom(PrivilegeMode initial_mode); ARM_DynCom(PrivilegeMode initial_mode);
@ -36,8 +32,8 @@ public:
void AddTicks(u64 ticks) override; void AddTicks(u64 ticks) override;
void SaveContext(Core::ThreadContext& ctx) override; void SaveContext(ThreadContext& ctx) override;
void LoadContext(const Core::ThreadContext& ctx) override; void LoadContext(const ThreadContext& ctx) override;
void PrepareReschedule() override; void PrepareReschedule() override;
void ExecuteInstructions(int num_instructions) override; void ExecuteInstructions(int num_instructions) override;

@ -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"
@ -10,18 +12,24 @@
#include "core/core.h" #include "core/core.h"
#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/kernel/kernel.h"
#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
#include "core/hle/service/service.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 (!cpu_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;
} }
} }
} }
@ -43,48 +51,114 @@ void RunLoop(int tight_loop) {
LOG_TRACE(Core_ARM11, "Idling"); LOG_TRACE(Core_ARM11, "Idling");
CoreTiming::Idle(); CoreTiming::Idle();
CoreTiming::Advance(); CoreTiming::Advance();
HLE::Reschedule(__func__); PrepareReschedule();
} else { } else {
g_app_core->Run(tight_loop); cpu_core->Run(tight_loop);
} }
HW::Update(); HW::Update();
if (HLE::IsReschedulePending()) { Reschedule();
Kernel::Reschedule();
return ResultStatus::Success;
}
System::ResultStatus System::SingleStep() {
return RunLoop(1);
}
System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
if (app_loader) {
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;
} }
/// Step the CPU one instruction void System::PrepareReschedule() {
void SingleStep() { cpu_core->PrepareReschedule();
RunLoop(1); reschedule_pending = true;
} }
/// Halt the core void System::Reschedule() {
void Halt(const char* msg) { if (!reschedule_pending) {
// TODO(ShizZy): ImplementMe return;
}
reschedule_pending = false;
Kernel::Reschedule();
} }
/// Kill the core System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
void Stop() { if (cpu_core) {
// TODO(ShizZy): ImplementMe cpu_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); cpu_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); cpu_core = std::make_unique<ARM_DynCom>(USER32MODE);
g_app_core = std::make_unique<ARM_DynCom>(USER32MODE); }
CoreTiming::Init();
HW::Init();
Kernel::Init(system_mode);
Service::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();
Service::Shutdown();
Kernel::Shutdown();
HW::Shutdown();
CoreTiming::Shutdown();
LOG_DEBUG(Core, "Shutdown OK"); LOG_DEBUG(Core, "Shutdown OK");
} }

@ -5,56 +5,118 @@
#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 {
struct ThreadContext { class System {
u32 cpu_registers[13]; public:
u32 sp; /**
u32 lr; * Gets the instance of the System singleton class.
u32 pc; * @returns Reference to the instance of the System singleton class.
u32 cpsr; */
u32 fpu_registers[64]; static System& GetInstance() {
u32 fpscr; return s_instance;
u32 fpexc; }
/// 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
};
/**
* 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);
/**
* Step the CPU one instruction
* @return Result status, indicating whethor or not the operation succeeded.
*/
ResultStatus SingleStep();
/// 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 cpu_core != nullptr;
}
/// Prepare the core emulation for a reschedule
void PrepareReschedule();
/**
* Gets a reference to the emulated CPU.
* @returns A reference to the emulated CPU.
*/
ARM_Interface& CPU() {
return *cpu_core;
}
private:
/**
* 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);
/// Reschedule the core emulation
void Reschedule();
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
///< ARM11 CPU core
std::unique_ptr<ARM_Interface> cpu_core;
/// When true, signals that a reschedule should happen
bool reschedule_pending{};
static System s_instance;
}; };
extern std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core static ARM_Interface& CPU() {
extern std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core return System::GetInstance().CPU();
}
//////////////////////////////////////////////////////////////////////////////////////////////////// } // namespace Core
/// Start the core
void Start();
/**
* 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).
*/
void RunLoop(int tight_loop = 1000);
/// Step the CPU one instruction
void SingleStep();
/// Halt the core
void Halt(const char* msg);
/// Kill the core
void Stop();
/// Initialize the core
void Init();
/// Shutdown the core
void Shutdown();
} // namespace

@ -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::CPU().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::CPU().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::CPU().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::CPU().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::CPU().down_count;
global_timer += cycles_executed; global_timer += cycles_executed;
Core::g_app_core->down_count = g_slice_length; Core::CPU().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::CPU().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::CPU().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::CPU().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::CPU().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::CPU().down_count -= cycles_down;
if (Core::g_app_core->down_count == 0) if (Core::CPU().down_count == 0)
Core::g_app_core->down_count = -1; Core::CPU().down_count = -1;
} }
std::string GetScheduledEventsSummary() { std::string GetScheduledEventsSummary() {

@ -141,11 +141,10 @@ std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path)
std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) { std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) {
if (shared) if (shared)
return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), SYSTEM_ID);
SYSTEM_ID.c_str());
return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), SYSTEM_ID,
SYSTEM_ID.c_str(), SDCARD_ID.c_str()); SDCARD_ID);
} }
Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) {

@ -19,7 +19,7 @@
namespace FileSys { namespace FileSys {
static std::string GetNCCHContainerPath(const std::string& nand_directory) { static std::string GetNCCHContainerPath(const std::string& nand_directory) {
return Common::StringFromFormat("%s%s/title/", nand_directory.c_str(), SYSTEM_ID.c_str()); return Common::StringFromFormat("%s%s/title/", nand_directory.c_str(), SYSTEM_ID);
} }
static std::string GetNCCHPath(const std::string& mount_point, u32 high, u32 low) { static std::string GetNCCHPath(const std::string& mount_point, u32 high, u32 low) {

@ -18,7 +18,7 @@ namespace {
std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { std::string GetSaveDataContainerPath(const std::string& sdmc_directory) {
return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(),
SYSTEM_ID.c_str(), SDCARD_ID.c_str()); SYSTEM_ID, SDCARD_ID);
} }
std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) { std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) {

@ -26,7 +26,7 @@ std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& pa
} }
std::string GetSystemSaveDataContainerPath(const std::string& mount_point) { std::string GetSystemSaveDataContainerPath(const std::string& mount_point) {
return Common::StringFromFormat("%sdata/%s/sysdata/", mount_point.c_str(), SYSTEM_ID.c_str()); return Common::StringFromFormat("%sdata/%s/sysdata/", mount_point.c_str(), SYSTEM_ID);
} }
Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low) { Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low) {

@ -35,6 +35,7 @@
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/core.h" #include "core/core.h"
#include "core/gdbstub/gdbstub.h" #include "core/gdbstub/gdbstub.h"
#include "core/loader/loader.h"
#include "core/memory.h" #include "core/memory.h"
const int GDB_BUFFER_SIZE = 10000; const int GDB_BUFFER_SIZE = 10000;
@ -449,9 +450,9 @@ 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 =
htonl(Core::g_app_core->GetPC()), 13, Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15,
htonl(Core::g_app_core->GetReg(13))); htonl(Core::CPU().GetPC()), 13, htonl(Core::CPU().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::CPU().GetReg(id));
} else if (id == CPSR_REGISTER) { } else if (id == CPSR_REGISTER) {
IntToGdbHex(reply, Core::g_app_core->GetCPSR()); IntToGdbHex(reply, Core::CPU().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::CPU().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::CPU().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::CPU().GetReg(reg));
} }
bufptr += (16 * CHAR_BIT); bufptr += (16 * CHAR_BIT);
IntToGdbHex(bufptr, Core::g_app_core->GetCPSR()); IntToGdbHex(bufptr, Core::CPU().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::CPU().GetVFPReg(reg));
} }
bufptr += (32 * CHAR_BIT); bufptr += (32 * CHAR_BIT);
IntToGdbHex(bufptr, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); IntToGdbHex(bufptr, Core::CPU().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::CPU().SetReg(id, GdbHexToInt(buffer_ptr));
} else if (id == CPSR_REGISTER) { } else if (id == CPSR_REGISTER) {
Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr)); Core::CPU().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::CPU().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::CPU().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr));
} else { } else {
return SendReply("E01"); return SendReply("E01");
} }
@ -618,20 +619,19 @@ 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::CPU().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::CPU().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::CPU().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::CPU().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
} }
} }
@ -908,7 +908,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 {

@ -7,14 +7,14 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/hle.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/svc.h" #include "core/hle/svc.h"
#include "core/memory.h" #include "core/memory.h"
namespace HLE { namespace HLE {
#define PARAM(n) Core::g_app_core->GetReg(n) #define PARAM(n) Core::CPU().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::CPU().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::CPU().SetReg(0, (u32)(res & 0xFFFFFFFF));
Core::g_app_core->SetReg(1, (u32)((res >> 32) & 0xFFFFFFFF)); Core::CPU().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(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().SetReg(1, param_1);
FuncReturn(retval); FuncReturn(retval);
} }
@ -57,19 +57,19 @@ template <ResultCode func(u32*, s32, u32, u32, u32, s32)>
void Wrap() { void Wrap() {
u32 param_1 = 0; u32 param_1 = 0;
u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().SetReg(1, param_1);
FuncReturn(retval); FuncReturn(retval);
} }
template <ResultCode func(s32*, u32*, s32, bool, s64)> template <ResultCode func(s32*, u32*, s32, bool, s64)>
void Wrap() { void Wrap() {
s32 param_1 = 0; s32 param_1 = 0;
s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), s32 retval = func(&param_1, (Kernel::Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2),
(PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))) (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0)))
.raw; .raw;
if (retval != RESULT_INVALID.raw) { if (retval != RESULT_INVALID.raw) {
Core::g_app_core->SetReg(1, (u32)param_1); Core::CPU().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(&param_1).raw; u32 retval = func(&param_1).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().SetReg(1, param_1);
FuncReturn(retval); FuncReturn(retval);
} }
@ -102,24 +102,24 @@ 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::CPU().SetReg(1, memory_info.base_address);
Core::g_app_core->SetReg(2, memory_info.size); Core::CPU().SetReg(2, memory_info.size);
Core::g_app_core->SetReg(3, memory_info.permission); Core::CPU().SetReg(3, memory_info.permission);
Core::g_app_core->SetReg(4, memory_info.state); Core::CPU().SetReg(4, memory_info.state);
Core::g_app_core->SetReg(5, page_info.flags); Core::CPU().SetReg(5, page_info.flags);
FuncReturn(retval); FuncReturn(retval);
} }
template <ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)> template <ResultCode func(MemoryInfo*, PageInfo*, Kernel::Handle, u32)>
void Wrap() { 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::CPU().SetReg(1, memory_info.base_address);
Core::g_app_core->SetReg(2, memory_info.size); Core::CPU().SetReg(2, memory_info.size);
Core::g_app_core->SetReg(3, memory_info.permission); Core::CPU().SetReg(3, memory_info.permission);
Core::g_app_core->SetReg(4, memory_info.state); Core::CPU().SetReg(4, memory_info.state);
Core::g_app_core->SetReg(5, page_info.flags); Core::CPU().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(&param_1, PARAM(1)).raw; u32 retval = func(&param_1, PARAM(1)).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().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(&param_1, PARAM(1)).raw; u32 retval = func(&param_1, PARAM(1)).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().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(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw; u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().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(&param_1, PARAM(1), PARAM(2)).raw; u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().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(&param_1, PARAM(1), PARAM(2)).raw; u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().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(&param_1, PARAM(1), PARAM(2)).raw; u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
Core::g_app_core->SetReg(1, (u32)param_1); Core::CPU().SetReg(1, (u32)param_1);
Core::g_app_core->SetReg(2, (u32)(param_1 >> 32)); Core::CPU().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(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw; u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw;
Core::g_app_core->SetReg(1, param_1); Core::CPU().SetReg(1, param_1);
FuncReturn(retval); FuncReturn(retval);
} }
@ -205,30 +205,30 @@ void Wrap() {
FuncReturn(func(PARAM(0), param1, param2).raw); FuncReturn(func(PARAM(0), param1, param2).raw);
} }
template <ResultCode func(s64*, Handle, u32)> template <ResultCode func(s64*, Kernel::Handle, u32)>
void Wrap() { void Wrap() {
s64 param_1 = 0; s64 param_1 = 0;
u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
Core::g_app_core->SetReg(1, (u32)param_1); Core::CPU().SetReg(1, (u32)param_1);
Core::g_app_core->SetReg(2, (u32)(param_1 >> 32)); Core::CPU().SetReg(2, (u32)(param_1 >> 32));
FuncReturn(retval); FuncReturn(retval);
} }
template <ResultCode func(Handle, u32)> template <ResultCode func(Kernel::Handle, u32)>
void Wrap() { void Wrap() {
FuncReturn(func(PARAM(0), PARAM(1)).raw); FuncReturn(func(PARAM(0), PARAM(1)).raw);
} }
template <ResultCode func(Handle*, Handle*, const char*, u32)> template <ResultCode func(Kernel::Handle*, Kernel::Handle*, const char*, u32)>
void Wrap() { void Wrap() {
Handle param_1 = 0; Kernel::Handle param_1 = 0;
Handle param_2 = 0; Kernel::Handle param_2 = 0;
u32 retval = func(&param_1, &param_2, u32 retval = func(&param_1, &param_2,
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::CPU().SetReg(1, param_2);
Core::g_app_core->SetReg(2, param_1); Core::CPU().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;
} }

@ -1,23 +0,0 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
typedef u32 Handle;
typedef s32 Result;
const Handle INVALID_HANDLE = 0;
namespace HLE {
void Reschedule(const char* reason);
bool IsReschedulePending();
void DoneRescheduling();
void Init();
void Shutdown();
} // namespace

@ -4,7 +4,6 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
#include "core/memory.h" #include "core/memory.h"

@ -11,11 +11,12 @@
#include <vector> #include <vector>
#include <boost/smart_ptr/intrusive_ptr.hpp> #include <boost/smart_ptr/intrusive_ptr.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/hle.h"
#include "core/hle/result.h" #include "core/hle/result.h"
namespace Kernel { namespace Kernel {
using Handle = u32;
class Thread; class Thread;
// TODO: Verify code // TODO: Verify code

@ -14,7 +14,6 @@
#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/armstate.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/memory.h" #include "core/hle/kernel/memory.h"
#include "core/hle/kernel/mutex.h" #include "core/hle/kernel/mutex.h"
@ -188,7 +187,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::CPU().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 +213,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::CPU().LoadContext(new_thread->context);
Core::g_app_core->SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); Core::CPU().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress());
} else { } else {
current_thread = nullptr; current_thread = nullptr;
} }
@ -330,7 +329,7 @@ void Thread::ResumeFromWait() {
ready_queue.push_back(current_priority, this); ready_queue.push_back(current_priority, this);
status = THREADSTATUS_READY; status = THREADSTATUS_READY;
HLE::Reschedule(__func__); Core::System::GetInstance().PrepareReschedule();
} }
/** /**
@ -385,9 +384,9 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t
* @param entry_point Address of entry point for execution * @param entry_point Address of entry point for execution
* @param arg User argument for thread * @param arg User argument for thread
*/ */
static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, static void ResetThreadContext(ARM_Interface::ThreadContext& context, u32 stack_top,
u32 arg) { u32 entry_point, u32 arg) {
memset(&context, 0, sizeof(Core::ThreadContext)); memset(&context, 0, sizeof(ARM_Interface::ThreadContext));
context.cpu_registers[0] = arg; context.cpu_registers[0] = arg;
context.pc = entry_point; context.pc = entry_point;
@ -545,8 +544,6 @@ void Reschedule() {
Thread* cur = GetCurrentThread(); Thread* cur = GetCurrentThread();
Thread* next = PopNextReadyThread(); Thread* next = PopNextReadyThread();
HLE::DoneRescheduling();
if (cur && next) { if (cur && next) {
LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId()); LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId());
} else if (cur) { } else if (cur) {

@ -10,8 +10,8 @@
#include <boost/container/flat_map.hpp> #include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp> #include <boost/container/flat_set.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/arm/arm_interface.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -158,7 +158,7 @@ public:
return !wait_objects.empty(); return !wait_objects.empty();
} }
Core::ThreadContext context; ARM_Interface::ThreadContext context;
u32 thread_id; u32 thread_id;

@ -23,7 +23,6 @@
#include "core/file_sys/archive_systemsavedata.h" #include "core/file_sys/archive_systemsavedata.h"
#include "core/file_sys/directory_backend.h" #include "core/file_sys/directory_backend.h"
#include "core/file_sys/file_backend.h" #include "core/file_sys/file_backend.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/fs/archive.h" #include "core/hle/service/fs/archive.h"
@ -46,9 +45,7 @@ struct hash<Service::FS::ArchiveIdCode> {
}; };
} }
/// TODO(Subv): Confirm length of these strings static constexpr Kernel::Handle INVALID_HANDLE{};
const std::string SYSTEM_ID = "00000000000000000000000000000000";
const std::string SDCARD_ID = "00000000000000000000000000000000";
namespace Service { namespace Service {
namespace FS { namespace FS {

@ -17,9 +17,9 @@ class FileBackend;
} }
/// The unique system identifier hash, also known as ID0 /// The unique system identifier hash, also known as ID0
extern const std::string SYSTEM_ID; static constexpr char SYSTEM_ID[]{"00000000000000000000000000000000"};
/// The scrambled SD card CID, also known as ID1 /// The scrambled SD card CID, also known as ID1
extern const std::string SDCARD_ID; static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"};
namespace Service { namespace Service {
namespace FS { namespace FS {

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/ir/ir.h" #include "core/hle/service/ir/ir.h"
#include "core/hle/service/ir/ir_rst.h" #include "core/hle/service/ir/ir_rst.h"
@ -36,7 +37,7 @@ void InitializeIrNopShared(Interface* self) {
u32 send_buff_size = cmd_buff[4]; u32 send_buff_size = cmd_buff[4];
u32 unk2 = cmd_buff[5]; u32 unk2 = cmd_buff[5];
u8 baud_rate = cmd_buff[6] & 0xFF; u8 baud_rate = cmd_buff[6] & 0xFF;
Handle handle = cmd_buff[8]; Kernel::Handle handle = cmd_buff[8];
if (Kernel::g_handle_table.IsValid(handle)) { if (Kernel::g_handle_table.IsValid(handle)) {
transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle); transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle);

@ -457,7 +457,7 @@ static void LoadCRO(Interface* self, bool link_on_load_bug_fix) {
} }
} }
Core::g_app_core->ClearInstructionCache(); Core::CPU().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::CPU().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::CPU().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::CPU().ClearInstructionCache();
cmd_buff[1] = result.raw; cmd_buff[1] = result.raw;
} }

@ -4,6 +4,7 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/mic_u.h" #include "core/hle/service/mic_u.h"
@ -50,7 +51,7 @@ static bool audio_buffer_loop;
static void MapSharedMem(Interface* self) { static void MapSharedMem(Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer(); u32* cmd_buff = Kernel::GetCommandBuffer();
u32 size = cmd_buff[1]; u32 size = cmd_buff[1];
Handle mem_handle = cmd_buff[3]; Kernel::Handle mem_handle = cmd_buff[3];
shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(mem_handle); shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(mem_handle);
if (shared_memory) { if (shared_memory) {
shared_memory->name = "MIC_U:shared_memory"; shared_memory->name = "MIC_U:shared_memory";

@ -166,7 +166,8 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
} }
/// Maps a memory block to specified address /// Maps a memory block to specified address
static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { static ResultCode MapMemoryBlock(Kernel::Handle handle, u32 addr, u32 permissions,
u32 other_permissions) {
using Kernel::SharedMemory; using Kernel::SharedMemory;
using Kernel::MemoryPermission; using Kernel::MemoryPermission;
@ -198,7 +199,7 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
ErrorSummary::InvalidArgument, ErrorLevel::Usage); ErrorSummary::InvalidArgument, ErrorLevel::Usage);
} }
static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) { static ResultCode UnmapMemoryBlock(Kernel::Handle handle, u32 addr) {
using Kernel::SharedMemory; using Kernel::SharedMemory;
LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X", handle, addr); LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X", handle, addr);
@ -213,7 +214,7 @@ static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
} }
/// Connect to an OS service given the port name, returns the handle to the port to out /// Connect to an OS service given the port name, returns the handle to the port to out
static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) { static ResultCode ConnectToPort(Kernel::Handle* out_handle, const char* port_name) {
if (port_name == nullptr) if (port_name == nullptr)
return ERR_NOT_FOUND; return ERR_NOT_FOUND;
if (std::strlen(port_name) > 11) if (std::strlen(port_name) > 11)
@ -238,7 +239,7 @@ static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) {
} }
/// Makes a blocking IPC call to an OS service. /// Makes a blocking IPC call to an OS service.
static ResultCode SendSyncRequest(Handle handle) { static ResultCode SendSyncRequest(Kernel::Handle handle) {
SharedPtr<Kernel::ClientSession> session = SharedPtr<Kernel::ClientSession> session =
Kernel::g_handle_table.Get<Kernel::ClientSession>(handle); Kernel::g_handle_table.Get<Kernel::ClientSession>(handle);
if (session == nullptr) { if (session == nullptr) {
@ -253,13 +254,13 @@ static ResultCode SendSyncRequest(Handle handle) {
} }
/// Close a handle /// Close a handle
static ResultCode CloseHandle(Handle handle) { static ResultCode CloseHandle(Kernel::Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle); LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle);
return Kernel::g_handle_table.Close(handle); return Kernel::g_handle_table.Close(handle);
} }
/// Wait for a handle to synchronize, timeout after the specified nanoseconds /// Wait for a handle to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) {
auto object = Kernel::g_handle_table.GetWaitObject(handle); auto object = Kernel::g_handle_table.GetWaitObject(handle);
Kernel::Thread* thread = Kernel::GetCurrentThread(); Kernel::Thread* thread = Kernel::GetCurrentThread();
@ -295,8 +296,8 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
} }
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 handle_count,
s64 nano_seconds) { bool wait_all, s64 nano_seconds) {
Kernel::Thread* thread = Kernel::GetCurrentThread(); Kernel::Thread* thread = Kernel::GetCurrentThread();
// Check if 'handles' is invalid // Check if 'handles' is invalid
@ -423,7 +424,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
} }
/// Create an address arbiter (to allocate access to shared resources) /// Create an address arbiter (to allocate access to shared resources)
static ResultCode CreateAddressArbiter(Handle* out_handle) { static ResultCode CreateAddressArbiter(Kernel::Handle* out_handle) {
using Kernel::AddressArbiter; using Kernel::AddressArbiter;
SharedPtr<AddressArbiter> arbiter = AddressArbiter::Create(); SharedPtr<AddressArbiter> arbiter = AddressArbiter::Create();
@ -433,7 +434,7 @@ static ResultCode CreateAddressArbiter(Handle* out_handle) {
} }
/// Arbitrate address /// Arbitrate address
static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, static ResultCode ArbitrateAddress(Kernel::Handle handle, u32 address, u32 type, u32 value,
s64 nanoseconds) { s64 nanoseconds) {
using Kernel::AddressArbiter; using Kernel::AddressArbiter;
@ -476,7 +477,7 @@ static void OutputDebugString(const char* string) {
} }
/// Get resource limit /// Get resource limit
static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { static ResultCode GetResourceLimit(Kernel::Handle* resource_limit, Kernel::Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
SharedPtr<Kernel::Process> process = SharedPtr<Kernel::Process> process =
@ -490,7 +491,7 @@ static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle
} }
/// Get resource limit current values /// Get resource limit current values
static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, static ResultCode GetResourceLimitCurrentValues(s64* values, Kernel::Handle resource_limit_handle,
u32* names, u32 name_count) { u32* names, u32 name_count) {
LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
resource_limit_handle, names, name_count); resource_limit_handle, names, name_count);
@ -507,8 +508,8 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim
} }
/// Get resource limit max values /// Get resource limit max values
static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, static ResultCode GetResourceLimitLimitValues(s64* values, Kernel::Handle resource_limit_handle,
u32 name_count) { u32* names, u32 name_count) {
LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
resource_limit_handle, names, name_count); resource_limit_handle, names, name_count);
@ -524,7 +525,7 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit
} }
/// Creates a new thread /// Creates a new thread
static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, static ResultCode CreateThread(Kernel::Handle* out_handle, s32 priority, u32 entry_point, u32 arg,
u32 stack_top, s32 processor_id) { u32 stack_top, s32 processor_id) {
using Kernel::Thread; using Kernel::Thread;
@ -582,13 +583,13 @@ 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::CPU().GetPC());
Kernel::ExitCurrentThread(); Kernel::ExitCurrentThread();
} }
/// Gets the priority for the specified thread /// Gets the priority for the specified thread
static ResultCode GetThreadPriority(s32* priority, Handle handle) { static ResultCode GetThreadPriority(s32* priority, Kernel::Handle handle) {
const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
if (thread == nullptr) if (thread == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -598,7 +599,7 @@ static ResultCode GetThreadPriority(s32* priority, Handle handle) {
} }
/// Sets the priority for the specified thread /// Sets the priority for the specified thread
static ResultCode SetThreadPriority(Handle handle, s32 priority) { static ResultCode SetThreadPriority(Kernel::Handle handle, s32 priority) {
SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
if (thread == nullptr) if (thread == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -608,11 +609,11 @@ static ResultCode SetThreadPriority(Handle handle, s32 priority) {
} }
/// Create a mutex /// Create a mutex
static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { static ResultCode CreateMutex(Kernel::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::CPU().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",
@ -622,7 +623,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
} }
/// Release a mutex /// Release a mutex
static ResultCode ReleaseMutex(Handle handle) { static ResultCode ReleaseMutex(Kernel::Handle handle) {
using Kernel::Mutex; using Kernel::Mutex;
LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle); LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle);
@ -637,7 +638,7 @@ static ResultCode ReleaseMutex(Handle handle) {
} }
/// Get the ID of the specified process /// Get the ID of the specified process
static ResultCode GetProcessId(u32* process_id, Handle process_handle) { static ResultCode GetProcessId(u32* process_id, Kernel::Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
const SharedPtr<Kernel::Process> process = const SharedPtr<Kernel::Process> process =
@ -650,7 +651,7 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
} }
/// Get the ID of the process that owns the specified thread /// Get the ID of the process that owns the specified thread
static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { static ResultCode GetProcessIdOfThread(u32* process_id, Kernel::Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
const SharedPtr<Kernel::Thread> thread = const SharedPtr<Kernel::Thread> thread =
@ -667,7 +668,7 @@ static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
} }
/// Get the ID for the specified thread. /// Get the ID for the specified thread.
static ResultCode GetThreadId(u32* thread_id, Handle handle) { static ResultCode GetThreadId(u32* thread_id, Kernel::Handle handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle);
const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
@ -679,11 +680,11 @@ static ResultCode GetThreadId(u32* thread_id, Handle handle) {
} }
/// Creates a semaphore /// Creates a semaphore
static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) { static ResultCode CreateSemaphore(Kernel::Handle* out_handle, s32 initial_count, s32 max_count) {
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::CPU().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",
@ -692,7 +693,7 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max
} }
/// Releases a certain number of slots in a semaphore /// Releases a certain number of slots in a semaphore
static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { static ResultCode ReleaseSemaphore(s32* count, Kernel::Handle handle, s32 release_count) {
using Kernel::Semaphore; using Kernel::Semaphore;
LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle); LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle);
@ -708,7 +709,7 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
/// Query process memory /// Query process memory
static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
Handle process_handle, u32 addr) { Kernel::Handle process_handle, u32 addr) {
using Kernel::Process; using Kernel::Process;
Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle);
if (process == nullptr) if (process == nullptr)
@ -736,11 +737,11 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32
} }
/// Create an event /// Create an event
static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { static ResultCode CreateEvent(Kernel::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::CPU().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,
@ -749,14 +750,14 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
} }
/// Duplicates a kernel handle /// Duplicates a kernel handle
static ResultCode DuplicateHandle(Handle* out, Handle handle) { static ResultCode DuplicateHandle(Kernel::Handle* out, Kernel::Handle handle) {
CASCADE_RESULT(*out, Kernel::g_handle_table.Duplicate(handle)); CASCADE_RESULT(*out, Kernel::g_handle_table.Duplicate(handle));
LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/// Signals an event /// Signals an event
static ResultCode SignalEvent(Handle handle) { static ResultCode SignalEvent(Kernel::Handle handle) {
using Kernel::Event; using Kernel::Event;
LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
@ -770,7 +771,7 @@ static ResultCode SignalEvent(Handle handle) {
} }
/// Clears an event /// Clears an event
static ResultCode ClearEvent(Handle handle) { static ResultCode ClearEvent(Kernel::Handle handle) {
using Kernel::Event; using Kernel::Event;
LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
@ -783,11 +784,11 @@ static ResultCode ClearEvent(Handle handle) {
} }
/// Creates a timer /// Creates a timer
static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { static ResultCode CreateTimer(Kernel::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::CPU().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,
@ -796,7 +797,7 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
} }
/// Clears a timer /// Clears a timer
static ResultCode ClearTimer(Handle handle) { static ResultCode ClearTimer(Kernel::Handle handle) {
using Kernel::Timer; using Kernel::Timer;
LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
@ -810,7 +811,7 @@ static ResultCode ClearTimer(Handle handle) {
} }
/// Starts a timer /// Starts a timer
static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { static ResultCode SetTimer(Kernel::Handle handle, s64 initial, s64 interval) {
using Kernel::Timer; using Kernel::Timer;
LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
@ -825,7 +826,7 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
} }
/// Cancels a timer /// Cancels a timer
static ResultCode CancelTimer(Handle handle) { static ResultCode CancelTimer(Kernel::Handle handle) {
using Kernel::Timer; using Kernel::Timer;
LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
@ -854,14 +855,13 @@ 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::CPU().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;
} }
/// Creates a memory block at the specified address with the specified permissions and size /// Creates a memory block at the specified address with the specified permissions and size
static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, static ResultCode CreateMemoryBlock(Kernel::Handle* out_handle, u32 addr, u32 size,
u32 other_permission) { u32 my_permission, u32 other_permission) {
using Kernel::SharedMemory; using Kernel::SharedMemory;
if (size % Memory::PAGE_SIZE != 0) if (size % Memory::PAGE_SIZE != 0)
@ -912,8 +912,8 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, static ResultCode CreatePort(Kernel::Handle* server_port, Kernel::Handle* client_port,
u32 max_sessions) { const char* name, u32 max_sessions) {
// TODO(Subv): Implement named ports. // TODO(Subv): Implement named ports.
ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented");
@ -978,7 +978,7 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { static ResultCode GetProcessInfo(s64* out, Kernel::Handle process_handle, u32 type) {
LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u", process_handle, type); LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u", process_handle, type);
using Kernel::Process; using Kernel::Process;
@ -1185,7 +1185,7 @@ void CallSVC(u32 immediate) {
if (info->func) { if (info->func) {
info->func(); info->func();
// TODO(Subv): Not all service functions should cause a reschedule in all cases. // TODO(Subv): Not all service functions should cause a reschedule in all cases.
HLE::Reschedule(__func__); Core::System::GetInstance().PrepareReschedule();
} else { } else {
LOG_ERROR(Kernel_SVC, "unimplemented SVC function %s(..)", info->name); LOG_ERROR(Kernel_SVC, "unimplemented SVC function %s(..)", info->name);
} }

@ -27,34 +27,14 @@ public:
*/ */
static FileType IdentifyType(FileUtil::IOFile& file); static FileType IdentifyType(FileUtil::IOFile& file);
/**
* Returns the type of this file
* @return FileType corresponding to the loaded file
*/
FileType GetFileType() override { FileType GetFileType() override {
return IdentifyType(file); return IdentifyType(file);
} }
/**
* Load the bootable file
* @return ResultStatus result of function
*/
ResultStatus Load() override; ResultStatus Load() override;
/**
* Get the icon (typically icon section) of the application
* @param buffer Reference to buffer to store data
* @return ResultStatus result of function
*/
ResultStatus ReadIcon(std::vector<u8>& buffer) override; ResultStatus ReadIcon(std::vector<u8>& buffer) override;
/**
* Get the RomFS of the application
* @param romfs_file Reference to buffer to store data
* @param offset Offset in the file to the RomFS
* @param size Size of the RomFS in bytes
* @return ResultStatus result of function
*/
ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
u64& size) override; u64& size) override;

@ -26,18 +26,10 @@ public:
*/ */
static FileType IdentifyType(FileUtil::IOFile& file); static FileType IdentifyType(FileUtil::IOFile& file);
/**
* Returns the type of this file
* @return FileType corresponding to the loaded file
*/
FileType GetFileType() override { FileType GetFileType() override {
return IdentifyType(file); return IdentifyType(file);
} }
/**
* Load the bootable file
* @return ResultStatus result of function
*/
ResultStatus Load() override; ResultStatus Load() override;
private: private:

@ -171,18 +171,10 @@ public:
*/ */
static FileType IdentifyType(FileUtil::IOFile& file); static FileType IdentifyType(FileUtil::IOFile& file);
/**
* Returns the type of this file
* @return FileType corresponding to the loaded file
*/
FileType GetFileType() override { FileType GetFileType() override {
return IdentifyType(file); return IdentifyType(file);
} }
/**
* Load the application
* @return ResultStatus result of function
*/
ResultStatus Load() override; ResultStatus Load() override;
/** /**
@ -191,32 +183,12 @@ public:
*/ */
boost::optional<u32> LoadKernelSystemMode(); boost::optional<u32> LoadKernelSystemMode();
/**
* Get the code (typically .code section) of the application
* @param buffer Reference to buffer to store data
* @return ResultStatus result of function
*/
ResultStatus ReadCode(std::vector<u8>& buffer) override; ResultStatus ReadCode(std::vector<u8>& buffer) override;
/**
* Get the icon (typically icon section) of the application
* @param buffer Reference to buffer to store data
* @return ResultStatus result of function
*/
ResultStatus ReadIcon(std::vector<u8>& buffer) override; ResultStatus ReadIcon(std::vector<u8>& buffer) override;
/**
* Get the banner (typically banner section) of the application
* @param buffer Reference to buffer to store data
* @return ResultStatus result of function
*/
ResultStatus ReadBanner(std::vector<u8>& buffer) override; ResultStatus ReadBanner(std::vector<u8>& buffer) override;
/**
* Get the logo (typically logo section) of the application
* @param buffer Reference to buffer to store data
* @return ResultStatus result of function
*/
ResultStatus ReadLogo(std::vector<u8>& buffer) override; ResultStatus ReadLogo(std::vector<u8>& buffer) override;
/** /**

@ -1,55 +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 System {
static bool is_powered_on{false};
Result Init(EmuWindow* emu_window, u32 system_mode) {
Core::Init();
CoreTiming::Init();
Memory::Init();
HW::Init();
Kernel::Init(system_mode);
HLE::Init();
if (!VideoCore::Init(emu_window)) {
return Result::ErrorInitVideoCore;
}
AudioCore::Init();
GDBStub::Init();
is_powered_on = true;
return Result::Success;
}
bool IsPoweredOn() {
return is_powered_on;
}
void Shutdown() {
GDBStub::Shutdown();
AudioCore::Shutdown();
VideoCore::Shutdown();
HLE::Shutdown();
Kernel::Shutdown();
HW::Shutdown();
CoreTiming::Shutdown();
Core::Shutdown();
is_powered_on = false;
}
} // namespace

@ -1,21 +0,0 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
class EmuWindow;
namespace System {
enum class Result {
Success, ///< Everything is fine
Error, ///< Something went wrong (no module specified)
ErrorInitCore, ///< Something went wrong during core init
ErrorInitVideoCore, ///< Something went wrong during video core init
};
Result Init(EmuWindow* emu_window, u32 system_mode);
bool IsPoweredOn();
void Shutdown();
}