#pragma once //license: GPLv3 //started: 2004-10-14 #include #include #include #include #include #include #include #include #include #include extern "C" { #include #include } namespace SuperFamicom { #define platform Emulator::platform namespace File = Emulator::File; using Random = Emulator::Random; using Cheat = Emulator::Cheat; extern Random random; extern Cheat cheat; struct Scheduler { enum class Mode : uint { Run, Synchronize } mode; enum class Event : uint { Frame, Synchronized, Desynchronized } event; cothread_t host = nullptr; cothread_t active = nullptr; bool desynchronized = false; bool StepOnce = false; auto enter() -> void { host = co_active(); co_switch(active); } auto leave(Event event_) -> void { event = event_; active = co_active(); co_switch(host); } auto resume(cothread_t thread) -> void { if(mode == Mode::Synchronize) desynchronized = true; co_switch(thread); } inline auto synchronizing() const -> bool { return mode == Mode::Synchronize; } inline auto synchronize() -> void { if(mode == Mode::Synchronize) { if(desynchronized) { desynchronized = false; leave(Event::Desynchronized); } else { leave(Event::Synchronized); } } } inline auto desynchronize() -> void { desynchronized = true; } }; extern Scheduler scheduler; struct Thread { enum : uint { Size = 4_KiB * sizeof(void*) }; auto create(auto (*entrypoint)() -> void, uint frequency_) -> void { if(thread) co_delete(thread); thread = co_create(Thread::Size, entrypoint); frequency = frequency_; clock = 0; } auto active() const -> bool { return thread == co_active(); } auto serialize(serializer& s) -> void { s.integer(frequency); s.integer(clock); } auto serializeStack(serializer& s) -> void { static uint8_t stack[Thread::Size]; bool active = co_active() == thread; if(s.mode() == serializer::Size) { s.array(stack, Thread::Size); s.boolean(active); } if(s.mode() == serializer::Load) { s.array(stack, Thread::Size); s.boolean(active); memory::copy(thread, stack, Thread::Size); if(active) scheduler.active = thread; } if(s.mode() == serializer::Save) { memory::copy(stack, thread, Thread::Size); s.array(stack, Thread::Size); s.boolean(active); } } cothread_t thread = nullptr; uint32_t frequency = 0; int64_t clock = 0; }; struct Region { static inline auto NTSC() -> bool; static inline auto PAL() -> bool; }; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include } #include