hle.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <vector>
  5. #include "common/profiler.h"
  6. #include "core/arm/arm_interface.h"
  7. #include "core/mem_map.h"
  8. #include "core/hle/hle.h"
  9. #include "core/hle/config_mem.h"
  10. #include "core/hle/shared_page.h"
  11. #include "core/hle/kernel/thread.h"
  12. #include "core/hle/service/service.h"
  13. ////////////////////////////////////////////////////////////////////////////////////////////////////
  14. namespace HLE {
  15. Common::Profiling::TimingCategory profiler_svc("SVC Calls");
  16. static std::vector<ModuleDef> g_module_db;
  17. bool g_reschedule = false; ///< If true, immediately reschedules the CPU to a new thread
  18. static const FunctionDef* GetSVCInfo(u32 opcode) {
  19. u32 func_num = opcode & 0xFFFFFF; // 8 bits
  20. if (func_num > 0xFF) {
  21. LOG_ERROR(Kernel_SVC,"unknown svc=0x%02X", func_num);
  22. return nullptr;
  23. }
  24. return &g_module_db[0].func_table[func_num];
  25. }
  26. void CallSVC(u32 opcode) {
  27. Common::Profiling::ScopeTimer timer_svc(profiler_svc);
  28. const FunctionDef *info = GetSVCInfo(opcode);
  29. if (!info) {
  30. return;
  31. }
  32. if (info->func) {
  33. info->func();
  34. } else {
  35. LOG_ERROR(Kernel_SVC, "unimplemented SVC function %s(..)", info->name.c_str());
  36. }
  37. }
  38. void Reschedule(const char *reason) {
  39. DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256, "Reschedule: Invalid or too long reason.");
  40. // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE
  41. // routines. This simulates that time by artificially advancing the number of CPU "ticks".
  42. // The value was chosen empirically, it seems to work well enough for everything tested, but
  43. // is likely not ideal. We should find a more accurate way to simulate timing with HLE.
  44. Core::g_app_core->AddTicks(4000);
  45. Core::g_app_core->PrepareReschedule();
  46. g_reschedule = true;
  47. }
  48. void RegisterModule(std::string name, int num_functions, const FunctionDef* func_table) {
  49. ModuleDef module = {name, num_functions, func_table};
  50. g_module_db.push_back(module);
  51. }
  52. static void RegisterAllModules() {
  53. SVC::Register();
  54. }
  55. void Init() {
  56. Service::Init();
  57. RegisterAllModules();
  58. ConfigMem::Init();
  59. SharedPage::Init();
  60. LOG_DEBUG(Kernel, "initialized OK");
  61. }
  62. void Shutdown() {
  63. Service::Shutdown();
  64. g_module_db.clear();
  65. LOG_DEBUG(Kernel, "shutdown OK");
  66. }
  67. } // namespace