mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-14 03:44:23 +02:00
v111.4
Serialization improvements.
This commit is contained in:
@@ -29,7 +29,7 @@ using namespace nall;
|
|||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "bsnes";
|
static const string Name = "bsnes";
|
||||||
static const string Version = "111.3";
|
static const string Version = "111.4";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "https://byuu.org";
|
static const string Website = "https://byuu.org";
|
||||||
|
@@ -7,14 +7,13 @@ namespace SuperFamicom {
|
|||||||
ArmDSP armdsp;
|
ArmDSP armdsp;
|
||||||
|
|
||||||
auto ArmDSP::synchronizeCPU() -> void {
|
auto ArmDSP::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ArmDSP::Enter() -> void {
|
auto ArmDSP::Enter() -> void {
|
||||||
armdsp.boot();
|
armdsp.boot();
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
armdsp.main();
|
armdsp.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,13 +8,12 @@ namespace SuperFamicom {
|
|||||||
EpsonRTC epsonrtc;
|
EpsonRTC epsonrtc;
|
||||||
|
|
||||||
auto EpsonRTC::synchronizeCPU() -> void {
|
auto EpsonRTC::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto EpsonRTC::Enter() -> void {
|
auto EpsonRTC::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
epsonrtc.main();
|
epsonrtc.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,13 +6,12 @@ namespace SuperFamicom {
|
|||||||
Event event;
|
Event event;
|
||||||
|
|
||||||
auto Event::synchronizeCPU() -> void {
|
auto Event::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Event::Enter() -> void {
|
auto Event::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
event.main();
|
event.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,13 +9,12 @@ namespace SuperFamicom {
|
|||||||
HitachiDSP hitachidsp;
|
HitachiDSP hitachidsp;
|
||||||
|
|
||||||
auto HitachiDSP::synchronizeCPU() -> void {
|
auto HitachiDSP::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HitachiDSP::Enter() -> void {
|
auto HitachiDSP::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
hitachidsp.main();
|
hitachidsp.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -48,13 +48,15 @@ namespace SameBoy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto ICD::synchronizeCPU() -> void {
|
auto ICD::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) {
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
scheduler.desynchronize();
|
||||||
|
co_switch(cpu.thread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ICD::Enter() -> void {
|
auto ICD::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
icd.main();
|
icd.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,14 +7,13 @@ MSU1 msu1;
|
|||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
|
|
||||||
auto MSU1::synchronizeCPU() -> void {
|
auto MSU1::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto MSU1::Enter() -> void {
|
auto MSU1::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
msu1.main();
|
msu1.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,13 +7,12 @@ namespace SuperFamicom {
|
|||||||
NECDSP necdsp;
|
NECDSP necdsp;
|
||||||
|
|
||||||
auto NECDSP::synchronizeCPU() -> void {
|
auto NECDSP::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto NECDSP::Enter() -> void {
|
auto NECDSP::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
necdsp.main();
|
necdsp.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,13 +12,15 @@ namespace SuperFamicom {
|
|||||||
SA1 sa1;
|
SA1 sa1;
|
||||||
|
|
||||||
auto SA1::synchronizeCPU() -> void {
|
auto SA1::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) {
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
scheduler.desynchronize();
|
||||||
|
co_switch(cpu.thread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SA1::Enter() -> void {
|
auto SA1::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
sa1.main();
|
sa1.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
//Super Accelerator (SA-1)
|
//Super Accelerator (SA-1)
|
||||||
|
|
||||||
struct SA1 : Processor::WDC65816, Thread {
|
struct SA1 : Processor::WDC65816, Thread {
|
||||||
inline auto synchronizing() const -> bool override { return scheduler.synchronizingAll(); }
|
inline auto synchronizing() const -> bool override { return scheduler.synchronizing(); }
|
||||||
|
|
||||||
//sa1.cpp
|
//sa1.cpp
|
||||||
auto synchronizeCPU() -> void;
|
auto synchronizeCPU() -> void;
|
||||||
|
@@ -8,13 +8,12 @@ namespace SuperFamicom {
|
|||||||
SharpRTC sharprtc;
|
SharpRTC sharprtc;
|
||||||
|
|
||||||
auto SharpRTC::synchronizeCPU() -> void {
|
auto SharpRTC::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SharpRTC::Enter() -> void {
|
auto SharpRTC::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
sharprtc.main();
|
sharprtc.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,13 +17,12 @@ SPC7110::~SPC7110() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto SPC7110::synchronizeCPU() -> void {
|
auto SPC7110::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC7110::Enter() -> void {
|
auto SPC7110::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
spc7110.main();
|
spc7110.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,13 +12,12 @@ namespace SuperFamicom {
|
|||||||
SuperFX superfx;
|
SuperFX superfx;
|
||||||
|
|
||||||
auto SuperFX::synchronizeCPU() -> void {
|
auto SuperFX::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::Enter() -> void {
|
auto SuperFX::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
superfx.main();
|
superfx.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@ struct SuperFX : Processor::GSU, Thread {
|
|||||||
ReadableMemory rom;
|
ReadableMemory rom;
|
||||||
WritableMemory ram;
|
WritableMemory ram;
|
||||||
|
|
||||||
inline auto synchronizing() const -> bool { return scheduler.synchronizingAll(); }
|
inline auto synchronizing() const -> bool { return scheduler.synchronizing(); }
|
||||||
|
|
||||||
//superfx.cpp
|
//superfx.cpp
|
||||||
auto synchronizeCPU() -> void;
|
auto synchronizeCPU() -> void;
|
||||||
|
@@ -11,26 +11,22 @@ CPU cpu;
|
|||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
|
|
||||||
auto CPU::synchronizeSMP() -> void {
|
auto CPU::synchronizeSMP() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(smp.clock < 0) scheduler.resume(smp.thread);
|
||||||
if(smp.clock < 0) co_switch(smp.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::synchronizePPU() -> void {
|
auto CPU::synchronizePPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(ppu.clock < 0) scheduler.resume(ppu.thread);
|
||||||
if(ppu.clock < 0) co_switch(ppu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::synchronizeCoprocessors() -> void {
|
auto CPU::synchronizeCoprocessors() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
|
||||||
for(auto coprocessor : coprocessors) {
|
for(auto coprocessor : coprocessors) {
|
||||||
if(coprocessor->clock < 0) co_switch(coprocessor->thread);
|
if(coprocessor->clock < 0) scheduler.resume(coprocessor->thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::Enter() -> void {
|
auto CPU::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeCPU();
|
scheduler.synchronize();
|
||||||
scheduler.synchronizeAll();
|
|
||||||
cpu.main();
|
cpu.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@ struct CPU : Processor::WDC65816, Thread, PPUcounter {
|
|||||||
inline auto interruptPending() const -> bool override { return status.interruptPending; }
|
inline auto interruptPending() const -> bool override { return status.interruptPending; }
|
||||||
inline auto pio() const -> uint8 { return io.pio; }
|
inline auto pio() const -> uint8 { return io.pio; }
|
||||||
inline auto refresh() const -> bool { return status.dramRefresh == 1; }
|
inline auto refresh() const -> bool { return status.dramRefresh == 1; }
|
||||||
inline auto synchronizing() const -> bool override { return scheduler.mode == Scheduler::Mode::SynchronizeCPU; }
|
inline auto synchronizing() const -> bool override { return scheduler.synchronizing(); }
|
||||||
|
|
||||||
//cpu.cpp
|
//cpu.cpp
|
||||||
auto synchronizeSMP() -> void;
|
auto synchronizeSMP() -> void;
|
||||||
|
@@ -69,13 +69,12 @@ PPU::~PPU() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::synchronizeCPU() -> void {
|
auto PPU::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(ppubase.clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(ppubase.clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::Enter() -> void {
|
auto PPU::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
ppu.main();
|
ppu.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -39,8 +39,7 @@ PPU::~PPU() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::synchronizeCPU() -> void {
|
auto PPU::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::step() -> void {
|
auto PPU::step() -> void {
|
||||||
@@ -60,7 +59,7 @@ auto PPU::step(uint clocks) -> void {
|
|||||||
|
|
||||||
auto PPU::Enter() -> void {
|
auto PPU::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
ppu.main();
|
ppu.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,11 +28,12 @@ namespace SuperFamicom {
|
|||||||
extern Cheat cheat;
|
extern Cheat cheat;
|
||||||
|
|
||||||
struct Scheduler {
|
struct Scheduler {
|
||||||
enum class Mode : uint { Run, SynchronizeCPU, SynchronizeAll } mode;
|
enum class Mode : uint { Run, Synchronize } mode;
|
||||||
enum class Event : uint { Frame, Synchronize } event;
|
enum class Event : uint { Frame, Synchronized, Desynchronized } event;
|
||||||
|
|
||||||
cothread_t host = nullptr;
|
cothread_t host = nullptr;
|
||||||
cothread_t active = nullptr;
|
cothread_t active = nullptr;
|
||||||
|
bool desynchronized = false;
|
||||||
|
|
||||||
auto enter() -> void {
|
auto enter() -> void {
|
||||||
host = co_active();
|
host = co_active();
|
||||||
@@ -45,20 +46,28 @@ namespace SuperFamicom {
|
|||||||
co_switch(host);
|
co_switch(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto synchronizingCPU() const -> bool {
|
auto resume(cothread_t thread) -> void {
|
||||||
return mode == Mode::SynchronizeCPU;
|
if(mode == Mode::Synchronize) desynchronized = true;
|
||||||
|
co_switch(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto synchronizingAll() const -> bool {
|
inline auto synchronizing() const -> bool {
|
||||||
return mode == Mode::SynchronizeAll;
|
return mode == Mode::Synchronize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto synchronizeCPU() -> void {
|
inline auto synchronize() -> void {
|
||||||
if(mode == Mode::SynchronizeCPU) leave(Event::Synchronize);
|
if(mode == Mode::Synchronize) {
|
||||||
|
if(desynchronized) {
|
||||||
|
desynchronized = false;
|
||||||
|
leave(Event::Desynchronized);
|
||||||
|
} else {
|
||||||
|
leave(Event::Synchronized);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto synchronizeAll() -> void {
|
inline auto desynchronize() -> void {
|
||||||
if(mode == Mode::SynchronizeAll) leave(Event::Synchronize);
|
desynchronized = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
|
@@ -13,13 +13,12 @@ BSMemory::BSMemory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto BSMemory::synchronizeCPU() -> void {
|
auto BSMemory::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) scheduler.resume(cpu.thread);
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BSMemory::Enter() -> void {
|
auto BSMemory::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
bsmemory.main();
|
bsmemory.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,8 +9,10 @@ SMP smp;
|
|||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
|
|
||||||
auto SMP::synchronizeCPU() -> void {
|
auto SMP::synchronizeCPU() -> void {
|
||||||
if(scheduler.synchronizingAll()) return;
|
if(clock >= 0) {
|
||||||
if(clock >= 0) co_switch(cpu.thread);
|
scheduler.desynchronize();
|
||||||
|
co_switch(cpu.thread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SMP::synchronizeDSP() -> void {
|
auto SMP::synchronizeDSP() -> void {
|
||||||
@@ -19,7 +21,7 @@ auto SMP::synchronizeDSP() -> void {
|
|||||||
|
|
||||||
auto SMP::Enter() -> void {
|
auto SMP::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.synchronizeAll();
|
scheduler.synchronize();
|
||||||
smp.main();
|
smp.main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
//Sony CXP1100Q-1
|
//Sony CXP1100Q-1
|
||||||
|
|
||||||
struct SMP : Processor::SPC700, Thread {
|
struct SMP : Processor::SPC700, Thread {
|
||||||
inline auto synchronizing() const -> bool override { return scheduler.synchronizingAll(); }
|
inline auto synchronizing() const -> bool override { return scheduler.synchronizing(); }
|
||||||
|
|
||||||
//io.cpp
|
//io.cpp
|
||||||
auto portRead(uint2 port) const -> uint8;
|
auto portRead(uint2 port) const -> uint8;
|
||||||
|
@@ -15,44 +15,47 @@ auto System::run() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto System::runToSave() -> void {
|
auto System::runToSave() -> void {
|
||||||
//run the CPU thread normally, exiting once we reach the next synchronization point.
|
while(true) {
|
||||||
//the CPU thread may run in the pathological case for up to 10 frames for a long 8-channel x 64KB DMA transfer.
|
//SMP thread is synchronized twice to ensure the CPU and SMP are closely aligned:
|
||||||
//in practice, this will typically be at most one DMA transfer.
|
//this is extremely critical for Tales of Phantasia and Star Ocean.
|
||||||
scheduler.mode = Scheduler::Mode::SynchronizeCPU;
|
scheduler.mode = Scheduler::Mode::Synchronize;
|
||||||
runToSynchronize();
|
scheduler.active = smp.thread;
|
||||||
|
if(!runToSynchronize()) continue;
|
||||||
|
|
||||||
//now synchronize every other thread to their synchronization points.
|
scheduler.mode = Scheduler::Mode::Synchronize;
|
||||||
//stop after each thread is very slightly ahead of the CPU thread.
|
scheduler.active = cpu.thread;
|
||||||
scheduler.mode = Scheduler::Mode::SynchronizeAll;
|
if(!runToSynchronize()) continue;
|
||||||
runToThread(smp);
|
|
||||||
runToThread(ppu);
|
scheduler.mode = Scheduler::Mode::Synchronize;
|
||||||
for(auto coprocessor : cpu.coprocessors) runToThread(*coprocessor);
|
scheduler.active = smp.thread;
|
||||||
|
if(!runToSynchronize()) continue;
|
||||||
|
|
||||||
|
scheduler.mode = Scheduler::Mode::Synchronize;
|
||||||
|
scheduler.active = ppu.thread;
|
||||||
|
if(!runToSynchronize()) continue;
|
||||||
|
|
||||||
|
for(auto coprocessor : cpu.coprocessors) {
|
||||||
|
scheduler.mode = Scheduler::Mode::Synchronize;
|
||||||
|
scheduler.active = coprocessor->thread;
|
||||||
|
if(!runToSynchronize()) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//at this point, the CPU thread is the furthest behind in time.
|
|
||||||
//all threads are now at their synchronization points and can be serialized safely.
|
|
||||||
scheduler.mode = Scheduler::Mode::Run;
|
scheduler.mode = Scheduler::Mode::Run;
|
||||||
scheduler.active = cpu.thread;
|
scheduler.active = cpu.thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto System::runToSynchronize() -> void {
|
auto System::runToSynchronize() -> bool {
|
||||||
while(true) {
|
while(true) {
|
||||||
scheduler.enter();
|
scheduler.enter();
|
||||||
if(scheduler.event == Scheduler::Event::Frame) frameEvent();
|
if(scheduler.event == Scheduler::Event::Frame) frameEvent();
|
||||||
if(scheduler.event == Scheduler::Event::Synchronize) break;
|
if(scheduler.event == Scheduler::Event::Synchronized) return true;
|
||||||
|
if(scheduler.event == Scheduler::Event::Desynchronized) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto System::runToThread(Thread& aux) -> void {
|
|
||||||
//first, ensure that the CPU is ahead of the thread we want to synchronize to.
|
|
||||||
//because if it isn't, and the other thread is ahead, it will run even more ahead to synchronize itself.
|
|
||||||
scheduler.active = cpu.thread;
|
|
||||||
while(aux.clock >= 0) runToSynchronize();
|
|
||||||
|
|
||||||
//now that it is, run the other thread until it's just barely surpassed the CPU thread.
|
|
||||||
scheduler.active = aux.thread;
|
|
||||||
do runToSynchronize(); while(aux.clock < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto System::frameEvent() -> void {
|
auto System::frameEvent() -> void {
|
||||||
ppu.refresh();
|
ppu.refresh();
|
||||||
|
|
||||||
|
@@ -10,8 +10,7 @@ struct System {
|
|||||||
|
|
||||||
auto run() -> void;
|
auto run() -> void;
|
||||||
auto runToSave() -> void;
|
auto runToSave() -> void;
|
||||||
auto runToSynchronize() -> void;
|
auto runToSynchronize() -> bool;
|
||||||
auto runToThread(Thread&) -> void;
|
|
||||||
auto frameEvent() -> void;
|
auto frameEvent() -> void;
|
||||||
|
|
||||||
auto load(Emulator::Interface*) -> bool;
|
auto load(Emulator::Interface*) -> bool;
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -167,6 +168,20 @@ void co_switch(cothread_t handle) {
|
|||||||
co_swap(co_active_handle = handle, co_previous_handle);
|
co_swap(co_active_handle = handle, co_previous_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int co_size(unsigned int size) {
|
||||||
|
size += 512;
|
||||||
|
size &= ~15;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void co_save(cothread_t handle, void* memory, unsigned int size) {
|
||||||
|
memcpy(memory, handle, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void co_load(cothread_t handle, const void* memory, unsigned int size) {
|
||||||
|
memcpy(handle, memory, size);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -18,6 +18,9 @@ cothread_t co_derive(void*, unsigned int, void (*)(void));
|
|||||||
cothread_t co_create(unsigned int, void (*)(void));
|
cothread_t co_create(unsigned int, void (*)(void));
|
||||||
void co_delete(cothread_t);
|
void co_delete(cothread_t);
|
||||||
void co_switch(cothread_t);
|
void co_switch(cothread_t);
|
||||||
|
unsigned int co_size(unsigned int);
|
||||||
|
void co_save(cothread_t, void*, unsigned int);
|
||||||
|
void co_load(cothread_t, const void*, unsigned int);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user