mirror of https://github.com/bsnes-emu/bsnes.git
Update to v101r10 release.
byuu says: Changelog: - 68K: MOVEQ is 8-bit signed - 68K: disassembler was print EOR for OR instructions - 68K: address/program-counter indexed mode had the signed-word/long bit backward - 68K: ADDQ/SUBQ #n,aN always works in long mode; regardless of size - 68K→VDP DMA needs to use `mode.bit(0)<<22|dmaSource`; increment by one instead of two - Z80: added registers and initial two instructions - MS: hooked up enough to load and start running games - Sonic the Hedgehog can execute exactly one instruction... whoo.
This commit is contained in:
parent
4d2e17f9c0
commit
0b70a01b47
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "101.09";
|
||||
static const string Version = "101.10";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -17,6 +17,19 @@ auto APU::step(uint clocks) -> void {
|
|||
synchronize(cpu);
|
||||
}
|
||||
|
||||
auto APU::wait() -> void {
|
||||
step(1);
|
||||
}
|
||||
|
||||
auto APU::read(uint16 addr) -> uint8 {
|
||||
step(1);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
auto APU::write(uint16 addr, uint8 data) -> void {
|
||||
step(1);
|
||||
}
|
||||
|
||||
auto APU::power() -> void {
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,10 @@ struct APU : Processor::Z80, Thread {
|
|||
auto main() -> void;
|
||||
auto step(uint clocks) -> void;
|
||||
|
||||
auto wait() -> void override;
|
||||
auto read(uint16 addr) -> uint8 override;
|
||||
auto write(uint16 addr, uint8 data) -> void override;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ auto CPU::boot() -> void {
|
|||
auto CPU::main() -> void {
|
||||
#if 0
|
||||
static file fp;
|
||||
if(!fp) fp.open({Path::user(), "Desktop/trace.log"}, file::mode::write);
|
||||
if(!fp) fp.open({Path::user(), "Desktop/tracer.log"}, file::mode::write);
|
||||
fp.print(pad(disassemble(r.pc), -60, ' '), " ", disassembleRegisters().replace("\n", " "), "\n");
|
||||
#endif
|
||||
|
||||
|
@ -85,7 +85,7 @@ auto CPU::reset() -> void {
|
|||
auto CPU::readByte(uint24 addr) -> uint8 {
|
||||
if(addr < 0x400000) return cartridge.readByte(addr);
|
||||
if(addr < 0xa00000) return 0x00;
|
||||
if(addr < 0xc00000) return rand();
|
||||
if(addr < 0xc00000) return rand(), 0;
|
||||
if(addr < 0xe00000) return vdp.readByte(addr);
|
||||
return ram[addr & 0xffff];
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ auto CPU::readByte(uint24 addr) -> uint8 {
|
|||
auto CPU::readWord(uint24 addr) -> uint16 {
|
||||
if(addr < 0x400000) return cartridge.readWord(addr);
|
||||
if(addr < 0xa00000) return 0x0000;
|
||||
if(addr < 0xc00000) return rand();
|
||||
if(addr < 0xc00000) return rand(), 0;
|
||||
if(addr < 0xe00000) return vdp.readWord(addr);
|
||||
uint16 data = ram[addr + 0 & 65535] << 8;
|
||||
return data | ram[addr + 1 & 65535] << 0;
|
||||
|
|
|
@ -10,10 +10,10 @@ auto VDP::dmaRun() -> void {
|
|||
auto VDP::dmaLoad() -> void {
|
||||
cpu.wait |= Wait::VDP_DMA;
|
||||
|
||||
auto data = cpu.readWord(io.dmaSource);
|
||||
auto data = cpu.readWord(io.dmaMode.bit(0) << 23 | io.dmaSource << 1);
|
||||
writeDataPort(data);
|
||||
|
||||
io.dmaSource.bits(0,15) += 2;
|
||||
io.dmaSource.bits(0,15)++;
|
||||
if(--io.dmaLength == 0) {
|
||||
io.command.bit(5) = 0;
|
||||
cpu.wait &=~ Wait::VDP_DMA;
|
||||
|
|
|
@ -4,4 +4,86 @@ namespace MasterSystem {
|
|||
|
||||
Cartridge cartridge;
|
||||
|
||||
auto Cartridge::load() -> bool {
|
||||
information = {};
|
||||
|
||||
switch(system.model()) {
|
||||
case Model::MasterSystem:
|
||||
if(auto pathID = interface->load(ID::MasterSystem, "Master System", "ms")) {
|
||||
information.pathID = pathID();
|
||||
} else return false;
|
||||
break;
|
||||
case Model::GameGear:
|
||||
if(auto pathID = interface->load(ID::GameGear, "Game Gear", "gg")) {
|
||||
information.pathID = pathID();
|
||||
} else return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(auto fp = interface->open(pathID(), "manifest.bml", File::Read, File::Required)) {
|
||||
information.manifest = fp->reads();
|
||||
} else return false;
|
||||
|
||||
auto document = BML::unserialize(information.manifest);
|
||||
information.title = document["information/title"].text();
|
||||
|
||||
if(auto node = document["board/rom"]) {
|
||||
rom.size = node["size"].natural();
|
||||
rom.mask = bit::round(rom.size) - 1;
|
||||
if(rom.size) {
|
||||
rom.data = new uint8[rom.mask + 1];
|
||||
if(auto name = node["name"].text()) {
|
||||
if(auto fp = interface->open(pathID(), name, File::Read, File::Required)) {
|
||||
fp->read(rom.data, rom.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(auto node = document["board/ram"]) {
|
||||
ram.size = node["size"].natural();
|
||||
ram.mask = bit::round(ram.size) - 1;
|
||||
if(ram.size) {
|
||||
ram.data = new uint8[ram.mask + 1];
|
||||
if(auto name = node["name"].text()) {
|
||||
if(auto fp = interface->open(pathID(), name, File::Read)) {
|
||||
fp->read(ram.data, ram.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Cartridge::save() -> void {
|
||||
auto document = BML::unserialize(information.manifest);
|
||||
|
||||
if(auto name = document["board/ram/name"].text()) {
|
||||
if(auto fp = interface->open(pathID(), name, File::Write)) {
|
||||
fp->write(ram.data, ram.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::unload() -> void {
|
||||
delete[] rom.data;
|
||||
delete[] ram.data;
|
||||
rom = {};
|
||||
ram = {};
|
||||
}
|
||||
|
||||
auto Cartridge::read(uint16 addr) -> uint8 {
|
||||
return rom.data[addr & rom.mask];
|
||||
}
|
||||
|
||||
auto Cartridge::write(uint16 addr, uint8 data) -> void {
|
||||
}
|
||||
|
||||
auto Cartridge::power() -> void {
|
||||
}
|
||||
|
||||
auto Cartridge::reset() -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,35 @@
|
|||
struct Cartridge {
|
||||
auto pathID() const -> uint { return information.pathID; }
|
||||
auto sha256() const -> string { return information.sha256; }
|
||||
auto manifest() const -> string { return information.manifest; }
|
||||
auto title() const -> string { return information.title; }
|
||||
|
||||
auto load() -> bool;
|
||||
auto save() -> void;
|
||||
auto unload() -> void;
|
||||
|
||||
auto read(uint16 addr) -> uint8;
|
||||
auto write(uint16 addr, uint8 data) -> void;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
private:
|
||||
struct Information {
|
||||
uint pathID = 0;
|
||||
string sha256;
|
||||
string manifest;
|
||||
string title;
|
||||
} information;
|
||||
|
||||
struct Memory {
|
||||
uint8* data = nullptr;
|
||||
uint size = 0;
|
||||
uint mask = 0;
|
||||
};
|
||||
|
||||
Memory rom;
|
||||
Memory ram;
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
||||
|
|
|
@ -9,10 +9,36 @@ auto CPU::Enter() -> void {
|
|||
}
|
||||
|
||||
auto CPU::main() -> void {
|
||||
instruction();
|
||||
}
|
||||
|
||||
auto CPU::step(uint clocks) -> void {
|
||||
Thread::step(clocks);
|
||||
synchronize(vdp);
|
||||
synchronize(psg);
|
||||
}
|
||||
|
||||
auto CPU::wait() -> void {
|
||||
step(1);
|
||||
}
|
||||
|
||||
auto CPU::read(uint16 addr) -> uint8 {
|
||||
step(1);
|
||||
if(addr < 0xc000) return cartridge.read(addr);
|
||||
return ram[addr & 0x1fff];
|
||||
}
|
||||
|
||||
auto CPU::write(uint16 addr, uint8 data) -> void {
|
||||
step(1);
|
||||
if(addr < 0xc000) return cartridge.write(addr, data);
|
||||
ram[addr & 0x1fff] = data;
|
||||
}
|
||||
|
||||
auto CPU::power() -> void {
|
||||
}
|
||||
|
||||
auto CPU::reset() -> void {
|
||||
create(CPU::Enter, system.colorburst());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,16 @@ struct CPU : Processor::Z80, Thread {
|
|||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto step(uint clocks) -> void;
|
||||
|
||||
auto wait() -> void override;
|
||||
auto read(uint16 addr) -> uint8 override;
|
||||
auto write(uint16 addr, uint8 data) -> void override;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
private:
|
||||
uint8 ram[0x2000]; //8KB
|
||||
};
|
||||
|
||||
extern CPU cpu;
|
||||
|
|
|
@ -32,25 +32,29 @@ Interface::Interface() {
|
|||
controllerPort1.devices.append(device);
|
||||
controllerPort2.devices.append(device);
|
||||
}
|
||||
|
||||
ports.append(move(controllerPort1));
|
||||
ports.append(move(controllerPort2));
|
||||
}
|
||||
|
||||
auto Interface::manifest() -> string {
|
||||
return "";
|
||||
return cartridge.manifest();
|
||||
}
|
||||
|
||||
auto Interface::title() -> string {
|
||||
return "";
|
||||
return cartridge.title();
|
||||
}
|
||||
|
||||
auto Interface::videoSize() -> VideoSize {
|
||||
return {256, 192};
|
||||
return {256, 240};
|
||||
}
|
||||
|
||||
auto Interface::videoSize(uint width, uint height, bool arc) -> VideoSize {
|
||||
auto a = arc ? 8.0 / 7.0 : 1.0;
|
||||
uint w = 256;
|
||||
uint h = 192;
|
||||
uint m = min(width / w, height / h);
|
||||
return {w * m, h * m};
|
||||
uint h = 240;
|
||||
uint m = min(width / (w * a), height / h);
|
||||
return {uint(w * a * m), uint(h * m)};
|
||||
}
|
||||
|
||||
auto Interface::videoFrequency() -> double {
|
||||
|
@ -70,26 +74,33 @@ auto Interface::audioFrequency() -> double {
|
|||
}
|
||||
|
||||
auto Interface::loaded() -> bool {
|
||||
return false;
|
||||
return system.loaded();
|
||||
}
|
||||
|
||||
auto Interface::load(uint id) -> bool {
|
||||
if(id == ID::MasterSystem) return system.load(Model::MasterSystem);
|
||||
if(id == ID::GameGear) return system.load(Model::GameGear);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Interface::save() -> void {
|
||||
system.save();
|
||||
}
|
||||
|
||||
auto Interface::unload() -> void {
|
||||
system.unload();
|
||||
}
|
||||
|
||||
auto Interface::power() -> void {
|
||||
system.power();
|
||||
}
|
||||
|
||||
auto Interface::reset() -> void {
|
||||
system.reset();
|
||||
}
|
||||
|
||||
auto Interface::run() -> void {
|
||||
system.run();
|
||||
}
|
||||
|
||||
auto Interface::serialize() -> serializer {
|
||||
|
|
|
@ -14,6 +14,11 @@ namespace MasterSystem {
|
|||
using Scheduler = Emulator::Scheduler;
|
||||
extern Scheduler scheduler;
|
||||
|
||||
enum class Model : uint {
|
||||
MasterSystem,
|
||||
GameGear,
|
||||
};
|
||||
|
||||
struct Thread : Emulator::Thread {
|
||||
auto create(auto (*entrypoint)() -> void, double frequency) -> void {
|
||||
Emulator::Thread::create(entrypoint, frequency);
|
||||
|
|
|
@ -9,10 +9,19 @@ auto PSG::Enter() -> void {
|
|||
}
|
||||
|
||||
auto PSG::main() -> void {
|
||||
step(1);
|
||||
}
|
||||
|
||||
auto PSG::step(uint clocks) -> void {
|
||||
Thread::step(clocks);
|
||||
synchronize(cpu);
|
||||
}
|
||||
|
||||
auto PSG::power() -> void {
|
||||
}
|
||||
|
||||
auto PSG::reset() -> void {
|
||||
create(PSG::Enter, system.colorburst());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ struct PSG : Thread {
|
|||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto step(uint clocks) -> void;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
};
|
||||
|
||||
extern PSG psg;
|
||||
|
|
|
@ -6,22 +6,54 @@ System system;
|
|||
Scheduler scheduler;
|
||||
|
||||
auto System::run() -> void {
|
||||
if(scheduler.enter() == Scheduler::Event::Frame) vdp.refresh();
|
||||
}
|
||||
|
||||
auto System::load() -> bool {
|
||||
return false;
|
||||
auto System::load(Model model) -> bool {
|
||||
information = {};
|
||||
information.model = model;
|
||||
|
||||
if(auto fp = interface->open(ID::System, "manifest.bml", File::Read, File::Required)) {
|
||||
information.manifest = fp->reads();
|
||||
} else return false;
|
||||
|
||||
auto document = BML::unserialize(information.manifest);
|
||||
if(!cartridge.load()) return false;
|
||||
|
||||
information.colorburst = Emulator::Constants::Colorburst::NTSC;
|
||||
return information.loaded = true;
|
||||
}
|
||||
|
||||
auto System::save() -> void {
|
||||
cartridge.save();
|
||||
}
|
||||
|
||||
auto System::unload() -> void {
|
||||
cartridge.unload();
|
||||
}
|
||||
|
||||
auto System::power() -> void {
|
||||
cartridge.power();
|
||||
cpu.power();
|
||||
vdp.power();
|
||||
psg.power();
|
||||
reset();
|
||||
}
|
||||
|
||||
auto System::reset() -> void {
|
||||
Emulator::video.reset();
|
||||
Emulator::video.setInterface(interface);
|
||||
Emulator::video.setPalette();
|
||||
|
||||
Emulator::audio.reset();
|
||||
Emulator::audio.setInterface(interface);
|
||||
|
||||
scheduler.reset();
|
||||
cartridge.reset();
|
||||
cpu.reset();
|
||||
vdp.reset();
|
||||
psg.reset();
|
||||
scheduler.primary(cpu);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
struct System {
|
||||
auto loaded() const -> bool { return false; }
|
||||
auto colorburst() const -> double { return 0.0; }
|
||||
auto loaded() const -> bool { return information.loaded; }
|
||||
auto model() const -> Model { return information.model; }
|
||||
auto colorburst() const -> double { return information.colorburst; }
|
||||
|
||||
auto run() -> void;
|
||||
|
||||
auto load() -> bool;
|
||||
auto load(Model model) -> bool;
|
||||
auto save() -> void;
|
||||
auto unload() -> void;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
private:
|
||||
struct Information {
|
||||
bool loaded = false;
|
||||
Model model = Model::MasterSystem;
|
||||
string manifest;
|
||||
double colorburst = 0.0;
|
||||
} information;
|
||||
};
|
||||
|
||||
extern System system;
|
||||
|
|
|
@ -9,10 +9,28 @@ auto VDP::Enter() -> void {
|
|||
}
|
||||
|
||||
auto VDP::main() -> void {
|
||||
for(uint y : range(262)) {
|
||||
for(uint x : range(342)) {
|
||||
step(1);
|
||||
}
|
||||
if(y == 240) scheduler.exit(Scheduler::Event::Frame);
|
||||
}
|
||||
}
|
||||
|
||||
auto VDP::step(uint clocks) -> void {
|
||||
Thread::step(clocks);
|
||||
synchronize(cpu);
|
||||
}
|
||||
|
||||
auto VDP::refresh() -> void {
|
||||
Emulator::video.refresh(buffer, 256 * sizeof(uint32), 256, 240);
|
||||
}
|
||||
|
||||
auto VDP::power() -> void {
|
||||
}
|
||||
|
||||
auto VDP::reset() -> void {
|
||||
create(VDP::Enter, system.colorburst());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
//...
|
||||
//TI TMS9918A (derivative)
|
||||
|
||||
struct VDP : Thread {
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto step(uint clocks) -> void;
|
||||
auto refresh() -> void;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
private:
|
||||
uint32 buffer[256 * 240];
|
||||
};
|
||||
|
||||
extern VDP vdp;
|
||||
|
|
|
@ -432,11 +432,11 @@ template<uint Size> auto M68K::disassembleNOT(EffectiveAddress with) -> string {
|
|||
}
|
||||
|
||||
template<uint Size> auto M68K::disassembleOR(EffectiveAddress from, DataRegister with) -> string {
|
||||
return {"eor", _suffix<Size>(), " ", _effectiveAddress<Size>(from), ",", _dataRegister(with)};
|
||||
return {"or", _suffix<Size>(), " ", _effectiveAddress<Size>(from), ",", _dataRegister(with)};
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::disassembleOR(DataRegister from, EffectiveAddress with) -> string {
|
||||
return {"eor", _suffix<Size>(), " ", _dataRegister(from), ",", _effectiveAddress<Size>(with)};
|
||||
return {"or", _suffix<Size>(), " ", _dataRegister(from), ",", _effectiveAddress<Size>(with)};
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::disassembleORI(EffectiveAddress with) -> string {
|
||||
|
|
|
@ -32,7 +32,7 @@ template<uint Size> auto M68K::fetch(EffectiveAddress& ea) -> uint32 {
|
|||
auto index = extension & 0x8000
|
||||
? read(AddressRegister{extension >> 12})
|
||||
: read(DataRegister{extension >> 12});
|
||||
if(extension & 0x800) index = (int16)index;
|
||||
if(!(extension & 0x800)) index = (int16)index;
|
||||
return read(AddressRegister{ea.reg}) + index + (int8)extension;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ template<uint Size> auto M68K::fetch(EffectiveAddress& ea) -> uint32 {
|
|||
auto index = extension & 0x8000
|
||||
? read(AddressRegister{extension >> 12})
|
||||
: read(DataRegister{extension >> 12});
|
||||
if(extension & 0x800) index = (int16)index;
|
||||
if(!(extension & 0x800)) index = (int16)index;
|
||||
return base + index + (int8)extension;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,8 +124,9 @@ template<uint Size> auto M68K::instructionADDQ(uint4 immediate, EffectiveAddress
|
|||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
//Size is ignored: always uses Long
|
||||
template<uint Size> auto M68K::instructionADDQ(uint4 immediate, AddressRegister with) -> void {
|
||||
auto result = read<Size>(with) + immediate;
|
||||
auto result = read<Long>(with) + immediate;
|
||||
write<Long>(with, result);
|
||||
}
|
||||
|
||||
|
@ -687,7 +688,7 @@ template<uint Size> auto M68K::instructionMOVEP(EffectiveAddress from, DataRegis
|
|||
}
|
||||
|
||||
auto M68K::instructionMOVEQ(DataRegister dr, uint8 immediate) -> void {
|
||||
write<Long>(dr, immediate);
|
||||
write<Long>(dr, sign<Byte>(immediate));
|
||||
|
||||
r.c = 0;
|
||||
r.v = 0;
|
||||
|
@ -1093,9 +1094,10 @@ template<uint Size> auto M68K::instructionSUBQ(uint4 immediate, EffectiveAddress
|
|||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
//Size is ignored: always uses Long
|
||||
template<uint Size> auto M68K::instructionSUBQ(uint4 immediate, AddressRegister with) -> void {
|
||||
auto result = read<Size>(with) - immediate;
|
||||
write<Size>(with, result);
|
||||
auto result = read<Long>(with) - immediate;
|
||||
write<Long>(with, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionSUBX(EffectiveAddress with, EffectiveAddress from) -> void {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);
|
||||
|
||||
auto Z80::instruction() -> void {
|
||||
instructionsExecuted++;
|
||||
|
||||
r.r = (r.r & 0x80) | (r.r + 1 & 0x7f);
|
||||
|
||||
auto opcode = read(r.pc++);
|
||||
switch(opcode) {
|
||||
op(0x00, NOP)
|
||||
op(0xf3, DI)
|
||||
}
|
||||
|
||||
print("[Z80] unimplemented instruction: ", hex(opcode, 2L), "\n");
|
||||
print("[Z80] instructions executed: ", --instructionsExecuted, "\n");
|
||||
while(true) wait();
|
||||
}
|
||||
|
||||
#undef op
|
|
@ -0,0 +1,5 @@
|
|||
auto Z80::instructionDI() -> void {
|
||||
}
|
||||
|
||||
auto Z80::instructionNOP() -> void {
|
||||
}
|
|
@ -1,5 +1,25 @@
|
|||
#include <processor/processor.hpp>
|
||||
#include "z80.hpp"
|
||||
|
||||
namespace Processor {
|
||||
|
||||
#include "instruction.cpp"
|
||||
#include "instructions.cpp"
|
||||
|
||||
auto Z80::power() -> void {
|
||||
}
|
||||
|
||||
auto Z80::reset() -> void {
|
||||
r.af = 0x0000;
|
||||
r.bc = 0x0000;
|
||||
r.de = 0x0000;
|
||||
r.hl = 0x0000;
|
||||
r.ix = 0x0000;
|
||||
r.iy = 0x0000;
|
||||
r.sp = 0x0000;
|
||||
r.pc = 0x0000;
|
||||
r.i = 0x00;
|
||||
r.r = 0x00;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,63 @@
|
|||
namespace Processor {
|
||||
|
||||
struct Z80 {
|
||||
virtual auto wait() -> void = 0;
|
||||
virtual auto read(uint16 addr) -> uint8 = 0;
|
||||
virtual auto write(uint16 addr, uint8 data) -> void = 0;
|
||||
|
||||
//z80.cpp
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
//instruction.cpp
|
||||
auto instruction() -> void;
|
||||
|
||||
//instructions.cpp
|
||||
auto instructionDI() -> void;
|
||||
auto instructionNOP() -> void;
|
||||
|
||||
struct Registers {
|
||||
union {
|
||||
uint16_t af;
|
||||
struct { uint8_t order_msb2(a, f); };
|
||||
union {
|
||||
BooleanBitField<uint16_t, 0> c; //carry
|
||||
BooleanBitField<uint16_t, 1> s; //subtract
|
||||
BooleanBitField<uint16_t, 2> v; //overflow
|
||||
//BooleanBitField<uint16_t, 3> _; //unused (copy of bit 3 of result)
|
||||
BooleanBitField<uint16_t, 4> h; //half-carry
|
||||
//BooleanBitField<uint16_t, 5> _; //unused (copy of bit 5 of result)
|
||||
BooleanBitField<uint16_t, 6> z; //zero
|
||||
BooleanBitField<uint16_t, 7> n; //negative
|
||||
} p;
|
||||
};
|
||||
|
||||
union {
|
||||
uint16_t bc;
|
||||
struct { uint8_t order_msb2(b, c); };
|
||||
};
|
||||
|
||||
union {
|
||||
uint16_t de;
|
||||
struct { uint8_t order_msb2(d, e); };
|
||||
};
|
||||
|
||||
union {
|
||||
uint16_t hl;
|
||||
struct { uint8_t order_msb2(h, l); };
|
||||
};
|
||||
|
||||
uint16_t ix;
|
||||
uint16_t iy;
|
||||
uint16_t sp;
|
||||
uint16_t pc;
|
||||
|
||||
uint8_t i;
|
||||
uint8_t r;
|
||||
} r;
|
||||
|
||||
private:
|
||||
uint64 instructionsExecuted = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue