diff --git a/CMakeLists.txt b/CMakeLists.txt index b4b1503a..e557c5c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,7 +244,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp include/services/news_u.hpp include/applets/software_keyboard.hpp include/applets/applet_manager.hpp include/fs/archive_user_save_data.hpp include/services/amiibo_device.hpp include/services/nfc_types.hpp include/swap.hpp include/services/csnd.hpp include/services/nwm_uds.hpp include/fs/archive_system_save_data.hpp include/lua_manager.hpp include/memory_mapped_file.hpp include/hydra_icon.hpp - include/PICA/dynapica/shader_rec_emitter_arm64.hpp + include/PICA/dynapica/shader_rec_emitter_arm64.hpp include/scheduler.hpp ) cmrc_add_resource_library( diff --git a/include/cpu_dynarmic.hpp b/include/cpu_dynarmic.hpp index 8f1e277b..e45705de 100644 --- a/include/cpu_dynarmic.hpp +++ b/include/cpu_dynarmic.hpp @@ -9,6 +9,7 @@ #include "helpers.hpp" #include "kernel.hpp" #include "memory.hpp" +#include "scheduler.hpp" class CPU; @@ -112,15 +113,16 @@ public: }; class CPU { - std::unique_ptr jit; - std::shared_ptr cp15; + std::unique_ptr jit; + std::shared_ptr cp15; - // Make exclusive monitor with only 1 CPU core - Dynarmic::ExclusiveMonitor exclusiveMonitor{1}; - MyEnvironment env; - Memory& mem; + // Make exclusive monitor with only 1 CPU core + Dynarmic::ExclusiveMonitor exclusiveMonitor{1}; + MyEnvironment env; + Memory& mem; + Scheduler scheduler; -public: + public: static constexpr u64 ticksPerSec = 268111856; CPU(Memory& mem, Kernel& kernel); diff --git a/include/scheduler.hpp b/include/scheduler.hpp new file mode 100644 index 00000000..e941259c --- /dev/null +++ b/include/scheduler.hpp @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include +#include + +#include "helpers.hpp" + +struct Scheduler { + enum class EventType { + VBlank = 0, // End of frame event + Panic = 1, // Dummy event that is always pending and should never be triggered (Timestamp = UINT64_MAX) + TotalNumberOfEvents // How many event types do we have in total? + }; + static constexpr usize totalNumberOfEvents = static_cast(EventType::TotalNumberOfEvents); + + template + using EventMap = boost::container::flat_multimap, boost::container::static_vector, size>>; + + EventMap events; + u64 currentTimestamp = 0; + u64 nextTimestamp = 0; + + // Set nextTimestamp to the timestamp of the next event + void updateNextTimestamp() { nextTimestamp = events.cbegin()->first; } + void addCycles(u64 cycles) { currentTimestamp += cycles; } + + void addEvent(EventType type, u64 timestamp) { + events.emplace(timestamp, type); + updateNextTimestamp(); + } + + void removeEvent(EventType type) { + auto it = std::ranges::find_if(events, [type](decltype(events)::const_reference pair) { return pair.second == type; }); + + if (it != events.end()) { + events.erase(it); + updateNextTimestamp(); + } + }; + + void reset() { + currentTimestamp = 0; + + // Clear any pending events + events.clear(); + // Add a dummy event to always keep the scheduler non-empty + addEvent(EventType::Panic, std::numeric_limits::max()); + } +}; \ No newline at end of file diff --git a/src/core/CPU/cpu_dynarmic.cpp b/src/core/CPU/cpu_dynarmic.cpp index 29ca49d1..62e484be 100644 --- a/src/core/CPU/cpu_dynarmic.cpp +++ b/src/core/CPU/cpu_dynarmic.cpp @@ -1,32 +1,37 @@ #ifdef CPU_DYNARMIC #include "cpu_dynarmic.hpp" + #include "arm_defs.hpp" CPU::CPU(Memory& mem, Kernel& kernel) : mem(mem), env(mem, kernel) { - cp15 = std::make_shared(); + cp15 = std::make_shared(); - Dynarmic::A32::UserConfig config; - config.arch_version = Dynarmic::A32::ArchVersion::v6K; - config.callbacks = &env; - config.coprocessors[15] = cp15; - config.define_unpredictable_behaviour = true; - config.global_monitor = &exclusiveMonitor; - config.processor_id = 0; - - jit = std::make_unique(config); + Dynarmic::A32::UserConfig config; + config.arch_version = Dynarmic::A32::ArchVersion::v6K; + config.callbacks = &env; + config.coprocessors[15] = cp15; + config.define_unpredictable_behaviour = true; + config.global_monitor = &exclusiveMonitor; + config.processor_id = 0; + + jit = std::make_unique(config); } void CPU::reset() { - setCPSR(CPSR::UserMode); - setFPSCR(FPSCR::MainThreadDefault); - env.totalTicks = 0; + setCPSR(CPSR::UserMode); + setFPSCR(FPSCR::MainThreadDefault); + env.totalTicks = 0; - cp15->reset(); - cp15->setTLSBase(VirtualAddrs::TLSBase); // Set cp15 TLS pointer to the main thread's thread-local storage - jit->Reset(); - jit->ClearCache(); - jit->Regs().fill(0); - jit->ExtRegs().fill(0); + cp15->reset(); + cp15->setTLSBase(VirtualAddrs::TLSBase); // Set cp15 TLS pointer to the main thread's thread-local storage + jit->Reset(); + jit->ClearCache(); + jit->Regs().fill(0); + jit->ExtRegs().fill(0); + + // Reset scheduler and add a VBlank event + scheduler.reset(); + scheduler.addEvent(Scheduler::EventType::VBlank, ticksPerSec / 60); } -#endif // CPU_DYNARMIC \ No newline at end of file +#endif // CPU_DYNARMIC \ No newline at end of file