From e78aca34b9454328b2de445806a28076ca21023b Mon Sep 17 00:00:00 2001 From: byuu <2107894+byuu@users.noreply.github.com> Date: Mon, 7 Oct 2019 13:32:21 +0900 Subject: [PATCH] v111.3 Save state improvements: rewind should be fully stable now. Before, Star Ocean and Tales of Phantasia would rarely hang with rewind. --- bsnes/emulator/emulator.hpp | 2 +- bsnes/sfc/coprocessor/armdsp/armdsp.cpp | 8 ++- bsnes/sfc/coprocessor/epsonrtc/epsonrtc.cpp | 8 ++- bsnes/sfc/coprocessor/event/event.cpp | 8 ++- .../sfc/coprocessor/hitachidsp/hitachidsp.cpp | 8 ++- bsnes/sfc/coprocessor/icd/icd.cpp | 5 +- bsnes/sfc/coprocessor/msu1/msu1.cpp | 8 ++- bsnes/sfc/coprocessor/necdsp/necdsp.cpp | 8 ++- bsnes/sfc/coprocessor/sa1/sa1.cpp | 8 ++- bsnes/sfc/coprocessor/sa1/sa1.hpp | 2 +- bsnes/sfc/coprocessor/sharprtc/sharprtc.cpp | 8 ++- bsnes/sfc/coprocessor/spc7110/spc7110.cpp | 8 ++- bsnes/sfc/coprocessor/superfx/superfx.cpp | 8 ++- bsnes/sfc/coprocessor/superfx/superfx.hpp | 2 +- bsnes/sfc/cpu/cpu.cpp | 8 ++- bsnes/sfc/ppu-fast/ppu.cpp | 11 +++- bsnes/sfc/ppu/main.cpp | 2 +- bsnes/sfc/ppu/ppu.cpp | 5 +- bsnes/sfc/sfc.hpp | 14 +++- bsnes/sfc/slot/bsmemory/bsmemory.cpp | 8 ++- bsnes/sfc/smp/smp.cpp | 5 +- bsnes/sfc/smp/smp.hpp | 2 +- bsnes/sfc/system/serialization.cpp | 1 + bsnes/sfc/system/system.cpp | 66 ++++++++++++------- bsnes/sfc/system/system.hpp | 3 + .../presentation/presentation.cpp | 2 +- 26 files changed, 155 insertions(+), 63 deletions(-) diff --git a/bsnes/emulator/emulator.hpp b/bsnes/emulator/emulator.hpp index 1a0a0a38..aa60c8b8 100644 --- a/bsnes/emulator/emulator.hpp +++ b/bsnes/emulator/emulator.hpp @@ -29,7 +29,7 @@ using namespace nall; namespace Emulator { static const string Name = "bsnes"; - static const string Version = "111.2"; + static const string Version = "111.3"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org"; diff --git a/bsnes/sfc/coprocessor/armdsp/armdsp.cpp b/bsnes/sfc/coprocessor/armdsp/armdsp.cpp index 2a2111e7..29095b11 100644 --- a/bsnes/sfc/coprocessor/armdsp/armdsp.cpp +++ b/bsnes/sfc/coprocessor/armdsp/armdsp.cpp @@ -7,12 +7,16 @@ namespace SuperFamicom { ArmDSP armdsp; auto ArmDSP::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto ArmDSP::Enter() -> void { armdsp.boot(); - while(true) scheduler.synchronize(), armdsp.main(); + while(true) { + scheduler.synchronizeAll(); + armdsp.main(); + } } auto ArmDSP::boot() -> void { diff --git a/bsnes/sfc/coprocessor/epsonrtc/epsonrtc.cpp b/bsnes/sfc/coprocessor/epsonrtc/epsonrtc.cpp index 4ddc20c9..de700ce9 100644 --- a/bsnes/sfc/coprocessor/epsonrtc/epsonrtc.cpp +++ b/bsnes/sfc/coprocessor/epsonrtc/epsonrtc.cpp @@ -8,11 +8,15 @@ namespace SuperFamicom { EpsonRTC epsonrtc; auto EpsonRTC::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto EpsonRTC::Enter() -> void { - while(true) scheduler.synchronize(), epsonrtc.main(); + while(true) { + scheduler.synchronizeAll(); + epsonrtc.main(); + } } auto EpsonRTC::main() -> void { diff --git a/bsnes/sfc/coprocessor/event/event.cpp b/bsnes/sfc/coprocessor/event/event.cpp index 4727be58..2316c3e2 100644 --- a/bsnes/sfc/coprocessor/event/event.cpp +++ b/bsnes/sfc/coprocessor/event/event.cpp @@ -6,11 +6,15 @@ namespace SuperFamicom { Event event; auto Event::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto Event::Enter() -> void { - while(true) scheduler.synchronize(), event.main(); + while(true) { + scheduler.synchronizeAll(); + event.main(); + } } auto Event::main() -> void { diff --git a/bsnes/sfc/coprocessor/hitachidsp/hitachidsp.cpp b/bsnes/sfc/coprocessor/hitachidsp/hitachidsp.cpp index 56a0852a..5b07b634 100644 --- a/bsnes/sfc/coprocessor/hitachidsp/hitachidsp.cpp +++ b/bsnes/sfc/coprocessor/hitachidsp/hitachidsp.cpp @@ -9,11 +9,15 @@ namespace SuperFamicom { HitachiDSP hitachidsp; auto HitachiDSP::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto HitachiDSP::Enter() -> void { - while(true) scheduler.synchronize(), hitachidsp.main(); + while(true) { + scheduler.synchronizeAll(); + hitachidsp.main(); + } } auto HitachiDSP::step(uint clocks) -> void { diff --git a/bsnes/sfc/coprocessor/icd/icd.cpp b/bsnes/sfc/coprocessor/icd/icd.cpp index 480bdce8..788cd8a5 100644 --- a/bsnes/sfc/coprocessor/icd/icd.cpp +++ b/bsnes/sfc/coprocessor/icd/icd.cpp @@ -48,12 +48,13 @@ namespace SameBoy { } auto ICD::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto ICD::Enter() -> void { while(true) { - scheduler.synchronize(); + scheduler.synchronizeAll(); icd.main(); } } diff --git a/bsnes/sfc/coprocessor/msu1/msu1.cpp b/bsnes/sfc/coprocessor/msu1/msu1.cpp index c95a8098..b0b891bb 100644 --- a/bsnes/sfc/coprocessor/msu1/msu1.cpp +++ b/bsnes/sfc/coprocessor/msu1/msu1.cpp @@ -7,12 +7,16 @@ MSU1 msu1; #include "serialization.cpp" auto MSU1::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto MSU1::Enter() -> void { - while(true) scheduler.synchronize(), msu1.main(); + while(true) { + scheduler.synchronizeAll(); + msu1.main(); + } } auto MSU1::main() -> void { diff --git a/bsnes/sfc/coprocessor/necdsp/necdsp.cpp b/bsnes/sfc/coprocessor/necdsp/necdsp.cpp index 522dc87a..fbbdb3d6 100644 --- a/bsnes/sfc/coprocessor/necdsp/necdsp.cpp +++ b/bsnes/sfc/coprocessor/necdsp/necdsp.cpp @@ -7,11 +7,15 @@ namespace SuperFamicom { NECDSP necdsp; auto NECDSP::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto NECDSP::Enter() -> void { - while(true) scheduler.synchronize(), necdsp.main(); + while(true) { + scheduler.synchronizeAll(); + necdsp.main(); + } } auto NECDSP::main() -> void { diff --git a/bsnes/sfc/coprocessor/sa1/sa1.cpp b/bsnes/sfc/coprocessor/sa1/sa1.cpp index 535b7708..0a87173c 100644 --- a/bsnes/sfc/coprocessor/sa1/sa1.cpp +++ b/bsnes/sfc/coprocessor/sa1/sa1.cpp @@ -12,11 +12,15 @@ namespace SuperFamicom { SA1 sa1; auto SA1::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto SA1::Enter() -> void { - while(true) scheduler.synchronize(), sa1.main(); + while(true) { + scheduler.synchronizeAll(); + sa1.main(); + } } auto SA1::main() -> void { diff --git a/bsnes/sfc/coprocessor/sa1/sa1.hpp b/bsnes/sfc/coprocessor/sa1/sa1.hpp index c493ce6b..21c46656 100644 --- a/bsnes/sfc/coprocessor/sa1/sa1.hpp +++ b/bsnes/sfc/coprocessor/sa1/sa1.hpp @@ -1,7 +1,7 @@ //Super Accelerator (SA-1) struct SA1 : Processor::WDC65816, Thread { - inline auto synchronizing() const -> bool override { return scheduler.mode == Scheduler::Mode::SynchronizeAll; } + inline auto synchronizing() const -> bool override { return scheduler.synchronizingAll(); } //sa1.cpp auto synchronizeCPU() -> void; diff --git a/bsnes/sfc/coprocessor/sharprtc/sharprtc.cpp b/bsnes/sfc/coprocessor/sharprtc/sharprtc.cpp index ee8e0326..372ffd56 100644 --- a/bsnes/sfc/coprocessor/sharprtc/sharprtc.cpp +++ b/bsnes/sfc/coprocessor/sharprtc/sharprtc.cpp @@ -8,11 +8,15 @@ namespace SuperFamicom { SharpRTC sharprtc; auto SharpRTC::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto SharpRTC::Enter() -> void { - while(true) scheduler.synchronize(), sharprtc.main(); + while(true) { + scheduler.synchronizeAll(); + sharprtc.main(); + } } auto SharpRTC::main() -> void { diff --git a/bsnes/sfc/coprocessor/spc7110/spc7110.cpp b/bsnes/sfc/coprocessor/spc7110/spc7110.cpp index fb253efb..85c7354c 100644 --- a/bsnes/sfc/coprocessor/spc7110/spc7110.cpp +++ b/bsnes/sfc/coprocessor/spc7110/spc7110.cpp @@ -17,11 +17,15 @@ SPC7110::~SPC7110() { } auto SPC7110::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto SPC7110::Enter() -> void { - while(true) scheduler.synchronize(), spc7110.main(); + while(true) { + scheduler.synchronizeAll(); + spc7110.main(); + } } auto SPC7110::main() -> void { diff --git a/bsnes/sfc/coprocessor/superfx/superfx.cpp b/bsnes/sfc/coprocessor/superfx/superfx.cpp index 9b3dc9f9..b9ddf09d 100644 --- a/bsnes/sfc/coprocessor/superfx/superfx.cpp +++ b/bsnes/sfc/coprocessor/superfx/superfx.cpp @@ -12,11 +12,15 @@ namespace SuperFamicom { SuperFX superfx; auto SuperFX::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto SuperFX::Enter() -> void { - while(true) scheduler.synchronize(), superfx.main(); + while(true) { + scheduler.synchronizeAll(); + superfx.main(); + } } auto SuperFX::main() -> void { diff --git a/bsnes/sfc/coprocessor/superfx/superfx.hpp b/bsnes/sfc/coprocessor/superfx/superfx.hpp index 0ef80292..680e9b1e 100644 --- a/bsnes/sfc/coprocessor/superfx/superfx.hpp +++ b/bsnes/sfc/coprocessor/superfx/superfx.hpp @@ -2,7 +2,7 @@ struct SuperFX : Processor::GSU, Thread { ReadableMemory rom; WritableMemory ram; - inline auto synchronizing() const -> bool { return scheduler.mode == Scheduler::Mode::SynchronizeAll; } + inline auto synchronizing() const -> bool { return scheduler.synchronizingAll(); } //superfx.cpp auto synchronizeCPU() -> void; diff --git a/bsnes/sfc/cpu/cpu.cpp b/bsnes/sfc/cpu/cpu.cpp index 782c1d57..2505dc92 100644 --- a/bsnes/sfc/cpu/cpu.cpp +++ b/bsnes/sfc/cpu/cpu.cpp @@ -11,14 +11,17 @@ CPU cpu; #include "serialization.cpp" auto CPU::synchronizeSMP() -> void { + if(scheduler.synchronizingAll()) return; if(smp.clock < 0) co_switch(smp.thread); } auto CPU::synchronizePPU() -> void { + if(scheduler.synchronizingAll()) return; if(ppu.clock < 0) co_switch(ppu.thread); } auto CPU::synchronizeCoprocessors() -> void { + if(scheduler.synchronizingAll()) return; for(auto coprocessor : coprocessors) { if(coprocessor->clock < 0) co_switch(coprocessor->thread); } @@ -26,9 +29,8 @@ auto CPU::synchronizeCoprocessors() -> void { auto CPU::Enter() -> void { while(true) { - if(scheduler.mode == Scheduler::Mode::SynchronizeCPU) { - scheduler.leave(Scheduler::Event::Synchronize); - } + scheduler.synchronizeCPU(); + scheduler.synchronizeAll(); cpu.main(); } } diff --git a/bsnes/sfc/ppu-fast/ppu.cpp b/bsnes/sfc/ppu-fast/ppu.cpp index 861669b5..6dd09b6c 100644 --- a/bsnes/sfc/ppu-fast/ppu.cpp +++ b/bsnes/sfc/ppu-fast/ppu.cpp @@ -69,12 +69,13 @@ PPU::~PPU() { } auto PPU::synchronizeCPU() -> void { - if(ppubase.clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(ppubase.clock >= 0) co_switch(cpu.thread); } auto PPU::Enter() -> void { while(true) { - scheduler.synchronize(); + scheduler.synchronizeAll(); ppu.main(); } } @@ -122,10 +123,14 @@ auto PPU::scanline() -> void { if(!io.displayDisable) oamAddressReset(); } - if(vcounter() == 240) { + if(vcounter() == vdisp()) { //240 Line::flush(); scheduler.leave(Scheduler::Event::Frame); } + + if(vcounter() == 240) { + Line::flush(); + } } auto PPU::refresh() -> void { diff --git a/bsnes/sfc/ppu/main.cpp b/bsnes/sfc/ppu/main.cpp index 8c9fe468..598ac2ba 100644 --- a/bsnes/sfc/ppu/main.cpp +++ b/bsnes/sfc/ppu/main.cpp @@ -21,7 +21,7 @@ auto PPU::main() -> void { if(auto device = controllerPort2.device) device->latch(); //light guns } - if(vcounter() == 240) { + if(vcounter() == vdisp()) { //240 scheduler.leave(Scheduler::Event::Frame); } diff --git a/bsnes/sfc/ppu/ppu.cpp b/bsnes/sfc/ppu/ppu.cpp index 6e08641f..a3de2dca 100644 --- a/bsnes/sfc/ppu/ppu.cpp +++ b/bsnes/sfc/ppu/ppu.cpp @@ -39,7 +39,8 @@ PPU::~PPU() { } auto PPU::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto PPU::step() -> void { @@ -59,7 +60,7 @@ auto PPU::step(uint clocks) -> void { auto PPU::Enter() -> void { while(true) { - scheduler.synchronize(); + scheduler.synchronizeAll(); ppu.main(); } } diff --git a/bsnes/sfc/sfc.hpp b/bsnes/sfc/sfc.hpp index 8412ebae..0f209dcf 100644 --- a/bsnes/sfc/sfc.hpp +++ b/bsnes/sfc/sfc.hpp @@ -45,7 +45,19 @@ namespace SuperFamicom { co_switch(host); } - auto synchronize() -> void { + inline auto synchronizingCPU() const -> bool { + return mode == Mode::SynchronizeCPU; + } + + inline auto synchronizingAll() const -> bool { + return mode == Mode::SynchronizeAll; + } + + inline auto synchronizeCPU() -> void { + if(mode == Mode::SynchronizeCPU) leave(Event::Synchronize); + } + + inline auto synchronizeAll() -> void { if(mode == Mode::SynchronizeAll) leave(Event::Synchronize); } }; diff --git a/bsnes/sfc/slot/bsmemory/bsmemory.cpp b/bsnes/sfc/slot/bsmemory/bsmemory.cpp index 86d76673..17f51a48 100644 --- a/bsnes/sfc/slot/bsmemory/bsmemory.cpp +++ b/bsnes/sfc/slot/bsmemory/bsmemory.cpp @@ -13,11 +13,15 @@ BSMemory::BSMemory() { } auto BSMemory::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto BSMemory::Enter() -> void { - while(true) scheduler.synchronize(), bsmemory.main(); + while(true) { + scheduler.synchronizeAll(); + bsmemory.main(); + } } auto BSMemory::main() -> void { diff --git a/bsnes/sfc/smp/smp.cpp b/bsnes/sfc/smp/smp.cpp index abea3a58..7d9ae842 100644 --- a/bsnes/sfc/smp/smp.cpp +++ b/bsnes/sfc/smp/smp.cpp @@ -9,7 +9,8 @@ SMP smp; #include "serialization.cpp" auto SMP::synchronizeCPU() -> void { - if(clock >= 0 && scheduler.mode != Scheduler::Mode::SynchronizeAll) co_switch(cpu.thread); + if(scheduler.synchronizingAll()) return; + if(clock >= 0) co_switch(cpu.thread); } auto SMP::synchronizeDSP() -> void { @@ -18,7 +19,7 @@ auto SMP::synchronizeDSP() -> void { auto SMP::Enter() -> void { while(true) { - scheduler.synchronize(); + scheduler.synchronizeAll(); smp.main(); } } diff --git a/bsnes/sfc/smp/smp.hpp b/bsnes/sfc/smp/smp.hpp index ee2aaecf..c973c079 100644 --- a/bsnes/sfc/smp/smp.hpp +++ b/bsnes/sfc/smp/smp.hpp @@ -1,7 +1,7 @@ //Sony CXP1100Q-1 struct SMP : Processor::SPC700, Thread { - inline auto synchronizing() const -> bool override { return scheduler.mode == Scheduler::Mode::SynchronizeAll; } + inline auto synchronizing() const -> bool override { return scheduler.synchronizingAll(); } //io.cpp auto portRead(uint2 port) const -> uint8; diff --git a/bsnes/sfc/system/serialization.cpp b/bsnes/sfc/system/serialization.cpp index 63764487..5dcf89a2 100644 --- a/bsnes/sfc/system/serialization.cpp +++ b/bsnes/sfc/system/serialization.cpp @@ -33,6 +33,7 @@ auto System::unserialize(serializer& s) -> bool { power(/* reset = */ false); serializeAll(s); serializeInit(); //hacks.fastPPU setting changes serializeSize + return true; } diff --git a/bsnes/sfc/system/system.cpp b/bsnes/sfc/system/system.cpp index 4e682d7a..d83689cd 100644 --- a/bsnes/sfc/system/system.cpp +++ b/bsnes/sfc/system/system.cpp @@ -11,39 +11,61 @@ Cheat cheat; auto System::run() -> void { scheduler.mode = Scheduler::Mode::Run; scheduler.enter(); - if(scheduler.event == Scheduler::Event::Frame) { - ppu.refresh(); - - //refresh all cheat codes once per frame - Memory::GlobalWriteEnable = true; - for(auto& code : cheat.codes) { - if(code.enable) { - bus.write(code.address, code.data); - } - } - Memory::GlobalWriteEnable = false; - } + if(scheduler.event == Scheduler::Event::Frame) frameEvent(); } auto System::runToSave() -> void { + //run the CPU thread normally, exiting once we reach the next synchronization point. + //the CPU thread may run in the pathological case for up to 10 frames for a long 8-channel x 64KB DMA transfer. + //in practice, this will typically be at most one DMA transfer. scheduler.mode = Scheduler::Mode::SynchronizeCPU; - while(true) { scheduler.enter(); if(scheduler.event == Scheduler::Event::Synchronize) break; } + runToSynchronize(); + //now synchronize every other thread to their synchronization points. + //stop after each thread is very slightly ahead of the CPU thread. scheduler.mode = Scheduler::Mode::SynchronizeAll; - scheduler.active = smp.thread; - while(true) { scheduler.enter(); if(scheduler.event == Scheduler::Event::Synchronize) break; } + runToThread(smp); + runToThread(ppu); + for(auto coprocessor : cpu.coprocessors) runToThread(*coprocessor); - scheduler.mode = Scheduler::Mode::SynchronizeAll; - scheduler.active = ppu.thread; - while(true) { scheduler.enter(); if(scheduler.event == Scheduler::Event::Synchronize) 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.active = cpu.thread; +} - for(auto coprocessor : cpu.coprocessors) { - scheduler.mode = Scheduler::Mode::SynchronizeAll; - scheduler.active = coprocessor->thread; - while(true) { scheduler.enter(); if(scheduler.event == Scheduler::Event::Synchronize) break; } +auto System::runToSynchronize() -> void { + while(true) { + scheduler.enter(); + if(scheduler.event == Scheduler::Event::Frame) frameEvent(); + if(scheduler.event == Scheduler::Event::Synchronize) break; } } +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 { + ppu.refresh(); + + //refresh all cheat codes once per frame + Memory::GlobalWriteEnable = true; + for(auto& code : cheat.codes) { + if(code.enable) { + bus.write(code.address, code.data); + } + } + Memory::GlobalWriteEnable = false; +} + auto System::load(Emulator::Interface* interface) -> bool { information = {}; diff --git a/bsnes/sfc/system/system.hpp b/bsnes/sfc/system/system.hpp index 6a4e3c37..3e717dc7 100644 --- a/bsnes/sfc/system/system.hpp +++ b/bsnes/sfc/system/system.hpp @@ -10,6 +10,9 @@ struct System { auto run() -> void; auto runToSave() -> void; + auto runToSynchronize() -> void; + auto runToThread(Thread&) -> void; + auto frameEvent() -> void; auto load(Emulator::Interface*) -> bool; auto save() -> void; diff --git a/bsnes/target-bsnes/presentation/presentation.cpp b/bsnes/target-bsnes/presentation/presentation.cpp index 700454e4..1b496c19 100644 --- a/bsnes/target-bsnes/presentation/presentation.cpp +++ b/bsnes/target-bsnes/presentation/presentation.cpp @@ -48,7 +48,7 @@ auto Presentation::create() -> void { settings.video.overscan = showOverscanArea.checked(); resizeWindow(); }); - blurEmulation.setText("Blur Emulation").setChecked(settings.video.blur).onToggle([&] { + blurEmulation.setText("Hires Blur Emulation").setChecked(settings.video.blur).onToggle([&] { settings.video.blur = blurEmulation.checked(); emulator->configure("Video/BlurEmulation", settings.video.blur); }).doToggle();