diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index b70dbed8..681fe677 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "102.07"; + static const string Version = "102.08"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/md/apu/apu.cpp b/higan/md/apu/apu.cpp index 4cd21ae4..0720d799 100644 --- a/higan/md/apu/apu.cpp +++ b/higan/md/apu/apu.cpp @@ -9,7 +9,19 @@ auto APU::Enter() -> void { } auto APU::main() -> void { - step(1); + if(!state.enabled) return step(1); + + if(state.nmiLine) { + state.nmiLine = 0; //edge-sensitive + irq(0, 0x0066, 0xff); + } + + if(state.intLine) { + //level-sensitive + irq(1, 0x0038, 0xff); + } + + instruction(); } auto APU::step(uint clocks) -> void { @@ -17,10 +29,30 @@ auto APU::step(uint clocks) -> void { synchronize(cpu); } +auto APU::setNMI(bool value) -> void { + state.nmiLine = value; +} + +auto APU::setINT(bool value) -> void { + state.intLine = value; +} + +auto APU::enable(bool value) -> void { + if(state.enabled && !value) power(); + state.enabled = value; +} + auto APU::power() -> void { Z80::bus = &busAPU; Z80::power(); create(APU::Enter, system.colorburst()); + memory::fill(&state, sizeof(State)); + + r.pc = 0x0000; + r.im = 0; + r.iff1 = 0; + r.iff2 = 0; + r.ir = {}; } } diff --git a/higan/md/apu/apu.hpp b/higan/md/apu/apu.hpp index 938513d7..ec0d7b3f 100644 --- a/higan/md/apu/apu.hpp +++ b/higan/md/apu/apu.hpp @@ -5,7 +5,18 @@ struct APU : Processor::Z80, Thread { auto main() -> void; auto step(uint clocks) -> void; + auto enable(bool) -> void; auto power() -> void; + + auto setNMI(bool value) -> void; + auto setINT(bool value) -> void; + +private: + struct State { + boolean enabled; + boolean nmiLine; + boolean intLine; + } state; }; extern APU apu; diff --git a/higan/md/bus/bus.cpp b/higan/md/bus/bus.cpp index 2708a36f..0247edda 100644 --- a/higan/md/bus/bus.cpp +++ b/higan/md/bus/bus.cpp @@ -8,8 +8,9 @@ BusAPU busAPU; auto BusCPU::readByte(uint24 addr) -> uint16 { if(addr < 0x400000) return cartridge.read(addr & ~1).byte(!addr.bit(0)); if(addr < 0xa00000) return 0x0000; - if(addr < 0xa10000) return 0x0000; - if(addr < 0xa10020) return readIO(addr); + if(addr < 0xa10000) return busAPU.granted() ? busAPU.read(addr) : (uint8)0x0000; + if(addr < 0xa11000) return readIO(addr & ~0xff00); + if(addr < 0xa12000) return readIO(addr & ~0x00ff); if(addr < 0xc00000) return 0x0000; if(addr < 0xe00000) return vdp.read(addr & ~1).byte(!addr.bit(0)); return ram[addr & 0xffff]; @@ -18,8 +19,9 @@ auto BusCPU::readByte(uint24 addr) -> uint16 { auto BusCPU::readWord(uint24 addr) -> uint16 { if(addr < 0x400000) return cartridge.read(addr); if(addr < 0xa00000) return 0x0000; - if(addr < 0xa10000) return 0x0000; - if(addr < 0xa10020) return readIO(addr); + if(addr < 0xa10000) return busAPU.granted() ? busAPU.read(addr) : (uint8)0x0000; + if(addr < 0xa11000) return readIO(addr & ~0xff00) << 0; + if(addr < 0xa12000) return readIO(addr & ~0x00ff) << 8; if(addr < 0xc00000) return 0x0000; if(addr < 0xe00000) return vdp.read(addr); uint16 data = ram[addr + 0 & 0xffff] << 8; @@ -29,20 +31,26 @@ auto BusCPU::readWord(uint24 addr) -> uint16 { auto BusCPU::writeByte(uint24 addr, uint16 data) -> void { if(addr < 0x400000) return cartridge.write(addr & ~1, data << 8 | data << 0); if(addr < 0xa00000) return; - if(addr < 0xa10000) return; - if(addr < 0xa10020) return writeIO(addr, data); + if(addr < 0xa10000) return busAPU.granted() ? busAPU.write(addr, data) : (void)0; + if(addr < 0xa11000) return writeIO(addr & ~0xff00, data); + if(addr < 0xa12000) return writeIO(addr & ~0x00ff, data); if(addr < 0xc00000) return; - if(addr < 0xe00000) return vdp.write(addr & ~1, data << 8 | data << 0); + if(addr < 0xc00010) return vdp.write(addr & ~1, data << 8 | data << 0); + if(addr < 0xc00018) return psg.write(data); + if(addr < 0xe00000) return; ram[addr & 0xffff] = data; } auto BusCPU::writeWord(uint24 addr, uint16 data) -> void { if(addr < 0x400000) return cartridge.write(addr, data); if(addr < 0xa00000) return; - if(addr < 0xa10000) return; - if(addr < 0xa10020) return writeIO(addr, data); + if(addr < 0xa10000) return busAPU.granted() ? busAPU.write(addr, data) : (void)0; + if(addr < 0xa11000) return writeIO(addr & ~0xff00, data >> 0); + if(addr < 0xa12000) return writeIO(addr & ~0x00ff, data >> 8); if(addr < 0xc00000) return; - if(addr < 0xe00000) return vdp.write(addr, data); + if(addr < 0xc00010) return vdp.write(addr, data); + if(addr < 0xc00018) return psg.write(data); + if(addr < 0xe00000) return; ram[addr + 0 & 0xffff] = data >> 8; ram[addr + 1 & 0xffff] = data >> 0; } @@ -65,6 +73,8 @@ auto BusCPU::readIO(uint24 addr) -> uint16 { case 0xa10008: return peripherals.controllerPort1->readControl(); case 0xa1000a: return peripherals.controllerPort2->readControl(); case 0xa1000c: return peripherals.extensionPort->readControl(); + + case 0xa11000: return !busAPU.granted(); } return 0x0000; @@ -79,22 +89,63 @@ auto BusCPU::writeIO(uint24 addr, uint16 data) -> void { case 0xa10008: return peripherals.controllerPort1->writeControl(data); case 0xa1000a: return peripherals.controllerPort2->writeControl(data); case 0xa1000c: return peripherals.extensionPort->writeControl(data); + + case 0xa11100: return busAPU.request(data.bit(0)); + case 0xa11200: return apu.enable(data.bit(0)); } } // auto BusAPU::read(uint16 addr) -> uint8 { - return 0x00; + if((addr & 0xe000) == 0x0000) { + return ram[addr]; + } + + if(addr == 0x4000) return ym2612.readStatus(); + if(addr == 0x4001) return ym2612.readStatus(); + if(addr == 0x4002) return ym2612.readStatus(); + if(addr == 0x4003) return ym2612.readStatus(); + + if((addr & 0x8000) == 0x8000) { + return cartridge.read(bank << 15 | (addr & 0x7ffe)).byte(!addr.bit(0)); + } } auto BusAPU::write(uint16 addr, uint8 data) -> void { + if((addr & 0xe000) == 0x0000) { + ram[addr] = data; + return; + } + + if(addr == 0x4000) return ym2612.writeAddress(0 << 8 | data); + if(addr == 0x4001) return ym2612.writeData(data); + if(addr == 0x4002) return ym2612.writeAddress(1 << 8 | data); + if(addr == 0x4003) return ym2612.writeData(data); + + if(addr == 0x6000) { + //1-bit shift register + bank = data.bit(0) << 8 | bank >> 1; + return; + } + + if(addr == 0x7f11) return psg.write(data); + if(addr == 0x7f13) return psg.write(data); + if(addr == 0x7f15) return psg.write(data); + if(addr == 0x7f17) return psg.write(data); + + if((addr & 0x8000) == 0x8000) { + //todo: do 8-bit writes mirror to 16-bits? + return cartridge.write(bank << 15 | (addr & 0x7ffe), data << 8 | data << 0); + } } +//unused on Mega Drive auto BusAPU::in(uint8 addr) -> uint8 { return 0x00; } +//unused on Mega Drive auto BusAPU::out(uint8 addr, uint8 data) -> void { } diff --git a/higan/md/bus/bus.hpp b/higan/md/bus/bus.hpp index 57f470ef..542a6904 100644 --- a/higan/md/bus/bus.hpp +++ b/higan/md/bus/bus.hpp @@ -14,8 +14,13 @@ private: struct BusAPU : Processor::Z80::Bus { auto read(uint16 addr) -> uint8 override; auto write(uint16 addr, uint8 data) -> void override; + auto in(uint8 addr) -> uint8 override; auto out(uint8 addr, uint8 data) -> void override; + +private: + uint8 ram[8 * 1024]; + uint9 bank; }; extern BusCPU busCPU; diff --git a/higan/md/psg/io.cpp b/higan/md/psg/io.cpp new file mode 100644 index 00000000..bd4c579e --- /dev/null +++ b/higan/md/psg/io.cpp @@ -0,0 +1,2 @@ +auto PSG::write(uint8 data) -> void { +} diff --git a/higan/md/psg/psg.cpp b/higan/md/psg/psg.cpp index 3af5686d..20bfa81f 100644 --- a/higan/md/psg/psg.cpp +++ b/higan/md/psg/psg.cpp @@ -3,13 +3,14 @@ namespace MegaDrive { PSG psg; +#include "io.cpp" auto PSG::Enter() -> void { while(true) scheduler.synchronize(), psg.main(); } auto PSG::main() -> void { - stream->sample(0.0, 0.0); + stream->sample(0.0); step(1); } @@ -19,8 +20,8 @@ auto PSG::step(uint clocks) -> void { } auto PSG::power() -> void { - create(PSG::Enter, 52'000); //system.colorburst()); - stream = Emulator::audio.createStream(2, 52'000.0); + create(PSG::Enter, system.colorburst() / 16.0); + stream = Emulator::audio.createStream(1, system.colorburst() / 16.0); } } diff --git a/higan/md/psg/psg.hpp b/higan/md/psg/psg.hpp index 9b11454b..cd988d7c 100644 --- a/higan/md/psg/psg.hpp +++ b/higan/md/psg/psg.hpp @@ -8,6 +8,9 @@ struct PSG : Thread { auto step(uint clocks) -> void; auto power() -> void; + + //io.cpp + auto write(uint8 data) -> void; }; extern PSG psg; diff --git a/higan/md/vdp/vdp.cpp b/higan/md/vdp/vdp.cpp index bd44bb15..e465d99c 100644 --- a/higan/md/vdp/vdp.cpp +++ b/higan/md/vdp/vdp.cpp @@ -33,8 +33,10 @@ auto VDP::main() -> void { if(io.verticalBlankInterruptEnable) { cpu.raise(CPU::Interrupt::VerticalBlank); } + apu.setINT(true); } step(1710); + apu.setINT(false); } } @@ -43,6 +45,7 @@ auto VDP::step(uint clocks) -> void { dmaRun(); Thread::step(1); synchronize(cpu); + synchronize(apu); } } diff --git a/higan/md/ym2612/io.cpp b/higan/md/ym2612/io.cpp new file mode 100644 index 00000000..4423fdaa --- /dev/null +++ b/higan/md/ym2612/io.cpp @@ -0,0 +1,9 @@ +auto YM2612::readStatus() -> uint8 { + return nall::random(); +} + +auto YM2612::writeAddress(uint9 data) -> void { +} + +auto YM2612::writeData(uint8 data) -> void { +} diff --git a/higan/md/ym2612/ym2612.cpp b/higan/md/ym2612/ym2612.cpp index acfb3029..195d34ce 100644 --- a/higan/md/ym2612/ym2612.cpp +++ b/higan/md/ym2612/ym2612.cpp @@ -3,13 +3,15 @@ namespace MegaDrive { YM2612 ym2612; +#include "io.cpp" auto YM2612::Enter() -> void { while(true) scheduler.synchronize(), ym2612.main(); } auto YM2612::main() -> void { - step(1); + stream->sample(0.0, 0.0); + step(144); } auto YM2612::step(uint clocks) -> void { @@ -19,6 +21,7 @@ auto YM2612::step(uint clocks) -> void { auto YM2612::power() -> void { create(YM2612::Enter, system.colorburst() * 15.0 / 7.0); + stream = Emulator::audio.createStream(2, system.colorburst() * 15.0 / 7.0 / 144.0); } } diff --git a/higan/md/ym2612/ym2612.hpp b/higan/md/ym2612/ym2612.hpp index f15eb4be..328d1da5 100644 --- a/higan/md/ym2612/ym2612.hpp +++ b/higan/md/ym2612/ym2612.hpp @@ -1,11 +1,18 @@ //Yamaha YM2612 struct YM2612 : Thread { + shared_pointer stream; + static auto Enter() -> void; auto main() -> void; auto step(uint clocks) -> void; auto power() -> void; + + //io.cpp + auto readStatus() -> uint8; + auto writeAddress(uint9 data) -> void; + auto writeData(uint8 data) -> void; }; extern YM2612 ym2612; diff --git a/higan/pce/cpu/cpu.hpp b/higan/pce/cpu/cpu.hpp index 97f02eea..b7a52f36 100644 --- a/higan/pce/cpu/cpu.hpp +++ b/higan/pce/cpu/cpu.hpp @@ -13,6 +13,7 @@ struct CPU : Processor::HuC6280, Thread { //io.cpp auto read(uint8 bank, uint13 addr) -> uint8 override; + auto read_(uint8 bank, uint13 addr) -> uint8; auto write(uint8 bank, uint13 addr, uint8 data) -> void override; auto store(uint2 addr, uint8 data) -> void override; diff --git a/higan/pce/cpu/io.cpp b/higan/pce/cpu/io.cpp index 7970873a..ab68c4f1 100644 --- a/higan/pce/cpu/io.cpp +++ b/higan/pce/cpu/io.cpp @@ -1,4 +1,10 @@ auto CPU::read(uint8 bank, uint13 addr) -> uint8 { + auto data = read_(bank, addr); + if(auto result = cheat.find(bank << 13 | addr, data)) data = result(); + return data; +} + +auto CPU::read_(uint8 bank, uint13 addr) -> uint8 { //$00-7f HuCard if(!bank.bit(7)) { return cartridge.read(bank << 13 | addr); diff --git a/higan/pce/interface/interface.cpp b/higan/pce/interface/interface.cpp index 4a4cd23f..b0b0b6ec 100644 --- a/higan/pce/interface/interface.cpp +++ b/higan/pce/interface/interface.cpp @@ -11,7 +11,7 @@ Interface::Interface() { information.overscan = true; information.capability.states = true; - information.capability.cheats = false; + information.capability.cheats = true; Port controllerPort{ID::Port::Controller, "Controller Port"}; @@ -116,6 +116,10 @@ auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } +auto Interface::cheatSet(const string_vector& list) -> void { + cheat.assign(list); +} + auto Interface::cap(const string& name) -> bool { return false; } diff --git a/higan/pce/interface/interface.hpp b/higan/pce/interface/interface.hpp index ed6000b5..dc20b3e8 100644 --- a/higan/pce/interface/interface.hpp +++ b/higan/pce/interface/interface.hpp @@ -43,6 +43,8 @@ struct Interface : Emulator::Interface { auto serialize() -> serializer override; auto unserialize(serializer&) -> bool override; + auto cheatSet(const string_vector&) -> void override; + auto cap(const string& name) -> bool override; auto get(const string& name) -> any override; auto set(const string& name, const any& value) -> bool override; diff --git a/higan/pce/pce.hpp b/higan/pce/pce.hpp index 3a31dae5..9512e97d 100644 --- a/higan/pce/pce.hpp +++ b/higan/pce/pce.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -13,7 +14,9 @@ namespace PCEngine { #define platform Emulator::platform namespace File = Emulator::File; using Scheduler = Emulator::Scheduler; + using Cheat = Emulator::Cheat; extern Scheduler scheduler; + extern Cheat cheat; struct Thread : Emulator::Thread { auto create(auto (*entrypoint)() -> void, double frequency) -> void { diff --git a/higan/pce/system/system.cpp b/higan/pce/system/system.cpp index fec92d79..f5c44b82 100644 --- a/higan/pce/system/system.cpp +++ b/higan/pce/system/system.cpp @@ -4,6 +4,7 @@ namespace PCEngine { System system; Scheduler scheduler; +Cheat cheat; #include "peripherals.cpp" #include "serialization.cpp" diff --git a/higan/pce/vce/vce.cpp b/higan/pce/vce/vce.cpp index 373edd23..80a97c35 100644 --- a/higan/pce/vce/vce.cpp +++ b/higan/pce/vce/vce.cpp @@ -12,38 +12,36 @@ auto VCE::Enter() -> void { } auto VCE::main() -> void { - vdc0.frame(); - vdc1.frame(); - timing.vclock = 0; - - while(timing.vclock < 262) { - vdc0.scanline(); - vdc1.scanline(); - timing.hclock = 0; - - auto output = buffer + 1365 * timing.vclock; - - while(timing.hclock < 1360) { - uint9 color; - if(Model::PCEngine()) color = vdc0.bus(); - if(Model::SuperGrafx()) color = vpc.bus(timing.hclock); - color = cram.read(color); - - //*output++ = color; - //step(1); - - if(clock() >= 2) *output++ = color; - if(clock() >= 2) *output++ = color; - if(clock() >= 3) *output++ = color; - if(clock() >= 4) *output++ = color; - step(clock()); - } - - step(1365 - timing.hclock); - timing.vclock++; + if(timing.vclock == 0) { + vdc0.frame(); + vdc1.frame(); } - scheduler.exit(Scheduler::Event::Frame); + vdc0.scanline(); + vdc1.scanline(); + timing.hclock = 0; + + auto output = buffer + 1365 * timing.vclock; + + while(timing.hclock < 1360) { + uint9 color; + if(Model::PCEngine()) color = vdc0.bus(); + if(Model::SuperGrafx()) color = vpc.bus(timing.hclock); + color = cram.read(color); + + if(clock() >= 2) *output++ = color; + if(clock() >= 2) *output++ = color; + if(clock() >= 3) *output++ = color; + if(clock() >= 4) *output++ = color; + step(clock()); + } + + step(1365 - timing.hclock); + + if(++timing.vclock == 262) { + timing.vclock = 0; + scheduler.exit(Scheduler::Event::Frame); + } } auto VCE::step(uint clocks) -> void { diff --git a/higan/pce/vdc/vdc.cpp b/higan/pce/vdc/vdc.cpp index 8b0cb7e9..db9bf840 100644 --- a/higan/pce/vdc/vdc.cpp +++ b/higan/pce/vdc/vdc.cpp @@ -23,61 +23,58 @@ auto VDC::Enter() -> void { auto VDC::main() -> void { if(Model::PCEngine() && vdc1.active()) return step(frequency()); - timing.vpulse = false; - timing.vclock = 0; - timing.voffset = 0; - timing.vstart = max((uint8)2, timing.verticalDisplayStart) - 2; - timing.vlength = min(242, timing.verticalDisplayLength + 1); + if(timing.vclock == 0) { + timing.voffset = 0; + timing.vstart = max((uint8)2, timing.verticalDisplayStart) - 2; + timing.vlength = min(242, timing.verticalDisplayLength + 1); + } - while(!timing.vpulse) { - timing.hpulse = false; - timing.hclock = 0; - timing.hoffset = 0; - timing.hstart = timing.horizontalDisplayStart; - timing.hlength = (timing.horizontalDisplayLength + 1) << 3; + timing.hclock = 0; + timing.hoffset = 0; + timing.hstart = timing.horizontalDisplayStart; + timing.hlength = (timing.horizontalDisplayLength + 1) << 3; - if(timing.vclock >= timing.vstart && timing.voffset < timing.vlength) { - background.scanline(timing.voffset); - sprite.scanline(timing.voffset); + if(timing.vclock >= timing.vstart && timing.voffset < timing.vlength) { + background.scanline(timing.voffset); + sprite.scanline(timing.voffset); - step(timing.hstart); + step(timing.hstart); - while(timing.hoffset < timing.hlength) { - data = 0; - - background.run(timing.hoffset, timing.voffset); - sprite.run(timing.hoffset, timing.voffset); - - if(sprite.color && sprite.priority) { - data = 1 << 8 | sprite.palette << 4 | sprite.color << 0; - } else if(background.color) { - data = 0 << 8 | background.palette << 4 | background.color << 0; - } else if(sprite.color) { - data = 1 << 8 | sprite.palette << 4 | sprite.color << 0; - } - - step(vce.clock()); - timing.hoffset++; - } + while(timing.hclock < 1360 && timing.hoffset < timing.hlength) { data = 0; - if(timing.voffset == io.lineCoincidence - 64) { - irq.raise(IRQ::Line::LineCoincidence); + background.run(timing.hoffset, timing.voffset); + sprite.run(timing.hoffset, timing.voffset); + + if(sprite.color && sprite.priority) { + data = 1 << 8 | sprite.palette << 4 | sprite.color << 0; + } else if(background.color) { + data = 0 << 8 | background.palette << 4 | background.color << 0; + } else if(sprite.color) { + data = 1 << 8 | sprite.palette << 4 | sprite.color << 0; } - while(!timing.hpulse) step(1); - timing.vclock++; - timing.voffset++; - } else { - data = 0; - while(!timing.hpulse) step(1); - timing.vclock++; + step(vce.clock()); + timing.hoffset++; } - if(timing.vclock == timing.vstart + timing.vlength) { - irq.raise(IRQ::Line::Vblank); - dma.satbStart(); + if(timing.voffset == io.lineCoincidence - 64) { + irq.raise(IRQ::Line::LineCoincidence); } + + timing.voffset++; + } + + data = 0; + step(1365 - timing.hclock); + + if(timing.vclock == timing.vstart + timing.vlength) { + irq.raise(IRQ::Line::Vblank); + dma.satbStart(); + } + + if(++timing.vclock == 262) { + timing.vclock = 0; } } diff --git a/higan/processor/m68k/instructions.cpp b/higan/processor/m68k/instructions.cpp index a4e95ee5..492c4eab 100644 --- a/higan/processor/m68k/instructions.cpp +++ b/higan/processor/m68k/instructions.cpp @@ -706,7 +706,7 @@ auto M68K::instructionMOVE_FROM_SR(EffectiveAddress ea) -> void { } auto M68K::instructionMOVE_TO_CCR(EffectiveAddress ea) -> void { - auto data = read(ea); + auto data = read(ea); writeCCR(data); } diff --git a/higan/processor/z80/memory.cpp b/higan/processor/z80/memory.cpp index 39c2918a..187dfe4d 100644 --- a/higan/processor/z80/memory.cpp +++ b/higan/processor/z80/memory.cpp @@ -1,13 +1,25 @@ +auto Z80::yield() -> void { + //freeze Z80, allow external access until relinquished + if(bus->requested()) { + bus->grant(true); + while(bus->requested()) step(1); + bus->grant(false); + } +} + auto Z80::wait(uint clocks) -> void { + yield(); step(clocks); } auto Z80::opcode() -> uint8 { + yield(); step(4); return bus->read(r.pc++); } auto Z80::operand() -> uint8 { + yield(); step(3); return bus->read(r.pc++); } @@ -35,21 +47,25 @@ auto Z80::displace(uint16& x) -> uint16 { } auto Z80::read(uint16 addr) -> uint8 { + yield(); step(3); return bus->read(addr); } auto Z80::write(uint16 addr, uint8 data) -> void { + yield(); step(3); return bus->write(addr, data); } auto Z80::in(uint8 addr) -> uint8 { + yield(); step(4); return bus->in(addr); } auto Z80::out(uint8 addr, uint8 data) -> void { + yield(); step(4); return bus->out(addr, data); } diff --git a/higan/processor/z80/z80.cpp b/higan/processor/z80/z80.cpp index 8f403a1d..3ce14d05 100644 --- a/higan/processor/z80/z80.cpp +++ b/higan/processor/z80/z80.cpp @@ -12,6 +12,8 @@ namespace Processor { auto Z80::power() -> void { memory::fill(&r, sizeof(Registers)); r.hlp = &r.hl; + bus->request(false); + bus->grant(false); } auto Z80::irq(bool maskable, uint16 pc, uint8 extbus) -> bool { diff --git a/higan/processor/z80/z80.hpp b/higan/processor/z80/z80.hpp index 3c8feebd..4a19ee9a 100644 --- a/higan/processor/z80/z80.hpp +++ b/higan/processor/z80/z80.hpp @@ -6,10 +6,21 @@ namespace Processor { struct Z80 { struct Bus { + virtual auto requested() -> bool { return _requested; } + virtual auto granted() -> bool { return _granted; } + + virtual auto request(bool value) -> void { _requested = value; } + virtual auto grant(bool value) -> void { _granted = value; } + virtual auto read(uint16 addr) -> uint8 = 0; virtual auto write(uint16 addr, uint8 data) -> void = 0; + virtual auto in(uint8 addr) -> uint8 = 0; virtual auto out(uint8 addr, uint8 data) -> void = 0; + + private: + bool _requested; + bool _granted; }; virtual auto step(uint clocks) -> void = 0; @@ -21,6 +32,7 @@ struct Z80 { auto parity(uint8) const -> bool; //memory.cpp + auto yield() -> void; auto wait(uint clocks = 1) -> void; auto opcode() -> uint8; auto operand() -> uint8;