diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index 8e27c495..977dc494 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -8,7 +8,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "094.33"; + static const string Version = "094.34"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; @@ -33,7 +33,7 @@ template struct hook { auto operator()(P... p) const -> R { #if defined(DEBUGGER) - if(callback) return callback(std::forward

(p)...); + if(callback) return callback(forward

(p)...); #endif return R(); } diff --git a/emulator/interface.hpp b/emulator/interface.hpp index 0248eded..349b5a8c 100644 --- a/emulator/interface.hpp +++ b/emulator/interface.hpp @@ -33,7 +33,7 @@ struct Interface { unsigned id; unsigned type; //0 = digital, 1 = analog (relative), 2 = rumble string name; - uintptr_t guid; + uintptr_t guid; //user data field }; vector input; vector order; @@ -57,7 +57,6 @@ struct Interface { virtual auto inputRumble(unsigned, unsigned, unsigned, bool) -> void {} virtual auto dipSettings(const Markup::Node&) -> unsigned { return 0; } virtual auto path(unsigned) -> string { return ""; } - virtual auto server() -> string { return ""; } virtual auto notify(string text) -> void { print(text, "\n"); } }; Bind* bind = nullptr; @@ -73,7 +72,6 @@ struct Interface { auto inputRumble(unsigned port, unsigned device, unsigned input, bool enable) -> void { return bind->inputRumble(port, device, input, enable); } auto dipSettings(const Markup::Node& node) -> unsigned { return bind->dipSettings(node); } auto path(unsigned group) -> string { return bind->path(group); } - auto server() -> string { return bind->server(); } template auto notify(P&&... p) -> void { return bind->notify({forward

(p)...}); } //information diff --git a/gba/cpu/cpu.cpp b/gba/cpu/cpu.cpp index 83df0496..1eda3368 100644 --- a/gba/cpu/cpu.cpp +++ b/gba/cpu/cpu.cpp @@ -63,6 +63,72 @@ auto CPU::step(unsigned clocks) -> void { sync_step(clocks); } +auto CPU::bus_idle(uint32 addr) -> void { + step(1); + prefetch_step(1); +} + +auto CPU::bus_read(uint32 addr, uint32 size, bool mode) -> uint32 { + unsigned wait = bus.wait(addr, size, mode); + + if(addr < 0x0800'0000) { + unsigned word = bus.read(addr, size); + step(wait); + prefetch_step(wait); + return word; + } + + if(addr < 0x0e00'0000) { + if(regs.wait.control.prefetch) { + if(mode == Nonsequential) prefetch_start(addr); + unsigned word = prefetch_take(); + if(size == Byte) word = (addr & 1) ? (word >> 8) : (word & 0xff); + if(size == Word) word |= prefetch_take() << 16; + return word; + } + + unsigned word = cartridge.read(addr, size); + step(wait); + return word; + } + + if(addr < 0x1000'0000) { + prefetch_stall(); + unsigned word = bus.read(addr, size); + step(wait); + return word; + } + + step(wait); + prefetch_step(wait); + return 0x0000'0000; //open bus? +} + +auto CPU::bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void { + unsigned wait = bus.wait(addr, size, mode); + + if(addr < 0x0800'0000) { + step(wait); + prefetch_step(wait); + return bus.write(addr, size, word); + } + + if(addr < 0x0e00'0000) { + prefetch_stall(); + step(wait); + return bus.write(addr, size, word); + } + + if(addr < 0x1000'0000) { + prefetch_stall(); + step(wait); + return bus.write(addr, size, word); + } + + step(wait); + prefetch_step(wait); +} + auto CPU::sync_step(unsigned clocks) -> void { ppu.clock -= clocks; if(ppu.clock < 0) co_switch(ppu.thread); @@ -71,43 +137,6 @@ auto CPU::sync_step(unsigned clocks) -> void { if(apu.clock < 0) co_switch(apu.thread); } -auto CPU::bus_idle(uint32 addr) -> void { - if(regs.wait.control.prefetch) prefetch_run(); - step(1); -} - -auto CPU::bus_read(uint32 addr, uint32 size, bool mode) -> uint32 { - if(regs.wait.control.prefetch) { - if((addr & 0x0fffffff) >= 0x08000000 && (addr & 0x0fffffff) <= 0x0dffffff) { - if(auto word = prefetch_read(addr, size)) { - step(1 + (size == Word)); - return *word; - } - } - } - - unsigned wait = bus.wait(addr, size, mode); - unsigned word = bus.read(addr, size); - step(wait); - return word; -} - -auto CPU::bus_load(uint32 addr, uint32 size, bool mode) -> uint32 { - if(regs.wait.control.prefetch) prefetch_run(); - return bus_read(addr, size, mode); -} - -auto CPU::bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void { - unsigned wait = bus.wait(addr, size, mode); - step(wait); - bus.write(addr, size, word); -} - -auto CPU::bus_store(uint32 addr, uint32 size, bool mode, uint32 word) -> void { - if(regs.wait.control.prefetch) prefetch_run(); - return bus_write(addr, size, mode, word); -} - auto CPU::keypad_run() -> void { if(regs.keypad.control.enable == false) return; @@ -122,7 +151,7 @@ auto CPU::keypad_run() -> void { } auto CPU::power() -> void { - create(CPU::Enter, 16777216); + create(CPU::Enter, 16'777'216); ARM::power(); for(auto n : range( 32 * 1024)) iwram[n] = 0; @@ -152,7 +181,7 @@ auto CPU::power() -> void { regs.postboot = 0; regs.mode = Registers::Mode::Normal; regs.clock = 0; - regs.memory.control = 0x0d000020; + regs.memory.control = 0x0d00'0020; pending.dma.vblank = 0; pending.dma.hblank = 0; diff --git a/gba/cpu/cpu.hpp b/gba/cpu/cpu.hpp index 75d9dff7..33818a0c 100644 --- a/gba/cpu/cpu.hpp +++ b/gba/cpu/cpu.hpp @@ -12,15 +12,13 @@ struct CPU : Processor::ARM, Thread, MMIO { static auto Enter() -> void; auto main() -> void; - auto step(unsigned clocks) -> void; + + auto step(unsigned clocks) -> void override; + auto bus_idle(uint32 addr) -> void override; + auto bus_read(uint32 addr, uint32 size, bool mode) -> uint32 override; + auto bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void override; + auto sync_step(unsigned clocks) -> void; - - auto bus_idle(uint32 addr) -> void; - auto bus_read(uint32 addr, uint32 size, bool mode) -> uint32; - auto bus_load(uint32 addr, uint32 size, bool mode) -> uint32; - auto bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void; - auto bus_store(uint32 addr, uint32 size, bool mode, uint32 word) -> void; - auto keypad_run() -> void; auto power() -> void; diff --git a/gba/cpu/prefetch.cpp b/gba/cpu/prefetch.cpp index 3bc48b68..ed3ee42a 100644 --- a/gba/cpu/prefetch.cpp +++ b/gba/cpu/prefetch.cpp @@ -1,17 +1,43 @@ -auto CPU::prefetch_run() -> void { - if(prefetch.slots == 8) return; - prefetch.slots++; +auto CPU::prefetch_stall() -> void { + prefetch.stalled = true; } -auto CPU::prefetch_read(uint32 addr, uint32 size) -> maybe { - if(prefetch.slots >= (size == Word ? 2 : 1)) { - prefetch.slots -= (size == Word ? 2 : 1); - return cartridge.read(addr, size); +auto CPU::prefetch_start(uint32 addr) -> void { + prefetch.stalled = false; + prefetch.slots = 0; + prefetch.input = 0; + prefetch.output = 0; + prefetch.addr = addr; + prefetch.wait = bus.wait(addr, Half, Nonsequential); +} + +auto CPU::prefetch_step(unsigned clocks) -> void { + if(!regs.wait.control.prefetch || prefetch.stalled) return; + + prefetch.wait -= clocks; + while(prefetch.wait <= 0) { + if(prefetch.slots < 8) { + prefetch.slot[prefetch.output++] = cartridge.read(prefetch.addr, Half); + prefetch.slots++; + prefetch.addr += 2; + } + prefetch.wait += bus.wait(prefetch.addr, Half, Sequential); } - prefetch.slots = 0; - return nothing; +} + +auto CPU::prefetch_wait() -> void { + step(prefetch.wait); + prefetch_step(prefetch.wait); } auto CPU::prefetch_take() -> uint16 { - return 0; + if(prefetch.slots) { + step(1); + prefetch_step(1); + } else { + prefetch_wait(); + } + + prefetch.slots--; + return prefetch.slot[prefetch.input++]; } diff --git a/gba/cpu/prefetch.hpp b/gba/cpu/prefetch.hpp index d4dd18d1..cd68acba 100644 --- a/gba/cpu/prefetch.hpp +++ b/gba/cpu/prefetch.hpp @@ -1,13 +1,16 @@ struct Prefetch { - struct Slot { - uint32 addr; - uint16 half; - } slot[8]; + uint16 slot[8] = {0}; + uint3 input = 0; + uint3 output = 0; + bool stalled = true; unsigned slots = 0; + signed wait = 0; uint32 addr = 0; } prefetch; -auto prefetch_run() -> void; -auto prefetch_read(uint32 addr, uint32 size) -> maybe; +auto prefetch_stall() -> void; +auto prefetch_start(uint32 addr) -> void; +auto prefetch_step(unsigned clocks) -> void; +auto prefetch_wait() -> void; auto prefetch_take() -> uint16; diff --git a/gba/cpu/registers.cpp b/gba/cpu/registers.cpp index fff279ca..aebc7b99 100644 --- a/gba/cpu/registers.cpp +++ b/gba/cpu/registers.cpp @@ -221,6 +221,9 @@ auto CPU::Registers::WaitControl::operator=(uint16 source) -> uint16 { prefetch = (source >> 14) & 1; gametype = (source >> 15) & 1; swait[3] = nwait[3]; + + cpu.prefetch.stalled = true; + return operator uint16(); } diff --git a/hiro/core/action/menu-radio-item.cpp b/hiro/core/action/menu-radio-item.cpp index bd97c094..73fa34f3 100644 --- a/hiro/core/action/menu-radio-item.cpp +++ b/hiro/core/action/menu-radio-item.cpp @@ -41,6 +41,7 @@ auto mMenuRadioItem::setChecked() -> type& { auto mMenuRadioItem::setGroup(sGroup group) -> type& { state.group = group; signal(setGroup, group); + if(group && group->objects() == 1) setChecked(); return *this; } diff --git a/hiro/core/widget/radio-button.cpp b/hiro/core/widget/radio-button.cpp index 4fdf1dc1..cab12ffd 100644 --- a/hiro/core/widget/radio-button.cpp +++ b/hiro/core/widget/radio-button.cpp @@ -59,6 +59,7 @@ auto mRadioButton::setChecked() -> type& { auto mRadioButton::setGroup(sGroup group) -> type& { state.group = group; signal(setGroup, group); + if(group && group->objects() == 1) setChecked(); return *this; } diff --git a/hiro/core/widget/radio-label.cpp b/hiro/core/widget/radio-label.cpp index 503fe9d3..ecab7391 100644 --- a/hiro/core/widget/radio-label.cpp +++ b/hiro/core/widget/radio-label.cpp @@ -41,6 +41,7 @@ auto mRadioLabel::setChecked() -> type& { auto mRadioLabel::setGroup(sGroup group) -> type& { state.group = group; signal(setGroup, group); + if(group && group->objects() == 1) setChecked(); return *this; } diff --git a/processor/arm/arm.cpp b/processor/arm/arm.cpp index 07e175f9..59656fd7 100644 --- a/processor/arm/arm.cpp +++ b/processor/arm/arm.cpp @@ -40,7 +40,7 @@ auto ARM::read(uint32 addr, uint32 size, bool mode) -> uint32 { auto ARM::load(uint32 addr, uint32 size, bool mode) -> uint32 { if(processor.nonsequential) processor.nonsequential = false, mode = Nonsequential; - uint32 word = bus_load(addr, size, mode); + uint32 word = bus_read(addr, size, mode); if(size == Half) { word &= 0xffff; word |= word << 16; } if(size == Byte) { word &= 0xff; word |= word << 8; word |= word << 16; } @@ -63,7 +63,7 @@ auto ARM::store(uint32 addr, uint32 size, bool mode, uint32 word) -> void { if(size == Byte) { word &= 0xff; word |= word << 8; word |= word << 16; } if(processor.nonsequential) processor.nonsequential = false, mode = Nonsequential; - bus_store(addr, size, mode, word); + bus_write(addr, size, mode, word); processor.nonsequential = true; } diff --git a/processor/arm/arm.hpp b/processor/arm/arm.hpp index 430a9d39..e9a93d15 100644 --- a/processor/arm/arm.hpp +++ b/processor/arm/arm.hpp @@ -19,9 +19,7 @@ struct ARM { virtual auto step(unsigned clocks) -> void = 0; virtual auto bus_idle(uint32 addr) -> void = 0; virtual auto bus_read(uint32 addr, uint32 size, bool mode) -> uint32 = 0; - virtual auto bus_load(uint32 addr, uint32 size, bool mode) -> uint32 = 0; virtual auto bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void = 0; - virtual auto bus_store(uint32 addr, uint32 size, bool mode, uint32 word) -> void = 0; //arm.cpp auto power() -> void; diff --git a/processor/gsu/gsu.cpp b/processor/gsu/gsu.cpp index ae9eb601..48281d21 100644 --- a/processor/gsu/gsu.cpp +++ b/processor/gsu/gsu.cpp @@ -1,27 +1,16 @@ #include #include "gsu.hpp" +//note: multiplication results *may* sometimes be invalid when both CLSR and MS0 are set +//the product of multiplication in this mode (21mhz + fast-multiply) has not been analyzed; +//however, the timing of this mode has been confirmed to work as specified below + namespace Processor { #include "instructions.cpp" #include "table.cpp" #include "serialization.cpp" -//note: multiplication results *may* sometimes be invalid when both CLSR and MS0 are set -//the product of multiplication in this mode (21mhz + fast-multiply) has not been analyzed; -//however, the timing of this mode has been confirmed to work as specified below -auto GSU::cache_access_speed() -> unsigned { - if(clockmode == 1) return 2; - if(clockmode == 2) return 1; - return regs.clsr ? 1 : 2; -} - -auto GSU::memory_access_speed() -> unsigned { - if(clockmode == 1) return 6; - if(clockmode == 2) return 5; - return regs.clsr ? 5 : 6; -} - auto GSU::power() -> void { } diff --git a/processor/gsu/gsu.hpp b/processor/gsu/gsu.hpp index 54b29770..99b06beb 100644 --- a/processor/gsu/gsu.hpp +++ b/processor/gsu/gsu.hpp @@ -4,7 +4,6 @@ namespace Processor { struct GSU { - unsigned clockmode; //0 = selectable; 1 = force 10.74mhz; 2 = force 21.48mhz #include "registers.hpp" virtual auto step(unsigned clocks) -> void = 0; @@ -23,9 +22,6 @@ struct GSU { virtual auto cache_flush() -> void = 0; //gsu.cpp - auto cache_access_speed() -> unsigned; - auto memory_access_speed() -> unsigned; - auto power() -> void; auto reset() -> void; diff --git a/processor/gsu/instructions.cpp b/processor/gsu/instructions.cpp index aafe78de..4a525ea8 100644 --- a/processor/gsu/instructions.cpp +++ b/processor/gsu/instructions.cpp @@ -383,7 +383,7 @@ auto GSU::op_mult_r() { regs.sfr.s = (regs.dr() & 0x8000); regs.sfr.z = (regs.dr() == 0); regs.reset(); - if(!regs.cfgr.ms0) step(cache_access_speed()); + if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2); } //$80-8f(alt1): umult rN @@ -393,7 +393,7 @@ auto GSU::op_umult_r() { regs.sfr.s = (regs.dr() & 0x8000); regs.sfr.z = (regs.dr() == 0); regs.reset(); - if(!regs.cfgr.ms0) step(cache_access_speed()); + if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2); } //$80-8f(alt2): mult #N @@ -403,7 +403,7 @@ auto GSU::op_mult_i() { regs.sfr.s = (regs.dr() & 0x8000); regs.sfr.z = (regs.dr() == 0); regs.reset(); - if(!regs.cfgr.ms0) step(cache_access_speed()); + if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2); } //$80-8f(alt3): umult #N @@ -413,7 +413,7 @@ auto GSU::op_umult_i() { regs.sfr.s = (regs.dr() & 0x8000); regs.sfr.z = (regs.dr() == 0); regs.reset(); - if(!regs.cfgr.ms0) step(cache_access_speed()); + if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2); } //$90: sbk @@ -499,7 +499,7 @@ auto GSU::op_fmult() { regs.sfr.cy = (result & 0x8000); regs.sfr.z = (regs.dr() == 0); regs.reset(); - step(4 + (regs.cfgr.ms0 << 2)); + step((regs.cfgr.ms0 ? 3 : 7) * (regs.clsr ? 1 : 2)); } //$9f(alt1): lmult @@ -511,7 +511,7 @@ auto GSU::op_lmult() { regs.sfr.cy = (result & 0x8000); regs.sfr.z = (regs.dr() == 0); regs.reset(); - step(4 + (regs.cfgr.ms0 << 2)); + step((regs.cfgr.ms0 ? 3 : 7) * (regs.clsr ? 1 : 2)); } //$a0-af(alt0): ibt rN,#pp @@ -618,7 +618,7 @@ auto GSU::op_getc() { //$df(alt2): ramb auto GSU::op_ramb() { rambuffer_sync(); - regs.rambr = regs.sr(); + regs.rambr = regs.sr() & 0x01; regs.reset(); } diff --git a/processor/gsu/registers.hpp b/processor/gsu/registers.hpp index fcff3d6f..29268787 100644 --- a/processor/gsu/registers.hpp +++ b/processor/gsu/registers.hpp @@ -31,6 +31,7 @@ struct reg16_t { inline auto operator = (const reg16_t& i) { return assign(i); } + reg16_t() = default; reg16_t(const reg16_t&) = delete; }; diff --git a/processor/gsu/serialization.cpp b/processor/gsu/serialization.cpp index 169602cd..e688231e 100644 --- a/processor/gsu/serialization.cpp +++ b/processor/gsu/serialization.cpp @@ -1,6 +1,4 @@ auto GSU::serialize(serializer& s) -> void { - s.integer(clockmode); - s.integer(regs.pipeline); s.integer(regs.ramaddr); diff --git a/sfc/chip/armdsp/armdsp.hpp b/sfc/chip/armdsp/armdsp.hpp index dca0ef44..30ca130f 100644 --- a/sfc/chip/armdsp/armdsp.hpp +++ b/sfc/chip/armdsp/armdsp.hpp @@ -10,12 +10,10 @@ struct ArmDSP : Processor::ARM, Coprocessor { static void Enter(); void enter(); - void step(unsigned clocks); - void bus_idle(uint32 addr); - uint32 bus_read(uint32 addr, uint32 size, bool mode); - uint32 bus_load(uint32 addr, uint32 size, bool mode); - void bus_write(uint32 addr, uint32 size, bool mode, uint32 word); - void bus_store(uint32 addr, uint32 size, bool mode, uint32 word); + void step(unsigned clocks) override; + void bus_idle(uint32 addr) override; + uint32 bus_read(uint32 addr, uint32 size, bool mode) override; + void bus_write(uint32 addr, uint32 size, bool mode, uint32 word) override; uint8 mmio_read(unsigned addr); void mmio_write(unsigned addr, uint8 data); diff --git a/sfc/chip/armdsp/memory.cpp b/sfc/chip/armdsp/memory.cpp index 6e6a6969..8a57d6ca 100644 --- a/sfc/chip/armdsp/memory.cpp +++ b/sfc/chip/armdsp/memory.cpp @@ -1,5 +1,8 @@ #ifdef ARMDSP_CPP +//note: timings are completely unverified +//due to the ST018 chip design (on-die ROM), testing is nearly impossible + void ArmDSP::bus_idle(uint32 addr) { step(1); } @@ -44,10 +47,6 @@ uint32 ArmDSP::bus_read(uint32 addr, uint32 size, bool mode) { return 0u; } -uint32 ArmDSP::bus_load(uint32 addr, uint32 size, bool mode) { - return bus_read(addr, size, mode); -} - void ArmDSP::bus_write(uint32 addr, uint32 size, bool mode, uint32 word) { step(1); @@ -102,8 +101,4 @@ void ArmDSP::bus_write(uint32 addr, uint32 size, bool mode, uint32 word) { } } -void ArmDSP::bus_store(uint32 addr, uint32 size, bool mode, uint32 word) { - return bus_write(addr, size, mode, word); -} - #endif diff --git a/sfc/chip/event/event.cpp b/sfc/chip/event/event.cpp index 5ffae110..300167a6 100644 --- a/sfc/chip/event/event.cpp +++ b/sfc/chip/event/event.cpp @@ -60,7 +60,7 @@ void Event::submitScore() { data.append("ba:", ba[0], ",", ba[1], "\n"); } - lstring side = interface->server().split<1>("@"); +/*lstring side = interface->server().split<1>("@"); string username = side(0).split<1>(":")(0); string password = side(0).split<1>(":")(1); side(1).ltrim("http://"); @@ -71,7 +71,7 @@ void Event::submitScore() { string hostport = side(1); if(hostport.empty()) hostport = "80"; -/*http server; + http server; if(server.connect(hostname, decimal(hostport))) { string content = { "username:", username, "\n", diff --git a/sfc/chip/superfx/core/core.cpp b/sfc/chip/superfx/core/core.cpp index 66b136e9..670aa25f 100644 --- a/sfc/chip/superfx/core/core.cpp +++ b/sfc/chip/superfx/core/core.cpp @@ -66,7 +66,7 @@ auto SuperFX::rpix(uint8 x, uint8 y) -> uint8 { for(unsigned n = 0; n < bpp; n++) { unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 }; - step(memory_access_speed()); + step(regs.clsr ? 5 : 6); data |= ((bus_read(addr + byte) >> x) & 1) << n; } @@ -94,11 +94,11 @@ auto SuperFX::pixelcache_flush(pixelcache_t& cache) -> void { uint8 data = 0x00; for(unsigned x = 0; x < 8; x++) data |= ((cache.data[x] >> n) & 1) << x; if(cache.bitpend != 0xff) { - step(memory_access_speed()); + step(regs.clsr ? 5 : 6); data &= cache.bitpend; data |= bus_read(addr + byte) & ~cache.bitpend; } - step(memory_access_speed()); + step(regs.clsr ? 5 : 6); bus_write(addr + byte, data); } diff --git a/sfc/chip/superfx/memory/memory.cpp b/sfc/chip/superfx/memory/memory.cpp index 3a993872..83ba6214 100644 --- a/sfc/chip/superfx/memory/memory.cpp +++ b/sfc/chip/superfx/memory/memory.cpp @@ -43,12 +43,12 @@ auto SuperFX::op_read(uint16 addr) -> uint8 { unsigned dp = offset & 0xfff0; unsigned sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0); for(unsigned n = 0; n < 16; n++) { - step(memory_access_speed()); + step(regs.clsr ? 5 : 6); cache.buffer[dp++] = bus_read(sp++); } cache.valid[offset >> 4] = true; } else { - step(cache_access_speed()); + step(regs.clsr ? 1 : 2); } return cache.buffer[offset]; } @@ -56,12 +56,12 @@ auto SuperFX::op_read(uint16 addr) -> uint8 { if(regs.pbr <= 0x5f) { //$[00-5f]:[0000-ffff] ROM rombuffer_sync(); - step(memory_access_speed()); + step(regs.clsr ? 5 : 6); return bus_read((regs.pbr << 16) + addr); } else { //$[60-7f]:[0000-ffff] RAM rambuffer_sync(); - step(memory_access_speed()); + step(regs.clsr ? 5 : 6); return bus_read((regs.pbr << 16) + addr); } } diff --git a/sfc/chip/superfx/mmio/mmio.cpp b/sfc/chip/superfx/mmio/mmio.cpp index a5d7c008..920b44aa 100644 --- a/sfc/chip/superfx/mmio/mmio.cpp +++ b/sfc/chip/superfx/mmio/mmio.cpp @@ -87,7 +87,7 @@ auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void { } break; case 0x3033: { - regs.bramr = data; + regs.bramr = data & 0x01; } break; case 0x3034: { @@ -104,7 +104,7 @@ auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void { } break; case 0x3039: { - regs.clsr = data; + regs.clsr = data & 0x01; } break; case 0x303a: { diff --git a/sfc/chip/superfx/serialization.cpp b/sfc/chip/superfx/serialization.cpp index edffca98..6dda7da8 100644 --- a/sfc/chip/superfx/serialization.cpp +++ b/sfc/chip/superfx/serialization.cpp @@ -5,7 +5,6 @@ auto SuperFX::serialize(serializer& s) -> void { Thread::serialize(s); s.array(ram.data(), ram.size()); - s.integer(instruction_counter); s.integer(r15_modified); } diff --git a/sfc/chip/superfx/superfx.cpp b/sfc/chip/superfx/superfx.cpp index fd2aa4a6..e339312d 100644 --- a/sfc/chip/superfx/superfx.cpp +++ b/sfc/chip/superfx/superfx.cpp @@ -25,17 +25,12 @@ auto SuperFX::enter() -> void { if(regs.sfr.g == 0) { step(6); - synchronize_cpu(); continue; } - (this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])(); + unsigned opcode = (regs.sfr & 0x0300) + peekpipe(); + (this->*opcode_table[opcode])(); if(r15_modified == false) regs.r[15]++; - - if(++instruction_counter >= 128) { - instruction_counter = 0; - synchronize_cpu(); - } } } @@ -60,7 +55,6 @@ auto SuperFX::power() -> void { auto SuperFX::reset() -> void { GSU::reset(); create(SuperFX::Enter, system.cpu_frequency()); - instruction_counter = 0; memory_reset(); timing_reset(); } diff --git a/sfc/chip/superfx/superfx.hpp b/sfc/chip/superfx/superfx.hpp index 96529a06..c40e0cfe 100644 --- a/sfc/chip/superfx/superfx.hpp +++ b/sfc/chip/superfx/superfx.hpp @@ -21,9 +21,6 @@ struct SuperFX : Processor::GSU, Coprocessor { //serialization.cpp auto serialize(serializer&) -> void; - -privileged: - unsigned instruction_counter = 0; }; extern SuperFX superfx; diff --git a/sfc/chip/superfx/timing/timing.cpp b/sfc/chip/superfx/timing/timing.cpp index ab68e79b..4fc8f8b2 100644 --- a/sfc/chip/superfx/timing/timing.cpp +++ b/sfc/chip/superfx/timing/timing.cpp @@ -26,7 +26,7 @@ auto SuperFX::rombuffer_sync() -> void { auto SuperFX::rombuffer_update() -> void { regs.sfr.r = 1; - regs.romcl = memory_access_speed(); + regs.romcl = regs.clsr ? 5 : 6; } auto SuperFX::rombuffer_read() -> uint8 { @@ -45,7 +45,7 @@ auto SuperFX::rambuffer_read(uint16 addr) -> uint8 { auto SuperFX::rambuffer_write(uint16 addr, uint8 data) -> void { rambuffer_sync(); - regs.ramcl = memory_access_speed(); + regs.ramcl = regs.clsr ? 5 : 6; regs.ramar = addr; regs.ramdr = data; }