core.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <memory>
  5. #include "audio_core/audio_core.h"
  6. #include "common/logging/log.h"
  7. #include "core/arm/arm_interface.h"
  8. #include "core/arm/dynarmic/arm_dynarmic.h"
  9. #include "core/arm/dyncom/arm_dyncom.h"
  10. #include "core/core.h"
  11. #include "core/core_timing.h"
  12. #include "core/gdbstub/gdbstub.h"
  13. #include "core/hle/kernel/kernel.h"
  14. #include "core/hle/kernel/memory.h"
  15. #include "core/hle/kernel/thread.h"
  16. #include "core/hle/service/service.h"
  17. #include "core/hw/hw.h"
  18. #include "core/loader/loader.h"
  19. #include "core/settings.h"
  20. #include "video_core/video_core.h"
  21. namespace Core {
  22. /*static*/ System System::s_instance;
  23. System::ResultStatus System::RunLoop(int tight_loop) {
  24. if (!cpu_core) {
  25. return ResultStatus::ErrorNotInitialized;
  26. }
  27. if (GDBStub::IsServerEnabled()) {
  28. GDBStub::HandlePacket();
  29. // If the loop is halted and we want to step, use a tiny (1) number of instructions to
  30. // execute. Otherwise, get out of the loop function.
  31. if (GDBStub::GetCpuHaltFlag()) {
  32. if (GDBStub::GetCpuStepFlag()) {
  33. GDBStub::SetCpuStepFlag(false);
  34. tight_loop = 1;
  35. } else {
  36. return ResultStatus::Success;
  37. }
  38. }
  39. }
  40. // If we don't have a currently active thread then don't execute instructions,
  41. // instead advance to the next event and try to yield to the next thread
  42. if (Kernel::GetCurrentThread() == nullptr) {
  43. LOG_TRACE(Core_ARM11, "Idling");
  44. CoreTiming::Idle();
  45. CoreTiming::Advance();
  46. PrepareReschedule();
  47. } else {
  48. cpu_core->Run(tight_loop);
  49. }
  50. HW::Update();
  51. Reschedule();
  52. return ResultStatus::Success;
  53. }
  54. System::ResultStatus System::SingleStep() {
  55. return RunLoop(1);
  56. }
  57. System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
  58. app_loader = Loader::GetLoader(filepath);
  59. if (!app_loader) {
  60. LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str());
  61. return ResultStatus::ErrorGetLoader;
  62. }
  63. boost::optional<u32> system_mode{app_loader->LoadKernelSystemMode()};
  64. if (!system_mode) {
  65. LOG_CRITICAL(Core, "Failed to determine system mode!");
  66. return ResultStatus::ErrorSystemMode;
  67. }
  68. ResultStatus init_result{Init(emu_window, system_mode.get())};
  69. if (init_result != ResultStatus::Success) {
  70. LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!", init_result);
  71. System::Shutdown();
  72. return init_result;
  73. }
  74. const Loader::ResultStatus load_result{app_loader->Load()};
  75. if (Loader::ResultStatus::Success != load_result) {
  76. LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result);
  77. System::Shutdown();
  78. switch (load_result) {
  79. case Loader::ResultStatus::ErrorEncrypted:
  80. return ResultStatus::ErrorLoader_ErrorEncrypted;
  81. case Loader::ResultStatus::ErrorInvalidFormat:
  82. return ResultStatus::ErrorLoader_ErrorInvalidFormat;
  83. default:
  84. return ResultStatus::ErrorLoader;
  85. }
  86. }
  87. return ResultStatus::Success;
  88. }
  89. void System::PrepareReschedule() {
  90. cpu_core->PrepareReschedule();
  91. reschedule_pending = true;
  92. }
  93. PerfStats::Results System::GetAndResetPerfStats() {
  94. auto perf_stats = this->perf_stats.Lock();
  95. return perf_stats->GetAndResetStats(CoreTiming::GetGlobalTimeUs());
  96. }
  97. void System::Reschedule() {
  98. if (!reschedule_pending) {
  99. return;
  100. }
  101. reschedule_pending = false;
  102. Kernel::Reschedule();
  103. }
  104. System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
  105. Memory::Init();
  106. if (Settings::values.use_cpu_jit) {
  107. cpu_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
  108. } else {
  109. cpu_core = std::make_unique<ARM_DynCom>(USER32MODE);
  110. }
  111. CoreTiming::Init();
  112. HW::Init();
  113. Kernel::Init(system_mode);
  114. Service::Init();
  115. AudioCore::Init();
  116. GDBStub::Init();
  117. if (!VideoCore::Init(emu_window)) {
  118. return ResultStatus::ErrorVideoCore;
  119. }
  120. LOG_DEBUG(Core, "Initialized OK");
  121. // Reset counters and set time origin to current frame
  122. GetAndResetPerfStats();
  123. perf_stats.Lock()->BeginSystemFrame();
  124. return ResultStatus::Success;
  125. }
  126. void System::Shutdown() {
  127. GDBStub::Shutdown();
  128. AudioCore::Shutdown();
  129. VideoCore::Shutdown();
  130. Service::Shutdown();
  131. Kernel::Shutdown();
  132. HW::Shutdown();
  133. CoreTiming::Shutdown();
  134. cpu_core = nullptr;
  135. app_loader = nullptr;
  136. LOG_DEBUG(Core, "Shutdown OK");
  137. }
  138. } // namespace